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