/* This doesn't look like -*- C -*-, but it is!
 *
 * ss.def - simplescalar machine definition
 *
 * This file is a part of the SimpleScalar tool suite written by
 * Todd M. Austin as a part of the Multiscalar Research Project.
 *
 * The tool suite is currently maintained by Doug Burger and Todd M. Austin.
 *
 * Copyright (C) 1994, 1995, 1996, 1997 by Todd M. Austin
 *
 * This source file is distributed "as is" in the hope that it will be
 * useful.  The tool set comes with no warranty, and no author or
 * distributor accepts any responsibility for the consequences of its
 * use.
 *
 * Everyone is granted permission to copy, modify and redistribute
 * this tool set under the following conditions:
 *
 *    This source code is distributed for non-commercial use only.
 *    Please contact the maintainer for restrictions applying to
 *    commercial use.
 *
 *    Permission is granted to anyone to make or distribute copies
 *    of this source code, either as received or modified, in any
 *    medium, provided that all copyright notices, permission and
 *    nonwarranty notices are preserved, and that the distributor
 *    grants the recipient permission for further redistribution as
 *    permitted by this document.
 *
 *    Permission is granted to distribute this file in compiled
 *    or executable form under the same conditions that apply for
 *    source code, provided that either:
 *
 *    A. it is accompanied by the corresponding machine-readable
 *       source code,
 *    B. it is accompanied by a written offer, with no time limit,
 *       to give anyone a machine-readable copy of the corresponding
 *       source code in return for reimbursement of the cost of
 *       distribution.  This written offer must permit verbatim
 *       duplication by anyone, or
 *    C. it is distributed by someone who received only the
 *       executable form, and is accompanied by a copy of the
 *       written offer of source code that they received concurrently.
 *
 * In other words, you are welcome to use, share and improve this
 * source file.  You are forbidden to forbid anyone else to use, share
 * and improve what you give them.
 *
 * INTERNET: dburger@cs.wisc.edu
 * US Mail:  1210 W. Dayton Street, Madison, WI 53706
 *
 * $Id: ss.def,v 1.6 1997/04/16 22:11:30 taustin Exp taustin $
 *
 * $Log: ss.def,v $
# Revision 1.6  1997/04/16  22:11:30  taustin
# fixed header comments
#
# Revision 1.5  1997/03/11  01:40:00  taustin
# updated copyrights
# removed inter-dependency between dependency and semantic macros
# supported added for non-GNU C compilers
#
# Revision 1.4  1997/01/06  16:07:49  taustin
# comments updated
# functional unit definitions moved to ss.h and ss.c
#
# Revision 1.3  1996/12/27  15:55:09  taustin
# eliminated compiler warnings
#
# Revision 1.1  1996/12/05  18:55:22  taustin
# Initial revision
#
 *
 */

