xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/cgen.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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