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