/* This file defines all aspects of the SimpleScalar instruction set
 * architecture.  Each instruction set in the architecture has a DEFINST()
 * macro call included below.  The contents of a instruction definition are
 * as follows:
 *
 *   DEFINST(<enum>,   <opcode>,
 *      <opname>,   <operands>,
 *      <fu_req>,   <iflags>,
 *      <output deps...>,  <input deps...>,
 *      <expr>)
 *
 * Where:
 *
 *   <enum> - is an enumerator that is returned when an instruction is
 *    decoded by SS_OP_ENUM()
 *   <opcode> - is the opcode of this instruction
 *   <opname>   - name of this instruction as a string, used by disassembler
 *   <operands> - specified the instruction operand fields and their printed
 *     order for disassembly, used by disassembler, the recognized
 *    operand field are (the instruction format is detailed in
 *    the header file ss.h):
 *      J - target field
 *      j - PC relative target (offset + PC)
 *      s - S register field
 *      b - S register field (base register)
 *      t - T register field
 *      d - D register field
 *      S - S register field (FP register)
 *      T - T register field (FP register)
 *      D - D register field (FP register)
 *      o - load address offset (offset)
 *      i - signed immediate field value
 *      u - unsigned immediate field value
 *      U - upper immediate field value
 *      H - shift amount immediate field value
 *      B - break code
 *
 *   <fu_req> - functional unit requirements for this instruction
 *   <iflags> - instruction flags, accessible via the SS_OP_FLAGS()
 *    macro, flags are defined with F_* prefix in ss.h
 *   <output deps...>
 *  - a list of up to two output dependency designators, the
 *    following designators are recognized (place an DNA in any
 *    unused fields:
 *      DGPR(N)   - general purpose register N
 *      DGPR_D(N) - double word general purpose register N
 *      DCGPR(N)  - general purpose register conditional on
 *           pre/post- increment/decrement mode
 *      DFPR_L(N) - floating-point register N, as word
 *      DFPR_F(N) - floating-point reg N, as single-prec float
 *      DFPR_D(N) - floating-point reg N, as double-prec double
 *      DHI       - HI result register
 *      DLO       - LO result register
 *      DFCC      - floating point condition codes
 *      DCPC      - current PC
 *      DNPC      - next PC
 *      DNA       - no dependence
 *
 *   <input deps...>
 *  - a list of up to three input dependency designators, the
 *    designators are defined above (place an DNA in any unused
 *    fields.
 *
 *   <expr> - a C expression that implements the instruction being
 *     defined, the expression must modify all architected state
 *    affected by the instruction's execution, by default, the
 *    next PC (NPC) value defaults to the current PC (CPC) plus
 *    SS_INST_SIZE, as a result, only taken branches need to set
 *    NPC
 *
 *    The following predefined macros are available for use in
 *    DEFINST() instruction expressions to access the value of
 *    instruction operand/opcode field values:
 *
 *      RS     - RS register field value
 *      RT     - RT register field value
 *      RD     - RD register field value
 *      FS     - RS register field value
 *      FT     - RT register field value
 *      FD     - RD register field value
 *      BS     - RS register field value
 *      TARG    - jump target field value
 *      OFS     - signed offset field value
 *      IMM     - signed offset field value
 *      UIMM    - unsigned offset field value
 *      SHAMT   - shift amount field value
 *      BCODE   - break code field value
 *
 *    To facilitate the construction of performance simulators
 *    (which may want to specialize their architected state
 *    storage format), all architected register and memory state
 *    is accessed through the following macros:
 *
 *      GPR(N)         - read general purpose register N
 *      SET_GPR(N,E)   - write general purpose register N with E
 *      GPR_D(N)       - read double word general purpose reg N
 *      SET_GPR_D(N,E) - write double word gen purpose reg N w/ E
 *      FPR_L(N)       - read floating-point register N, as word
 *      SET_FPR_L(N,E) - floating-point reg N, as word, with E
 *      FPR_F(N)       - read FP reg N, as single-prec float
 *      SET_FPR_F(N,E) - write FP reg N, as single-prec float w/ E
 *      FPR_D(N)       - read FP reg N, as double-prec double
 *      SET_FPR_D(N,E) - write FP reg N, as double-prec double w/E
 *      HI            - read HI result register
 *      SET_HI(E)      - write HI result register with E
 *      LO            - read LO result register
 *      SET_LO(E)      - write LO result register with E
 *      FCC            - read floating point condition codes
 *      SET_FCC(E)     - write floating point condition codes w/ E
 *      CPC            - read current PC register
 *      NPC            - read next PC register
 *      SET_NPC(E)     - write next PC register with E
 *      TPC            - read target PC register
 *      SET_TPC(E)     - write target PC register with E
 *
 *      READ_SIGNED_BYTE(A)   - read signed byte from address A
 *      READ_UNSIGNED_BYTE(A) - read unsigned byte from address A
 *      READ_SIGNED_HALF(A)   - read signed half from address A
 *      READ_UNSIGNED_HALF(A) - read unsigned half from address A
 *      READ_WORD(A)          - read word from address A
 *      WRITE_BYTE(E,A)       - write byte value E to address A
 *      WRITE_HALF(E,A)       - write half value E to address A
 *      WRITE_WORD(E,A)       - write word value E to address A
 *
 *    Finally, the following helper functions are available to
 *    assist in the construction of instruction expressions:
 *
 *      INC_DEC(E,N,S) - execute E and update N as per pre/post-
 *         incr/decr addressing sementics for an
 *         access of S bytes
 *      OVER(X,Y)      - check for overflow for X+Y, both signed
 *      UNDER(X,Y)    - check for umderflow for X-Y, both signed
 *      DIV0(N)    - check for divide by zero, N is denom
 *      INTALIGN(N)    - check double word int reg N alignment
 *      FPALIGN(N)    - check double word FP reg N alignment
 *      TALIGN(T)    - check jump target T alignment
 */

/* no operation */
DEFINST(NOP,  0x00,
 "nop",  "",
 IntALU,  F_ICOMP,
 DNA, DNA, DNA, DNA, DNA,
 /* do nothing */((void) 0))

/*
 * control operations
 */

DEFINST(JUMP,   0x01,
 "j",   "J",
 NA,    F_CTRL|F_UNCOND|F_DIRJMP,
 DNA, DNA,   DNA, DNA, DNA,
 (SET_TPC((CPC & 036000000000) | (TARG << 2)),
  SET_NPC((CPC & 036000000000) | (TARG << 2))))
DEFINST(JAL,   0x02,
 "jal",   "J",
 IntALU,   F_CTRL|F_UNCOND|F_DIRJMP|F_CALL,
 DGPR(31), DNA,   DNA, DNA, DNA,
 (SET_TPC((CPC & 036000000000) | (TARG << 2)),
  SET_NPC((CPC & 036000000000) | (TARG << 2)),
  SET_GPR(31, CPC + 8)))
DEFINST(JR,    0x03,
 "jr",    "s",
 NA,    F_CTRL|F_UNCOND|F_INDIRJMP,
 DNA, DNA,  DGPR(RS), DNA, DNA,
 (TALIGN(GPR(RS)), SET_TPC(GPR(RS)), SET_NPC(GPR(RS))))
