/* * 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); }