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