DEFINST(JALR,    0x04,
 "jalr",   "d,s",
 IntALU,   F_CTRL|F_UNCOND|F_INDIRJMP|F_CALL,
 DGPR(RD), DNA,  DGPR(RS), DNA, DNA,
 (TALIGN(GPR(RS)), SET_GPR(RD, CPC + 8),
  SET_TPC(GPR(RS)), SET_NPC(GPR(RS))))
DEFINST(BEQ,   0x05,
 "beq",   "s,t,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DGPR(RT), DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) == GPR(RT)) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BNE,   0x06,
 "bne",   "s,t,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DGPR(RT), DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) != GPR(RT)) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BLEZ,   0x07,
 "blez",   "s,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) <= 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BGTZ,   0x08,
 "bgtz",   "s,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) > 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BLTZ,    0x09,
 "bltz",   "s,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) < 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BGEZ,    0x0a,
 "bgez",   "s,j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP,
 DNA, DNA,  DGPR(RS), DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (GPR(RS) >= 0) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BC1F,    0x0b,
 "bc1f",   "j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP|F_FPCOND,
 DNA, DNA,  DFCC, DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (!FCC) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))
DEFINST(BC1T,    0x0c,
 "bc1t",   "j",
 IntALU,   F_CTRL|F_COND|F_DIRJMP|F_FPCOND,
 DNA, DNA,  DFCC, DNA, DNA,
 (SET_TPC(CPC + 8 + (OFS << 2)),
  (FCC) ? SET_NPC(CPC + 8 + (OFS << 2)) : 0))

/*
 * load/store operations
 *
 * NOTE: the out-of-order issue simulator(s) require that load and store
 * address computation input dependencies be placed in slots 1 and 2 of
 * the input dependency list slot 0 is reserved for the input dependency
 * of store values for store instructions
 */

