diff options
author | pixel <pixel> | 2004-11-27 21:44:44 +0000 |
---|---|---|
committer | pixel <pixel> | 2004-11-27 21:44:44 +0000 |
commit | d38e80ee04afe582e70150d3884e56c05f3fd7a8 (patch) | |
tree | f2627c50fa22aea89447e8406ac418eb68650d3d /lib/mips.cpp | |
parent | 50f0dd331f8168fb5b2cd60c70178fad627b7fb6 (diff) |
Large dos2unix commit...
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 05a1201..3a9a8f9 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.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);
-}
+/* + * 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.5 2004-11-27 21:47:56 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); +} |