Back to index

cell-binutils  2.17cvs20070401
tc-iq2000.c
Go to the documentation of this file.
00001 /* tc-iq2000.c -- Assembler for the Sitera IQ2000.
00002    Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation.
00003 
00004    This file is part of GAS, the GNU Assembler.
00005 
00006    GAS is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    GAS is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with GAS; see the file COPYING.  If not, write to
00018    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
00019    Boston, MA 02110-1301, USA.  */
00020 
00021 #include "as.h"
00022 #include "safe-ctype.h"
00023 #include "subsegs.h"
00024 #include "symcat.h"
00025 #include "opcodes/iq2000-desc.h"
00026 #include "opcodes/iq2000-opc.h"
00027 #include "cgen.h"
00028 #include "elf/common.h"
00029 #include "elf/iq2000.h"
00030 #include "libbfd.h"
00031 #include "sb.h"
00032 #include "macro.h"
00033 
00034 /* Structure to hold all of the different components describing
00035    an individual instruction.  */
00036 typedef struct
00037 {
00038   const CGEN_INSN *  insn;
00039   const CGEN_INSN *  orig_insn;
00040   CGEN_FIELDS        fields;
00041 #if CGEN_INT_INSN_P
00042   CGEN_INSN_INT         buffer [1];
00043 #define INSN_VALUE(buf) (*(buf))
00044 #else
00045   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
00046 #define INSN_VALUE(buf) (buf)
00047 #endif
00048   char *             addr;
00049   fragS *            frag;
00050   int                   num_fixups;
00051   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
00052   int                   indices [MAX_OPERAND_INSTANCES];
00053 }
00054 iq2000_insn;
00055 
00056 const char comment_chars[]        = "#";
00057 const char line_comment_chars[]   = "#";
00058 const char line_separator_chars[] = ";";
00059 const char EXP_CHARS[]            = "eE";
00060 const char FLT_CHARS[]            = "dD";
00061 
00062 /* Default machine.  */
00063 #define DEFAULT_MACHINE bfd_mach_iq2000
00064 #define DEFAULT_FLAGS       EF_IQ2000_CPU_IQ2000
00065 
00066 static unsigned long iq2000_mach = bfd_mach_iq2000;
00067 static int cpu_mach = (1 << MACH_IQ2000);
00068 
00069 /* Flags to set in the elf header.  */
00070 static flagword iq2000_flags = DEFAULT_FLAGS;
00071 
00072 typedef struct proc
00073 {
00074   symbolS *isym;
00075   unsigned long reg_mask;
00076   unsigned long reg_offset;
00077   unsigned long fpreg_mask;
00078   unsigned long fpreg_offset;
00079   unsigned long frame_offset;
00080   unsigned long frame_reg;
00081   unsigned long pc_reg;
00082 } procS;
00083 
00084 static procS cur_proc;
00085 static procS *cur_proc_ptr;
00086 static int numprocs;
00087 
00088 /* Relocations against symbols are done in two
00089    parts, with a HI relocation and a LO relocation.  Each relocation
00090    has only 16 bits of space to store an addend.  This means that in
00091    order for the linker to handle carries correctly, it must be able
00092    to locate both the HI and the LO relocation.  This means that the
00093    relocations must appear in order in the relocation table.
00094 
00095    In order to implement this, we keep track of each unmatched HI
00096    relocation.  We then sort them so that they immediately precede the
00097    corresponding LO relocation.  */
00098 
00099 struct iq2000_hi_fixup
00100 {
00101   struct iq2000_hi_fixup * next;  /* Next HI fixup.  */
00102   fixS *                  fixp;   /* This fixup.  */
00103   segT                    seg;    /* The section this fixup is in.  */
00104 };
00105 
00106 /* The list of unmatched HI relocs.  */
00107 static struct iq2000_hi_fixup * iq2000_hi_fixup_list;
00108 
00109 /* Macro hash table, which we will add to.  */
00110 extern struct hash_control *macro_hash;
00111 
00112 const char *md_shortopts = "";
00113 struct option md_longopts[] =
00114 {
00115   {NULL, no_argument, NULL, 0}
00116 };
00117 size_t md_longopts_size = sizeof (md_longopts);
00118 
00119 int
00120 md_parse_option (int c ATTRIBUTE_UNUSED,
00121                char * arg ATTRIBUTE_UNUSED)
00122 {
00123   return 0;
00124 }
00125 
00126 void
00127 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
00128 {
00129 }
00130 
00131 /* Automatically enter conditional branch macros.  */
00132 
00133 typedef struct
00134 {
00135   const char * mnemonic;
00136   const char ** expansion;
00137   const char ** args;
00138 } iq2000_macro_defs_s;
00139 
00140 static const char * abs_args[] = { "rd", "rs", "scratch=%1", NULL };
00141 static const char * abs_expn   = "\n sra \\rd,\\rs,31\n xor \\scratch,\\rd,\\rs\n sub \\rd,\\scratch,\\rd\n";
00142 static const char * la_expn    = "\n lui \\reg,%hi(\\label)\n ori \\reg,\\reg,%lo(\\label)\n";
00143 static const char * la_args[]  = { "reg", "label", NULL };
00144 static const char * bxx_args[] = { "rs", "rt", "label", "scratch=%1", NULL };
00145 static const char * bge_expn   = "\n slt \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
00146 static const char * bgeu_expn  = "\n sltu \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
00147 static const char * bgt_expn   = "\n slt \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
00148 static const char * bgtu_expn  = "\n sltu \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
00149 static const char * ble_expn   = "\n slt \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
00150 static const char * bleu_expn  = "\n sltu \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
00151 static const char * blt_expn   = "\n slt \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
00152 static const char * bltu_expn  = "\n sltu \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
00153 static const char * sxx_args[] = { "rd", "rs", "rt", NULL };
00154 static const char * sge_expn   = "\n slt \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
00155 static const char * sgeu_expn  = "\n sltu \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
00156 static const char * sle_expn   = "\n slt \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
00157 static const char * sleu_expn  = "\n sltu \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
00158 static const char * sgt_expn   = "\n slt \\rd,\\rt,\\rs\n";
00159 static const char * sgtu_expn  = "\n sltu \\rd,\\rt,\\rs\n";
00160 static const char * sne_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n";
00161 static const char * seq_expn   = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n xori \\rd,\\rd,1\n";
00162 static const char * ai32_args[] = { "rt", "rs", "imm", NULL };
00163 static const char * andi32_expn = "\n\
00164  .if (\\imm & 0xffff0000 == 0xffff0000)\n\
00165  andoi \\rt,\\rs,%lo(\\imm)\n\
00166  .elseif (\\imm & 0x0000ffff == 0x0000ffff)\n\
00167  andoui \\rt,\\rs,%uhi(\\imm)\n\
00168  .elseif (\\imm & 0xffff0000 == 0x00000000)\n\
00169  andi \\rt,\\rs,%lo(\\imm)\n\
00170  .else\n\
00171  andoui \\rt,\\rs,%uhi(\\imm)\n\
00172  andoi \\rt,\\rt,%lo(\\imm)\n\
00173  .endif\n";
00174 static const char * ori32_expn  = "\n\
00175  .if (\\imm & 0xffff == 0)\n\
00176  orui \\rt,\\rs,%uhi(\\imm)\n\
00177  .elseif (\\imm & 0xffff0000 == 0)\n\
00178  ori \\rt,\\rs,%lo(\\imm)\n\
00179  .else\n\
00180  orui \\rt,\\rs,%uhi(\\imm)\n\
00181  ori \\rt,\\rt,%lo(\\imm)\n\
00182  .endif\n";
00183 
00184 static const char * neg_args[] = { "rd", "rs", NULL };
00185 static const char * neg_expn   = "\n sub \\rd,%0,\\rs\n";
00186 static const char * negu_expn  = "\n subu \\rd,%0,\\rs\n";
00187 static const char * li_args[]  = { "rt", "imm", NULL };
00188 static const char * li_expn    = "\n\
00189  .if (\\imm & 0xffff0000 == 0x0)\n\
00190  ori \\rt,%0,\\imm\n\
00191  .elseif (\\imm & 0xffff0000 == 0xffff0000)\n\
00192  addi \\rt,%0,\\imm\n\
00193  .elseif (\\imm & 0x0000ffff == 0)\n\
00194  lui \\rt,%uhi(\\imm)\n\
00195  .else\n\
00196  lui \\rt,%uhi(\\imm)\n\
00197  ori \\rt,\\rt,%lo(\\imm)\n\
00198  .endif\n";
00199 
00200 static iq2000_macro_defs_s iq2000_macro_defs[] =
00201 {
00202   {"abs",   (const char **) & abs_expn,   (const char **) & abs_args},
00203   {"la",    (const char **) & la_expn,    (const char **) & la_args},
00204   {"bge",   (const char **) & bge_expn,   (const char **) & bxx_args},
00205   {"bgeu",  (const char **) & bgeu_expn,  (const char **) & bxx_args},
00206   {"bgt",   (const char **) & bgt_expn,   (const char **) & bxx_args},
00207   {"bgtu",  (const char **) & bgtu_expn,  (const char **) & bxx_args},
00208   {"ble",   (const char **) & ble_expn,   (const char **) & bxx_args},
00209   {"bleu",  (const char **) & bleu_expn,  (const char **) & bxx_args},
00210   {"blt",   (const char **) & blt_expn,   (const char **) & bxx_args},
00211   {"bltu",  (const char **) & bltu_expn,  (const char **) & bxx_args},
00212   {"sge",   (const char **) & sge_expn,   (const char **) & sxx_args},
00213   {"sgeu",  (const char **) & sgeu_expn,  (const char **) & sxx_args},
00214   {"sle",   (const char **) & sle_expn,   (const char **) & sxx_args},
00215   {"sleu",  (const char **) & sleu_expn,  (const char **) & sxx_args},
00216   {"sgt",   (const char **) & sgt_expn,   (const char **) & sxx_args},
00217   {"sgtu",  (const char **) & sgtu_expn,  (const char **) & sxx_args},
00218   {"seq",   (const char **) & seq_expn,   (const char **) & sxx_args},
00219   {"sne",   (const char **) & sne_expn,   (const char **) & sxx_args},
00220   {"neg",   (const char **) & neg_expn,   (const char **) & neg_args},
00221   {"negu",  (const char **) & negu_expn,  (const char **) & neg_args},
00222   {"li",    (const char **) & li_expn,    (const char **) & li_args},
00223   {"ori32", (const char **) & ori32_expn, (const char **) & ai32_args},
00224   {"andi32",(const char **) & andi32_expn,(const char **) & ai32_args},
00225 };
00226 
00227 static void
00228 iq2000_add_macro (const char *  name,
00229                 const char *  semantics,
00230                 const char ** arguments)
00231 {
00232   macro_entry *macro;
00233   sb macro_name;
00234   const char *namestr;
00235 
00236   macro = xmalloc (sizeof (macro_entry));
00237   sb_new (& macro->sub);
00238   sb_new (& macro_name);
00239 
00240   macro->formal_count = 0;
00241   macro->formals = 0;
00242 
00243   sb_add_string (& macro->sub, semantics);
00244 
00245   if (arguments != NULL)
00246     {
00247       formal_entry ** p = &macro->formals;
00248 
00249       macro->formal_count = 0;
00250       macro->formal_hash = hash_new ();
00251 
00252       while (*arguments != NULL)
00253        {
00254          formal_entry *formal;
00255 
00256          formal = xmalloc (sizeof (formal_entry));
00257 
00258          sb_new (& formal->name);
00259          sb_new (& formal->def);
00260          sb_new (& formal->actual);
00261 
00262          /* chlm: Added the following to allow defaulted args.  */
00263          if (strchr (*arguments,'='))
00264            {
00265              char * tt_args = strdup (*arguments);
00266              char * tt_dflt = strchr (tt_args,'=');
00267 
00268              *tt_dflt = 0;
00269              sb_add_string (& formal->name, tt_args);
00270              sb_add_string (& formal->def,  tt_dflt + 1);
00271            }
00272          else
00273            sb_add_string (& formal->name, *arguments);
00274 
00275          /* Add to macro's hash table.  */
00276          hash_jam (macro->formal_hash, sb_terminate (& formal->name), formal);
00277 
00278          formal->index = macro->formal_count;
00279          macro->formal_count++;
00280          *p = formal;
00281          p = & formal->next;
00282          *p = NULL;
00283          ++arguments;
00284        }
00285     }
00286 
00287   sb_add_string (&macro_name, name);
00288   namestr = sb_terminate (&macro_name);
00289   hash_jam (macro_hash, namestr, macro);
00290 
00291   macro_defined = 1;
00292 }
00293 
00294 static void
00295 iq2000_load_macros (void)
00296 {
00297   int i;
00298   int mcnt = ARRAY_SIZE (iq2000_macro_defs);
00299 
00300   for (i = 0; i < mcnt; i++)
00301     iq2000_add_macro (iq2000_macro_defs[i].mnemonic,
00302                     *iq2000_macro_defs[i].expansion,
00303                     iq2000_macro_defs[i].args);
00304 }
00305 
00306 void
00307 md_begin (void)
00308 {
00309   /* Initialize the `cgen' interface.  */
00310 
00311   /* Set the machine number and endian.  */
00312   gas_cgen_cpu_desc = iq2000_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
00313                                       CGEN_CPU_OPEN_ENDIAN,
00314                                       CGEN_ENDIAN_BIG,
00315                                       CGEN_CPU_OPEN_END);
00316   iq2000_cgen_init_asm (gas_cgen_cpu_desc);
00317 
00318   /* This is a callback from cgen to gas to parse operands.  */
00319   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
00320 
00321   /* Set the ELF flags if desired.  */
00322   if (iq2000_flags)
00323     bfd_set_private_flags (stdoutput, iq2000_flags);
00324 
00325   /* Set the machine type */
00326   bfd_default_set_arch_mach (stdoutput, bfd_arch_iq2000, iq2000_mach);
00327 
00328   iq2000_load_macros ();
00329 }
00330 
00331 void
00332 md_assemble (char * str)
00333 {
00334   static long delayed_load_register = 0;
00335   static int last_insn_had_delay_slot = 0;
00336   static int last_insn_has_load_delay = 0;
00337   static int last_insn_unconditional_jump = 0;
00338   static int last_insn_was_ldw = 0;
00339 
00340   iq2000_insn insn;
00341   char * errmsg;
00342 
00343   /* Initialize GAS's cgen interface for a new instruction.  */
00344   gas_cgen_init_parse ();
00345 
00346   insn.insn = iq2000_cgen_assemble_insn
00347       (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
00348 
00349   if (!insn.insn)
00350     {
00351       as_bad ("%s", errmsg);
00352       return;
00353     }
00354 
00355   /* Doesn't really matter what we pass for RELAX_P here.  */
00356   gas_cgen_finish_insn (insn.insn, insn.buffer,
00357                      CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
00358 
00359   /* We need to generate an error if there's a yielding instruction in the delay
00360      slot of a control flow modifying instruction (jump (yes), load (no))  */
00361   if ((last_insn_had_delay_slot && !last_insn_has_load_delay) &&
00362       CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_YIELD_INSN))
00363       as_bad (_("the yielding instruction %s may not be in a delay slot."),
00364               CGEN_INSN_NAME (insn.insn));
00365 
00366   /* Warn about odd numbered base registers for paired-register
00367      instructions like LDW.  On iq2000, result is always rt.  */
00368   if (iq2000_mach == bfd_mach_iq2000
00369       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_EVEN_REG_NUM)
00370       && (insn.fields.f_rt % 2))
00371     as_bad (_("Register number (R%ld) for double word access must be even."),
00372            insn.fields.f_rt);
00373 
00374   /* Warn about insns that reference the target of a previous load.  */
00375   /* NOTE: R0 is a special case and is not subject to load delays (except for ldw).  */
00376   if (delayed_load_register && (last_insn_has_load_delay || last_insn_was_ldw))
00377     {
00378       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD) &&
00379          insn.fields.f_rd == delayed_load_register)
00380        as_warn (_("operand references R%ld of previous load."),
00381                insn.fields.f_rd);
00382 
00383       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS) &&
00384          insn.fields.f_rs == delayed_load_register)
00385        as_warn (_("operand references R%ld of previous load."),
00386                insn.fields.f_rs);
00387 
00388       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT) &&
00389          insn.fields.f_rt == delayed_load_register)
00390        as_warn (_("operand references R%ld of previous load."),
00391                insn.fields.f_rt);
00392 
00393       if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_R31) &&
00394          delayed_load_register == 31)
00395        as_warn (_("instruction implicitly accesses R31 of previous load."));
00396     }
00397 
00398   /* Warn about insns that reference the (target + 1) of a previous ldw.  */
00399   if (last_insn_was_ldw)
00400     {
00401       if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD)
00402            && insn.fields.f_rd == delayed_load_register + 1)
00403        || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS)
00404            && insn.fields.f_rs == delayed_load_register + 1)
00405        || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT)
00406            && insn.fields.f_rt == delayed_load_register + 1))
00407         as_warn (_("operand references R%ld of previous load."),
00408                 delayed_load_register + 1);
00409     }
00410 
00411   last_insn_had_delay_slot =
00412     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
00413 
00414   last_insn_has_load_delay =
00415     CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
00416 
00417   if (last_insn_unconditional_jump)
00418     last_insn_has_load_delay = last_insn_unconditional_jump = 0;
00419   else if (! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "j")
00420           || ! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "jal"))
00421           last_insn_unconditional_jump = 1;
00422 
00423   /* The meaning of EVEN_REG_NUM was overloaded to also imply LDW.  Since
00424      that's not true for IQ10, let's make the above logic specific to LDW.  */
00425   last_insn_was_ldw = ! strcmp ("ldw", CGEN_INSN_NAME (insn.insn));
00426 
00427   /* The assumption here is that the target of a load is always rt.  */
00428   delayed_load_register = insn.fields.f_rt;
00429 }
00430 
00431 valueT
00432 md_section_align (segT segment, valueT size)
00433 {
00434   int align = bfd_get_section_alignment (stdoutput, segment);
00435   return ((size + (1 << align) - 1) & (-1 << align));
00436 }
00437 
00438 symbolS *
00439 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
00440 {
00441     return 0;
00442 }
00443 
00444 /* Interface to relax_segment.  */
00445 
00446 /* Return an initial guess of the length by which a fragment must grow to
00447    hold a branch to reach its destination.
00448    Also updates fr_type/fr_subtype as necessary.
00449 
00450    Called just before doing relaxation.
00451    Any symbol that is now undefined will not become defined.
00452    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
00453    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
00454    Although it may not be explicit in the frag, pretend fr_var starts with a
00455    0 value.  */
00456 
00457 int
00458 md_estimate_size_before_relax (fragS * fragP,
00459                             segT    segment ATTRIBUTE_UNUSED)
00460 {
00461   int    old_fr_fix = fragP->fr_fix;
00462 
00463   /* The only thing we have to handle here are symbols outside of the
00464      current segment.  They may be undefined or in a different segment in
00465      which case linker scripts may place them anywhere.
00466      However, we can't finish the fragment here and emit the reloc as insn
00467      alignment requirements may move the insn about.  */
00468 
00469   return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
00470 }
00471 
00472 /* *fragP has been relaxed to its final size, and now needs to have
00473    the bytes inside it modified to conform to the new size.
00474 
00475    Called after relaxation is finished.
00476    fragP->fr_type == rs_machine_dependent.
00477    fragP->fr_subtype is the subtype of what the address relaxed to.  */
00478 
00479 void
00480 md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
00481                segT    sec   ATTRIBUTE_UNUSED,
00482                fragS * fragP ATTRIBUTE_UNUSED)
00483 {
00484 }
00485 
00486 
00487 /* Functions concerning relocs.  */
00488 
00489 long
00490 md_pcrel_from_section (fixS * fixP, segT sec)
00491 {
00492   if (fixP->fx_addsy != (symbolS *) NULL
00493       && (! S_IS_DEFINED (fixP->fx_addsy)
00494          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
00495     {
00496       /* The symbol is undefined (or is defined but not in this section).
00497         Let the linker figure it out.  */
00498       return 0;
00499     }
00500 
00501   /* Return the address of the delay slot.  */
00502   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
00503 }
00504 
00505 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
00506    Returns BFD_RELOC_NONE if no reloc type can be found.
00507    *FIXP may be modified if desired.  */
00508 
00509 bfd_reloc_code_real_type
00510 md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
00511                     const CGEN_OPERAND * operand,
00512                     fixS *               fixP     ATTRIBUTE_UNUSED)
00513 {
00514   switch (operand->type)
00515     {
00516     case IQ2000_OPERAND_OFFSET:      return BFD_RELOC_16_PCREL_S2;
00517     case IQ2000_OPERAND_JMPTARG:     return BFD_RELOC_IQ2000_OFFSET_16;
00518     case IQ2000_OPERAND_JMPTARGQ10:  return BFD_RELOC_NONE;
00519     case IQ2000_OPERAND_HI16:        return BFD_RELOC_HI16;
00520     case IQ2000_OPERAND_LO16:        return BFD_RELOC_LO16;
00521     default: break;
00522     }
00523 
00524   return BFD_RELOC_NONE;
00525 }
00526 
00527 /* Record a HI16 reloc for later matching with its LO16 cousin.  */
00528 
00529 static void
00530 iq2000_record_hi16 (int    reloc_type,
00531                   fixS * fixP,
00532                   segT   seg ATTRIBUTE_UNUSED)
00533 {
00534   struct iq2000_hi_fixup * hi_fixup;
00535 
00536   assert (reloc_type == BFD_RELOC_HI16);
00537 
00538   hi_fixup = xmalloc (sizeof * hi_fixup);
00539   hi_fixup->fixp = fixP;
00540   hi_fixup->seg  = now_seg;
00541   hi_fixup->next = iq2000_hi_fixup_list;
00542 
00543   iq2000_hi_fixup_list = hi_fixup;
00544 }
00545 
00546 /* Called while parsing an instruction to create a fixup.
00547    We need to check for HI16 relocs and queue them up for later sorting.  */
00548 
00549 fixS *
00550 iq2000_cgen_record_fixup_exp (fragS *              frag,
00551                            int                  where,
00552                            const CGEN_INSN *    insn,
00553                            int                  length,
00554                            const CGEN_OPERAND * operand,
00555                            int                  opinfo,
00556                            expressionS *        exp)
00557 {
00558   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
00559                                       operand, opinfo, exp);
00560 
00561   if (operand->type == IQ2000_OPERAND_HI16
00562       /* If low/high was used, it is recorded in `opinfo'.  */
00563       && (fixP->fx_cgen.opinfo == BFD_RELOC_HI16
00564          || fixP->fx_cgen.opinfo == BFD_RELOC_LO16))
00565     iq2000_record_hi16 (fixP->fx_cgen.opinfo, fixP, now_seg);
00566 
00567   return fixP;
00568 }
00569 
00570 /* Return BFD reloc type from opinfo field in a fixS.
00571    It's tricky using fx_r_type in iq2000_frob_file because the values
00572    are BFD_RELOC_UNUSED + operand number.  */
00573 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
00574 
00575 /* Sort any unmatched HI16 relocs so that they immediately precede
00576    the corresponding LO16 reloc.  This is called before md_apply_fix and
00577    tc_gen_reloc.  */
00578 
00579 void
00580 iq2000_frob_file (void)
00581 {
00582   struct iq2000_hi_fixup * l;
00583 
00584   for (l = iq2000_hi_fixup_list; l != NULL; l = l->next)
00585     {
00586       segment_info_type * seginfo;
00587       int                 pass;
00588 
00589       assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
00590              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
00591 
00592       /* Check quickly whether the next fixup happens to be a matching low.  */
00593       if (l->fixp->fx_next != NULL
00594          && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
00595          && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
00596          && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
00597        continue;
00598 
00599       /* Look through the fixups for this segment for a matching
00600          `low'.  When we find one, move the high just in front of it.
00601          We do this in two passes.  In the first pass, we try to find
00602          a unique `low'.  In the second pass, we permit multiple
00603          high's relocs for a single `low'.  */
00604       seginfo = seg_info (l->seg);
00605       for (pass = 0; pass < 2; pass++)
00606        {
00607          fixS * f;
00608          fixS * prev;
00609 
00610          prev = NULL;
00611          for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
00612            {
00613              /* Check whether this is a `low' fixup which matches l->fixp.  */
00614              if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
00615                 && f->fx_addsy == l->fixp->fx_addsy
00616                 && f->fx_offset == l->fixp->fx_offset
00617                 && (pass == 1
00618                     || prev == NULL
00619                     || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
00620                     || prev->fx_addsy != f->fx_addsy
00621                     || prev->fx_offset !=  f->fx_offset))
00622               {
00623                 fixS ** pf;
00624 
00625                 /* Move l->fixp before f.  */
00626                 for (pf = &seginfo->fix_root;
00627                      * pf != l->fixp;
00628                      pf = & (* pf)->fx_next)
00629                   assert (* pf != NULL);
00630 
00631                 * pf = l->fixp->fx_next;
00632 
00633                 l->fixp->fx_next = f;
00634                 if (prev == NULL)
00635                   seginfo->fix_root = l->fixp;
00636                 else
00637                   prev->fx_next = l->fixp;
00638 
00639                 break;
00640               }
00641 
00642              prev = f;
00643            }
00644 
00645          if (f != NULL)
00646            break;
00647 
00648          if (pass == 1)
00649            as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
00650                         _("Unmatched high relocation"));
00651        }
00652     }
00653 }
00654 
00655 /* See whether we need to force a relocation into the output file.  */
00656 
00657 int
00658 iq2000_force_relocation (fixS * fix)
00659 {
00660   if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
00661       || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
00662     return 1;
00663 
00664   return 0;
00665 }
00666 
00667 /* Handle the .set pseudo-op.  */
00668 
00669 static void
00670 s_iq2000_set (int x ATTRIBUTE_UNUSED)
00671 {
00672   static const char * ignored_arguments [] =
00673     {
00674       "reorder",
00675       "noreorder",
00676       "at",
00677       "noat",
00678       "macro",
00679       "nomacro",
00680       "move",
00681       "novolatile",
00682       "nomove",
00683       "volatile",
00684       "bopt",
00685       "nobopt",
00686       NULL
00687     };
00688   const char ** ignored;
00689   char *name = input_line_pointer, ch;
00690   char *save_ILP = input_line_pointer;
00691 
00692   while (!is_end_of_line[(unsigned char) *input_line_pointer])
00693     input_line_pointer++;
00694   ch = *input_line_pointer;
00695   *input_line_pointer = '\0';
00696 
00697   for (ignored = ignored_arguments; * ignored; ignored ++)
00698     if (strcmp (* ignored, name) == 0)
00699       break;
00700   if (* ignored == NULL)
00701     {
00702       /* We'd like to be able to use .set symbol, expn */
00703       input_line_pointer = save_ILP;
00704       s_set (0);
00705       return;
00706     }
00707   *input_line_pointer = ch;
00708   demand_empty_rest_of_line ();
00709 }
00710 
00711 /* Write a value out to the object file, using the appropriate endianness.  */
00712 
00713 void
00714 md_number_to_chars (char * buf, valueT val, int n)
00715 {
00716   number_to_chars_bigendian (buf, val, n);
00717 }
00718 
00719 void
00720 md_operand (expressionS * exp)
00721 {
00722   /* In case of a syntax error, escape back to try next syntax combo.  */
00723   if (exp->X_op == O_absent)
00724     gas_cgen_md_operand (exp);
00725 }
00726 
00727 /* Turn a string in input_line_pointer into a floating point constant
00728    of type type, and store the appropriate bytes in *litP.  The number
00729    of LITTLENUMS emitted is stored in *sizeP .  An error message is
00730    returned, or NULL on OK.  */
00731 
00732 /* Equal to MAX_PRECISION in atof-ieee.c */
00733 #define MAX_LITTLENUMS 6
00734 
00735 char *
00736 md_atof (int type, char * litP, int * sizeP)
00737 {
00738   int              i;
00739   int              prec;
00740   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
00741   char *           t;
00742 
00743   switch (type)
00744     {
00745     case 'f':
00746     case 'F':
00747     case 's':
00748     case 'S':
00749       prec = 2;
00750       break;
00751 
00752     case 'd':
00753     case 'D':
00754     case 'r':
00755     case 'R':
00756       prec = 4;
00757       break;
00758 
00759    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
00760 
00761     default:
00762       * sizeP = 0;
00763       return _("Bad call to md_atof()");
00764     }
00765 
00766   t = atof_ieee (input_line_pointer, type, words);
00767   if (t)
00768     input_line_pointer = t;
00769   * sizeP = prec * sizeof (LITTLENUM_TYPE);
00770 
00771   for (i = 0; i < prec; i++)
00772     {
00773       md_number_to_chars (litP, (valueT) words[i],
00774                        sizeof (LITTLENUM_TYPE));
00775       litP += sizeof (LITTLENUM_TYPE);
00776     }
00777 
00778   return 0;
00779 }
00780 
00781 
00782 bfd_boolean
00783 iq2000_fix_adjustable (fixS * fixP)
00784 {
00785   bfd_reloc_code_real_type reloc_type;
00786 
00787   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
00788     {
00789       const CGEN_INSN *insn = NULL;
00790       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
00791       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
00792 
00793       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
00794     }
00795   else
00796     reloc_type = fixP->fx_r_type;
00797 
00798   if (fixP->fx_addsy == NULL)
00799     return TRUE;
00800 
00801   /* Prevent all adjustments to global symbols.  */
00802   if (S_IS_EXTERNAL (fixP->fx_addsy))
00803     return FALSE;
00804 
00805   if (S_IS_WEAK (fixP->fx_addsy))
00806     return FALSE;
00807 
00808   /* We need the symbol name for the VTABLE entries.  */
00809   if (   reloc_type == BFD_RELOC_VTABLE_INHERIT
00810       || reloc_type == BFD_RELOC_VTABLE_ENTRY)
00811     return FALSE;
00812 
00813   return TRUE;
00814 }
00815 
00816 static void
00817 s_change_sec (int sec)
00818 {
00819 #ifdef OBJ_ELF
00820   /* The ELF backend needs to know that we are changing sections, so
00821      that .previous works correctly.  We could do something like check
00822      for a obj_section_change_hook macro, but that might be confusing
00823      as it would not be appropriate to use it in the section changing
00824      functions in read.c, since obj-elf.c intercepts those.  FIXME:
00825      This should be cleaner, somehow.  */
00826   obj_elf_section_change_hook ();
00827 #endif
00828 
00829   switch (sec)
00830     {
00831     case 't':
00832       s_text (0);
00833       break;
00834     case 'd':
00835     case 'r':
00836       s_data (0);
00837       break;
00838     }
00839 }
00840 
00841 static symbolS *
00842 get_symbol (void)
00843 {
00844   int c;
00845   char *name;
00846   symbolS *p;
00847 
00848   name = input_line_pointer;
00849   c = get_symbol_end ();
00850   p = (symbolS *) symbol_find_or_make (name);
00851   *input_line_pointer = c;
00852   return p;
00853 }
00854 
00855 /* The .end directive.  */
00856 
00857 static void
00858 s_iq2000_end (int x ATTRIBUTE_UNUSED)
00859 {
00860   symbolS *p;
00861   int maybe_text;
00862 
00863   if (!is_end_of_line[(unsigned char) *input_line_pointer])
00864     {
00865       p = get_symbol ();
00866       demand_empty_rest_of_line ();
00867     }
00868   else
00869     p = NULL;
00870 
00871   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
00872     maybe_text = 1;
00873   else
00874     maybe_text = 0;
00875 
00876   if (!maybe_text)
00877     as_warn (_(".end not in text section"));
00878 
00879   if (!cur_proc_ptr)
00880     {
00881       as_warn (_(".end directive without a preceding .ent directive."));
00882       demand_empty_rest_of_line ();
00883       return;
00884     }
00885 
00886   if (p != NULL)
00887     {
00888       assert (S_GET_NAME (p));
00889       if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
00890        as_warn (_(".end symbol does not match .ent symbol."));
00891     }
00892   else
00893     as_warn (_(".end directive missing or unknown symbol"));
00894 
00895   cur_proc_ptr = NULL;
00896 }
00897 
00898 static int
00899 get_number (void)
00900 {
00901   int negative = 0;
00902   long val = 0;
00903 
00904   if (*input_line_pointer == '-')
00905     {
00906       ++input_line_pointer;
00907       negative = 1;
00908     }
00909 
00910   if (! ISDIGIT (*input_line_pointer))
00911     as_bad (_("Expected simple number."));
00912 
00913   if (input_line_pointer[0] == '0')
00914     {
00915       if (input_line_pointer[1] == 'x')
00916        {
00917          input_line_pointer += 2;
00918          while (ISXDIGIT (*input_line_pointer))
00919            {
00920              val <<= 4;
00921              val |= hex_value (*input_line_pointer++);
00922            }
00923          return negative ? -val : val;
00924        }
00925       else
00926        {
00927          ++input_line_pointer;
00928 
00929          while (ISDIGIT (*input_line_pointer))
00930            {
00931              val <<= 3;
00932              val |= *input_line_pointer++ - '0';
00933            }
00934          return negative ? -val : val;
00935        }
00936     }
00937 
00938   if (! ISDIGIT (*input_line_pointer))
00939     {
00940       printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
00941              *input_line_pointer, *input_line_pointer);
00942       as_warn (_("Invalid number"));
00943       return -1;
00944     }
00945 
00946   while (ISDIGIT (*input_line_pointer))
00947     {
00948       val *= 10;
00949       val += *input_line_pointer++ - '0';
00950     }
00951 
00952   return negative ? -val : val;
00953 }
00954 
00955 /* The .aent and .ent directives.  */
00956 
00957 static void
00958 s_iq2000_ent (int aent)
00959 {
00960   int number = 0;
00961   symbolS *symbolP;
00962   int maybe_text;
00963 
00964   symbolP = get_symbol ();
00965   if (*input_line_pointer == ',')
00966     input_line_pointer++;
00967   SKIP_WHITESPACE ();
00968   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
00969     number = get_number ();
00970 
00971   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
00972     maybe_text = 1;
00973   else
00974     maybe_text = 0;
00975 
00976   if (!maybe_text)
00977     as_warn (_(".ent or .aent not in text section."));
00978 
00979   if (!aent && cur_proc_ptr)
00980     as_warn (_("missing `.end'"));
00981 
00982   if (!aent)
00983     {
00984       cur_proc_ptr = &cur_proc;
00985       memset (cur_proc_ptr, '\0', sizeof (procS));
00986 
00987       cur_proc_ptr->isym = symbolP;
00988 
00989       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
00990 
00991       numprocs++;
00992     }
00993 
00994   demand_empty_rest_of_line ();
00995 }
00996 
00997 /* The .frame directive. If the mdebug section is present (IRIX 5 native)
00998    then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
00999    s_iq2000_frame is used so that we can set the PDR information correctly.
01000    We can't use the ecoff routines because they make reference to the ecoff
01001    symbol table (in the mdebug section).  */
01002 
01003 static void
01004 s_iq2000_frame (int ignore)
01005 {
01006   s_ignore (ignore);
01007 }
01008 
01009 /* The .fmask and .mask directives. If the mdebug section is present
01010    (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
01011    embedded targets, s_iq2000_mask is used so that we can set the PDR
01012    information correctly. We can't use the ecoff routines because they
01013    make reference to the ecoff symbol table (in the mdebug section).  */
01014 
01015 static void
01016 s_iq2000_mask (int reg_type)
01017 {
01018   s_ignore (reg_type);
01019 }
01020 
01021 /* The target specific pseudo-ops which we support.  */
01022 const pseudo_typeS md_pseudo_table[] =
01023 {
01024     { "align",  s_align_bytes,           0 },
01025     { "word",   cons,                    4 },
01026     { "rdata",  s_change_sec,             'r'},
01027     { "sdata",  s_change_sec,             's'},
01028     { "set",  s_iq2000_set,         0 },
01029     { "ent",    s_iq2000_ent,              0 },
01030     { "end",    s_iq2000_end,            0 },
01031     { "frame",  s_iq2000_frame,     0 },
01032     { "fmask",  s_iq2000_mask,            'F'},
01033     { "mask",   s_iq2000_mask,            'R'},
01034     { "dword",       cons,                 8 },
01035     { "half", cons,                 2 },
01036     { NULL,   NULL,                 0 }
01037 };