text: /* Table of opcodes for the Motorola M88k family.
     Copyright (C) 1989-2014 Free Software Foundation, Inc.
  
     This file is part of GDB and GAS.
  
     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 3 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.  */
  
  /*
   *			Disassembler Instruction Table
   *
   *	The first field of the table is the opcode field. If an opcode
   *	is specified which has any non-opcode bits on, a system error
   *	will occur when the system attempts the install it into the
   *	instruction table.  The second parameter is a pointer to the
   *	instruction mnemonic. Each operand is specified by offset, width,
   *	and type. The offset is the bit number of the least significant
   *	bit of the operand with bit 0 being the least significant bit of
   *	the instruction. The width is the number of bits used to specify
   *	the operand. The type specifies the output format to be used for
   *	the operand. The valid formats are: register, register indirect,
   *	hex constant, and bit field specification.  The last field is a
   *	pointer to the next instruction in the linked list.  These pointers
   *	are initialized by init_disasm().
   *
   *				Revision History
   *
   *	Revision 1.0	11/08/85	Creation date
   *		 1.1	02/05/86	Updated instruction mnemonic table MD
   *		 1.2	06/16/86	Updated SIM_FLAGS for floating point
   *		 1.3	09/20/86	Updated for new encoding
   *		 	05/11/89	R. Trawick adapted from Motorola disassembler
   */
  
  #include <stdio.h>
  
  /* Define the number of bits in the primary opcode field of the instruction,
     the destination field, the source 1 and source 2 fields.  */
  
  /* Size of opcode field.  */
  #define OP 8
  
  /* Size of destination.  */
  #define DEST 6
  
  /* Size of source1.  */
  #define SOURCE1 6
  
  /* Size of source2.  */
  #define SOURCE2 6
  
  /* Number of registers.  */
  #define REGs 32
  
  /* Type definitions.  */
  
  typedef unsigned int UINT;
  #define    WORD    long
  #define    FLAG    unsigned
  #define    STATE   short
  
  /* The next four equates define the priorities that the various classes
   * of instructions have regarding writing results back into registers and
   * signalling exceptions.  */
  
  /* PMEM is also defined in <sys/param.h> on Delta 88's.  Sigh!  */
  #undef PMEM
  
  /* Integer priority.  */
  #define    PINT  0
  
  /* Floating point priority.  */
  #define    PFLT  1
  
  /* Memory priority.  */
  #define    PMEM  2
  
  /* Not applicable, instruction doesn't write to regs.  */
  #define    NA    3
  
  /* Highest of these priorities.  */
  #define    HIPRI 3
  
  /* The instruction registers are an artificial mechanism to speed up
   * simulator execution.  In the real processor, an instruction register
   * is 32 bits wide.  In the simulator, the 32 bit instruction is kept in
   * a structure field called rawop, and the instruction is partially decoded,
   * and split into various fields and flags which make up the other fields
   * of the structure.
   * The partial decode is done when the instructions are initially loaded
   * into simulator memory.  The simulator code memory is not an array of
   * 32 bit words, but is an array of instruction register structures.
   * Yes this wastes memory, but it executes much quicker.
   */
  
  struct IR_FIELDS
  {
    unsigned op:OP,
      dest: DEST,
      src1: SOURCE1,
      src2: SOURCE2;
    int ltncy,
      extime,
      /* Writeback priority.  */
      wb_pri;
    /* Immediate size.  */
    unsigned        imm_flags:2,
      /* Register source 1 used.  */
      rs1_used:1,
      /* Register source 2 used. */
      rs2_used:1,
      /* Register source/dest. used.  */
      rsd_used:1,
      /* Complement.  */
      c_flag:1,
      /* Upper half word.  */
      u_flag:1,
      /* Execute next.  */
      n_flag:1,
      /* Uses writeback slot.  */
      wb_flag:1,
      /* Dest size.  */
      dest_64:1,
      /* Source 1 size.  */
      s1_64:1,
      /* Source 2 size.  */
      s2_64:1,
      scale_flag:1,
      /* Scaled register.  */
      brk_flg:1;
  };
  
  struct	mem_segs
  {
    /* Pointer (returned by calloc) to segment.  */
    struct mem_wrd *seg;			
  
    /* Base load address from file headers.  */
    unsigned long baseaddr;			
  
    /* Ending address of segment.  */
    unsigned long endaddr;		
  
    /* Segment control flags (none defined).  */	
    int	      flags;			
  };
  
  #define	MAXSEGS		(10)			/* max number of segment allowed */
  #define	MEMSEGSIZE	(sizeof(struct mem_segs))/* size of mem_segs structure */
  
  #if 0
  #define BRK_RD		(0x01)			/* break on memory read */
  #define BRK_WR		(0x02)			/* break on memory write */
  #define BRK_EXEC	(0x04)			/* break on execution */
  #define	BRK_CNT		(0x08)			/* break on terminal count */
  #endif
  
  struct mem_wrd
  {
    /* Simulator instruction break down.  */
    struct IR_FIELDS opcode;
    union {
      /* Memory element break down.  */
      unsigned long  l;
      unsigned short s[2];
      unsigned char  c[4];
    } mem;
  };
  
  /* Size of each 32 bit memory model.  */
  #define	MEMWRDSIZE	(sizeof (struct mem_wrd))
  
  extern struct mem_segs memory[];
  extern struct PROCESSOR m78000;
  
  struct PROCESSOR
  {
    unsigned WORD
    /* Execute instruction pointer.  */
    ip, 
      /* Vector base register.  */
      vbr,
      /* Processor status register.  */
      psr;
    
    /* Source 1.  */
    WORD    S1bus,
      /* Source 2.  */
      S2bus,
      /* Destination.  */
      Dbus,
      /* Data address bus.  */
      DAbus,
      ALU,
      /* Data registers.  */
      Regs[REGs],
      /* Max clocks before reg is available.  */
      time_left[REGs],
      /* Writeback priority of reg.  */
      wb_pri[REGs], 
      /* Integer unit control regs.  */
      SFU0_regs[REGs],
      /* Floating point control regs.  */
      SFU1_regs[REGs], 
      Scoreboard[REGs],
      Vbr;
    unsigned WORD   scoreboard,
      Psw,
      Tpsw;
    /* Waiting for a jump instruction.  */
    FLAG   jump_pending:1;
  };
  
  /* Size of immediate field.  */
  
  #define    i26bit      1
  #define    i16bit      2
  #define    i10bit      3
  
  /* Definitions for fields in psr.  */
  
  #define psr_mode  31
  #define psr_rbo   30
  #define psr_ser   29
  #define psr_carry 28
  #define psr_sf7m  11
  #define psr_sf6m  10
  #define psr_sf5m   9
  #define psr_sf4m   8
  #define psr_sf3m   7
  #define psr_sf2m   6
  #define psr_sf1m   5
  #define psr_mam    4
  #define psr_inm    3
  #define psr_exm    2
  #define psr_trm    1
  #define psr_ovfm   0
  
  /* The 1 clock operations.  */
  
  #define    ADDU        1
  #define    ADDC        2
  #define    ADDUC       3
  #define    ADD         4
  
  #define    SUBU    ADD+1
  #define    SUBB    ADD+2
  #define    SUBUB   ADD+3
  #define    SUB     ADD+4
  
  #define    AND_    ADD+5
  #define    OR      ADD+6
  #define    XOR     ADD+7
  #define    CMP     ADD+8
  
  /* Loads.  */
  
  #define    LDAB    CMP+1
  #define    LDAH    CMP+2
  #define    LDA     CMP+3
  #define    LDAD    CMP+4
  
  #define    LDB   LDAD+1
  #define    LDH   LDAD+2
  #define    LD    LDAD+3
  #define    LDD   LDAD+4
  #define    LDBU  LDAD+5
  #define    LDHU  LDAD+6
  
  /* Stores.  */
  
  #define    STB    LDHU+1
  #define    STH    LDHU+2
  #define    ST     LDHU+3
  #define    STD    LDHU+4
  
  /* Exchange.  */
  
  #define    XMEMBU LDHU+5
  #define    XMEM   LDHU+6
  
  /* Branches.  */
  
  #define    JSR    STD+1
  #define    BSR    STD+2
  #define    BR     STD+3
  #define    JMP    STD+4
  #define    BB1    STD+5
  #define    BB0    STD+6
  #define    RTN    STD+7
  #define    BCND   STD+8
  
  /* Traps.  */
  
  #define    TB1    BCND+1
  #define    TB0    BCND+2
  #define    TCND   BCND+3
  #define    RTE    BCND+4
  #define    TBND   BCND+5
  
  /* Misc.  */
  
  #define    MUL     TBND + 1
  #define    DIV     MUL  +2
  #define    DIVU    MUL  +3
  #define    MASK    MUL  +4
  #define    FF0     MUL  +5
  #define    FF1     MUL  +6
  #define    CLR     MUL  +7
  #define    SET     MUL  +8
  #define    EXT     MUL  +9
  #define    EXTU    MUL  +10
  #define    MAK     MUL  +11
  #define    ROT     MUL  +12
  
  /* Control register manipulations.  */
  
  #define    LDCR    ROT  +1
  #define    STCR    ROT  +2
  #define    XCR     ROT  +3
  
  #define    FLDCR    ROT  +4
  #define    FSTCR    ROT  +5
  #define    FXCR     ROT  +6
  
  #define    NOP     XCR +1
  
  /* Floating point instructions.  */
  
  #define    FADD    NOP +1
  #define    FSUB    NOP +2
  #define    FMUL    NOP +3
  #define    FDIV    NOP +4
  #define    FSQRT   NOP +5
  #define    FCMP    NOP +6
  #define    FIP     NOP +7
  #define    FLT     NOP +8
  #define    INT     NOP +9
  #define    NINT    NOP +10
  #define    TRNC    NOP +11
  #define    FLDC   NOP +12
  #define    FSTC   NOP +13
  #define    FXC    NOP +14
  
  #define UEXT(src,off,wid) \
    ((((unsigned int)(src)) >> (off)) & ((1 << (wid)) - 1))
  
  #define SEXT(src,off,wid) \
    (((((int)(src))<<(32 - ((off) + (wid)))) >>(32 - (wid))) )
  
  #define MAKE(src,off,wid) \
    ((((unsigned int)(src)) & ((1 << (wid)) - 1)) << (off))
  
  #define opword(n) (unsigned long) (memaddr->mem.l)
  
  /* Constants and masks.  */
  
  #define SFU0       0x80000000
  #define SFU1       0x84000000
  #define SFU7       0x9c000000
  #define RRI10      0xf0000000
  #define RRR        0xf4000000
  #define SFUMASK    0xfc00ffe0
  #define RRRMASK    0xfc00ffe0
  #define RRI10MASK  0xfc00fc00
  #define DEFMASK    0xfc000000
  #define CTRL       0x0000f000
  #define CTRLMASK   0xfc00f800
  
  /* Operands types.  */
  
  enum operand_type
  {
    HEX = 1,
    REG = 2,
    CONT = 3,
    IND = 3,
    BF = 4,
    /* Scaled register.  */
    REGSC = 5,
    /* Control register.  */
    CRREG = 6,
    /* Floating point control register.  */
    FCRREG = 7,
    PCREL = 8,
    CONDMASK = 9,
    /* Extended register.  */
    XREG = 10,
    /* Decimal.  */
    DEC = 11
  };
  
  /* Hashing specification.  */
  
  #define HASHVAL     79
  
  /* Structure templates.  */
  
  typedef struct
  {
    unsigned int offset;
    unsigned int width;
    enum operand_type type;
  } OPSPEC;
  
  struct SIM_FLAGS
  {
    int  ltncy,   /* latency (max number of clocks needed to execute).  */
      extime,   /* execution time (min number of clocks needed to execute).  */
      wb_pri;   /* writeback slot priority.  */
    unsigned         op:OP,   /* simulator version of opcode.  */
      imm_flags:2,   /* 10,16 or 26 bit immediate flags.  */
      rs1_used:1,   /* register source 1 used.  */
      rs2_used:1,   /* register source 2 used.  */
      rsd_used:1,   /* register source/dest used.  */
      c_flag:1,   /* complement.  */
      u_flag:1,   /* upper half word.  */
      n_flag:1,   /* execute next.  */
      wb_flag:1,   /* uses writeback slot.  */
      dest_64:1,   /* double precision dest.  */
      s1_64:1,   /* double precision source 1.  */
      s2_64:1,   /* double precision source 2.  */
      scale_flag:1;   /* register is scaled.  */
  };
  
  typedef struct INSTRUCTAB {
    unsigned int  opcode;
    char          *mnemonic;
    OPSPEC        op1,op2,op3;
    struct SIM_FLAGS flgs;
  } INSTAB;
  
  
  #define NO_OPERAND {0,0,0}
  
  extern const INSTAB  instructions[];
  
  /*
   * Local Variables:
   * fill-column: 131
   * End:
   */
  