summaryrefslogtreecommitdiff
path: root/lib/mips.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mips.cpp')
-rw-r--r--lib/mips.cpp2136
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);
+}