diff options
Diffstat (limited to 'arch/mips/isa')
-rw-r--r-- | arch/mips/isa/base.isa | 63 | ||||
-rw-r--r-- | arch/mips/isa/bitfields.isa | 4 | ||||
-rw-r--r-- | arch/mips/isa/decoder.isa | 1221 | ||||
-rw-r--r-- | arch/mips/isa/formats.isa | 27 | ||||
-rw-r--r-- | arch/mips/isa/formats/basic.isa | 5 | ||||
-rw-r--r-- | arch/mips/isa/formats/branch.isa | 333 | ||||
-rw-r--r-- | arch/mips/isa/formats/fp.isa | 27 | ||||
-rw-r--r-- | arch/mips/isa/formats/int.isa | 21 | ||||
-rw-r--r-- | arch/mips/isa/formats/mem.isa | 508 | ||||
-rw-r--r-- | arch/mips/isa/formats/noop.isa | 103 | ||||
-rw-r--r-- | arch/mips/isa/formats/unimp.isa | 165 | ||||
-rw-r--r-- | arch/mips/isa/formats/unknown.isa | 52 | ||||
-rw-r--r-- | arch/mips/isa/formats/util.isa | 125 | ||||
-rw-r--r-- | arch/mips/isa/main.isa | 12 | ||||
-rw-r--r-- | arch/mips/isa/operands.isa | 15 |
15 files changed, 1909 insertions, 772 deletions
diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa new file mode 100644 index 000000000..846d161b9 --- /dev/null +++ b/arch/mips/isa/base.isa @@ -0,0 +1,63 @@ +// -*- mode:c++ -*- + +//////////////////////////////////////////////////////////////////// +// +// Base class for MIPS instructions, and some support functions +// + +//Outputs to decoder.hh +output header {{ + /** + * Base class for all MIPS static instructions. + */ + class MipsStaticInst : public StaticInst<MIPSISA> + { + protected: + + // Constructor. + MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass) + : StaticInst<MIPSISA>(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + +}}; + +//Ouputs to decoder.cc +output decoder {{ + + std::string MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // just print the first two source regs... if there's + // a third one, it's a read-modify-write dest (Rc), + // e.g. for CMOVxx + if(_numSrcRegs > 0) + { + printReg(ss, _srcRegIdx[0]); + } + if(_numSrcRegs > 1) + { + ss << ","; + printReg(ss, _srcRegIdx[1]); + } + + // just print the first dest... if there's a second one, + // it's generally implicit + if(_numDestRegs > 0) + { + if(_numSrcRegs > 0) + ss << ","; + printReg(ss, _destRegIdx[0]); + } + + return ss.str(); + } + +}}; + diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa index bead9c151..532b3793a 100644 --- a/arch/mips/isa/bitfields.isa +++ b/arch/mips/isa/bitfields.isa @@ -1,3 +1,5 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // Bitfield definitions. @@ -41,7 +43,7 @@ def bitfield SC < 5: 5>; // Branch format def bitfield OFFSET <15: 0>; // displacement -// Memory-format jumps +// Jmp format def bitfield JMPTARG <25: 0>; def bitfield JMPHINT <10: 6>; diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa index 2ec7da805..7dd08ac49 100644 --- a/arch/mips/isa/decoder.isa +++ b/arch/mips/isa/decoder.isa @@ -1,3 +1,5 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // The actual MIPS32 ISA decoder @@ -9,193 +11,207 @@ // //@todo: Distinguish "unknown/future" use insts from "reserved" // ones -decode OPCODE_HI default FailUnimpl::unknown() { +decode OPCODE_HI default Unknown::unknown() { // Derived From ... Table A-2 MIPS32 ISA Manual - 0x0: decode OPCODE_LO default FailUnimpl::reserved(){ + 0x0: decode OPCODE_LO { 0x0: decode FUNCTION_HI { 0x0: decode FUNCTION_LO { - 0x1: decode MOVCI { - format BasicOp { - 0: movf({{ if( xc->miscRegs.fpcr == 0) Rd = Rs}}); - 1: movt({{ if( xc->miscRegs.fpcr == 1) Rd = Rs}}); + 0x1: decode MOVCI { + format BasicOp { + 0: movf({{ if( xc->miscRegs.fpcr == 0) Rd = Rs}}); + 1: movt({{ if( xc->miscRegs.fpcr == 1) Rd = Rs}}); + } } - } - format BasicOp { + 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." + //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: sll({{ Rd = Rt.uw << SA; }}); + 0x0: sll({{ Rd = Rt.uw << SA; }}); - 0x2: decode SRL { - 0: srl({{ Rd = Rt.uw >> SA; }}); + 0x2: 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);}}); - } + //Hardcoded assuming 32-bit ISA, probably need parameter here + 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}}); + } - 0x3: sra({{ Rd = Rt.sw >> SA; }}); + 0x3: sra({{ Rd = Rt.sw >> SA; }}); - 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); + 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }}); - 0x6: decode SRLV { - 0: srlv({{ 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>);}}); - } + //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({{ Rd = Rt.sw >> Rs<4:0>; }}); - } + 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }}); + } } 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: jr(IsReturn); - 0x1: jalr(IsCall,IsReturn); - } - - format BasicOp { - 0x2: movz({{ if (Rt == 0) Rd = Rs; }}); - 0x3: movn({{ if (Rt != 0) Rd = Rs; }}); - } - - format WarnUnimpl { - 0x4: syscall({{ xc->syscall()}},IsNonSpeculative); - 0x5: break({{ }}); - 0x7: sync({{ }}); - } + //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; }},IsReturn); + + 1:jr_hb({{ NNPC = Rs; clear_exe_inst_hazards(); }},IsReturn); + } + + 0x1: decode HINT { + 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn); + + 1: jalr_hb({{ 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 WarnUnimpl { + 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative + 0x5: break(); + 0x7: sync(); + } } 0x2: decode FUNCTION_LO { - format BasicOp { - 0x0: mfhi({{ Rd = xc->miscRegs.hi; }}); - 0x1: mthi({{ xc->miscRegs.hi = Rs; }}); - 0x2: mflo({{ Rd = xc->miscRegs.lo; }}); - 0x3: mtlo({{ xc->miscRegs.lo = Rs; }}); - } - }; + format BasicOp { + 0x0: mfhi({{ Rd = xc->miscRegs.hi; }}); + 0x1: mthi({{ xc->miscRegs.hi = Rs; }}); + 0x2: mflo({{ Rd = xc->miscRegs.lo; }}); + 0x3: mtlo({{ xc->miscRegs.lo = Rs; }}); + } + } 0x3: decode FUNCTION_LO { - format IntOp { - 0x0: mult({{ + format IntOp { + 0x0: mult({{ INT64 temp1 = Rs.sw * Rt.sw; xc->miscRegs.hi->temp1<63:32>; - xc->miscRegs.lo->temp1<31:0> - }}); + xc->miscRegs.lo->temp1<31:0>; + }}); - 0x1: multu({{ + 0x1: multu({{ INT64 temp1 = Rs.uw * Rt.uw; xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - Rd.sw = Rs.uw * Rt.uw; - }}); + Rd.sw = Rs.uw * Rt.uw; + }}); - 0x2: div({{ + 0x2: div({{ xc->miscRegs.hi = Rs.sw % Rt.sw; xc->miscRegs.lo = Rs.sw / Rt.sw; - }}); + }}); - 0x3: divu({{ + 0x3: divu({{ xc->miscRegs.hi = Rs.uw % Rt.uw; xc->miscRegs.lo = Rs.uw / Rt.uw; - }}); - } - }; + }}); + } + } 0x4: decode FUNCTION_LO { - format IntOp { - 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;}}); - 0x1: addu({{ Rd.uw = Rs.uw + Rt.uw;}}); - 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw;}}); - 0x3: subu({{ Rd.uw = Rs.uw - Rt.uw;}}); - 0x4: and({{ Rd.sw = Rs.uw & Rt.uw;}}); - 0x5: or({{ Rd.sw = Rs.uw | Rt.uw;}}); - 0x6: xor({{ Rd.sw = Rs.uw ^ Rt.uw;}}); - 0x7: nor({{ Rd.sw = ~(Rs.uw | Rt.uw);}}); - } + format IntOp { + 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;}}); + 0x1: addu({{ Rd.uw = Rs.uw + Rt.uw;}}); + 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw;}}); + 0x3: subu({{ Rd.uw = Rs.uw - Rt.uw;}}); + 0x4: and({{ Rd.sw = Rs.uw & Rt.uw;}}); + 0x5: or({{ Rd.sw = Rs.uw | Rt.uw;}}); + 0x6: xor({{ Rd.sw = Rs.uw ^ Rt.uw;}}); + 0x7: nor({{ Rd.sw = ~(Rs.uw | Rt.uw);}}); + } } 0x5: 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}}); - } - }; + 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); }}); - } + 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.sq < 0); }}); - 0x1: bgez({{ cond = (Rs.sq >= 0); }}); - - //MIPS obsolete instructions - 0x2: bltzl({{ cond = (Rs.sq < 0); }}); - 0x3: bgezl({{ cond = (Rs.sq >= 0); }}); - } + format Branch { + 0x0: bltz({{ cond = (Rs.sw < 0); }}); + 0x1: bgez({{ cond = (Rs.sw >= 0); }}); + } + + format BranchLikely { + //MIPS obsolete instructions + 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); }}); - } + 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.sq < 0); }}); - 0x1: bgezal({{ cond = (Rs.sq >= 0); }}); - - //MIPS obsolete instructions - 0x2: bltzall({{ cond = (Rs.sq < 0); }}); - 0x3: bgezall({{ cond = (Rs.sq >= 0); }}); - } + format Branch { + 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsLink); + 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsLink); + } + + format BranchLikely { + //Will be removed in future MIPS releases + 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsLink); + 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsLink); + } } 0x3: decode REGIMM_LO { - format WarnUnimpl { - 0x7: synci({{ }}); - } + format WarnUnimpl { + 0x7: synci(); + } } } format Jump { - 0x2: j(); - 0x3: jal(IsCall); + 0x2: j({{ NNPC = (NPC & 0xF0000000) & (0x00000000 & JMPTARG << 2);}}); + + 0x3: jal({{ NNPC = (NPC & 0xF0000000) & (0x00000000 & JMPTARG << 2);}},IsCall,IsReturn); } format Branch { - 0x4: beq({{ cond = (Rs.sq == 0); }}); - 0x5: bne({{ cond = (Rs.sq != 0); }}); - 0x6: blez({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtz({{ cond = (Rs.sq > 0); }}); + 0x4: beq({{ cond = (Rs.sw == 0); }}); + 0x5: bne({{ cond = (Rs.sw != 0); }}); + 0x6: blez({{ cond = (Rs.sw <= 0); }}); + 0x7: bgtz({{ cond = (Rs.sw > 0); }}); } - }; + } - 0x1: decode OPCODE_LO default FailUnimpl::reserved(){ + 0x1: decode OPCODE_LO { format IntOp { 0x0: addi({{ Rt.sw = Rs.sw + INTIMM; }}); 0x1: addiu({{ Rt.uw = Rs.uw + INTIMM;}}); @@ -205,540 +221,539 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}}); 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}}); 0x7: lui({{ Rt = INTIMM << 16}}); - }; - }; - - 0x2: decode OPCODE_LO default FailUnimpl::reserved(){ + } + } - //Table A-11 MIPS32 COP0 Encoding of rs Field - 0x0: decode RS_MSB { - 0x0: decode RS { + 0x2: decode OPCODE_LO { - format BasicOp { - 0x0: mfc0({{ + //Table A-11 MIPS32 COP0 Encoding of rs Field + 0x0: decode RS_MSB { + 0x0: decode RS { + format BasicOp { + 0x0: mfc0({{ //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. if (SEL > 0) - panic("Can't Handle Cop0 with register select yet\n"); + panic("Can't Handle Cop0 with register select yet\n"); uint64_t reg_num = Rd.uw; Rt = xc->miscRegs.cop0[reg_num]; - }}); + }}); - 0x4: mtc0({{ + 0x4: mtc0({{ //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. if (SEL > 0) - panic("Can't Handle Cop0 with register select yet\n"); + panic("Can't Handle Cop0 with register select yet\n"); uint64_t reg_num = Rd.uw; xc->miscRegs.cop0[reg_num] = Rt; - }}); + }}); - 0x8: mftr({{ + 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({{ + 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({{ + 0xA: rdpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; uint64_t reg_num = Rt.uw; Rd = xc->shadowIntRegFile[prev][reg_num]; - }}); - } + }}); - 0xB: decode RD { + 0xB: decode RD { - 0x0: decode SC { - format BasicOp { - 0x0: dvpe({{ - Rt.sw = xc->miscRegs.cop0.MVPControl; - xc->miscRegs.cop0.MVPControl[EVP] = 0; - }}); + 0x0: decode SC { + 0x0: dvpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 0; + }}); - 0x1: evpe({{ - Rt.sw = xc->miscRegs.cop0.MVPControl; - xc->miscRegs.cop0.MVPControl[EVP] = 1; - }}); - } - } + 0x1: evpe({{ + Rt.sw = xc->miscRegs.cop0.MVPControl; + xc->miscRegs.cop0.MVPControl[EVP] = 1; + }}); + } - 0x1: decode SC { - format BasicOp { - 0x0: dmt({{ - Rt.sw = xc->miscRegs.cop0.VPEControl; - xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 0; - }}); + 0x1: decode SC { + 0x0: dmt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 0; + }}); - 0x1: emt({{ - Rt.sw = xc->miscRegs.cop0.VPEControl; - xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 1; - }}); - } - } + 0x1: emt({{ + Rt.sw = xc->miscRegs.cop0.VPEControl; + xc->miscRegs.cop0.VPEControl[THREAD_ENABLE] = 1; + }}); + } - 0xC: decode SC { - format BasicOp { - 0x0: di({{ - Rt.sw = xc->miscRegs.cop0.Status; - xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 0; - }}); + 0xC: decode SC { + 0x0: di({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 0; + }}); - 0x1: ei({{ - Rt.sw = xc->miscRegs.cop0.Status; - xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 1; - }}); - } - } - } + 0x1: ei({{ + Rt.sw = xc->miscRegs.cop0.Status; + xc->miscRegs.cop0.Status[INTERRUPT_ENABLE] = 1; + }}); + } + } - 0xE: BasicOp::wrpgpr({{ + 0xE: wrpgpr({{ //Accessing Previous Shadow Set Register Number uint64_t prev = xc->miscRegs.cop0[SRSCtl][PSS]; uint64_t reg_num = Rd.uw; xc->shadowIntRegFile[prev][reg_num] = Rt; - }}); - } - - //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO - 0x1: decode FUNCTION { - format Trap { - 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 = Fs<31:0>; }}); - 0x2: cfc1({{ Rt = xc->miscRegs.fpcr[Fs];}}); - 0x3: mfhc1({{ Rt = Fs<63:32>;}}); - 0x4: mtc1({{ Fs<31:0> = Rt}}); - 0x6: ctc1({{ xc->miscRegs.fpcr[Fs] = Rt;}}); - 0x7: mftc1({{ Fs<63:32> = Rt}}); - } - } - - 0x1: decode ND { - 0x0: decode TF { - format Branch { - 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }}); - 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }}); - } + }}); + } } - 0x1: decode TF { - format Branch { - 0x0: bc1fl({{ cond = (xc->miscRegs.fpcr == 0); }}); - 0x1: bc1tl({{ cond = (xc->miscRegs.fpcr == 1); }}); - } + //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO + 0x1: decode FUNCTION { + format Trap { + 0x01: tlbr({{ }}); + 0x02: tlbwi({{ }}); + 0x06: tlbwr({{ }}); + 0x08: tlbp({{ }}); + } + + format WarnUnimpl { + 0x18: eret(); + 0x1F: deret(); + 0x20: wait(); + } } - } } - 0x1: decode RS_HI { - 0x2: decode RS_LO { + //Table A-13 MIPS32 COP1 Encoding of rs Field + 0x1: decode RS_MSB { - //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S - //(( single-word )) 0x0: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp { - 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); - 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); - 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); - 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); - 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); - 0x5: abss({{ Fd.sf = abs(Fs.sf);}}); - 0x6: movs({{ Fd.sf = Fs.sf;}}); - 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); - } - } - - 0x1: decode RS_LO { - //only legal for 64 bit - format Float64Op { - 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); - 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); - 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); - 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); - } - - format FloatOp { - 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); - 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); - 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); - 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); - } - } - - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp { - 0x0: movfs({{ if ( FPConditionCode(CC) == 0 ) Fd = Fs; }}); - 0x1: movts({{ if ( FPConditionCode(CC) == 1 ) Fd = Fs;}}); - } + 0x0: decode RS_LO { + format FloatOp { + 0x0: mfc1({{ Rt = Fs<31:0>; }}); + 0x2: cfc1({{ Rt = xc->miscRegs.fpcr[Fs];}}); + 0x3: mfhc1({{ Rt = Fs<63:32>;}}); + 0x4: mtc1({{ Fs<31:0> = Rt}}); + 0x6: ctc1({{ xc->miscRegs.fpcr[Fs] = Rt;}}); + 0x7: mftc1({{ Fs<63:32> = Rt}}); + } } - format BasicOp { - 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); - 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); - } + 0x1: decode ND { + 0x0: decode TF { + format Branch { + 0x0: bc1f({{ cond = (xc->miscRegs.fpcr == 0); }}); + 0x1: bc1t({{ cond = (xc->miscRegs.fpcr == 1); }}); + } + } - format Float64Op { - 0x2: recips({{ Fd = 1 / Fs; }}); - 0x3: rsqrts{{ Fd = 1 / sqrt(Fs); }}); + 0x1: decode TF { + format BranchLikely { + 0x0: bc1fl({{ cond = (xc->miscRegs.fpcr == 0); }}); + 0x1: bc1tl({{ cond = (xc->miscRegs.fpcr == 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 RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}}); + 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}}); + 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}}); + 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}}); + 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}}); + 0x5: abss({{ Fd.sf = abs(Fs.sf);}}); + 0x6: movs({{ Fd.sf = Fs.sf;}}); + 0x7: negs({{ Fd.sf = -1 * Fs.sf;}}); + } + } - 0x4: decode RS_LO { - 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; + 0x1: decode RS_LO { + //only legal for 64 bit-FP + format Float64Op { + 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}}); + 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}}); + 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}}); + 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}}); + } + + format FloatOp { + 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}}); + 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}}); + 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}}); + 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}}); + } + } + + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfs({{ if ( FPConditionCode(CC) == 0 ) Fd = Fs; }}); + 0x1: movts({{ if ( FPConditionCode(CC) == 1 ) Fd = Fs;}}); + } + } + + format BasicOp { + 0x2: movzs({{ if (Rt == 0) Fd = Fs; }}); + 0x3: movns({{ if (Rt != 0) Fd = Fs; }}); + } + + format Float64Op { + 0x2: recips({{ Fd = 1 / Fs; }}); + 0x3: rsqrts({{ Fd = 1 / sqrt(Fs.ud);}}); + } + } + + 0x4: decode RS_LO { + + format FloatOp { + 0x1: cvt_d_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE); - }}); + }}); - 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; + 0x4: cvt_w_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE); - }}); + }}); + } - //only legal for 64 bit - format Float64Op { - 0x5: cvt_l_s({{ int rnd_mode = xc->miscRegs.fcsr; + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.sf,rnd_mode,FP_LONG,FP_SINGLE); - }}); - - 0x6: cvt_ps_s({{ Fd.df = Fs.df<31:0> | Ft.df<31:0>; }}); - } - } - } + }}); - //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D - 0x1: decode RS_HI { - 0x0: decode RS_LO { - format FloatOp { - 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); - 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); - 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); - 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); - 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); - 0x5: absd({{ Fd.df = abs(Fs.df);}}); - 0x6: movd({{ Fd.df = Fs.df;}}); - 0x7: negd({{ Fd.df = -1 * Fs.df;}}); - } - } - - 0x1: decode RS_LO { - //only legal for 64 bit - format FloatOp64 { - 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); - 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); - 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); - } - - format FloatOp { - 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); - 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); - 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); - 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); - } - } - - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp { - 0x0: movfd({{ if (FPConditionCode(CC) == 0) Fd.df = Fs.df; }}); - 0x1: movtd({{ if (FPConditionCode(CC) == 1) Fd.df = Fs.df; }}); - } - } + 0x6: cvt_ps_s({{ Fd.df = Fs.df<31:0> | Ft.df<31:0>; }}); + } + } + } + + //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D + 0x1: decode RS_HI { + 0x0: decode RS_LO { + format FloatOp { + 0x0: addd({{ Fd.df = Fs.df + Ft.df;}}); + 0x1: subd({{ Fd.df = Fs.df - Ft.df;}}); + 0x2: muld({{ Fd.df = Fs.df * Ft.df;}}); + 0x3: divd({{ Fd.df = Fs.df / Ft.df;}}); + 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}}); + 0x5: absd({{ Fd.df = abs(Fs.df);}}); + 0x6: movd({{ Fd.df = Fs.df;}}); + 0x7: negd({{ Fd.df = -1 * Fs.df;}}); + } + } - format BasicOp { - 0x2: movz({{ if (Rt == 0) Fd.df = Fs.df; }}); - 0x3: movn({{ if (Rt != 0) Fd.df = Fs.df; }}); - } + 0x1: decode RS_LO { + //only legal for 64 bit + format Float64Op { + 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}}); + 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}}); + 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}}); + } + + format FloatOp { + 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }}); + 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }}); + 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }}); + 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }}); + } + } - format FloatOp64 { - 0x5: recipd({{ Fd.df = 1 / Fs.df}}); - 0x6: rsqrtd{{ Fd.df = 1 / sqrt(Fs.df) }}); - } - } + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format FloatOp { + 0x0: movfd({{ if (FPConditionCode(CC) == 0) Fd.df = Fs.df; }}); + 0x1: movtd({{ if (FPConditionCode(CC) == 1) Fd.df = Fs.df; }}); + } + } + + format BasicOp { + 0x2: movz({{ if (Rt == 0) Fd.df = Fs.df; }}); + 0x3: movn({{ if (Rt != 0) Fd.df = Fs.df; }}); + } + + format Float64Op { + 0x5: recipd({{ Fd.df = 1 / Fs.df}}); + 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }}); + } + } - 0x4: decode RS_LO { - format FloatOp { - 0x0: cvt_s_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); - }}); + 0x4: decode RS_LO { + format FloatOp { + 0x0: cvt_s_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE); + }}); - 0x4: cvt_w_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); - }}); - } + 0x4: cvt_w_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE); + }}); + } - //only legal for 64 bit - format FloatOp64 { - 0x5: cvt_l_d({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); - }}); - } - } - } + //only legal for 64 bit + format Float64Op { + 0x5: cvt_l_d({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE); + }}); + } + } + } - //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W - 0x4: decode FUNCTION { - format FloatOp { - 0x10: cvt_s({{ + //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W + 0x4: decode FUNCTION { + format FloatOp { + 0x10: cvt_s({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD); }}); - 0x10: cvt_d({{ + 0x10: cvt_d({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD); }}); - } - } - - //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 FloatOp { - 0x10: cvt_s_l({{ + } + } + + //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 FloatOp { + 0x10: cvt_s_l({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG); }}); - 0x11: cvt_d_l({{ + 0x11: cvt_d_l({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG); }}); - } - } + } + } + + //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 RS_HI { + 0x0: decode RS_LO { + format Float64Op { + 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df + Ft.df; + }}); - //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 RS_HI { - 0x0: decode RS_LO { - format FloatOp64 { - 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df + Ft.df; - }}); - - 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df - Ft.df; - }}); + 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df - Ft.df; + }}); - 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs.df * Ft.df; - }}); + 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs.df * Ft.df; + }}); - 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = abs(Fs.df); - }}); + 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = abs(Fs.df); + }}); - 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = Fs<31:0> | Ft<31:0>; - }}); + 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = Fs<31:0> | Ft<31:0>; + }}); - 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = -1 * Fs.df; - }}); - } - } + 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = -1 * Fs.df; + }}); + } + } - 0x2: decode RS_LO { - 0x1: decode MOVCF { - format FloatOp64 { - 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) - 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}) - } - } + 0x2: decode RS_LO { + 0x1: decode MOVCF { + format Float64Op { + 0x0: movfps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); + 0x1: movtps({{ if ( FPConditionCode(CC) == 0) Fd = Fs;}}); + } + } - } + } - 0x4: decode RS_LO { - 0x0: FloatOp64::cvt_s_pu({{ + 0x4: decode RS_LO { + 0x0: Float64Op::cvt_s_pu({{ int rnd_mode = xc->miscRegs.fcsr; Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI); - }}); - } + }}); + } - 0x5: decode RS_LO { - format FloatOp64 { - 0x0: cvt_s_pl({{ - int rnd_mode = xc->miscRegs.fcsr; - Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); - }}); - 0x4: pll({{ Fd.df = Fs<31:0> | Ft<31:0>}}); - 0x5: plu({{ Fd.df = Fs<31:0> | Ft<63:32>}}); - 0x6: pul({{ Fd.df = Fs<63:32> | Ft<31:0>}}); - 0x7: puu({{ Fd.df = Fs<63:32 | Ft<63:32>}}); - } - } - } - } - - //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({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2); - 0x1: bc2t({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); - } + 0x5: decode RS_LO { + format Float64Op { + 0x0: cvt_s_pl({{ + int rnd_mode = xc->miscRegs.fcsr; + Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO); + }}); + 0x4: pll({{ Fd.df = Fs<31:0> | Ft<31:0>}}); + 0x5: plu({{ Fd.df = Fs<31:0> | Ft<63:32>}}); + 0x6: pul({{ Fd.df = Fs<63:32> | Ft<31:0>}}); + 0x7: puu({{ Fd.df = Fs<63:32 | Ft<63:32>}}); + } + } + } + } } + } + + //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({{ cond = (xc->miscRegs.cop2cc == 0); }}, COP2}}); - 0x1: bc2tl({{ cond = (xc->miscRegs.cop2cc == 1); }}, COP2}}); - } + 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 Memory { - 0x0: lwxc1({{ EA = Rs + Rt; }},{{ Ft<31:0> = Mem.uf; }}); - 0x1: ldxc1({{ EA = Rs + Rt; }},{{ Ft<63:0> = Mem.df; }}); - 0x5: luxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ Ft<31:0> = Mem.df; }}); + + //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 LoadMemory2 { + 0x0: lwxc1({{ EA = Rs + Rt; }},{{ Ft<31:0> = Mem.sf; }}); + 0x1: ldxc1({{ EA = Rs + Rt; }},{{ Ft<63:0> = Mem.df; }}); + 0x5: luxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ Ft<31:0> = Mem.df; }}); } - } + } - 0x1: decode FUNCTION_LO { - format Memory { - 0x0: swxc1({{ EA = Rs + Rt; }},{{ Mem.uf = Ft<31:0>; }}); - 0x1: sdxc1({{ EA = Rs + Rt; }},{{ Mem.uf = Ft<63:0>}}); - 0x5: suxc1({{ //Need to make EA<2:0> = 0 - EA = Rs + Rt; - }}, - {{ Mem.df = Ft<63:0>;}}); - 0x7: prefx({{ }}); + 0x1: decode FUNCTION_LO { + format StoreMemory2 { + 0x0: swxc1({{ EA = Rs + Rt; }},{{ Mem.sf = Ft<31:0>; }}); + 0x1: sdxc1({{ EA = Rs + Rt; }},{{ Mem.df = Ft<63:0>}}); + 0x5: suxc1({{ //Need to make EA<2:0> = 0 + EA = Rs + Rt; + }}, + {{ Mem.df = Ft<63:0>;}}); } - } - format FloatOp { - 0x3: WarnUnimpl::alnv_ps({{ }}); + 0x7: WarnUnimpl::prefx(); + } + + format FloatOp { + 0x3: WarnUnimpl::alnv_ps(); format BasicOp { - 0x4: decode FUNCTION_LO { - 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); - 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); - 0x6: madd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) + Fr.df; - }}); - } - - 0x5: decode FUNCTION_LO { - 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); - 0x6: msub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (Fs.df * Fs.df) - Fr.df; - }}); - } - - 0x6: decode FUNCTION_LO { - 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); - 0x6: nmadd_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; - }}); - } - - 0x7: decode FUNCTION_LO { - 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); - 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); - 0x6: nmsub_ps({{ - //Must Check for Exception Here... Supposed to Operate on Upper and - //Lower Halves Independently but we take simulator shortcut - Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; - }}); - } + 0x4: decode FUNCTION_LO { + 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }}); + 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }}); + 0x6: madd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x5: decode FUNCTION_LO { + 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }}); + 0x6: msub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (Fs.df * Fs.df) - Fr.df; + }}); + } + + 0x6: decode FUNCTION_LO { + 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }}); + 0x6: nmadd_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } + + 0x7: decode FUNCTION_LO { + 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }}); + 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }}); + 0x6: nmsub_ps({{ + //Must Check for Exception Here... Supposed to Operate on Upper and + //Lower Halves Independently but we take simulator shortcut + Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; + }}); + } } + } } - } - //MIPS obsolete instructions - format Branch { - 0x4: beql({{ cond = (Rs.sq == 0); }}); - 0x5: bnel({{ cond = (Rs.sq != 0); }}); - 0x6: blezl({{ cond = (Rs.sq <= 0); }}); - 0x7: bgtzl({{ cond = (Rs.sq > 0); }}); + //MIPS obsolete instructions + 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() { @@ -747,149 +762,149 @@ decode OPCODE_HI default FailUnimpl::unknown() { 0x0: decode FUNCTION_LO { format IntOp { - 0x0: madd({{ + 0x0: madd({{ INT64 temp1 = Hi.sw << 32 | Lo.sw >> 32; temp1 = temp1 + (Rs.sw * Rt.sw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x1: maddu({{ + 0x1: maddu({{ INT64 temp1 = Hi.uw << 32 | Lo.uw >> 32; temp1 = temp1 + (Rs.uw * Rt.uw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); + 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }}); - 0x4: msub({{ + 0x4: msub({{ INT64 temp1 = Hi.sw << 32 | Lo.sw >> 32; temp1 = temp1 - (Rs.sw * Rt.sw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); - 0x5: msubu({{ + 0x5: msubu({{ INT64 temp1 = Hi.uw << 32 | Lo.uw >> 32; temp1 = temp1 - (Rs.uw * Rt.uw); xc->miscRegs.hi->temp1<63:32>; xc->miscRegs.lo->temp1<31:0> - }}); + }}); } } 0x4: decode FUNCTION_LO { - format BasicOp { - 0x0: clz({{ + format BasicOp { + 0x0: clz({{ int cnt = 0; int idx = 0; while ( Rs.uw<idx>!= 1) { - cnt++; - idx--; + cnt++; + idx--; } Rd.uw = cnt; - }}); + }}); - 0x1: clo({{ + 0x1: clo({{ int cnt = 0; int idx = 0; while ( Rs.uw<idx>!= 0) { - cnt++; - idx--; + cnt++; + idx--; } Rd.uw = cnt; - }}); - } + }}); + } } 0x7: decode FUNCTION_LO { - 0x7: WarnUnimpl::sdbbp({{ }}); + 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 { + 0x0: decode FUNCTION_LO { format WarnUnimpl { - 0x1: ext({{ }}); - 0x4: ins({{ }}); + 0x1: ext(); + 0x4: ins(); } - } + } - 0x1: decode FUNCTION_LO { + 0x1: decode FUNCTION_LO { format WarnUnimpl { - 0x0: fork({{ }}); - 0x1: yield({{ }}); + 0x0: fork(); + 0x1: yield(); } - } + } - //Table A-10 MIPS32 BSHFL Encoding of sa Field - 0x4: decode SA { + //Table A-10 MIPS32 BSHFL Encoding of sa Field + 0x4: decode SA { - 0x02: WarnUnimpl::wsbh({{ }}); + 0x02: WarnUnimpl::wsbh(); format BasicOp { 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}}); 0x18: seh({{ Rd.sw = /* sext32(Rt<15>,16) | */ Rt<15:0>}}); } - } + } - 0x6: decode FUNCTION_LO { - 0x7: BasicOp::rdhwr({{ Rt = xc->hwRegs[RD];}}); - } + 0x6: decode FUNCTION_LO { + 0x7: BasicOp::rdhwr({{ Rt = xc->hwRegs[RD];}}); + } } - }; + } 0x4: decode OPCODE_LO default FailUnimpl::reserved() { - format Memory { - 0x0: lb({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sb; }}); - 0x1: lh({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sh; }}); - 0x2: lwl({{ EA = Rs + disp; }}, {{ Rb.sw = Mem.sw; }}, WordAlign); - 0x3: lw({{ EA = Rs + disp; }}, {{ Rb.uq = Mem.sb; }}); - 0x4: lbu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.ub; }}); - 0x5: lhu({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uh; }}); - 0x6: lwr({{ EA = Rs + disp; }}, {{ Rb.uw = Mem.uw; }}, WordAlign); - }; - - 0x7: FailUnimpl::reserved({{ }}); - }; + format LoadMemory { + 0x0: lb({{ Rb.sw = Mem.sb; }}); + 0x1: lh({{ Rb.sw = Mem.sh; }}); + 0x2: lwl({{ Rb.sw = Mem.sw; }});//, WordAlign); + 0x3: lw({{ Rb.uq = Mem.sb; }}); + 0x4: lbu({{ Rb.uw = Mem.ub; }}); + 0x5: lhu({{ Rb.uw = Mem.uh; }}); + 0x6: lwr({{ Rb.uw = Mem.uw; }});//, WordAlign); + } + + 0x7: FailUnimpl::reserved(); + } 0x5: decode OPCODE_LO default FailUnimpl::reserved() { - format Memory { - 0x0: sb({{ EA = Rs + disp; }}, {{ Mem.ub = Rt<7:0>; }}); - 0x1: sh({{ EA = Rs + disp; }},{{ Mem.uh = Rt<15:0>; }}); - 0x2: swl({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); - 0x3: sw({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }}); - 0x6: swr({{ EA = Rs + disp; }},{{ Mem.ub = Rt<31:0>; }},WordAlign); - }; + format StoreMemory { + 0x0: sb({{ Mem.ub = Rt<7:0>; }}); + 0x1: sh({{ Mem.uh = Rt<15:0>; }}); + 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + 0x3: sw({{ Mem.ub = Rt<31:0>; }}); + 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign); + } format WarnUnimpl { - 0x7: cache({{ }}); - }; + 0x7: cache(); + } - }; + } 0x6: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::ll({{ }}); + 0x0: WarnUnimpl::ll(); - format Memory { - 0x1: lwc1({{ EA = Rs + disp; }},{{ Ft<31:0> = Mem.uf; }}); - 0x5: ldc1({{ EA = Rs + disp; }},{{ Ft<63:0> = Mem.df; }}); - }; - }; + format LoadMemory { + 0x1: lwc1({{ Ft<31:0> = Mem.sf; }}); + 0x5: ldc1({{ Ft<63:0> = Mem.df; }}); + } + } 0x7: decode OPCODE_LO default FailUnimpl::reserved() { - 0x0: WarnUnimpl::sc({{ }}); + 0x0: WarnUnimpl::sc(); - format Memory { - 0x1: swc1({{ EA = Rs + disp; }},{{ Mem.uf = Ft<31:0>; }}); - 0x5: sdc1({{ EA = Rs + disp; }},{{ Mem.df = Ft<63:0>; }}); - }; + format StoreMemory { + 0x1: swc1({{ Mem.sf = Ft<31:0>; }}); + 0x5: sdc1({{ Mem.df = Ft<63:0>; }}); + } } } diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa index 404314c7a..c244013df 100644 --- a/arch/mips/isa/formats.isa +++ b/arch/mips/isa/formats.isa @@ -1,22 +1,33 @@ -//Include the basic format +// -*- mode:c++ -*- + //Templates from this format are used later -##include "m5/arch/mips/isa_desc/formats/basic.format" +//Include the basic format +##include "m5/arch/mips/isa/formats/basic.isa" + +//Include the basic format +##include "m5/arch/mips/isa/formats/noop.isa" + +//Include utility formats/functions +##include "m5/arch/mips/isa/formats/util.isa" //Include the integerOp and integerOpCc format -##include "m5/arch/mips/isa_desc/formats/integerop.format" +##include "m5/arch/mips/isa/formats/int.isa" //Include the floatOp format -##include "m5/arch/mips/isa_desc/formats/floatop.format" +##include "m5/arch/mips/isa/formats/fp.isa" //Include the mem format -##include "m5/arch/mips/isa_desc/formats/mem.format" +##include "m5/arch/mips/isa/formats/mem.isa" //Include the trap format -##include "m5/arch/mips/isa_desc/formats/trap.format" +##include "m5/arch/mips/isa/formats/trap.isa" //Include the branch format -##include "m5/arch/mips/isa_desc/formats/branch.format" +##include "m5/arch/mips/isa/formats/branch.isa" + +//Include the noop format +##include "m5/arch/mips/isa/formats/unimp.isa" //Include the noop format -##include "m5/arch/mips/isa_desc/formats/noop.format" +##include "m5/arch/mips/isa/formats/unknown.isa" diff --git a/arch/mips/isa/formats/basic.isa b/arch/mips/isa/formats/basic.isa index 8fba9845a..3b62aa5c3 100644 --- a/arch/mips/isa/formats/basic.isa +++ b/arch/mips/isa/formats/basic.isa @@ -1,3 +1,4 @@ +// -*- mode:c++ -*- // Declarations for execute() methods. def template BasicExecDeclare {{ @@ -39,7 +40,7 @@ def template BasicExecute {{ if(fault == No_Fault) { - %(op_wb)s; + %(op_wb)s; } return fault; } @@ -56,7 +57,7 @@ def template BasicDecodeWithMnemonic {{ }}; // The most basic instruction format... used only for a few misc. insts -def format BasicOperate(code, *flags) {{ +def format BasicOp(code, *flags) {{ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/arch/mips/isa/formats/branch.isa b/arch/mips/isa/formats/branch.isa index a565eb71b..fc207fd3f 100644 --- a/arch/mips/isa/formats/branch.isa +++ b/arch/mips/isa/formats/branch.isa @@ -1,66 +1,317 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // -// Branch instructions +// Control transfer instructions // output header {{ - /** - * Base class for integer operations. - */ - class Branch : public MipsStaticInst + + /** + * Base class for instructions whose disassembly is not purely a + * function of the machine instruction (i.e., it depends on the + * PC). This class overrides the disassemble() method to check + * the PC and symbol table values before re-using a cached + * disassembly string. This is necessary for branches and jumps, + * where the disassembly string includes the target address (which + * may depend on the PC and/or symbol table). + */ + class PCDependentDisassembly : public MipsStaticInst + { + protected: + /// Cached program counter from last disassembly + mutable Addr cachedPC; + + /// Cached symbol table pointer from last disassembly + mutable const SymbolTable *cachedSymtab; + + /// Constructor + PCDependentDisassembly(const char *mnem, MachInst _machInst, + OpClass __opClass) + : MipsStaticInst(mnem, _machInst, __opClass), + cachedPC(0), cachedSymtab(0) { - protected: + } - /// Constructor - Branch(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + const std::string & + disassemble(Addr pc, const SymbolTable *symtab) const; + }; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; -}}; + /** + * Base class for branches (PC-relative control transfers), + * conditional or unconditional. + */ + class Branch : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; -output decoder {{ - std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) { - return "Disassembly of integer instruction\n"; } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for branch likely branches (PC-relative control transfers), + */ + class BranchLikely : public PCDependentDisassembly + { + protected: + /// target address (signed) Displacement . + int32_t disp; + + /// Constructor. + Branch(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET << 2) + { + } + + Addr branchTarget(Addr branchPC) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for jumps (register-indirect control transfers). In + * the Mips ISA, these are always unconditional. + */ + class Jump : public PCDependentDisassembly + { + protected: + + /// Displacement to target address (signed). + int32_t disp; + + public: + /// Constructor + Jump(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + disp(OFFSET) + { + } + + Addr branchTarget(ExecContext *xc) const; + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; }}; -def template BranchExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const +output decoder {{ + Addr + Branch::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + BranchLikely::branchTarget(Addr branchPC) const + { + return branchPC + 4 + disp; + } + + Addr + Jump::branchTarget(ExecContext *xc) const + { + Addr NPC = xc->readPC() + 4; + uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); + return (Rb & ~3) | (NPC & 1); + } + + const std::string & + PCDependentDisassembly::disassemble(Addr pc, + const SymbolTable *symtab) const + { + if (!cachedDisassembly || + pc != cachedPC || symtab != cachedSymtab) { - //Attempt to execute the instruction - try - { - checkPriv; - - %(op_decl)s; - %(op_rd)s; - %(code)s; - } - //If we have an exception for some reason, - //deal with it - catch(MipsException except) - { - //Deal with exception - return No_Fault; - } - - //Write the resulting state to the execution context - %(op_wb)s; - - return No_Fault; + if (cachedDisassembly) + delete cachedDisassembly; + + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + cachedPC = pc; + cachedSymtab = symtab; + } + + return *cachedDisassembly; + } + + std::string + Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numSrcRegs == 0 && _numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // There's only one register arg (RA), but it could be + // either a source (the condition for conditional + // branches) or a destination (the link reg for + // unconditional branches) + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + ss << ","; + } + else if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numSrcRegs == 0 && _numDestRegs == 0) { + printReg(ss, 31); + ss << ","; + } +#endif + + Addr target = pc + 4 + disp; + + std::string str; + if (symtab && symtab->findSymbol(target, str)) + ss << str; + else + ccprintf(ss, "0x%x", target); + + return ss.str(); + } + + std::string + Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + +#ifdef SS_COMPATIBLE_DISASSEMBLY + if (_numDestRegs == 0) { + printReg(ss, 31); + ss << ","; } +#endif + + if (_numDestRegs > 0) { + printReg(ss, _destRegIdx[0]); + ss << ","; + } + + ccprintf(ss, "(r%d)", RB); + + return ss.str(); + } }}; -def format CondBranch(code) {{ - code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n'; +def format Branch(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-2:] == 'al': + code += 'R31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {\n' + #code += '//NPC=NPC: just placeholder to force parser to writeback NPC\n' + #code += ' NPC = NPC; \n' + code += ' NNPC = NPC + disp;\n' + code += '} \n' + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), ('IsDirectControl', 'IsCondControl')) + header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecode.subst(iop) exec_output = BasicExecute.subst(iop) }}; + +def format BranchLikely(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if name[strlen-3:] == 'all': + code += 'R31 = NNPC;\n' + + #Condition code + code = 'bool cond;\n' + code + code += 'if (cond) {' + #code += '//NPC=NPC: just placeholder to force parser to writeback NPC\n' + #code += 'NPC = NPC; \n' + code += 'NNPC = NPC + disp;\n' + code += '} \n' + + + iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), + ('IsDirectControl', 'IsCondControl','IsCondDelaySlot')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + +def format Jump(code,*flags) {{ + #Add Link Code if Link instruction + strlen = len(name) + if strlen >= 3 and name[2:3] == 'al': + code = 'R31 = NNPC;\n' + code + + iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\ + ('IsIndirectControl', 'IsUncondControl')) + + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + + + diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa index 707109fc2..23fcbaa67 100644 --- a/arch/mips/isa/formats/fp.isa +++ b/arch/mips/isa/formats/fp.isa @@ -27,7 +27,7 @@ output decoder {{ } }}; -def template FPExecute {{ +def template FloatingPointExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { //These are set to constants when the execute method @@ -70,7 +70,7 @@ def template FPExecute {{ }}; // Primary format for integer operate instructions: -def format FPOp(code, *opt_flags) {{ +def format FloatOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) @@ -86,12 +86,33 @@ def format FPOp(code, *opt_flags) {{ header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = IntegerExecute.subst(iop) + exec_output = FloatingPointExecute.subst(iop) +}}; + +// Primary format for integer operate instructions: +def format Float64Op(code, *opt_flags) {{ + orig_code = code + cblk = CodeBlock(code) + checkPriv = (code.find('checkPriv') != -1) + code.replace('checkPriv', '') + if checkPriv: + code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;') + else: + code.replace('checkPriv;', '') + for (marker, value) in (('ivValue', '0'), ('icValue', '0'), + ('xvValue', '0'), ('xcValue', '0')): + code.replace(marker, value) + iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecodeWithMnemonic.subst(iop) + exec_output = FloatingPointExecute.subst(iop) }}; // Primary format for integer operate instructions: def format FPOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{ orig_code = code + cblk = CodeBlock(code) checkPriv = (code.find('checkPriv') != -1) code.replace('checkPriv', '') diff --git a/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa index 5b8df54e9..cf06741a1 100644 --- a/arch/mips/isa/formats/int.isa +++ b/arch/mips/isa/formats/int.isa @@ -1,8 +1,11 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // // Integer operate instructions // +//Outputs to decoder.hh output header {{ /** * Base class for integer operations. @@ -12,7 +15,7 @@ output header {{ protected: /// Constructor - IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) { } @@ -26,7 +29,7 @@ output header {{ uint16_t imm; /// Constructor - IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) : + IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM) { } @@ -36,6 +39,7 @@ output header {{ }}; +//Outputs to decoder.cc output decoder {{ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { @@ -48,17 +52,18 @@ output decoder {{ } }}; -// Primary format for integer operate instructions: + +//Used by decoder.isa def format IntOp(code, *opt_flags) {{ orig_code = code cblk = CodeBlock(code) - //Figure out if we are creating a IntImmOp or a IntOp + # Figure out if we are creating a IntImmOp or a IntOp + # by looking at the instruction name + iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) strlen = len(name) - if ( name[strlen-1] = 'i' or ( name[strlen-2:] = 'iu')) - iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags) - else: - iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) + if name[strlen-1] == 'i' or name[strlen-2:] == 'iu': + iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags) header_output = BasicDeclare.subst(iop) decoder_output = BasicConstructor.subst(iop) diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa index 5ed5237c5..134548746 100644 --- a/arch/mips/isa/formats/mem.isa +++ b/arch/mips/isa/formats/mem.isa @@ -1,78 +1,462 @@ -//////////////////////////////////////////////////////////////////// +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. // -// Mem instructions +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. // +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. output header {{ + /** + * Base class for general Mips memory-format instructions. + */ + class Memory : public MipsStaticInst + { + protected: + + /// Memory request flags. See mem_req_base.hh. + unsigned memAccessFlags; + /// Pointer to EAComp object. + const StaticInstPtr eaCompPtr; + /// Pointer to MemAcc object. + const StaticInstPtr memAccPtr; + /// Displacement for EA calculation (signed). + int32_t disp; + + /// Constructor + Memory(const char *mnem, MachInst _machInst, OpClass __opClass, + StaticInstPtr _eaCompPtr = nullStaticInstPtr, + StaticInstPtr _memAccPtr = nullStaticInstPtr) + : MipsStaticInst(mnem, _machInst, __opClass), + memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr), + disp(OFFSET) + { + } + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + public: + + const StaticInstPtr &eaCompInst() const { return eaCompPtr; } + const StaticInstPtr &memAccInst() const { return memAccPtr; } + }; + +}}; + + +output decoder {{ + std::string + Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s %c%d,%d(r%d)", mnemonic, + flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB); + } + +}}; + +def format LoadAddress(code) {{ + iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code)) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = BasicDecode.subst(iop) + exec_output = BasicExecute.subst(iop) +}}; + + +def template LoadStoreDeclare {{ + /** + * Static instruction class for "%(mnemonic)s". + */ + class %(class_name)s : public %(base_class)s + { + protected: + /** - * Base class for integer operations. + * "Fake" effective address computation class for "%(mnemonic)s". */ - class Mem : public MipsStaticInst + class EAComp : public %(base_class)s { - protected: + public: + /// Constructor + EAComp(MachInst machInst); - /// Constructor - Mem(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + %(BasicExecDeclare)s + }; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + /** + * "Fake" memory access instruction class for "%(mnemonic)s". + */ + class MemAcc : public %(base_class)s + { + public: + /// Constructor + MemAcc(MachInst machInst); + + %(BasicExecDeclare)s }; + + public: + + /// Constructor. + %(class_name)s(MachInst machInst); + + %(BasicExecDeclare)s + + %(InitiateAccDeclare)s + + %(CompleteAccDeclare)s + }; }}; -output decoder {{ - std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - return "Disassembly of integer instruction\n"; + +def template InitiateAccDeclare {{ + Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template CompleteAccDeclare {{ + Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const; +}}; + + +def template LoadStoreConstructor {{ + /** TODO: change op_class to AddrGenOp or something (requires + * creating new member of OpClass enum in op_class.hh, updating + * config files, etc.). */ + inline %(class_name)s::EAComp::EAComp(MachInst machInst) + : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp) + { + %(ea_constructor)s; + } + + inline %(class_name)s::MemAcc::MemAcc(MachInst machInst) + : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s) + { + %(memacc_constructor)s; + } + + inline %(class_name)s::%(class_name)s(MachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + new EAComp(machInst), new MemAcc(machInst)) + { + %(constructor)s; + } +}}; + + +def template EACompExecute {{ + Fault + %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(code)s; + + if (fault == NoFault) { + %(op_wb)s; + xc->setEA(EA); } + + return fault; + } }}; -def template MemExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - //Attempt to execute the instruction - try - { - - %(op_decl)s; - %(op_rd)s; - ea_code - %(code)s; - } - //If we have an exception for some reason, - //deal with it - catch(MipsException except) - { - //Deal with exception - return No_Fault; - } - - //Write the resulting state to the execution context - %(op_wb)s; - - return No_Fault; - } -}}; - -// Primary format for integer operate instructions: -def format Mem(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = I ? (R1 + SIMM13) : R1 + R2;'); -}}; - -def format Cas(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = MemExecute.subst(iop) - exec_output.replace('ea_code', 'EA = R1;'); +def template LoadMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } }}; + + +def template LoadExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags); + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template LoadInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags); + } + + return fault; + } +}}; + + +def template LoadCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + + memcpy(&Mem, data, sizeof(Mem)); + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreMemAccExecute {{ + Fault + %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + EA = xc->getEA(); + + if (fault == NoFault) { + %(code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + + +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +def template StoreInitiateAcc {{ + Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Addr EA; + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_src_decl)s; + %(op_dest_decl)s; + %(op_rd)s; + %(ea_code)s; + + if (fault == NoFault) { + %(memacc_code)s; + } + + if (fault == NoFault) { + fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA, + memAccessFlags, &write_result); + if (traceData) { traceData->setData(Mem); } + } + + return fault; + } +}}; + + +def template StoreCompleteAcc {{ + Fault %(class_name)s::completeAcc(uint8_t *data, + %(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + + %(fp_enable_check)s; + %(op_dest_decl)s; + + memcpy(&write_result, data, sizeof(write_result)); + + if (fault == NoFault) { + %(postacc_code)s; + } + + if (fault == NoFault) { + %(op_wb)s; + } + + return fault; + } +}}; + +// load instructions use Rt as dest, so check for +// Rt == 31 to detect nops +def template LoadNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + if (RT == 0) { + i = makeNop(i); + } + return i; + } +}}; + +def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + exec_template_base = 'Store') +}}; + +//FP loads are offloaded to these formats for now ... +def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Load') +}}; + + +//FP stores are offloaded to these formats for now ... +def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + decode_template = LoadNopCheckDecode, + exec_template_base = 'Store') +}}; + diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa index b1ece654d..d366461e2 100644 --- a/arch/mips/isa/formats/noop.isa +++ b/arch/mips/isa/formats/noop.isa @@ -1,47 +1,88 @@ +// -*- mode:c++ -*- + //////////////////////////////////////////////////////////////////// // -// Noop instruction +// Nop // output header {{ - /** - * Base class for integer operations. - */ - class Noop : public MipsStaticInst + /** + * Static instruction class for no-ops. This is a leaf class. + */ + class Nop : public MipsStaticInst + { + /// Disassembly of original instruction. + const std::string originalDisassembly; + + public: + /// Constructor + Nop(const std::string _originalDisassembly, MachInst _machInst) + : MipsStaticInst("nop", _machInst, No_OpClass), + originalDisassembly(_originalDisassembly) { - protected: + flags[IsNop] = true; + } + + ~Nop() { } - /// Constructor - Noop(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass) - { - } + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; - std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - }; + %(BasicExecDeclare)s + }; }}; output decoder {{ - std::string Noop::generateDisassembly(Addr pc, const SymbolTable *symtab) const - { - return "Disassembly of integer instruction\n"; - } + std::string Nop::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return originalDisassembly; +#else + return csprintf("%-10s (%s)", "nop", originalDisassembly); +#endif + } + + /// Helper function for decoding nops. Substitute Nop object + /// for original inst passed in as arg (and delete latter). + inline + MipsStaticInst * + makeNop(MipsStaticInst *inst) + { + MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst); + delete inst; + return nop; + } }}; -def template NoopExecute {{ - Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const - { - //Nothing to see here, move along - return No_Fault; - } +output exec {{ + Fault + Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const + { + return No_Fault; + } +}}; + +// integer & FP operate instructions use Rc as dest, so check for +// Rc == 31 to detect nops +def template OperateNopCheckDecode {{ + { + MipsStaticInst *i = new %(class_name)s(machInst); + if (RC == 31) { + i = makeNop(i); + } + return i; + } }}; -// Primary format for integer operate instructions: -def format Noop(code, *opt_flags) {{ - orig_code = code - cblk = CodeBlock(code) - iop = InstObjParams(name, Name, 'MipsStaticInst', cblk, opt_flags) - header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) - decode_block = BasicDecodeWithMnemonic.subst(iop) - exec_output = NoopExecute.subst(iop) + +// Like BasicOperate format, but generates NOP if RC/FC == 31 +def format BasicOperateWithNopCheck(code, *opt_args) {{ + iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), + opt_args) + header_output = BasicDeclare.subst(iop) + decoder_output = BasicConstructor.subst(iop) + decode_block = OperateNopCheckDecode.subst(iop) + exec_output = BasicExecute.subst(iop) }}; + diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa new file mode 100644 index 000000000..a7a71c681 --- /dev/null +++ b/arch/mips/isa/formats/unimp.isa @@ -0,0 +1,165 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +output header {{ + /** + * Static instruction class for unimplemented instructions that + * cause simulator termination. Note that these are recognized + * (legal) instructions that the simulator does not support; the + * 'Unknown' class is used for unrecognized/illegal instructions. + * This is a leaf class. + */ + class FailUnimplemented : public MipsStaticInst + { + public: + /// Constructor + FailUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; + + /** + * Base class for unimplemented instructions that cause a warning + * to be printed (but do not terminate simulation). This + * implementation is a little screwy in that it will print a + * warning for each instance of a particular unimplemented machine + * instruction, not just for each unimplemented opcode. Should + * probably make the 'warned' flag a static member of the derived + * class. + */ + class WarnUnimplemented : public MipsStaticInst + { + private: + /// Have we warned on this instruction yet? + mutable bool warned; + + public: + /// Constructor + WarnUnimplemented(const char *_mnemonic, MachInst _machInst) + : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + +output decoder {{ + std::string + FailUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + return csprintf("%-10s (unimplemented)", mnemonic); + } + + std::string + WarnUnimplemented::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { +#ifdef SS_COMPATIBLE_DISASSEMBLY + return csprintf("%-10s", mnemonic); +#else + return csprintf("%-10s (unimplemented)", mnemonic); +#endif + } +}}; + +output exec {{ + Fault + FailUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unimplemented instruction '%s' " + "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE); + return Unimplemented_Opcode_Fault; + } + + Fault + WarnUnimplemented::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + if (!warned) { + warn("instruction '%s' unimplemented\n", mnemonic); + warned = true; + } + + return No_Fault; + } +}}; + + +def format FailUnimpl() {{ + iop = InstObjParams(name, 'FailUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +def format WarnUnimpl() {{ + iop = InstObjParams(name, 'WarnUnimplemented') + decode_block = BasicDecodeWithMnemonic.subst(iop) +}}; + +output header {{ + /** + * Static instruction class for unknown (illegal) instructions. + * These cause simulator termination if they are executed in a + * non-speculative mode. This is a leaf class. + */ + class Unknown : public MipsStaticInst + { + public: + /// Constructor + Unknown(MachInst _machInst) + : MipsStaticInst("unknown", _machInst, No_OpClass) + { + // don't call execute() (which panics) if we're on a + // speculative path + flags[IsNonSpeculative] = true; + } + + %(BasicExecDeclare)s + + std::string + generateDisassembly(Addr pc, const SymbolTable *symtab) const; + }; +}}; + diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa new file mode 100644 index 000000000..6eba5b4f9 --- /dev/null +++ b/arch/mips/isa/formats/unknown.isa @@ -0,0 +1,52 @@ +// -*- mode:c++ -*- + +// Copyright (c) 2003-2005 The Regents of The University of Michigan +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer; +// redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution; +// neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +output decoder {{ + std::string + Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const + { + return csprintf("%-10s (inst 0x%x, opcode 0x%x)", + "unknown", machInst, OPCODE); + } +}}; + +output exec {{ + Fault + Unknown::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + panic("attempt to execute unknown instruction " + "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE); + return Unimplemented_Opcode_Fault; + } +}}; + +def format Unknown() {{ + decode_block = 'return new Unknown(machInst);\n' +}}; + diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa new file mode 100644 index 000000000..f0671726c --- /dev/null +++ b/arch/mips/isa/formats/util.isa @@ -0,0 +1,125 @@ +// -*- mode:c++ -*- + +let {{ +def UncondCtrlBase(name, Name, base_class, npc_expr, flags): + # Declare basic control transfer w/o link (i.e. link reg is R31) + nolink_code = 'NPC = %s;\n' % npc_expr + nolink_iop = InstObjParams(name, Name, base_class, + CodeBlock(nolink_code), flags) + header_output = BasicDeclare.subst(nolink_iop) + decoder_output = BasicConstructor.subst(nolink_iop) + exec_output = BasicExecute.subst(nolink_iop) + + # Generate declaration of '*AndLink' version, append to decls + link_code = 'Ra = NPC & ~3;\n' + nolink_code + link_iop = InstObjParams(name, Name + 'AndLink', base_class, + CodeBlock(link_code), flags) + header_output += BasicDeclare.subst(link_iop) + decoder_output += BasicConstructor.subst(link_iop) + exec_output += BasicExecute.subst(link_iop) + + # need to use link_iop for the decode template since it is expecting + # the shorter version of class_name (w/o "AndLink") + + return (header_output, decoder_output, + JumpOrBranchDecode.subst(nolink_iop), exec_output) + +def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + postacc_code = '', base_class = 'Memory', + decode_template = BasicDecode, exec_template_base = ''): + # Make sure flags are in lists (convert to lists if not). + mem_flags = makeList(mem_flags) + inst_flags = makeList(inst_flags) + + # add hook to get effective addresses into execution trace output. + ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n' + + # generate code block objects + ea_cblk = CodeBlock(ea_code) + memacc_cblk = CodeBlock(memacc_code) + postacc_cblk = CodeBlock(postacc_code) + + # Some CPU models execute the memory operation as an atomic unit, + # while others want to separate them into an effective address + # computation and a memory access operation. As a result, we need + # to generate three StaticInst objects. Note that the latter two + # are nested inside the larger "atomic" one. + + # generate InstObjParams for EAComp object + ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags) + + # generate InstObjParams for MemAcc object + memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags) + # in the split execution model, the MemAcc portion is responsible + # for the post-access code. + memacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for InitiateAcc, CompleteAcc object + # The code used depends on the template being used + if (exec_template_base == 'Load'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(memacc_code + postacc_code) + elif (exec_template_base == 'Store'): + initiateacc_cblk = CodeBlock(ea_code + memacc_code) + completeacc_cblk = CodeBlock(postacc_code) + else: + initiateacc_cblk = '' + completeacc_cblk = '' + + initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk, + inst_flags) + + completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk, + inst_flags) + + if (exec_template_base == 'Load'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + elif (exec_template_base == 'Store'): + initiateacc_iop.ea_code = ea_cblk.code + initiateacc_iop.memacc_code = memacc_cblk.code + completeacc_iop.postacc_code = postacc_cblk.code + + # generate InstObjParams for unified execution + cblk = CodeBlock(ea_code + memacc_code + postacc_code) + iop = InstObjParams(name, Name, base_class, cblk, inst_flags) + + iop.ea_constructor = ea_cblk.constructor + iop.ea_code = ea_cblk.code + iop.memacc_constructor = memacc_cblk.constructor + iop.memacc_code = memacc_cblk.code + iop.postacc_code = postacc_cblk.code + + if mem_flags: + s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';' + iop.constructor += s + memacc_iop.constructor += s + + # select templates + memAccExecTemplate = eval(exec_template_base + 'MemAccExecute') + fullExecTemplate = eval(exec_template_base + 'Execute') + initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') + completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + + # (header_output, decoder_output, decode_block, exec_output) + return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), + decode_template.subst(iop), + EACompExecute.subst(ea_iop) + + memAccExecTemplate.subst(memacc_iop) + + fullExecTemplate.subst(iop) + + initiateAccTemplate.subst(initiateacc_iop) + + completeAccTemplate.subst(completeacc_iop)) +}}; + + +output exec {{ + + /// CLEAR ALL CPU INST/EXE HAZARDS + inline void + clear_exe_inst_hazards() + { + //CODE HERE + } +} diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa index a8c71872b..411e398b4 100644 --- a/arch/mips/isa/main.isa +++ b/arch/mips/isa/main.isa @@ -26,7 +26,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -##include "m5/arch/sparc/isa_desc/includes.h" +##include "m5/arch/mips/isa/includes.isa" //////////////////////////////////////////////////////////////////// // @@ -37,16 +37,16 @@ namespace MipsISA; //Include the bitfield definitions -##include "m5/arch/mips/isa_desc/bitfields.h" +##include "m5/arch/mips/isa/bitfields.isa" //Include the operand_types and operand definitions -##include "m5/arch/mips/isa_desc/operands.h" +##include "m5/arch/mips/isa/operands.isa" //Include the base class for mips instructions, and some support code -##include "m5/arch/mips/isa_desc/base.h" +##include "m5/arch/mips/isa/base.isa" //Include the definitions for the instruction formats -##include "m5/arch/mips/isa_desc/formats.h" +##include "m5/arch/mips/isa/formats.isa" //Include the decoder definition -##include "m5/arch/mips/isa_desc/decoder.h" +##include "m5/arch/mips/isa/decoder.isa" diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa index c8e08a436..65ef2245f 100644 --- a/arch/mips/isa/operands.isa +++ b/arch/mips/isa/operands.isa @@ -1,12 +1,12 @@ def operand_types {{ 'sb' : ('signed int', 8), 'ub' : ('unsigned int', 8), - 'shw' : ('signed int', 16), - 'uhw' : ('unsigned int', 16), + 'sh' : ('signed int', 16), + 'uh' : ('unsigned int', 16), 'sw' : ('signed int', 32), 'uw' : ('unsigned int', 32), - 'sdw' : ('signed int', 64), - 'udw' : ('unsigned int', 64), + 'sd' : ('signed int', 64), + 'ud' : ('unsigned int', 64), 'sf' : ('float', 32), 'df' : ('float', 64), 'qf' : ('float', 128) @@ -16,6 +16,7 @@ def operands {{ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1), 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2), 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3), + 'R31': ('IntReg', 'uw','R31','IsInteger', 4), 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3), 'Sa': ('IntReg', 'uw', 'SA', 'IsInteger', 4), @@ -24,12 +25,12 @@ def operands {{ 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2), 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3), - 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4) + 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4), - #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4), + 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4), + 'NNPC': ('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4) #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1), #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1), # The next two are hacks for non-full-system call-pal emulation #'R0': ('IntReg', 'uq', '0', None, 1), - #'R16': ('IntReg', 'uq', '16', None, 1) }}; |