1*3d8817e4Smiod /* GAS interface for targets using CGEN: Cpu tools GENerator.
2*3d8817e4Smiod Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3*3d8817e4Smiod Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod This file is part of GAS, the GNU Assembler.
6*3d8817e4Smiod
7*3d8817e4Smiod GAS is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2, or (at your option)
10*3d8817e4Smiod any later version.
11*3d8817e4Smiod
12*3d8817e4Smiod GAS is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with GAS; see the file COPYING. If not, write to the Free Software
19*3d8817e4Smiod Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20*3d8817e4Smiod
21*3d8817e4Smiod #include <setjmp.h>
22*3d8817e4Smiod #include "ansidecl.h"
23*3d8817e4Smiod #include "libiberty.h"
24*3d8817e4Smiod #include "bfd.h"
25*3d8817e4Smiod #include "symcat.h"
26*3d8817e4Smiod #include "cgen-desc.h"
27*3d8817e4Smiod #include "as.h"
28*3d8817e4Smiod #include "subsegs.h"
29*3d8817e4Smiod #include "cgen.h"
30*3d8817e4Smiod #include "dwarf2dbg.h"
31*3d8817e4Smiod
32*3d8817e4Smiod static void queue_fixup (int, int, expressionS *);
33*3d8817e4Smiod
34*3d8817e4Smiod /* Opcode table descriptor, must be set by md_begin. */
35*3d8817e4Smiod
36*3d8817e4Smiod CGEN_CPU_DESC gas_cgen_cpu_desc;
37*3d8817e4Smiod
38*3d8817e4Smiod /* Callback to insert a register into the symbol table.
39*3d8817e4Smiod A target may choose to let GAS parse the registers.
40*3d8817e4Smiod ??? Not currently used. */
41*3d8817e4Smiod
42*3d8817e4Smiod void
cgen_asm_record_register(name,number)43*3d8817e4Smiod cgen_asm_record_register (name, number)
44*3d8817e4Smiod char *name;
45*3d8817e4Smiod int number;
46*3d8817e4Smiod {
47*3d8817e4Smiod /* Use symbol_create here instead of symbol_new so we don't try to
48*3d8817e4Smiod output registers into the object file's symbol table. */
49*3d8817e4Smiod symbol_table_insert (symbol_create (name, reg_section,
50*3d8817e4Smiod number, &zero_address_frag));
51*3d8817e4Smiod }
52*3d8817e4Smiod
53*3d8817e4Smiod /* We need to keep a list of fixups. We can't simply generate them as
54*3d8817e4Smiod we go, because that would require us to first create the frag, and
55*3d8817e4Smiod that would screw up references to ``.''.
56*3d8817e4Smiod
57*3d8817e4Smiod This is used by cpu's with simple operands. It keeps knowledge of what
58*3d8817e4Smiod an `expressionS' is and what a `fixup' is out of CGEN which for the time
59*3d8817e4Smiod being is preferable.
60*3d8817e4Smiod
61*3d8817e4Smiod OPINDEX is the index in the operand table.
62*3d8817e4Smiod OPINFO is something the caller chooses to help in reloc determination. */
63*3d8817e4Smiod
64*3d8817e4Smiod struct fixup
65*3d8817e4Smiod {
66*3d8817e4Smiod int opindex;
67*3d8817e4Smiod int opinfo;
68*3d8817e4Smiod expressionS exp;
69*3d8817e4Smiod };
70*3d8817e4Smiod
71*3d8817e4Smiod static struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
72*3d8817e4Smiod static int num_fixups;
73*3d8817e4Smiod
74*3d8817e4Smiod /* Prepare to parse an instruction.
75*3d8817e4Smiod ??? May wish to make this static and delete calls in md_assemble. */
76*3d8817e4Smiod
77*3d8817e4Smiod void
gas_cgen_init_parse()78*3d8817e4Smiod gas_cgen_init_parse ()
79*3d8817e4Smiod {
80*3d8817e4Smiod num_fixups = 0;
81*3d8817e4Smiod }
82*3d8817e4Smiod
83*3d8817e4Smiod /* Queue a fixup. */
84*3d8817e4Smiod
85*3d8817e4Smiod static void
queue_fixup(opindex,opinfo,expP)86*3d8817e4Smiod queue_fixup (opindex, opinfo, expP)
87*3d8817e4Smiod int opindex;
88*3d8817e4Smiod int opinfo;
89*3d8817e4Smiod expressionS * expP;
90*3d8817e4Smiod {
91*3d8817e4Smiod /* We need to generate a fixup for this expression. */
92*3d8817e4Smiod if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
93*3d8817e4Smiod as_fatal (_("too many fixups"));
94*3d8817e4Smiod fixups[num_fixups].exp = *expP;
95*3d8817e4Smiod fixups[num_fixups].opindex = opindex;
96*3d8817e4Smiod fixups[num_fixups].opinfo = opinfo;
97*3d8817e4Smiod ++ num_fixups;
98*3d8817e4Smiod }
99*3d8817e4Smiod
100*3d8817e4Smiod /* The following functions allow fixup chains to be stored, retrieved,
101*3d8817e4Smiod and swapped. They are a generalization of a pre-existing scheme
102*3d8817e4Smiod for storing, restoring and swapping fixup chains that was used by
103*3d8817e4Smiod the m32r port. The functionality is essentially the same, only
104*3d8817e4Smiod instead of only being able to store a single fixup chain, an entire
105*3d8817e4Smiod array of fixup chains can be stored. It is the user's responsibility
106*3d8817e4Smiod to keep track of how many fixup chains have been stored and which
107*3d8817e4Smiod elements of the array they are in.
108*3d8817e4Smiod
109*3d8817e4Smiod The algorithms used are the same as in the old scheme. Other than the
110*3d8817e4Smiod "array-ness" of the whole thing, the functionality is identical to the
111*3d8817e4Smiod old scheme.
112*3d8817e4Smiod
113*3d8817e4Smiod gas_cgen_initialize_saved_fixups_array():
114*3d8817e4Smiod Sets num_fixups_in_chain to 0 for each element. Call this from
115*3d8817e4Smiod md_begin() if you plan to use these functions and you want the
116*3d8817e4Smiod fixup count in each element to be set to 0 initially. This is
117*3d8817e4Smiod not necessary, but it's included just in case. It performs
118*3d8817e4Smiod the same function for each element in the array of fixup chains
119*3d8817e4Smiod that gas_init_parse() performs for the current fixups.
120*3d8817e4Smiod
121*3d8817e4Smiod gas_cgen_save_fixups (element):
122*3d8817e4Smiod element - element number of the array you wish to store the fixups
123*3d8817e4Smiod to. No mechanism is built in for tracking what element
124*3d8817e4Smiod was last stored to.
125*3d8817e4Smiod
126*3d8817e4Smiod gas_cgen_restore_fixups (element):
127*3d8817e4Smiod element - element number of the array you wish to restore the fixups
128*3d8817e4Smiod from.
129*3d8817e4Smiod
130*3d8817e4Smiod gas_cgen_swap_fixups(int element):
131*3d8817e4Smiod element - swap the current fixups with those in this element number.
132*3d8817e4Smiod */
133*3d8817e4Smiod
134*3d8817e4Smiod struct saved_fixups
135*3d8817e4Smiod {
136*3d8817e4Smiod struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
137*3d8817e4Smiod int num_fixups_in_chain;
138*3d8817e4Smiod };
139*3d8817e4Smiod
140*3d8817e4Smiod static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
141*3d8817e4Smiod
142*3d8817e4Smiod void
gas_cgen_initialize_saved_fixups_array()143*3d8817e4Smiod gas_cgen_initialize_saved_fixups_array ()
144*3d8817e4Smiod {
145*3d8817e4Smiod int i = 0;
146*3d8817e4Smiod
147*3d8817e4Smiod while (i < MAX_SAVED_FIXUP_CHAINS)
148*3d8817e4Smiod stored_fixups[i++].num_fixups_in_chain = 0;
149*3d8817e4Smiod }
150*3d8817e4Smiod
151*3d8817e4Smiod void
gas_cgen_save_fixups(i)152*3d8817e4Smiod gas_cgen_save_fixups (i)
153*3d8817e4Smiod int i;
154*3d8817e4Smiod {
155*3d8817e4Smiod if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
156*3d8817e4Smiod {
157*3d8817e4Smiod as_fatal ("index into stored_fixups[] out of bounds");
158*3d8817e4Smiod return;
159*3d8817e4Smiod }
160*3d8817e4Smiod
161*3d8817e4Smiod stored_fixups[i].num_fixups_in_chain = num_fixups;
162*3d8817e4Smiod memcpy (stored_fixups[i].fixup_chain, fixups,
163*3d8817e4Smiod sizeof (fixups[0]) * num_fixups);
164*3d8817e4Smiod num_fixups = 0;
165*3d8817e4Smiod }
166*3d8817e4Smiod
167*3d8817e4Smiod void
gas_cgen_restore_fixups(i)168*3d8817e4Smiod gas_cgen_restore_fixups (i)
169*3d8817e4Smiod int i;
170*3d8817e4Smiod {
171*3d8817e4Smiod if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
172*3d8817e4Smiod {
173*3d8817e4Smiod as_fatal ("index into stored_fixups[] out of bounds");
174*3d8817e4Smiod return;
175*3d8817e4Smiod }
176*3d8817e4Smiod
177*3d8817e4Smiod num_fixups = stored_fixups[i].num_fixups_in_chain;
178*3d8817e4Smiod memcpy (fixups, stored_fixups[i].fixup_chain,
179*3d8817e4Smiod (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
180*3d8817e4Smiod stored_fixups[i].num_fixups_in_chain = 0;
181*3d8817e4Smiod }
182*3d8817e4Smiod
183*3d8817e4Smiod void
gas_cgen_swap_fixups(i)184*3d8817e4Smiod gas_cgen_swap_fixups (i)
185*3d8817e4Smiod int i;
186*3d8817e4Smiod {
187*3d8817e4Smiod if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
188*3d8817e4Smiod {
189*3d8817e4Smiod as_fatal ("index into stored_fixups[] out of bounds");
190*3d8817e4Smiod return;
191*3d8817e4Smiod }
192*3d8817e4Smiod
193*3d8817e4Smiod if (num_fixups == 0)
194*3d8817e4Smiod gas_cgen_restore_fixups (i);
195*3d8817e4Smiod
196*3d8817e4Smiod else if (stored_fixups[i].num_fixups_in_chain == 0)
197*3d8817e4Smiod gas_cgen_save_fixups (i);
198*3d8817e4Smiod
199*3d8817e4Smiod else
200*3d8817e4Smiod {
201*3d8817e4Smiod int tmp;
202*3d8817e4Smiod struct fixup tmp_fixup;
203*3d8817e4Smiod
204*3d8817e4Smiod tmp = stored_fixups[i].num_fixups_in_chain;
205*3d8817e4Smiod stored_fixups[i].num_fixups_in_chain = num_fixups;
206*3d8817e4Smiod num_fixups = tmp;
207*3d8817e4Smiod
208*3d8817e4Smiod for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
209*3d8817e4Smiod {
210*3d8817e4Smiod tmp_fixup = stored_fixups[i].fixup_chain [tmp];
211*3d8817e4Smiod stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
212*3d8817e4Smiod fixups [tmp] = tmp_fixup;
213*3d8817e4Smiod }
214*3d8817e4Smiod }
215*3d8817e4Smiod }
216*3d8817e4Smiod
217*3d8817e4Smiod /* Default routine to record a fixup.
218*3d8817e4Smiod This is a cover function to fix_new.
219*3d8817e4Smiod It exists because we record INSN with the fixup.
220*3d8817e4Smiod
221*3d8817e4Smiod FRAG and WHERE are their respective arguments to fix_new_exp.
222*3d8817e4Smiod LENGTH is in bits.
223*3d8817e4Smiod OPINFO is something the caller chooses to help in reloc determination.
224*3d8817e4Smiod
225*3d8817e4Smiod At this point we do not use a bfd_reloc_code_real_type for
226*3d8817e4Smiod operands residing in the insn, but instead just use the
227*3d8817e4Smiod operand index. This lets us easily handle fixups for any
228*3d8817e4Smiod operand type. We pick a BFD reloc type in md_apply_fix. */
229*3d8817e4Smiod
230*3d8817e4Smiod fixS *
gas_cgen_record_fixup(frag,where,insn,length,operand,opinfo,symbol,offset)231*3d8817e4Smiod gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
232*3d8817e4Smiod fragS * frag;
233*3d8817e4Smiod int where;
234*3d8817e4Smiod const CGEN_INSN * insn;
235*3d8817e4Smiod int length;
236*3d8817e4Smiod const CGEN_OPERAND * operand;
237*3d8817e4Smiod int opinfo;
238*3d8817e4Smiod symbolS * symbol;
239*3d8817e4Smiod offsetT offset;
240*3d8817e4Smiod {
241*3d8817e4Smiod fixS *fixP;
242*3d8817e4Smiod
243*3d8817e4Smiod /* It may seem strange to use operand->attrs and not insn->attrs here,
244*3d8817e4Smiod but it is the operand that has a pc relative relocation. */
245*3d8817e4Smiod fixP = fix_new (frag, where, length / 8, symbol, offset,
246*3d8817e4Smiod CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
247*3d8817e4Smiod (bfd_reloc_code_real_type)
248*3d8817e4Smiod ((int) BFD_RELOC_UNUSED
249*3d8817e4Smiod + (int) operand->type));
250*3d8817e4Smiod fixP->fx_cgen.insn = insn;
251*3d8817e4Smiod fixP->fx_cgen.opinfo = opinfo;
252*3d8817e4Smiod
253*3d8817e4Smiod return fixP;
254*3d8817e4Smiod }
255*3d8817e4Smiod
256*3d8817e4Smiod /* Default routine to record a fixup given an expression.
257*3d8817e4Smiod This is a cover function to fix_new_exp.
258*3d8817e4Smiod It exists because we record INSN with the fixup.
259*3d8817e4Smiod
260*3d8817e4Smiod FRAG and WHERE are their respective arguments to fix_new_exp.
261*3d8817e4Smiod LENGTH is in bits.
262*3d8817e4Smiod OPINFO is something the caller chooses to help in reloc determination.
263*3d8817e4Smiod
264*3d8817e4Smiod At this point we do not use a bfd_reloc_code_real_type for
265*3d8817e4Smiod operands residing in the insn, but instead just use the
266*3d8817e4Smiod operand index. This lets us easily handle fixups for any
267*3d8817e4Smiod operand type. We pick a BFD reloc type in md_apply_fix. */
268*3d8817e4Smiod
269*3d8817e4Smiod fixS *
gas_cgen_record_fixup_exp(frag,where,insn,length,operand,opinfo,exp)270*3d8817e4Smiod gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
271*3d8817e4Smiod fragS * frag;
272*3d8817e4Smiod int where;
273*3d8817e4Smiod const CGEN_INSN * insn;
274*3d8817e4Smiod int length;
275*3d8817e4Smiod const CGEN_OPERAND * operand;
276*3d8817e4Smiod int opinfo;
277*3d8817e4Smiod expressionS * exp;
278*3d8817e4Smiod {
279*3d8817e4Smiod fixS *fixP;
280*3d8817e4Smiod
281*3d8817e4Smiod /* It may seem strange to use operand->attrs and not insn->attrs here,
282*3d8817e4Smiod but it is the operand that has a pc relative relocation. */
283*3d8817e4Smiod fixP = fix_new_exp (frag, where, length / 8, exp,
284*3d8817e4Smiod CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
285*3d8817e4Smiod (bfd_reloc_code_real_type)
286*3d8817e4Smiod ((int) BFD_RELOC_UNUSED
287*3d8817e4Smiod + (int) operand->type));
288*3d8817e4Smiod fixP->fx_cgen.insn = insn;
289*3d8817e4Smiod fixP->fx_cgen.opinfo = opinfo;
290*3d8817e4Smiod
291*3d8817e4Smiod return fixP;
292*3d8817e4Smiod }
293*3d8817e4Smiod
294*3d8817e4Smiod /* Used for communication between the next two procedures. */
295*3d8817e4Smiod static jmp_buf expr_jmp_buf;
296*3d8817e4Smiod static int expr_jmp_buf_p;
297*3d8817e4Smiod
298*3d8817e4Smiod /* Callback for cgen interface. Parse the expression at *STRP.
299*3d8817e4Smiod The result is an error message or NULL for success (in which case
300*3d8817e4Smiod *STRP is advanced past the parsed text).
301*3d8817e4Smiod WANT is an indication of what the caller is looking for.
302*3d8817e4Smiod If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
303*3d8817e4Smiod a table entry with the insn, reset the queued fixups counter.
304*3d8817e4Smiod An enum cgen_parse_operand_result is stored in RESULTP.
305*3d8817e4Smiod OPINDEX is the operand's table entry index.
306*3d8817e4Smiod OPINFO is something the caller chooses to help in reloc determination.
307*3d8817e4Smiod The resulting value is stored in VALUEP. */
308*3d8817e4Smiod
309*3d8817e4Smiod const char *
gas_cgen_parse_operand(cd,want,strP,opindex,opinfo,resultP,valueP)310*3d8817e4Smiod gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
311*3d8817e4Smiod CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
312*3d8817e4Smiod enum cgen_parse_operand_type want;
313*3d8817e4Smiod const char **strP;
314*3d8817e4Smiod int opindex;
315*3d8817e4Smiod int opinfo;
316*3d8817e4Smiod enum cgen_parse_operand_result *resultP;
317*3d8817e4Smiod bfd_vma *valueP;
318*3d8817e4Smiod {
319*3d8817e4Smiod #ifdef __STDC__
320*3d8817e4Smiod /* These are volatile to survive the setjmp. */
321*3d8817e4Smiod char * volatile hold;
322*3d8817e4Smiod enum cgen_parse_operand_result * volatile resultP_1;
323*3d8817e4Smiod volatile int opinfo_1;
324*3d8817e4Smiod #else
325*3d8817e4Smiod static char *hold;
326*3d8817e4Smiod static enum cgen_parse_operand_result *resultP_1;
327*3d8817e4Smiod int opinfo_1;
328*3d8817e4Smiod #endif
329*3d8817e4Smiod const char *errmsg;
330*3d8817e4Smiod expressionS exp;
331*3d8817e4Smiod
332*3d8817e4Smiod if (want == CGEN_PARSE_OPERAND_INIT)
333*3d8817e4Smiod {
334*3d8817e4Smiod gas_cgen_init_parse ();
335*3d8817e4Smiod return NULL;
336*3d8817e4Smiod }
337*3d8817e4Smiod
338*3d8817e4Smiod resultP_1 = resultP;
339*3d8817e4Smiod hold = input_line_pointer;
340*3d8817e4Smiod input_line_pointer = (char *) *strP;
341*3d8817e4Smiod opinfo_1 = opinfo;
342*3d8817e4Smiod
343*3d8817e4Smiod /* We rely on md_operand to longjmp back to us.
344*3d8817e4Smiod This is done via gas_cgen_md_operand. */
345*3d8817e4Smiod if (setjmp (expr_jmp_buf) != 0)
346*3d8817e4Smiod {
347*3d8817e4Smiod expr_jmp_buf_p = 0;
348*3d8817e4Smiod input_line_pointer = (char *) hold;
349*3d8817e4Smiod *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
350*3d8817e4Smiod return _("illegal operand");
351*3d8817e4Smiod }
352*3d8817e4Smiod
353*3d8817e4Smiod expr_jmp_buf_p = 1;
354*3d8817e4Smiod expression (&exp);
355*3d8817e4Smiod expr_jmp_buf_p = 0;
356*3d8817e4Smiod errmsg = NULL;
357*3d8817e4Smiod
358*3d8817e4Smiod *strP = input_line_pointer;
359*3d8817e4Smiod input_line_pointer = hold;
360*3d8817e4Smiod
361*3d8817e4Smiod #ifdef TC_CGEN_PARSE_FIX_EXP
362*3d8817e4Smiod opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
363*3d8817e4Smiod #endif
364*3d8817e4Smiod
365*3d8817e4Smiod /* FIXME: Need to check `want'. */
366*3d8817e4Smiod
367*3d8817e4Smiod switch (exp.X_op)
368*3d8817e4Smiod {
369*3d8817e4Smiod case O_illegal:
370*3d8817e4Smiod errmsg = _("illegal operand");
371*3d8817e4Smiod *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
372*3d8817e4Smiod break;
373*3d8817e4Smiod case O_absent:
374*3d8817e4Smiod errmsg = _("missing operand");
375*3d8817e4Smiod *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
376*3d8817e4Smiod break;
377*3d8817e4Smiod case O_constant:
378*3d8817e4Smiod if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
379*3d8817e4Smiod goto de_fault;
380*3d8817e4Smiod *valueP = exp.X_add_number;
381*3d8817e4Smiod *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
382*3d8817e4Smiod break;
383*3d8817e4Smiod case O_register:
384*3d8817e4Smiod *valueP = exp.X_add_number;
385*3d8817e4Smiod *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
386*3d8817e4Smiod break;
387*3d8817e4Smiod de_fault:
388*3d8817e4Smiod default:
389*3d8817e4Smiod queue_fixup (opindex, opinfo_1, &exp);
390*3d8817e4Smiod *valueP = 0;
391*3d8817e4Smiod *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
392*3d8817e4Smiod break;
393*3d8817e4Smiod }
394*3d8817e4Smiod
395*3d8817e4Smiod return errmsg;
396*3d8817e4Smiod }
397*3d8817e4Smiod
398*3d8817e4Smiod /* md_operand handler to catch unrecognized expressions and halt the
399*3d8817e4Smiod parsing process so the next entry can be tried.
400*3d8817e4Smiod
401*3d8817e4Smiod ??? This could be done differently by adding code to `expression'. */
402*3d8817e4Smiod
403*3d8817e4Smiod void
gas_cgen_md_operand(expressionP)404*3d8817e4Smiod gas_cgen_md_operand (expressionP)
405*3d8817e4Smiod expressionS *expressionP ATTRIBUTE_UNUSED;
406*3d8817e4Smiod {
407*3d8817e4Smiod /* Don't longjmp if we're not called from within cgen_parse_operand(). */
408*3d8817e4Smiod if (expr_jmp_buf_p)
409*3d8817e4Smiod longjmp (expr_jmp_buf, 1);
410*3d8817e4Smiod }
411*3d8817e4Smiod
412*3d8817e4Smiod /* Finish assembling instruction INSN.
413*3d8817e4Smiod BUF contains what we've built up so far.
414*3d8817e4Smiod LENGTH is the size of the insn in bits.
415*3d8817e4Smiod RELAX_P is non-zero if relaxable insns should be emitted as such.
416*3d8817e4Smiod Otherwise they're emitted in non-relaxable forms.
417*3d8817e4Smiod The "result" is stored in RESULT if non-NULL. */
418*3d8817e4Smiod
419*3d8817e4Smiod void
gas_cgen_finish_insn(insn,buf,length,relax_p,result)420*3d8817e4Smiod gas_cgen_finish_insn (insn, buf, length, relax_p, result)
421*3d8817e4Smiod const CGEN_INSN *insn;
422*3d8817e4Smiod CGEN_INSN_BYTES_PTR buf;
423*3d8817e4Smiod unsigned int length;
424*3d8817e4Smiod int relax_p;
425*3d8817e4Smiod finished_insnS *result;
426*3d8817e4Smiod {
427*3d8817e4Smiod int i;
428*3d8817e4Smiod int relax_operand;
429*3d8817e4Smiod char *f;
430*3d8817e4Smiod unsigned int byte_len = length / 8;
431*3d8817e4Smiod
432*3d8817e4Smiod /* ??? Target foo issues various warnings here, so one might want to provide
433*3d8817e4Smiod a hook here. However, our caller is defined in tc-foo.c so there
434*3d8817e4Smiod shouldn't be a need for a hook. */
435*3d8817e4Smiod
436*3d8817e4Smiod /* Write out the instruction.
437*3d8817e4Smiod It is important to fetch enough space in one call to `frag_more'.
438*3d8817e4Smiod We use (f - frag_now->fr_literal) to compute where we are and we
439*3d8817e4Smiod don't want frag_now to change between calls.
440*3d8817e4Smiod
441*3d8817e4Smiod Relaxable instructions: We need to ensure we allocate enough
442*3d8817e4Smiod space for the largest insn. */
443*3d8817e4Smiod
444*3d8817e4Smiod if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
445*3d8817e4Smiod /* These currently shouldn't get here. */
446*3d8817e4Smiod abort ();
447*3d8817e4Smiod
448*3d8817e4Smiod /* Is there a relaxable insn with the relaxable operand needing a fixup? */
449*3d8817e4Smiod
450*3d8817e4Smiod relax_operand = -1;
451*3d8817e4Smiod if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
452*3d8817e4Smiod {
453*3d8817e4Smiod /* Scan the fixups for the operand affected by relaxing
454*3d8817e4Smiod (i.e. the branch address). */
455*3d8817e4Smiod
456*3d8817e4Smiod for (i = 0; i < num_fixups; ++i)
457*3d8817e4Smiod {
458*3d8817e4Smiod if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
459*3d8817e4Smiod CGEN_OPERAND_RELAX))
460*3d8817e4Smiod {
461*3d8817e4Smiod relax_operand = i;
462*3d8817e4Smiod break;
463*3d8817e4Smiod }
464*3d8817e4Smiod }
465*3d8817e4Smiod }
466*3d8817e4Smiod
467*3d8817e4Smiod if (relax_operand != -1)
468*3d8817e4Smiod {
469*3d8817e4Smiod int max_len;
470*3d8817e4Smiod fragS *old_frag;
471*3d8817e4Smiod expressionS *exp;
472*3d8817e4Smiod symbolS *sym;
473*3d8817e4Smiod offsetT off;
474*3d8817e4Smiod
475*3d8817e4Smiod #ifdef TC_CGEN_MAX_RELAX
476*3d8817e4Smiod max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
477*3d8817e4Smiod #else
478*3d8817e4Smiod max_len = CGEN_MAX_INSN_SIZE;
479*3d8817e4Smiod #endif
480*3d8817e4Smiod /* Ensure variable part and fixed part are in same fragment. */
481*3d8817e4Smiod /* FIXME: Having to do this seems like a hack. */
482*3d8817e4Smiod frag_grow (max_len);
483*3d8817e4Smiod
484*3d8817e4Smiod /* Allocate space for the fixed part. */
485*3d8817e4Smiod f = frag_more (byte_len);
486*3d8817e4Smiod
487*3d8817e4Smiod /* Create a relaxable fragment for this instruction. */
488*3d8817e4Smiod old_frag = frag_now;
489*3d8817e4Smiod
490*3d8817e4Smiod exp = &fixups[relax_operand].exp;
491*3d8817e4Smiod sym = exp->X_add_symbol;
492*3d8817e4Smiod off = exp->X_add_number;
493*3d8817e4Smiod if (exp->X_op != O_constant && exp->X_op != O_symbol)
494*3d8817e4Smiod {
495*3d8817e4Smiod /* Handle complex expressions. */
496*3d8817e4Smiod sym = make_expr_symbol (exp);
497*3d8817e4Smiod off = 0;
498*3d8817e4Smiod }
499*3d8817e4Smiod
500*3d8817e4Smiod frag_var (rs_machine_dependent,
501*3d8817e4Smiod max_len - byte_len /* max chars */,
502*3d8817e4Smiod 0 /* variable part already allocated */,
503*3d8817e4Smiod /* FIXME: When we machine generate the relax table,
504*3d8817e4Smiod machine generate a macro to compute subtype. */
505*3d8817e4Smiod 1 /* subtype */,
506*3d8817e4Smiod sym,
507*3d8817e4Smiod off,
508*3d8817e4Smiod f);
509*3d8817e4Smiod
510*3d8817e4Smiod /* Record the operand number with the fragment so md_convert_frag
511*3d8817e4Smiod can use gas_cgen_md_record_fixup to record the appropriate reloc. */
512*3d8817e4Smiod old_frag->fr_cgen.insn = insn;
513*3d8817e4Smiod old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
514*3d8817e4Smiod old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
515*3d8817e4Smiod if (result)
516*3d8817e4Smiod result->frag = old_frag;
517*3d8817e4Smiod }
518*3d8817e4Smiod else
519*3d8817e4Smiod {
520*3d8817e4Smiod f = frag_more (byte_len);
521*3d8817e4Smiod if (result)
522*3d8817e4Smiod result->frag = frag_now;
523*3d8817e4Smiod }
524*3d8817e4Smiod
525*3d8817e4Smiod /* If we're recording insns as numbers (rather than a string of bytes),
526*3d8817e4Smiod target byte order handling is deferred until now. */
527*3d8817e4Smiod #if CGEN_INT_INSN_P
528*3d8817e4Smiod cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
529*3d8817e4Smiod #else
530*3d8817e4Smiod memcpy (f, buf, byte_len);
531*3d8817e4Smiod #endif
532*3d8817e4Smiod
533*3d8817e4Smiod /* Emit DWARF2 debugging information. */
534*3d8817e4Smiod dwarf2_emit_insn (byte_len);
535*3d8817e4Smiod
536*3d8817e4Smiod /* Create any fixups. */
537*3d8817e4Smiod for (i = 0; i < num_fixups; ++i)
538*3d8817e4Smiod {
539*3d8817e4Smiod fixS *fixP;
540*3d8817e4Smiod const CGEN_OPERAND *operand =
541*3d8817e4Smiod cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);
542*3d8817e4Smiod
543*3d8817e4Smiod /* Don't create fixups for these. That's done during relaxation.
544*3d8817e4Smiod We don't need to test for CGEN_INSN_RELAXED as they can't get here
545*3d8817e4Smiod (see above). */
546*3d8817e4Smiod if (relax_p
547*3d8817e4Smiod && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
548*3d8817e4Smiod && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
549*3d8817e4Smiod continue;
550*3d8817e4Smiod
551*3d8817e4Smiod #ifndef md_cgen_record_fixup_exp
552*3d8817e4Smiod #define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
553*3d8817e4Smiod #endif
554*3d8817e4Smiod
555*3d8817e4Smiod fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
556*3d8817e4Smiod insn, length, operand,
557*3d8817e4Smiod fixups[i].opinfo,
558*3d8817e4Smiod &fixups[i].exp);
559*3d8817e4Smiod if (result)
560*3d8817e4Smiod result->fixups[i] = fixP;
561*3d8817e4Smiod }
562*3d8817e4Smiod
563*3d8817e4Smiod if (result)
564*3d8817e4Smiod {
565*3d8817e4Smiod result->num_fixups = num_fixups;
566*3d8817e4Smiod result->addr = f;
567*3d8817e4Smiod }
568*3d8817e4Smiod }
569*3d8817e4Smiod
570*3d8817e4Smiod /* Apply a fixup to the object code. This is called for all the
571*3d8817e4Smiod fixups we generated by the call to fix_new_exp, above. In the call
572*3d8817e4Smiod above we used a reloc code which was the largest legal reloc code
573*3d8817e4Smiod plus the operand index. Here we undo that to recover the operand
574*3d8817e4Smiod index. At this point all symbol values should be fully resolved,
575*3d8817e4Smiod and we attempt to completely resolve the reloc. If we can not do
576*3d8817e4Smiod that, we determine the correct reloc code and put it back in the fixup. */
577*3d8817e4Smiod
578*3d8817e4Smiod /* FIXME: This function handles some of the fixups and bfd_install_relocation
579*3d8817e4Smiod handles the rest. bfd_install_relocation (or some other bfd function)
580*3d8817e4Smiod should handle them all. */
581*3d8817e4Smiod
582*3d8817e4Smiod void
gas_cgen_md_apply_fix(fixP,valP,seg)583*3d8817e4Smiod gas_cgen_md_apply_fix (fixP, valP, seg)
584*3d8817e4Smiod fixS * fixP;
585*3d8817e4Smiod valueT * valP;
586*3d8817e4Smiod segT seg ATTRIBUTE_UNUSED;
587*3d8817e4Smiod {
588*3d8817e4Smiod char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
589*3d8817e4Smiod valueT value = * valP;
590*3d8817e4Smiod /* Canonical name, since used a lot. */
591*3d8817e4Smiod CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
592*3d8817e4Smiod
593*3d8817e4Smiod if (fixP->fx_addsy == (symbolS *) NULL)
594*3d8817e4Smiod fixP->fx_done = 1;
595*3d8817e4Smiod
596*3d8817e4Smiod /* We don't actually support subtracting a symbol. */
597*3d8817e4Smiod if (fixP->fx_subsy != (symbolS *) NULL)
598*3d8817e4Smiod as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
599*3d8817e4Smiod
600*3d8817e4Smiod if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
601*3d8817e4Smiod {
602*3d8817e4Smiod int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
603*3d8817e4Smiod const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
604*3d8817e4Smiod const char *errmsg;
605*3d8817e4Smiod bfd_reloc_code_real_type reloc_type;
606*3d8817e4Smiod CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
607*3d8817e4Smiod const CGEN_INSN *insn = fixP->fx_cgen.insn;
608*3d8817e4Smiod
609*3d8817e4Smiod /* If the reloc has been fully resolved finish the operand here. */
610*3d8817e4Smiod /* FIXME: This duplicates the capabilities of code in BFD. */
611*3d8817e4Smiod if (fixP->fx_done
612*3d8817e4Smiod /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
613*3d8817e4Smiod finish the job. Testing for pcrel is a temporary hack. */
614*3d8817e4Smiod || fixP->fx_pcrel)
615*3d8817e4Smiod {
616*3d8817e4Smiod CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
617*3d8817e4Smiod CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
618*3d8817e4Smiod
619*3d8817e4Smiod #if CGEN_INT_INSN_P
620*3d8817e4Smiod {
621*3d8817e4Smiod CGEN_INSN_INT insn_value =
622*3d8817e4Smiod cgen_get_insn_value (cd, (unsigned char *) where,
623*3d8817e4Smiod CGEN_INSN_BITSIZE (insn));
624*3d8817e4Smiod
625*3d8817e4Smiod /* ??? 0 is passed for `pc'. */
626*3d8817e4Smiod errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
627*3d8817e4Smiod &insn_value, (bfd_vma) 0);
628*3d8817e4Smiod cgen_put_insn_value (cd, (unsigned char *) where,
629*3d8817e4Smiod CGEN_INSN_BITSIZE (insn), insn_value);
630*3d8817e4Smiod }
631*3d8817e4Smiod #else
632*3d8817e4Smiod /* ??? 0 is passed for `pc'. */
633*3d8817e4Smiod errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
634*3d8817e4Smiod (unsigned char *) where,
635*3d8817e4Smiod (bfd_vma) 0);
636*3d8817e4Smiod #endif
637*3d8817e4Smiod if (errmsg)
638*3d8817e4Smiod as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
639*3d8817e4Smiod }
640*3d8817e4Smiod
641*3d8817e4Smiod if (fixP->fx_done)
642*3d8817e4Smiod return;
643*3d8817e4Smiod
644*3d8817e4Smiod /* The operand isn't fully resolved. Determine a BFD reloc value
645*3d8817e4Smiod based on the operand information and leave it to
646*3d8817e4Smiod bfd_install_relocation. Note that this doesn't work when
647*3d8817e4Smiod partial_inplace == false. */
648*3d8817e4Smiod
649*3d8817e4Smiod reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
650*3d8817e4Smiod
651*3d8817e4Smiod if (reloc_type != BFD_RELOC_NONE)
652*3d8817e4Smiod fixP->fx_r_type = reloc_type;
653*3d8817e4Smiod else
654*3d8817e4Smiod {
655*3d8817e4Smiod as_bad_where (fixP->fx_file, fixP->fx_line,
656*3d8817e4Smiod _("unresolved expression that must be resolved"));
657*3d8817e4Smiod fixP->fx_done = 1;
658*3d8817e4Smiod return;
659*3d8817e4Smiod }
660*3d8817e4Smiod }
661*3d8817e4Smiod else if (fixP->fx_done)
662*3d8817e4Smiod {
663*3d8817e4Smiod /* We're finished with this fixup. Install it because
664*3d8817e4Smiod bfd_install_relocation won't be called to do it. */
665*3d8817e4Smiod switch (fixP->fx_r_type)
666*3d8817e4Smiod {
667*3d8817e4Smiod case BFD_RELOC_8:
668*3d8817e4Smiod md_number_to_chars (where, value, 1);
669*3d8817e4Smiod break;
670*3d8817e4Smiod case BFD_RELOC_16:
671*3d8817e4Smiod md_number_to_chars (where, value, 2);
672*3d8817e4Smiod break;
673*3d8817e4Smiod case BFD_RELOC_32:
674*3d8817e4Smiod md_number_to_chars (where, value, 4);
675*3d8817e4Smiod break;
676*3d8817e4Smiod case BFD_RELOC_64:
677*3d8817e4Smiod md_number_to_chars (where, value, 8);
678*3d8817e4Smiod break;
679*3d8817e4Smiod default:
680*3d8817e4Smiod as_bad_where (fixP->fx_file, fixP->fx_line,
681*3d8817e4Smiod _("internal error: can't install fix for reloc type %d (`%s')"),
682*3d8817e4Smiod fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
683*3d8817e4Smiod break;
684*3d8817e4Smiod }
685*3d8817e4Smiod }
686*3d8817e4Smiod /* else
687*3d8817e4Smiod bfd_install_relocation will be called to finish things up. */
688*3d8817e4Smiod
689*3d8817e4Smiod /* Tuck `value' away for use by tc_gen_reloc.
690*3d8817e4Smiod See the comment describing fx_addnumber in write.h.
691*3d8817e4Smiod This field is misnamed (or misused :-). */
692*3d8817e4Smiod fixP->fx_addnumber = value;
693*3d8817e4Smiod }
694*3d8817e4Smiod
695*3d8817e4Smiod /* Translate internal representation of relocation info to BFD target format.
696*3d8817e4Smiod
697*3d8817e4Smiod FIXME: To what extent can we get all relevant targets to use this? */
698*3d8817e4Smiod
699*3d8817e4Smiod arelent *
gas_cgen_tc_gen_reloc(section,fixP)700*3d8817e4Smiod gas_cgen_tc_gen_reloc (section, fixP)
701*3d8817e4Smiod asection * section ATTRIBUTE_UNUSED;
702*3d8817e4Smiod fixS * fixP;
703*3d8817e4Smiod {
704*3d8817e4Smiod arelent *reloc;
705*3d8817e4Smiod
706*3d8817e4Smiod reloc = (arelent *) xmalloc (sizeof (arelent));
707*3d8817e4Smiod
708*3d8817e4Smiod reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
709*3d8817e4Smiod if (reloc->howto == (reloc_howto_type *) NULL)
710*3d8817e4Smiod {
711*3d8817e4Smiod as_bad_where (fixP->fx_file, fixP->fx_line,
712*3d8817e4Smiod _("relocation is not supported"));
713*3d8817e4Smiod return NULL;
714*3d8817e4Smiod }
715*3d8817e4Smiod
716*3d8817e4Smiod assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
717*3d8817e4Smiod
718*3d8817e4Smiod reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
719*3d8817e4Smiod *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
720*3d8817e4Smiod
721*3d8817e4Smiod /* Use fx_offset for these cases. */
722*3d8817e4Smiod if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
723*3d8817e4Smiod || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
724*3d8817e4Smiod reloc->addend = fixP->fx_offset;
725*3d8817e4Smiod else
726*3d8817e4Smiod reloc->addend = fixP->fx_addnumber;
727*3d8817e4Smiod
728*3d8817e4Smiod reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
729*3d8817e4Smiod return reloc;
730*3d8817e4Smiod }
731*3d8817e4Smiod
732*3d8817e4Smiod /* Perform any cgen specific initialisation.
733*3d8817e4Smiod Called after gas_cgen_cpu_desc has been created. */
734*3d8817e4Smiod
735*3d8817e4Smiod void
gas_cgen_begin()736*3d8817e4Smiod gas_cgen_begin ()
737*3d8817e4Smiod {
738*3d8817e4Smiod if (flag_signed_overflow_ok)
739*3d8817e4Smiod cgen_set_signed_overflow_ok (gas_cgen_cpu_desc);
740*3d8817e4Smiod else
741*3d8817e4Smiod cgen_clear_signed_overflow_ok (gas_cgen_cpu_desc);
742*3d8817e4Smiod }
743