DEFINST(LB,   0x20,
 "lb",   "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_GPR(RT, READ_SIGNED_BYTE(GPR(BS)+OFS)), BS, 1))
DEFINST(LBU,    0x22,
 "lbu",    "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_GPR(RT, READ_UNSIGNED_BYTE(GPR(BS)+OFS)), BS, 1))
DEFINST(LH,    0x24,
 "lh",   "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_GPR(RT, READ_SIGNED_HALF(GPR(BS)+OFS)), BS, 2))
DEFINST(LHU,    0x26,
 "lhu",    "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_GPR(RT, READ_UNSIGNED_HALF(GPR(BS)+OFS)), BS, 2))
DEFINST(LW,   0x28,
 "lw",    "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_GPR(RT, READ_WORD(GPR(BS)+OFS)), BS, 4))
DEFINST(DLW,   0x29,
 "dlw",   "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR_D(RT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC((INTALIGN(RT), temp_bs = GPR(BS),
   SET_GPR((RT)^sim_swap_words, READ_WORD(temp_bs+OFS)),
   SET_GPR(((RT)+1)^sim_swap_words, READ_WORD(temp_bs+OFS+4))),
  BS, 8))
DEFINST(L_S,    0x2a,
 "l.s",   "T,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DFPR_L(FT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC(SET_FPR_L(FT, READ_WORD(GPR(BS)+OFS)), BS, 4))
DEFINST(L_D,   0x2b,
 "l.d",   "T,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DFPR_D(FT), DCGPR(BS), DNA, DGPR(BS), DNA,
 INC_DEC((FPALIGN(FT),
   SET_FPR_L((FT)^sim_swap_words, READ_WORD(GPR(BS)+OFS)),
   SET_FPR_L(((FT)+1)^sim_swap_words, READ_WORD(GPR(BS)+OFS+4))),
  BS, 8))
DEFINST(LWL,   0x2c,
 "lwl",   "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DNA,  DNA, DGPR(BS), DNA,
 (/* inc/dec not supported */
  /* BS may == RT */temp_bs = GPR(BS),
  ss_lr_temp = READ_WORD(WL_BASE(temp_bs+OFS)),
  SET_GPR(RT, ((GPR(RT) & WL_PROT_MASK(temp_bs+OFS)) |
        (ss_lr_temp & ~WL_PROT_MASK(temp_bs+OFS))))))
DEFINST(LWR,   0x2d,
 "lwr",   "t,o(b)",
 RdPort,   F_MEM|F_LOAD|F_DISP,
 DGPR(RT), DNA,  DNA, DGPR(BS), DNA,
 (/* inc/dec not supported */
  /* BS may == RT */temp_bs = GPR(BS),
  ss_lr_temp = READ_WORD(WR_BASE(temp_bs+OFS)),
  SET_GPR(RT, ((GPR(RT) & WR_PROT_MASK(temp_bs+OFS)) |
        (ss_lr_temp & ~WR_PROT_MASK(temp_bs+OFS))))))

DEFINST(SB,    0x30,
 "sb",    "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,   DGPR(RT), DGPR(BS), DNA,
 INC_DEC(WRITE_BYTE(GPR(RT), GPR(BS)+OFS), BS, 1))
DEFINST(SH,    0x32,
 "sh",    "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,   DGPR(RT), DGPR(BS), DNA,
 INC_DEC(WRITE_HALF(GPR(RT), GPR(BS)+OFS), BS, 2))
DEFINST(SW,    0x34,
 "sw",    "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,   DGPR(RT), DGPR(BS), DNA,
 INC_DEC(WRITE_WORD(GPR(RT), GPR(BS)+OFS), BS, 4))
DEFINST(DSW,   0x35,
 "dsw",   "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,  DGPR_D(RT), DGPR(BS), DNA,
 INC_DEC((INTALIGN(RT),
   WRITE_WORD(GPR((RT)^sim_swap_words), GPR(BS)+OFS),
   WRITE_WORD(GPR(((RT)+1)^sim_swap_words), GPR(BS)+OFS+4)),
  BS, 8))
DEFINST(DSZ,   0x38,
 "dsz",   "o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,  DNA, DGPR(BS), DNA,
 INC_DEC((WRITE_WORD(GPR(0), GPR(BS)+OFS),
   WRITE_WORD(GPR(0), GPR(BS)+OFS+4)),
  BS, 8))
DEFINST(S_S,    0x36,
 "s.s",    "T,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,  DFPR_L(FT), DGPR(BS), DNA,
 INC_DEC(WRITE_WORD(FPR_L(FT), GPR(BS)+OFS), BS, 4))
DEFINST(S_D,   0x37,
 "s.d",   "T,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DCGPR(BS), DNA,  DFPR_D(FT), DGPR(BS), DNA,
 INC_DEC((FPALIGN(FT),
   WRITE_WORD(FPR_L(FT), GPR(BS)+OFS),
   WRITE_WORD(FPR_L((FT)+1), GPR(BS)+OFS+4)),
  BS, 4))
DEFINST(SWL,   0x39,
 "swl",   "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DNA, DNA,  DGPR(RT), DGPR(BS), DNA,
 (/* inc/dec not supported */
  ss_lr_temp = READ_WORD(WL_BASE(GPR(BS)+OFS)),
  ss_lr_temp = ((GPR(RT) & ~WL_PROT_MASK(GPR(BS)+OFS)) |
         (ss_lr_temp & WL_PROT_MASK(GPR(BS)+OFS))),
  WRITE_WORD(ss_lr_temp, WL_BASE(GPR(BS)+OFS))))
DEFINST(SWR,   0x3a,
 "swr",   "t,o(b)",
 WrPort,   F_MEM|F_STORE|F_DISP,
 DNA, DNA,  DGPR(RT), DGPR(BS), DNA,
 (/* inc/dec not supported */
  ss_lr_temp = READ_WORD(WR_BASE(GPR(BS)+OFS)),
  ss_lr_temp = ((GPR(RT) & ~WR_PROT_MASK(GPR(BS)+OFS)) |
         (ss_lr_temp & WR_PROT_MASK(GPR(BS)+OFS))),
  WRITE_WORD(ss_lr_temp, WR_BASE(GPR(BS)+OFS))))

/* reg+reg loads and stores */

DEFINST(LB_RR,   0xc0,
 "lb",   "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_SIGNED_BYTE(GPR(BS)+GPR(RD))), BS, 1))
DEFINST(LBU_RR,   0xc1,
 "lbu",    "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_UNSIGNED_BYTE(GPR(BS)+GPR(RD))), BS, 1))
DEFINST(LH_RR,    0xc2,
 "lh",   "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_SIGNED_HALF(GPR(BS)+GPR(RD))), BS, 2))
DEFINST(LHU_RR,   0xc3,
 "lhu",    "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_UNSIGNED_HALF(GPR(BS)+GPR(RD))), BS, 2))
DEFINST(LW_RR,   0xc4,
 "lw",    "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_WORD(GPR(BS)+GPR(RD))), BS, 4))
DEFINST(DLW_RR,   0xce,
 "dlw",   "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR_D(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC((INTALIGN(RT),
   temp_bs = GPR(BS), temp_rd = GPR(RD),
   SET_GPR((RT)^sim_swap_words, READ_WORD(temp_bs+temp_rd)),
   SET_GPR(((RT)+1)^sim_swap_words,
    READ_WORD(temp_bs+temp_rd+4))),
  BS, 8))
DEFINST(L_S_RR,   0xc5,
 "l.s",    "T,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DFPR_L(FT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_FPR_L(FT, READ_WORD(GPR(BS)+GPR(RD))), BS, 4))
/* was INC_DEC(SET_FPR_L(RT, READ_WORD(GPR(BS)+GPR(RD))), BS, 4)) */
DEFINST(L_D_RR,   0xcf,
 "l.d",   "T,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DFPR_D(FT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC((FPALIGN(FT),
   SET_FPR_L((FT)^sim_swap_words, READ_WORD(GPR(BS)+GPR(RD))),
   SET_FPR_L(((FT)+1)^sim_swap_words,
      READ_WORD(GPR(BS)+GPR(RD)+4))),
  BS, 8))

DEFINST(SB_RR,    0xc6,
 "sb",    "t,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DGPR(RT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_BYTE(GPR(RT), GPR(BS)+GPR(RD)), BS, 1))
DEFINST(SH_RR,    0xc7,
 "sh",    "t,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,   DGPR(RT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_HALF(GPR(RT), GPR(BS)+GPR(RD)), BS, 2))
DEFINST(SW_RR,    0xc8,
 "sw",    "t,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DGPR(RT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_WORD(GPR(RT), GPR(BS)+GPR(RD)), BS, 4))
DEFINST(DSW_RR,   0xd0,
 "dsw",   "t,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DGPR_D(RT), DGPR(BS), DGPR(RD),
 INC_DEC((INTALIGN(RT),
   WRITE_WORD(GPR((RT)^sim_swap_words), GPR(BS)+GPR(RD)),
   WRITE_WORD(GPR(((RT)+1)^sim_swap_words), GPR(BS)+GPR(RD)+4)),
  BS, 8))
DEFINST(DSZ_RR,   0xd1,
 "dsz",   "(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DNA, DGPR(BS), DGPR(RD),
 INC_DEC((WRITE_WORD(GPR(0), GPR(BS)+GPR(RD)),
   WRITE_WORD(GPR(0), GPR(BS)+GPR(RD)+4)),
  BS, 8))
DEFINST(S_S_RR,   0xc9,
 "s.s",    "T,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DFPR_L(FT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_WORD(FPR_L(FT), GPR(BS)+GPR(RD)), BS, 4))
DEFINST(S_D_RR,   0xd2,
 "s.d",   "T,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DFPR_D(FT), DGPR(BS), DGPR(RD),
 INC_DEC((FPALIGN(FT),
   WRITE_WORD(FPR_L((FT)^sim_swap_words), GPR(BS)+GPR(RD)),
   WRITE_WORD(FPR_L(((FT)+1)^sim_swap_words),
       GPR(BS)+GPR(RD)+4)),
  BS, 8))
 

/* reg + reg + 4 addressing mode, used to synthesize `l.d r,(s+t)^++' */
/* FIXME: obsolete */
DEFINST(L_S_RR_R2,  0xca,
 "l.s.r2",   "T,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DFPR_L(FT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_FPR_L(FT, READ_WORD(GPR(BS)+GPR(RD)+4)), BS, 4))
/* was INC_DEC(SET_FPR_L(RT, READ_WORD(GPR(BS)+GPR(RD)+4)), BS, 4)) */
/* FIXME: obsolete */
DEFINST(S_S_RR_R2,  0xcb,
 "s.s.r2",   "T,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DFPR_L(FT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_WORD(FPR_L(FT), GPR(BS)+GPR(RD)+4), BS, 4))
/* FIXME: obsolete */
DEFINST(LW_RR_R2,  0xcc,
 "lw.r2",  "t,(b+d)",
 RdPort,   F_MEM|F_LOAD|F_RR,
 DGPR(RT), DCGPR(BS), DNA, DGPR(BS), DGPR(RD),
 INC_DEC(SET_GPR(RT, READ_WORD(GPR(BS)+GPR(RD)+4)), BS, 4))
/* FIXME: obsolete */
DEFINST(SW_RR_R2,  0xcd,
 "sw.r2",   "t,(b+d)",
 WrPort,   F_MEM|F_STORE|F_RR,
 DCGPR(BS), DNA,  DGPR(RT), DGPR(BS), DGPR(RD),
 INC_DEC(WRITE_WORD(GPR(RT), GPR(BS)+GPR(RD)+4), BS, 4))
 

/*
 * Integer ALU operations
 */

DEFINST(ADD,    0x40,
 "add",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 (OVER(GPR(RS),GPR(RT)), SET_GPR(RD, GPR(RS) + GPR(RT))))
DEFINST(ADDI,   0x41,
 "addi",   "t,s,i",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 (OVER(GPR(RS),IMM), SET_GPR(RT, GPR(RS) + IMM)))
DEFINST(ADDU,    0x42,
 "addu",   "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, GPR(RS) + GPR(RT)))
DEFINST(ADDIU,   0x43,
 "addiu",  "t,s,i",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, GPR(RS) + IMM))

DEFINST(SUB,    0x44,
 "sub",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 (UNDER(GPR(RS),GPR(RT)), SET_GPR(RD, GPR(RS) - GPR(RT))))
DEFINST(SUBU,    0x45,
 "subu",   "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, GPR(RS) - GPR(RT)))

DEFINST(MULT,    0x46,
 "mult",   "s,t",
 IntMULT,   F_ICOMP|F_LONGLAT,
 DHI, DLO,  DGPR(RT), DGPR(RS), DNA,
 InstMULT(inst))
DEFINST(MULTU,    0x47,
 "multu",   "s,t",
 IntMULT,   F_ICOMP|F_LONGLAT,
 DHI, DLO,  DGPR(RT), DGPR(RS), DNA,
 InstMULTU(inst))
DEFINST(DIV,    0x48,
 "div",    "s,t",
 IntDIV,   F_ICOMP|F_LONGLAT,
 DHI, DLO,  DGPR(RT), DGPR(RS), DNA,
 (DIV0(GPR(RT)),
  SET_LO(IDIV(GPR(RS), GPR(RT))), SET_HI(IMOD(GPR(RS), GPR(RT)))))
DEFINST(DIVU,    0x49,
 "divu",   "s,t",
 IntDIV,   F_ICOMP|F_LONGLAT,
 DHI, DLO,  DGPR(RT), DGPR(RS), DNA,
 (DIV0(GPR(RT)),
  SET_LO(IDIV(((unsigned)GPR(RS)), ((unsigned)GPR(RT)))),
  SET_HI(IMOD(((unsigned)GPR(RS)), ((unsigned)GPR(RT))))))

DEFINST(MFHI,    0x4a,
 "mfhi",   "d",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DHI, DNA, DNA,
 SET_GPR(RD, HI))
DEFINST(MTHI,    0x4b,
 "mthi",   "s",
 IntALU,   F_ICOMP,
 DHI, DNA,  DGPR(RS), DNA, DNA,
 SET_HI(GPR(RS)))
DEFINST(MFLO,    0x4c,
 "mflo",   "d",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DLO, DNA, DNA,
 SET_GPR(RD, LO))
DEFINST(MTLO,    0x4d,
 "mtlo",   "s",
 IntALU,   F_ICOMP,
 DLO, DNA,  DGPR(RS), DNA, DNA,
 SET_LO(GPR(RS)))

/* AND conflicts with GNU defs */
DEFINST(AND_,    0x4e,
 "and",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, GPR(RS) & GPR(RT)))
DEFINST(ANDI,   0x4f,
 "andi",   "t,s,u",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, GPR(RS) & UIMM))
DEFINST(OR,    0x50,
 "or",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, GPR(RS) | GPR(RT)))
DEFINST(ORI,    0x51,
 "ori",   "t,s,u",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, GPR(RS) | UIMM))
DEFINST(XOR,    0x52,
 "xor",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, GPR(RS) ^ GPR(RT)))
DEFINST(XORI,    0x53,
 "xori",   "t,s,u",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, GPR(RS) ^ UIMM))
DEFINST(NOR,    0x54,
 "nor",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, ~(GPR(RS) | GPR(RT))))

DEFINST(SLL,    0x55,
 "sll",    "d,t,H",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DNA, DNA,
 SET_GPR(RD, GPR(RT) << SHAMT))
DEFINST(SLLV,    0x56,
 "sllv",   "d,t,s",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DGPR(RS), DNA,
 SET_GPR(RD, GPR(RT) << (GPR(RS) & 037)))
DEFINST(SRL,    0x57,
 "srl",    "d,t,H",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DNA, DNA,
 SET_GPR(RD, ((unsigned)GPR(RT)) >> SHAMT))
DEFINST(SRLV,    0x58,
 "srlv",   "d,t,s",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DGPR(RS), DNA,
 SET_GPR(RD, ((unsigned)GPR(RT)) >> (GPR(RS) & 037)))
DEFINST(SRA,    0x59,
 "sra",    "d,t,H",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DNA, DNA,
 InstSRA(inst))
DEFINST(SRAV,    0x5a,
 "srav",   "d,t,s",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RT), DGPR(RS), DNA,
 InstSRAV(inst))

DEFINST(SLT,   0x5b,
 "slt",    "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, (GPR(RS) < GPR(RT)) ? 1 : 0))
DEFINST(SLTI,    0x5c,
 "slti",   "t,s,i",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, (GPR(RS) < IMM) ? 1 : 0))
DEFINST(SLTU,    0x5d,
 "sltu",   "d,s,t",
 IntALU,   F_ICOMP,
 DGPR(RD), DNA,  DGPR(RS), DGPR(RT), DNA,
 SET_GPR(RD, (((unsigned)GPR(RS)) < ((unsigned)GPR(RT))) ? 1 : 0))
DEFINST(SLTIU,   0x5e,
 "sltiu",  "t,s,i",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DGPR(RS), DNA, DNA,
 SET_GPR(RT, ((unsigned)GPR(RS) < (unsigned)IMM) ? 1 : 0))
 

/*
 * Floating Point ALU operations
 */

DEFINST(FADD_S,   0x70,
 "add.s",  "D,S,T",
 FloatADD,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_F(FS), DFPR_F(FT), DNA,
 /* FIXME: check precedences here */
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_F(FD, FPR_F(FS) + FPR_F(FT))))
DEFINST(FADD_D,   0x71,
 "add.d",  "D,S,T",
 FloatADD,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_D(FS), DFPR_D(FT), DNA,
 /* FIXME: check precedences here */
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_D(FD, FPR_D(FS) + FPR_D(FT))))
DEFINST(FSUB_S,   0x72,
 "sub.s",  "D,S,T",
 FloatADD,   F_FCOMP,
 DFPR_F(FD), DNA, DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_F(FD, FPR_F(FS) - FPR_F(FT))))
DEFINST(FSUB_D,   0x73,
 "sub.d",  "D,S,T",
 FloatADD,   F_FCOMP,
 DFPR_D(FD), DNA, DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_D(FD, FPR_D(FS) - FPR_D(FT))))
DEFINST(FMUL_S,   0x74,
 "mul.s",  "D,S,T",
 FloatMULT,   F_FCOMP|F_LONGLAT,
 DFPR_F(FD), DNA, DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_F(FD, FPR_F(FS) * FPR_F(FT))))
