1 /* IQ2000 opcode support. -*- C -*-
3 Copyright 2000, 2001, 2002 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 2 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, MA 02110-1301, USA.
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.
32 Each section is delimited with start and end markers.
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"
43 /* Allows reason codes to be output when assembler errors occur. */
44 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
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)
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
55 extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn);
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 *));
63 /* Special check to ensure that instruction exists for given machine. */
65 iq2000_cgen_insn_supported (cd, insn)
67 const CGEN_INSN *insn;
69 int machs = cd->machs;
71 return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
74 static int iq2000_cgen_isa_register (strp)
79 if (**strp == 'r' || **strp == 'R')
85 if ('0' <= ch1 && ch1 <= '9')
92 if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
94 if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
98 if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
103 /* Handle negated literal. */
106 parse_mimm (cd, strp, opindex, valuep)
115 /* Verify this isn't a register */
116 if (iq2000_cgen_isa_register (strp))
117 errmsg = _("immediate value cannot be register");
122 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
125 long x = (-value) & 0xFFFF0000;
126 if (x != 0 && x != 0xFFFF0000)
127 errmsg = _("immediate value out of range");
129 *valuep = (-value & 0xFFFF);
135 /* Handle signed/unsigned literal. */
138 parse_imm (cd, strp, opindex, valuep)
142 unsigned long *valuep;
147 if (iq2000_cgen_isa_register (strp))
148 errmsg = _("immediate value cannot be register");
153 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
156 long x = value & 0xFFFF0000;
157 if (x != 0 && x != 0xFFFF0000)
158 errmsg = _("immediate value out of range");
160 *valuep = (value & 0xFFFF);
166 /* Handle iq10 21-bit jmp offset. */
169 parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
174 enum cgen_parse_operand_result *type_addr;
179 enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
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)
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");
189 *valuep = (value & 0x7FFFFF);
196 parse_hi16 (cd, strp, opindex, valuep)
200 unsigned long *valuep;
202 if (strncasecmp (*strp, "%hi(", 4) == 0)
204 enum cgen_parse_operand_result result_type;
209 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
210 &result_type, &value);
212 return _("missing `)'");
216 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
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 */
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)
234 enum cgen_parse_operand_result result_type;
239 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
240 &result_type, &value);
242 return _("missing `)'");
246 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
255 return parse_imm (cd, strp, opindex, valuep);
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. */
263 parse_lo16 (cd, strp, opindex, valuep)
269 if (strncasecmp (*strp, "%lo(", 4) == 0)
272 enum cgen_parse_operand_result result_type;
276 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
277 &result_type, &value);
279 return _("missing `)'");
282 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
288 return parse_imm (cd, strp, opindex, valuep);
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. */
296 parse_mlo16 (cd, strp, opindex, valuep)
302 if (strncasecmp (*strp, "%lo(", 4) == 0)
305 enum cgen_parse_operand_result result_type;
309 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
310 &result_type, &value);
312 return _("missing `)'");
315 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
316 value = (-value) & 0xffff;
321 return parse_mimm (cd, strp, opindex, valuep);