diff options
Diffstat (limited to 'lib/mips.cpp')
-rw-r--r-- | lib/mips.cpp | 2136 |
1 files changed, 1068 insertions, 1068 deletions
diff --git a/lib/mips.cpp b/lib/mips.cpp index 1378227..05a1201 100644 --- a/lib/mips.cpp +++ b/lib/mips.cpp @@ -1,1068 +1,1068 @@ -/* - * PSX-Tools Bundle Pack - * Copyright (C) 2002-2003 Nicolas "Pixel" Noble - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* $Id: mips.cpp,v 1.3 2004-01-03 15:04:47 pixel Exp $ */ - -#include "mips.h" - -/* Code HIGHLY ripped off^W^W inspired from PCSX. */ - -#if 1 -char * registers[] = { - "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", -}; -#else -char * registers[] = { - "00", "01", "02", "03", "04", "05", "06", "07", - "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", - "10", "11", "12", "13", "14", "15", "16", "17", - "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", -}; -#endif - -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_); } -#if 0 -#define dOfB() { \ - Uint32 pcode = d->getmem()->Read32(pc - 4); \ - if ((((pcode >> 16) & 0x1F) == _Rs_) && ((pcode >> 26) == 0xf)) { \ - Uint32 full; \ - Uint16 lower; \ - int16 slower; \ - lower = _Im_; \ - slower = *((int16 *) &lower); \ - \ - full = ((pcode & 0xffff) << 16) + slower; \ - \ - d->PushOfB(_Rs_, full, width); \ - \ - dMemRefer(full, width); \ - } else { \ - d->PushOfB(_Rs_, _Im_, width); \ - } \ -} -#else -#define dOfB() { \ - d->PushOfB(_Rs_, _Im_, width); \ -} -#endif -#define dOffset() { \ - d->PushOffset(_Branch_); \ -} -// printf(" ; Maybe RefTo %8.8lX", offset); -#define dFull(full) { \ - d->PushFull(full); \ - d->Comment("MaybeRefTo..."); \ -} - -#define sep - -#define dInvalid() { \ - d->SetTag(pc, CODE, false); \ - d->SetTag(pc, STOP, true); \ - d->Invalid(); \ -} - -#define dSuspect() { \ - d->Suspect(); \ - d->Comment("Suspect!"); \ -} -#if 0 // with OfB... -// printf(" ; RefTo %8.8lX - %i bits", offset, width); -#define dMemRefer(offset, width) { \ - d->PushMemref(offset, width); \ - d->Comment("RefTo..."); \ -} -#endif - -#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(); - - Invalidate(_Rt_); - - d->Comment("Add immediate"); -) - -MakeDisF(disADDIU, - if (!_Rs_) { - dName("li"); - - dGPR(_Rt_); sep; - dImm(); - - Uint32 full; - int32 sfull; - Uint16 lower; - int16 slower; - lower = _Im_; - slower = *((int16 *) &lower); - - sfull = slower; - full = *((Uint32 *) &sfull); - - SetReg(_Rt_, full); - - d->Comment("Load immediate"); - } else { - Uint32 pcode = d->getmem()->Read32(pc - 4); - if ((((pcode >> 16) & 0x1F) == _Rt_) && (_Rt_ == _Rs_) && ((pcode >> 26) == 0xf)) { - Uint32 full; - Uint16 lower; - int16 slower; - lower = _Im_; - slower = *((int16 *) &lower); - - full = ((pcode & 0xffff) << 16) + slower; - - dName("li"); - dGPR(_Rt_); sep; - dFull(full); - SetReg(_Rt_, full); - d->Comment("Load immediate (aggregate)"); - } else { - dName("addiu"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - d->Comment("Add immediate"); - } - } -) - -MakeDisF(disANDI, - dName("andi"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - 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(); - Invalidate(_Rt_); - d->Comment("Or immediate"); - } -) - -MakeDisF(disSLTI, - dName("slti"); - - dGPR(_Rt_); sep; - if (_Rt_ != _Rs_) { - dGPR(_Rs_); sep; - } - dImm(); - - Invalidate(_Rt_); - - 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(); - - Invalidate(_Rt_); - - 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(); - - Invalidate(_Rt_); - - 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_); - - Invalidate(_Rt_); - - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); -) - -MakeDisF(disADDU, - if (!_Rt_) { - dName("move"); - - dGPR(_Rd_); sep; - dGPR(_Rs_); - if (_Rs_) { - Invalidate(_Rd_); - } 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_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); - } -) - -MakeDisF(disAND, - dName("and"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]); -) - -MakeDisF(disNOR, - dName("nor"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " & " + registers[_Rt_] + ")"); -) - -MakeDisF(disOR, - dName("or"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]); -) - -MakeDisF(disSLT, - dName("slt"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - 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_); - Invalidate(_Rd_); - 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_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); -) - -MakeDisF(disSUBU, - dName("subu"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); -) - -MakeDisF(disXOR, - dName("xor"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rs_) { - dGPR(_Rs_); sep; - } - dGPR(_Rt_); - Invalidate(_Rd_); - 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_); - - 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_); - - d->Comment(String("lo = " ) + registers[_Rs_] + " / " + registers[_Rt_] + "; hi = " + registers[_Rs_] + " % " + registers[_Rt_]); -) - -MakeDisF(disMULT, - dName("mult"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); -) - -MakeDisF(disMULTU, - dName("multu"); - - dGPR(_Rs_); sep; - dGPR(_Rt_); - - 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, - dName("bgezal"); - - dGPR(_Rs_); sep; - dOffset(); - Branch(_Branch_); - d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0"); -) - -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(); - Branch(_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(); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate"); - } -) - -MakeDisF(disSRA, - dName("sra"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dSa(); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)"); -) - -MakeDisF(disSRL, - dName("srl"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dSa(); - Invalidate(_Rd_); - 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_); - Invalidate(_Rd_); - d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]); -) - -MakeDisF(disSRAV, - dName("srav"); - - dGPR(_Rd_); sep; - if (_Rd_ != _Rt_) { - dGPR(_Rt_); sep; - } - dGPR(_Rs_); - Invalidate(_Rd_); - 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_); - Invalidate(_Rd_); - 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(); - - Invalidate(_Rt_); - - d->Comment("Load upper immediate"); -) - -/********************************************************* -* Move from HI/LO to GPR * -* Format: OP rd * -*********************************************************/ -MakeDisF(disMFHI, - dName("mfhi"); - - dGPR(_Rd_); - Invalidate(_Rd_); - - d->Comment(String(registers[_Rd_]) + " = hi"); -) - -MakeDisF(disMFLO, - dName("mflo"); - - dGPR(_Rd_); - Invalidate(_Rd_); - - d->Comment(String(registers[_Rd_]) + " = lo"); -) - -/********************************************************* -* Move from GPR to HI/LO * -* Format: OP rd * -*********************************************************/ -MakeDisF(disMTHI, - dName("mthi"); - - dGPR(_Rd_); - - d->Comment("hi = " + String(registers[_Rd_])); -) - -MakeDisF(disMTLO, - dName("mtlo"); - - dGPR(_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; - - 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); -} +/*
+ * PSX-Tools Bundle Pack
+ * Copyright (C) 2002-2003 Nicolas "Pixel" Noble
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* $Id: mips.cpp,v 1.4 2004-11-27 21:44:48 pixel Exp $ */
+
+#include "mips.h"
+
+/* Code HIGHLY ripped off^W^W inspired from PCSX. */
+
+#if 1
+char * registers[] = {
+ "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",
+};
+#else
+char * registers[] = {
+ "00", "01", "02", "03", "04", "05", "06", "07",
+ "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
+ "10", "11", "12", "13", "14", "15", "16", "17",
+ "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
+};
+#endif
+
+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_); }
+#if 0
+#define dOfB() { \
+ Uint32 pcode = d->getmem()->Read32(pc - 4); \
+ if ((((pcode >> 16) & 0x1F) == _Rs_) && ((pcode >> 26) == 0xf)) { \
+ Uint32 full; \
+ Uint16 lower; \
+ int16 slower; \
+ lower = _Im_; \
+ slower = *((int16 *) &lower); \
+ \
+ full = ((pcode & 0xffff) << 16) + slower; \
+ \
+ d->PushOfB(_Rs_, full, width); \
+ \
+ dMemRefer(full, width); \
+ } else { \
+ d->PushOfB(_Rs_, _Im_, width); \
+ } \
+}
+#else
+#define dOfB() { \
+ d->PushOfB(_Rs_, _Im_, width); \
+}
+#endif
+#define dOffset() { \
+ d->PushOffset(_Branch_); \
+}
+// printf(" ; Maybe RefTo %8.8lX", offset);
+#define dFull(full) { \
+ d->PushFull(full); \
+ d->Comment("MaybeRefTo..."); \
+}
+
+#define sep
+
+#define dInvalid() { \
+ d->SetTag(pc, CODE, false); \
+ d->SetTag(pc, STOP, true); \
+ d->Invalid(); \
+}
+
+#define dSuspect() { \
+ d->Suspect(); \
+ d->Comment("Suspect!"); \
+}
+#if 0 // with OfB...
+// printf(" ; RefTo %8.8lX - %i bits", offset, width);
+#define dMemRefer(offset, width) { \
+ d->PushMemref(offset, width); \
+ d->Comment("RefTo..."); \
+}
+#endif
+
+#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();
+
+ Invalidate(_Rt_);
+
+ d->Comment("Add immediate");
+)
+
+MakeDisF(disADDIU,
+ if (!_Rs_) {
+ dName("li");
+
+ dGPR(_Rt_); sep;
+ dImm();
+
+ Uint32 full;
+ int32 sfull;
+ Uint16 lower;
+ int16 slower;
+ lower = _Im_;
+ slower = *((int16 *) &lower);
+
+ sfull = slower;
+ full = *((Uint32 *) &sfull);
+
+ SetReg(_Rt_, full);
+
+ d->Comment("Load immediate");
+ } else {
+ Uint32 pcode = d->getmem()->Read32(pc - 4);
+ if ((((pcode >> 16) & 0x1F) == _Rt_) && (_Rt_ == _Rs_) && ((pcode >> 26) == 0xf)) {
+ Uint32 full;
+ Uint16 lower;
+ int16 slower;
+ lower = _Im_;
+ slower = *((int16 *) &lower);
+
+ full = ((pcode & 0xffff) << 16) + slower;
+
+ dName("li");
+ dGPR(_Rt_); sep;
+ dFull(full);
+ SetReg(_Rt_, full);
+ d->Comment("Load immediate (aggregate)");
+ } else {
+ dName("addiu");
+
+ dGPR(_Rt_); sep;
+ if (_Rt_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dImm();
+
+ Invalidate(_Rt_);
+
+ d->Comment("Add immediate");
+ }
+ }
+)
+
+MakeDisF(disANDI,
+ dName("andi");
+
+ dGPR(_Rt_); sep;
+ if (_Rt_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dImm();
+
+ Invalidate(_Rt_);
+
+ 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();
+ Invalidate(_Rt_);
+ d->Comment("Or immediate");
+ }
+)
+
+MakeDisF(disSLTI,
+ dName("slti");
+
+ dGPR(_Rt_); sep;
+ if (_Rt_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dImm();
+
+ Invalidate(_Rt_);
+
+ 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();
+
+ Invalidate(_Rt_);
+
+ 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();
+
+ Invalidate(_Rt_);
+
+ 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_);
+
+ Invalidate(_Rt_);
+
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]);
+)
+
+MakeDisF(disADDU,
+ if (!_Rt_) {
+ dName("move");
+
+ dGPR(_Rd_); sep;
+ dGPR(_Rs_);
+ if (_Rs_) {
+ Invalidate(_Rd_);
+ } 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_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]);
+ }
+)
+
+MakeDisF(disAND,
+ dName("and");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]);
+)
+
+MakeDisF(disNOR,
+ dName("nor");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " & " + registers[_Rt_] + ")");
+)
+
+MakeDisF(disOR,
+ dName("or");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]);
+)
+
+MakeDisF(disSLT,
+ dName("slt");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ 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_);
+ Invalidate(_Rd_);
+ 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_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]);
+)
+
+MakeDisF(disSUBU,
+ dName("subu");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]);
+)
+
+MakeDisF(disXOR,
+ dName("xor");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rs_) {
+ dGPR(_Rs_); sep;
+ }
+ dGPR(_Rt_);
+ Invalidate(_Rd_);
+ 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_);
+
+ 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_);
+
+ d->Comment(String("lo = " ) + registers[_Rs_] + " / " + registers[_Rt_] + "; hi = " + registers[_Rs_] + " % " + registers[_Rt_]);
+)
+
+MakeDisF(disMULT,
+ dName("mult");
+
+ dGPR(_Rs_); sep;
+ dGPR(_Rt_);
+
+ d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]);
+)
+
+MakeDisF(disMULTU,
+ dName("multu");
+
+ dGPR(_Rs_); sep;
+ dGPR(_Rt_);
+
+ 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,
+ dName("bgezal");
+
+ dGPR(_Rs_); sep;
+ dOffset();
+ Branch(_Branch_);
+ d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0");
+)
+
+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();
+ Branch(_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();
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate");
+ }
+)
+
+MakeDisF(disSRA,
+ dName("sra");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rt_) {
+ dGPR(_Rt_); sep;
+ }
+ dSa();
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)");
+)
+
+MakeDisF(disSRL,
+ dName("srl");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rt_) {
+ dGPR(_Rt_); sep;
+ }
+ dSa();
+ Invalidate(_Rd_);
+ 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_);
+ Invalidate(_Rd_);
+ d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]);
+)
+
+MakeDisF(disSRAV,
+ dName("srav");
+
+ dGPR(_Rd_); sep;
+ if (_Rd_ != _Rt_) {
+ dGPR(_Rt_); sep;
+ }
+ dGPR(_Rs_);
+ Invalidate(_Rd_);
+ 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_);
+ Invalidate(_Rd_);
+ 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();
+
+ Invalidate(_Rt_);
+
+ d->Comment("Load upper immediate");
+)
+
+/*********************************************************
+* Move from HI/LO to GPR *
+* Format: OP rd *
+*********************************************************/
+MakeDisF(disMFHI,
+ dName("mfhi");
+
+ dGPR(_Rd_);
+ Invalidate(_Rd_);
+
+ d->Comment(String(registers[_Rd_]) + " = hi");
+)
+
+MakeDisF(disMFLO,
+ dName("mflo");
+
+ dGPR(_Rd_);
+ Invalidate(_Rd_);
+
+ d->Comment(String(registers[_Rd_]) + " = lo");
+)
+
+/*********************************************************
+* Move from GPR to HI/LO *
+* Format: OP rd *
+*********************************************************/
+MakeDisF(disMTHI,
+ dName("mthi");
+
+ dGPR(_Rd_);
+
+ d->Comment("hi = " + String(registers[_Rd_]));
+)
+
+MakeDisF(disMTLO,
+ dName("mtlo");
+
+ dGPR(_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;
+
+ 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);
+}
|