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) ms1_asm_hash (insn)
51 extern unsigned int ms1_asm_hash (const char *);
53 extern int ms1_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 ms1_cgen_insn_supported (CGEN_CPU_DESC cd,
63 const CGEN_INSN *insn)
65 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
67 /* No mach attribute? Assume it's supported for all machs. */
71 return ((machs & cd->machs) != 0);
74 /* A better hash function for instruction mnemonics. */
77 ms1_asm_hash (const char* insn)
82 for (hash = 0; *m && ! ISSPACE (*m); m++)
83 hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
85 /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
87 return hash % CGEN_ASM_HASH_SIZE;
92 /* Range checking for signed numbers. Returns 0 if acceptable
93 and 1 if the value is out of bounds for a signed quantity. */
96 signed_out_of_bounds (long val)
98 if ((val < -32768) || (val > 32767))
104 parse_imm16 (CGEN_CPU_DESC cd,
109 signed long * valuep = (signed long *) arg;
111 enum cgen_parse_operand_result result_type;
112 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
115 /* Is it a control transfer instructions? */
116 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
118 code = BFD_RELOC_16_PCREL;
119 errmsg = cgen_parse_address (cd, strp, opindex, code,
120 & result_type, & value);
123 if (signed_out_of_bounds (value))
124 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
130 /* If it's not a control transfer instruction, then
131 we have to check for %OP relocating operators. */
132 if (strncmp (*strp, "%hi16", 5) == 0)
135 code = BFD_RELOC_HI16;
137 else if (strncmp (*strp, "%lo16", 5) == 0)
140 code = BFD_RELOC_LO16;
143 /* If we found a %OP relocating operator, then parse it as an address.
144 If not, we need to parse it as an integer, either signed or unsigned
145 depending on which operand type we have. */
146 if (code != BFD_RELOC_NONE)
148 /* %OP relocating operator found. */
149 errmsg = cgen_parse_address (cd, strp, opindex, code,
150 & result_type, & value);
155 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
156 if (code == BFD_RELOC_HI16)
157 value = (value >> 16) & 0xFFFF;
158 else if (code == BFD_RELOC_LO16)
159 value = value & 0xFFFF;
161 errmsg = _("Biiiig Trouble in parse_imm16!");
164 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
165 /* No special processing for this case. */
169 errmsg = _("%operator operand is not a symbol");
177 /* Parse hex values like 0xffff as unsigned, and sign extend
179 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
181 if ((*strp)[0] == '0'
182 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
185 /* No relocating operator. Parse as an number. */
188 /* Parse as as signed integer. */
190 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
195 /* Manual range checking is needed for the signed case. */
196 if (*valuep & 0x8000)
197 value = 0xffff0000 | *valuep;
201 if (signed_out_of_bounds (value))
202 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
203 /* Truncate to 16 bits. This is necessary
204 because cgen will have sign extended *valuep. */
211 /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */
212 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
214 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
216 && *valuep <= 0xffff)
226 parse_dup (CGEN_CPU_DESC cd,
229 unsigned long *valuep)
231 const char *errmsg = NULL;
233 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
238 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
244 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
251 parse_ball (CGEN_CPU_DESC cd,
254 unsigned long *valuep)
256 const char *errmsg = NULL;
258 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
263 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
269 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
275 parse_xmode (CGEN_CPU_DESC cd,
278 unsigned long *valuep)
280 const char *errmsg = NULL;
282 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
287 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
293 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
299 parse_rc (CGEN_CPU_DESC cd,
302 unsigned long *valuep)
304 const char *errmsg = NULL;
306 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
311 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
317 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
323 parse_cbrb (CGEN_CPU_DESC cd,
326 unsigned long *valuep)
328 const char *errmsg = NULL;
330 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
335 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
341 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
347 parse_rbbc (CGEN_CPU_DESC cd,
350 unsigned long *valuep)
352 const char *errmsg = NULL;
354 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
359 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
364 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
369 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
375 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
381 parse_type (CGEN_CPU_DESC cd,
384 unsigned long *valuep)
386 const char *errmsg = NULL;
388 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
393 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
398 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
404 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
406 if ((errmsg == NULL) && (*valuep == 3))
407 errmsg = _("invalid operand. type may have values 0,1,2 only.");
413 static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
416 print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
419 unsigned int attrs ATTRIBUTE_UNUSED,
420 bfd_vma pc ATTRIBUTE_UNUSED,
421 int length ATTRIBUTE_UNUSED)
423 disassemble_info *info = (disassemble_info *) dis_info;
425 info->fprintf_func (info->stream, "$%lx", value);
428 print_normal (cd, dis_info, value, attrs, pc, length);