DEFINST(FMUL_D,   0x75,
 "mul.d",  "D,S,T",
 FloatMULT,   F_FCOMP|F_LONGLAT,
 DFPR_D(FD), DNA, DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  SET_FPR_D(FD, FPR_D(FS) * FPR_D(FT))))
DEFINST(FDIV_S,   0x76,
 "div.s",  "D,S,T",
 FloatDIV,  F_FCOMP|F_LONGLAT,
 DFPR_F(FD), DNA, DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  (DIV0(FPR_F(FT)), SET_FPR_F(FD, FDIV(FPR_F(FS), FPR_F(FT))))))
DEFINST(FDIV_D,   0x77,
 "div.d",  "D,S,T",
 FloatDIV,  F_FCOMP|F_LONGLAT,
 DFPR_D(FD), DNA, DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FD), FPALIGN(FS), FPALIGN(FT),
  (DIV0(FPR_D(FT)), SET_FPR_D(FD, FDIV(FPR_D(FS), FPR_D(FT))))))
DEFINST(FABS_S,   0x78,
 "abs.s",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, fabs((double)FPR_F(FS)))))
DEFINST(FABS_D,   0x79,
 "abs.d",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, fabs(FPR_D(FS)))))
DEFINST(FMOV_S,   0x7a,
 "mov.s",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, FPR_F(FS))))
