diff options
Diffstat (limited to 'cpu/mt.opc')
-rw-r--r-- | cpu/mt.opc | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/cpu/mt.opc b/cpu/mt.opc new file mode 100644 index 0000000..e3b32db --- /dev/null +++ b/cpu/mt.opc @@ -0,0 +1,475 @@ +/* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*- + Copyright 2001 Free Software Foundation, Inc. + + Contributed by Red Hat Inc; developed under contract from + Morpho Technologies. + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +/* + Each section is delimited with start and end markers. + + <arch>-opc.h additions use: "-- opc.h" + <arch>-opc.c additions use: "-- opc.c" + <arch>-asm.c additions use: "-- asm.c" + <arch>-dis.c additions use: "-- dis.c" + <arch>-ibd.h additions use: "-- ibd.h" +*/ + +/* -- opc.h */ + +/* Check applicability of instructions against machines. */ +#define CGEN_VALIDATE_INSN_SUPPORTED + +/* Allows reason codes to be output when assembler errors occur. */ +#define CGEN_VERBOSE_ASSEMBLER_ERRORS + +/* Override disassembly hashing - there are variable bits in the top + byte of these instructions. */ +#define CGEN_DIS_HASH_SIZE 8 +#define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE) + +#define CGEN_ASM_HASH_SIZE 127 +#define CGEN_ASM_HASH(insn) ms1_asm_hash (insn) + +extern unsigned int ms1_asm_hash (const char *); + +extern int ms1_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *); + + +/* -- opc.c */ +#include "safe-ctype.h" + +/* Special check to ensure that instruction exists for given machine. */ + +int +ms1_cgen_insn_supported (CGEN_CPU_DESC cd, + const CGEN_INSN *insn) +{ + int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH); + + /* No mach attribute? Assume it's supported for all machs. */ + if (machs == 0) + return 1; + + return ((machs & cd->machs) != 0); +} + +/* A better hash function for instruction mnemonics. */ + +unsigned int +ms1_asm_hash (const char* insn) +{ + unsigned int hash; + const char* m = insn; + + for (hash = 0; *m && ! ISSPACE (*m); m++) + hash = (hash * 23) ^ (0x1F & TOLOWER (*m)); + + /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */ + + return hash % CGEN_ASM_HASH_SIZE; +} + + +/* -- asm.c */ +/* Range checking for signed numbers. Returns 0 if acceptable + and 1 if the value is out of bounds for a signed quantity. */ + +static int +signed_out_of_bounds (long val) +{ + if ((val < -32768) || (val > 32767)) + return 1; + return 0; +} + +static const char * +parse_loopsize (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + void *arg) +{ + signed long * valuep = (signed long *) arg; + const char *errmsg; + bfd_reloc_code_real_type code = BFD_RELOC_NONE; + enum cgen_parse_operand_result result_type; + bfd_vma value; + + /* Is it a control transfer instructions? */ + if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_LOOPSIZE) + { + code = BFD_RELOC_MS1_PCINSN8; + errmsg = cgen_parse_address (cd, strp, opindex, code, + & result_type, & value); + *valuep = value; + return errmsg; + } + + abort (); +} + +static const char * +parse_imm16 (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + void *arg) +{ + signed long * valuep = (signed long *) arg; + const char *errmsg; + enum cgen_parse_operand_result result_type; + bfd_reloc_code_real_type code = BFD_RELOC_NONE; + bfd_vma value; + + /* Is it a control transfer instructions? */ + if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O) + { + code = BFD_RELOC_16_PCREL; + errmsg = cgen_parse_address (cd, strp, opindex, code, + & result_type, & value); + if (errmsg == NULL) + { + if (signed_out_of_bounds (value)) + errmsg = _("Operand out of range. Must be between -32768 and 32767."); + } + *valuep = value; + return errmsg; + } + + /* If it's not a control transfer instruction, then + we have to check for %OP relocating operators. */ + if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16L) + ; + else if (strncmp (*strp, "%hi16", 5) == 0) + { + *strp += 5; + code = BFD_RELOC_HI16; + } + else if (strncmp (*strp, "%lo16", 5) == 0) + { + *strp += 5; + code = BFD_RELOC_LO16; + } + + /* If we found a %OP relocating operator, then parse it as an address. + If not, we need to parse it as an integer, either signed or unsigned + depending on which operand type we have. */ + if (code != BFD_RELOC_NONE) + { + /* %OP relocating operator found. */ + errmsg = cgen_parse_address (cd, strp, opindex, code, + & result_type, & value); + if (errmsg == NULL) + { + switch (result_type) + { + case (CGEN_PARSE_OPERAND_RESULT_NUMBER): + if (code == BFD_RELOC_HI16) + value = (value >> 16) & 0xFFFF; + else if (code == BFD_RELOC_LO16) + value = value & 0xFFFF; + else + errmsg = _("Biiiig Trouble in parse_imm16!"); + break; + + case (CGEN_PARSE_OPERAND_RESULT_QUEUED): + /* No special processing for this case. */ + break; + + default: + errmsg = _("%operator operand is not a symbol"); + break; + } + } + *valuep = value; + } + else + { + /* Parse hex values like 0xffff as unsigned, and sign extend + them manually. */ + int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16); + + if ((*strp)[0] == '0' + && ((*strp)[1] == 'x' || (*strp)[1] == 'X')) + parse_signed = 0; + + /* No relocating operator. Parse as an number. */ + if (parse_signed) + { + /* Parse as as signed integer. */ + + errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep); + + if (errmsg == NULL) + { +#if 0 + /* Manual range checking is needed for the signed case. */ + if (*valuep & 0x8000) + value = 0xffff0000 | *valuep; + else + value = *valuep; + + if (signed_out_of_bounds (value)) + errmsg = _("Operand out of range. Must be between -32768 and 32767."); + /* Truncate to 16 bits. This is necessary + because cgen will have sign extended *valuep. */ + *valuep &= 0xFFFF; +#endif + } + } + else + { + /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */ + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep); + + if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16 + && *valuep >= 0x8000 + && *valuep <= 0xffff) + *valuep -= 0x10000; + } + } + + return errmsg; +} + + +static const char * +parse_dup (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0) + { + *strp += 3; + *valuep = 1; + } + else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0) + { + *strp += 2; + *valuep = 0; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + + +static const char * +parse_ball (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0) + { + *strp += 3; + *valuep = 1; + } + else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0) + { + *strp += 3; + *valuep = 0; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + +static const char * +parse_xmode (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0) + { + *strp += 2; + *valuep = 1; + } + else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0) + { + *strp += 2; + *valuep = 0; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + +static const char * +parse_rc (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0) + { + *strp += 1; + *valuep = 1; + } + else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0) + { + *strp += 1; + *valuep = 0; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + +static const char * +parse_cbrb (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0) + { + *strp += 2; + *valuep = 1; + } + else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0) + { + *strp += 2; + *valuep = 0; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + +static const char * +parse_rbbc (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0) + { + *strp += 2; + *valuep = 0; + } + else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0) + { + *strp += 3; + *valuep = 1; + } + else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0) + { + *strp += 3; + *valuep = 2; + } + else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0) + { + *strp += 2; + *valuep = 3; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + return errmsg; +} + +static const char * +parse_type (CGEN_CPU_DESC cd, + const char **strp, + int opindex, + unsigned long *valuep) +{ + const char *errmsg = NULL; + + if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0) + { + *strp += 3; + *valuep = 0; + } + else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0) + { + *strp += 4; + *valuep = 1; + } + else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0) + { + *strp += 2; + *valuep = 2; + } + else + errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); + + if ((errmsg == NULL) && (*valuep == 3)) + errmsg = _("invalid operand. type may have values 0,1,2 only."); + + return errmsg; +} + +/* -- dis.c */ +static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int); +static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int); + +static void +print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, + void * dis_info, + long value, + unsigned int attrs ATTRIBUTE_UNUSED, + bfd_vma pc ATTRIBUTE_UNUSED, + int length ATTRIBUTE_UNUSED) +{ + disassemble_info *info = (disassemble_info *) dis_info; + + info->fprintf_func (info->stream, "$%lx", value); + + if (0) + print_normal (cd, dis_info, value, attrs, pc, length); +} + +static void +print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, + void * dis_info, + long value, + unsigned int attrs ATTRIBUTE_UNUSED, + bfd_vma pc ATTRIBUTE_UNUSED, + int length ATTRIBUTE_UNUSED) +{ + print_address (cd, dis_info, value + pc, attrs, pc, length); +} + +/* -- */ + + + + + |