]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-iq2000.c
Typo fix.
[thirdparty/binutils-gdb.git] / gas / config / tc-iq2000.c
CommitLineData
1c53c80d 1/* tc-iq2000.c -- Assembler for the Sitera IQ2000.
ebd1c875 2 Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation.
1c53c80d
SC
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 2, 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
4b4da160
NC
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
1c53c80d 20
1c53c80d
SC
21#include "as.h"
22#include "safe-ctype.h"
5515a510 23#include "subsegs.h"
1c53c80d
SC
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"
1c53c80d
SC
31#include "macro.h"
32
33/* Structure to hold all of the different components describing
34 an individual instruction. */
35typedef 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}
53iq2000_insn;
54
55const char comment_chars[] = "#";
406a7f05 56const char line_comment_chars[] = "#";
5515a510 57const char line_separator_chars[] = ";";
1c53c80d
SC
58const char EXP_CHARS[] = "eE";
59const char FLT_CHARS[] = "dD";
60
5515a510 61/* Default machine. */
1c53c80d
SC
62#define DEFAULT_MACHINE bfd_mach_iq2000
63#define DEFAULT_FLAGS EF_IQ2000_CPU_IQ2000
64
65static unsigned long iq2000_mach = bfd_mach_iq2000;
66static int cpu_mach = (1 << MACH_IQ2000);
67
5515a510 68/* Flags to set in the elf header. */
1c53c80d
SC
69static flagword iq2000_flags = DEFAULT_FLAGS;
70
5515a510
NC
71typedef struct proc
72{
1c53c80d
SC
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
83static procS cur_proc;
84static procS *cur_proc_ptr;
85static int numprocs;
86
1c53c80d
SC
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
98struct iq2000_hi_fixup
99{
100 struct iq2000_hi_fixup * next; /* Next HI fixup. */
5515a510
NC
101 fixS * fixp; /* This fixup. */
102 segT seg; /* The section this fixup is in. */
1c53c80d
SC
103};
104
105/* The list of unmatched HI relocs. */
106static struct iq2000_hi_fixup * iq2000_hi_fixup_list;
107
5515a510
NC
108/* Macro hash table, which we will add to. */
109extern struct hash_control *macro_hash;
1c53c80d 110\f
5515a510 111const char *md_shortopts = "";
1c53c80d 112struct option md_longopts[] =
5515a510
NC
113{
114 {NULL, no_argument, NULL, 0}
1c53c80d 115};
1c53c80d
SC
116size_t md_longopts_size = sizeof (md_longopts);
117
1c53c80d 118int
5515a510
NC
119md_parse_option (int c ATTRIBUTE_UNUSED,
120 char * arg ATTRIBUTE_UNUSED)
1c53c80d 121{
5515a510 122 return 0;
1c53c80d
SC
123}
124
125void
5515a510 126md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
1c53c80d 127{
1c53c80d 128}
5515a510 129\f
1c53c80d
SC
130/* Automatically enter conditional branch macros. */
131
5515a510
NC
132typedef struct
133{
1c53c80d
SC
134 const char * mnemonic;
135 const char ** expansion;
136 const char ** args;
137} iq2000_macro_defs_s;
138
139static const char * abs_args[] = { "rd", "rs", "scratch=%1", NULL };
140static const char * abs_expn = "\n sra \\rd,\\rs,31\n xor \\scratch,\\rd,\\rs\n sub \\rd,\\scratch,\\rd\n";
1c53c80d
SC
141static const char * la_expn = "\n lui \\reg,%hi(\\label)\n ori \\reg,\\reg,%lo(\\label)\n";
142static const char * la_args[] = { "reg", "label", NULL };
1c53c80d
SC
143static const char * bxx_args[] = { "rs", "rt", "label", "scratch=%1", NULL };
144static const char * bge_expn = "\n slt \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
145static const char * bgeu_expn = "\n sltu \\scratch,\\rs,\\rt\n beq %0,\\scratch,\\label\n";
146static const char * bgt_expn = "\n slt \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
147static const char * bgtu_expn = "\n sltu \\scratch,\\rt,\\rs\n bne %0,\\scratch,\\label\n";
148static const char * ble_expn = "\n slt \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
149static const char * bleu_expn = "\n sltu \\scratch,\\rt,\\rs\n beq %0,\\scratch,\\label\n";
150static const char * blt_expn = "\n slt \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
151static const char * bltu_expn = "\n sltu \\scratch,\\rs,\\rt\n bne %0,\\scratch,\\label\n";
1c53c80d
SC
152static const char * sxx_args[] = { "rd", "rs", "rt", NULL };
153static const char * sge_expn = "\n slt \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
154static const char * sgeu_expn = "\n sltu \\rd,\\rs,\\rt\n xori \\rd,\\rd,1\n";
155static const char * sle_expn = "\n slt \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
156static const char * sleu_expn = "\n sltu \\rd,\\rt,\\rs\n xori \\rd,\\rd,1\n";
157static const char * sgt_expn = "\n slt \\rd,\\rt,\\rs\n";
158static const char * sgtu_expn = "\n sltu \\rd,\\rt,\\rs\n";
159static const char * sne_expn = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n";
160static const char * seq_expn = "\n xor \\rd,\\rt,\\rs\n sltu \\rd,%0,\\rd\n xori \\rd,\\rd,1\n";
1c53c80d
SC
161static const char * ai32_args[] = { "rt", "rs", "imm", NULL };
162static 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";
173static 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
183static const char * neg_args[] = { "rd", "rs", NULL };
184static const char * neg_expn = "\n sub \\rd,%0,\\rs\n";
185static const char * negu_expn = "\n subu \\rd,%0,\\rs\n";
1c53c80d
SC
186static const char * li_args[] = { "rt", "imm", NULL };
187static 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\
95385380 192 .elseif (\\imm & 0x0000ffff == 0)\n\
1c53c80d
SC
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";
5515a510
NC
198
199static 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},
1c53c80d
SC
224};
225
226static void
5515a510
NC
227iq2000_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 = xmalloc (sizeof (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 = xmalloc (sizeof (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
293static void
294iq2000_load_macros (void)
1c53c80d
SC
295{
296 int i;
5515a510 297 int mcnt = ARRAY_SIZE (iq2000_macro_defs);
1c53c80d
SC
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
5515a510
NC
305void
306md_begin (void)
1c53c80d 307{
5515a510 308 /* Initialize the `cgen' interface. */
1c53c80d 309
5515a510
NC
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);
1c53c80d 316
5515a510
NC
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);
1c53c80d 323
5515a510
NC
324 /* Set the machine type */
325 bfd_default_set_arch_mach (stdoutput, bfd_arch_iq2000, iq2000_mach);
326
327 iq2000_load_macros ();
328}
1c53c80d
SC
329
330void
5515a510 331md_assemble (char * str)
1c53c80d
SC
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
5515a510
NC
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)) */
1c53c80d
SC
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
5515a510 366 instructions like LDW. On iq2000, result is always rt. */
1c53c80d
SC
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
1c53c80d
SC
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);
5515a510 381
1c53c80d
SC
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);
5515a510 386
1c53c80d
SC
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);
5515a510 391
1c53c80d
SC
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
5515a510
NC
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 }
1c53c80d
SC
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
5515a510
NC
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. */
1c53c80d
SC
424 last_insn_was_ldw = ! strcmp ("ldw", CGEN_INSN_NAME (insn.insn));
425
5515a510 426 /* The assumption here is that the target of a load is always rt. */
1c53c80d
SC
427 delayed_load_register = insn.fields.f_rt;
428}
429
430valueT
5515a510 431md_section_align (segT segment, valueT size)
1c53c80d
SC
432{
433 int align = bfd_get_section_alignment (stdoutput, segment);
434 return ((size + (1 << align) - 1) & (-1 << align));
435}
436
1c53c80d 437symbolS *
5515a510 438md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1c53c80d
SC
439{
440 return 0;
441}
442\f
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
456int
5515a510
NC
457md_estimate_size_before_relax (fragS * fragP,
458 segT segment ATTRIBUTE_UNUSED)
1c53c80d
SC
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);
5515a510 469}
1c53c80d
SC
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
478void
5515a510
NC
479md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
480 segT sec ATTRIBUTE_UNUSED,
481 fragS * fragP ATTRIBUTE_UNUSED)
1c53c80d
SC
482{
483}
484
485\f
486/* Functions concerning relocs. */
487
488long
5515a510 489md_pcrel_from_section (fixS * fixP, segT sec)
1c53c80d
SC
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
5515a510 500 /* Return the address of the delay slot. */
1c53c80d
SC
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
508bfd_reloc_code_real_type
5515a510
NC
509md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED,
510 const CGEN_OPERAND * operand,
511 fixS * fixP ATTRIBUTE_UNUSED)
1c53c80d
SC
512{
513 switch (operand->type)
514 {
5515a510
NC
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;
1c53c80d
SC
521 }
522
523 return BFD_RELOC_NONE;
524}
525
526/* Record a HI16 reloc for later matching with its LO16 cousin. */
527
528static void
5515a510
NC
529iq2000_record_hi16 (int reloc_type,
530 fixS * fixP,
531 segT seg ATTRIBUTE_UNUSED)
1c53c80d
SC
532{
533 struct iq2000_hi_fixup * hi_fixup;
534
535 assert (reloc_type == BFD_RELOC_HI16);
536
5515a510 537 hi_fixup = xmalloc (sizeof * hi_fixup);
1c53c80d
SC
538 hi_fixup->fixp = fixP;
539 hi_fixup->seg = now_seg;
540 hi_fixup->next = iq2000_hi_fixup_list;
5515a510 541
1c53c80d
SC
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
548fixS *
5515a510
NC
549iq2000_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)
1c53c80d
SC
556{
557 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
558 operand, opinfo, exp);
559
5515a510 560 if (operand->type == IQ2000_OPERAND_HI16
1c53c80d 561 /* If low/high was used, it is recorded in `opinfo'. */
5515a510
NC
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);
1c53c80d
SC
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
55cf6793 575 the corresponding LO16 reloc. This is called before md_apply_fix and
1c53c80d
SC
576 tc_gen_reloc. */
577
578void
5515a510 579iq2000_frob_file (void)
1c53c80d
SC
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;
5515a510 587
1c53c80d
SC
588 assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
589 || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
5515a510 590
1c53c80d
SC
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 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
656int
5515a510 657iq2000_force_relocation (fixS * fix)
1c53c80d
SC
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\f
666/* Handle the .set pseudo-op. */
667
668static void
5515a510 669s_iq2000_set (int x ATTRIBUTE_UNUSED)
1c53c80d 670{
5515a510
NC
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 };
b8b80cf7 687 const char ** ignored;
1c53c80d
SC
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
b8b80cf7
NC
696 for (ignored = ignored_arguments; * ignored; ignored ++)
697 if (strcmp (* ignored, name) == 0)
5515a510 698 break;
b8b80cf7 699 if (* ignored == NULL)
1c53c80d
SC
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;
1c53c80d
SC
705 }
706 *input_line_pointer = ch;
707 demand_empty_rest_of_line ();
708}
709\f
710/* Write a value out to the object file, using the appropriate endianness. */
711
712void
5515a510 713md_number_to_chars (char * buf, valueT val, int n)
1c53c80d
SC
714{
715 number_to_chars_bigendian (buf, val, n);
716}
717
718void
5515a510 719md_operand (expressionS * exp)
1c53c80d 720{
5515a510 721 /* In case of a syntax error, escape back to try next syntax combo. */
1c53c80d
SC
722 if (exp->X_op == O_absent)
723 gas_cgen_md_operand (exp);
724}
725
726/* Turn a string in input_line_pointer into a floating point constant
727 of type type, and store the appropriate bytes in *litP. The number
728 of LITTLENUMS emitted is stored in *sizeP . An error message is
729 returned, or NULL on OK. */
730
731/* Equal to MAX_PRECISION in atof-ieee.c */
732#define MAX_LITTLENUMS 6
733
734char *
5515a510 735md_atof (int type, char * litP, int * sizeP)
1c53c80d
SC
736{
737 int i;
738 int prec;
739 LITTLENUM_TYPE words [MAX_LITTLENUMS];
740 char * t;
1c53c80d
SC
741
742 switch (type)
743 {
744 case 'f':
745 case 'F':
746 case 's':
747 case 'S':
748 prec = 2;
749 break;
750
751 case 'd':
752 case 'D':
753 case 'r':
754 case 'R':
755 prec = 4;
756 break;
757
758 /* FIXME: Some targets allow other format chars for bigger sizes here. */
759
760 default:
761 * sizeP = 0;
762 return _("Bad call to md_atof()");
763 }
764
765 t = atof_ieee (input_line_pointer, type, words);
766 if (t)
767 input_line_pointer = t;
768 * sizeP = prec * sizeof (LITTLENUM_TYPE);
5515a510 769
1c53c80d
SC
770 for (i = 0; i < prec; i++)
771 {
772 md_number_to_chars (litP, (valueT) words[i],
773 sizeof (LITTLENUM_TYPE));
774 litP += sizeof (LITTLENUM_TYPE);
775 }
776
777 return 0;
778}
779
780
781bfd_boolean
5515a510 782iq2000_fix_adjustable (fixS * fixP)
1c53c80d
SC
783{
784 bfd_reloc_code_real_type reloc_type;
785
786 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
787 {
788 const CGEN_INSN *insn = NULL;
789 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
790 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
5515a510 791
1c53c80d
SC
792 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
793 }
794 else
795 reloc_type = fixP->fx_r_type;
796
797 if (fixP->fx_addsy == NULL)
798 return TRUE;
5515a510 799
1c53c80d 800 /* Prevent all adjustments to global symbols. */
e97b3f28 801 if (S_IS_EXTERNAL (fixP->fx_addsy))
1c53c80d 802 return FALSE;
5515a510 803
1c53c80d
SC
804 if (S_IS_WEAK (fixP->fx_addsy))
805 return FALSE;
5515a510 806
1c53c80d
SC
807 /* We need the symbol name for the VTABLE entries. */
808 if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
809 || reloc_type == BFD_RELOC_VTABLE_ENTRY)
810 return FALSE;
811
812 return TRUE;
813}
814
815static void
5515a510 816s_change_sec (int sec)
1c53c80d 817{
1c53c80d
SC
818#ifdef OBJ_ELF
819 /* The ELF backend needs to know that we are changing sections, so
820 that .previous works correctly. We could do something like check
821 for a obj_section_change_hook macro, but that might be confusing
822 as it would not be appropriate to use it in the section changing
823 functions in read.c, since obj-elf.c intercepts those. FIXME:
824 This should be cleaner, somehow. */
825 obj_elf_section_change_hook ();
826#endif
827
1c53c80d
SC
828 switch (sec)
829 {
830 case 't':
831 s_text (0);
832 break;
833 case 'd':
834 case 'r':
835 s_data (0);
836 break;
837 }
838}
839
5515a510
NC
840static symbolS *
841get_symbol (void)
842{
843 int c;
844 char *name;
845 symbolS *p;
846
847 name = input_line_pointer;
848 c = get_symbol_end ();
849 p = (symbolS *) symbol_find_or_make (name);
850 *input_line_pointer = c;
851 return p;
852}
853
1c53c80d
SC
854/* The .end directive. */
855
856static void
5515a510 857s_iq2000_end (int x ATTRIBUTE_UNUSED)
1c53c80d
SC
858{
859 symbolS *p;
860 int maybe_text;
861
862 if (!is_end_of_line[(unsigned char) *input_line_pointer])
863 {
864 p = get_symbol ();
865 demand_empty_rest_of_line ();
866 }
867 else
868 p = NULL;
869
5515a510
NC
870 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
871 maybe_text = 1;
872 else
873 maybe_text = 0;
1c53c80d 874
5515a510
NC
875 if (!maybe_text)
876 as_warn (_(".end not in text section"));
1c53c80d 877
5515a510
NC
878 if (!cur_proc_ptr)
879 {
880 as_warn (_(".end directive without a preceding .ent directive."));
881 demand_empty_rest_of_line ();
882 return;
883 }
1c53c80d 884
5515a510 885 if (p != NULL)
1c53c80d 886 {
5515a510
NC
887 assert (S_GET_NAME (p));
888 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
889 as_warn (_(".end symbol does not match .ent symbol."));
1c53c80d
SC
890 }
891 else
5515a510 892 as_warn (_(".end directive missing or unknown symbol"));
1c53c80d 893
5515a510 894 cur_proc_ptr = NULL;
1c53c80d
SC
895}
896
897static int
5515a510 898get_number (void)
1c53c80d
SC
899{
900 int negative = 0;
901 long val = 0;
902
903 if (*input_line_pointer == '-')
904 {
905 ++input_line_pointer;
906 negative = 1;
907 }
908
909 if (! ISDIGIT (*input_line_pointer))
910 as_bad (_("Expected simple number."));
911
912 if (input_line_pointer[0] == '0')
913 {
914 if (input_line_pointer[1] == 'x')
915 {
916 input_line_pointer += 2;
917 while (ISXDIGIT (*input_line_pointer))
918 {
919 val <<= 4;
920 val |= hex_value (*input_line_pointer++);
921 }
922 return negative ? -val : val;
923 }
924 else
925 {
926 ++input_line_pointer;
927
928 while (ISDIGIT (*input_line_pointer))
929 {
930 val <<= 3;
931 val |= *input_line_pointer++ - '0';
932 }
933 return negative ? -val : val;
934 }
935 }
936
937 if (! ISDIGIT (*input_line_pointer))
938 {
939 printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
940 *input_line_pointer, *input_line_pointer);
941 as_warn (_("Invalid number"));
942 return -1;
943 }
944
945 while (ISDIGIT (*input_line_pointer))
946 {
947 val *= 10;
948 val += *input_line_pointer++ - '0';
949 }
950
951 return negative ? -val : val;
952}
953
5515a510
NC
954/* The .aent and .ent directives. */
955
956static void
957s_iq2000_ent (int aent)
958{
959 int number = 0;
960 symbolS *symbolP;
961 int maybe_text;
962
963 symbolP = get_symbol ();
964 if (*input_line_pointer == ',')
965 input_line_pointer++;
966 SKIP_WHITESPACE ();
967 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
968 number = get_number ();
969
970 if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
971 maybe_text = 1;
972 else
973 maybe_text = 0;
974
975 if (!maybe_text)
976 as_warn (_(".ent or .aent not in text section."));
977
978 if (!aent && cur_proc_ptr)
979 as_warn (_("missing `.end'"));
980
981 if (!aent)
982 {
983 cur_proc_ptr = &cur_proc;
984 memset (cur_proc_ptr, '\0', sizeof (procS));
985
986 cur_proc_ptr->isym = symbolP;
987
988 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
989
990 numprocs++;
991 }
992
993 demand_empty_rest_of_line ();
994}
995
996/* The .frame directive. If the mdebug section is present (IRIX 5 native)
997 then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
998 s_iq2000_frame is used so that we can set the PDR information correctly.
999 We can't use the ecoff routines because they make reference to the ecoff
1000 symbol table (in the mdebug section). */
1001
1002static void
1003s_iq2000_frame (int ignore)
1004{
1005 s_ignore (ignore);
1006}
1007
1008/* The .fmask and .mask directives. If the mdebug section is present
1009 (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
1010 embedded targets, s_iq2000_mask is used so that we can set the PDR
1011 information correctly. We can't use the ecoff routines because they
1012 make reference to the ecoff symbol table (in the mdebug section). */
1013
1014static void
1015s_iq2000_mask (int reg_type)
1016{
1017 s_ignore (reg_type);
1018}
1019
1020/* The target specific pseudo-ops which we support. */
1021const pseudo_typeS md_pseudo_table[] =
1022{
1023 { "align", s_align_bytes, 0 },
1024 { "word", cons, 4 },
1025 { "rdata", s_change_sec, 'r'},
1026 { "sdata", s_change_sec, 's'},
1027 { "set", s_iq2000_set, 0 },
1028 { "ent", s_iq2000_ent, 0 },
1029 { "end", s_iq2000_end, 0 },
1030 { "frame", s_iq2000_frame, 0 },
1031 { "fmask", s_iq2000_mask, 'F'},
1032 { "mask", s_iq2000_mask, 'R'},
1033 { "dword", cons, 8 },
1034 { "half", cons, 2 },
1035 { NULL, NULL, 0 }
1036};