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