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_loopsize (CGEN_CPU_DESC cd,
109 signed long * valuep = (signed long *) arg;
111 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
112 enum cgen_parse_operand_result result_type;
115 /* Is it a control transfer instructions? */
116 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_LOOPSIZE)
118 code = BFD_RELOC_MS1_PCINSN8;
119 errmsg = cgen_parse_address (cd, strp, opindex, code,
120 & result_type, & value);
129 parse_imm16 (CGEN_CPU_DESC cd,
134 signed long * valuep = (signed long *) arg;
136 enum cgen_parse_operand_result result_type;
137 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
140 /* Is it a control transfer instructions? */
141 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
143 code = BFD_RELOC_16_PCREL;
144 errmsg = cgen_parse_address (cd, strp, opindex, code,
145 & result_type, & value);
148 if (signed_out_of_bounds (value))
149 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
155 /* If it's not a control transfer instruction, then
156 we have to check for %OP relocating operators. */
157 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16L)
159 else if (strncmp (*strp, "%hi16", 5) == 0)
162 code = BFD_RELOC_HI16;
164 else if (strncmp (*strp, "%lo16", 5) == 0)
167 code = BFD_RELOC_LO16;
170 /* If we found a %OP relocating operator, then parse it as an address.
171 If not, we need to parse it as an integer, either signed or unsigned
172 depending on which operand type we have. */
173 if (code != BFD_RELOC_NONE)
175 /* %OP relocating operator found. */
176 errmsg = cgen_parse_address (cd, strp, opindex, code,
177 & result_type, & value);
182 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
183 if (code == BFD_RELOC_HI16)
184 value = (value >> 16) & 0xFFFF;
185 else if (code == BFD_RELOC_LO16)
186 value = value & 0xFFFF;
188 errmsg = _("Biiiig Trouble in parse_imm16!");
191 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
192 /* No special processing for this case. */
196 errmsg = _("%operator operand is not a symbol");
204 /* Parse hex values like 0xffff as unsigned, and sign extend
206 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
208 if ((*strp)[0] == '0'
209 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
212 /* No relocating operator. Parse as an number. */
215 /* Parse as as signed integer. */
217 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
222 /* Manual range checking is needed for the signed case. */
223 if (*valuep & 0x8000)
224 value = 0xffff0000 | *valuep;
228 if (signed_out_of_bounds (value))
229 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
230 /* Truncate to 16 bits. This is necessary
231 because cgen will have sign extended *valuep. */
238 /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */
239 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
241 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
243 && *valuep <= 0xffff)
253 parse_dup (CGEN_CPU_DESC cd,
256 unsigned long *valuep)
258 const char *errmsg = NULL;
260 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
265 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
271 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
278 parse_ball (CGEN_CPU_DESC cd,
281 unsigned long *valuep)
283 const char *errmsg = NULL;
285 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
290 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
296 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
302 parse_xmode (CGEN_CPU_DESC cd,
305 unsigned long *valuep)
307 const char *errmsg = NULL;
309 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
314 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
320 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
326 parse_rc (CGEN_CPU_DESC cd,
329 unsigned long *valuep)
331 const char *errmsg = NULL;
333 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
338 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
344 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
350 parse_cbrb (CGEN_CPU_DESC cd,
353 unsigned long *valuep)
355 const char *errmsg = NULL;
357 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
362 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
368 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
374 parse_rbbc (CGEN_CPU_DESC cd,
377 unsigned long *valuep)
379 const char *errmsg = NULL;
381 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
386 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
391 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
396 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
402 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
408 parse_type (CGEN_CPU_DESC cd,
411 unsigned long *valuep)
413 const char *errmsg = NULL;
415 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
420 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
425 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
431 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
433 if ((errmsg == NULL) && (*valuep == 3))
434 errmsg = _("invalid operand. type may have values 0,1,2 only.");
440 static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
441 static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
444 print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
447 unsigned int attrs ATTRIBUTE_UNUSED,
448 bfd_vma pc ATTRIBUTE_UNUSED,
449 int length ATTRIBUTE_UNUSED)
451 disassemble_info *info = (disassemble_info *) dis_info;
453 info->fprintf_func (info->stream, "$%lx", value);
456 print_normal (cd, dis_info, value, attrs, pc, length);
460 print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
463 unsigned int attrs ATTRIBUTE_UNUSED,
464 bfd_vma pc ATTRIBUTE_UNUSED,
465 int length ATTRIBUTE_UNUSED)
467 print_address (cd, dis_info, value + pc, attrs, pc, length);