133965Sjdp/* GAS interface for targets using CGEN: Cpu tools GENerator.
2218822Sdim   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3218822Sdim   2006 Free Software Foundation, Inc.
433965Sjdp
5130561Sobrien   This file is part of GAS, the GNU Assembler.
633965Sjdp
7130561Sobrien   GAS is free software; you can redistribute it and/or modify
8130561Sobrien   it under the terms of the GNU General Public License as published by
9130561Sobrien   the Free Software Foundation; either version 2, or (at your option)
10130561Sobrien   any later version.
1133965Sjdp
12130561Sobrien   GAS is distributed in the hope that it will be useful,
13130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130561Sobrien   GNU General Public License for more details.
1633965Sjdp
17130561Sobrien   You should have received a copy of the GNU General Public License
18130561Sobrien   along with GAS; see the file COPYING.  If not, write to the Free Software
19218822Sdim   Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2033965Sjdp
2138889Sjdp#include <setjmp.h>
22218822Sdim#include "as.h"
2338889Sjdp#include "symcat.h"
2460484Sobrien#include "cgen-desc.h"
2533965Sjdp#include "subsegs.h"
2660484Sobrien#include "cgen.h"
2785815Sobrien#include "dwarf2dbg.h"
2833965Sjdp
29218822Sdim#include "symbols.h"
30218822Sdim#include "struc-symbol.h"
31218822Sdim
32218822Sdim#ifdef OBJ_COMPLEX_RELC
33218822Sdimstatic expressionS * make_right_shifted_expr
34218822Sdim  (expressionS *, const int, const int);
35218822Sdim
36218822Sdimstatic unsigned long gas_cgen_encode_addend
37218822Sdim  (const unsigned long, const unsigned long, const unsigned long, \
38218822Sdim   const unsigned long, const unsigned long, const unsigned long, \
39218822Sdim   const unsigned long);
40218822Sdim
41218822Sdimstatic char * weak_operand_overflow_check
42218822Sdim  (const expressionS *, const CGEN_OPERAND *);
43218822Sdim
44218822Sdimstatic void queue_fixup_recursively
45218822Sdim  (const int, const int, expressionS *, \
46218822Sdim   const CGEN_MAYBE_MULTI_IFLD *, const int, const int);
47218822Sdim
48218822Sdimstatic int rightshift = 0;
49218822Sdim#endif
50130561Sobrienstatic void queue_fixup (int, int, expressionS *);
5189857Sobrien
5260484Sobrien/* Opcode table descriptor, must be set by md_begin.  */
5360484Sobrien
5460484SobrienCGEN_CPU_DESC gas_cgen_cpu_desc;
5560484Sobrien
5633965Sjdp/* Callback to insert a register into the symbol table.
5733965Sjdp   A target may choose to let GAS parse the registers.
5833965Sjdp   ??? Not currently used.  */
5933965Sjdp
6033965Sjdpvoid
6133965Sjdpcgen_asm_record_register (name, number)
6285815Sobrien     char *name;
6360484Sobrien     int number;
6433965Sjdp{
6533965Sjdp  /* Use symbol_create here instead of symbol_new so we don't try to
6633965Sjdp     output registers into the object file's symbol table.  */
6733965Sjdp  symbol_table_insert (symbol_create (name, reg_section,
6885815Sobrien				      number, &zero_address_frag));
6933965Sjdp}
7033965Sjdp
7133965Sjdp/* We need to keep a list of fixups.  We can't simply generate them as
7233965Sjdp   we go, because that would require us to first create the frag, and
7333965Sjdp   that would screw up references to ``.''.
7433965Sjdp
7533965Sjdp   This is used by cpu's with simple operands.  It keeps knowledge of what
7633965Sjdp   an `expressionS' is and what a `fixup' is out of CGEN which for the time
7733965Sjdp   being is preferable.
7833965Sjdp
7933965Sjdp   OPINDEX is the index in the operand table.
8033965Sjdp   OPINFO is something the caller chooses to help in reloc determination.  */
8133965Sjdp
82130561Sobrienstruct fixup
83130561Sobrien{
8460484Sobrien  int opindex;
8560484Sobrien  int opinfo;
8633965Sjdp  expressionS exp;
87218822Sdim  struct cgen_maybe_multi_ifield * field;
88218822Sdim  int msb_field_p;
8933965Sjdp};
9033965Sjdp
9185815Sobrienstatic struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
9260484Sobrienstatic int num_fixups;
9333965Sjdp
9433965Sjdp/* Prepare to parse an instruction.
9533965Sjdp   ??? May wish to make this static and delete calls in md_assemble.  */
9633965Sjdp
9733965Sjdpvoid
9860484Sobriengas_cgen_init_parse ()
9933965Sjdp{
10033965Sjdp  num_fixups = 0;
10133965Sjdp}
10233965Sjdp
10333965Sjdp/* Queue a fixup.  */
10433965Sjdp
10538889Sjdpstatic void
10660484Sobrienqueue_fixup (opindex, opinfo, expP)
10738889Sjdp     int           opindex;
10885815Sobrien     int           opinfo;
10938889Sjdp     expressionS * expP;
11033965Sjdp{
11133965Sjdp  /* We need to generate a fixup for this expression.  */
11260484Sobrien  if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
11360484Sobrien    as_fatal (_("too many fixups"));
11485815Sobrien  fixups[num_fixups].exp     = *expP;
11533965Sjdp  fixups[num_fixups].opindex = opindex;
11638889Sjdp  fixups[num_fixups].opinfo  = opinfo;
11738889Sjdp  ++ num_fixups;
11833965Sjdp}
11933965Sjdp
12089857Sobrien/* The following functions allow fixup chains to be stored, retrieved,
12189857Sobrien   and swapped.  They are a generalization of a pre-existing scheme
12289857Sobrien   for storing, restoring and swapping fixup chains that was used by
12389857Sobrien   the m32r port.  The functionality is essentially the same, only
12489857Sobrien   instead of only being able to store a single fixup chain, an entire
12589857Sobrien   array of fixup chains can be stored.  It is the user's responsibility
12689857Sobrien   to keep track of how many fixup chains have been stored and which
12789857Sobrien   elements of the array they are in.
12838889Sjdp
129104834Sobrien   The algorithms used are the same as in the old scheme.  Other than the
130104834Sobrien   "array-ness" of the whole thing, the functionality is identical to the
13189857Sobrien   old scheme.
13260484Sobrien
13389857Sobrien   gas_cgen_initialize_saved_fixups_array():
13489857Sobrien      Sets num_fixups_in_chain to 0 for each element. Call this from
13589857Sobrien      md_begin() if you plan to use these functions and you want the
136130561Sobrien      fixup count in each element to be set to 0 initially.  This is
13789857Sobrien      not necessary, but it's included just in case.  It performs
13889857Sobrien      the same function for each element in the array of fixup chains
13989857Sobrien      that gas_init_parse() performs for the current fixups.
14089857Sobrien
14189857Sobrien   gas_cgen_save_fixups (element):
14289857Sobrien      element - element number of the array you wish to store the fixups
14389857Sobrien                to.  No mechanism is built in for tracking what element
14489857Sobrien                was last stored to.
14589857Sobrien
14689857Sobrien   gas_cgen_restore_fixups (element):
14789857Sobrien      element - element number of the array you wish to restore the fixups
14889857Sobrien                from.
14989857Sobrien
15089857Sobrien   gas_cgen_swap_fixups(int element):
15189857Sobrien       element - swap the current fixups with those in this element number.
15289857Sobrien*/
15389857Sobrien
154130561Sobrienstruct saved_fixups
155130561Sobrien{
15689857Sobrien  struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
15789857Sobrien  int num_fixups_in_chain;
15889857Sobrien};
15989857Sobrien
16089857Sobrienstatic struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
16189857Sobrien
16238889Sjdpvoid
16389857Sobriengas_cgen_initialize_saved_fixups_array ()
16438889Sjdp{
16589857Sobrien  int i = 0;
16685815Sobrien
16789857Sobrien  while (i < MAX_SAVED_FIXUP_CHAINS)
16889857Sobrien    stored_fixups[i++].num_fixups_in_chain = 0;
16989857Sobrien}
17038889Sjdp
17189857Sobrienvoid
17289857Sobriengas_cgen_save_fixups (i)
17389857Sobrien     int i;
17489857Sobrien{
17589857Sobrien  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
17689857Sobrien    {
17789857Sobrien      as_fatal ("index into stored_fixups[] out of bounds");
17889857Sobrien      return;
17989857Sobrien    }
18089857Sobrien
18189857Sobrien  stored_fixups[i].num_fixups_in_chain = num_fixups;
18289857Sobrien  memcpy (stored_fixups[i].fixup_chain, fixups,
18389857Sobrien	  sizeof (fixups[0]) * num_fixups);
18438889Sjdp  num_fixups = 0;
18538889Sjdp}
18638889Sjdp
18738889Sjdpvoid
18889857Sobriengas_cgen_restore_fixups (i)
18989857Sobrien     int i;
19038889Sjdp{
19189857Sobrien  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
19289857Sobrien    {
19389857Sobrien      as_fatal ("index into stored_fixups[] out of bounds");
19489857Sobrien      return;
19589857Sobrien    }
19685815Sobrien
19789857Sobrien  num_fixups = stored_fixups[i].num_fixups_in_chain;
198104834Sobrien  memcpy (fixups, stored_fixups[i].fixup_chain,
19989857Sobrien	  (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
20089857Sobrien  stored_fixups[i].num_fixups_in_chain = 0;
20138889Sjdp}
20238889Sjdp
20338889Sjdpvoid
20489857Sobriengas_cgen_swap_fixups (i)
20589857Sobrien     int i;
20638889Sjdp{
20789857Sobrien  if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
20889857Sobrien    {
20989857Sobrien      as_fatal ("index into stored_fixups[] out of bounds");
21089857Sobrien      return;
21189857Sobrien    }
21238889Sjdp
21338889Sjdp  if (num_fixups == 0)
21489857Sobrien    gas_cgen_restore_fixups (i);
21589857Sobrien
21689857Sobrien  else if (stored_fixups[i].num_fixups_in_chain == 0)
21789857Sobrien    gas_cgen_save_fixups (i);
21889857Sobrien
21938889Sjdp  else
22038889Sjdp    {
22189857Sobrien      int tmp;
22289857Sobrien      struct fixup tmp_fixup;
22389857Sobrien
22489857Sobrien      tmp = stored_fixups[i].num_fixups_in_chain;
22589857Sobrien      stored_fixups[i].num_fixups_in_chain = num_fixups;
22638889Sjdp      num_fixups = tmp;
22785815Sobrien
22860484Sobrien      for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
22938889Sjdp	{
23089857Sobrien	  tmp_fixup = stored_fixups[i].fixup_chain [tmp];
23189857Sobrien	  stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
23289857Sobrien	  fixups [tmp] = tmp_fixup;
23338889Sjdp	}
23438889Sjdp    }
23538889Sjdp}
23638889Sjdp
23733965Sjdp/* Default routine to record a fixup.
23833965Sjdp   This is a cover function to fix_new.
23933965Sjdp   It exists because we record INSN with the fixup.
24033965Sjdp
24133965Sjdp   FRAG and WHERE are their respective arguments to fix_new_exp.
24233965Sjdp   LENGTH is in bits.
24333965Sjdp   OPINFO is something the caller chooses to help in reloc determination.
24433965Sjdp
24533965Sjdp   At this point we do not use a bfd_reloc_code_real_type for
24633965Sjdp   operands residing in the insn, but instead just use the
24733965Sjdp   operand index.  This lets us easily handle fixups for any
248218822Sdim   operand type.  We pick a BFD reloc type in md_apply_fix.  */
24933965Sjdp
25033965SjdpfixS *
25160484Sobriengas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
25238889Sjdp     fragS *              frag;
25338889Sjdp     int                  where;
25438889Sjdp     const CGEN_INSN *    insn;
25538889Sjdp     int                  length;
25638889Sjdp     const CGEN_OPERAND * operand;
25738889Sjdp     int                  opinfo;
25838889Sjdp     symbolS *            symbol;
25938889Sjdp     offsetT              offset;
26033965Sjdp{
26185815Sobrien  fixS *fixP;
26233965Sjdp
26333965Sjdp  /* It may seem strange to use operand->attrs and not insn->attrs here,
26433965Sjdp     but it is the operand that has a pc relative relocation.  */
26533965Sjdp  fixP = fix_new (frag, where, length / 8, symbol, offset,
26660484Sobrien		  CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
26760484Sobrien		  (bfd_reloc_code_real_type)
26860484Sobrien		    ((int) BFD_RELOC_UNUSED
26960484Sobrien		     + (int) operand->type));
27060484Sobrien  fixP->fx_cgen.insn = insn;
27160484Sobrien  fixP->fx_cgen.opinfo = opinfo;
272218822Sdim  fixP->fx_cgen.field = NULL;
273218822Sdim  fixP->fx_cgen.msb_field_p = 0;
27433965Sjdp
27533965Sjdp  return fixP;
27633965Sjdp}
27733965Sjdp
27833965Sjdp/* Default routine to record a fixup given an expression.
27933965Sjdp   This is a cover function to fix_new_exp.
28033965Sjdp   It exists because we record INSN with the fixup.
28133965Sjdp
28233965Sjdp   FRAG and WHERE are their respective arguments to fix_new_exp.
28333965Sjdp   LENGTH is in bits.
28433965Sjdp   OPINFO is something the caller chooses to help in reloc determination.
28533965Sjdp
28633965Sjdp   At this point we do not use a bfd_reloc_code_real_type for
28733965Sjdp   operands residing in the insn, but instead just use the
28833965Sjdp   operand index.  This lets us easily handle fixups for any
289218822Sdim   operand type.  We pick a BFD reloc type in md_apply_fix.  */
29033965Sjdp
29133965SjdpfixS *
29260484Sobriengas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
29338889Sjdp     fragS *              frag;
29438889Sjdp     int                  where;
29538889Sjdp     const CGEN_INSN *    insn;
29638889Sjdp     int                  length;
29738889Sjdp     const CGEN_OPERAND * operand;
29838889Sjdp     int                  opinfo;
29938889Sjdp     expressionS *        exp;
30033965Sjdp{
30185815Sobrien  fixS *fixP;
30233965Sjdp
30333965Sjdp  /* It may seem strange to use operand->attrs and not insn->attrs here,
30433965Sjdp     but it is the operand that has a pc relative relocation.  */
30533965Sjdp  fixP = fix_new_exp (frag, where, length / 8, exp,
30660484Sobrien		      CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
30760484Sobrien		      (bfd_reloc_code_real_type)
30860484Sobrien		        ((int) BFD_RELOC_UNUSED
30960484Sobrien			 + (int) operand->type));
31060484Sobrien  fixP->fx_cgen.insn = insn;
31160484Sobrien  fixP->fx_cgen.opinfo = opinfo;
312218822Sdim  fixP->fx_cgen.field = NULL;
313218822Sdim  fixP->fx_cgen.msb_field_p = 0;
31433965Sjdp
31533965Sjdp  return fixP;
31633965Sjdp}
31733965Sjdp
318218822Sdim#ifdef OBJ_COMPLEX_RELC
319218822Sdimstatic symbolS *
320218822Sdimexpr_build_binary (operatorT op, symbolS * s1, symbolS * s2)
321218822Sdim{
322218822Sdim  expressionS e;
323218822Sdim
324218822Sdim  e.X_op = op;
325218822Sdim  e.X_add_symbol = s1;
326218822Sdim  e.X_op_symbol = s2;
327218822Sdim  e.X_add_number = 0;
328218822Sdim  return make_expr_symbol (& e);
329218822Sdim}
330218822Sdim#endif
331218822Sdim
33238889Sjdp/* Used for communication between the next two procedures.  */
33338889Sjdpstatic jmp_buf expr_jmp_buf;
33485815Sobrienstatic int expr_jmp_buf_p;
33538889Sjdp
33633965Sjdp/* Callback for cgen interface.  Parse the expression at *STRP.
33733965Sjdp   The result is an error message or NULL for success (in which case
33833965Sjdp   *STRP is advanced past the parsed text).
33933965Sjdp   WANT is an indication of what the caller is looking for.
34033965Sjdp   If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
34133965Sjdp   a table entry with the insn, reset the queued fixups counter.
34233965Sjdp   An enum cgen_parse_operand_result is stored in RESULTP.
34333965Sjdp   OPINDEX is the operand's table entry index.
34433965Sjdp   OPINFO is something the caller chooses to help in reloc determination.
34533965Sjdp   The resulting value is stored in VALUEP.  */
34633965Sjdp
34733965Sjdpconst char *
34860484Sobriengas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
349218822Sdim
350218822Sdim#ifdef OBJ_COMPLEX_RELC
351218822Sdim     CGEN_CPU_DESC cd;
352218822Sdim#else
35385815Sobrien     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
354218822Sdim#endif
35560484Sobrien     enum cgen_parse_operand_type want;
35685815Sobrien     const char **strP;
35760484Sobrien     int opindex;
35860484Sobrien     int opinfo;
35985815Sobrien     enum cgen_parse_operand_result *resultP;
36085815Sobrien     bfd_vma *valueP;
36133965Sjdp{
36238889Sjdp#ifdef __STDC__
36360484Sobrien  /* These are volatile to survive the setjmp.  */
36460484Sobrien  char * volatile hold;
36538889Sjdp  enum cgen_parse_operand_result * volatile resultP_1;
366218822Sdim  volatile int opinfo_1;
36738889Sjdp#else
36885815Sobrien  static char *hold;
36985815Sobrien  static enum cgen_parse_operand_result *resultP_1;
370218822Sdim  int opinfo_1;
37138889Sjdp#endif
37289857Sobrien  const char *errmsg;
37360484Sobrien  expressionS exp;
37433965Sjdp
375218822Sdim#ifdef OBJ_COMPLEX_RELC
376218822Sdim  volatile int              signed_p = 0;
377218822Sdim  symbolS *                 stmp = NULL;
378218822Sdim  bfd_reloc_code_real_type  reloc_type;
379218822Sdim  const CGEN_OPERAND *      operand;
380218822Sdim  fixS                      dummy_fixup;
381218822Sdim#endif
38233965Sjdp  if (want == CGEN_PARSE_OPERAND_INIT)
38333965Sjdp    {
38460484Sobrien      gas_cgen_init_parse ();
38533965Sjdp      return NULL;
38633965Sjdp    }
38733965Sjdp
38838889Sjdp  resultP_1 = resultP;
38933965Sjdp  hold = input_line_pointer;
39085815Sobrien  input_line_pointer = (char *) *strP;
391218822Sdim  opinfo_1 = opinfo;
39238889Sjdp
39338889Sjdp  /* We rely on md_operand to longjmp back to us.
39460484Sobrien     This is done via gas_cgen_md_operand.  */
39538889Sjdp  if (setjmp (expr_jmp_buf) != 0)
39638889Sjdp    {
39785815Sobrien      expr_jmp_buf_p = 0;
39838889Sjdp      input_line_pointer = (char *) hold;
39985815Sobrien      *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
40089857Sobrien      return _("illegal operand");
40138889Sjdp    }
40238889Sjdp
40385815Sobrien  expr_jmp_buf_p = 1;
40485815Sobrien  expression (&exp);
40585815Sobrien  expr_jmp_buf_p = 0;
40689857Sobrien  errmsg = NULL;
40738889Sjdp
40885815Sobrien  *strP = input_line_pointer;
40933965Sjdp  input_line_pointer = hold;
41033965Sjdp
411218822Sdim#ifdef TC_CGEN_PARSE_FIX_EXP
412218822Sdim  opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
413218822Sdim#endif
414218822Sdim
41533965Sjdp  /* FIXME: Need to check `want'.  */
41633965Sjdp
41733965Sjdp  switch (exp.X_op)
41833965Sjdp    {
41985815Sobrien    case O_illegal:
42060484Sobrien      errmsg = _("illegal operand");
42185815Sobrien      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
42233965Sjdp      break;
42385815Sobrien    case O_absent:
42460484Sobrien      errmsg = _("missing operand");
42585815Sobrien      *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
42633965Sjdp      break;
42785815Sobrien    case O_constant:
428218822Sdim      if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
429218822Sdim	goto de_fault;
43085815Sobrien      *valueP = exp.X_add_number;
43185815Sobrien      *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
43233965Sjdp      break;
43385815Sobrien    case O_register:
43485815Sobrien      *valueP = exp.X_add_number;
43585815Sobrien      *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
43633965Sjdp      break;
437218822Sdim    de_fault:
43885815Sobrien    default:
439218822Sdim#ifdef OBJ_COMPLEX_RELC
440218822Sdim      /* Look up operand, check to see if there's an obvious
441218822Sdim	 overflow (this helps disambiguate some insn parses).  */
442218822Sdim      operand = cgen_operand_lookup_by_num (cd, opindex);
443218822Sdim      errmsg = weak_operand_overflow_check (& exp, operand);
444218822Sdim
445218822Sdim      if (! errmsg)
446218822Sdim	{
447218822Sdim	  /* Fragment the expression as necessary, and queue a reloc.  */
448218822Sdim	  memset (& dummy_fixup, 0, sizeof (fixS));
449218822Sdim
450218822Sdim	  reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);
451218822Sdim
452218822Sdim	  if (exp.X_op == O_symbol
453218822Sdim	      && reloc_type == BFD_RELOC_RELC
454218822Sdim	      && exp.X_add_symbol->sy_value.X_op == O_constant
455218822Sdim	      && exp.X_add_symbol->bsym->section != expr_section
456218822Sdim	      && exp.X_add_symbol->bsym->section != absolute_section
457218822Sdim	      && exp.X_add_symbol->bsym->section != undefined_section)
458218822Sdim	    {
459218822Sdim	      /* Local labels will have been (eagerly) turned into constants
460218822Sdim		 by now, due to the inappropriately deep insight of the
461218822Sdim		 expression parser.  Unfortunately make_expr_symbol
462218822Sdim		 prematurely dives into the symbol evaluator, and in this
463218822Sdim		 case it gets a bad answer, so we manually create the
464218822Sdim		 expression symbol we want here.  */
465218822Sdim	      stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
466218822Sdim				    & zero_address_frag);
467218822Sdim	      symbol_set_value_expression (stmp, & exp);
468218822Sdim	    }
469218822Sdim	  else
470218822Sdim	    stmp = make_expr_symbol (& exp);
471218822Sdim
472218822Sdim	  /* If this is a pc-relative RELC operand, we
473218822Sdim	     need to subtract "." from the expression.  */
474218822Sdim 	  if (reloc_type == BFD_RELOC_RELC
475218822Sdim	      && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
476218822Sdim 	    stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ());
477218822Sdim
478218822Sdim	  /* FIXME: this is not a perfect heuristic for figuring out
479218822Sdim	     whether an operand is signed: it only works when the operand
480218822Sdim	     is an immediate. it's not terribly likely that any other
481218822Sdim	     values will be signed relocs, but it's possible. */
482218822Sdim	  if (operand && (operand->hw_type == HW_H_SINT))
483218822Sdim	    signed_p = 1;
484218822Sdim
485218822Sdim	  if (stmp->bsym && (stmp->bsym->section == expr_section))
486218822Sdim	    {
487218822Sdim	      if (signed_p)
488218822Sdim		stmp->bsym->flags |= BSF_SRELC;
489218822Sdim	      else
490218822Sdim		stmp->bsym->flags |= BSF_RELC;
491218822Sdim	    }
492218822Sdim
493218822Sdim	  /* Now package it all up for the fixup emitter.  */
494218822Sdim	  exp.X_op = O_symbol;
495218822Sdim	  exp.X_op_symbol = 0;
496218822Sdim	  exp.X_add_symbol = stmp;
497218822Sdim	  exp.X_add_number = 0;
498218822Sdim
499218822Sdim	  /* Re-init rightshift quantity, just in case.  */
500218822Sdim	  rightshift = operand->length;
501218822Sdim	  queue_fixup_recursively (opindex, opinfo_1, & exp,
502218822Sdim				   (reloc_type == BFD_RELOC_RELC) ?
503218822Sdim				   & (operand->index_fields) : 0,
504218822Sdim				   signed_p, -1);
505218822Sdim	}
506218822Sdim      * resultP = errmsg
507218822Sdim	? CGEN_PARSE_OPERAND_RESULT_ERROR
508218822Sdim	: CGEN_PARSE_OPERAND_RESULT_QUEUED;
50985815Sobrien      *valueP = 0;
510218822Sdim#else
511218822Sdim      queue_fixup (opindex, opinfo_1, &exp);
512218822Sdim      *valueP = 0;
51385815Sobrien      *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
514218822Sdim#endif
51533965Sjdp      break;
51633965Sjdp    }
51733965Sjdp
51833965Sjdp  return errmsg;
51933965Sjdp}
52033965Sjdp
52138889Sjdp/* md_operand handler to catch unrecognized expressions and halt the
52238889Sjdp   parsing process so the next entry can be tried.
52338889Sjdp
52438889Sjdp   ??? This could be done differently by adding code to `expression'.  */
52538889Sjdp
52638889Sjdpvoid
52760484Sobriengas_cgen_md_operand (expressionP)
52885815Sobrien     expressionS *expressionP ATTRIBUTE_UNUSED;
52938889Sjdp{
53085815Sobrien  /* Don't longjmp if we're not called from within cgen_parse_operand().  */
53185815Sobrien  if (expr_jmp_buf_p)
53285815Sobrien    longjmp (expr_jmp_buf, 1);
53338889Sjdp}
53438889Sjdp
53533965Sjdp/* Finish assembling instruction INSN.
53633965Sjdp   BUF contains what we've built up so far.
53738889Sjdp   LENGTH is the size of the insn in bits.
53860484Sobrien   RELAX_P is non-zero if relaxable insns should be emitted as such.
53960484Sobrien   Otherwise they're emitted in non-relaxable forms.
54060484Sobrien   The "result" is stored in RESULT if non-NULL.  */
54133965Sjdp
54260484Sobrienvoid
54360484Sobriengas_cgen_finish_insn (insn, buf, length, relax_p, result)
54485815Sobrien     const CGEN_INSN *insn;
54560484Sobrien     CGEN_INSN_BYTES_PTR buf;
54660484Sobrien     unsigned int length;
54760484Sobrien     int relax_p;
54885815Sobrien     finished_insnS *result;
54933965Sjdp{
55060484Sobrien  int i;
55160484Sobrien  int relax_operand;
55285815Sobrien  char *f;
55333965Sjdp  unsigned int byte_len = length / 8;
55433965Sjdp
55533965Sjdp  /* ??? Target foo issues various warnings here, so one might want to provide
55633965Sjdp     a hook here.  However, our caller is defined in tc-foo.c so there
55733965Sjdp     shouldn't be a need for a hook.  */
55860484Sobrien
55933965Sjdp  /* Write out the instruction.
56033965Sjdp     It is important to fetch enough space in one call to `frag_more'.
56133965Sjdp     We use (f - frag_now->fr_literal) to compute where we are and we
56233965Sjdp     don't want frag_now to change between calls.
56333965Sjdp
56433965Sjdp     Relaxable instructions: We need to ensure we allocate enough
56533965Sjdp     space for the largest insn.  */
56633965Sjdp
567130561Sobrien  if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
56885815Sobrien    /* These currently shouldn't get here.  */
56985815Sobrien    abort ();
57033965Sjdp
57133965Sjdp  /* Is there a relaxable insn with the relaxable operand needing a fixup?  */
57233965Sjdp
57333965Sjdp  relax_operand = -1;
57460484Sobrien  if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
57533965Sjdp    {
57633965Sjdp      /* Scan the fixups for the operand affected by relaxing
57733965Sjdp	 (i.e. the branch address).  */
57833965Sjdp
57985815Sobrien      for (i = 0; i < num_fixups; ++i)
58033965Sjdp	{
58160484Sobrien	  if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
58260484Sobrien				       CGEN_OPERAND_RELAX))
58333965Sjdp	    {
58433965Sjdp	      relax_operand = i;
58533965Sjdp	      break;
58633965Sjdp	    }
58733965Sjdp	}
58833965Sjdp    }
58933965Sjdp
59033965Sjdp  if (relax_operand != -1)
59133965Sjdp    {
59260484Sobrien      int max_len;
59385815Sobrien      fragS *old_frag;
59485815Sobrien      expressionS *exp;
59585815Sobrien      symbolS *sym;
59685815Sobrien      offsetT off;
59733965Sjdp
59833965Sjdp#ifdef TC_CGEN_MAX_RELAX
59933965Sjdp      max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
60033965Sjdp#else
60133965Sjdp      max_len = CGEN_MAX_INSN_SIZE;
60233965Sjdp#endif
60333965Sjdp      /* Ensure variable part and fixed part are in same fragment.  */
60433965Sjdp      /* FIXME: Having to do this seems like a hack.  */
60533965Sjdp      frag_grow (max_len);
60660484Sobrien
60733965Sjdp      /* Allocate space for the fixed part.  */
60833965Sjdp      f = frag_more (byte_len);
60960484Sobrien
61033965Sjdp      /* Create a relaxable fragment for this instruction.  */
61133965Sjdp      old_frag = frag_now;
61238889Sjdp
61385815Sobrien      exp = &fixups[relax_operand].exp;
61485815Sobrien      sym = exp->X_add_symbol;
61585815Sobrien      off = exp->X_add_number;
61685815Sobrien      if (exp->X_op != O_constant && exp->X_op != O_symbol)
61785815Sobrien	{
61885815Sobrien	  /* Handle complex expressions.  */
61985815Sobrien	  sym = make_expr_symbol (exp);
62085815Sobrien	  off = 0;
62185815Sobrien	}
62285815Sobrien
62333965Sjdp      frag_var (rs_machine_dependent,
62433965Sjdp		max_len - byte_len /* max chars */,
62533965Sjdp		0 /* variable part already allocated */,
62633965Sjdp		/* FIXME: When we machine generate the relax table,
62733965Sjdp		   machine generate a macro to compute subtype.  */
62833965Sjdp		1 /* subtype */,
62985815Sobrien		sym,
63085815Sobrien		off,
63133965Sjdp		f);
63260484Sobrien
63333965Sjdp      /* Record the operand number with the fragment so md_convert_frag
63460484Sobrien	 can use gas_cgen_md_record_fixup to record the appropriate reloc.  */
63538889Sjdp      old_frag->fr_cgen.insn    = insn;
63638889Sjdp      old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
63738889Sjdp      old_frag->fr_cgen.opinfo  = fixups[relax_operand].opinfo;
63860484Sobrien      if (result)
63960484Sobrien	result->frag = old_frag;
64033965Sjdp    }
64133965Sjdp  else
64260484Sobrien    {
64360484Sobrien      f = frag_more (byte_len);
64460484Sobrien      if (result)
64560484Sobrien	result->frag = frag_now;
64660484Sobrien    }
64733965Sjdp
64833965Sjdp  /* If we're recording insns as numbers (rather than a string of bytes),
64933965Sjdp     target byte order handling is deferred until now.  */
65060484Sobrien#if CGEN_INT_INSN_P
651218822Sdim  cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
65233965Sjdp#else
65333965Sjdp  memcpy (f, buf, byte_len);
65433965Sjdp#endif
65533965Sjdp
65685815Sobrien  /* Emit DWARF2 debugging information.  */
65785815Sobrien  dwarf2_emit_insn (byte_len);
65885815Sobrien
65933965Sjdp  /* Create any fixups.  */
66033965Sjdp  for (i = 0; i < num_fixups; ++i)
66133965Sjdp    {
66260484Sobrien      fixS *fixP;
66360484Sobrien      const CGEN_OPERAND *operand =
66460484Sobrien	cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);
66560484Sobrien
66633965Sjdp      /* Don't create fixups for these.  That's done during relaxation.
667130561Sobrien	 We don't need to test for CGEN_INSN_RELAXED as they can't get here
66833965Sjdp	 (see above).  */
66960484Sobrien      if (relax_p
67060484Sobrien	  && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
67160484Sobrien	  && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
67233965Sjdp	continue;
67333965Sjdp
67433965Sjdp#ifndef md_cgen_record_fixup_exp
67560484Sobrien#define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
67633965Sjdp#endif
67733965Sjdp
67885815Sobrien      fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
67985815Sobrien				       insn, length, operand,
68085815Sobrien				       fixups[i].opinfo,
68185815Sobrien				       &fixups[i].exp);
682218822Sdim      fixP->fx_cgen.field = fixups[i].field;
683218822Sdim      fixP->fx_cgen.msb_field_p = fixups[i].msb_field_p;
68485815Sobrien      if (result)
68585815Sobrien	result->fixups[i] = fixP;
68633965Sjdp    }
68738889Sjdp
68860484Sobrien  if (result)
68960484Sobrien    {
69060484Sobrien      result->num_fixups = num_fixups;
69160484Sobrien      result->addr = f;
69260484Sobrien    }
69333965Sjdp}
69433965Sjdp
695218822Sdim#ifdef OBJ_COMPLEX_RELC
696218822Sdim/* Queue many fixups, recursively. If the field is a multi-ifield,
697218822Sdim   repeatedly queue its sub-parts, right shifted to fit into the field (we
698218822Sdim   assume here multi-fields represent a left-to-right, MSB0-LSB0
699218822Sdim   reading). */
700218822Sdim
701218822Sdimstatic void
702218822Sdimqueue_fixup_recursively (const int                      opindex,
703218822Sdim			 const int                      opinfo,
704218822Sdim			 expressionS *                  expP,
705218822Sdim			 const CGEN_MAYBE_MULTI_IFLD *  field,
706218822Sdim			 const int                      signed_p,
707218822Sdim			 const int                      part_of_multi)
708218822Sdim{
709218822Sdim  if (field && field->count)
710218822Sdim    {
711218822Sdim      int i;
712218822Sdim
713218822Sdim      for (i = 0; i < field->count; ++ i)
714218822Sdim	queue_fixup_recursively (opindex, opinfo, expP,
715218822Sdim				 & (field->val.multi[i]), signed_p, i);
716218822Sdim    }
717218822Sdim  else
718218822Sdim    {
719218822Sdim      expressionS * new_exp = expP;
720218822Sdim
721218822Sdim#ifdef DEBUG
722218822Sdim      printf ("queueing fixup for field %s\n",
723218822Sdim	      (field ? field->val.leaf->name : "??"));
724218822Sdim      print_symbol_value (expP->X_add_symbol);
725218822Sdim#endif
726218822Sdim      if (field && part_of_multi != -1)
727218822Sdim	{
728218822Sdim	  rightshift -= field->val.leaf->length;
729218822Sdim
730218822Sdim	  /* Shift reloc value by number of bits remaining after this
731218822Sdim	     field.  */
732218822Sdim	  if (rightshift)
733218822Sdim	    new_exp = make_right_shifted_expr (expP, rightshift, signed_p);
734218822Sdim	}
735218822Sdim
736218822Sdim      /* Truncate reloc values to length, *after* leftmost one.  */
737218822Sdim      fixups[num_fixups].msb_field_p = (part_of_multi <= 0);
738218822Sdim      fixups[num_fixups].field = (CGEN_MAYBE_MULTI_IFLD *) field;
739218822Sdim
740218822Sdim      queue_fixup (opindex, opinfo, new_exp);
741218822Sdim    }
742218822Sdim}
743218822Sdim
744218822Sdim/* Encode the self-describing RELC reloc format's addend.  */
745218822Sdim
746218822Sdimstatic unsigned long
747218822Sdimgas_cgen_encode_addend (const unsigned long start,    /* in bits */
748218822Sdim			const unsigned long len,      /* in bits */
749218822Sdim			const unsigned long oplen,    /* in bits */
750218822Sdim			const unsigned long wordsz,   /* in bytes */
751218822Sdim			const unsigned long chunksz,  /* in bytes */
752218822Sdim			const unsigned long signed_p,
753218822Sdim			const unsigned long trunc_p)
754218822Sdim{
755218822Sdim  unsigned long res = 0L;
756218822Sdim
757218822Sdim  res |= start    & 0x3F;
758218822Sdim  res |= (oplen   & 0x3F) << 6;
759218822Sdim  res |= (len     & 0x3F) << 12;
760218822Sdim  res |= (wordsz  & 0xF)  << 18;
761218822Sdim  res |= (chunksz & 0xF)  << 22;
762218822Sdim  res |= (CGEN_INSN_LSB0_P ? 1 : 0) << 27;
763218822Sdim  res |= signed_p << 28;
764218822Sdim  res |= trunc_p << 29;
765218822Sdim
766218822Sdim  return res;
767218822Sdim}
768218822Sdim
769218822Sdim/* Purpose: make a weak check that the expression doesn't overflow the
770218822Sdim   operand it's to be inserted into.
771218822Sdim
772218822Sdim   Rationale: some insns used to use %operators to disambiguate during a
773218822Sdim   parse. when these %operators are translated to expressions by the macro
774218822Sdim   expander, the ambiguity returns. we attempt to disambiguate by field
775218822Sdim   size.
776218822Sdim
777218822Sdim   Method: check to see if the expression's top node is an O_and operator,
778218822Sdim   and the mask is larger than the operand length. This would be an
779218822Sdim   overflow, so signal it by returning an error string. Any other case is
780218822Sdim   ambiguous, so we assume it's OK and return NULL.  */
781218822Sdim
782218822Sdimstatic char *
783218822Sdimweak_operand_overflow_check (const expressionS *  exp,
784218822Sdim			     const CGEN_OPERAND * operand)
785218822Sdim{
786218822Sdim  const unsigned long len = operand->length;
787218822Sdim  unsigned long mask;
788218822Sdim  unsigned long opmask = (((1L << (len - 1)) - 1) << 1) | 1;
789218822Sdim
790218822Sdim  if (!exp)
791218822Sdim    return NULL;
792218822Sdim
793218822Sdim  if (exp->X_op != O_bit_and)
794218822Sdim    {
795218822Sdim      /* Check for implicit overflow flag.  */
796218822Sdim      if (CGEN_OPERAND_ATTR_VALUE
797218822Sdim	  (operand, CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW))
798218822Sdim	return _("a reloc on this operand implies an overflow");
799218822Sdim      return NULL;
800218822Sdim    }
801218822Sdim
802218822Sdim  mask = exp->X_add_number;
803218822Sdim
804218822Sdim  if (exp->X_add_symbol &&
805218822Sdim      exp->X_add_symbol->sy_value.X_op == O_constant)
806218822Sdim    mask |= exp->X_add_symbol->sy_value.X_add_number;
807218822Sdim
808218822Sdim  if (exp->X_op_symbol &&
809218822Sdim      exp->X_op_symbol->sy_value.X_op == O_constant)
810218822Sdim    mask |= exp->X_op_symbol->sy_value.X_add_number;
811218822Sdim
812218822Sdim  /* Want to know if mask covers more bits than opmask.
813218822Sdim     this is the same as asking if mask has any bits not in opmask,
814218822Sdim     or whether (mask & ~opmask) is nonzero.  */
815218822Sdim  if (mask && (mask & ~opmask))
816218822Sdim    {
817218822Sdim#ifdef DEBUG
818218822Sdim      printf ("overflow: (mask = %8.8x, ~opmask = %8.8x, AND = %8.8x)\n",
819218822Sdim	      mask, ~opmask, (mask & ~opmask));
820218822Sdim#endif
821218822Sdim      return _("operand mask overflow");
822218822Sdim    }
823218822Sdim
824218822Sdim  return NULL;
825218822Sdim}
826218822Sdim
827218822Sdim
828218822Sdimstatic expressionS *
829218822Sdimmake_right_shifted_expr (expressionS * exp,
830218822Sdim			 const int     amount,
831218822Sdim			 const int     signed_p)
832218822Sdim{
833218822Sdim  symbolS * stmp = 0;
834218822Sdim  expressionS * new_exp;
835218822Sdim
836218822Sdim  stmp = expr_build_binary (O_right_shift,
837218822Sdim			    make_expr_symbol (exp),
838218822Sdim			    expr_build_uconstant (amount));
839218822Sdim
840218822Sdim  if (signed_p)
841218822Sdim    stmp->bsym->flags |= BSF_SRELC;
842218822Sdim  else
843218822Sdim    stmp->bsym->flags |= BSF_RELC;
844218822Sdim
845218822Sdim  /* Then wrap that in a "symbol expr" for good measure.  */
846218822Sdim  new_exp = xmalloc (sizeof (expressionS));
847218822Sdim  memset (new_exp, 0, sizeof (expressionS));
848218822Sdim  new_exp->X_op = O_symbol;
849218822Sdim  new_exp->X_op_symbol = 0;
850218822Sdim  new_exp->X_add_symbol = stmp;
851218822Sdim  new_exp->X_add_number = 0;
852218822Sdim
853218822Sdim  return new_exp;
854218822Sdim}
855218822Sdim#endif
85633965Sjdp/* Apply a fixup to the object code.  This is called for all the
85733965Sjdp   fixups we generated by the call to fix_new_exp, above.  In the call
85833965Sjdp   above we used a reloc code which was the largest legal reloc code
85933965Sjdp   plus the operand index.  Here we undo that to recover the operand
86033965Sjdp   index.  At this point all symbol values should be fully resolved,
86133965Sjdp   and we attempt to completely resolve the reloc.  If we can not do
86233965Sjdp   that, we determine the correct reloc code and put it back in the fixup.  */
86333965Sjdp
86433965Sjdp/* FIXME: This function handles some of the fixups and bfd_install_relocation
86533965Sjdp   handles the rest.  bfd_install_relocation (or some other bfd function)
86633965Sjdp   should handle them all.  */
86733965Sjdp
86889857Sobrienvoid
869218822Sdimgas_cgen_md_apply_fix (fixP, valP, seg)
87038889Sjdp     fixS *   fixP;
87189857Sobrien     valueT * valP;
87285815Sobrien     segT     seg ATTRIBUTE_UNUSED;
87333965Sjdp{
87485815Sobrien  char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
87589857Sobrien  valueT value = * valP;
87685815Sobrien  /* Canonical name, since used a lot.  */
87760484Sobrien  CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
87885815Sobrien
87933965Sjdp  if (fixP->fx_addsy == (symbolS *) NULL)
88089857Sobrien    fixP->fx_done = 1;
88189857Sobrien
882130561Sobrien  /* We don't actually support subtracting a symbol.  */
883130561Sobrien  if (fixP->fx_subsy != (symbolS *) NULL)
884130561Sobrien    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
88589857Sobrien
88633965Sjdp  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
88733965Sjdp    {
88860484Sobrien      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
88960484Sobrien      const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
89060484Sobrien      const char *errmsg;
89133965Sjdp      bfd_reloc_code_real_type reloc_type;
89260484Sobrien      CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
89360484Sobrien      const CGEN_INSN *insn = fixP->fx_cgen.insn;
894218822Sdim      int start;
895218822Sdim      int length;
896218822Sdim      int signed_p = 0;
89733965Sjdp
898218822Sdim      if (fixP->fx_cgen.field)
899218822Sdim	{
900218822Sdim	  /* Use the twisty little pointer path
901218822Sdim	     back to the ifield if it exists.  */
902218822Sdim	  start = fixP->fx_cgen.field->val.leaf->start;
903218822Sdim	  length = fixP->fx_cgen.field->val.leaf->length;
904218822Sdim	}
905218822Sdim      else
906218822Sdim	{
907218822Sdim	  /* Or the far less useful operand-size guesstimate.  */
908218822Sdim	  start = operand->start;
909218822Sdim	  length = operand->length;
910218822Sdim	}
911218822Sdim
912218822Sdim      /* FIXME: this is not a perfect heuristic for figuring out
913218822Sdim         whether an operand is signed: it only works when the operand
914218822Sdim         is an immediate. it's not terribly likely that any other
915218822Sdim         values will be signed relocs, but it's possible. */
916218822Sdim      if (operand && (operand->hw_type == HW_H_SINT))
917218822Sdim        signed_p = 1;
918218822Sdim
91933965Sjdp      /* If the reloc has been fully resolved finish the operand here.  */
92033965Sjdp      /* FIXME: This duplicates the capabilities of code in BFD.  */
92133965Sjdp      if (fixP->fx_done
92233965Sjdp	  /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
92333965Sjdp	     finish the job.  Testing for pcrel is a temporary hack.  */
92433965Sjdp	  || fixP->fx_pcrel)
92533965Sjdp	{
92660484Sobrien	  CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
92760484Sobrien	  CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
92860484Sobrien
92960484Sobrien#if CGEN_INT_INSN_P
93060484Sobrien	  {
93160484Sobrien	    CGEN_INSN_INT insn_value =
932218822Sdim	      cgen_get_insn_value (cd, (unsigned char *) where,
933218822Sdim				   CGEN_INSN_BITSIZE (insn));
93460484Sobrien
93585815Sobrien	    /* ??? 0 is passed for `pc'.  */
93660484Sobrien	    errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
93760484Sobrien						   &insn_value, (bfd_vma) 0);
938218822Sdim	    cgen_put_insn_value (cd, (unsigned char *) where,
939218822Sdim				 CGEN_INSN_BITSIZE (insn), insn_value);
94060484Sobrien	  }
94160484Sobrien#else
94285815Sobrien	  /* ??? 0 is passed for `pc'.  */
943218822Sdim	  errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
944218822Sdim						 (unsigned char *) where,
94585815Sobrien						 (bfd_vma) 0);
94660484Sobrien#endif
94733965Sjdp	  if (errmsg)
94860484Sobrien	    as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
94933965Sjdp	}
95033965Sjdp
95133965Sjdp      if (fixP->fx_done)
95289857Sobrien	return;
95333965Sjdp
95433965Sjdp      /* The operand isn't fully resolved.  Determine a BFD reloc value
95533965Sjdp	 based on the operand information and leave it to
95633965Sjdp	 bfd_install_relocation.  Note that this doesn't work when
95733965Sjdp	 partial_inplace == false.  */
95833965Sjdp
95960484Sobrien      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
960218822Sdim#ifdef OBJ_COMPLEX_RELC
961218822Sdim      if (reloc_type == BFD_RELOC_RELC)
962218822Sdim	{
963218822Sdim	  /* Change addend to "self-describing" form,
964218822Sdim	     for BFD to handle in the linker.  */
965218822Sdim	  value = gas_cgen_encode_addend (start, operand->length,
966218822Sdim					  length, fixP->fx_size,
967218822Sdim					  cd->insn_chunk_bitsize / 8,
968218822Sdim					  signed_p,
969218822Sdim					  ! (fixP->fx_cgen.msb_field_p));
970218822Sdim	}
971218822Sdim#endif
97289857Sobrien
97333965Sjdp      if (reloc_type != BFD_RELOC_NONE)
97489857Sobrien	fixP->fx_r_type = reloc_type;
97533965Sjdp      else
97633965Sjdp	{
97733965Sjdp	  as_bad_where (fixP->fx_file, fixP->fx_line,
97860484Sobrien			_("unresolved expression that must be resolved"));
97933965Sjdp	  fixP->fx_done = 1;
98089857Sobrien	  return;
98133965Sjdp	}
98233965Sjdp    }
98333965Sjdp  else if (fixP->fx_done)
98433965Sjdp    {
98533965Sjdp      /* We're finished with this fixup.  Install it because
98633965Sjdp	 bfd_install_relocation won't be called to do it.  */
98733965Sjdp      switch (fixP->fx_r_type)
98833965Sjdp	{
98933965Sjdp	case BFD_RELOC_8:
99033965Sjdp	  md_number_to_chars (where, value, 1);
99133965Sjdp	  break;
99233965Sjdp	case BFD_RELOC_16:
99333965Sjdp	  md_number_to_chars (where, value, 2);
99433965Sjdp	  break;
99533965Sjdp	case BFD_RELOC_32:
99633965Sjdp	  md_number_to_chars (where, value, 4);
99733965Sjdp	  break;
99885815Sobrien	case BFD_RELOC_64:
99985815Sobrien	  md_number_to_chars (where, value, 8);
100085815Sobrien	  break;
100133965Sjdp	default:
100260484Sobrien	  as_bad_where (fixP->fx_file, fixP->fx_line,
100360484Sobrien			_("internal error: can't install fix for reloc type %d (`%s')"),
100460484Sobrien			fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
100560484Sobrien	  break;
100633965Sjdp	}
100733965Sjdp    }
100889857Sobrien  /* else
100989857Sobrien     bfd_install_relocation will be called to finish things up.  */
101033965Sjdp
101133965Sjdp  /* Tuck `value' away for use by tc_gen_reloc.
101233965Sjdp     See the comment describing fx_addnumber in write.h.
101333965Sjdp     This field is misnamed (or misused :-).  */
101433965Sjdp  fixP->fx_addnumber = value;
101533965Sjdp}
101633965Sjdp
101733965Sjdp/* Translate internal representation of relocation info to BFD target format.
101833965Sjdp
101933965Sjdp   FIXME: To what extent can we get all relevant targets to use this?  */
102033965Sjdp
102133965Sjdparelent *
102260484Sobriengas_cgen_tc_gen_reloc (section, fixP)
102385815Sobrien     asection * section ATTRIBUTE_UNUSED;
102438889Sjdp     fixS *     fixP;
102533965Sjdp{
102685815Sobrien  arelent *reloc;
102760484Sobrien  reloc = (arelent *) xmalloc (sizeof (arelent));
102833965Sjdp
102933965Sjdp  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
103033965Sjdp  if (reloc->howto == (reloc_howto_type *) NULL)
103133965Sjdp    {
103233965Sjdp      as_bad_where (fixP->fx_file, fixP->fx_line,
103385815Sobrien		    _("relocation is not supported"));
103433965Sjdp      return NULL;
103533965Sjdp    }
103633965Sjdp
103733965Sjdp  assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
103833965Sjdp
103960484Sobrien  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
104060484Sobrien  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
104133965Sjdp
104285815Sobrien  /* Use fx_offset for these cases.  */
104385815Sobrien  if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
104460484Sobrien      || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
104585815Sobrien    reloc->addend = fixP->fx_offset;
104660484Sobrien  else
104785815Sobrien    reloc->addend = fixP->fx_addnumber;
104860484Sobrien
104960484Sobrien  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
105033965Sjdp  return reloc;
105133965Sjdp}
1052130561Sobrien
1053130561Sobrien/* Perform any cgen specific initialisation.
1054130561Sobrien   Called after gas_cgen_cpu_desc has been created.  */
1055130561Sobrien
1056130561Sobrienvoid
1057130561Sobriengas_cgen_begin ()
1058130561Sobrien{
1059130561Sobrien  if (flag_signed_overflow_ok)
1060130561Sobrien    cgen_set_signed_overflow_ok (gas_cgen_cpu_desc);
1061130561Sobrien  else
1062130561Sobrien    cgen_clear_signed_overflow_ok (gas_cgen_cpu_desc);
1063130561Sobrien}
1064218822Sdim
1065