Home | History | Annotate | Download | only in config
      1 /* tc-iq2000.c -- Assembler for the Sitera IQ2000.
      2    Copyright (C) 2003-2014 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 3, 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
     18    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
     19    Boston, MA 02110-1301, USA.  */
     20 
     21 #include "as.h"
     22 #include "safe-ctype.h"
     23 #include "subsegs.h"
     24 #include "symcat.h"
     25 #include "opcodes/iq2000-desc.h"
     26 #include "opcodes/iq2000-opc.h"
     27 #include "cgen.h"
     28 #include "elf/common.h"
     29 #include "elf/iq2000.h"
     30 #include "libbfd.h"
     31 #include "sb.h"
     32 #include "macro.h"
     33 
     34 /* Structure to hold all of the different components describing
     35    an individual instruction.  */
     36 typedef struct
     37 {
     38   const CGEN_INSN *	insn;
     39   const CGEN_INSN *	orig_insn;
     40   CGEN_FIELDS		fields;
     41 #if CGEN_INT_INSN_P
     42   CGEN_INSN_INT         buffer [1];
     43 #define INSN_VALUE(buf) (*(buf))
     44 #else
     45   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
     46 #define INSN_VALUE(buf) (buf)
     47 #endif
     48   char *		addr;
     49   fragS *		frag;
     50   int                   num_fixups;
     51   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
     52   int                   indices [MAX_OPERAND_INSTANCES];
     53 }
     54 iq2000_insn;
     55 
     56 const char comment_chars[]        = "#";
     57 const char line_comment_chars[]   = "#";
     58 const char line_separator_chars[] = ";";
     59 const char EXP_CHARS[]            = "eE";
     60 const char FLT_CHARS[]            = "dD";
     61 
     62 /* Default machine.  */
     63 #define DEFAULT_MACHINE bfd_mach_iq2000
     64 #define DEFAULT_FLAGS	EF_IQ2000_CPU_IQ2000
     65 
     66 static unsigned long iq2000_mach = bfd_mach_iq2000;
     67 static int cpu_mach = (1 << MACH_IQ2000);
     68 
     69 /* Flags to set in the elf header.  */
     70 static flagword iq2000_flags = DEFAULT_FLAGS;
     71 
     72 typedef struct proc
     73 {
     74   symbolS *isym;
     75   unsigned long reg_mask;
     76   unsigned long reg_offset;
     77   unsigned long fpreg_mask;
     78   unsigned long fpreg_offset;
     79   unsigned long frame_offset;
     80   unsigned long frame_reg;
     81   unsigned long pc_reg;
     82 } procS;
     83 
     84 static procS cur_proc;
     85 static procS *cur_proc_ptr;
     86 static int numprocs;
     87 
     88 /* Relocations against symbols are done in two
     89    parts, with a HI relocation and a LO relocation.  Each relocation
     90    has only 16 bits of space to store an addend.  This means that in
     91    order for the linker to handle carries correctly, it must be able
     92    to locate both the HI and the LO relocation.  This means that the
     93    relocations must appear in order in the relocation table.
     94 
     95    In order to implement this, we keep track of each unmatched HI
     96    relocation.  We then sort them so that they immediately precede the
     97    corresponding LO relocation.  */
     98 
     99 struct iq2000_hi_fixup
    100 {
    101   struct iq2000_hi_fixup * next;  /* Next HI fixup.  */
    102   fixS *                  fixp;   /* This fixup.  */
    103   segT                    seg;    /* The section this fixup is in.  */
    104 };
    105 
    106 /* The list of unmatched HI relocs.  */
    107 static struct iq2000_hi_fixup * iq2000_hi_fixup_list;
    108 
    109 /* Macro hash table, which we will add to.  */
    110 extern struct hash_control *macro_hash;
    111 
    112 const char *md_shortopts = "";
    114 struct option md_longopts[] =
    115 {
    116   {NULL, no_argument, NULL, 0}
    117 };
    118 size_t md_longopts_size = sizeof (md_longopts);
    119 
    120 int
    121 md_parse_option (int c ATTRIBUTE_UNUSED,
    122 		 char * arg ATTRIBUTE_UNUSED)
    123 {
    124   return 0;
    125 }
    126 
    127 void
    128 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
    129 {
    130 }
    131 
    132 /* Automatically enter conditional branch macros.  */
    134 
    135 typedef struct
    136 {
    137   const char * mnemonic;
    138   const char ** expansion;
    139   const char ** args;
    140 } iq2000_macro_defs_s;
    141 
    142 static const char * abs_args[] = { "rd", "rs", "scratch=%1", NULL };
    143 static const char * abs_expn   = "\n sra \\rd,\\rs,31\n xor \\scratch,\\rd,\\rs\n sub \\rd,\\scratch,\\rd\n";
    144 static const char * la_expn    = "\n lui \\reg,%hi(\\label)\n ori \\reg,\\reg,%lo(\\label)\n";
    145 static const char * la_args[]  = { "reg", "label", NULL };
    146 static const char * bxx_args[] = { "rs", "rt", "label", "scratch=%1", NULL };
    147 static const char * bge_expn   = "\n slt \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
    148 static const char * bgeu_expn  = "\n sltu \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
    149 static const char * bgt_expn   = "\n slt \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
    150 static const char * bgtu_expn  = "\n sltu \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
    151 static const char * ble_expn   = "\n slt \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
    152 static const char * bleu_expn  = "\n sltu \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
    153 static const char * blt_expn   = "\n slt \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
    154 static const char * bltu_expn  = "\n sltu \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
    155 static const char * sxx_args[] = { "rd", "rs", "rt", NULL };
    156 static const char * sge_expn   = "\n slt \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
    157 static const char * sgeu_expn  = "\n sltu \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
    158 static const char * sle_expn   = "\n slt \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
    159 static const char * sleu_expn  = "\n sltu \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
    160 static const char * sgt_expn   = "\n slt \\rd,\\rt,\\rs\n";
    161 static const char * sgtu_expn  = "\n sltu \\rd,\\rt,\\rs\n";
    162 static const char * sne_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n";
    163 static const char * seq_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n xori \\rd,\\rd,1\n";
    164 static const char * ai32_args[] = { "rt", "rs", "imm", NULL };
    165 static const char * andi32_expn = "\n\
    166  .if (\\imm & 0xffff0000 == 0xffff0000)\n\
    167  andoi \\rt,\\rs,%lo(\\imm)\n\
    168  .elseif (\\imm & 0x0000ffff == 0x0000ffff)\n\
    169  andoui \\rt,\\rs,%uhi(\\imm)\n\
    170  .elseif (\\imm & 0xffff0000 == 0x00000000)\n\
    171  andi \\rt,\\rs,%lo(\\imm)\n\
    172  .else\n\
    173  andoui \\rt,\\rs,%uhi(\\imm)\n\
    174  andoi \\rt,\\rt,%lo(\\imm)\n\
    175  .endif\n";
    176 static const char * ori32_expn  = "\n\
    177  .if (\\imm & 0xffff == 0)\n\
    178  orui \\rt,\\rs,%uhi(\\imm)\n\
    179  .elseif (\\imm & 0xffff0000 == 0)\n\
    180  ori \\rt,\\rs,%lo(\\imm)\n\
    181  .else\n\
    182  orui \\rt,\\rs,%uhi(\\imm)\n\
    183  ori \\rt,\\rt,%lo(\\imm)\n\
    184  .endif\n";
    185 
    186 static const char * neg_args[] = { "rd", "rs", NULL };
    187 static const char * neg_expn   = "\n sub \\rd,%0,\\rs\n";
    188 static const char * negu_expn  = "\n subu \\rd,%0,\\rs\n";
    189 static const char * li_args[]  = { "rt", "imm", NULL };
    190 static const char * li_expn    = "\n\
    191  .if (\\imm & 0xffff0000 == 0x0)\n\
    192  ori \\rt,%0,\\imm\n\
    193  .elseif (\\imm & 0xffff0000 == 0xffff0000)\n\
    194  addi \\rt,%0,\\imm\n\
    195  .elseif (\\imm & 0x0000ffff == 0)\n\
    196  lui \\rt,%uhi(\\imm)\n\
    197  .else\n\
    198  lui \\rt,%uhi(\\imm)\n\
    199  ori \\rt,\\rt,%lo(\\imm)\n\
    200  .endif\n";
    201 
    202 static iq2000_macro_defs_s iq2000_macro_defs[] =
    203 {
    204   {"abs",   (const char **) & abs_expn,   (const char **) & abs_args},
    205   {"la",    (const char **) & la_expn,    (const char **) & la_args},
    206   {"bge",   (const char **) & bge_expn,   (const char **) & bxx_args},
    207   {"bgeu",  (const char **) & bgeu_expn,  (const char **) & bxx_args},
    208   {"bgt",   (const char **) & bgt_expn,   (const char **) & bxx_args},
    209   {"bgtu",  (const char **) & bgtu_expn,  (const char **) & bxx_args},
    210   {"ble",   (const char **) & ble_expn,   (const char **) & bxx_args},
    211   {"bleu",  (const char **) & bleu_expn,  (const char **) & bxx_args},
    212   {"blt",   (const char **) & blt_expn,   (const char **) & bxx_args},
    213   {"bltu",  (const char **) & bltu_expn,  (const char **) & bxx_args},
    214   {"sge",   (const char **) & sge_expn,   (const char **) & sxx_args},
    215   {"sgeu",  (const char **) & sgeu_expn,  (const char **) & sxx_args},
    216   {"sle",   (const char **) & sle_expn,   (const char **) & sxx_args},
    217   {"sleu",  (const char **) & sleu_expn,  (const char **) & sxx_args},
    218   {"sgt",   (const char **) & sgt_expn,   (const char **) & sxx_args},
    219   {"sgtu",  (const char **) & sgtu_expn,  (const char **) & sxx_args},
    220   {"seq",   (const char **) & seq_expn,   (const char **) & sxx_args},
    221   {"sne",   (const char **) & sne_expn,   (const char **) & sxx_args},
    222   {"neg",   (const char **) & neg_expn,   (const char **) & neg_args},
    223   {"negu",  (const char **) & negu_expn,  (const char **) & neg_args},
    224   {"li",    (const char **) & li_expn,    (const char **) & li_args},
    225   {"ori32", (const char **) & ori32_expn, (const char **) & ai32_args},
    226   {"andi32",(const char **) & andi32_expn,(const char **) & ai32_args},
    227 };
    228 
    229 static void
    230 iq2000_add_macro (const char *  name,
    231 		  const char *  semantics,
    232 		  const char ** arguments)
    233 {
    234   macro_entry *macro;
    235   sb macro_name;
    236   const char *namestr;
    237 
    238   macro = xmalloc (sizeof (macro_entry));
    239   sb_new (& macro->sub);
    240   sb_new (& macro_name);
    241 
    242   macro->formal_count = 0;
    243   macro->formals = 0;
    244 
    245   sb_add_string (& macro->sub, semantics);
    246 
    247   if (arguments != NULL)
    248     {
    249       formal_entry ** p = &macro->formals;
    250 
    251       macro->formal_count = 0;
    252       macro->formal_hash = hash_new ();
    253 
    254       while (*arguments != NULL)
    255 	{
    256 	  formal_entry *formal;
    257 
    258 	  formal = xmalloc (sizeof (formal_entry));
    259 
    260 	  sb_new (& formal->name);
    261 	  sb_new (& formal->def);
    262 	  sb_new (& formal->actual);
    263 
    264 	  /* chlm: Added the following to allow defaulted args.  */
    265 	  if (strchr (*arguments,'='))
    266 	    {
    267 	      char * tt_args = strdup (*arguments);
    268 	      char * tt_dflt = strchr (tt_args,'=');
    269 
    270 	      *tt_dflt = 0;
    271 	      sb_add_string (& formal->name, tt_args);
    272 	      sb_add_string (& formal->def,  tt_dflt + 1);
    273 	    }
    274 	  else
    275 	    sb_add_string (& formal->name, *arguments);
    276 
    277 	  /* Add to macro's hash table.  */
    278 	  hash_jam (macro->formal_hash, sb_terminate (& formal->name), formal);
    279 
    280 	  formal->index = macro->formal_count;
    281 	  macro->formal_count++;
    282 	  *p = formal;
    283 	  p = & formal->next;
    284 	  *p = NULL;
    285 	  ++arguments;
    286 	}
    287     }
    288 
    289   sb_add_string (&macro_name, name);
    290   namestr = sb_terminate (&macro_name);
    291   hash_jam (macro_hash, namestr, macro);
    292 
    293   macro_defined = 1;
    294 }
    295 
    296 static void
    297 iq2000_load_macros (void)
    298 {
    299   int i;
    300   int mcnt = ARRAY_SIZE (iq2000_macro_defs);
    301 
    302   for (i = 0; i < mcnt; i++)
    303     iq2000_add_macro (iq2000_macro_defs[i].mnemonic,
    304     		      *iq2000_macro_defs[i].expansion,
    305 		      iq2000_macro_defs[i].args);
    306 }
    307 
    308 void
    309 md_begin (void)
    310 {
    311   /* Initialize the `cgen' interface.  */
    312 
    313   /* Set the machine number and endian.  */
    314   gas_cgen_cpu_desc = iq2000_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
    315 					   CGEN_CPU_OPEN_ENDIAN,
    316 					   CGEN_ENDIAN_BIG,
    317 					   CGEN_CPU_OPEN_END);
    318   iq2000_cgen_init_asm (gas_cgen_cpu_desc);
    319 
    320   /* This is a callback from cgen to gas to parse operands.  */
    321   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
    322 
    323   /* Set the ELF flags if desired.  */
    324   if (iq2000_flags)
    325     bfd_set_private_flags (stdoutput, iq2000_flags);
    326 
    327   /* Set the machine type */
    328   bfd_default_set_arch_mach (stdoutput, bfd_arch_iq2000, iq2000_mach);
    329 
    330   iq2000_load_macros ();
    331 }
    332 
    333 void
    334 md_assemble (char * str)
    335 {
    336   static long delayed_load_register = 0;
    337   static int last_insn_had_delay_slot = 0;
    338   static int last_insn_has_load_delay = 0;
    339   static int last_insn_unconditional_jump = 0;
    340   static int last_insn_was_ldw = 0;
    341 
    342   iq2000_insn insn;
    343   char * errmsg;
    344 
    345   /* Initialize GAS's cgen interface for a new instruction.  */
    346   gas_cgen_init_parse ();
    347 
    348   insn.insn = iq2000_cgen_assemble_insn
    349       (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
    350 
    351   if (!insn.insn)
    352     {
    353       as_bad ("%s", errmsg);
    354       return;
    355     }
    356 
    357   /* Doesn't really matter what we pass for RELAX_P here.  */
    358   gas_cgen_finish_insn (insn.insn, insn.buffer,
    359 			CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
    360 
    361   /* We need to generate an error if there's a yielding instruction in the delay
    362      slot of a control flow modifying instruction (jump (yes), load (no))  */
    363   if ((last_insn_had_delay_slot && !last_insn_has_load_delay) &&
    364       CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_YIELD_INSN))
    365       as_bad (_("the yielding instruction %s may not be in a delay slot."),
    366               CGEN_INSN_NAME (insn.insn));
    367 
    368   /* Warn about odd numbered base registers for paired-register
    369      instructions like LDW.  On iq2000, result is always rt.  */
    370   if (iq2000_mach == bfd_mach_iq2000
    371       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_EVEN_REG_NUM)
    372       && (insn.fields.f_rt % 2))
    373     as_bad (_("Register number (R%ld) for double word access must be even."),
    374 	    insn.fields.f_rt);
    375 
    376   /* Warn about insns that reference the target of a previous load.  */
    377   /* NOTE: R0 is a special case and is not subject to load delays (except for ldw).  */
    378   if (delayed_load_register && (last_insn_has_load_delay || last_insn_was_ldw))
    379     {
    380       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD) &&
    381 	  insn.fields.f_rd == delayed_load_register)
    382 	as_warn (_("operand references R%ld of previous load."),
    383 		 insn.fields.f_rd);
    384 
    385       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS) &&
    386 	  insn.fields.f_rs == delayed_load_register)
    387 	as_warn (_("operand references R%ld of previous load."),
    388 		 insn.fields.f_rs);
    389 
    390       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT) &&
    391 	  insn.fields.f_rt == delayed_load_register)
    392 	as_warn (_("operand references R%ld of previous load."),
    393 		 insn.fields.f_rt);
    394 
    395       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_R31) &&
    396 	  delayed_load_register == 31)
    397 	as_warn (_("instruction implicitly accesses R31 of previous load."));
    398     }
    399 
    400   /* Warn about insns that reference the (target + 1) of a previous ldw.  */
    401   if (last_insn_was_ldw)
    402     {
    403       if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD)
    404            && insn.fields.f_rd == delayed_load_register + 1)
    405        || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS)
    406            && insn.fields.f_rs == delayed_load_register + 1)
    407        || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT)
    408            && insn.fields.f_rt == delayed_load_register + 1))
    409         as_warn (_("operand references R%ld of previous load."),
    410                 delayed_load_register + 1);
    411     }
    412 
    413   last_insn_had_delay_slot =
    414     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
    415 
    416   last_insn_has_load_delay =
    417     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
    418 
    419   if (last_insn_unconditional_jump)
    420     last_insn_has_load_delay = last_insn_unconditional_jump = 0;
    421   else if (! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "j")
    422 	   || ! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "jal"))
    423 	   last_insn_unconditional_jump = 1;
    424 
    425   /* The meaning of EVEN_REG_NUM was overloaded to also imply LDW.  Since
    426      that's not true for IQ10, let's make the above logic specific to LDW.  */
    427   last_insn_was_ldw = ! strcmp ("ldw", CGEN_INSN_NAME (insn.insn));
    428 
    429   /* The assumption here is that the target of a load is always rt.  */
    430   delayed_load_register = insn.fields.f_rt;
    431 }
    432 
    433 valueT
    434 md_section_align (segT segment, valueT size)
    435 {
    436   int align = bfd_get_section_alignment (stdoutput, segment);
    437   return ((size + (1 << align) - 1) & (-1 << align));
    438 }
    439 
    440 symbolS *
    441 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
    442 {
    443     return 0;
    444 }
    445 
    446 /* Interface to relax_segment.  */
    448 
    449 /* Return an initial guess of the length by which a fragment must grow to
    450    hold a branch to reach its destination.
    451    Also updates fr_type/fr_subtype as necessary.
    452 
    453    Called just before doing relaxation.
    454    Any symbol that is now undefined will not become defined.
    455    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
    456    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
    457    Although it may not be explicit in the frag, pretend fr_var starts with a
    458    0 value.  */
    459 
    460 int
    461 md_estimate_size_before_relax (fragS * fragP,
    462 			       segT    segment ATTRIBUTE_UNUSED)
    463 {
    464   int    old_fr_fix = fragP->fr_fix;
    465 
    466   /* The only thing we have to handle here are symbols outside of the
    467      current segment.  They may be undefined or in a different segment in
    468      which case linker scripts may place them anywhere.
    469      However, we can't finish the fragment here and emit the reloc as insn
    470      alignment requirements may move the insn about.  */
    471 
    472   return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
    473 }
    474 
    475 /* *fragP has been relaxed to its final size, and now needs to have
    476    the bytes inside it modified to conform to the new size.
    477 
    478    Called after relaxation is finished.
    479    fragP->fr_type == rs_machine_dependent.
    480    fragP->fr_subtype is the subtype of what the address relaxed to.  */
    481 
    482 void
    483 md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
    484 		 segT    sec   ATTRIBUTE_UNUSED,
    485 		 fragS * fragP ATTRIBUTE_UNUSED)
    486 {
    487 }
    488 
    489 
    490 /* Functions concerning relocs.  */
    492 
    493 long
    494 md_pcrel_from_section (fixS * fixP, segT sec)
    495 {
    496   if (fixP->fx_addsy != (symbolS *) NULL
    497       && (! S_IS_DEFINED (fixP->fx_addsy)
    498 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
    499     {
    500       /* The symbol is undefined (or is defined but not in this section).
    501 	 Let the linker figure it out.  */
    502       return 0;
    503     }
    504 
    505   /* Return the address of the delay slot.  */
    506   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
    507 }
    508 
    509 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
    510    Returns BFD_RELOC_NONE if no reloc type can be found.
    511    *FIXP may be modified if desired.  */
    512 
    513 bfd_reloc_code_real_type
    514 md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
    515 		      const CGEN_OPERAND * operand,
    516 		      fixS *               fixP     ATTRIBUTE_UNUSED)
    517 {
    518   switch (operand->type)
    519     {
    520     case IQ2000_OPERAND_OFFSET:      return BFD_RELOC_16_PCREL_S2;
    521     case IQ2000_OPERAND_JMPTARG:     return BFD_RELOC_IQ2000_OFFSET_16;
    522     case IQ2000_OPERAND_JMPTARGQ10:  return BFD_RELOC_NONE;
    523     case IQ2000_OPERAND_HI16:        return BFD_RELOC_HI16;
    524     case IQ2000_OPERAND_LO16:        return BFD_RELOC_LO16;
    525     default: break;
    526     }
    527 
    528   return BFD_RELOC_NONE;
    529 }
    530 
    531 /* Record a HI16 reloc for later matching with its LO16 cousin.  */
    532 
    533 static void
    534 iq2000_record_hi16 (int    reloc_type,
    535 		    fixS * fixP,
    536 		    segT   seg ATTRIBUTE_UNUSED)
    537 {
    538   struct iq2000_hi_fixup * hi_fixup;
    539 
    540   gas_assert (reloc_type == BFD_RELOC_HI16);
    541 
    542   hi_fixup = xmalloc (sizeof * hi_fixup);
    543   hi_fixup->fixp = fixP;
    544   hi_fixup->seg  = now_seg;
    545   hi_fixup->next = iq2000_hi_fixup_list;
    546 
    547   iq2000_hi_fixup_list = hi_fixup;
    548 }
    549 
    550 /* Called while parsing an instruction to create a fixup.
    551    We need to check for HI16 relocs and queue them up for later sorting.  */
    552 
    553 fixS *
    554 iq2000_cgen_record_fixup_exp (fragS *              frag,
    555 			      int                  where,
    556 			      const CGEN_INSN *    insn,
    557 			      int                  length,
    558 			      const CGEN_OPERAND * operand,
    559 			      int                  opinfo,
    560 			      expressionS *        exp)
    561 {
    562   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
    563 					   operand, opinfo, exp);
    564 
    565   if (operand->type == IQ2000_OPERAND_HI16
    566       /* If low/high was used, it is recorded in `opinfo'.  */
    567       && (fixP->fx_cgen.opinfo == BFD_RELOC_HI16
    568 	  || fixP->fx_cgen.opinfo == BFD_RELOC_LO16))
    569     iq2000_record_hi16 (fixP->fx_cgen.opinfo, fixP, now_seg);
    570 
    571   return fixP;
    572 }
    573 
    574 /* Return BFD reloc type from opinfo field in a fixS.
    575    It's tricky using fx_r_type in iq2000_frob_file because the values
    576    are BFD_RELOC_UNUSED + operand number.  */
    577 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
    578 
    579 /* Sort any unmatched HI16 relocs so that they immediately precede
    580    the corresponding LO16 reloc.  This is called before md_apply_fix and
    581    tc_gen_reloc.  */
    582 
    583 void
    584 iq2000_frob_file (void)
    585 {
    586   struct iq2000_hi_fixup * l;
    587 
    588   for (l = iq2000_hi_fixup_list; l != NULL; l = l->next)
    589     {
    590       segment_info_type * seginfo;
    591       int                 pass;
    592 
    593       gas_assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
    594 	      || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
    595 
    596       /* Check quickly whether the next fixup happens to be a matching low.  */
    597       if (l->fixp->fx_next != NULL
    598 	  && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
    599 	  && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
    600 	  && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
    601 	continue;
    602 
    603       /* Look through the fixups for this segment for a matching
    604          `low'.  When we find one, move the high just in front of it.
    605          We do this in two passes.  In the first pass, we try to find
    606          a unique `low'.  In the second pass, we permit multiple
    607          high's relocs for a single `low'.  */
    608       seginfo = seg_info (l->seg);
    609       for (pass = 0; pass < 2; pass++)
    610 	{
    611 	  fixS * f;
    612 	  fixS * prev;
    613 
    614 	  prev = NULL;
    615 	  for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
    616 	    {
    617 	      /* Check whether this is a `low' fixup which matches l->fixp.  */
    618 	      if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
    619 		  && f->fx_addsy == l->fixp->fx_addsy
    620 		  && f->fx_offset == l->fixp->fx_offset
    621 		  && (pass == 1
    622 		      || prev == NULL
    623 		      || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
    624 		      || prev->fx_addsy != f->fx_addsy
    625 		      || prev->fx_offset !=  f->fx_offset))
    626 		{
    627 		  fixS ** pf;
    628 
    629 		  /* Move l->fixp before f.  */
    630 		  for (pf = &seginfo->fix_root;
    631 		       * pf != l->fixp;
    632 		       pf = & (* pf)->fx_next)
    633 		    gas_assert (* pf != NULL);
    634 
    635 		  * pf = l->fixp->fx_next;
    636 
    637 		  l->fixp->fx_next = f;
    638 		  if (prev == NULL)
    639 		    seginfo->fix_root = l->fixp;
    640 		  else
    641 		    prev->fx_next = l->fixp;
    642 
    643 		  break;
    644 		}
    645 
    646 	      prev = f;
    647 	    }
    648 
    649 	  if (f != NULL)
    650 	    break;
    651 
    652 	  if (pass == 1)
    653 	    as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
    654 			   _("Unmatched high relocation"));
    655 	}
    656     }
    657 }
    658 
    659 /* See whether we need to force a relocation into the output file.  */
    660 
    661 int
    662 iq2000_force_relocation (fixS * fix)
    663 {
    664   if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
    665       || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    666     return 1;
    667 
    668   return 0;
    669 }
    670 
    671 /* Handle the .set pseudo-op.  */
    673 
    674 static void
    675 s_iq2000_set (int x ATTRIBUTE_UNUSED)
    676 {
    677   static const char * ignored_arguments [] =
    678     {
    679       "reorder",
    680       "noreorder",
    681       "at",
    682       "noat",
    683       "macro",
    684       "nomacro",
    685       "move",
    686       "novolatile",
    687       "nomove",
    688       "volatile",
    689       "bopt",
    690       "nobopt",
    691       NULL
    692     };
    693   const char ** ignored;
    694   char *name = input_line_pointer, ch;
    695   char *save_ILP = input_line_pointer;
    696 
    697   while (!is_end_of_line[(unsigned char) *input_line_pointer])
    698     input_line_pointer++;
    699   ch = *input_line_pointer;
    700   *input_line_pointer = '\0';
    701 
    702   for (ignored = ignored_arguments; * ignored; ignored ++)
    703     if (strcmp (* ignored, name) == 0)
    704       break;
    705   if (* ignored == NULL)
    706     {
    707       /* We'd like to be able to use .set symbol, expn */
    708       input_line_pointer = save_ILP;
    709       s_set (0);
    710       return;
    711     }
    712   *input_line_pointer = ch;
    713   demand_empty_rest_of_line ();
    714 }
    715 
    716 /* Write a value out to the object file, using the appropriate endianness.  */
    718 
    719 void
    720 md_number_to_chars (char * buf, valueT val, int n)
    721 {
    722   number_to_chars_bigendian (buf, val, n);
    723 }
    724 
    725 void
    726 md_operand (expressionS * exp)
    727 {
    728   /* In case of a syntax error, escape back to try next syntax combo.  */
    729   if (exp->X_op == O_absent)
    730     gas_cgen_md_operand (exp);
    731 }
    732 
    733 char *
    734 md_atof (int type, char * litP, int * sizeP)
    735 {
    736   return ieee_md_atof (type, litP, sizeP, TRUE);
    737 }
    738 
    739 bfd_boolean
    740 iq2000_fix_adjustable (fixS * fixP)
    741 {
    742   bfd_reloc_code_real_type reloc_type;
    743 
    744   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    745     {
    746       const CGEN_INSN *insn = NULL;
    747       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
    748       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
    749 
    750       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
    751     }
    752   else
    753     reloc_type = fixP->fx_r_type;
    754 
    755   if (fixP->fx_addsy == NULL)
    756     return TRUE;
    757 
    758   /* Prevent all adjustments to global symbols.  */
    759   if (S_IS_EXTERNAL (fixP->fx_addsy))
    760     return FALSE;
    761 
    762   if (S_IS_WEAK (fixP->fx_addsy))
    763     return FALSE;
    764 
    765   /* We need the symbol name for the VTABLE entries.  */
    766   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
    767       || reloc_type == BFD_RELOC_VTABLE_ENTRY)
    768     return FALSE;
    769 
    770   return TRUE;
    771 }
    772 
    773 static void
    774 s_change_sec (int sec)
    775 {
    776 #ifdef OBJ_ELF
    777   /* The ELF backend needs to know that we are changing sections, so
    778      that .previous works correctly.  We could do something like check
    779      for a obj_section_change_hook macro, but that might be confusing
    780      as it would not be appropriate to use it in the section changing
    781      functions in read.c, since obj-elf.c intercepts those.  FIXME:
    782      This should be cleaner, somehow.  */
    783   obj_elf_section_change_hook ();
    784 #endif
    785 
    786   switch (sec)
    787     {
    788     case 't':
    789       s_text (0);
    790       break;
    791     case 'd':
    792     case 'r':
    793       s_data (0);
    794       break;
    795     }
    796 }
    797 
    798 static symbolS *
    799 get_symbol (void)
    800 {
    801   int c;
    802   char *name;
    803   symbolS *p;
    804 
    805   name = input_line_pointer;
    806   c = get_symbol_end ();
    807   p = (symbolS *) symbol_find_or_make (name);
    808   *input_line_pointer = c;
    809   return p;
    810 }
    811 
    812 /* The .end directive.  */
    813 
    814 static void
    815 s_iq2000_end (int x ATTRIBUTE_UNUSED)
    816 {
    817   symbolS *p;
    818   int maybe_text;
    819 
    820   if (!is_end_of_line[(unsigned char) *input_line_pointer])
    821     {
    822       p = get_symbol ();
    823       demand_empty_rest_of_line ();
    824     }
    825   else
    826     p = NULL;
    827 
    828   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
    829     maybe_text = 1;
    830   else
    831     maybe_text = 0;
    832 
    833   if (!maybe_text)
    834     as_warn (_(".end not in text section"));
    835 
    836   if (!cur_proc_ptr)
    837     {
    838       as_warn (_(".end directive without a preceding .ent directive."));
    839       demand_empty_rest_of_line ();
    840       return;
    841     }
    842 
    843   if (p != NULL)
    844     {
    845       gas_assert (S_GET_NAME (p));
    846       if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
    847 	as_warn (_(".end symbol does not match .ent symbol."));
    848     }
    849   else
    850     as_warn (_(".end directive missing or unknown symbol"));
    851 
    852   cur_proc_ptr = NULL;
    853 }
    854 
    855 static int
    856 get_number (void)
    857 {
    858   int negative = 0;
    859   long val = 0;
    860 
    861   if (*input_line_pointer == '-')
    862     {
    863       ++input_line_pointer;
    864       negative = 1;
    865     }
    866 
    867   if (! ISDIGIT (*input_line_pointer))
    868     as_bad (_("Expected simple number."));
    869 
    870   if (input_line_pointer[0] == '0')
    871     {
    872       if (input_line_pointer[1] == 'x')
    873 	{
    874 	  input_line_pointer += 2;
    875 	  while (ISXDIGIT (*input_line_pointer))
    876 	    {
    877 	      val <<= 4;
    878 	      val |= hex_value (*input_line_pointer++);
    879 	    }
    880 	  return negative ? -val : val;
    881 	}
    882       else
    883 	{
    884 	  ++input_line_pointer;
    885 
    886 	  while (ISDIGIT (*input_line_pointer))
    887 	    {
    888 	      val <<= 3;
    889 	      val |= *input_line_pointer++ - '0';
    890 	    }
    891 	  return negative ? -val : val;
    892 	}
    893     }
    894 
    895   if (! ISDIGIT (*input_line_pointer))
    896     {
    897       printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
    898 	      *input_line_pointer, *input_line_pointer);
    899       as_warn (_("Invalid number"));
    900       return -1;
    901     }
    902 
    903   while (ISDIGIT (*input_line_pointer))
    904     {
    905       val *= 10;
    906       val += *input_line_pointer++ - '0';
    907     }
    908 
    909   return negative ? -val : val;
    910 }
    911 
    912 /* The .aent and .ent directives.  */
    913 
    914 static void
    915 s_iq2000_ent (int aent)
    916 {
    917   symbolS *symbolP;
    918   int maybe_text;
    919 
    920   symbolP = get_symbol ();
    921   if (*input_line_pointer == ',')
    922     input_line_pointer++;
    923   SKIP_WHITESPACE ();
    924   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
    925     get_number ();
    926 
    927   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
    928     maybe_text = 1;
    929   else
    930     maybe_text = 0;
    931 
    932   if (!maybe_text)
    933     as_warn (_(".ent or .aent not in text section."));
    934 
    935   if (!aent && cur_proc_ptr)
    936     as_warn (_("missing `.end'"));
    937 
    938   if (!aent)
    939     {
    940       cur_proc_ptr = &cur_proc;
    941       memset (cur_proc_ptr, '\0', sizeof (procS));
    942 
    943       cur_proc_ptr->isym = symbolP;
    944 
    945       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
    946 
    947       numprocs++;
    948     }
    949 
    950   demand_empty_rest_of_line ();
    951 }
    952 
    953 /* The .frame directive. If the mdebug section is present (IRIX 5 native)
    954    then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
    955    s_iq2000_frame is used so that we can set the PDR information correctly.
    956    We can't use the ecoff routines because they make reference to the ecoff
    957    symbol table (in the mdebug section).  */
    958 
    959 static void
    960 s_iq2000_frame (int ignore)
    961 {
    962   s_ignore (ignore);
    963 }
    964 
    965 /* The .fmask and .mask directives. If the mdebug section is present
    966    (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
    967    embedded targets, s_iq2000_mask is used so that we can set the PDR
    968    information correctly. We can't use the ecoff routines because they
    969    make reference to the ecoff symbol table (in the mdebug section).  */
    970 
    971 static void
    972 s_iq2000_mask (int reg_type)
    973 {
    974   s_ignore (reg_type);
    975 }
    976 
    977 /* The target specific pseudo-ops which we support.  */
    978 const pseudo_typeS md_pseudo_table[] =
    979 {
    980     { "align",  s_align_bytes,           0 },
    981     { "word",   cons,                    4 },
    982     { "rdata",  s_change_sec, 		'r'},
    983     { "sdata",  s_change_sec, 		's'},
    984     { "set",	s_iq2000_set,		 0 },
    985     { "ent",    s_iq2000_ent, 		 0 },
    986     { "end",    s_iq2000_end,            0 },
    987     { "frame",  s_iq2000_frame, 	 0 },
    988     { "fmask",  s_iq2000_mask, 		'F'},
    989     { "mask",   s_iq2000_mask, 		'R'},
    990     { "dword",	cons, 			 8 },
    991     { "half",	cons, 			 2 },
    992     { NULL, 	NULL,			 0 }
    993 };
    994