DEFINST(FMOV_D,   0x7b,
 "mov.d",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, FPR_D(FS))))
DEFINST(FNEG_S,   0x7c,
 "neg.s",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, -FPR_F(FS))))
DEFINST(FNEG_D,   0x7d,
 "neg.d",  "D,S",
 FloatADD,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, -FPR_D(FS))))

DEFINST(CVT_S_D,  0x80,
 "cvt.s.d",   "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, (float)FPR_D(FS))))
DEFINST(CVT_S_W,  0x81,
 "cvt.s.w",   "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_F(FD), DNA, DFPR_L(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, (float)FPR_L(FS))))
DEFINST(CVT_D_S,  0x82,
 "cvt.d.s",  "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, (double)FPR_F(FS))))
DEFINST(CVT_D_W,  0x83,
 "cvt.d.w",  "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_D(FD), DNA, DFPR_L(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, (double)FPR_L(FS))))
DEFINST(CVT_W_S,  0x84,
 "cvt.w.s",   "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_L(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_L(FD, FINT(FPR_F(FS)))))
DEFINST(CVT_W_D,  0x85,
 "cvt.w.d",   "D,S",
 FloatCVT,  F_FCOMP,
 DFPR_L(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_L(FD, FINT(FPR_D(FS)))))

DEFINST(C_EQ_S,   0x90,
 "c.eq.s",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) == FPR_F(FT))))
DEFINST(C_EQ_D,   0x91,
 "c.eq.d",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) == FPR_D(FT))))
