/* This doesn't look like -*- C -*-, but it is! */

/* pisa.def - SimpleScalar portable ISA (pisa) machine definition */

/* SimpleScalar(TM) Tool Suite
 * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC.
 * All Rights Reserved. 
 * 
 * THIS IS A LEGAL DOCUMENT, BY USING SIMPLESCALAR,
 * YOU ARE AGREEING TO THESE TERMS AND CONDITIONS.
 * 
 * No portion of this work may be used by any commercial entity, or for any
 * commercial purpose, without the prior, written permission of SimpleScalar,
 * LLC (info@simplescalar.com). Nonprofit and noncommercial use is permitted
 * as described below.
 * 
 * 1. SimpleScalar is provided AS IS, with no warranty of any kind, express
 * or implied. The user of the program accepts full responsibility for the
 * application of the program and the use of any results.
 * 
 * 2. Nonprofit and noncommercial use is encouraged. SimpleScalar may be
 * downloaded, compiled, executed, copied, and modified solely for nonprofit,
 * educational, noncommercial research, and noncommercial scholarship
 * purposes provided that this notice in its entirety accompanies all copies.
 * Copies of the modified software can be delivered to persons who use it
 * solely for nonprofit, educational, noncommercial research, and
 * noncommercial scholarship purposes provided that this notice in its
 * entirety accompanies all copies.
 * 
 * 3. ALL COMMERCIAL USE, AND ALL USE BY FOR PROFIT ENTITIES, IS EXPRESSLY
 * PROHIBITED WITHOUT A LICENSE FROM SIMPLESCALAR, LLC (info@simplescalar.com).
 * 
 * 4. No nonprofit user may place any restrictions on the use of this software,
 * including as modified by the user, by any other authorized user.
 * 
 * 5. Noncommercial and nonprofit users may distribute copies of SimpleScalar
 * in compiled or executable form as set forth in Section 2, provided that
 * either: (A) it is accompanied by the corresponding machine-readable source
 * code, or (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.
 * 
 * 6. SimpleScalar was developed by Todd M. Austin, Ph.D. The tool suite is
 * currently maintained by SimpleScalar LLC (info@simplescalar.com). US Mail:
 * 2395 Timbercrest Court, Ann Arbor, MI 48105.
 * 
 * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC.
 */


/* 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 */
#define NOP_IMPL							\
  {									\
    /* nada... */							\
  }
DEFINST(NOP,		0x00,
	"nop",		"",
	IntALU,		F_ICOMP,
	DNA, DNA,	DNA, DNA, DNA)

/*
 * control operations
 */

#define JUMP_IMPL							\
  {									\
    SET_TPC((CPC & 036000000000) | (TARG << 2));			\
    SET_NPC((CPC & 036000000000) | (TARG << 2));			\
  }
DEFINST(JUMP,			0x01,
	"j",			"J",
	NA, 			F_CTRL|F_UNCOND|F_DIRJMP,
	DNA, DNA, 		DNA, DNA, DNA)

#define JAL_IMPL							\
  {									\
    SET_TPC((CPC & 036000000000) | (TARG << 2));			\
    SET_NPC((CPC & 036000000000) | (TARG << 2));			\
    SET_GPR(31, CPC + 8);						\
  }
DEFINST(JAL,			0x02,
	"jal",			"J",
	IntALU,			F_CTRL|F_UNCOND|F_DIRJMP|F_CALL,
	DGPR(31), DNA,	 	DNA, DNA, DNA)

#define JR_IMPL								\
  {									\
    if (GPR(RS) & 0x7)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_TPC(GPR(RS));							\
    SET_NPC(GPR(RS));							\
  }
DEFINST(JR, 			0x03,
	"jr", 			"s", 
	NA, 			F_CTRL|F_UNCOND|F_INDIRJMP,
	DNA, DNA,		DGPR(RS), DNA, DNA)

#define JALR_IMPL							\
  {									\
    if (GPR(RS) & 0x7)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_GPR(RD, CPC + 8);						\
    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)

#define BEQ_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) == GPR(RT))						\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BEQ,			0x05,
	"beq",			"s,t,j",
	IntALU,			F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DGPR(RT), DNA)

#define BNE_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) != GPR(RT))						\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BNE,			0x06,
	"bne",			"s,t,j",
	IntALU,			F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DGPR(RT), DNA)

#define BLEZ_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) <= 0)							\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BLEZ,			0x07,
	"blez",			"s,j",
	IntALU,			F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DNA, DNA)

#define BGTZ_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) > 0)							\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BGTZ,			0x08,
	"bgtz",			"s,j",
	IntALU,			F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DNA, DNA)

#define BLTZ_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) < 0)							\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BLTZ,	 		0x09,
	"bltz", 		"s,j", 
	IntALU, 		F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DNA, DNA)

#define BGEZ_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (GPR(RS) >= 0)							\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BGEZ, 			0x0a,
	"bgez", 		"s,j", 
	IntALU, 		F_CTRL|F_COND|F_DIRJMP,
	DNA, DNA,		DGPR(RS), DNA, DNA)

#define BC1F_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (!FCC)								\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BC1F, 			0x0b,
	"bc1f", 		"j", 
	IntALU,			F_CTRL|F_COND|F_DIRJMP|F_FPCOND,
	DNA, DNA,		DFCC, DNA, DNA)

#define BC1T_IMPL							\
  {									\
    SET_TPC(CPC + 8 + (OFS << 2));					\
    if (FCC)								\
      SET_NPC(CPC + 8 + (OFS << 2));					\
  }
DEFINST(BC1T, 			0x0c,
	"bc1t", 		"j", 
	IntALU,			F_CTRL|F_COND|F_DIRJMP|F_FPCOND,
	DNA, DNA,		DFCC, DNA, DNA)


/*
 * 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
 */

