c552b06a8c
Auxiliary Functions and Formats for FP in general arch/mips/isa/decoder.isa: ISA Parser doesnt accept operands of different types in one instruction so fix this for unorderedFP functions... Add basic support for Paired Singled (PS) FP ops which happen to be part of the MIPS 32-ASE but turned out to be included in the MIPS32ISA manual... The PS instructions allow SIMD in a pipeline... arch/mips/isa/formats/fp.isa: Add some more Formats for FP operation. I will add some auxiliary code through these formats to alleviate code redundancy in the decoder.isa arch/mips/isa/operands.isa: Add operands for Paired Singles Ops arch/mips/isa_traits.cc: removed convert&round function and replace with fpConvert. The whole "rounding mode" stuff is something that should be considered for full-system mode... Also added skeletons for the unorderedFP,truncFP,and condition code funcs. arch/mips/isa_traits.hh: declare some Functions arch/mips/types.hh: add new conversion types --HG-- extra : convert_revision : 79251d590a27b74a3d6a62a2fbb937df3e59963f
1543 lines
58 KiB
C++
1543 lines
58 KiB
C++
// -*- mode:c++ -*-
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The actual MIPS32 ISA decoder
|
|
// -----------------------------
|
|
// The following instructions are specified in the MIPS32 ISA
|
|
// Specification. Decoding closely follows the style specified
|
|
// in the MIPS32 ISAthe specification document starting with Table
|
|
// A-2 (document available @ www.mips.com)
|
|
//
|
|
//@todo: Distinguish "unknown/future" use insts from "reserved"
|
|
// ones
|
|
decode OPCODE_HI default Unknown::unknown() {
|
|
|
|
// Derived From ... Table A-2 MIPS32 ISA Manual
|
|
0x0: decode OPCODE_LO {
|
|
|
|
0x0: decode FUNCTION_HI {
|
|
0x0: decode FUNCTION_LO {
|
|
0x1: decode MOVCI {
|
|
format BasicOp {
|
|
0: movf({{ if (getFPConditionCode(CC) == 0) Rd = Rs}});
|
|
1: movt({{ if (getFPConditionCode(CC) == 1) Rd = Rs}});
|
|
}
|
|
}
|
|
|
|
format BasicOp {
|
|
|
|
//Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields
|
|
//are used to distinguish among the SLL, NOP, SSNOP and EHB functions.
|
|
0x0: decode RS {
|
|
0x0: decode RT { //fix Nop traditional vs. Nop converted disassembly later
|
|
0x0: decode RD default Nop::nop(){
|
|
0x0: decode SA {
|
|
0x1: ssnop({{ ; }}); //really sll r0,r0,1
|
|
0x3: ehb({{ ; }}); //really sll r0,r0,3
|
|
}
|
|
}
|
|
|
|
default: sll({{ Rd = Rt.uw << SA; }});
|
|
}
|
|
|
|
}
|
|
|
|
0x2: decode RS_SRL {
|
|
0x0:decode SRL {
|
|
0: srl({{ Rd = Rt.uw >> SA; }});
|
|
|
|
//Hardcoded assuming 32-bit ISA, probably need parameter here
|
|
1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}});
|
|
}
|
|
}
|
|
|
|
0x3: decode RS {
|
|
0x0: sra({{
|
|
uint32_t temp = Rt >> SA;
|
|
|
|
if ( (Rt & 0x80000000) > 0 ) {
|
|
uint32_t mask = 0x80000000;
|
|
for(int i=0; i < SA; i++) {
|
|
temp |= mask;
|
|
mask = mask >> 1;
|
|
}
|
|
}
|
|
|
|
Rd = temp;
|
|
}});
|
|
}
|
|
|
|
0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }});
|
|
|
|
0x6: decode SRLV {
|
|
0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }});
|
|
|
|
//Hardcoded assuming 32-bit ISA, probably need parameter here
|
|
1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}});
|
|
}
|
|
|
|
0x7: srav({{
|
|
int shift_amt = Rs<4:0>;
|
|
|
|
uint32_t temp = Rt >> shift_amt;
|
|
|
|
if ( (Rt & 0x80000000) > 0 ) {
|
|
uint32_t mask = 0x80000000;
|
|
for(int i=0; i < shift_amt; i++) {
|
|
temp |= mask;
|
|
mask = mask >> 1;
|
|
}
|
|
}
|
|
|
|
Rd = temp;
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x1: decode FUNCTION_LO {
|
|
|
|
//Table A-3 Note: "Specific encodings of the hint field are used
|
|
//to distinguish JR from JR.HB and JALR from JALR.HB"
|
|
format Jump {
|
|
0x0: decode HINT {
|
|
0:jr({{ NNPC = Rs & ~1; }},IsReturn);
|
|
|
|
1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn);
|
|
}
|
|
|
|
0x1: decode HINT {
|
|
0: jalr({{ Rd = NNPC; NNPC = Rs; }},IsCall,IsReturn);
|
|
|
|
1: jalr_hb({{ Rd = NNPC; NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
|
|
}
|
|
}
|
|
|
|
format BasicOp {
|
|
0x2: movz({{ if (Rt == 0) Rd = Rs; }});
|
|
0x3: movn({{ if (Rt != 0) Rd = Rs; }});
|
|
}
|
|
|
|
format BasicOp {
|
|
0x4: syscall({{ xc->syscall(R2); }},IsNonSpeculative);
|
|
0x5: break({{ panic("Not implemented break yet"); }},IsNonSpeculative);
|
|
0x7: sync({{ panic("Not implemented sync yet"); }},IsNonSpeculative);
|
|
}
|
|
}
|
|
|
|
0x2: decode FUNCTION_LO {
|
|
format BasicOp {
|
|
0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }});
|
|
0x1: mthi({{ xc->setMiscReg(Hi,Rs); }});
|
|
0x2: mflo({{ Rd = xc->readMiscReg(Lo); }});
|
|
0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }});
|
|
}
|
|
}
|
|
|
|
0x3: decode FUNCTION_LO {
|
|
format IntOp {
|
|
0x0: mult({{
|
|
int64_t temp1 = Rs.sd * Rt.sd;
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
|
|
0x1: multu({{
|
|
uint64_t temp1 = Rs.ud * Rt.ud;
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
|
|
0x2: div({{
|
|
xc->setMiscReg(Hi,Rs.sd % Rt.sd);
|
|
xc->setMiscReg(Lo,Rs.sd / Rt.sd);
|
|
}});
|
|
|
|
0x3: divu({{
|
|
xc->setMiscReg(Hi,Rs.ud % Rt.ud);
|
|
xc->setMiscReg(Lo,Rs.ud / Rt.ud);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x4: decode HINT {
|
|
0x0: decode FUNCTION_LO {
|
|
format IntOp {
|
|
0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}});
|
|
0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}});
|
|
0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}});
|
|
0x3: subu({{ Rd.sw = Rs.sw - Rt.sw;}});
|
|
0x4: and({{ Rd = Rs & Rt;}});
|
|
0x5: or({{ Rd = Rs | Rt;}});
|
|
0x6: xor({{ Rd = Rs ^ Rt;}});
|
|
0x7: nor({{ Rd = ~(Rs | Rt);}});
|
|
}
|
|
}
|
|
}
|
|
|
|
0x5: decode HINT {
|
|
0x0: decode FUNCTION_LO {
|
|
format IntOp{
|
|
0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}});
|
|
0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}});
|
|
}
|
|
}
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
format Trap {
|
|
0x0: tge({{ cond = (Rs.sw >= Rt.sw); }});
|
|
0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }});
|
|
0x2: tlt({{ cond = (Rs.sw < Rt.sw); }});
|
|
0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }});
|
|
0x4: teq({{ cond = (Rs.sw == Rt.sw); }});
|
|
0x6: tne({{ cond = (Rs.sw != Rt.sw); }});
|
|
}
|
|
}
|
|
}
|
|
|
|
0x1: decode REGIMM_HI {
|
|
0x0: decode REGIMM_LO {
|
|
format Branch {
|
|
0x0: bltz({{ cond = (Rs.sw < 0); }});
|
|
0x1: bgez({{ cond = (Rs.sw >= 0); }});
|
|
}
|
|
|
|
format BranchLikely {
|
|
0x2: bltzl({{ cond = (Rs.sw < 0); }});
|
|
0x3: bgezl({{ cond = (Rs.sw >= 0); }});
|
|
}
|
|
}
|
|
|
|
0x1: decode REGIMM_LO {
|
|
format Trap {
|
|
0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }});
|
|
0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }});
|
|
0x2: tlti( {{ cond = (Rs.sw < INTIMM); }});
|
|
0x3: tltiu({{ cond = (Rs.uw < INTIMM); }});
|
|
0x4: teqi( {{ cond = (Rs.sw == INTIMM);}});
|
|
0x6: tnei( {{ cond = (Rs.sw != INTIMM);}});
|
|
}
|
|
}
|
|
|
|
0x2: decode REGIMM_LO {
|
|
format Branch {
|
|
0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn);
|
|
0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn);
|
|
}
|
|
|
|
format BranchLikely {
|
|
0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn);
|
|
0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn);
|
|
}
|
|
}
|
|
|
|
0x3: decode REGIMM_LO {
|
|
format WarnUnimpl {
|
|
0x7: synci();
|
|
}
|
|
}
|
|
}
|
|
|
|
format Jump {
|
|
0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}});
|
|
|
|
0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn);
|
|
}
|
|
|
|
format Branch {
|
|
0x4: beq({{ cond = (Rs.sw == Rt.sw); }});
|
|
0x5: bne({{ cond = (Rs.sw != Rt.sw); }});
|
|
0x6: decode RT {
|
|
0x0: blez({{ cond = (Rs.sw <= 0); }});
|
|
}
|
|
|
|
0x7: decode RT {
|
|
0x0: bgtz({{ cond = (Rs.sw > 0); }});
|
|
}
|
|
}
|
|
}
|
|
|
|
0x1: decode OPCODE_LO {
|
|
format IntOp {
|
|
0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}});
|
|
0x1: addiu({{ Rt.sw = Rs.sw + imm;}});
|
|
0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }});
|
|
0x3: sltiu({{ Rt.uw = ( Rs.uw < (uint32_t)sextImm ) ? 1 : 0 }});
|
|
0x4: andi({{ Rt.sw = Rs.sw & zextImm;}});
|
|
0x5: ori({{ Rt.sw = Rs.sw | zextImm;}});
|
|
0x6: xori({{ Rt.sw = Rs.sw ^ zextImm;}});
|
|
|
|
0x7: decode RS {
|
|
0x0: lui({{ Rt = imm << 16}});
|
|
}
|
|
}
|
|
}
|
|
|
|
0x2: decode OPCODE_LO {
|
|
|
|
//Table A-11 MIPS32 COP0 Encoding of rs Field
|
|
0x0: decode RS_MSB {
|
|
0x0: decode RS {
|
|
format System {
|
|
0x0: mfc0({{
|
|
//uint64_t reg_num = Rd.uw;
|
|
|
|
Rt = xc->readMiscReg(RD << 5 | SEL);
|
|
}});
|
|
|
|
0x4: mtc0({{
|
|
//uint64_t reg_num = Rd.uw;
|
|
|
|
xc->setMiscReg(RD << 5 | SEL,Rt);
|
|
}});
|
|
|
|
0x8: mftr({{
|
|
//The contents of the coprocessor 0 register specified by the
|
|
//combination of rd and sel are loaded into general register
|
|
//rt. Note that not all coprocessor 0 registers support the
|
|
//sel field. In those instances, the sel field must be zero.
|
|
|
|
//MT Code Needed Here
|
|
}});
|
|
|
|
0xC: mttr({{
|
|
//The contents of the coprocessor 0 register specified by the
|
|
//combination of rd and sel are loaded into general register
|
|
//rt. Note that not all coprocessor 0 registers support the
|
|
//sel field. In those instances, the sel field must be zero.
|
|
|
|
//MT Code Needed Here
|
|
}});
|
|
|
|
|
|
0xA: rdpgpr({{
|
|
//Accessing Previous Shadow Set Register Number
|
|
//uint64_t prev = xc->readMiscReg(SRSCtl)/*[PSS]*/;
|
|
//uint64_t reg_num = Rt.uw;
|
|
|
|
//Rd = xc->regs.IntRegFile[prev];
|
|
//Rd = xc->shadowIntRegFile[prev][reg_num];
|
|
}});
|
|
|
|
0xB: decode RD {
|
|
|
|
0x0: decode SC {
|
|
0x0: dvpe({{
|
|
Rt.sw = xc->readMiscReg(MVPControl);
|
|
xc->setMiscReg(MVPControl,0);
|
|
}});
|
|
|
|
0x1: evpe({{
|
|
Rt.sw = xc->readMiscReg(MVPControl);
|
|
xc->setMiscReg(MVPControl,1);
|
|
}});
|
|
}
|
|
|
|
0x1: decode SC {
|
|
0x0: dmt({{
|
|
Rt.sw = xc->readMiscReg(VPEControl);
|
|
xc->setMiscReg(VPEControl,0);
|
|
}});
|
|
|
|
0x1: emt({{
|
|
Rt.sw = xc->readMiscReg(VPEControl);
|
|
xc->setMiscReg(VPEControl,1);
|
|
}});
|
|
}
|
|
|
|
0xC: decode SC {
|
|
0x0: di({{
|
|
Rt.sw = xc->readMiscReg(Status);
|
|
xc->setMiscReg(Status,0);
|
|
}});
|
|
|
|
0x1: ei({{
|
|
Rt.sw = xc->readMiscReg(Status);
|
|
xc->setMiscReg(Status,1);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0xE: wrpgpr({{
|
|
//Accessing Previous Shadow Set Register Number
|
|
//uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/);
|
|
//uint64_t reg_num = Rd.uw;
|
|
|
|
//xc->regs.IntRegFile[prev];
|
|
//xc->shadowIntRegFile[prev][reg_num] = Rt;
|
|
}});
|
|
}
|
|
}
|
|
|
|
//Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO
|
|
0x1: decode FUNCTION {
|
|
format System {
|
|
0x01: tlbr({{ }});
|
|
0x02: tlbwi({{ }});
|
|
0x06: tlbwr({{ }});
|
|
0x08: tlbp({{ }});
|
|
}
|
|
|
|
format WarnUnimpl {
|
|
0x18: eret();
|
|
0x1F: deret();
|
|
0x20: wait();
|
|
}
|
|
}
|
|
}
|
|
|
|
//Table A-13 MIPS32 COP1 Encoding of rs Field
|
|
0x1: decode RS_MSB {
|
|
|
|
0x0: decode RS_HI {
|
|
0x0: decode RS_LO {
|
|
format FloatOp {
|
|
0x0: mfc1 ({{ Rt.uw = Fs.uw<31:0>; }});
|
|
0x3: mfhc1({{ Rt.uw = Fs.ud<63:32>;}});
|
|
0x4: mtc1 ({{ Fs.uw = Rt.uw; }});
|
|
0x7: mthc1({{
|
|
uint64_t fs_hi = Rt.ud << 32;
|
|
uint64_t fs_lo = Fs.ud & 0x0000FFFF;
|
|
Fs.ud = fs_hi & fs_lo;
|
|
}});
|
|
}
|
|
|
|
format System {
|
|
0x2: cfc1({{
|
|
uint32_t fcsr_reg = xc->readMiscReg(FCSR);
|
|
|
|
switch (FS)
|
|
{
|
|
case 0:
|
|
Rt = xc->readMiscReg(FIR);
|
|
break;
|
|
case 25:
|
|
Rt = 0 | (fcsr_reg & 0xFE000000) >> 24 | (fcsr_reg & 0x00800000) >> 23;
|
|
break;
|
|
case 26:
|
|
Rt = 0 | (fcsr_reg & 0x0003F07C);
|
|
break;
|
|
case 28:
|
|
Rt = 0 | (fcsr_reg);
|
|
break;
|
|
case 31:
|
|
Rt = fcsr_reg;
|
|
break;
|
|
default:
|
|
panic("FP Control Value (%d) Not Available. Ignoring Access to"
|
|
"Floating Control Status Register",fcsr_reg);
|
|
}
|
|
}});
|
|
|
|
0x6: ctc1({{
|
|
uint32_t fcsr_reg = xc->readMiscReg(FCSR);
|
|
uint32_t temp;
|
|
|
|
switch (FS)
|
|
{
|
|
case 25:
|
|
temp = 0 | (Rt.uw<7:1> << 25) // move 31...25
|
|
| (fcsr_reg & 0x01000000) // bit 24
|
|
| (fcsr_reg & 0x004FFFFF);// bit 22...0
|
|
break;
|
|
|
|
case 26:
|
|
temp = 0 | (fcsr_reg & 0xFFFC0000) // move 31...18
|
|
| Rt.uw<17:12> << 12 // bit 17...12
|
|
| (fcsr_reg & 0x00000F80) << 7// bit 11...7
|
|
| Rt.uw<6:2> << 2 // bit 6...2
|
|
| (fcsr_reg & 0x00000002); // bit 1...0
|
|
break;
|
|
|
|
case 28:
|
|
temp = 0 | (fcsr_reg & 0xFE000000) // move 31...25
|
|
| Rt.uw<2:2> << 24 // bit 24
|
|
| (fcsr_reg & 0x00FFF000) << 23// bit 23...12
|
|
| Rt.uw<11:7> << 7 // bit 24
|
|
| (fcsr_reg & 0x000007E)
|
|
| Rt.uw<1:0>;// bit 22...0
|
|
break;
|
|
|
|
case 31:
|
|
temp = Rt.uw;
|
|
break;
|
|
|
|
default:
|
|
panic("FP Control Value (%d) Not Available. Ignoring Access to"
|
|
"Floating Control Status Register",fcsr_reg);
|
|
}
|
|
|
|
xc->setMiscReg(FCSR,temp);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x1: decode ND {
|
|
0x0: decode TF {
|
|
format Branch {
|
|
0x0: bc1f({{ cond = (getFPConditionCode(CC) == 0); }});
|
|
0x1: bc1t({{ cond = (getFPConditionCode(CC) == 1); }});
|
|
}
|
|
}
|
|
|
|
0x1: decode TF {
|
|
format BranchLikely {
|
|
0x0: bc1fl({{ cond = (getFPConditionCode(CC) == 0); }});
|
|
0x1: bc1tl({{ cond = (getFPConditionCode(CC) == 1); }});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
0x1: decode RS_HI {
|
|
0x2: decode RS_LO {
|
|
|
|
//Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S
|
|
//(( single-word ))
|
|
0x0: decode FUNCTION_HI {
|
|
0x0: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: add_s({{ Fd.sf = Fs.sf + Ft.sf;}});
|
|
0x1: sub_s({{ Fd.sf = Fs.sf - Ft.sf;}});
|
|
0x2: mul_s({{ Fd.sf = Fs.sf * Ft.sf;}});
|
|
0x3: div_s({{ Fd.sf = Fs.sf / Ft.sf;}});
|
|
0x4: sqrt_s({{ Fd.sf = sqrt(Fs.sf);}});
|
|
0x5: abs_s({{ Fd.sf = fabs(Fs.sf);}});
|
|
0x6: mov_s({{ Fd.sf = Fs.sf;}});
|
|
0x7: neg_s({{ Fd.sf = -1 * Fs.sf;}});
|
|
}
|
|
}
|
|
|
|
0x1: decode FUNCTION_LO {
|
|
format Float64Op {
|
|
0x0: round_l_s({{
|
|
Fd.ud = fpConvert(roundFP(Fs.sf), SINGLE_TO_LONG);
|
|
}});
|
|
|
|
0x1: trunc_l_s({{
|
|
Fd.ud = fpConvert(truncFP(Fs.sf), SINGLE_TO_LONG);
|
|
}});
|
|
|
|
0x2: ceil_l_s({{
|
|
Fd.ud = fpConvert(ceil(Fs.sf), SINGLE_TO_LONG);
|
|
}});
|
|
|
|
0x3: floor_l_s({{
|
|
Fd.ud = fpConvert(floor(Fs.sf), SINGLE_TO_LONG);
|
|
}});
|
|
}
|
|
|
|
format FloatOp {
|
|
0x4: round_w_s({{
|
|
Fd.uw = fpConvert(roundFP(Fs.sf), SINGLE_TO_WORD);
|
|
}});
|
|
|
|
0x5: trunc_w_s({{
|
|
Fd.uw = fpConvert(truncFP(Fs.sf), SINGLE_TO_WORD);
|
|
}});
|
|
|
|
0x6: ceil_w_s({{
|
|
Fd.uw = fpConvert(ceil(Fs.sf), SINGLE_TO_WORD);
|
|
}});
|
|
|
|
0x7: floor_w_s({{
|
|
Fd.uw = fpConvert(floor(Fs.sf), SINGLE_TO_WORD);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x2: decode FUNCTION_LO {
|
|
0x1: decode MOVCF {
|
|
format FloatOp {
|
|
0x0: movf_s({{if (getFPConditionCode(CC) == 0) Fd = Fs;}});
|
|
0x1: movt_s({{if (getFPConditionCode(CC) == 1) Fd = Fs;}});
|
|
}
|
|
}
|
|
|
|
format FloatOp {
|
|
0x2: movz_s({{ if (Rt == 0) Fd = Fs; }});
|
|
0x3: movn_s({{ if (Rt != 0) Fd = Fs; }});
|
|
0x5: recip_s({{ Fd = 1 / Fs; }});
|
|
0x6: rsqrt_s({{ Fd = 1 / sqrt(Fs);}});
|
|
}
|
|
}
|
|
|
|
0x4: decode FUNCTION_LO {
|
|
|
|
format FloatConvertOp {
|
|
0x1: cvt_d_s({{
|
|
Fd.ud = fpConvert(Fs.sf, SINGLE_TO_DOUBLE);
|
|
}});
|
|
|
|
0x4: cvt_w_s({{
|
|
Fd.uw = fpConvert(Fs.sf, SINGLE_TO_WORD);
|
|
}});
|
|
}
|
|
|
|
format FloatConvertOp {
|
|
0x5: cvt_l_s({{
|
|
Fd.ud = fpConvert(Fs.sf, SINGLE_TO_LONG);
|
|
}});
|
|
|
|
0x6: cvt_ps_st({{
|
|
Fd.ud = (uint64_t)Fs.uw << 32 | (uint64_t)Ft.uw;
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
format FloatCompareOp {
|
|
0x0: c_f_s({{ cond = 0; }});
|
|
|
|
0x1: c_un_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = 0;
|
|
}});
|
|
|
|
0x2: c_eq_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf == Ft.sf);
|
|
}});
|
|
|
|
0x3: c_ueq_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf == Ft.sf);
|
|
}});
|
|
|
|
0x4: c_olt_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf < Ft.sf);
|
|
}});
|
|
|
|
0x5: c_ult_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf < Ft.sf);
|
|
}});
|
|
|
|
0x6: c_ole_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf <= Ft.sf);
|
|
}});
|
|
|
|
0x7: c_ule_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf <= Ft.sf);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x7: decode FUNCTION_LO {
|
|
format FloatCompareWithXcptOp {
|
|
0x0: c_sf_s({{ cond = 0; }});
|
|
|
|
0x1: c_ngle_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = 0;
|
|
}});
|
|
|
|
0x2: c_seq_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf == Ft.sf);
|
|
}});
|
|
|
|
0x3: c_ngl_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf == Ft.sf);
|
|
}});
|
|
|
|
0x4: c_lt_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf < Ft.sf);
|
|
}});
|
|
|
|
0x5: c_nge_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf < Ft.sf);
|
|
}});
|
|
|
|
0x6: c_le_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.sf <= Ft.sf);
|
|
}});
|
|
|
|
0x7: c_ngt_s({{
|
|
if (unorderedFP(Fs.sf) || unorderedFP(Ft.sf))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.sf <= Ft.sf);
|
|
}});
|
|
}
|
|
}
|
|
}
|
|
|
|
//Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D
|
|
0x1: decode FUNCTION_HI {
|
|
0x0: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: add_d({{ Fd.df = Fs.df + Ft.df;}});
|
|
0x1: sub_d({{ Fd.df = Fs.df - Ft.df;}});
|
|
0x2: mul_d({{ Fd.df = Fs.df * Ft.df;}});
|
|
0x3: div_d({{ Fd.df = Fs.df / Ft.df;}});
|
|
0x4: sqrt_d({{ Fd.df = sqrt(Fs.df);}});
|
|
0x5: abs_d({{ Fd.df = fabs(Fs.df);}});
|
|
0x6: mov_d({{ Fd.ud = Fs.ud;}});
|
|
0x7: neg_d({{ Fd.df = -1 * Fs.df;}});
|
|
}
|
|
}
|
|
|
|
0x1: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: round_l_d({{
|
|
Fd.ud = fpConvert(roundFP(Fs.ud), DOUBLE_TO_LONG);
|
|
}});
|
|
|
|
0x1: trunc_l_d({{
|
|
Fd.ud = fpConvert(truncFP(Fs.ud), DOUBLE_TO_LONG);
|
|
}});
|
|
|
|
0x2: ceil_l_d({{
|
|
Fd.ud = fpConvert(ceil(Fs.ud), DOUBLE_TO_LONG);
|
|
}});
|
|
|
|
0x3: floor_l_d({{
|
|
Fd.ud = fpConvert(floor(Fs.ud), DOUBLE_TO_LONG);
|
|
}});
|
|
}
|
|
|
|
format FloatOp {
|
|
0x4: round_w_d({{
|
|
Fd.uw = fpConvert(roundFP(Fs.ud), DOUBLE_TO_WORD);
|
|
}});
|
|
|
|
0x5: trunc_w_d({{
|
|
Fd.uw = fpConvert(truncFP(Fs.ud), DOUBLE_TO_WORD);
|
|
}});
|
|
|
|
0x6: ceil_w_d({{
|
|
Fd.uw = fpConvert(ceil(Fs.ud), DOUBLE_TO_WORD);
|
|
}});
|
|
|
|
0x7: floor_w_d({{
|
|
Fd.uw = fpConvert(floor(Fs.ud), DOUBLE_TO_WORD);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x2: decode FUNCTION_LO {
|
|
0x1: decode MOVCF {
|
|
format FloatOp {
|
|
0x0: movf_d({{if (getFPConditionCode(CC) == 0) Fd.df = Fs.df; }});
|
|
0x1: movt_d({{if (getFPConditionCode(CC) == 1) Fd.df = Fs.df; }});
|
|
}
|
|
}
|
|
|
|
format BasicOp {
|
|
0x2: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }});
|
|
0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }});
|
|
}
|
|
|
|
format FloatOp {
|
|
0x5: recip_d({{ Fd.df = 1 / Fs.df}});
|
|
0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }});
|
|
}
|
|
}
|
|
|
|
0x4: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: cvt_s_d({{
|
|
Fd.uw = fpConvert(Fs.ud, DOUBLE_TO_SINGLE);
|
|
}});
|
|
|
|
0x4: cvt_w_d({{
|
|
Fd.uw = fpConvert(Fs.ud, DOUBLE_TO_WORD);
|
|
}});
|
|
|
|
0x5: cvt_l_d({{
|
|
Fd.ud = fpConvert(Fs.ud, DOUBLE_TO_LONG);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
format FloatCompareOp {
|
|
0x0: c_f_d({{ cond = 0; }});
|
|
|
|
0x1: c_un_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = 0;
|
|
}});
|
|
|
|
0x2: c_eq_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df == Ft.df);
|
|
}});
|
|
|
|
0x3: c_ueq_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df == Ft.df);
|
|
}});
|
|
|
|
0x4: c_olt_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df < Ft.df);
|
|
}});
|
|
|
|
0x5: c_ult_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df < Ft.df);
|
|
}});
|
|
|
|
0x6: c_ole_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df <= Ft.df);
|
|
}});
|
|
|
|
0x7: c_ule_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df <= Ft.df);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x7: decode FUNCTION_LO {
|
|
format FloatCompareWithXcptOp {
|
|
0x0: c_sf_d({{ cond = 0; }});
|
|
|
|
0x1: c_ngle_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = 0;
|
|
}});
|
|
|
|
0x2: c_seq_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df == Ft.df);
|
|
}});
|
|
|
|
0x3: c_ngl_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df == Ft.df);
|
|
}});
|
|
|
|
0x4: c_lt_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df < Ft.df);
|
|
}});
|
|
|
|
0x5: c_nge_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df < Ft.df);
|
|
}});
|
|
|
|
0x6: c_le_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 0;
|
|
else
|
|
cond = (Fs.df <= Ft.df);
|
|
}});
|
|
|
|
0x7: c_ngt_d({{
|
|
if (unorderedFP(Fs.df) || unorderedFP(Ft.df))
|
|
cond = 1;
|
|
else
|
|
cond = (Fs.df <= Ft.df);
|
|
}});
|
|
}
|
|
}
|
|
}
|
|
|
|
//Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W
|
|
0x4: decode FUNCTION {
|
|
format FloatConvertOp {
|
|
0x20: cvt_s_w({{
|
|
Fd.uw = fpConvert(Fs.sf, WORD_TO_SINGLE);
|
|
}});
|
|
|
|
0x21: cvt_d_w({{
|
|
Fd.ud = fpConvert(Fs.sf, WORD_TO_DOUBLE);
|
|
}});
|
|
}
|
|
|
|
format Float64ConvertOp {
|
|
0x26: cvt_ps_pw({{
|
|
Fd.ud = fpConvert(Fs.ud, WORD_TO_PS);
|
|
}});
|
|
}
|
|
}
|
|
|
|
//Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1
|
|
//Note: "1. Format type L is legal only if 64-bit floating point operations
|
|
//are enabled."
|
|
0x5: decode FUNCTION_HI {
|
|
format Float64ConvertOp {
|
|
0x20: cvt_s_l({{
|
|
Fd.uw = fpConvert(Fs.ud, LONG_TO_SINGLE);
|
|
}});
|
|
|
|
0x21: cvt_d_l({{
|
|
Fd.ud = fpConvert(Fs.ud, LONG_TO_DOUBLE);
|
|
}});
|
|
|
|
0x26: cvt_ps_l({{
|
|
Fd.ud = fpConvert(Fs.ud, LONG_TO_PS);
|
|
}});
|
|
}
|
|
}
|
|
|
|
//Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1
|
|
//Note: "1. Format type PS is legal only if 64-bit floating point operations
|
|
//are enabled. "
|
|
0x6: decode FUNCTION_HI {
|
|
0x0: decode FUNCTION_LO {
|
|
format Float64Op {
|
|
0x0: add_ps({{
|
|
Fd1.sf = Fs1.sf + Ft2.sf;
|
|
Fd2.sf = Fs2.sf + Ft2.sf;
|
|
}});
|
|
|
|
0x1: sub_ps({{
|
|
Fd1.sf = Fs1.sf - Ft2.sf;
|
|
Fd2.sf = Fs2.sf - Ft2.sf;
|
|
}});
|
|
|
|
0x2: mul_ps({{
|
|
Fd1.sf = Fs1.sf * Ft2.sf;
|
|
Fd2.sf = Fs2.sf * Ft2.sf;
|
|
}});
|
|
|
|
0x5: abs_ps({{
|
|
Fd1.sf = fabs(Fs1.sf);
|
|
Fd2.sf = fabs(Fs2.sf);
|
|
}});
|
|
|
|
0x6: mov_ps({{
|
|
Fd1.sf = Fs1.sf;
|
|
Fd2.sf = Fs2.sf;
|
|
}});
|
|
|
|
0x7: neg_ps({{
|
|
Fd1.sf = -1 * Fs1.sf;
|
|
Fd2.sf = -1 * Fs2.sf;
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x2: decode FUNCTION_LO {
|
|
0x1: decode MOVCF {
|
|
format Float64Op {
|
|
0x0: movf_ps({{
|
|
if (getFPConditionCode(CC) == 0)
|
|
Fd1 = Fs1;
|
|
if (getFPConditionCode(CC+1) == 0)
|
|
Fd2 = Fs2;
|
|
}});
|
|
|
|
0x1: movt_ps({{
|
|
if (getFPConditionCode(CC) == 1)
|
|
Fd1 = Fs1;
|
|
if (getFPConditionCode(CC+1) == 1)
|
|
Fd2 = Fs2;
|
|
}});
|
|
}
|
|
}
|
|
|
|
format Float64Op {
|
|
0x2: movz_ps({{
|
|
if (getFPConditionCode(CC) == 0)
|
|
Fd1 = Fs1;
|
|
if (getFPConditionCode(CC) == 0)
|
|
Fd2 = Fs2;
|
|
}});
|
|
|
|
0x3: movn_ps({{
|
|
if (getFPConditionCode(CC) == 1)
|
|
Fd1 = Fs1;
|
|
if (getFPConditionCode(CC) == 1)
|
|
Fd2 = Fs2;
|
|
}});
|
|
}
|
|
|
|
}
|
|
|
|
0x4: decode FUNCTION_LO {
|
|
0x0: Float64Op::cvt_s_pu({{
|
|
Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE);
|
|
}});
|
|
}
|
|
|
|
0x5: decode FUNCTION_LO {
|
|
format Float64Op {
|
|
0x0: cvt_s_pl({{
|
|
Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE);
|
|
}});
|
|
|
|
0x4: pll({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<31:0>; }});
|
|
0x5: plu({{ Fd.ud = Fs.ud<31:0> << 32 | Ft.ud<63:32>;}});
|
|
0x6: pul({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<31:0>; }});
|
|
0x7: puu({{ Fd.ud = Fs.ud<63:32> << 32 | Ft.ud<63:32>;}});
|
|
}
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: c_f_ps({{ ; }});
|
|
0x1: c_un_ps({{ ; }});
|
|
0x2: c_eq_ps({{ ; }});
|
|
0x3: c_ueq_ps({{ ; }});
|
|
0x4: c_olt_ps({{ ; }});
|
|
0x5: c_ult_ps({{ ; }});
|
|
0x6: c_ole_ps({{ ; }});
|
|
0x7: c_ule_ps({{ ; }});
|
|
}
|
|
}
|
|
|
|
0x7: decode FUNCTION_LO {
|
|
format FloatOp {
|
|
0x0: c_sf_ps({{ ; }});
|
|
0x1: c_ngle_ps({{ ; }});
|
|
0x2: c_seq_ps({{ ; }});
|
|
0x3: c_ngl_ps({{ ; }});
|
|
0x4: c_lt_ps({{ ; }});
|
|
0x5: c_nge_ps({{ ; }});
|
|
0x6: c_le_ps({{ ; }});
|
|
0x7: c_ngt_ps({{ ; }});
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Table A-19 MIPS32 COP2 Encoding of rs Field
|
|
0x2: decode RS_MSB {
|
|
0x0: decode RS_HI {
|
|
0x0: decode RS_LO {
|
|
format WarnUnimpl {
|
|
0x0: mfc2();
|
|
0x2: cfc2();
|
|
0x3: mfhc2();
|
|
0x4: mtc2();
|
|
0x6: ctc2();
|
|
0x7: mftc2();
|
|
}
|
|
}
|
|
|
|
0x1: decode ND {
|
|
0x0: decode TF {
|
|
format WarnUnimpl {
|
|
0x0: bc2f();
|
|
0x1: bc2t();
|
|
}
|
|
}
|
|
|
|
0x1: decode TF {
|
|
format WarnUnimpl {
|
|
0x0: bc2fl();
|
|
0x1: bc2tl();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Table A-20 MIPS64 COP1X Encoding of Function Field 1
|
|
//Note: "COP1X instructions are legal only if 64-bit floating point
|
|
//operations are enabled."
|
|
0x3: decode FUNCTION_HI {
|
|
0x0: decode FUNCTION_LO {
|
|
format LoadFloatMemory {
|
|
0x0: lwxc1({{ Ft.uw = Mem.uw;}}, {{ EA = Rs + Rt; }});
|
|
0x1: ldxc1({{ Ft.ud = Mem.ud;}}, {{ EA = Rs + Rt; }});
|
|
0x5: luxc1({{ Ft.uw = Mem.ud;}}, {{ EA = Rs + Rt; }});
|
|
}
|
|
}
|
|
|
|
0x1: decode FUNCTION_LO {
|
|
format StoreFloatMemory {
|
|
0x0: swxc1({{ Mem.uw = Ft.uw;}}, {{ EA = Rs + Rt; }});
|
|
0x1: sdxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }});
|
|
0x5: suxc1({{ Mem.ud = Ft.ud;}}, {{ EA = Rs + Rt; }});
|
|
}
|
|
|
|
0x7: WarnUnimpl::prefx();
|
|
}
|
|
|
|
format FloatOp {
|
|
0x3: WarnUnimpl::alnv_ps();
|
|
|
|
format BasicOp {
|
|
0x4: decode FUNCTION_LO {
|
|
0x0: madd_s({{ Fd.sf = (Fs.sf * Ft.sf) + Fr.sf; }});
|
|
0x1: madd_d({{ Fd.df = (Fs.df * Ft.df) + Fr.df; }});
|
|
0x6: madd_ps({{
|
|
Fd1.sf = (Fs1.df * Ft1.df) + Fr1.df;
|
|
Fd2.sf = (Fs2.df * Ft2.df) + Fr2.df;
|
|
}});
|
|
}
|
|
|
|
0x5: decode FUNCTION_LO {
|
|
0x0: msub_s({{ Fd.sf = (Fs.sf * Ft.sf) - Fr.sf; }});
|
|
0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }});
|
|
0x6: msub_ps({{
|
|
Fd1.sf = (Fs1.df * Ft1.df) - Fr1.df;
|
|
Fd2.sf = (Fs2.df * Ft2.df) - Fr2.df;
|
|
}});
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }});
|
|
0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }});
|
|
0x6: nmadd_ps({{
|
|
Fd1.sf = -1 * ((Fs1.df * Ft1.df) + Fr1.df);
|
|
Fd2.sf = -1 * ((Fs2.df * Ft2.df) + Fr2.df);
|
|
}});
|
|
}
|
|
|
|
0x7: decode FUNCTION_LO {
|
|
0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Ft.sf) - Fr.sf; }});
|
|
0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }});
|
|
0x6: nmsub_ps({{
|
|
0x6: msub_ps({{
|
|
Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df);
|
|
Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df);
|
|
}});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
format BranchLikely {
|
|
0x4: beql({{ cond = (Rs.sw == 0); }});
|
|
0x5: bnel({{ cond = (Rs.sw != 0); }});
|
|
0x6: blezl({{ cond = (Rs.sw <= 0); }});
|
|
0x7: bgtzl({{ cond = (Rs.sw > 0); }});
|
|
}
|
|
}
|
|
|
|
0x3: decode OPCODE_LO default FailUnimpl::reserved() {
|
|
|
|
//Table A-5 MIPS32 SPECIAL2 Encoding of Function Field
|
|
0x4: decode FUNCTION_HI {
|
|
|
|
0x0: decode FUNCTION_LO {
|
|
format IntOp {
|
|
0x0: madd({{
|
|
int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
|
|
temp1 = temp1 + (Rs.sw * Rt.sw);
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
|
|
0x1: maddu({{
|
|
int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
|
|
temp1 = temp1 + (Rs.uw * Rt.uw);
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
|
|
0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }});
|
|
|
|
0x4: msub({{
|
|
int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
|
|
temp1 = temp1 - (Rs.sw * Rt.sw);
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
|
|
0x5: msubu({{
|
|
int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
|
|
temp1 = temp1 - (Rs.uw * Rt.uw);
|
|
xc->setMiscReg(Hi,temp1<63:32>);
|
|
xc->setMiscReg(Lo,temp1<31:0>);
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x4: decode FUNCTION_LO {
|
|
format BasicOp {
|
|
0x0: clz({{
|
|
int cnt = 0;
|
|
uint32_t mask = 0x80000000;
|
|
for (int i=0; i < 32; i++) {
|
|
if( (Rs & mask) == 0) {
|
|
cnt++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
Rd.uw = cnt;
|
|
}});
|
|
|
|
0x1: clo({{
|
|
int cnt = 0;
|
|
uint32_t mask = 0x80000000;
|
|
for (int i=0; i < 32; i++) {
|
|
if( (Rs & mask) != 0) {
|
|
cnt++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
Rd.uw = cnt;
|
|
}});
|
|
}
|
|
}
|
|
|
|
0x7: decode FUNCTION_LO {
|
|
0x7: WarnUnimpl::sdbbp();
|
|
}
|
|
}
|
|
|
|
//Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture
|
|
0x7: decode FUNCTION_HI {
|
|
|
|
0x0: decode FUNCTION_LO {
|
|
format FailUnimpl {
|
|
0x1: ext();
|
|
0x4: ins();
|
|
}
|
|
}
|
|
|
|
0x1: decode FUNCTION_LO {
|
|
format FailUnimpl {
|
|
0x0: fork();
|
|
0x1: yield();
|
|
}
|
|
}
|
|
|
|
|
|
//Table A-10 MIPS32 BSHFL Encoding of sa Field
|
|
0x4: decode SA {
|
|
|
|
0x02: FailUnimpl::wsbh();
|
|
|
|
format BasicOp {
|
|
0x10: seb({{ Rd.sw = Rt<7:0>}});
|
|
0x18: seh({{ Rd.sw = Rt<15:0>}});
|
|
}
|
|
}
|
|
|
|
0x6: decode FUNCTION_LO {
|
|
0x7: FailUnimpl::rdhwr();//{{ /*Rt = xc->hwRegs[RD];*/ }}
|
|
}
|
|
}
|
|
}
|
|
|
|
0x4: decode OPCODE_LO default FailUnimpl::reserved() {
|
|
format LoadMemory {
|
|
0x0: lb({{ Rt.sw = Mem.sb; }});
|
|
0x1: lh({{ Rt.sw = Mem.sh; }});
|
|
|
|
0x2: lwl({{
|
|
uint32_t mem_word = Mem.uw;
|
|
uint32_t unalign_addr = Rs + disp;
|
|
uint32_t offset = unalign_addr & 0x00000003;
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
Rt = mem_word;
|
|
break;
|
|
|
|
case 1:
|
|
Rt &= 0x000F;
|
|
Rt |= (mem_word << 4);
|
|
break;
|
|
|
|
case 2:
|
|
Rt &= 0x00FF;
|
|
Rt |= (mem_word << 8);
|
|
break;
|
|
|
|
case 3:
|
|
Rt &= 0x0FFF;
|
|
Rt |= (mem_word << 12);
|
|
break;
|
|
|
|
default:
|
|
panic("lwl: bad offset");
|
|
}
|
|
#elif BYTE_ORDER == LITTLE_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
Rt &= 0x0FFF;
|
|
Rt |= (mem_word << 12);
|
|
break;
|
|
|
|
case 1:
|
|
Rt &= 0x00FF;
|
|
Rt |= (mem_word << 8);
|
|
break;
|
|
|
|
case 2:
|
|
Rt &= 0x000F;
|
|
Rt |= (mem_word << 4);
|
|
break;
|
|
|
|
case 3:
|
|
Rt = mem_word;
|
|
break;
|
|
|
|
default:
|
|
panic("lwl: bad offset");
|
|
}
|
|
#endif
|
|
}}, {{ EA = (Rs + disp) & ~3; }});
|
|
|
|
0x3: lw({{ Rt.sw = Mem.sw; }});
|
|
0x4: lbu({{ Rt.uw = Mem.ub; }});
|
|
0x5: lhu({{ Rt.uw = Mem.uh; }});
|
|
0x6: lwr({{
|
|
uint32_t mem_word = Mem.uw;
|
|
uint32_t unalign_addr = Rs + disp;
|
|
uint32_t offset = unalign_addr & 0x00000003;
|
|
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break;
|
|
case 1: Rt &= 0xFF00; Rt |= (mem_word >> 8); break;
|
|
case 2: Rt &= 0xF000; Rt |= (mem_word >> 4); break;
|
|
case 3: Rt = mem_word; break;
|
|
default: panic("lwr: bad offset");
|
|
}
|
|
#elif BYTE_ORDER == LITTLE_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0: Rt = mem_word; break;
|
|
case 1: Rt &= 0xF000; Rt |= (mem_word >> 4); break;
|
|
case 2: Rt &= 0xFF00; Rt |= (mem_word >> 8); break;
|
|
case 3: Rt &= 0xFFF0; Rt |= (mem_word >> 12); break;
|
|
default: panic("lwr: bad offset");
|
|
}
|
|
#endif
|
|
}},
|
|
{{ EA = (Rs + disp) & ~3; }});
|
|
}
|
|
|
|
0x7: FailUnimpl::reserved();
|
|
}
|
|
|
|
0x5: decode OPCODE_LO default FailUnimpl::reserved() {
|
|
format StoreMemory {
|
|
0x0: sb({{ Mem.ub = Rt<7:0>; }});
|
|
0x1: sh({{ Mem.uh = Rt<15:0>; }});
|
|
0x2: swl({{
|
|
uint32_t mem_word = 0;
|
|
uint32_t aligned_addr = (Rs + disp) & ~3;
|
|
uint32_t unalign_addr = Rs + disp;
|
|
uint32_t offset = unalign_addr & 0x00000003;
|
|
|
|
DPRINTF(IEW,"Execute: aligned=0x%x unaligned=0x%x\n offset=0x%x",
|
|
aligned_addr,unalign_addr,offset);
|
|
|
|
fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags);
|
|
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
Mem = Rt;
|
|
break;
|
|
|
|
case 1:
|
|
mem_word &= 0xF000;
|
|
mem_word |= (Rt >> 4);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 2:
|
|
mem_word &= 0xFF00;
|
|
mem_word |= (Rt >> 8);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 3:
|
|
mem_word &= 0xFFF0;
|
|
mem_word |= (Rt >> 12);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
default:
|
|
panic("swl: bad offset");
|
|
}
|
|
#elif BYTE_ORDER == LITTLE_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
mem_word &= 0xFFF0;
|
|
mem_word |= (Rt >> 12);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 1:
|
|
mem_word &= 0xFF00;
|
|
mem_word |= (Rt >> 8);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 2:
|
|
mem_word &= 0xF000;
|
|
mem_word |= (Rt >> 4);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 3:
|
|
Mem = Rt;
|
|
break;
|
|
|
|
default:
|
|
panic("swl: bad offset");
|
|
}
|
|
#endif
|
|
}},{{ EA = (Rs + disp) & ~3; }},mem_flags = NO_ALIGN_FAULT);
|
|
|
|
0x3: sw({{ Mem.uw = Rt<31:0>; }});
|
|
|
|
0x6: swr({{
|
|
uint32_t mem_word = 0;
|
|
uint32_t aligned_addr = (Rs + disp) & ~3;
|
|
uint32_t unalign_addr = Rs + disp;
|
|
uint32_t offset = unalign_addr & 0x00000003;
|
|
|
|
fault = xc->read(aligned_addr, (uint32_t&)mem_word, memAccessFlags);
|
|
|
|
#if BYTE_ORDER == BIG_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
mem_word &= 0x0FFF;
|
|
mem_word |= (Rt << 12);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 1:
|
|
mem_word &= 0x00FF;
|
|
mem_word |= (Rt << 8);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 2:
|
|
mem_word &= 0x000F;
|
|
mem_word |= (Rt << 4);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 3:
|
|
Mem = Rt;
|
|
break;
|
|
|
|
default:
|
|
panic("swr: bad offset");
|
|
}
|
|
#elif BYTE_ORDER == LITTLE_ENDIAN
|
|
switch(offset)
|
|
{
|
|
case 0:
|
|
Mem = Rt;
|
|
break;
|
|
|
|
case 1:
|
|
mem_word &= 0x000F;
|
|
mem_word |= (Rt << 4);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 2:
|
|
mem_word &= 0x00FF;
|
|
mem_word |= (Rt << 8);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
case 3:
|
|
mem_word &= 0x0FFF;
|
|
mem_word |= (Rt << 12);
|
|
Mem = mem_word;
|
|
break;
|
|
|
|
default:
|
|
panic("swr: bad offset");
|
|
}
|
|
#endif
|
|
}},{{ EA = (Rs + disp) & ~3;}},mem_flags = NO_ALIGN_FAULT);
|
|
}
|
|
|
|
format WarnUnimpl {
|
|
0x7: cache();
|
|
}
|
|
|
|
}
|
|
|
|
0x6: decode OPCODE_LO default FailUnimpl::reserved() {
|
|
0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED);
|
|
|
|
format LoadFloatMemory {
|
|
0x1: lwc1({{ Ft.uw = Mem.uw; }});
|
|
0x5: ldc1({{ Ft.ud = Mem.ud; }});
|
|
}
|
|
}
|
|
|
|
|
|
0x7: decode OPCODE_LO default FailUnimpl::reserved() {
|
|
0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }});
|
|
|
|
format StoreFloatMemory {
|
|
0x1: swc1({{ Mem.uw = Ft.uw; }});
|
|
0x5: sdc1({{ Mem.ud = Ft.ud; }});
|
|
}
|
|
}
|
|
}
|
|
|
|
|