xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/config/tc-iq2000.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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 = &macro->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 (&macro_name, name);
289*3d8817e4Smiod   namestr = sb_terminate (&macro_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