1 /* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
2 Copyright 2001 Free Software Foundation, Inc.
4 Contributed by Red Hat Inc; developed under contract from
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.
26 Each section is delimited with start and end markers.
28 <arch>-opc.h additions use: "-- opc.h"
29 <arch>-opc.c additions use: "-- opc.c"
30 <arch>-asm.c additions use: "-- asm.c"
31 <arch>-dis.c additions use: "-- dis.c"
32 <arch>-ibd.h additions use: "-- ibd.h"
37 /* Check applicability of instructions against machines. */
38 #define CGEN_VALIDATE_INSN_SUPPORTED
40 /* Allows reason codes to be output when assembler errors occur. */
41 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
43 /* Override disassembly hashing - there are variable bits in the top
44 byte of these instructions. */
45 #define CGEN_DIS_HASH_SIZE 8
46 #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
48 #define CGEN_ASM_HASH_SIZE 127
49 #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
51 extern unsigned int mt_asm_hash (const char *);
53 extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
57 #include "safe-ctype.h"
59 /* Special check to ensure that instruction exists for given machine. */
62 mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
64 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
66 /* No mach attribute? Assume it's supported for all machs. */
70 return ((machs & cd->machs) != 0);
73 /* A better hash function for instruction mnemonics. */
76 mt_asm_hash (const char* insn)
81 for (hash = 0; *m && ! ISSPACE (*m); m++)
82 hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
84 /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
86 return hash % CGEN_ASM_HASH_SIZE;
91 /* Range checking for signed numbers. Returns 0 if acceptable
92 and 1 if the value is out of bounds for a signed quantity. */
95 signed_out_of_bounds (long val)
97 if ((val < -32768) || (val > 32767))
103 parse_loopsize (CGEN_CPU_DESC cd,
108 signed long * valuep = (signed long *) arg;
110 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
111 enum cgen_parse_operand_result result_type;
114 /* Is it a control transfer instructions? */
115 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
117 code = BFD_RELOC_MT_PCINSN8;
118 errmsg = cgen_parse_address (cd, strp, opindex, code,
119 & result_type, & value);
128 parse_imm16 (CGEN_CPU_DESC cd,
133 signed long * valuep = (signed long *) arg;
135 enum cgen_parse_operand_result result_type;
136 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
139 /* Is it a control transfer instructions? */
140 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
142 code = BFD_RELOC_16_PCREL;
143 errmsg = cgen_parse_address (cd, strp, opindex, code,
144 & result_type, & value);
147 if (signed_out_of_bounds (value))
148 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
154 /* If it's not a control transfer instruction, then
155 we have to check for %OP relocating operators. */
156 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
158 else if (strncmp (*strp, "%hi16", 5) == 0)
161 code = BFD_RELOC_HI16;
163 else if (strncmp (*strp, "%lo16", 5) == 0)
166 code = BFD_RELOC_LO16;
169 /* If we found a %OP relocating operator, then parse it as an address.
170 If not, we need to parse it as an integer, either signed or unsigned
171 depending on which operand type we have. */
172 if (code != BFD_RELOC_NONE)
174 /* %OP relocating operator found. */
175 errmsg = cgen_parse_address (cd, strp, opindex, code,
176 & result_type, & value);
181 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
182 if (code == BFD_RELOC_HI16)
183 value = (value >> 16) & 0xFFFF;
184 else if (code == BFD_RELOC_LO16)
185 value = value & 0xFFFF;
187 errmsg = _("Biiiig Trouble in parse_imm16!");
190 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
191 /* No special processing for this case. */
195 errmsg = _("%operator operand is not a symbol");
203 /* Parse hex values like 0xffff as unsigned, and sign extend
205 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
207 if ((*strp)[0] == '0'
208 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
211 /* No relocating operator. Parse as an number. */
214 /* Parse as as signed integer. */
216 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
221 /* Manual range checking is needed for the signed case. */
222 if (*valuep & 0x8000)
223 value = 0xffff0000 | *valuep;
227 if (signed_out_of_bounds (value))
228 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
229 /* Truncate to 16 bits. This is necessary
230 because cgen will have sign extended *valuep. */
237 /* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */
238 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
240 if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
242 && *valuep <= 0xffff)
252 parse_dup (CGEN_CPU_DESC cd,
255 unsigned long *valuep)
257 const char *errmsg = NULL;
259 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
264 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
270 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
277 parse_ball (CGEN_CPU_DESC cd,
280 unsigned long *valuep)
282 const char *errmsg = NULL;
284 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
289 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
295 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
301 parse_xmode (CGEN_CPU_DESC cd,
304 unsigned long *valuep)
306 const char *errmsg = NULL;
308 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
313 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
319 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
325 parse_rc (CGEN_CPU_DESC cd,
328 unsigned long *valuep)
330 const char *errmsg = NULL;
332 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
337 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
343 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
349 parse_cbrb (CGEN_CPU_DESC cd,
352 unsigned long *valuep)
354 const char *errmsg = NULL;
356 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
361 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
367 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
373 parse_rbbc (CGEN_CPU_DESC cd,
376 unsigned long *valuep)
378 const char *errmsg = NULL;
380 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
385 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
390 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
395 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
401 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
407 parse_type (CGEN_CPU_DESC cd,
410 unsigned long *valuep)
412 const char *errmsg = NULL;
414 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
419 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
424 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
430 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
432 if ((errmsg == NULL) && (*valuep == 3))
433 errmsg = _("invalid operand. type may have values 0,1,2 only.");
439 static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
440 static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
443 print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
446 unsigned int attrs ATTRIBUTE_UNUSED,
447 bfd_vma pc ATTRIBUTE_UNUSED,
448 int length ATTRIBUTE_UNUSED)
450 disassemble_info *info = (disassemble_info *) dis_info;
452 info->fprintf_func (info->stream, "$%lx", value);
455 print_normal (cd, dis_info, value, attrs, pc, length);
459 print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
462 unsigned int attrs ATTRIBUTE_UNUSED,
463 bfd_vma pc ATTRIBUTE_UNUSED,
464 int length ATTRIBUTE_UNUSED)
466 print_address (cd, dis_info, value + pc, attrs, pc, length);