]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-iq2000.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-iq2000.c
CommitLineData
1c53c80d 1/* tc-iq2000.c -- Assembler for the Sitera IQ2000.
fd67aa11 2 Copyright (C) 2003-2024 Free Software Foundation, Inc.
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
ec2655a6 8 the Free Software Foundation; either version 3, or (at your option)
1c53c80d
SC
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"
96f989c2 30#include "sb.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 108/* Macro hash table, which we will add to. */
2b272f44 109extern struct htab *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 119md_parse_option (int c ATTRIBUTE_UNUSED,
17b9d67d 120 const 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;
5515a510 232
325801bd 233 macro = XNEW (macro_entry);
c026360c 234 macro->name = xstrdup (name);
5515a510 235 sb_new (& macro->sub);
5515a510
NC
236 macro->formal_count = 0;
237 macro->formals = 0;
c026360c
AM
238 macro->formal_hash = str_htab_create ();
239 macro->file = as_where (&macro->line);
5515a510
NC
240
241 sb_add_string (& macro->sub, semantics);
242
243 if (arguments != NULL)
244 {
245 formal_entry ** p = &macro->formals;
246
5515a510
NC
247 while (*arguments != NULL)
248 {
249 formal_entry *formal;
250
325801bd 251 formal = XNEW (formal_entry);
5515a510
NC
252
253 sb_new (& formal->name);
254 sb_new (& formal->def);
255 sb_new (& formal->actual);
256
257 /* chlm: Added the following to allow defaulted args. */
258 if (strchr (*arguments,'='))
259 {
c026360c 260 char * tt_args = xstrdup (*arguments);
5515a510
NC
261 char * tt_dflt = strchr (tt_args,'=');
262
263 *tt_dflt = 0;
264 sb_add_string (& formal->name, tt_args);
265 sb_add_string (& formal->def, tt_dflt + 1);
266 }
267 else
268 sb_add_string (& formal->name, *arguments);
269
270 /* Add to macro's hash table. */
bdcc1de1
AM
271 str_hash_insert (macro->formal_hash,
272 sb_terminate (&formal->name), formal, 1);
5515a510
NC
273 formal->index = macro->formal_count;
274 macro->formal_count++;
275 *p = formal;
276 p = & formal->next;
277 *p = NULL;
278 ++arguments;
279 }
280 }
281
c026360c 282 str_hash_insert (macro_hash, macro->name, macro, 1);
5515a510
NC
283
284 macro_defined = 1;
285}
286
287static void
288iq2000_load_macros (void)
1c53c80d
SC
289{
290 int i;
5515a510 291 int mcnt = ARRAY_SIZE (iq2000_macro_defs);
1c53c80d
SC
292
293 for (i = 0; i < mcnt; i++)
294 iq2000_add_macro (iq2000_macro_defs[i].mnemonic,
295 *iq2000_macro_defs[i].expansion,
296 iq2000_macro_defs[i].args);
297}
298
5515a510
NC
299void
300md_begin (void)
1c53c80d 301{
5515a510 302 /* Initialize the `cgen' interface. */
1c53c80d 303
5515a510
NC
304 /* Set the machine number and endian. */
305 gas_cgen_cpu_desc = iq2000_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, cpu_mach,
306 CGEN_CPU_OPEN_ENDIAN,
307 CGEN_ENDIAN_BIG,
308 CGEN_CPU_OPEN_END);
309 iq2000_cgen_init_asm (gas_cgen_cpu_desc);
1c53c80d 310
5515a510
NC
311 /* This is a callback from cgen to gas to parse operands. */
312 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
313
314 /* Set the ELF flags if desired. */
315 if (iq2000_flags)
316 bfd_set_private_flags (stdoutput, iq2000_flags);
1c53c80d 317
5515a510
NC
318 /* Set the machine type */
319 bfd_default_set_arch_mach (stdoutput, bfd_arch_iq2000, iq2000_mach);
320
321 iq2000_load_macros ();
322}
1c53c80d
SC
323
324void
5515a510 325md_assemble (char * str)
1c53c80d
SC
326{
327 static long delayed_load_register = 0;
328 static int last_insn_had_delay_slot = 0;
329 static int last_insn_has_load_delay = 0;
330 static int last_insn_unconditional_jump = 0;
331 static int last_insn_was_ldw = 0;
332
333 iq2000_insn insn;
334 char * errmsg;
335
336 /* Initialize GAS's cgen interface for a new instruction. */
337 gas_cgen_init_parse ();
338
339 insn.insn = iq2000_cgen_assemble_insn
340 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
341
342 if (!insn.insn)
343 {
344 as_bad ("%s", errmsg);
345 return;
346 }
347
348 /* Doesn't really matter what we pass for RELAX_P here. */
349 gas_cgen_finish_insn (insn.insn, insn.buffer,
350 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
351
5515a510
NC
352 /* We need to generate an error if there's a yielding instruction in the delay
353 slot of a control flow modifying instruction (jump (yes), load (no)) */
1c53c80d
SC
354 if ((last_insn_had_delay_slot && !last_insn_has_load_delay) &&
355 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_YIELD_INSN))
356 as_bad (_("the yielding instruction %s may not be in a delay slot."),
357 CGEN_INSN_NAME (insn.insn));
358
359 /* Warn about odd numbered base registers for paired-register
5515a510 360 instructions like LDW. On iq2000, result is always rt. */
1c53c80d
SC
361 if (iq2000_mach == bfd_mach_iq2000
362 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_EVEN_REG_NUM)
363 && (insn.fields.f_rt % 2))
364 as_bad (_("Register number (R%ld) for double word access must be even."),
365 insn.fields.f_rt);
366
1c53c80d
SC
367 /* Warn about insns that reference the target of a previous load. */
368 /* NOTE: R0 is a special case and is not subject to load delays (except for ldw). */
369 if (delayed_load_register && (last_insn_has_load_delay || last_insn_was_ldw))
370 {
371 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD) &&
372 insn.fields.f_rd == delayed_load_register)
373 as_warn (_("operand references R%ld of previous load."),
374 insn.fields.f_rd);
5515a510 375
1c53c80d
SC
376 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS) &&
377 insn.fields.f_rs == delayed_load_register)
378 as_warn (_("operand references R%ld of previous load."),
379 insn.fields.f_rs);
5515a510 380
1c53c80d
SC
381 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT) &&
382 insn.fields.f_rt == delayed_load_register)
383 as_warn (_("operand references R%ld of previous load."),
384 insn.fields.f_rt);
5515a510 385
1c53c80d
SC
386 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_R31) &&
387 delayed_load_register == 31)
388 as_warn (_("instruction implicitly accesses R31 of previous load."));
389 }
390
5515a510
NC
391 /* Warn about insns that reference the (target + 1) of a previous ldw. */
392 if (last_insn_was_ldw)
393 {
394 if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RD)
395 && insn.fields.f_rd == delayed_load_register + 1)
396 || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RS)
397 && insn.fields.f_rs == delayed_load_register + 1)
398 || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_RT)
399 && insn.fields.f_rt == delayed_load_register + 1))
400 as_warn (_("operand references R%ld of previous load."),
401 delayed_load_register + 1);
402 }
1c53c80d
SC
403
404 last_insn_had_delay_slot =
405 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
406
407 last_insn_has_load_delay =
408 CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
409
410 if (last_insn_unconditional_jump)
411 last_insn_has_load_delay = last_insn_unconditional_jump = 0;
412 else if (! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "j")
413 || ! strcmp (CGEN_INSN_MNEMONIC (insn.insn), "jal"))
414 last_insn_unconditional_jump = 1;
415
5515a510
NC
416 /* The meaning of EVEN_REG_NUM was overloaded to also imply LDW. Since
417 that's not true for IQ10, let's make the above logic specific to LDW. */
1c53c80d
SC
418 last_insn_was_ldw = ! strcmp ("ldw", CGEN_INSN_NAME (insn.insn));
419
5515a510 420 /* The assumption here is that the target of a load is always rt. */
1c53c80d
SC
421 delayed_load_register = insn.fields.f_rt;
422}
423
424valueT
5515a510 425md_section_align (segT segment, valueT size)
1c53c80d 426{
fd361982 427 int align = bfd_section_alignment (segment);
8d3842cd 428 return ((size + (1 << align) - 1) & -(1 << align));
1c53c80d
SC
429}
430
1c53c80d 431symbolS *
5515a510 432md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1c53c80d
SC
433{
434 return 0;
435}
436\f
437/* Interface to relax_segment. */
438
439/* Return an initial guess of the length by which a fragment must grow to
440 hold a branch to reach its destination.
441 Also updates fr_type/fr_subtype as necessary.
442
443 Called just before doing relaxation.
444 Any symbol that is now undefined will not become defined.
445 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
446 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
447 Although it may not be explicit in the frag, pretend fr_var starts with a
448 0 value. */
449
450int
5515a510
NC
451md_estimate_size_before_relax (fragS * fragP,
452 segT segment ATTRIBUTE_UNUSED)
1c53c80d
SC
453{
454 int old_fr_fix = fragP->fr_fix;
455
456 /* The only thing we have to handle here are symbols outside of the
457 current segment. They may be undefined or in a different segment in
458 which case linker scripts may place them anywhere.
459 However, we can't finish the fragment here and emit the reloc as insn
460 alignment requirements may move the insn about. */
461
462 return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
5515a510 463}
1c53c80d
SC
464
465/* *fragP has been relaxed to its final size, and now needs to have
466 the bytes inside it modified to conform to the new size.
467
468 Called after relaxation is finished.
469 fragP->fr_type == rs_machine_dependent.
470 fragP->fr_subtype is the subtype of what the address relaxed to. */
471
472void
5515a510
NC
473md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
474 segT sec ATTRIBUTE_UNUSED,
475 fragS * fragP ATTRIBUTE_UNUSED)
1c53c80d
SC
476{
477}
478
479\f
480/* Functions concerning relocs. */
481
482long
5515a510 483md_pcrel_from_section (fixS * fixP, segT sec)
1c53c80d
SC
484{
485 if (fixP->fx_addsy != (symbolS *) NULL
486 && (! S_IS_DEFINED (fixP->fx_addsy)
487 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
488 {
489 /* The symbol is undefined (or is defined but not in this section).
490 Let the linker figure it out. */
491 return 0;
492 }
493
5515a510 494 /* Return the address of the delay slot. */
1c53c80d
SC
495 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
496}
497
498/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
499 Returns BFD_RELOC_NONE if no reloc type can be found.
500 *FIXP may be modified if desired. */
501
502bfd_reloc_code_real_type
5515a510
NC
503md_cgen_lookup_reloc (const CGEN_INSN * insn ATTRIBUTE_UNUSED,
504 const CGEN_OPERAND * operand,
505 fixS * fixP ATTRIBUTE_UNUSED)
1c53c80d
SC
506{
507 switch (operand->type)
508 {
5515a510
NC
509 case IQ2000_OPERAND_OFFSET: return BFD_RELOC_16_PCREL_S2;
510 case IQ2000_OPERAND_JMPTARG: return BFD_RELOC_IQ2000_OFFSET_16;
511 case IQ2000_OPERAND_JMPTARGQ10: return BFD_RELOC_NONE;
512 case IQ2000_OPERAND_HI16: return BFD_RELOC_HI16;
513 case IQ2000_OPERAND_LO16: return BFD_RELOC_LO16;
514 default: break;
1c53c80d
SC
515 }
516
517 return BFD_RELOC_NONE;
518}
519
520/* Record a HI16 reloc for later matching with its LO16 cousin. */
521
522static void
5515a510
NC
523iq2000_record_hi16 (int reloc_type,
524 fixS * fixP,
525 segT seg ATTRIBUTE_UNUSED)
1c53c80d
SC
526{
527 struct iq2000_hi_fixup * hi_fixup;
528
9c2799c2 529 gas_assert (reloc_type == BFD_RELOC_HI16);
1c53c80d 530
325801bd 531 hi_fixup = XNEW (struct iq2000_hi_fixup);
1c53c80d
SC
532 hi_fixup->fixp = fixP;
533 hi_fixup->seg = now_seg;
534 hi_fixup->next = iq2000_hi_fixup_list;
5515a510 535
1c53c80d
SC
536 iq2000_hi_fixup_list = hi_fixup;
537}
538
539/* Called while parsing an instruction to create a fixup.
540 We need to check for HI16 relocs and queue them up for later sorting. */
541
542fixS *
5515a510
NC
543iq2000_cgen_record_fixup_exp (fragS * frag,
544 int where,
545 const CGEN_INSN * insn,
546 int length,
547 const CGEN_OPERAND * operand,
548 int opinfo,
549 expressionS * exp)
1c53c80d
SC
550{
551 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
552 operand, opinfo, exp);
553
5515a510 554 if (operand->type == IQ2000_OPERAND_HI16
1c53c80d 555 /* If low/high was used, it is recorded in `opinfo'. */
5515a510
NC
556 && (fixP->fx_cgen.opinfo == BFD_RELOC_HI16
557 || fixP->fx_cgen.opinfo == BFD_RELOC_LO16))
558 iq2000_record_hi16 (fixP->fx_cgen.opinfo, fixP, now_seg);
1c53c80d
SC
559
560 return fixP;
561}
562
563/* Return BFD reloc type from opinfo field in a fixS.
564 It's tricky using fx_r_type in iq2000_frob_file because the values
565 are BFD_RELOC_UNUSED + operand number. */
566#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
567
568/* Sort any unmatched HI16 relocs so that they immediately precede
55cf6793 569 the corresponding LO16 reloc. This is called before md_apply_fix and
1c53c80d
SC
570 tc_gen_reloc. */
571
572void
5515a510 573iq2000_frob_file (void)
1c53c80d
SC
574{
575 struct iq2000_hi_fixup * l;
576
577 for (l = iq2000_hi_fixup_list; l != NULL; l = l->next)
578 {
579 segment_info_type * seginfo;
580 int pass;
5515a510 581
9c2799c2 582 gas_assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
1c53c80d 583 || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
5515a510 584
1c53c80d
SC
585 /* Check quickly whether the next fixup happens to be a matching low. */
586 if (l->fixp->fx_next != NULL
587 && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
588 && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
589 && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
590 continue;
591
592 /* Look through the fixups for this segment for a matching
593 `low'. When we find one, move the high just in front of it.
594 We do this in two passes. In the first pass, we try to find
595 a unique `low'. In the second pass, we permit multiple
596 high's relocs for a single `low'. */
597 seginfo = seg_info (l->seg);
598 for (pass = 0; pass < 2; pass++)
599 {
600 fixS * f;
601 fixS * prev;
602
603 prev = NULL;
604 for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
605 {
606 /* Check whether this is a `low' fixup which matches l->fixp. */
607 if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
608 && f->fx_addsy == l->fixp->fx_addsy
609 && f->fx_offset == l->fixp->fx_offset
610 && (pass == 1
611 || prev == NULL
612 || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
613 || prev->fx_addsy != f->fx_addsy
614 || prev->fx_offset != f->fx_offset))
615 {
616 fixS ** pf;
617
618 /* Move l->fixp before f. */
619 for (pf = &seginfo->fix_root;
620 * pf != l->fixp;
621 pf = & (* pf)->fx_next)
9c2799c2 622 gas_assert (* pf != NULL);
1c53c80d
SC
623
624 * pf = l->fixp->fx_next;
625
626 l->fixp->fx_next = f;
627 if (prev == NULL)
628 seginfo->fix_root = l->fixp;
629 else
630 prev->fx_next = l->fixp;
631
632 break;
633 }
634
635 prev = f;
636 }
637
638 if (f != NULL)
639 break;
640
641 if (pass == 1)
642 as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
643 _("Unmatched high relocation"));
644 }
645 }
646}
647
648/* See whether we need to force a relocation into the output file. */
649
650int
5515a510 651iq2000_force_relocation (fixS * fix)
1c53c80d
SC
652{
653 if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
654 || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
655 return 1;
656
657 return 0;
658}
659\f
660/* Handle the .set pseudo-op. */
661
662static void
5515a510 663s_iq2000_set (int x ATTRIBUTE_UNUSED)
1c53c80d 664{
5515a510
NC
665 static const char * ignored_arguments [] =
666 {
667 "reorder",
668 "noreorder",
669 "at",
670 "noat",
671 "macro",
672 "nomacro",
673 "move",
674 "novolatile",
675 "nomove",
676 "volatile",
677 "bopt",
678 "nobopt",
679 NULL
680 };
b8b80cf7 681 const char ** ignored;
1c53c80d
SC
682 char *name = input_line_pointer, ch;
683 char *save_ILP = input_line_pointer;
684
685 while (!is_end_of_line[(unsigned char) *input_line_pointer])
686 input_line_pointer++;
687 ch = *input_line_pointer;
688 *input_line_pointer = '\0';
689
b8b80cf7
NC
690 for (ignored = ignored_arguments; * ignored; ignored ++)
691 if (strcmp (* ignored, name) == 0)
5515a510 692 break;
b8b80cf7 693 if (* ignored == NULL)
1c53c80d
SC
694 {
695 /* We'd like to be able to use .set symbol, expn */
696 input_line_pointer = save_ILP;
697 s_set (0);
698 return;
1c53c80d
SC
699 }
700 *input_line_pointer = ch;
701 demand_empty_rest_of_line ();
702}
703\f
704/* Write a value out to the object file, using the appropriate endianness. */
705
706void
5515a510 707md_number_to_chars (char * buf, valueT val, int n)
1c53c80d
SC
708{
709 number_to_chars_bigendian (buf, val, n);
710}
711
712void
5515a510 713md_operand (expressionS * exp)
1c53c80d 714{
5515a510 715 /* In case of a syntax error, escape back to try next syntax combo. */
1c53c80d
SC
716 if (exp->X_op == O_absent)
717 gas_cgen_md_operand (exp);
718}
719
6d4af3c2 720const char *
5515a510 721md_atof (int type, char * litP, int * sizeP)
1c53c80d 722{
5b7c81bd 723 return ieee_md_atof (type, litP, sizeP, true);
1c53c80d
SC
724}
725
5b7c81bd 726bool
5515a510 727iq2000_fix_adjustable (fixS * fixP)
1c53c80d
SC
728{
729 bfd_reloc_code_real_type reloc_type;
730
731 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
732 {
733 const CGEN_INSN *insn = NULL;
734 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
735 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
5515a510 736
1c53c80d
SC
737 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
738 }
739 else
740 reloc_type = fixP->fx_r_type;
741
742 if (fixP->fx_addsy == NULL)
5b7c81bd 743 return true;
5515a510 744
1c53c80d 745 /* Prevent all adjustments to global symbols. */
e97b3f28 746 if (S_IS_EXTERNAL (fixP->fx_addsy))
5b7c81bd 747 return false;
5515a510 748
1c53c80d 749 if (S_IS_WEAK (fixP->fx_addsy))
5b7c81bd 750 return false;
5515a510 751
1c53c80d
SC
752 /* We need the symbol name for the VTABLE entries. */
753 if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
754 || reloc_type == BFD_RELOC_VTABLE_ENTRY)
5b7c81bd 755 return false;
1c53c80d 756
5b7c81bd 757 return true;
1c53c80d
SC
758}
759
760static void
5515a510 761s_change_sec (int sec)
1c53c80d 762{
1c53c80d
SC
763#ifdef OBJ_ELF
764 /* The ELF backend needs to know that we are changing sections, so
765 that .previous works correctly. We could do something like check
766 for a obj_section_change_hook macro, but that might be confusing
767 as it would not be appropriate to use it in the section changing
768 functions in read.c, since obj-elf.c intercepts those. FIXME:
769 This should be cleaner, somehow. */
770 obj_elf_section_change_hook ();
771#endif
772
1c53c80d
SC
773 switch (sec)
774 {
775 case 't':
776 s_text (0);
777 break;
778 case 'd':
779 case 'r':
780 s_data (0);
781 break;
782 }
783}
784
5515a510
NC
785static symbolS *
786get_symbol (void)
787{
788 int c;
789 char *name;
790 symbolS *p;
791
d02603dc 792 c = get_symbol_name (&name);
5515a510 793 p = (symbolS *) symbol_find_or_make (name);
d02603dc 794 (void) restore_line_pointer (c);
5515a510
NC
795 return p;
796}
797
1c53c80d
SC
798/* The .end directive. */
799
800static void
5515a510 801s_iq2000_end (int x ATTRIBUTE_UNUSED)
1c53c80d
SC
802{
803 symbolS *p;
804 int maybe_text;
805
806 if (!is_end_of_line[(unsigned char) *input_line_pointer])
807 {
808 p = get_symbol ();
809 demand_empty_rest_of_line ();
810 }
811 else
812 p = NULL;
813
fd361982 814 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5515a510
NC
815 maybe_text = 1;
816 else
817 maybe_text = 0;
1c53c80d 818
5515a510
NC
819 if (!maybe_text)
820 as_warn (_(".end not in text section"));
1c53c80d 821
5515a510
NC
822 if (!cur_proc_ptr)
823 {
824 as_warn (_(".end directive without a preceding .ent directive."));
825 demand_empty_rest_of_line ();
826 return;
827 }
1c53c80d 828
5515a510 829 if (p != NULL)
1c53c80d 830 {
9c2799c2 831 gas_assert (S_GET_NAME (p));
5515a510
NC
832 if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
833 as_warn (_(".end symbol does not match .ent symbol."));
1c53c80d
SC
834 }
835 else
5515a510 836 as_warn (_(".end directive missing or unknown symbol"));
1c53c80d 837
5515a510 838 cur_proc_ptr = NULL;
1c53c80d
SC
839}
840
841static int
5515a510 842get_number (void)
1c53c80d
SC
843{
844 int negative = 0;
845 long val = 0;
846
847 if (*input_line_pointer == '-')
848 {
849 ++input_line_pointer;
850 negative = 1;
851 }
852
853 if (! ISDIGIT (*input_line_pointer))
854 as_bad (_("Expected simple number."));
855
856 if (input_line_pointer[0] == '0')
857 {
858 if (input_line_pointer[1] == 'x')
859 {
860 input_line_pointer += 2;
861 while (ISXDIGIT (*input_line_pointer))
862 {
863 val <<= 4;
864 val |= hex_value (*input_line_pointer++);
865 }
866 return negative ? -val : val;
867 }
868 else
869 {
870 ++input_line_pointer;
871
872 while (ISDIGIT (*input_line_pointer))
873 {
874 val <<= 3;
875 val |= *input_line_pointer++ - '0';
876 }
877 return negative ? -val : val;
878 }
879 }
880
881 if (! ISDIGIT (*input_line_pointer))
882 {
883 printf (_(" *input_line_pointer == '%c' 0x%02x\n"),
884 *input_line_pointer, *input_line_pointer);
885 as_warn (_("Invalid number"));
886 return -1;
887 }
888
889 while (ISDIGIT (*input_line_pointer))
890 {
891 val *= 10;
892 val += *input_line_pointer++ - '0';
893 }
894
895 return negative ? -val : val;
896}
897
5515a510
NC
898/* The .aent and .ent directives. */
899
900static void
901s_iq2000_ent (int aent)
902{
5515a510
NC
903 symbolS *symbolP;
904 int maybe_text;
905
906 symbolP = get_symbol ();
907 if (*input_line_pointer == ',')
908 input_line_pointer++;
909 SKIP_WHITESPACE ();
910 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
87975d2a 911 get_number ();
5515a510 912
fd361982 913 if ((bfd_section_flags (now_seg) & SEC_CODE) != 0)
5515a510
NC
914 maybe_text = 1;
915 else
916 maybe_text = 0;
917
918 if (!maybe_text)
919 as_warn (_(".ent or .aent not in text section."));
920
921 if (!aent && cur_proc_ptr)
922 as_warn (_("missing `.end'"));
923
924 if (!aent)
925 {
926 cur_proc_ptr = &cur_proc;
927 memset (cur_proc_ptr, '\0', sizeof (procS));
928
929 cur_proc_ptr->isym = symbolP;
930
931 symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
932
933 numprocs++;
934 }
935
936 demand_empty_rest_of_line ();
937}
938
939/* The .frame directive. If the mdebug section is present (IRIX 5 native)
940 then ecoff.c (ecoff_directive_frame) is used. For embedded targets,
941 s_iq2000_frame is used so that we can set the PDR information correctly.
942 We can't use the ecoff routines because they make reference to the ecoff
943 symbol table (in the mdebug section). */
944
945static void
946s_iq2000_frame (int ignore)
947{
948 s_ignore (ignore);
949}
950
951/* The .fmask and .mask directives. If the mdebug section is present
952 (IRIX 5 native) then ecoff.c (ecoff_directive_mask) is used. For
953 embedded targets, s_iq2000_mask is used so that we can set the PDR
954 information correctly. We can't use the ecoff routines because they
955 make reference to the ecoff symbol table (in the mdebug section). */
956
957static void
958s_iq2000_mask (int reg_type)
959{
960 s_ignore (reg_type);
961}
962
963/* The target specific pseudo-ops which we support. */
964const pseudo_typeS md_pseudo_table[] =
965{
966 { "align", s_align_bytes, 0 },
967 { "word", cons, 4 },
968 { "rdata", s_change_sec, 'r'},
969 { "sdata", s_change_sec, 's'},
970 { "set", s_iq2000_set, 0 },
971 { "ent", s_iq2000_ent, 0 },
972 { "end", s_iq2000_end, 0 },
973 { "frame", s_iq2000_frame, 0 },
974 { "fmask", s_iq2000_mask, 'F'},
975 { "mask", s_iq2000_mask, 'R'},
976 { "dword", cons, 8 },
977 { "half", cons, 2 },
978 { NULL, NULL, 0 }
979};