From 1945cfa59de0a6093011891e1974ac2b6d25658f Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Sat, 6 Dec 2014 16:25:55 +0100 Subject: [PATCH] Add Visium support to opcodes include/ * dis-asm.h (print_insn_visium): Declare. include/opcode/ * visium.h: New file. opcodes/ * configure.ac: Add Visium support. * configure: Regenerate. * Makefile.am (TARGET_LIBOPCODES_CFILES): Add visium-dis.c and visium-opc.c. * Makefile.in: Regenerate. * disassemble.c (ARCH_visium): Define if ARCH_all. (disassembler): Deal with bfd_arch_visium if ARCH_visium. * visium-dis.c: New file. * visium-opc.c: Likewise. * po/POTFILES.in: Regenerate. --- include/ChangeLog | 4 + include/dis-asm.h | 1 + include/opcode/ChangeLog | 4 + include/opcode/visium.h | 337 ++++++++++++++++ opcodes/ChangeLog | 13 + opcodes/Makefile.am | 2 + opcodes/Makefile.in | 4 + opcodes/configure | 1 + opcodes/configure.ac | 1 + opcodes/disassemble.c | 6 + opcodes/po/POTFILES.in | 2 + opcodes/visium-dis.c | 834 +++++++++++++++++++++++++++++++++++++++ opcodes/visium-opc.c | 23 ++ 13 files changed, 1232 insertions(+) create mode 100644 include/opcode/visium.h create mode 100644 opcodes/visium-dis.c create mode 100644 opcodes/visium-opc.c diff --git a/include/ChangeLog b/include/ChangeLog index ea722954876..e80d2ec993b 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2014-12-06 Eric Botcazou + + * dis-asm.h (print_insn_visium): Declare. + 2014-11-24 Mark Wielaard * dwarf2.h: Add DW_LANG_C_plus_plus_11, DW_LANG_C11 and diff --git a/include/dis-asm.h b/include/dis-asm.h index 1b653b5db9e..7260d59a7b8 100644 --- a/include/dis-asm.h +++ b/include/dis-asm.h @@ -295,6 +295,7 @@ extern int print_insn_tilegx (bfd_vma, disassemble_info *); extern int print_insn_tilepro (bfd_vma, disassemble_info *); extern int print_insn_v850 (bfd_vma, disassemble_info *); extern int print_insn_vax (bfd_vma, disassemble_info *); +extern int print_insn_visium (bfd_vma, disassemble_info *); extern int print_insn_w65 (bfd_vma, disassemble_info *); extern int print_insn_xc16x (bfd_vma, disassemble_info *); extern int print_insn_xgate (bfd_vma, disassemble_info *); diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index 062ecc008fa..a2248dc6bd6 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,7 @@ +2014-12-06 Eric Botcazou + + * visium.h: New file. + 2014-11-28 Sandra Loosemore * nios2.h (NIOS2_INSN_ADDI, NIOS2_INSN_ANDI): Delete. diff --git a/include/opcode/visium.h b/include/opcode/visium.h new file mode 100644 index 00000000000..49a8e1a0b70 --- /dev/null +++ b/include/opcode/visium.h @@ -0,0 +1,337 @@ +/* Opcode table header for Visium. + + Copyright (C) 2003-2014 Free Software Foundation. + + This file is part of GDB, GAS, and GNU binutils. + + GDB, GAS and the GNU binutils are free software; you can redistribute + them and/or modify them under the terms of the GNU General Public + License as published by the Free Software Foundation; either version 3, + or (at your option) any later version. + + GDB, GAS, and the GNU binutils are distributed in the hope that they + 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 file; see the file COPYING3. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +enum visium_opcode_arch_val +{ + VISIUM_OPCODE_ARCH_DEF = 0, + VISIUM_OPCODE_ARCH_GR5, + VISIUM_OPCODE_ARCH_GR6, + VISIUM_OPCODE_ARCH_BAD +}; + +/* The highest architecture in the table. */ +#define VISIUM_OPCODE_ARCH_MAX (VISIUM_OPCODE_ARCH_BAD - 1) + +/* Given an enum visium_opcode_arch_val, return the bitmask to use in + insn encoding/decoding. */ +#define VISIUM_OPCODE_ARCH_MASK(arch) (1 << (arch)) + +/* Some defines to make life easy. */ +#define MASK_DEF VISIUM_OPCODE_ARCH_MASK (VISIUM_OPCODE_ARCH_DEF) +#define MASK_GR5 VISIUM_OPCODE_ARCH_MASK (VISIUM_OPCODE_ARCH_GR5) +#define MASK_GR6 VISIUM_OPCODE_ARCH_MASK (VISIUM_OPCODE_ARCH_GR6) + +/* Bit masks of architectures supporting the insn. */ +#define def (MASK_DEF | MASK_GR5 | MASK_GR6) +#define gr5 (MASK_GR5 | MASK_GR6) +#define gr6 (MASK_GR6) + +/* The condition code field is not used (zero) for most instructions. + BRR and BRA make normal use of it. Floating point instructions use + it as a sub-opcode. */ +#define CC_MASK (0xf << 27) + +/* It seems a shame not to use these bits in a class 0 instruction, + since they could be used to extend the range of the branch. */ +#define CLASS0_UNUSED_MASK (0x1f << 16) + +/* For class 1 instructions the following bit is unused. */ +#define CLASS1_UNUSED_MASK (1 << 9) + +/* For class 1 instructions this field gives the index for a write + instruction, the specific operation for an EAM instruction, or + the floating point destination register for a floating point + instruction. */ +#define CLASS1_INDEX_MASK (0x1f << 10) + +/* For class 3 instructions the following field gives the destination + general register. */ +#define CLASS3_DEST_MASK (0x1f << 10) + +/* For class 1 and class 3 instructions the following bit selects an + EAM write/read rather than a memory write/read. */ +#define EAM_SELECT_MASK (1 << 15) + +/* Floating point instructions are distinguished from general EAM + instructions by the following bit. */ +#define FP_SELECT_MASK (1 << 3) + +/* For both class 1 and class 3 the following fields give, where + appropriate the srcA and srcB registers whether floating point + or general. */ +#define SRCA_MASK (0x1f << 16) +#define SRCB_MASK (0x1f << 4) + +/* The class 3 interrupt bit. It turns a BRA into a SYS1, and an + RFLAG into a SYS2. This bit should not be set in the user's + class 3 instructions. This bit is also used in class 3 + to distinguish between floating point and other EAM operations. + (see FP_SELECT_MASK). */ +#define CLASS3_INT (1 << 3) + +/* Class 3 shift instructions use this bit to indicate that the + srcB field is a 5 bit immediate shift count rather than a + register number. */ +#define CLASS3_SOURCEB_IMMED (1 << 9) + +#define BMD 0x02630004 +#define BMI 0x82230004 +#define DSI 0x82800004 +#define ENI 0x02a00004 +#define RFI 0x82fe01d4 + +struct reg_entry +{ + char *name; + unsigned char code; +}; + +const struct reg_entry gen_reg_table[] = +{ + {"fp", 0x16}, + {"r0", 0x0}, + {"r1", 0x1}, + {"r10", 0xA}, + {"r11", 0xB}, + {"r12", 0xC}, + {"r13", 0xD}, + {"r14", 0xE}, + {"r15", 0xF}, + {"r16", 0x10}, + {"r17", 0x11}, + {"r18", 0x12}, + {"r19", 0x13}, + {"r2", 0x2}, + {"r20", 0x14}, + {"r21", 0x15}, + {"r22", 0x16}, + {"r23", 0x17}, + {"r24", 0x18}, + {"r25", 0x19}, + {"r26", 0x1a}, + {"r27", 0x1b}, + {"r28", 0x1c}, + {"r29", 0x1d}, + {"r3", 0x3}, + {"r30", 0x1e}, + {"r31", 0x1f}, + {"r4", 0x4}, + {"r5", 0x5}, + {"r6", 0x6}, + {"r7", 0x7}, + {"r8", 0x8}, + {"r9", 0x9}, + {"sp", 0x17}, +}; + +const struct reg_entry fp_reg_table[] = +{ + {"f0", 0x0}, + {"f1", 0x1}, + {"f10", 0xa}, + {"f11", 0xb}, + {"f12", 0xc}, + {"f13", 0xd}, + {"f14", 0xe}, + {"f15", 0xf}, + {"f2", 0x2}, + {"f3", 0x3}, + {"f4", 0x4}, + {"f5", 0x5}, + {"f6", 0x6}, + {"f7", 0x7}, + {"f8", 0x8}, + {"f9", 0x9}, +}; + +const struct cc_entry +{ + char *name; + int code; +} cc_table [] = +{ + {"cc", 6}, + {"cs", 2}, + {"eq", 1}, + {"fa", 0}, + {"ge", 9}, + {"gt", 10}, + {"hi", 11}, + {"le", 12}, + {"ls", 13}, + {"lt", 14}, + {"nc", 8}, + {"ne", 5}, + {"ns", 4}, + {"oc", 7}, + {"os", 3}, + {"tr", 15}, +}; + +enum addressing_mode +{ + mode_d, /* register := */ + mode_a, /* op= register */ + mode_da, /* register := register */ + mode_ab, /* register * register */ + mode_dab, /* register := register * register */ + mode_iab, /* 5-bit immediate * register * register */ + mode_0ab, /* zero * register * register */ + mode_da0, /* register := register * zero */ + mode_cad, /* condition * register * register */ + mode_das, /* register := register * 5-bit immed/register shift count */ + mode_di, /* register := 5-bit immediate */ + mode_ir, /* 5-bit immediate * register */ + mode_ai, /* register 16-bit unsigned immediate */ + mode_i, /* 16-bit unsigned immediate */ + mode_bax, /* register * register * 5-bit immediate */ + mode_dax, /* register := register * 5-bit immediate */ + mode_s, /* special mode */ + mode_sr, /* special mode with register */ + mode_ci, /* condition * 16-bit signed word displacement */ + mode_fdab, /* float := float * float */ + mode_ifdab, /* fpinst: 4-bit immediate * float * float * float */ + mode_idfab, /* fpuread: 4-bit immediate * register * float * float */ + mode_fda, /* float := float */ + mode_fdra, /* float := register */ + mode_rdfab, /* register := float * float */ + mode_rdfa, /* register := float */ + mode_rrr, /* 3 register sources and destinations (block move) */ +}; + +#define class0 (0<<25) +#define class1 (1<<25) +#define class2 (2<<25) +#define class3 (3<<25) + +static const struct opcode_entry +{ + char *mnem; + enum addressing_mode mode; + unsigned code; + char flags; +} +opcode_table[] = +{ + { "adc.b", mode_dab, class3|(1<<21)|(1), def }, + { "adc.l", mode_dab, class3|(1<<21)|(4), def }, + { "adc.w", mode_dab, class3|(1<<21)|(2), def }, + { "add.b", mode_dab, class3|(0<<21)|(1), def }, + { "add.l", mode_dab, class3|(0<<21)|(4), def }, + { "add.w", mode_dab, class3|(0<<21)|(2), def }, + { "addi", mode_ai, class2, def }, + { "and.b", mode_dab, class3|(10<<21)|(1), def}, + { "and.l", mode_dab, class3|(10<<21)|(4), def }, + { "and.w", mode_dab, class3|(10<<21)|(2), def }, + { "asl.b", mode_das, class3|(7<<21)|(1), def }, + { "asl.l", mode_das, class3|(7<<21)|(4), def }, + { "asl.w", mode_das, class3|(7<<21)|(2), def }, + { "asld", mode_a, class1|(15<<21)|(1<<15)|(11<<10)|(4), def }, + { "asr.b", mode_das, class3|(5<<21)|(1), def }, + { "asr.l", mode_das, class3|(5<<21)|(4), def }, + { "asr.w", mode_das, class3|(5<<21)|(2), def }, + { "asrd", mode_a, class1|(15<<21)|(1<<15)|(9<<10)|(4), def }, + { "bmd", mode_rrr, class1|(3<<21)|(3<<16)|(4), gr6 }, + { "bmi", mode_rrr, class1|(1<<21)|(3<<16)|(4), gr6 }, + { "bra", mode_cad, class3|(12<<21)|(4), def }, + { "brr", mode_ci, class0, def }, + { "cmp.b", mode_0ab, class3|(2<<21)|(1), def }, + { "cmp.l", mode_0ab, class3|(2<<21)|(4), def }, + { "cmp.w", mode_0ab, class3|(2<<21)|(2), def }, + { "cmpc.b", mode_0ab, class3|(3<<21)|(1), def }, + { "cmpc.l", mode_0ab, class3|(3<<21)|(4), def }, + { "cmpc.w", mode_0ab, class3|(3<<21)|(2), def }, + { "divds", mode_a, class1|(15<<21)|(1<<15)|(6<<10)|(4), def }, + { "divdu", mode_a, class1|(15<<21)|(1<<15)|(7<<10)|(4), def }, + { "divs", mode_a, class1|(15<<21)|(1<<15)|(2<<10)|(4), def }, + { "divu", mode_a, class1|(15<<21)|(1<<15)|(3<<10)|(4), def }, + { "dsi", mode_s, class1|(4<<21)|(4), def }, + { "eamread", mode_di, class3|(15<<21)|(1<<15)|(1<<9)|(4), def }, + { "eamwrite", mode_iab, class1|(15<<21)|(1<<15)|(4), def }, + { "eni", mode_s, class1|(5<<21)|(4), def }, + { "extb.b", mode_da, class3|(14<<21)|(1), def }, + { "extb.l", mode_da, class3|(14<<21)|(4), def }, + { "extb.w", mode_da, class3|(14<<21)|(2), def }, + { "extw.l", mode_da, class3|(4<<21)|(4), def }, + { "extw.w", mode_da, class3|(4<<21)|(2), def }, + { "fabs", mode_fda, class1|(7<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fadd", mode_fdab, class1|(1<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fcmp", mode_rdfab,class3|(10<<27)|(15<<21)|(1<<15)|(1<<9)|(1<<3)|(4), gr5 }, + { "fcmpe", mode_rdfab,class3|(11<<27)|(15<<21)|(1<<15)|(1<<9)|(1<<3)|(4), gr5 }, + { "fdiv", mode_fdab, class1|(4<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fload", mode_fdra, class1|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fmove", mode_fda, class1|(12<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5}, + { "fmult", mode_fdab, class1|(3<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fneg", mode_fda, class1|(6<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fpinst", mode_ifdab,class1|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fpuread", mode_idfab,class3|(15<<21)|(1<<15)|(1<<9)|(1<<3)|(4), gr5 }, + { "fsqrt", mode_fda, class1|(5<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "fstore", mode_rdfa, class3|(15<<21)|(1<<15)|(1<<9)|(1<<3)|(4), gr5 }, + { "fsub", mode_fdab, class1|(2<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "ftoi", mode_fda, class1|(8<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "itof", mode_fda, class1|(9<<27)|(15<<21)|(1<<15)|(1<<3)|(4), gr5 }, + { "lsr.b", mode_das, class3|(6<<21)|(1), def }, + { "lsr.l", mode_das, class3|(6<<21)|(4), def }, + { "lsr.w", mode_das, class3|(6<<21)|(2), def }, + { "lsrd", mode_a, class1|(15<<21)|(1<<15)|(10<<10)|(4), def }, + { "move.b", mode_da0, class3|(9<<21)|(1), def }, + { "move.l", mode_da0, class3|(9<<21)|(4), def }, + { "move.w", mode_da0, class3|(9<<21)|(2), def }, + { "movil", mode_ai, class2|(4<<21), def }, + { "moviq", mode_ai, class2|(6<<21), def }, + { "moviu", mode_ai, class2|(5<<21), def }, + { "mults", mode_ab, class1|(15<<21)|(1<<15)|(0<<10)|(4), def }, + { "multu", mode_ab, class1|(15<<21)|(1<<15)|(1<<10)|(4), def }, + { "nop", mode_s, class0, def }, + { "not.b", mode_da, class3|(11<<21)|(1), def }, + { "not.l", mode_da, class3|(11<<21)|(4), def }, + { "not.w", mode_da, class3|(11<<21)|(2), def }, + { "or.b", mode_dab, class3|(9<<21)|(1), def }, + { "or.l", mode_dab, class3|(9<<21)|(4), def }, + { "or.w", mode_dab, class3|(9<<21)|(2), def }, + { "read.b", mode_dax, class3|(15<<21)|(1<<9)|(1), def }, + { "read.l", mode_dax, class3|(15<<21)|(1<<9)|(4), def }, + { "read.w", mode_dax, class3|(15<<21)|(1<<9)|(2), def }, + { "readmda", mode_d, class3|(15<<21)|(1<<15)|(1<<9)|(4), def }, + { "readmdb", mode_d, class3|(15<<21)|(1<<15)|(1<<9)|(1<<4)|(4), def }, + { "readmdc", mode_d, class3|(15<<21)|(1<<15)|(1<<9)|(2<<4)|(4), def }, + { "rfi", mode_s, class1|(7<<21)|(30<<16)|(29<<4)|(4), def }, + { "rflag", mode_d, class3|(13<<21)|(4), def }, + { "stop", mode_ir, class1|(0<<21)|(4), def }, + { "sub.b", mode_dab, class3|(2<<21)|(1), def }, + { "sub.l", mode_dab, class3|(2<<21)|(4), def }, + { "sub.w", mode_dab, class3|(2<<21)|(2), def }, + { "subc.b", mode_dab, class3|(3<<21)|(1), def }, + { "subc.l", mode_dab, class3|(3<<21)|(4), def }, + { "subc.w", mode_dab, class3|(3<<21)|(2), def }, + { "subi", mode_ai, class2|(2<<21), def }, + { "trace", mode_ir, class1|(13<<21), def }, + { "write.b", mode_bax, class1|(15<<21)|(1), def }, + { "write.l", mode_bax, class1|(15<<21)|(4), def }, + { "write.w", mode_bax, class1|(15<<21)|(2), def }, + { "writemd", mode_ab, class1|(15<<21)|(1<<15)|(4<<10)|(4), def }, + { "writemdc", mode_a, class1|(15<<21)|(1<<15)|(5<<10)|(4), def }, + { "wrtl", mode_i, class2|(8<<21), gr6 }, + { "wrtu", mode_i, class2|(9<<21), gr6 }, + { "xor.b", mode_dab, class3|(8<<21)|(1), def }, + { "xor.l", mode_dab, class3|(8<<21)|(4), def }, + { "xor.w", mode_dab, class3|(8<<21)|(2), def }, +}; diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 00bb53ad360..d64d138d767 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,16 @@ +2014-12-06 Eric Botcazou + + * configure.ac: Add Visium support. + * configure: Regenerate. + * Makefile.am (TARGET_LIBOPCODES_CFILES): Add visium-dis.c and + visium-opc.c. + * Makefile.in: Regenerate. + * disassemble.c (ARCH_visium): Define if ARCH_all. + (disassembler): Deal with bfd_arch_visium if ARCH_visium. + * visium-dis.c: New file. + * visium-opc.c: Likewise. + * po/POTFILES.in: Regenerate. + 2014-11-30 Alan Modra * ppc-opc.c (powerpc_opcodes): Make mftb* generate mfspr for diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am index 4acc4363f38..9b762398d92 100644 --- a/opcodes/Makefile.am +++ b/opcodes/Makefile.am @@ -250,6 +250,8 @@ TARGET_LIBOPCODES_CFILES = \ v850-dis.c \ v850-opc.c \ vax-dis.c \ + visium-dis.c \ + visium-opc.c \ w65-dis.c \ xc16x-asm.c \ xc16x-desc.c \ diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index 46ef017de6a..4f02d81c8d7 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -523,6 +523,8 @@ TARGET_LIBOPCODES_CFILES = \ v850-dis.c \ v850-opc.c \ vax-dis.c \ + visium-dis.c \ + visium-opc.c \ w65-dis.c \ xc16x-asm.c \ xc16x-desc.c \ @@ -923,6 +925,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/v850-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/v850-opc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vax-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visium-dis.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/visium-opc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w65-dis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xc16x-asm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xc16x-desc.Plo@am__quote@ diff --git a/opcodes/configure b/opcodes/configure index 7f1369930e0..c97bdf64032 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -12626,6 +12626,7 @@ if test x${all_targets} = xfalse ; then bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850_rh850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_vax_arch) ta="$ta vax-dis.lo" ;; + bfd_visium_arch) ta="$ta visium-dis.lo visium-opc.lo" ;; bfd_w65_arch) ta="$ta w65-dis.lo" ;; bfd_we32k_arch) ;; bfd_xc16x_arch) ta="$ta xc16x-asm.lo xc16x-desc.lo xc16x-dis.lo xc16x-ibld.lo xc16x-opc.lo" using_cgen=yes ;; diff --git a/opcodes/configure.ac b/opcodes/configure.ac index b93e855a719..39eb2fbe9a7 100644 --- a/opcodes/configure.ac +++ b/opcodes/configure.ac @@ -343,6 +343,7 @@ if test x${all_targets} = xfalse ; then bfd_v850ea_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_v850_rh850_arch) ta="$ta v850-opc.lo v850-dis.lo" ;; bfd_vax_arch) ta="$ta vax-dis.lo" ;; + bfd_visium_arch) ta="$ta visium-dis.lo visium-opc.lo" ;; bfd_w65_arch) ta="$ta w65-dis.lo" ;; bfd_we32k_arch) ;; bfd_xc16x_arch) ta="$ta xc16x-asm.lo xc16x-desc.lo xc16x-dis.lo xc16x-ibld.lo xc16x-opc.lo" using_cgen=yes ;; diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c index 0a0814ebddb..63103bb4b8f 100644 --- a/opcodes/disassemble.c +++ b/opcodes/disassemble.c @@ -89,6 +89,7 @@ #define ARCH_tilepro #define ARCH_v850 #define ARCH_vax +#define ARCH_visium #define ARCH_w65 #define ARCH_xstormy16 #define ARCH_xc16x @@ -493,6 +494,11 @@ disassembler (abfd) disassemble = print_insn_vax; break; #endif +#ifdef ARCH_visium + case bfd_arch_visium: + disassemble = print_insn_visium; + break; +#endif #ifdef ARCH_frv case bfd_arch_frv: disassemble = print_insn_frv; diff --git a/opcodes/po/POTFILES.in b/opcodes/po/POTFILES.in index 0212748ba05..8e8e122bd67 100644 --- a/opcodes/po/POTFILES.in +++ b/opcodes/po/POTFILES.in @@ -207,6 +207,8 @@ tilepro-opc.c v850-dis.c v850-opc.c vax-dis.c +visium-dis.c +visium-opc.c w65-dis.c w65-opc.h xc16x-asm.c diff --git a/opcodes/visium-dis.c b/opcodes/visium-dis.c new file mode 100644 index 00000000000..96be9721b1d --- /dev/null +++ b/opcodes/visium-dis.c @@ -0,0 +1,834 @@ +/* Single instruction disassembler for the Visium. + + Copyright (C) 2002-2014 Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library 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 3, or (at your option) + any later version. + + It 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. */ + +#include "sysdep.h" +#include "dis-asm.h" +#include "opcode/visium.h" + +#include +#include +#include +#include +#include + +/* Maximum length of an instruction. */ +#define MAXLEN 4 + +struct private +{ + /* Points to first byte not fetched. */ + bfd_byte *max_fetched; + bfd_byte the_buffer[MAXLEN]; + bfd_vma insn_start; + jmp_buf bailout; +}; + +/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) + to ADDR (exclusive) are valid. Returns 1 for success, longjmps + on error. */ +#define FETCH_DATA(info, addr) \ + ((addr) <= ((struct private *)(info->private_data))->max_fetched \ + ? 1 : fetch_data ((info), (addr))) + +static int fetch_data (struct disassemble_info *info, bfd_byte * addr); + +static int +fetch_data (struct disassemble_info *info, bfd_byte *addr) +{ + int status; + struct private *priv = (struct private *) info->private_data; + bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); + + status = (*info->read_memory_func) (start, + priv->max_fetched, + addr - priv->max_fetched, info); + if (status != 0) + { + (*info->memory_error_func) (status, start, info); + longjmp (priv->bailout, 1); + } + else + priv->max_fetched = addr; + return 1; +} + +static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" }; + +static char *cc_names[] = +{ + "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc", + "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr" +}; + +/* Disassemble non-storage relative instructions. */ + +static int +disassem_class0 (disassemble_info *info, unsigned int ins) +{ + int opcode = (ins >> 21) & 0x000f; + + if (ins & CLASS0_UNUSED_MASK) + goto illegal_opcode; + + switch (opcode) + { + case 0: + /* BRR instruction. */ + { + unsigned cbf = (ins >> 27) & 0x000f; + int displacement = ((int) (ins << 16)) >> 16; + + if (ins == 0) + (*info->fprintf_func) (info->stream, "nop"); + else + (*info->fprintf_func) (info->stream, "brr %s,%+d", + cc_names[cbf], displacement); + } + break; + case 1: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 2: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 3: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 4: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 5: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 6: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 7: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 8: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 9: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 10: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 11: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 12: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 13: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 14: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 15: + /* Illegal opcode. */ + goto illegal_opcode; + break; + } + return 0; + +illegal_opcode: + return -1; +} + +/* Disassemble non-storage register class instructions. */ + +static int +disassem_class1 (disassemble_info *info, unsigned int ins) +{ + int opcode = (ins >> 21) & 0xf; + int source_a = (ins >> 16) & 0x1f; + int source_b = (ins >> 4) & 0x1f; + int indx = (ins >> 10) & 0x1f; + + int size = ins & 0x7; + + if (ins & CLASS1_UNUSED_MASK) + goto illegal_opcode; + + switch (opcode) + { + case 0: + /* Stop. */ + (*info->fprintf_func) (info->stream, "stop"); + break; + case 1: + /* BMI - Block Move Indirect. */ + if (ins != BMI) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "bmi r1,r2,r3"); + break; + case 2: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 3: + /* BMD - Block Move Direct. */ + if (ins != BMD) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "bmd r1,r2,r3"); + break; + case 4: + /* DSI - Disable Interrupts. */ + if (ins != DSI) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "dsi"); + break; + + case 5: + /* ENI - Enable Interrupts. */ + if (ins != ENI) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "eni"); + break; + + case 6: + /* Illegal opcode (was EUT). */ + goto illegal_opcode; + break; + case 7: + /* RFI - Return from Interrupt. */ + if (ins != RFI) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "rfi"); + break; + case 8: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 9: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 10: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 11: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 12: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 13: + goto illegal_opcode; + break; + case 14: + goto illegal_opcode; + break; + case 15: + if (ins & EAM_SELECT_MASK) + { + /* Extension arithmetic module write */ + int fp_ins = (ins >> 27) & 0xf; + + if (size != 4) + goto illegal_opcode; + + if (ins & FP_SELECT_MASK) + { + /* Which floating point instructions don't need a fsrcB + register. */ + const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 0, 0, 1, 0, 0, 0 + }; + if (no_fsrcb[fp_ins] && source_b) + goto illegal_opcode; + + /* Check that none of the floating register register numbers + is higher than 15. (If this is fload, then srcA is a + general register. */ + if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20))) + goto illegal_opcode; + + switch (fp_ins) + { + case 0: + (*info->fprintf_func) (info->stream, "fload f%d,r%d", + indx, source_a); + break; + case 1: + (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d", + indx, source_a, source_b); + break; + case 2: + (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d", + indx, source_a, source_b); + break; + case 3: + (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d", + indx, source_a, source_b); + break; + case 4: + (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d", + indx, source_a, source_b); + break; + case 5: + (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d", + indx, source_a); + break; + case 6: + (*info->fprintf_func) (info->stream, "fneg f%d,f%d", + indx, source_a); + break; + case 7: + (*info->fprintf_func) (info->stream, "fabs f%d,f%d", + indx, source_a); + break; + case 8: + (*info->fprintf_func) (info->stream, "ftoi f%d,f%d", + indx, source_a); + break; + case 9: + (*info->fprintf_func) (info->stream, "itof f%d,f%d", + indx, source_a); + break; + case 12: + (*info->fprintf_func) (info->stream, "fmove f%d,f%d", + indx, source_a); + break; + default: + (*info->fprintf_func) (info->stream, + "fpinst %d,f%d,f%d,f%d", fp_ins, + indx, source_a, source_b); + break; + } + } + else + { + /* Which EAM operations do not need a srcB register. */ + const int no_srcb[32] = + { 0, 0, 1, 1, 0, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (no_srcb[indx] && source_b) + goto illegal_opcode; + + if (fp_ins) + goto illegal_opcode; + + switch (indx) + { + case 0: + (*info->fprintf_func) (info->stream, "mults r%d,r%d", + source_a, source_b); + break; + case 1: + (*info->fprintf_func) (info->stream, "multu r%d,r%d", + source_a, source_b); + break; + case 2: + (*info->fprintf_func) (info->stream, "divs r%d", + source_a); + break; + case 3: + (*info->fprintf_func) (info->stream, "divu r%d", + source_a); + break; + case 4: + (*info->fprintf_func) (info->stream, "writemd r%d,r%d", + source_a, source_b); + break; + case 5: + (*info->fprintf_func) (info->stream, "writemdc r%d", + source_a); + break; + case 6: + (*info->fprintf_func) (info->stream, "divds r%d", + source_a); + break; + case 7: + (*info->fprintf_func) (info->stream, "divdu r%d", + source_a); + break; + case 9: + (*info->fprintf_func) (info->stream, "asrd r%d", + source_a); + break; + case 10: + (*info->fprintf_func) (info->stream, "lsrd r%d", + source_a); + break; + case 11: + (*info->fprintf_func) (info->stream, "asld r%d", + source_a); + break; + default: + (*info->fprintf_func) (info->stream, + "eamwrite %d,r%d,r%d", indx, + source_a, source_b); + break; + } + } + } + else + { + /* WRITE - write to memory. */ + (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d", + size_names[size], indx, source_a, source_b); + } + break; + } + + return 0; + +illegal_opcode: + return -1; +} + +/* Disassemble storage immediate class instructions. */ + +static int +disassem_class2 (disassemble_info *info, unsigned int ins) +{ + int opcode = (ins >> 21) & 0xf; + int source_a = (ins >> 16) & 0x1f; + unsigned immediate = ins & 0x0000ffff; + + if (ins & CC_MASK) + goto illegal_opcode; + + switch (opcode) + { + case 0: + /* ADDI instruction. */ + (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a, + immediate); + break; + case 1: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 2: + /* SUBI instruction. */ + (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a, + immediate); + break; + case 3: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 4: + /* MOVIL instruction. */ + (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a, + immediate); + break; + case 5: + /* MOVIU instruction. */ + (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a, + immediate); + break; + case 6: + /* MOVIQ instruction. */ + (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a, + immediate); + break; + case 7: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 8: + /* WRTL instruction. */ + if (source_a != 0) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate); + break; + case 9: + /* WRTU instruction. */ + if (source_a != 0) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate); + break; + case 10: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 11: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 12: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 13: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 14: + /* Illegal opcode. */ + goto illegal_opcode; + break; + case 15: + /* Illegal opcode. */ + goto illegal_opcode; + break; + } + + return 0; + +illegal_opcode: + return -1; +} + +/* Disassemble storage register class instructions. */ + +static int +disassem_class3 (disassemble_info *info, unsigned int ins) +{ + int opcode = (ins >> 21) & 0xf; + int source_b = (ins >> 4) & 0x1f; + int source_a = (ins >> 16) & 0x1f; + int size = ins & 0x7; + int dest = (ins >> 10) & 0x1f; + + /* Those instructions that don't have a srcB register. */ + const int no_srcb[16] = + { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 }; + + /* These are instructions which can take an immediate srcB value. */ + const int srcb_immed[16] = + { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }; + + /* User opcodes should not provide a non-zero srcB register + when none is required. Only a BRA or floating point + instruction should have a non-zero condition code field. + Only a WRITE or EAMWRITE (opcode 15) should select an EAM + or floating point operation. Note that FP_SELECT_MASK is + the same bit (bit 3) as the interrupt bit which + distinguishes SYS1 from BRA and SYS2 from RFLAG. */ + if ((no_srcb[opcode] && source_b) + || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED) + || (opcode != 12 && opcode != 15 && ins & CC_MASK) + || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK))) + goto illegal_opcode; + + + switch (opcode) + { + case 0: + /* ADD instruction. */ + (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 1: + /* ADC instruction. */ + (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 2: + /* SUB instruction. */ + if (dest == 0) + (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d", + size_names[size], source_a, source_b); + else + (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 3: + /* SUBC instruction. */ + if (dest == 0) + (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d", + size_names[size], source_a, source_b); + else + (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 4: + /* EXTW instruction. */ + if (size == 1) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d", + size_names[size], dest, source_a); + break; + case 5: + /* ASR instruction. */ + if (ins & CLASS3_SOURCEB_IMMED) + (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d", + size_names[size], dest, source_a, source_b); + else + (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 6: + /* LSR instruction. */ + if (ins & CLASS3_SOURCEB_IMMED) + (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d", + size_names[size], dest, source_a, source_b); + else + (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 7: + /* ASL instruction. */ + if (ins & CLASS3_SOURCEB_IMMED) + (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d", + size_names[size], dest, source_a, source_b); + else + (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 8: + /* XOR instruction. */ + (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 9: + /* OR instruction. */ + if (source_b == 0) + (*info->fprintf_func) (info->stream, "move.%s r%d,r%d", + size_names[size], dest, source_a); + else + (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 10: + /* AND instruction. */ + (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d", + size_names[size], dest, source_a, source_b); + break; + case 11: + /* NOT instruction. */ + (*info->fprintf_func) (info->stream, "not.%s r%d,r%d", + size_names[size], dest, source_a); + break; + case 12: + /* BRA instruction. */ + { + unsigned cbf = (ins >> 27) & 0x000f; + + if (size != 4) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d", + cc_names[cbf], source_a, dest); + } + break; + case 13: + /* RFLAG instruction. */ + if (source_a || size != 4) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "rflag r%d", dest); + break; + case 14: + /* EXTB instruction. */ + (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d", + size_names[size], dest, source_a); + break; + case 15: + if (!(ins & CLASS3_SOURCEB_IMMED)) + goto illegal_opcode; + + if (ins & EAM_SELECT_MASK) + { + /* Extension arithmetic module read. */ + int fp_ins = (ins >> 27) & 0xf; + + if (size != 4) + goto illegal_opcode; + + if (ins & FP_SELECT_MASK) + { + /* Check fsrcA <= 15 and fsrcB <= 15. */ + if (ins & ((1 << 20) | (1 << 8))) + goto illegal_opcode; + + switch (fp_ins) + { + case 0: + if (source_b) + goto illegal_opcode; + + (*info->fprintf_func) (info->stream, "fstore r%d,f%d", + dest, source_a); + break; + case 10: + (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d", + dest, source_a, source_b); + break; + case 11: + (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d", + dest, source_a, source_b); + break; + default: + (*info->fprintf_func) (info->stream, + "fpuread %d,r%d,f%d,f%d", fp_ins, + dest, source_a, source_b); + break; + } + } + else + { + if (fp_ins || source_a) + goto illegal_opcode; + + switch (source_b) + { + case 0: + (*info->fprintf_func) (info->stream, "readmda r%d", dest); + break; + case 1: + (*info->fprintf_func) (info->stream, "readmdb r%d", dest); + break; + case 2: + (*info->fprintf_func) (info->stream, "readmdc r%d", dest); + break; + default: + (*info->fprintf_func) (info->stream, "eamread r%d,%d", + dest, source_b); + break; + } + } + } + else + { + if (ins & FP_SELECT_MASK) + goto illegal_opcode; + + /* READ instruction. */ + (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)", + size_names[size], dest, source_b, source_a); + } + break; + } + + return 0; + +illegal_opcode: + return -1; + +} + +/* Print the visium instruction at address addr in debugged memory, + on info->stream. Return length of the instruction, in bytes. */ + +int +print_insn_visium (bfd_vma addr, disassemble_info *info) +{ + unsigned ins; + unsigned p1, p2; + int ans; + int i; + + /* Stuff copied from m68k-dis.c. */ + struct private priv; + bfd_byte *buffer = priv.the_buffer; + info->private_data = (PTR) & priv; + priv.max_fetched = priv.the_buffer; + priv.insn_start = addr; + if (setjmp (priv.bailout) != 0) + { + /* Error return. */ + return -1; + } + + /* We do return this info. */ + info->insn_info_valid = 1; + + /* Assume non branch insn. */ + info->insn_type = dis_nonbranch; + + /* Assume no delay. */ + info->branch_delay_insns = 0; + + /* Assume no target known. */ + info->target = 0; + + /* Get 32-bit instruction word. */ + FETCH_DATA (info, buffer + 4); + ins = buffer[0] << 24; + ins |= buffer[1] << 16; + ins |= buffer[2] << 8; + ins |= buffer[3]; + + ans = 0; + + p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3]; + p2 = 0; + for (i = 0; i < 8; i++) + { + p2 += p1 & 1; + p1 >>= 1; + } + + /* Decode the instruction. */ + if (p2 & 1) + ans = -1; + else + { + switch ((ins >> 25) & 0x3) + { + case 0: + ans = disassem_class0 (info, ins); + break; + case 1: + ans = disassem_class1 (info, ins); + break; + case 2: + ans = disassem_class2 (info, ins); + break; + case 3: + ans = disassem_class3 (info, ins); + break; + } + } + + if (ans != 0) + (*info->fprintf_func) (info->stream, "err"); + + /* Return number of bytes consumed (always 4 for the Visium). */ + return 4; +} diff --git a/opcodes/visium-opc.c b/opcodes/visium-opc.c new file mode 100644 index 00000000000..742452c38b6 --- /dev/null +++ b/opcodes/visium-opc.c @@ -0,0 +1,23 @@ +/* Opcode table for the Visium. + + Copyright (C) 2002-2014 Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library 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 3, or (at your option) + any later version. + + It 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. */ + +#include "ansidecl.h" +#include "opcode/visium.h" -- 2.30.2