* elf32-mips.c (mips_elf_generic_reloc): New Function.
[deliverable/binutils-gdb.git] / cpu / iq2000.opc
1 /* IQ2000 opcode support. -*- C -*-
2
3 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
4
5 Contributed by Red Hat Inc; developed under contract from Fujitsu.
6
7 This file is part of the GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 */
24
25 /* This file is an addendum to iq2000.cpu. Heavy use of C code isn't
26 appropriate in .cpu files, so it resides here. This especially applies
27 to assembly/disassembly where parsing/printing can be quite involved.
28 Such things aren't really part of the specification of the cpu, per se,
29 so .cpu files provide the general framework and .opc files handle the
30 nitty-gritty details as necessary.
31
32 Each section is delimited with start and end markers.
33
34 <arch>-opc.h additions use: "-- opc.h"
35 <arch>-opc.c additions use: "-- opc.c"
36 <arch>-asm.c additions use: "-- asm.c"
37 <arch>-dis.c additions use: "-- dis.c"
38 <arch>-ibd.h additions use: "-- ibd.h"
39 */
40 \f
41 /* -- opc.h */
42
43 /* Allows reason codes to be output when assembler errors occur. */
44 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
45
46 /* Override disassembly hashing - there are variable bits in the top
47 byte of these instructions. */
48 #define CGEN_DIS_HASH_SIZE 8
49 #define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
50
51 /* following activates check beyond hashing since some iq2000 and iq10
52 instructions have same mnemonics but different functionality. */
53 #define CGEN_VALIDATE_INSN_SUPPORTED
54
55 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, CGEN_INSN *insn);
56
57 /* -- asm.c */
58 static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
59 static const char * parse_imm PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
60 static const char * parse_hi16 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
61 static const char * parse_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
62
63 /* Special check to ensure that instruction exists for given machine */
64 int
65 iq2000_cgen_insn_supported (cd, insn)
66 CGEN_CPU_DESC cd;
67 CGEN_INSN *insn;
68 {
69 int machs = cd->machs;
70
71 return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
72 }
73
74 static int iq2000_cgen_isa_register (strp)
75 const char **strp;
76 {
77 int len;
78 int ch1, ch2;
79 if (**strp == 'r' || **strp == 'R')
80 {
81 len = strlen (*strp);
82 if (len == 2)
83 {
84 ch1 = (*strp)[1];
85 if ('0' <= ch1 && ch1 <= '9')
86 return 1;
87 }
88 else if (len == 3)
89 {
90 ch1 = (*strp)[1];
91 ch2 = (*strp)[2];
92 if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
93 return 1;
94 if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
95 return 1;
96 }
97 }
98 if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
99 return 1;
100 return 0;
101 }
102
103 /* Handle negated literal. */
104
105 static const char *
106 parse_mimm (cd, strp, opindex, valuep)
107 CGEN_CPU_DESC cd;
108 const char **strp;
109 int opindex;
110 long *valuep;
111 {
112 const char *errmsg;
113 long value;
114
115 /* Verify this isn't a register */
116 if (iq2000_cgen_isa_register (strp))
117 errmsg = _("immediate value cannot be register");
118 else
119 {
120 long value;
121
122 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
123 if (errmsg == NULL)
124 {
125 long x = (-value) & 0xFFFF0000;
126 if (x != 0 && x != 0xFFFF0000)
127 errmsg = _("immediate value out of range");
128 else
129 *valuep = (-value & 0xFFFF);
130 }
131 }
132 return errmsg;
133 }
134
135 /* Handle signed/unsigned literal. */
136
137 static const char *
138 parse_imm (cd, strp, opindex, valuep)
139 CGEN_CPU_DESC cd;
140 const char **strp;
141 int opindex;
142 unsigned long *valuep;
143 {
144 const char *errmsg;
145 long value;
146
147 if (iq2000_cgen_isa_register (strp))
148 errmsg = _("immediate value cannot be register");
149 else
150 {
151 long value;
152
153 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
154 if (errmsg == NULL)
155 {
156 long x = value & 0xFFFF0000;
157 if (x != 0 && x != 0xFFFF0000)
158 errmsg = _("immediate value out of range");
159 else
160 *valuep = (value & 0xFFFF);
161 }
162 }
163 return errmsg;
164 }
165
166 /* Handle iq10 21-bit jmp offset. */
167
168 static const char *
169 parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
170 CGEN_CPU_DESC cd;
171 const char **strp;
172 int opindex;
173 int reloc;
174 enum cgen_parse_operand_result *type_addr;
175 unsigned long *valuep;
176 {
177 const char *errmsg;
178 bfd_vma value;
179 enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
180
181 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
182 &result_type, &value);
183 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
184 {
185 /* check value is within 23-bits (remembering that 2-bit shift right will occur) */
186 if (value > 0x7fffff)
187 return _("21-bit offset out of range");
188 }
189 *valuep = (value & 0x7FFFFF);
190 return errmsg;
191 }
192
193 /* Handle high(). */
194
195 static const char *
196 parse_hi16 (cd, strp, opindex, valuep)
197 CGEN_CPU_DESC cd;
198 const char **strp;
199 int opindex;
200 unsigned long *valuep;
201 {
202 if (strncasecmp (*strp, "%hi(", 4) == 0)
203 {
204 enum cgen_parse_operand_result result_type;
205 bfd_vma value;
206 const char *errmsg;
207
208 *strp += 4;
209 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
210 &result_type, &value);
211 if (**strp != ')')
212 return _("missing `)'");
213
214 ++*strp;
215 if (errmsg == NULL
216 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
217 {
218 /* if value has top-bit of %lo on, then it will
219 sign-propagate and so we compensate by adding
220 1 to the resultant %hi value */
221 if (value & 0x8000)
222 value += 0x10000;
223 value >>= 16;
224 }
225 *valuep = value;
226
227 return errmsg;
228 }
229
230 /* we add %uhi in case a user just wants the high 16-bits or is using
231 an insn like ori for %lo which does not sign-propagate */
232 if (strncasecmp (*strp, "%uhi(", 5) == 0)
233 {
234 enum cgen_parse_operand_result result_type;
235 bfd_vma value;
236 const char *errmsg;
237
238 *strp += 5;
239 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
240 &result_type, &value);
241 if (**strp != ')')
242 return _("missing `)'");
243
244 ++*strp;
245 if (errmsg == NULL
246 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
247 {
248 value >>= 16;
249 }
250 *valuep = value;
251
252 return errmsg;
253 }
254
255 return parse_imm (cd, strp, opindex, valuep);
256 }
257
258 /* Handle %lo in a signed context.
259 The signedness of the value doesn't matter to %lo(), but this also
260 handles the case where %lo() isn't present. */
261
262 static const char *
263 parse_lo16 (cd, strp, opindex, valuep)
264 CGEN_CPU_DESC cd;
265 const char **strp;
266 int opindex;
267 long *valuep;
268 {
269 if (strncasecmp (*strp, "%lo(", 4) == 0)
270 {
271 const char *errmsg;
272 enum cgen_parse_operand_result result_type;
273 bfd_vma value;
274
275 *strp += 4;
276 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
277 &result_type, &value);
278 if (**strp != ')')
279 return _("missing `)'");
280 ++*strp;
281 if (errmsg == NULL
282 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
283 value &= 0xffff;
284 *valuep = value;
285 return errmsg;
286 }
287
288 return parse_imm (cd, strp, opindex, valuep);
289 }
290
291 /* Handle %lo in a negated signed context.
292 The signedness of the value doesn't matter to %lo(), but this also
293 handles the case where %lo() isn't present. */
294
295 static const char *
296 parse_mlo16 (cd, strp, opindex, valuep)
297 CGEN_CPU_DESC cd;
298 const char **strp;
299 int opindex;
300 long *valuep;
301 {
302 if (strncasecmp (*strp, "%lo(", 4) == 0)
303 {
304 const char *errmsg;
305 enum cgen_parse_operand_result result_type;
306 bfd_vma value;
307
308 *strp += 4;
309 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
310 &result_type, &value);
311 if (**strp != ')')
312 return _("missing `)'");
313 ++*strp;
314 if (errmsg == NULL
315 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
316 value = (-value) & 0xffff;
317 *valuep = value;
318 return errmsg;
319 }
320
321 return parse_mimm (cd, strp, opindex, valuep);
322 }
323
324 /* -- */
This page took 0.039731 seconds and 4 git commands to generate.