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