Tweak comment.
[platform/upstream/binutils.git] / gas / cgen.c
1 /* GAS interface for targets using CGEN: Cpu tools GENerator.
2    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING.  If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20 #include "ansidecl.h"
21 #include "bfd.h"
22 #include "cgen-opc.h"
23 #include "as.h"
24 #include "subsegs.h"
25
26 /* Callback to insert a register into the symbol table.
27    A target may choose to let GAS parse the registers.
28    ??? Not currently used.  */
29
30 void
31 cgen_asm_record_register (name, number)
32      char *name;
33      int number;
34 {
35   /* Use symbol_create here instead of symbol_new so we don't try to
36      output registers into the object file's symbol table.  */
37   symbol_table_insert (symbol_create (name, reg_section,
38                                       number, &zero_address_frag));
39 }
40
41 /* We need to keep a list of fixups.  We can't simply generate them as
42    we go, because that would require us to first create the frag, and
43    that would screw up references to ``.''.
44
45    This is used by cpu's with simple operands.  It keeps knowledge of what
46    an `expressionS' is and what a `fixup' is out of CGEN which for the time
47    being is preferable.
48
49    OPINDEX is the index in the operand table.
50    OPINFO is something the caller chooses to help in reloc determination.  */
51
52 struct fixup
53 {
54   int opindex;
55   int opinfo;
56   expressionS exp;
57 };
58
59 #define MAX_FIXUPS 5
60
61 static struct fixup fixups[MAX_FIXUPS];
62 static int num_fixups;
63
64 void
65 cgen_asm_init_parse ()
66 {
67   num_fixups = 0;
68 }
69
70 /* Queue a fixup.  */
71
72 void
73 cgen_queue_fixup (opindex, opinfo, expP)
74      int opindex;
75      expressionS *expP;
76 {
77   /* We need to generate a fixup for this expression.  */
78   if (num_fixups >= MAX_FIXUPS)
79     as_fatal ("too many fixups");
80   fixups[num_fixups].exp = *expP;
81   fixups[num_fixups].opindex = opindex;
82   fixups[num_fixups].opinfo = opinfo;
83   ++num_fixups;
84 }
85
86 /* Default routine to record a fixup.
87    This is a cover function to fix_new.
88    It exists because we record INSN with the fixup.
89
90    FRAG and WHERE are their respective arguments to fix_new_exp.
91    LENGTH is in bits.
92    OPINFO is something the caller chooses to help in reloc determination.
93
94    At this point we do not use a bfd_reloc_code_real_type for
95    operands residing in the insn, but instead just use the
96    operand index.  This lets us easily handle fixups for any
97    operand type.  We pick a BFD reloc type in md_apply_fix.  */
98
99 fixS *
100 cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
101      fragS *frag;
102      int where;
103      const struct cgen_insn *insn;
104      int length;
105      const struct cgen_operand *operand;
106      int opinfo;
107      symbolS *symbol;
108      offsetT offset;
109 {
110   fixS *fixP;
111
112   /* It may seem strange to use operand->attrs and not insn->attrs here,
113      but it is the operand that has a pc relative relocation.  */
114
115   fixP = fix_new (frag, where, length / 8, symbol, offset,
116                   CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
117                   (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
118   fixP->tc_fix_data.insn = (PTR) insn;
119   fixP->tc_fix_data.opinfo = opinfo;
120
121   return fixP;
122 }
123
124 /* Default routine to record a fixup given an expression.
125    This is a cover function to fix_new_exp.
126    It exists because we record INSN with the fixup.
127
128    FRAG and WHERE are their respective arguments to fix_new_exp.
129    LENGTH is in bits.
130    OPINFO is something the caller chooses to help in reloc determination.
131
132    At this point we do not use a bfd_reloc_code_real_type for
133    operands residing in the insn, but instead just use the
134    operand index.  This lets us easily handle fixups for any
135    operand type.  We pick a BFD reloc type in md_apply_fix.  */
136
137 fixS *
138 cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
139      fragS *frag;
140      int where;
141      const struct cgen_insn *insn;
142      int length;
143      const struct cgen_operand *operand;
144      int opinfo;
145      expressionS *exp;
146 {
147   fixS *fixP;
148
149   /* It may seem strange to use operand->attrs and not insn->attrs here,
150      but it is the operand that has a pc relative relocation.  */
151
152   fixP = fix_new_exp (frag, where, length / 8, exp,
153                       CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
154                       (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
155   fixP->tc_fix_data.insn = (PTR) insn;
156   fixP->tc_fix_data.opinfo = opinfo;
157
158   return fixP;
159 }
160
161 /* Callback for cgen interface.  Parse the expression at *STRP.
162    The result is an error message or NULL for success (in which case
163    *STRP is advanced past the parsed text).
164    An enum cgen_asm_result is stored in RESULTP.
165    OPINFO is something the caller chooses to help in reloc determination.
166    The resulting value is stored in VALUEP.  */
167
168 const char *
169 cgen_asm_parse_operand (strP, opindex, opinfo, resultP, valueP)
170      const char **strP;
171      int opindex;
172      int opinfo;
173      enum cgen_asm_result *resultP;
174      bfd_vma *valueP;
175 {
176   char *hold;
177   const char *errmsg = NULL;
178   expressionS exp;
179
180   hold = input_line_pointer;
181   input_line_pointer = (char *) *strP;
182   expression (&exp);
183   *strP = input_line_pointer;
184   input_line_pointer = hold;
185
186   switch (exp.X_op)
187     {
188     case O_illegal :
189       errmsg = "illegal operand";
190       *resultP = CGEN_ASM_ERROR;
191       break;
192     case O_absent :
193       errmsg = "missing operand";
194       *resultP = CGEN_ASM_ERROR;
195       break;
196     case O_constant :
197       *valueP = exp.X_add_number;
198       *resultP = CGEN_ASM_NUMBER;
199       break;
200     case O_register :
201       *valueP = exp.X_add_number;
202       *resultP = CGEN_ASM_REGISTER;
203       break;
204     default :
205       cgen_queue_fixup (opindex, opinfo, &exp);
206       *valueP = 0;
207       *resultP = CGEN_ASM_QUEUED;
208       break;
209     }
210
211   return errmsg;
212 }
213
214 /* Finish assembling instruction INSN.
215    BUF contains what we've built up so far.
216    LENGTH is the size of the insn in bits.  */
217
218 void
219 cgen_asm_finish_insn (insn, buf, length)
220      const struct cgen_insn *insn;
221      cgen_insn_t *buf;
222      unsigned int length;
223 {
224   int i, relax_operand;
225   char *f;
226   unsigned int byte_len = length / 8;
227
228   /* ??? Target foo issues various warnings here, so one might want to provide
229      a hook here.  However, our caller is defined in tc-foo.c so there
230      shouldn't be a need for a hook.  */
231
232   /* Write out the instruction.
233      It is important to fetch enough space in one call to `frag_more'.
234      We use (f - frag_now->fr_literal) to compute where we are and we
235      don't want frag_now to change between calls.
236
237      Relaxable instructions: We need to ensure we allocate enough
238      space for the largest insn.  */
239
240   if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
241     abort (); /* These currently shouldn't get here.  */
242
243   /* Is there a relaxable insn with the relaxable operand needing a fixup?  */
244
245   relax_operand = -1;
246   if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0)
247     {
248       /* Scan the fixups for the operand affected by relaxing
249          (i.e. the branch address).  */
250
251       for (i = 0; i < num_fixups; ++i)
252         {
253           if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
254                                  CGEN_OPERAND_RELAX) != 0)
255             {
256               relax_operand = i;
257               break;
258             }
259         }
260     }
261
262   if (relax_operand != -1)
263     {
264       int max_len;
265       fragS *old_frag;
266
267 #ifdef TC_CGEN_MAX_RELAX
268       max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
269 #else
270       max_len = CGEN_MAX_INSN_SIZE;
271 #endif
272       /* Ensure variable part and fixed part are in same fragment.  */
273       /* FIXME: Having to do this seems like a hack.  */
274       frag_grow (max_len);
275       /* Allocate space for the fixed part.  */
276       f = frag_more (byte_len);
277       /* Create a relaxable fragment for this instruction.  */
278       old_frag = frag_now;
279       frag_var (rs_machine_dependent,
280                 max_len - byte_len /* max chars */,
281                 0 /* variable part already allocated */,
282                 /* FIXME: When we machine generate the relax table,
283                    machine generate a macro to compute subtype.  */
284                 1 /* subtype */,
285                 fixups[relax_operand].exp.X_add_symbol,
286                 fixups[relax_operand].exp.X_add_number,
287                 f);
288       /* Record the operand number with the fragment so md_convert_frag
289          can use cgen_md_record_fixup to record the appropriate reloc.  */
290       /* FIXME: fr_targ.cgen is used pending deciding whether to
291          allow a target to add members to fragS.  For more info
292          see the comment above fr_targ in as.h.  */
293       old_frag->fr_targ.cgen.insn = insn;
294       old_frag->fr_targ.cgen.opindex = fixups[relax_operand].opindex;
295       old_frag->fr_targ.cgen.opinfo = fixups[relax_operand].opinfo;
296     }
297   else
298     f = frag_more (byte_len);
299
300   /* If we're recording insns as numbers (rather than a string of bytes),
301      target byte order handling is deferred until now.  */
302 #if 0 /*def CGEN_INT_INSN*/
303   switch (length)
304     {
305     case 16:
306       if (cgen_big_endian_p)
307         bfd_putb16 ((bfd_vma) *buf, f);
308       else
309         bfd_putl16 ((bfd_vma) *buf, f);
310       break;
311     case 32:
312       if (cgen_big_endian_p)
313         bfd_putb32 ((bfd_vma) *buf, f);
314       else
315         bfd_putl32 ((bfd_vma) *buf, f);
316       break;
317     default:
318       abort ();
319     }
320 #else
321   memcpy (f, buf, byte_len);
322 #endif
323
324   /* Create any fixups.  */
325   for (i = 0; i < num_fixups; ++i)
326     {
327       /* Don't create fixups for these.  That's done during relaxation.
328          We don't need to test for CGEN_INSN_RELAX as they can't get here
329          (see above).  */
330       if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAXABLE) != 0
331           && CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
332                                 CGEN_OPERAND_RELAX) != 0)
333         continue;
334
335 #ifndef md_cgen_record_fixup_exp
336 #define md_cgen_record_fixup_exp cgen_record_fixup_exp
337 #endif
338
339       md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
340                                 insn, length,
341                                 & CGEN_SYM (operand_table) [fixups[i].opindex],
342                                 fixups[i].opinfo,
343                                 &fixups[i].exp);
344     }
345 }
346
347 /* Apply a fixup to the object code.  This is called for all the
348    fixups we generated by the call to fix_new_exp, above.  In the call
349    above we used a reloc code which was the largest legal reloc code
350    plus the operand index.  Here we undo that to recover the operand
351    index.  At this point all symbol values should be fully resolved,
352    and we attempt to completely resolve the reloc.  If we can not do
353    that, we determine the correct reloc code and put it back in the fixup.  */
354
355 /* FIXME: This function handles some of the fixups and bfd_install_relocation
356    handles the rest.  bfd_install_relocation (or some other bfd function)
357    should handle them all.  */
358
359 int
360 cgen_md_apply_fix3 (fixP, valueP, seg)
361      fixS *fixP;
362      valueT *valueP;
363      segT seg;
364 {
365   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
366   valueT value;
367
368   /* FIXME FIXME FIXME: The value we are passed in *valuep includes
369      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
370      doing this relocation the code in write.c is going to call
371      bfd_install_relocation, which is also going to use the symbol
372      value.  That means that if the reloc is fully resolved we want to
373      use *valuep since bfd_install_relocation is not being used.
374      However, if the reloc is not fully resolved we do not want to use
375      *valuep, and must use fx_offset instead.  However, if the reloc
376      is PC relative, we do want to use *valuep since it includes the
377      result of md_pcrel_from.  This is confusing.  */
378
379   if (fixP->fx_addsy == (symbolS *) NULL)
380     {
381       value = *valueP;
382       fixP->fx_done = 1;
383     }
384   else if (fixP->fx_pcrel)
385     value = *valueP;
386   else
387     {
388       value = fixP->fx_offset;
389       if (fixP->fx_subsy != (symbolS *) NULL)
390         {
391           if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
392             value -= S_GET_VALUE (fixP->fx_subsy);
393           else
394             {
395               /* We don't actually support subtracting a symbol.  */
396               as_bad_where (fixP->fx_file, fixP->fx_line,
397                             "expression too complex");
398             }
399         }
400     }
401
402   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
403     {
404       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
405       const struct cgen_operand *operand = & CGEN_SYM (operand_table) [opindex];
406       const char *errmsg;
407       bfd_reloc_code_real_type reloc_type;
408       struct cgen_fields fields;
409       const struct cgen_insn *insn = (struct cgen_insn *) fixP->tc_fix_data.insn;
410
411       /* If the reloc has been fully resolved finish the operand here.  */
412       /* FIXME: This duplicates the capabilities of code in BFD.  */
413       if (fixP->fx_done
414           /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
415              finish the job.  Testing for pcrel is a temporary hack.  */
416           || fixP->fx_pcrel)
417         {
418           /* This may seem like overkill, and using bfd_install_relocation or
419              some such may be preferable, but this is simple.  */
420           CGEN_FIELDS_BITSIZE (&fields) = CGEN_INSN_BITSIZE (insn);
421           CGEN_SYM (set_operand) (opindex, &value, &fields);
422           errmsg = CGEN_SYM (validate_operand) (opindex, &fields);
423           if (errmsg)
424             as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg);
425           CGEN_SYM (insert_operand) (opindex, &fields, where);
426         }
427
428       if (fixP->fx_done)
429         return 1;
430
431       /* The operand isn't fully resolved.  Determine a BFD reloc value
432          based on the operand information and leave it to
433          bfd_install_relocation.  Note that this doesn't work when
434          partial_inplace == false.  */
435
436       reloc_type = CGEN_SYM (lookup_reloc) (insn, operand, fixP);
437       if (reloc_type != BFD_RELOC_NONE)
438         {
439           fixP->fx_r_type = reloc_type;
440         }
441       else
442         {
443           as_bad_where (fixP->fx_file, fixP->fx_line,
444                         "unresolved expression that must be resolved");
445           fixP->fx_done = 1;
446           return 1;
447         }
448     }
449   else if (fixP->fx_done)
450     {
451       /* We're finished with this fixup.  Install it because
452          bfd_install_relocation won't be called to do it.  */
453       switch (fixP->fx_r_type)
454         {
455         case BFD_RELOC_8:
456           md_number_to_chars (where, value, 1);
457           break;
458         case BFD_RELOC_16:
459           md_number_to_chars (where, value, 2);
460           break;
461         case BFD_RELOC_32:
462           md_number_to_chars (where, value, 4);
463           break;
464         /* FIXME: later add support for 64 bits.  */
465         default:
466           abort ();
467         }
468     }
469   else
470     {
471       /* bfd_install_relocation will be called to finish things up.  */
472     }
473
474   /* Tuck `value' away for use by tc_gen_reloc.
475      See the comment describing fx_addnumber in write.h.
476      This field is misnamed (or misused :-).  */
477   fixP->fx_addnumber = value;
478
479   return 1;
480 }
481
482 /* Translate internal representation of relocation info to BFD target format.
483
484    FIXME: To what extent can we get all relevant targets to use this?  */
485
486 arelent *
487 cgen_tc_gen_reloc (section, fixP)
488      asection *section;
489      fixS *fixP;
490 {
491   arelent *reloc;
492
493   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
494
495   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
496   if (reloc->howto == (reloc_howto_type *) NULL)
497     {
498       as_bad_where (fixP->fx_file, fixP->fx_line,
499                     "internal error: can't export reloc type %d (`%s')",
500                     fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
501       return NULL;
502     }
503
504   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
505
506   reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
507   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
508   reloc->addend = fixP->fx_addnumber;
509
510   return reloc;
511 }