#define LB_IMPL								\
  {									\
    sbyte_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_BYTE(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_GPR(RT, (word_t)(sword_t)_result);				\
  }
DEFINST(LB,			0x20,
	"lb",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LBU_IMPL							\
  {									\
    byte_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_BYTE(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_GPR(RT, (word_t)_result);					\
  }
DEFINST(LBU, 			0x22, 
	"lbu", 			"t,o(b)",
	RdPort, 		F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LH_IMPL								\
  {									\
    shalf_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_HALF(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_GPR(RT, (word_t)(sword_t)_result);				\
  }
DEFINST(LH, 			0x24,
	"lh",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LHU_IMPL							\
  {									\
    half_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_HALF(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_GPR(RT, (word_t)_result);					\
  }
DEFINST(LHU, 			0x26, 
	"lhu", 			"t,o(b)",
	RdPort, 		F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LW_IMPL								\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_GPR(RT, _result);						\
  }
DEFINST(LW,			0x28,
	"lw", 			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define DLW_IMPL							\
  {									\
    word_t _result_hi, _result_lo;					\
    enum md_fault_type _fault;						\
									\
    if ((RT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    _result_hi = READ_WORD(GPR(BS) + OFS, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    _result_lo = READ_WORD(GPR(BS) + OFS + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, _result_hi);						\
    SET_GPR((RT) + 1, _result_lo);					\
  }
DEFINST(DLW,			0x29,
	"dlw",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR_D(RT), DNA,	DNA, DGPR(BS), DNA)

#define L_S_IMPL							\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    SET_FPR_L(FT, _result);						\
  }
DEFINST(L_S, 			0x2a,
	"l.s",			"T,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DFPR_L(FT), DNA,	DNA, DGPR(BS), DNA)

#define L_D_IMPL							\
  {									\
    word_t _result_hi, _result_lo;					\
    enum md_fault_type _fault;						\
									\
    if ((FT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    _result_hi = READ_WORD(GPR(BS) + OFS, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    _result_lo = READ_WORD(GPR(BS) + OFS + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_FPR_L(FT, _result_hi);						\
    SET_FPR_L((FT) + 1, _result_lo);					\
  }

DEFINST(L_D,			0x2b,
	"l.d",			"T,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DFPR_D(FT), DNA,	DNA, DGPR(BS), DNA)

#if (!defined(MD_CROSS_ENDIAN) && defined(BYTES_BIG_ENDIAN)) || (defined(MD_CROSS_ENDIAN) && defined(BYTES_LITTLE_ENDIAN))
#define LWL_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WL_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & WL_PROT_MASK1(_temp_bs + OFS))		\
		 | ((_lr_temp << (8 * WL_SIZE(_temp_bs + OFS)))		\
		    & ~WL_PROT_MASK1(_temp_bs + OFS))));		\
  }
DEFINST(LWL,			0x2c,
        "lwl",			"t,o(b)",
        RdPort,			F_MEM|F_LOAD|F_DISP,
        DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LWR_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WR_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & ~WR_PROT_MASK1(_temp_bs + OFS))		\
		 | ((_lr_temp >> (8 * (4 - WR_SIZE(_temp_bs + OFS))))	\
		    & WR_PROT_MASK1(_temp_bs + OFS))));			\
  }
DEFINST(LWR,			0x2d,
        "lwr",			"t,o(b)",
        RdPort,			F_MEM|F_LOAD|F_DISP,
        DGPR(RT), DNA,		DNA, DGPR(BS), DNA)
#else /* defined BYTES_LITTLE_ENDIAN */
#define LWL_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WL_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & WR_PROT_MASK1(_temp_bs + OFS))		\
		 | ((_lr_temp << (8 * (WL_SIZE(_temp_bs + OFS)-1)))	\
		    & ~WR_PROT_MASK1(_temp_bs + OFS))));		\
  }
DEFINST(LWL,			0x2c,
        "lwl",			"t,o(b)",
        RdPort,			F_MEM|F_LOAD|F_DISP,
        DGPR(RT), DNA,		DNA, DGPR(BS), DNA)

#define LWR_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WR_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & ~WL_PROT_MASK2(_temp_bs + OFS))		\
		 | ((_lr_temp >> (8 * (WR_SIZE(_temp_bs + OFS)-1)))	\
		    & WL_PROT_MASK2(_temp_bs + OFS))));			\
  }
DEFINST(LWR,			0x2d,
        "lwr",			"t,o(b)",
        RdPort,			F_MEM|F_LOAD|F_DISP,
        DGPR(RT), DNA,		DNA, DGPR(BS), DNA)
#endif
  
#if 0
#define LWL_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WL_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & WL_PROT_MASK(_temp_bs + OFS)) |		\
                      (_lr_temp & ~WL_PROT_MASK(_temp_bs + OFS))));	\
  }
DEFINST(LWL,			0x2c,
	"lwl",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA)
/* #else */
DEFINST(LWL,			0x2c,
	"lwl",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA,
	(ss_lr_temp = READ_WORD(WL_BASE(GPR(BS) + OFS)),
	 SET_GPR(RT, ((GPR(RT) & WL_PROT_MASK1(GPR(BS) + OFS)) |
		      ((ss_lr_temp << (8 * WL_SIZE(GPR(BS) + OFS))) 
		       & ~WL_PROT_MASK1(GPR(BS) + OFS))))))
#endif

#if 0
#define LWR_IMPL							\
  {									\
    md_addr_t _temp_bs;							\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    /* BS may == RT */							\
    _temp_bs = GPR(BS);							\
    _lr_temp = READ_WORD(WR_BASE(_temp_bs + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, ((GPR(RT) & WR_PROT_MASK(_temp_bs + OFS)) |		\
                      (_lr_temp & ~WR_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)
/* #else */
DEFINST(LWR,			0x2d,
	"lwr",			"t,o(b)",
	RdPort,			F_MEM|F_LOAD|F_DISP,
	DGPR(RT), DNA,		DNA, DGPR(BS), DNA,
	(ss_lr_temp = READ_WORD(WR_BASE(GPR(BS) + OFS)),
	 SET_GPR(RT, ((GPR(RT) & ~WR_PROT_MASK1(GPR(BS) + OFS)) |
		      ((ss_lr_temp >> (8 * (4 - WR_SIZE(GPR(BS) + OFS)))) 
		       & WR_PROT_MASK1(GPR(BS) + OFS))))))
#endif

#define SB_IMPL								\
  {									\
    byte_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (byte_t)(word_t)GPR(RT);					\
    WRITE_BYTE(_src, GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SB, 			0x30, 
	"sb", 			"t,o(b)",
	WrPort, 		F_MEM|F_STORE|F_DISP,
	DNA, DNA,	 	DGPR(RT), DGPR(BS), DNA)

#define SH_IMPL								\
  {									\
    half_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (half_t)(word_t)GPR(RT);					\
    WRITE_HALF(_src, GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SH, 			0x32, 
	"sh", 			"t,o(b)",
	WrPort, 		F_MEM|F_STORE|F_DISP,
	DNA, DNA,	 	DGPR(RT), DGPR(BS), DNA)

#define SW_IMPL								\
  {									\
    word_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (word_t)GPR(RT);						\
    WRITE_WORD(_src, GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SW, 			0x34, 
	"sw", 			"t,o(b)",
	WrPort, 		F_MEM|F_STORE|F_DISP,
	DNA, DNA,	 	DGPR(RT), DGPR(BS), DNA)

/* FIXME: this code not fault-safe, yet... */
#define DSW_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    if ((RT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    WRITE_WORD(GPR(RT), GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(GPR((RT) + 1), GPR(BS) + OFS + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(DSW,			0x35,
	"dsw",			"t,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DGPR_D(RT), DGPR(BS), DNA)

/* FIXME: this code not fault-safe, yet... */
#define DSZ_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(GPR(0), GPR(BS) + OFS, _fault);				\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(GPR(0), GPR(BS) + OFS + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(DSZ,			0x38,
	"dsz",			"o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DNA, DGPR(BS), DNA)

#define S_S_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(FPR_L(FT), GPR(BS) + OFS, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(S_S, 			0x36, 
	"s.s", 			"T,o(b)",
	WrPort, 		F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DFPR_L(FT), DGPR(BS), DNA)

/* FIXME: this code not fault-safe, yet... */
#define S_D_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    if ((FT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    WRITE_WORD(FPR_L(FT), GPR(BS) + OFS, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(FPR_L((FT)+1), GPR(BS) + OFS + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(S_D,			0x37,
	"s.d",			"T,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DFPR_D(FT), DGPR(BS), DNA)

#if (!defined(MD_CROSS_ENDIAN) && defined(BYTES_BIG_ENDIAN)) || (defined(MD_CROSS_ENDIAN) && defined(BYTES_LITTLE_ENDIAN))
#define SWL_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WL_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = (((GPR(RT) >> (8 * WL_SIZE(GPR(BS) + OFS)))		\
		 & WL_PROT_MASK2(GPR(BS) + OFS))			\
		| (_lr_temp & ~WL_PROT_MASK2(GPR(BS) + OFS)));		\
    WRITE_WORD(_lr_temp, WL_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWL,			0x39,
        "swl",			"t,o(b)",
        WrPort,			F_MEM|F_STORE|F_DISP,
        DNA, DNA,		DGPR(RT), DGPR(BS), DNA)

#define SWR_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = (((GPR(RT) << (8 * (4 - WR_SIZE(GPR(BS) + OFS))))	\
		 & ~WR_PROT_MASK2(GPR(BS) + OFS))			\
		| (_lr_temp & WR_PROT_MASK2(GPR(BS) + OFS)));		\
    WRITE_WORD(_lr_temp, WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWR,			0x3a,
        "swr",			"t,o(b)",
        WrPort,			F_MEM|F_STORE|F_DISP,
        DNA, DNA,		DGPR(RT), DGPR(BS), DNA)
#else /* BYTES_LITTLE_ENDIAN */
#define SWL_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WL_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = (((GPR(RT) >> (8 * (4 - WR_SIZE(GPR(BS) + OFS))))	\
		 & WR_PROT_MASK2(GPR(BS) + OFS))			\
		| (_lr_temp & ~WR_PROT_MASK2(GPR(BS) + OFS)));		\
    WRITE_WORD(_lr_temp, WL_BASE(GPR(BS)+OFS), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWL,			0x39,
        "swl",			"t,o(b)",
        WrPort,			F_MEM|F_STORE|F_DISP,
        DNA, DNA,		DGPR(RT), DGPR(BS), DNA)

#define SWR_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = (((GPR(RT) << (8 * (4 - WL_SIZE(GPR(BS) + OFS))))	\
		   & ~WL_PROT_MASK1(GPR(BS) + OFS))			\
		  | (_lr_temp & WL_PROT_MASK1(GPR(BS) + OFS)));		\
    WRITE_WORD(_lr_temp, WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWR,			0x3a,
        "swr",			"t,o(b)",
        WrPort,			F_MEM|F_STORE|F_DISP,
        DNA, DNA,		DGPR(RT), DGPR(BS), DNA)
