diff options
Diffstat (limited to 'Cpu/cpu-mips.cpp')
-rw-r--r-- | Cpu/cpu-mips.cpp | 1166 |
1 files changed, 1166 insertions, 0 deletions
diff --git a/Cpu/cpu-mips.cpp b/Cpu/cpu-mips.cpp index e69de29..d7fcb8b 100644 --- a/Cpu/cpu-mips.cpp +++ b/Cpu/cpu-mips.cpp @@ -0,0 +1,1166 @@ +/* Code HIGHLY ripped off^W^W inspired from PCSX. */ + +enum registers { + Rzr, Rat, Rv0, Rv1, Ra0, Ra1, Ra2, Ra3, + Rt0, Rt1, Rt2, Rt3, Rt4, Rt5, Rt6, Rt7, + Rs0, Rs1, Rs2, Rs3, Rs4, Rs5, Rs6, Rs7, + Rt8, Rt9, Rk0, Rk1, Rgp, Rsp, Rfp, Rra, + Rhi, Rlo, +}; + +char * GPRregisters[] = { + "0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", + "hi", "lo", +}; + +char * CP0registers[] = { + "Index" , "Random" , "EntryLo0", "EntryLo1", "Context" , "PageMask" , "Wired" , "*Check me*", + "BadVAddr" , "Count" , "EntryHi" , "Compare" , "Status" , "Cause" , "ExceptPC" , "PRevID" , + "Config" , "LLAddr" , "WatchLo" , "WatchHi" , "XContext", "*RES*" , "*RES*" , "*RES*" , + "*RES*" , "*RES* " , "PErr" , "CacheErr", "TagLo" , "TagHi" , "ErrorEPC" , "*RES*" }; + +typedef void (*TdisR3000AF)(TDis *, Uint32 code, Uint32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ + static void fn(TDis * d, Uint32 code, Uint32 pc) { \ + d->pc = pc; \ + b; \ + } + +#define _Funct_ ((code ) & 0x3F) // The funct part of the instruction register +#define _Rd_ ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _Rt_ ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _Rs_ ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _Sa_ ((code >> 6) & 0x1F) // The sa part of the instruction register +#define _Im_ ( code & 0xFFFF) // The immediate part of the instruction register + // The signed immediate part of the instruction register +#define _sIm_ (code & 0x8000 ? - (((~code) & 0x7FFF) + 1) : ( code & 0x7FFF)) + +#define _Target_ (0x80000000 + ((code & 0x03ffffff) * 4)) +#define _Branch_ (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_ _Im_, _nRs_ + +#define dName(n) { d->Name(n); } +#define dGPR(i) { d->PushGPReg(i); } +#define dCP0(i) { d->PushCPReg(i); } +#define dImm() { d->PushImm(_Im_); } +#define dTarget() { d->PushTarget(_Target_); } +#define dSa() { d->PushSa(_Sa_); } +#define dOfB() { \ + d->PushOfB(_Rs_, _Im_, width); \ +} +#define dOffset() { \ + d->PushOffset(_Branch_); \ +} + +#define dFull(full) { \ + d->PushFull(full); \ + d->Comment("MaybeRefTo..."); \ +} + +#define sep + +#define dInvalid() { \ + d->Invalid(); \ +} + +#define dSuspect() { \ + d->Suspect(); \ +} + +#define Invalidate(reg) { \ + if (!reg) \ + dSuspect(); \ +} + +#define SetReg(reg, val) { \ + if (!reg) \ + dSuspect(); \ +} + +#define MarkFunction(target) { \ + d->add_function(target); \ +} + +#define Branch(branch) { \ + d->add_branch(branch); \ +} + +#define Jump(target) { \ + d->add_jump(target); \ +} + +#define Stop(target) { \ + d->SetTag(target, STOP, true); \ +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ + +MakeDisF(disADDI, + dName("addi"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_)) { + Invalidate(_Rt_); + } else { + SetRegS(_Rt_, GetRegS(_Rs_) + _sIm_); + } + + d->Comment("Add immediate"); +) + +MakeDisF(disADDIU, + if (!_Rs_) { + dName("li"); + + dGPR(_Rt_); sep; + dImm(); + + SetRegS(_Rt_, _sIm_); + + d->Comment("Load immediate"); + } else { + dName("addiu"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_) { + Invalidate(_Rt_); + } else { + SetRegS(_Rt_, GetRegS(_Rs_) + _sIm_); + } + + d->Comment("Add immediate"); + } +) + +MakeDisF(disANDI, + dName("andi"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_) { + Invalidate(_Rt_); + } else { + SetReg(_Rt_, GetReg(_Rs_) & _Im_); + } + + d->Comment("And immediate"); +) + +MakeDisF(disORI, + if (!_Rs_) { + dName("liu"); + + dGPR(_Rt_); sep; + dImm(); + SetReg(_Rt_, _Im_); + + d->Comment("Load immediate without sign extension"); + } else { + dName("ori"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_)) { + Invalidate(_Rt_); + } else { + SetReg(_Rt_, GetReg(_Rs_) | _Im_); + } + d->Comment("Or immediate"); + } +) + +MakeDisF(disSLTI, + dName("slti"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_)) { + Invalidate(_Rt_); + } else { + SetReg(_Rt_, GetRegS(_Rs_) < _sIm_ ? 1 : 0); + } + + d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTIU, + dName("sltiu"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_)) { + Invalidate(_Rt_); + } else { + SetReg(_Rt_, GetReg(_Rs_) < _Im_ ? 1 : 0); + } + + d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (unsigned)"); +) + +MakeDisF(disXORI, + dName("xori"); + + dGPR(_Rt_); sep; + if (_Rt_ != _Rs_) { + dGPR(_Rs_); sep; + } + dImm(); + + if (isInvalid(_Rs_)) { + Invalidate(_Rt_); + } else { + SetReg(_Rt_, GetReg(_Rs_) ^ _Im_); + } + + d->Comment("XOr immediate"); +) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +MakeDisF(disADD, + dName("add"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rs_) + GetRegS(_Rt_)); + } + + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); +) + +MakeDisF(disADDU, + if (!_Rt_) { + dName("move"); + + dGPR(_Rd_); sep; + dGPR(_Rs_); + if (_Rs_) { + if (isInvalid(_Rs_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, _Rs_); + } + } else { + SetReg(_Rd_, 0); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_]); + } else { + dName("addu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rs_) + GetRegS(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); + } +) + +MakeDisF(disAND, + dName("and"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rs_) & GetReg(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]); +) + +MakeDisF(disNOR, + dName("nor"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, ~(GetReg(_Rs_) | GetReg(_Rt_))); + } + d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " | " + registers[_Rt_] + ")"); +) + +MakeDisF(disOR, + dName("or"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rs_) | GetReg(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]); +) + +MakeDisF(disSLT, + dName("slt"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetRegS(_Rs_) < GetRegS(_Rt_) ? 1 : 0); + } + d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTU, + dName("sltu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rs_) < GetReg(_Rt_) ? 1 : 0); + } + d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (unsigned)"); +) + +MakeDisF(disSUB, + dName("sub"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rs_) - GetRegS(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disSUBU, + dName("subu"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rs_) - GetRegS(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disXOR, + dName("xor"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rs_) { + dGPR(_Rs_); sep; + } + dGPR(_Rt_); + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rs_) ^ GetReg(_Rt_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " ^ " + registers[_Rt_]); +) + +/********************************************************* +* Register arithmetic & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +MakeDisF(disDIV, + dName("div"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(Rhi); + Invalidate(Rlo); + } else { + int32 lo, hi, rs, rt; + rs = GetRegS(_Rs_); + rt = GetRegS(_Rt_); + lo = rs / rt; + hi = rs % rt; + SetRegS(Rlo, lo); + SetRegS(Rhi, hi); + } + String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; + String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; + + d->Comment("lo = " + c1 + "; hi = " + c2); +) + +MakeDisF(disDIVU, + dName("divu"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(Rhi); + Invalidate(Rlo); + } else { + Uint32 lo, hi, rs, rt; + rs = GetReg(_Rs_); + rt = GetReg(_Rt_); + lo = rs / rt; + hi = rs % rt; + SetReg(Rlo, lo); + SetReg(Rhi, hi); + } + String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; + String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; + + d->Comment("lo = " + c1 + "; hi = " + c2); +) + +MakeDisF(disMULT, + dName("mult"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(Rhi); + Invalidate(Rlo); + } else { + int64 res; + Uint32 lo, hi; + res = ((int64) GetRegS(_Rs_)) * ((int64) GetRegS(_Rt_)); + lo = (Uint32) (((Uint64) res) & 0xffffffffUL); + hi = (Uint32) (((Uint64) res >> 32) & 0xffffffffUL); + SetReg(Rlo, lo); + SetReg(Rhi, hi); + } + + d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +MakeDisF(disMULTU, + dName("multu"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); + + if (isInvalid(_Rs_) || isInvalid(_Rt_)) { + Invalidate(Rhi); + Invalidate(Rlo); + } else { + Uint64 res; + Uint32 lo, hi; + res = ((Uint64) GetReg(_Rs_)) * ((Uint64) GetReg(_Rt_)); + lo = (Uint32) (res & 0xffffffffUL); + hi = (Uint32) ((res >> 32) & 0xffffffffUL); + SetReg(Rlo, lo); + SetReg(Rhi, hi); + } + + d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +MakeDisF(disBGEZ, + dName("bgez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " >= 0"); +) + +MakeDisF(disBGEZAL, + if (_Rs_) { + dName("bgezal"); + + dGPR(_Rs_); sep; + dOffset(); + Call(_Branch_); + d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0"); + } else { + dName("bal"); + + dOffset(); + Call(_Branch_); + d->Comment("Branch and link"); + } +) + +MakeDisF(disBGTZ, + dName("bgtz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " > 0"); +) + +MakeDisF(disBLEZ, + dName("blez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " <= 0"); +) + +MakeDisF(disBLTZ, + dName("bltz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + d->Comment("Branch if " + String(registers[_Rs_]) + " < 0"); +) + +MakeDisF(disBLTZAL, + dName("bltzal"); + + dGPR(_Rs_); sep; + dOffset(); + Call(_Branch_); + d->Comment("Branch and link if " + String(registers[_Rs_]) + " < 0"); +) + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +MakeDisF(disSLL, + if ((!_Rd_) && (!_Rt_)) { + dName("nop"); + if (code) { + dSuspect(); + } + } else { + dName("sll"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + if (isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rt_) << _Sa_); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate"); + } +) + +MakeDisF(disSRA, + dName("sra"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + if (isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rt_) << _Sa_); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)"); +) + +MakeDisF(disSRL, + dName("srl"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dSa(); + if (isInvalid(_Rt_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rt_) << _Sa_); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (logical)"); +) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +MakeDisF(disSLLV, + dName("sllv"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + if (isInvalid(_Rt_) || isInvalid(_Rs_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rt_) << GetReg(_Rs_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]); +) + +MakeDisF(disSRAV, + dName("srav"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + if (isInvalid(_Rt_) || isInvalid(_Rs_)) { + Invalidate(_Rd_); + } else { + SetRegS(_Rd_, GetRegS(_Rt_) >> GetReg(_Rs_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (arithmetic)"); +) + +MakeDisF(disSRLV, + dName("srlv"); + + dGPR(_Rd_); sep; + if (_Rd_ != _Rt_) { + dGPR(_Rt_); sep; + } + dGPR(_Rs_); + if (isInvalid(_Rt_) || isInvalid(_Rs_)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(_Rt_) >> GetReg(_Rs_)); + } + d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (logical)"); +) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +MakeDisF(disLUI, + dName("lui"); + + dGPR(_Rt_); sep; + dImm(); + + SetReg(_Rt_, _Imm_ << 16) + + d->Comment("Load upper immediate"); +) + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMFHI, + dName("mfhi"); + + dGPR(_Rd_); + if (isInvalid(Rhi)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(Rhi)); + } + + d->Comment(String(registers[_Rd_]) + " = hi"); +) + +MakeDisF(disMFLO, + dName("mflo"); + + dGPR(_Rd_); + if (isInvalid(Rlo)) { + Invalidate(_Rd_); + } else { + SetReg(_Rd_, GetReg(Rlo)); + } + + d->Comment(String(registers[_Rd_]) + " = lo"); +) + +/********************************************************* +* Move from GPR to HI/LO * +* Format: OP rd * +*********************************************************/ +MakeDisF(disMTHI, + dName("mthi"); + + dGPR(_Rd_); + if (isInvalid(_Rd_)) { + Invalidate(Rhi); + } else { + SetReg(Rhi, GetReg(_Rd_)); + } + + d->Comment("hi = " + String(registers[_Rd_])); +) + +MakeDisF(disMTLO, + dName("mtlo"); + + dGPR(_Rd_); + if (isInvalid(_Rd_)) { + Invalidate(Rlo); + } else { + SetReg(Rlo, GetReg(_Rd_)); + } + + + d->Comment("lo = " + String(registers[_Rd_])); +) + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +MakeDisF(disBREAK, + dName("break"); + + Stop(pc + 4); + + d->Comment("Stops the machine"); +) +MakeDisF(disRFE, dName("rfe")) + +MakeDisF(disSYSCALL, + int syscall; + dName("syscall"); + syscall = code & 0xfffff; + + Syscall(syscall); + + d->Comment(String("Syscall number ") + syscall); +) + +MakeDisF(disHLE, dName("hle")) + +MakeDisF(disRTPS, dName("rtps")) +MakeDisF(disOP, dName("op")) +MakeDisF(disNCLIP, dName("nclip")) +MakeDisF(disDPCS, dName("dpcs")) +MakeDisF(disINTPL, dName("intpl")) +MakeDisF(disMVMVA, dName("mvmva")) +MakeDisF(disNCDS, dName("ncds")) +MakeDisF(disCDP, dName("cdp")) +MakeDisF(disNCDT, dName("ncdt")) +MakeDisF(disNCCS, dName("nccs")) +MakeDisF(disCC, dName("cc")) +MakeDisF(disNCS, dName("ncs")) +MakeDisF(disNCT, dName("nct")) +MakeDisF(disSQR, dName("sqr")) +MakeDisF(disDCPL, dName("dcpl")) +MakeDisF(disDPCT, dName("dpct")) +MakeDisF(disAVSZ3, dName("avsz3")) +MakeDisF(disAVSZ4, dName("avsz4")) +MakeDisF(disRTPT, dName("rtpt")) +MakeDisF(disGPF, dName("gpf")) +MakeDisF(disGPL, dName("gpl")) +MakeDisF(disNCCT, dName("ncct")) + +MakeDisF(disMFC2, dName("mfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disCFC2, dName("cfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disMTC2, dName("mtc2"); dGPR(_Rt_);) +MakeDisF(disCTC2, dName("ctc2"); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +MakeDisF(disBEQ, + if ((!_Rt_) && (!_Rs_)) { + dName("b"); + + dOffset(); + Branch(_Branch_); + Stop(pc + 8); + + d->Comment("Branch always"); + } + if (!_Rt_) { + dName("bez"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " == 0"); + } else { + dName("beq"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " == " + registers[_Rt_]); + } +) + +MakeDisF(disBNE, + if (!_Rt_) { + dName("bnz"); + + dGPR(_Rs_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " != 0"); + } else { + dName("bne"); + + dGPR(_Rs_); sep; + dGPR(_Rt_); sep; + dOffset(); + Branch(_Branch_); + + d->Comment(String("Branch if ") + registers[_Rs_] + " != " + registers[_Rt_]); + } +) + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +MakeDisF(disJ, + dName("j"); + + dTarget(); + Jump(_Target_); + Stop(pc + 8); + + d->Comment("Jump always"); +) + +MakeDisF(disJAL, + dName("jal"); + + dTarget(); + Invalidate(Rra); + MarkFunction(_Target_); + + d->Comment("Jump and link (function call)"); +) + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +MakeDisF(disJR, + dName("jr"); + dGPR(_Rs_); + Stop(pc + 8); + + d->Comment("Jump register"); +) + +MakeDisF(disJALR, + dName("jalr"); + + dGPR(_Rs_); + + if ((_Rd_) != Rra) { + sep; dGPR(_Rd_); + } + + Invalidate(_Rd_); + + d->Comment("Jump and link register (function call)"); +) + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ +MakeDisF(disLB, + int width = 8; + dName("lb"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load signed byte"); +) + +MakeDisF(disLBU, + int width = 8; + dName("lbu"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load unsigned byte"); +) + +MakeDisF(disLH, + int width = 16; + dName("lh"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load signed half"); +) + +MakeDisF(disLHU, + int width = 16; + dName("lhu"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load unsigned half"); +) + +MakeDisF(disLW, + int width = 32; + dName("lw"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word"); +) + +MakeDisF(disLWL, + int width = 32; + dName("lwl"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word left"); +) + +MakeDisF(disLWR, + int width = 32; + dName("lwr"); + + dGPR(_Rt_); sep; + dOfB(); + + Invalidate(_Rt_); + d->Comment("Load word right"); +) + +MakeDisF(disLWC2, + int width = 32; + dName("lwc2"); + + dCP0(_Rt_); sep; + dOfB(); +) + +MakeDisF(disSB, + int width = 8; + dName("sb"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store byte"); +) + +MakeDisF(disSH, + int width = 16; + dName("sh"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store half"); +) + +MakeDisF(disSW, + int width = 32; + dName("sw"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word"); +) + +MakeDisF(disSWL, + int width = 32; + dName("swl"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word left"); +) + +MakeDisF(disSWR, + int width = 32; + dName("swr"); + + dGPR(_Rt_); sep; + dOfB(); + d->Comment("Store word right"); +) + +MakeDisF(disSWC2, + int width = 32; + dName("swc2"); + + dGPR(_Rt_); sep; + dOfB(); +) + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +MakeDisF(disMFC0, dName("mfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disMTC0, dName("mtc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) +MakeDisF(disCFC0, dName("cfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disCTC0, dName("ctc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +MakeDisF(disNULL, + dName("*** Bad OP ***"); + dInvalid(); +) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL + disSLL , disNULL , disSRL , disSRA , disSLLV , disNULL , disSRLV , disSRAV , + disJR , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL , disNULL , + disMFHI, disMTHI , disMFLO, disMTLO, disNULL , disNULL , disNULL , disNULL , + disMULT, disMULTU, disDIV , disDIVU, disNULL , disNULL , disNULL , disNULL , + disADD , disADDU , disSUB , disSUBU, disAND , disOR , disXOR , disNOR , + disNULL, disNULL , disSLT , disSLTU, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL , + disNULL, disNULL , disNULL, disNULL, disNULL , disNULL , disNULL , disNULL ,}; + +MakeDisF(disSPECIAL, disR3000A_SPECIAL[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND + disBLTZ , disBGEZ , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL , disNULL , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disBCOND, disR3000A_BCOND[_Rt_](d, code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 + disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disCOP0, disR3000A_COP0[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) + disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, + disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disBASIC, disR3000A_BASIC[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) + disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, + disNULL , disNULL , disNULL , disNULL , disOP , disNULL , disNULL , disNULL, + disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, + disNULL , disNULL , disNULL , disNCCS , disCC , disNULL , disNCS , disNULL, + disNCT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disSQR , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, + disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, + disNULL , disNULL , disNULL , disNULL , disNULL, disGPF , disGPL , disNCCT,}; + +MakeDisF(disCOP2, disR3000A_COP2[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A[] = { + disSPECIAL , disBCOND , disJ , disJAL , disBEQ , disBNE , disBLEZ , disBGTZ , + disADDI , disADDIU , disSLTI , disSLTIU, disANDI, disORI , disXORI , disLUI , + disCOP0 , disNULL , disCOP2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disNULL , disNULL , disNULL, disNULL, disNULL , disNULL , + disLB , disLH , disLWL , disLW , disLBU , disLHU , disLWR , disNULL , + disSB , disSH , disSWL , disSW , disNULL, disNULL, disSWR , disNULL , + disNULL , disNULL , disLWC2 , disNULL , disNULL, disNULL, disNULL , disNULL , + disNULL , disNULL , disSWC2 , disHLE , disNULL, disNULL, disNULL , disNULL ,}; + +//MakeDisFg(disR3000AF, disR3000A[code >> 26](code, pc)) + +void decode(TDis * d, Uint32 pc) { + Uint32 code = d->getmem()->Read32(pc); + disR3000A[code >> 26](d, code, pc); +} |