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