#endif

#if 0
#define SWL_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WL_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = ((GPR(RT) & ~WL_PROT_MASK(GPR(BS) + OFS)) |		\
                       (_lr_temp & WL_PROT_MASK(GPR(BS) + OFS)));	\
    WRITE_WORD(_lr_temp, WL_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWL,			0x39,
	"swl",			"t,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DGPR(RT), DGPR(BS), DNA)
/* #else */
DEFINST(SWL,			0x39,
	"swl",			"t,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DGPR(RT), DGPR(BS), DNA,
	(ss_lr_temp = READ_WORD(WL_BASE(GPR(BS) + OFS)),
	 ss_lr_temp = (((GPR(RT) >> (8 * WL_SIZE(GPR(BS) + OFS))) 
			& WL_PROT_MASK2(GPR(BS) + OFS)) |
		       (ss_lr_temp & ~WL_PROT_MASK2(GPR(BS) + OFS))),
	 WRITE_WORD(ss_lr_temp, WL_BASE(GPR(BS) + OFS))))
#endif

#if 0
#define SWR_IMPL							\
  {									\
    word_t _lr_temp;							\
    enum md_fault_type _fault;						\
									\
    _lr_temp = READ_WORD(WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    _lr_temp = ((GPR(RT) & ~WR_PROT_MASK(GPR(BS) + OFS)) |		\
                       (_lr_temp & WR_PROT_MASK(GPR(BS) + OFS)));	\
    WRITE_WORD(_lr_temp, WR_BASE(GPR(BS) + OFS), _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SWR,			0x3a,
	"swr",			"t,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DGPR(RT), DGPR(BS), DNA)
/* #else */
DEFINST(SWR,			0x3a,
	"swr",			"t,o(b)",
	WrPort,			F_MEM|F_STORE|F_DISP,
	DNA, DNA,		DGPR(RT), DGPR(BS), DNA,
	(ss_lr_temp = READ_WORD(WR_BASE(GPR(BS)+OFS)),
	 ss_lr_temp = (((GPR(RT) << (8 * (4 - WR_SIZE(GPR(BS) + OFS)))) 
			& ~WR_PROT_MASK2(GPR(BS)+OFS)) |
		       (ss_lr_temp & WR_PROT_MASK2(GPR(BS)+OFS))),
	 WRITE_WORD(ss_lr_temp, WR_BASE(GPR(BS)+OFS))))
#endif

/* reg+reg loads and stores */

#define LB_RR_IMPL							\
  {									\
    sbyte_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_BYTE(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, (word_t)(sword_t)_result);				\
  }
DEFINST(LB_RR,			0xc0,
	"lb",			"t,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

#define LBU_RR_IMPL							\
  {									\
    byte_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_BYTE(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, (word_t)_result);					\
  }
DEFINST(LBU_RR,			0xc1, 
	"lbu", 			"t,(b+d)",
	RdPort, 		F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

#define LH_RR_IMPL							\
  {									\
    shalf_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_HALF(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, (word_t)(sword_t)_result);				\
  }
DEFINST(LH_RR,	 		0xc2,
	"lh",			"t,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

#define LHU_RR_IMPL							\
  {									\
    half_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_HALF(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, (word_t)_result);					\
  }
DEFINST(LHU_RR,			0xc3, 
	"lhu", 			"t,(b+d)",
	RdPort, 		F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

#define LW_RR_IMPL							\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, _result);						\
  }
DEFINST(LW_RR,			0xc4,
	"lw", 			"t,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

#define DLW_RR_IMPL							\
  {									\
    word_t _result_hi, _result_lo;					\
    enum md_fault_type _fault;						\
									\
    if ((RT) & 01)							\
      DECLARE_FAULT(md_fault_alignment)					\
									\
    _result_hi = READ_WORD(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    _result_lo = READ_WORD(GPR(BS) + GPR(RD) + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, _result_hi);						\
    SET_GPR((RT) + 1, _result_lo);					\
  }
DEFINST(DLW_RR,			0xce,
	"dlw",			"t,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DGPR_D(RT), DNA,	DNA, DGPR(BS), DGPR(RD))

#define L_S_RR_IMPL							\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_FPR_L(FT, _result);						\
  }
DEFINST(L_S_RR,			0xc5,
	"l.s",	 		"T,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DFPR_L(FT), DNA,	DNA, DGPR(BS), DGPR(RD))

#define L_D_RR_IMPL							\
  {									\
    word_t _result_hi, _result_lo;					\
    enum md_fault_type _fault;						\
									\
    if ((FT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    _result_hi = READ_WORD(GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    _result_lo = READ_WORD(GPR(BS) + GPR(RD) + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_FPR_L(FT, _result_hi);						\
    SET_FPR_L((FT) + 1, _result_lo);					\
  }
DEFINST(L_D_RR,			0xcf,
	"l.d",			"T,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DFPR_D(FT), DNA,	DNA, DGPR(BS), DGPR(RD))

#define SB_RR_IMPL							\
  {									\
    byte_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (byte_t)(word_t)GPR(RT);					\
    WRITE_BYTE(_src, GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SB_RR, 			0xc6, 
	"sb", 			"t,(b+d)", 
	WrPort, 		F_MEM|F_STORE|F_RR,
	DNA, DNA,	 	DGPR(RT), DGPR(BS), DGPR(RD))

#define SH_RR_IMPL							\
  {									\
    half_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (half_t)(word_t)GPR(RT);					\
    WRITE_HALF(_src, GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SH_RR,	 		0xc7, 
	"sh", 			"t,(b+d)", 
	WrPort,			F_MEM|F_STORE|F_RR,
	DNA, DNA,	 	DGPR(RT), DGPR(BS), DGPR(RD))

#define SW_RR_IMPL							\
  {									\
    word_t _src;							\
    enum md_fault_type _fault;						\
									\
    _src = (word_t)GPR(RT);						\
    WRITE_WORD(_src, GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SW_RR,	 		0xc8, 
	"sw", 			"t,(b+d)", 
	WrPort, 		F_MEM|F_STORE|F_RR,
	DNA, DNA,		DGPR(RT), DGPR(BS), DGPR(RD))

/* FIXME: this code not fault-safe, yet... */
#define DSW_RR_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    if ((RT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    WRITE_WORD(GPR(RT), GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(GPR((RT)+1), GPR(BS) + GPR(RD) + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(DSW_RR,			0xd0,
	"dsw",			"t,(b+d)",
	WrPort,			F_MEM|F_STORE|F_RR,
	DNA, DNA,		DGPR_D(RT), DGPR(BS), DGPR(RD))

/* FIXME: this code not fault-safe, yet... */
#define DSZ_RR_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(GPR(0), GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(GPR(0), GPR(BS) + GPR(RD) + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(DSZ_RR,			0xd1,
	"dsz",			"(b+d)",
	WrPort,			F_MEM|F_STORE|F_RR,
	DNA, DNA,		DNA, DGPR(BS), DGPR(RD))

#define S_S_RR_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(FPR_L(FT), GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(S_S_RR,			0xc9, 
	"s.s",	 		"T,(b+d)", 
	WrPort, 		F_MEM|F_STORE|F_RR,
	DNA, DNA,		DFPR_L(FT), DGPR(BS), DGPR(RD))

/* FIXME: this code not fault-safe, yet... */
#define S_D_RR_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    if ((FT) & 01)							\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    WRITE_WORD(FPR_L(FT), GPR(BS) + GPR(RD), _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
    WRITE_WORD(FPR_L((FT)+1), GPR(BS) + GPR(RD) + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(S_D_RR,			0xd2,
	"s.d",			"T,(b+d)",
	WrPort,			F_MEM|F_STORE|F_RR,
	DNA, DNA,		DFPR_D(FT), DGPR(BS), DGPR(RD))


/* reg + reg + 4 addressing mode, used to synthesize `l.d r,(s+t)^++' */
/* FIXME: obsolete, but do not delete or predecoded state images will break! */
#define L_S_RR_R2_IMPL							\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + GPR(RD) + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_FPR_L(FT, _result);						\
  }
DEFINST(L_S_RR_R2,		0xca,
	"l.s.r2", 		"T,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DFPR_L(FT), DNA,	DNA, DGPR(BS), DGPR(RD))


/* FIXME: obsolete, but do not delete or predecoded state images will break! */
#define S_S_RR_R2_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(FPR_L(FT), GPR(BS) + GPR(RD) + 4, _fault);		\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(S_S_RR_R2,		0xcb,
	"s.s.r2", 		"T,(b+d)", 
	WrPort, 		F_MEM|F_STORE|F_RR,
	DNA, DNA,		DFPR_L(FT), DGPR(BS), DGPR(RD))

/* FIXME: obsolete, but do not delete or predecoded state images will break! */
#define LW_RR_R2_IMPL							\
  {									\
    word_t _result;							\
    enum md_fault_type _fault;						\
									\
    _result = READ_WORD(GPR(BS) + GPR(RD) + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
									\
    SET_GPR(RT, _result);						\
  }
DEFINST(LW_RR_R2,		0xcc,
	"lw.r2",		"t,(b+d)",
	RdPort,			F_MEM|F_LOAD|F_RR,
	DGPR(RT), DNA,		DNA, DGPR(BS), DGPR(RD))

/* FIXME: obsolete, but do not delete or predecoded state images will break! */
#define SW_RR_R2_IMPL							\
  {									\
    enum md_fault_type _fault;						\
									\
    WRITE_WORD(GPR(RT), GPR(BS) + GPR(RD) + 4, _fault);			\
    if (_fault != md_fault_none)					\
      DECLARE_FAULT(_fault);						\
  }
DEFINST(SW_RR_R2,		0xcd, 
	"sw.r2", 		"t,(b+d)",
	WrPort, 		F_MEM|F_STORE|F_RR,
	DNA, DNA,		DGPR(RT), DGPR(BS), DGPR(RD))


/*
 * Integer ALU operations
 */

#define ADD_IMPL							\
  {									\
    if (OVER(GPR(RS), GPR(RT)))						\
      DECLARE_FAULT(md_fault_overflow);					\
									\
    SET_GPR(RD, GPR(RS) + GPR(RT));					\
  }
DEFINST(ADD,	 		0x40,
	"add", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define ADDI_IMPL							\
  {									\
    if (OVER(GPR(RS), IMM))						\
      DECLARE_FAULT(md_fault_overflow);					\
									\
    SET_GPR(RT, GPR(RS) + IMM);						\
  }
DEFINST(ADDI,			0x41,
	"addi",			"t,s,i",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)

#define ADDU_IMPL							\
  {									\
    SET_GPR(RD, GPR(RS) + GPR(RT));					\
  }
DEFINST(ADDU, 			0x42,
	"addu", 		"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define ADDIU_IMPL							\
  {									\
    SET_GPR(RT, GPR(RS) + IMM);						\
  }
DEFINST(ADDIU,			0x43,
	"addiu",		"t,s,i",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)

#define SUB_IMPL							\
  {									\
    if (UNDER(GPR(RS), GPR(RT)))					\
      DECLARE_FAULT(md_fault_overflow);					\
									\
    SET_GPR(RD, GPR(RS) - GPR(RT));					\
  }
DEFINST(SUB, 			0x44,
	"sub", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define SUBU_IMPL							\
  {									\
    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)

#define MULT_IMPL							\
  {									\
    bool_t _sign1, _sign2;						\
    int _i;								\
    sword_t _op1, _op2;							\
									\
    /* HI,LO <- [rs] * [rt], integer product of [rs] & [rt] to HI/LO */	\
    _sign1 = _sign2 = FALSE;						\
    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 = TRUE;							\
	_op1 = (~_op1) + 1;						\
      }									\
    if (_op2 & 020000000000)						\
      {									\
	_sign2 = TRUE;							\
	_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);							\
      }									\
  }
DEFINST(MULT, 			0x46,
	"mult", 		"s,t", 
	IntMULT, 		F_ICOMP|F_LONGLAT,
	DHI, DLO,		DGPR(RT), DGPR(RS), DNA)

#define MULTU_IMPL							\
  {									\
    int _i;								\
									\
    /* HI,LO <- [rs] * [rt], integer product of [rs] & [rt] to HI/LO */	\
    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));					\
	  }								\
      }									\
  }
DEFINST(MULTU, 			0x47,
	"multu", 		"s,t", 
	IntMULT, 		F_ICOMP|F_LONGLAT,
	DHI, DLO,		DGPR(RT), DGPR(RS), DNA)

#define DIV_IMPL							\
  {									\
    if (GPR(RT) == 0)							\
      DECLARE_FAULT(md_fault_div0);					\
									\
    SET_LO(GPR(RS) / GPR(RT));						\
    SET_HI(GPR(RS) % GPR(RT));						\
  }
DEFINST(DIV, 			0x48,
	"div", 			"s,t", 
	IntDIV, 		F_ICOMP|F_LONGLAT,
	DHI, DLO,		DGPR(RT), DGPR(RS), DNA)

#define DIVU_IMPL							\
  {									\
    if (GPR(RT) == 0)							\
      DECLARE_FAULT(md_fault_div0);					\
									\
    SET_LO(((unsigned)GPR(RS)) / ((unsigned)GPR(RT)));			\
    SET_HI(((unsigned)GPR(RS)) % ((unsigned)GPR(RT)));			\
  }
DEFINST(DIVU, 			0x49,
	"divu", 		"s,t", 
	IntDIV, 		F_ICOMP|F_LONGLAT,
	DHI, DLO,		DGPR(RT), DGPR(RS), DNA)

#define MFHI_IMPL							\
  {									\
    SET_GPR(RD, HI);							\
  }
DEFINST(MFHI, 			0x4a,
	"mfhi", 		"d",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DHI, DNA, DNA)

#define MTHI_IMPL							\
  {									\
    SET_HI(GPR(RS));							\
  }
DEFINST(MTHI, 			0x4b,
	"mthi", 		"s",
	IntALU, 		F_ICOMP,
	DHI, DNA,		DGPR(RS), DNA, DNA)

#define MFLO_IMPL							\
  {									\
    SET_GPR(RD, LO);							\
  }
DEFINST(MFLO, 			0x4c,
	"mflo", 		"d", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DLO, DNA, DNA)

#define MTLO_IMPL							\
  {									\
    SET_LO(GPR(RS));							\
  }
DEFINST(MTLO, 			0x4d,
	"mtlo", 		"s", 
	IntALU, 		F_ICOMP,
	DLO, DNA,		DGPR(RS), DNA, DNA)

/* AND conflicts with GNU defs */
#define AND__IMPL							\
  {									\
    SET_GPR(RD, GPR(RS) & GPR(RT));					\
  }
DEFINST(AND_, 			0x4e,
	"and", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define ANDI_IMPL							\
  {									\
    SET_GPR(RT, GPR(RS) & UIMM);					\
  }
DEFINST(ANDI,			0x4f,
	"andi",			"t,s,u",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA,	 	DGPR(RS), DNA, DNA)

#define OR_IMPL								\
  {									\
    SET_GPR(RD, GPR(RS) | GPR(RT));					\
  }
DEFINST(OR, 			0x50,
	"or", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define ORI_IMPL							\
  {									\
    SET_GPR(RT, GPR(RS) | UIMM);					\
  }
DEFINST(ORI, 			0x51,
	"ori",			"t,s,u",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)

#define XOR_IMPL							\
  {									\
    SET_GPR(RD, GPR(RS) ^ GPR(RT));					\
  }
DEFINST(XOR, 			0x52,
	"xor", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define XORI_IMPL							\
  {									\
    SET_GPR(RT, GPR(RS) ^ UIMM);					\
  }
DEFINST(XORI, 			0x53,
	"xori",			"t,s,u",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)

#define NOR_IMPL							\
  {									\
    SET_GPR(RD, ~(GPR(RS) | GPR(RT)));					\
  }
DEFINST(NOR, 			0x54,
	"nor", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define SLL_IMPL							\
  {									\
    SET_GPR(RD, GPR(RT) << SHAMT);					\
  }
DEFINST(SLL, 			0x55,
	"sll", 			"d,t,H", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DNA, DNA)

#define SLLV_IMPL							\
  {									\
    SET_GPR(RD, GPR(RT) << (GPR(RS) & 037));				\
  }
DEFINST(SLLV, 			0x56,
	"sllv", 		"d,t,s", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DGPR(RS), DNA)

#ifdef FAST_SRL
#define SRL_IMPL							\
  {									\
    SET_GPR(RD, ((unsigned)GPR(RT)) >> SHAMT);				\
  }
#else /* !FAST_SRL */
#define SRL_IMPL							\
  {									\
    /* C standard says >> is implementation specific;			\
       could be SRL, SRA, or dependent on signdness of operand */	\
    if ((SHAMT) != 0)							\
      {									\
	word_t _rd;							\
									\
	_rd = (((unsigned)GPR(RT)) >> 1) & ~0x80000000;	/* first bit */	\
	SET_GPR(RD, (_rd >> ((SHAMT) - 1)));		/* rest */	\
      }									\
    else								\
      {									\
	SET_GPR(RD, GPR(RT));						\
      }									\
  }
#endif /* FAST_SRL */
DEFINST(SRL, 			0x57,
	"srl", 			"d,t,H", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DNA, DNA)

#ifdef FAST_SRL
#define SRLV_IMPL							\
  {									\
    SET_GPR(RD, ((unsigned)GPR(RT)) >> (GPR(RS) & 037));		\
  }
#else /* !FAST_SRL */
#define SRLV_IMPL							\
  {									\
    int _shamt = GPR(RS) & 037;						\
									\
    /* C standard says >> is implementation specific;			\
       could be SRL, SRA, or dependent on signdness of operand */	\
    if (_shamt != 0)							\
      {									\
	word_t _rd;							\
									\
	_rd = (((unsigned)GPR(RT)) >> 1) & ~0x80000000;	/* first bit */	\
	SET_GPR(RD, (_rd >> (_shamt - 1)));		/* rest */	\
      }									\
    else								\
      {									\
	SET_GPR(RD, GPR(RT));						\
      }									\
  }
#endif /* FAST_SRL */
DEFINST(SRLV, 			0x58,
	"srlv", 		"d,t,s", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DGPR(RS), DNA)

#ifdef FAST_SRA
#define SRA_IMPL							\
  {									\
    SET_GPR(RD, ((signed)GPR(RT)) >> SHAMT);				\
  }
#else /* !FAST_SRA */
#define SRA_IMPL							\
  {									\
    int _i;								\
									\
    /* C standard says >> is implementation specific;			\
       could be SRL, SRA, or dependent on sign-ness of operand */	\
    /* rd <- [rt] >> SHAMT */						\
    if (GPR(RT) & 0x80000000)						\
      {									\
        SET_GPR(RD, GPR(RT));						\
        for (_i = 0; _i < SHAMT; _i++)					\
	  {								\
	    SET_GPR(RD, (GPR(RD) >> 1) | 0x80000000);			\
	  }								\
      }									\
    else								\
      {									\
	SET_GPR(RD, GPR(RT) >> SHAMT);					\
      }									\
  }
#endif /* FAST_SRA */
DEFINST(SRA, 			0x59,
	"sra", 			"d,t,H", 
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DNA, DNA)

#ifdef FAST_SRA
#define SRAV_IMPL							\
  {									\
    SET_GPR(RD, ((signed)GPR(RT)) >> (GPR(RS) & 037));			\
  }
#else /* !FAST_SRA */
#define SRAV_IMPL							\
  {									\
    int _i;								\
    int _shamt = GPR(RS) & 037;						\
									\
    /* C standard says >> is implementation specific;			\
       could be SRL, SRA, or dependent on sign-ness of operand */	\
    /* rd <- [rt] >> SHAMT */						\
    if (GPR(RT) & 0x80000000)						\
      {									\
        SET_GPR(RD, GPR(RT));						\
        for (_i = 0; _i < _shamt; _i++)					\
	  {								\
	    SET_GPR(RD, (GPR(RD) >> 1) | 0x80000000);			\
	  }								\
      }									\
    else								\
      {									\
	SET_GPR(RD, GPR(RT) >> _shamt);					\
      }									\
  }
#endif /* FAST_SRA */
DEFINST(SRAV, 			0x5a,
	"srav", 		"d,t,s",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RT), DGPR(RS), DNA)

#define SLT_IMPL							\
  {									\
    if (GPR(RS) < GPR(RT))						\
      SET_GPR(RD, 1);							\
    else								\
      SET_GPR(RD, 0);							\
  }
DEFINST(SLT,			0x5b,
	"slt", 			"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define SLTI_IMPL							\
  {									\
    if (GPR(RS) < IMM)							\
      SET_GPR(RT, 1);							\
    else								\
      SET_GPR(RT, 0);							\
  }
DEFINST(SLTI, 			0x5c,
	"slti",			"t,s,i",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)

#define SLTU_IMPL							\
  {									\
    if (((unsigned)GPR(RS)) < ((unsigned)GPR(RT)))			\
      SET_GPR(RD, 1);							\
    else								\
      SET_GPR(RD, 0);							\
  }
DEFINST(SLTU, 			0x5d,
	"sltu", 		"d,s,t",
	IntALU, 		F_ICOMP,
	DGPR(RD), DNA,		DGPR(RS), DGPR(RT), DNA)

#define SLTIU_IMPL							\
  {									\
    if ((unsigned)GPR(RS) < (unsigned)IMM)				\
      SET_GPR(RT, 1);							\
    else								\
      SET_GPR(RT, 0);							\
  }
DEFINST(SLTIU,			0x5e,
	"sltiu",		"t,s,i",
	IntALU,			F_ICOMP|F_IMM,
	DGPR(RT), DNA, 		DGPR(RS), DNA, DNA)


/*
 * Floating Point ALU operations
 */

#define FADD_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, FPR_F(FS) + FPR_F(FT));				\
  }
DEFINST(FADD_S,			0x70,
	"add.s",		"D,S,T",
	FloatADD,		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_F(FS), DFPR_F(FT), DNA)

#define FADD_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, FPR_D(FS) + FPR_D(FT));				\
  }
DEFINST(FADD_D,			0x71,
	"add.d",		"D,S,T",
	FloatADD,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_D(FS), DFPR_D(FT), DNA)

#define FSUB_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, FPR_F(FS) - FPR_F(FT));				\
  }
DEFINST(FSUB_S,			0x72,
	"sub.s",		"D,S,T",
	FloatADD, 		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_F(FS), DFPR_F(FT), DNA)

#define FSUB_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, FPR_D(FS) - FPR_D(FT));				\
  }
DEFINST(FSUB_D,			0x73,
	"sub.d",		"D,S,T",
	FloatADD, 		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_D(FS), DFPR_D(FT), DNA)

#define FMUL_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, FPR_F(FS) * FPR_F(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)

#define FMUL_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, FPR_D(FS) * FPR_D(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)

#define FDIV_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, FPR_F(FS) / FPR_F(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)

#define FDIV_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01) || ((FT) & 01))			\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, FPR_D(FS) / FPR_D(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)

#define FABS_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, (sfloat_t)fabs((dfloat_t)FPR_F(FS)));			\
  }
DEFINST(FABS_S,			0x78,
	"abs.s",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define FABS_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, fabs(FPR_D(FS)));					\
  }
DEFINST(FABS_D,			0x79,
	"abs.d",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_D(FS), DNA, DNA)

#define FMOV_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, FPR_F(FS));						\
  }
DEFINST(FMOV_S,			0x7a,
	"mov.s",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define FMOV_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, FPR_D(FS));						\
  }
DEFINST(FMOV_D,			0x7b,
	"mov.d",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_D(FS), DNA, DNA)

#define FNEG_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, -FPR_F(FS));						\
  }
DEFINST(FNEG_S,			0x7c,
	"neg.s",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define FNEG_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, -FPR_D(FS));						\
  }
DEFINST(FNEG_D,			0x7d,
	"neg.d",		"D,S",
	FloatADD,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_D(FS), DNA, DNA)

#define CVT_S_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, (float)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)

#define CVT_S_W_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, (float)FPR_L(FS));					\
  }
DEFINST(CVT_S_W,		0x81,
	"cvt.s.w", 		"D,S",
	FloatCVT,		F_FCOMP,
	DFPR_F(FD), DNA,	DFPR_L(FS), DNA, DNA)

#define CVT_D_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, (dfloat_t)FPR_F(FS));					\
  }
DEFINST(CVT_D_S,		0x82,
	"cvt.d.s",		"D,S",
	FloatCVT,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define CVT_D_W_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, (dfloat_t)FPR_L(FS));					\
  }
DEFINST(CVT_D_W,		0x83,
	"cvt.d.w",		"D,S",
	FloatCVT,		F_FCOMP,
	DFPR_D(FD), DNA,	DFPR_L(FS), DNA, DNA)

#define CVT_W_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_L(FD, (sword_t)FPR_F(FS));					\
  }
DEFINST(CVT_W_S,		0x84,
	"cvt.w.s", 		"D,S",
	FloatCVT,		F_FCOMP,
	DFPR_L(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define CVT_W_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_L(FD, (sword_t)FPR_D(FS));					\
  }
DEFINST(CVT_W_D,		0x85,
	"cvt.w.d", 		"D,S",
	FloatCVT,		F_FCOMP,
	DFPR_L(FD), DNA,	DFPR_D(FS), DNA, DNA)

#define C_EQ_S_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_F(FS) == FPR_F(FT));					\
  }
DEFINST(C_EQ_S,			0x90,
	"c.eq.s", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_F(FS), DFPR_F(FT), DNA)

#define C_EQ_D_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_D(FS) == FPR_D(FT));					\
  }
DEFINST(C_EQ_D,			0x91,
	"c.eq.d", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_D(FS), DFPR_D(FT), DNA)

#define C_LT_S_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_F(FS) < FPR_F(FT));					\
  }
DEFINST(C_LT_S,			0x92,
	"c.lt.s", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_F(FS), DFPR_F(FT), DNA)

#define C_LT_D_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_D(FS) < FPR_D(FT));					\
  }