DEFINST(C_LT_S,   0x92,
 "c.lt.s",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) < FPR_F(FT))))
DEFINST(C_LT_D,   0x93,
 "c.lt.d",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) < FPR_D(FT))))
DEFINST(C_LE_S,   0x94,
 "c.le.s",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_F(FS), DFPR_F(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_F(FS) <= FPR_F(FT))))
DEFINST(C_LE_D,   0x95,
 "c.le.d",   "S,T",
 FloatCMP,  F_FCOMP,
 DFCC, DNA,  DFPR_D(FS), DFPR_D(FT), DNA,
 (FPALIGN(FS), FPALIGN(FT), SET_FCC(FPR_D(FS) <= FPR_D(FT))))

DEFINST(FSQRT_S,  0x96,
 "sqrt.s",  "D,S",
 FloatSQRT,  F_FCOMP|F_LONGLAT,
 DFPR_F(FD), DNA, DFPR_F(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_F(FD, sqrt((double)FPR_F(FS)))))
DEFINST(FSQRT_D,  0x97,
 "sqrt.d",  "D,S",
 FloatSQRT,  F_FCOMP|F_LONGLAT,
 DFPR_D(FD), DNA, DFPR_D(FS), DNA, DNA,
 (FPALIGN(FD), FPALIGN(FS), SET_FPR_D(FD, sqrt(FPR_D(FS)))))
 

/*
 * miscellaneous
 */

DEFINST(SYSCALL,   0xa0,
 "syscall",   "",
 NA,    F_TRAP,
 DNA, DNA,  DNA, DNA, DNA,
 SYSCALL(inst))
DEFINST(BREAK,   0xa1,
 "break",  "B",
 NA,   F_TRAP,
 DNA, DNA,  DNA, DNA, DNA,
 /* NOTE: these are decoded speculatively, as they occur in integer
    divide sequences, however, they should NEVER be executed under
    non-exception conditions */
 /* abort() */(void) 0)
DEFINST(LUI,    0xa2,
 "lui",   "t,U",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,   DNA, DNA, DNA,
 SET_GPR(RT, UIMM << 16))

DEFINST(MFC1,    0xa3,
 "mfc1",   "t,S",
 IntALU,   F_ICOMP,
 DGPR(RT), DNA,  DFPR_L(FS), DNA, DNA,
 SET_GPR(RT, FPR_L(FS)))
