1 /* IQ2000 opcode support. -*- C -*-
3 Copyright 2000, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
5 Contributed by Red Hat Inc; developed under contract from Fujitsu.
7 This file is part of the GNU Binutils.
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 3 of the License, or
12 (at your option) any later version.
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.
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., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
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.
31 Each section is delimited with start and end markers.
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"
37 <arch>-ibd.h additions use: "-- ibd.h". */
41 /* Allows reason codes to be output when assembler errors occur. */
42 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
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)
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
53 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
57 #include "safe-ctype.h"
59 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
61 /* Special check to ensure that instruction exists for given machine. */
64 iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
66 int machs = cd->machs;
68 return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
72 iq2000_cgen_isa_register (const char **strp)
77 if (**strp == 'r' || **strp == 'R')
83 if ('0' <= ch1 && ch1 <= '9')
90 if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
92 if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
97 && TOLOWER ((*strp)[1]) != 'l'
98 && TOLOWER ((*strp)[1]) != 'h')
103 /* Handle negated literal. */
106 parse_mimm (CGEN_CPU_DESC cd,
109 unsigned long *valuep)
113 /* Verify this isn't a register. */
114 if (iq2000_cgen_isa_register (strp))
115 errmsg = _("immediate value cannot be register");
120 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
123 long x = (-value) & 0xFFFF0000;
125 if (x != 0 && x != (long) 0xFFFF0000)
126 errmsg = _("immediate value out of range");
128 *valuep = (-value & 0xFFFF);
134 /* Handle signed/unsigned literal. */
137 parse_imm (CGEN_CPU_DESC cd,
140 unsigned long *valuep)
144 if (iq2000_cgen_isa_register (strp))
145 errmsg = _("immediate value cannot be register");
150 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
153 long x = value & 0xFFFF0000;
155 if (x != 0 && x != (long) 0xFFFF0000)
156 errmsg = _("immediate value out of range");
158 *valuep = (value & 0xFFFF);
164 /* Handle iq10 21-bit jmp offset. */
167 parse_jtargq10 (CGEN_CPU_DESC cd,
170 int reloc ATTRIBUTE_UNUSED,
171 enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
176 enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
178 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
179 & result_type, & value);
180 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
182 /* Check value is within 23-bits
183 (remembering that 2-bit shift right will occur). */
184 if (value > 0x7fffff)
185 return _("21-bit offset out of range");
187 *valuep = (value & 0x7FFFFF);
194 parse_hi16 (CGEN_CPU_DESC cd,
197 unsigned long *valuep)
199 if (strncasecmp (*strp, "%hi(", 4) == 0)
201 enum cgen_parse_operand_result result_type;
206 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
207 & result_type, & value);
209 return MISSING_CLOSING_PARENTHESIS;
213 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
215 /* If value has top-bit of %lo on, then it will
216 sign-propagate and so we compensate by adding
217 1 to the resultant %hi value. */
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. */
230 if (strncasecmp (*strp, "%uhi(", 5) == 0)
232 enum cgen_parse_operand_result result_type;
237 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
238 & result_type, & value);
240 return MISSING_CLOSING_PARENTHESIS;
244 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
253 return parse_imm (cd, strp, opindex, valuep);
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. */
261 parse_lo16 (CGEN_CPU_DESC cd,
264 unsigned long *valuep)
266 if (strncasecmp (*strp, "%lo(", 4) == 0)
269 enum cgen_parse_operand_result result_type;
273 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
274 & result_type, & value);
276 return MISSING_CLOSING_PARENTHESIS;
279 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
285 return parse_imm (cd, strp, opindex, valuep);
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. */
293 parse_mlo16 (CGEN_CPU_DESC cd,
296 unsigned long *valuep)
298 if (strncasecmp (*strp, "%lo(", 4) == 0)
301 enum cgen_parse_operand_result result_type;
305 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
306 & result_type, & value);
308 return MISSING_CLOSING_PARENTHESIS;
311 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
312 value = (-value) & 0xffff;
317 return parse_mimm (cd, strp, opindex, valuep);