text: /* Opcode table header for Visium.
  
     Copyright (C) 2003-2020 Free Software Foundation, Inc.
  
     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
  {
    const char *name;
    unsigned char code;
  };
  
  static const struct reg_entry gen_reg_table[] ATTRIBUTE_UNUSED =
  {
    {"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},
  };
  
  static const struct reg_entry fp_reg_table[] ATTRIBUTE_UNUSED =
  {
    {"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},
  };
  
  static const struct cc_entry
  {
    const char *name;
    int code;
  } cc_table [] ATTRIBUTE_UNUSED =
  {
    {"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
  {
    const char *mnem;
    enum addressing_mode mode;
    unsigned code;
    char flags;
  }
  opcode_table[] ATTRIBUTE_UNUSED =
  {
    { "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 },
  };
  
  