DEFINST(C_LT_D,			0x93,
	"c.lt.d", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_D(FS), DFPR_D(FT), DNA)

#define C_LE_S_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_F(FS) <= FPR_F(FT));					\
  }
DEFINST(C_LE_S,			0x94,
	"c.le.s", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_F(FS), DFPR_F(FT), DNA)

#define C_LE_D_IMPL							\
  {									\
    if (((FS) & 01) || ((FT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FCC(FPR_D(FS) <= FPR_D(FT));					\
  }
DEFINST(C_LE_D,			0x95,
	"c.le.d", 		"S,T",
	FloatCMP,		F_FCOMP,
	DFCC, DNA,		DFPR_D(FS), DFPR_D(FT), DNA)

#define FSQRT_S_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_F(FD, (sfloat_t)sqrt((dfloat_t)FPR_F(FS)));			\
  }
DEFINST(FSQRT_S,		0x96,
	"sqrt.s",		"D,S",
	FloatSQRT,		F_FCOMP|F_LONGLAT,
	DFPR_F(FD), DNA,	DFPR_F(FS), DNA, DNA)

#define FSQRT_D_IMPL							\
  {									\
    if (((FD) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_D(FD, sqrt(FPR_D(FS)));					\
  }
DEFINST(FSQRT_D,		0x97,
	"sqrt.d",		"D,S",
	FloatSQRT,		F_FCOMP|F_LONGLAT,
	DFPR_D(FD), DNA,	DFPR_D(FS), DNA, DNA)


/*
 * miscellaneous
 */

#define SYSCALL_IMPL							\
  {									\
    SYSCALL(inst);							\
  }
DEFINST(SYSCALL, 		0xa0,
	"syscall", 		"",
	NA, 			F_TRAP,
	DNA, DNA,		DNA, DNA, DNA)

#define BREAK_IMPL							\
  {									\
    /* NOTE: these are decoded speculatively, as they occur in integer	\
       divide sequences, however, they should NEVER be executed under	\
       non-exception conditions */					\
    DECLARE_FAULT(md_fault_break);					\
  }

DEFINST(BREAK,			0xa1,
	"break",		"B",
	NA,			F_TRAP,
	DNA, DNA,		DNA, DNA, DNA)

#define LUI_IMPL							\
  {									\
    SET_GPR(RT, UIMM << 16);						\
  }
DEFINST(LUI, 			0xa2,
	"lui",			"t,U",
	IntALU,			F_ICOMP,
	DGPR(RT), DNA, 		DNA, DNA, DNA)

#define MFC1_IMPL							\
  {									\
    SET_GPR(RT, FPR_L(FS));						\
  }
DEFINST(MFC1,	 		0xa3,
	"mfc1", 		"t,S",
	IntALU, 		F_ICOMP,
	DGPR(RT), DNA,		DFPR_L(FS), DNA, DNA)

#define DMFC1_IMPL							\
  {									\
    if (((RT) & 01) || ((FS) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_GPR(RT, FPR_L(FS));						\
    SET_GPR((RT)+1, FPR_L((FS)+1));					\
  }
DEFINST(DMFC1, 			0xa7,
	"dmfc1",		"t,S",
	IntALU,			F_ICOMP,
	DGPR_D(RT), DNA, 	DFPR_D(FS), DNA, DNA)

#define CFC1_IMPL							\
  {									\
    /* FIXME: is this needed??? */					\
  }
DEFINST(CFC1, 			0xa4,
	"cfc1", 		"t,S",
	IntALU, 		F_ICOMP,
	DNA, DNA,		DNA, DNA, DNA)

#define MTC1_IMPL							\
  {									\
    SET_FPR_L(FS, GPR(RT));						\
  }
DEFINST(MTC1, 			0xa5,
	"mtc1", 		"t,S",
	IntALU, 		F_ICOMP,
	DFPR_L(FS), DNA,	DGPR(RT), DNA, DNA)

#define DMTC1_IMPL							\
  {									\
    if (((FS) & 01) || ((RT) & 01))					\
      DECLARE_FAULT(md_fault_alignment);				\
									\
    SET_FPR_L(FS, GPR(RT));						\
    SET_FPR_L((FS)+1, GPR((RT)+1));					\
  }
DEFINST(DMTC1,	 		0xa8,
	"dmtc1",		"t,S",
	IntALU,			F_ICOMP,
	DFPR_D(FS), DNA,	DGPR_D(RT), DNA, DNA)

#define CTC1_IMPL							\
  {									\
    /* FIXME: is this needed??? */					\
  }
DEFINST(CTC1, 			0xa6,
	"ctc1", 		"t,S",
	IntALU, 		F_ICOMP,
	DNA, DNA,		DNA, DNA, DNA)


/* clean up all definitions... */
#undef NOP_IMPL
#undef JUMP_IMPL
#undef JAL_IMPL
#undef JR_IMPL
#undef JALR_IMPL
#undef BEQ_IMPL
#undef BNE_IMPL
#undef BLEZ_IMPL
#undef BGTZ_IMPL
#undef BLTZ_IMPL
#undef BGEZ_IMPL
#undef BC1F_IMPL
#undef BC1T_IMPL
#undef LB_IMPL
#undef LBU_IMPL
#undef LH_IMPL
#undef LHU_IMPL
#undef LW_IMPL
#undef DLW_IMPL
#undef L_S_IMPL
#undef L_D_IMPL
#undef SB_IMPL
#undef SH_IMPL
#undef SW_IMPL
#undef DSW_IMPL
#undef DSZ_IMPL
#undef S_S_IMPL
#undef S_D_IMPL
#undef LB_RR_IMPL
#undef LBU_RR_IMPL
#undef LH_RR_IMPL
#undef LHU_RR_IMPL
#undef LW_RR_IMPL
#undef DLW_RR_IMPL
#undef L_S_RR_IMPL
#undef L_D_RR_IMPL
#undef SB_RR_IMPL
#undef SH_RR_IMPL
#undef SW_RR_IMPL
#undef DSW_RR_IMPL
#undef DSZ_RR_IMPL
#undef S_S_RR_IMPL
#undef S_D_RR_IMPL
#undef L_S_RR_R2_IMPL
#undef S_S_RR_R2_IMPL
#undef LW_RR_R2_IMPL
#undef SW_RR_R2_IMPL
#undef ADD_IMPL
#undef ADDI_IMPL
#undef ADDU_IMPL
#undef ADDIU_IMPL
#undef SUB_IMPL
#undef SUBU_IMPL
#undef MULT_IMPL
#undef MULTU_IMPL
#undef DIV_IMPL
#undef DIVU_IMPL
#undef MFHI_IMPL
#undef MTHI_IMPL
#undef MFLO_IMPL
#undef MTLO_IMPL
#undef AND__IMPL
#undef ANDI_IMPL
#undef OR_IMPL
#undef ORI_IMPL
#undef XOR_IMPL
#undef XORI_IMPL
#undef NOR_IMPL
#undef SLL_IMPL
#undef SLLV_IMPL
#undef SRL_IMPL
#undef SRLV_IMPL
#undef SRA_IMPL
#undef SRAV_IMPL
#undef SLT_IMPL
#undef SLTI_IMPL
#undef SLTU_IMPL
#undef SLTIU_IMPL
#undef FADD_S_IMPL
#undef FADD_D_IMPL
#undef FSUB_S_IMPL
#undef FSUB_D_IMPL
#undef FMUL_S_IMPL
#undef FMUL_D_IMPL
#undef FDIV_S_IMPL
#undef FDIV_D_IMPL
#undef FABS_S_IMPL
#undef FABS_D_IMPL
#undef FMOV_S_IMPL
#undef FMOV_D_IMPL
#undef FNEG_S_IMPL
#undef FNEG_D_IMPL
#undef CVT_S_D_IMPL
#undef CVT_S_W_IMPL
#undef CVT_D_S_IMPL
#undef CVT_D_W_IMPL
#undef CVT_W_S_IMPL
#undef CVT_W_D_IMPL
#undef C_EQ_S_IMPL
#undef C_EQ_D_IMPL
#undef C_LT_S_IMPL
#undef C_LT_D_IMPL
#undef C_LE_S_IMPL
#undef C_LE_D_IMPL
#undef FSQRT_S_IMPL
#undef FSQRT_D_IMPL
#undef SYSCALL_IMPL
#undef BREAK_IMPL
#undef LUI_IMPL
#undef MFC1_IMPL
#undef DMFC1_IMPL
#undef CFC1_IMPL
#undef MTC1_IMPL
#undef DMTC1_IMPL
#undef CTC1_IMPL

#undef DEFINST
#undef DEFLINK
#undef CONNECT