DEFINST(DMFC1,    0xa7,
 "dmfc1",  "t,S",
 IntALU,   F_ICOMP,
 DGPR_D(RT), DNA,  DFPR_D(FS), DNA, DNA,
 (INTALIGN(RT), FPALIGN(FS),
  SET_GPR(RT, FPR_L(FS)), SET_GPR((RT)+1, FPR_L((FS)+1))))
DEFINST(CFC1,    0xa4,
 "cfc1",   "t,S",
 IntALU,   F_ICOMP,
 DNA, DNA,  DNA, DNA, DNA,
 /* FIXME: is this needed */((void) 0))
DEFINST(MTC1,    0xa5,
 "mtc1",   "t,S",
 IntALU,   F_ICOMP,
 DFPR_L(FS), DNA, DGPR(RT), DNA, DNA,
 SET_FPR_L(FS, GPR(RT)))
DEFINST(DMTC1,    0xa8,
 "dmtc1",  "t,S",
 IntALU,   F_ICOMP,
 DFPR_D(FS), DNA, DGPR_D(RT), DNA, DNA,
 (FPALIGN(FS), INTALIGN(RT),
  SET_FPR_L(FS, GPR(RT)), SET_FPR_L((FS)+1, GPR((RT)+1))))
DEFINST(CTC1,    0xa6,
 "ctc1",   "t,S",
 IntALU,   F_ICOMP,
 DNA, DNA,  DNA, DNA, DNA,
 /* FIXME: is this needed */((void) 0))

#ifdef IMPL

/*
 * non-expression instruction implementations
 */

/*
 * rd <- [rt] >> SHAMT
 */
static void
InstSRA(SS_INST_TYPE inst)
{
  unsigned int i;

  /* Although SRA could be implemented with the >> operator in most
     machines, there are other machines that perform a logical
     right shift with the >> operator. */
  if (GPR(RT) & 020000000000) {
    SET_GPR(RD, GPR(RT));
    for (i = 0; i < SHAMT; i++) {
      SET_GPR(RD, (GPR(RD) >> 1) | 020000000000);
    }
  }
  else {
    SET_GPR(RD, GPR(RT) >> SHAMT);
  }
}

/*
 * rd <- [rt] >> [5 LSBs of rs])
 */
static void
InstSRAV(SS_INST_TYPE inst)
{
  unsigned int i;
  unsigned int shamt = GPR(RS) & 037;

  if (GPR(RT) & 020000000000) {
    SET_GPR(RD, GPR(RT));
    for (i = 0; i < shamt; i++) {
      SET_GPR(RD, (GPR(RD) >> 1) | 020000000000);
    }
  }
  else {
    SET_GPR(RD, GPR(RT) >> shamt);
  }
}

/*
 * HI,LO <- [rs] * [rt], integer product of [rs] & [rt] to HI/LO
 */
static void
InstMULT(SS_INST_TYPE inst)
{
  int sign1, sign2;
  int i, op1, op2;

  sign1 = sign2 = 0;
  SET_HI(0);
  SET_LO(0);
  op1 = GPR(RS);
  op2 = GPR(RT);

  /* For multiplication, treat -ve numbers as +ve numbers by
     converting 2's complement -ve numbers to ordinary notation */
  if (op1 & 020000000000) {
    sign1 = 1;
    op1 = (~op1) + 1;
  }
  if (op2 & 020000000000) {
    sign2 = 1;
    op2 = (~op2) + 1;
  }
  if (op1 & 020000000000)
    SET_LO(op2);
  for (i = 0; i < 31; i++) {
    SET_HI(HI << 1);
    SET_HI(HI + extractl(LO, 31, 1));
    SET_LO(LO << 1);
    if ((extractl(op1, 30-i, 1)) == 1) {
      if (((unsigned)037777777777 - (unsigned)LO) < (unsigned)op2) {
 SET_HI(HI + 1);
      }
      SET_LO(LO + op2);
    }
  }

  /* Take 2's complement of the result if the result is negative */
  if (sign1 ^ sign2) {
    SET_LO(~LO);
    SET_HI(~HI);
    if ((unsigned)LO == 037777777777) {
      SET_HI(HI + 1);
    }
    SET_LO(LO + 1);
  }
}

/*
 * HI,LO <- [rs] * [rt], integer product of [rs] & [rt] to HI/LO
 */
static void
InstMULTU(SS_INST_TYPE inst)
{
  int i;

  SET_HI(0);
  SET_LO(0);
  if (GPR(RS) & 020000000000)
    SET_LO(GPR(RT));
  for (i = 0; i < 31; i++) {
    SET_HI(HI << 1);
    SET_HI(HI + extractl(LO, 31, 1));
    SET_LO(LO << 1);
    if ((extractl(GPR(RS), 30-i, 1)) == 1) {
      if (((unsigned)037777777777 - (unsigned)LO) < (unsigned)GPR(RT)) {
 SET_HI(HI + 1);
      }
      SET_LO(LO + GPR(RT));
    }
  }
}

#endif /* IMPL */
 

 back