Files
ppsspp/Core/MIPS/MIPSTables.cpp
T
Unknown W. Brackets de2df87758 Make interpreter call Advance() the same as jit.
Probably makes more sense anyway, since the first events will be
more correctly timed, like savestates, sound, etc.
2013-01-21 23:16:23 -08:00

1175 lines
38 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "MIPSTables.h"
#include "MIPS.h"
#include "MIPSDis.h"
#include "MIPSDisVFPU.h"
#include "MIPSInt.h"
#include "MIPSIntVFPU.h"
#include "MIPSCodeUtils.h"
#include "../../Core/CoreTiming.h"
#include "../Debugger/Breakpoints.h"
#include "JitCommon/JitCommon.h"
enum MipsEncoding
{
Imme,
Spec,
Spe2,
Spe3,
RegI,
Cop0,
Cop0CO,
Cop1,
Cop1BC,
Cop2,
Cop2BC2,
Cop2Rese,
VFPU0,
VFPU1,
VFPU3,
VFPU4Jump,
VFPU7,
VFPU4,
VFPU5,
VFPU6,
VFPUMatrix1,
VFPU9,
ALLEGREX0,
Emu,
Rese,
NumEncodings
};
struct MIPSInstruction
{
int altEncoding;
const char *name;
MIPSComp::MIPSCompileFunc compile;
#ifndef FINAL
MIPSDisFunc disasm;
#endif
MIPSInterpretFunc interpret;
//MIPSInstructionInfo information;
u32 flags;
};
#define INVALID {-2}
#define N(a) a
#ifndef FINAL
#define ENCODING(a) {a}
#define INSTR(name, comp, dis, inter, flags) {-1, N(name), comp, dis, inter, flags}
#else
#define ENCODING(a) {a}
#define INSTR(name, comp, dis, inter, flags) {-1, comp, inter, flags}
#endif
using namespace MIPSDis;
using namespace MIPSInt;
using namespace MIPSComp;
//regregreg instructions
const MIPSInstruction tableImmediate[64] = //xxxxxx .....
{
//0
ENCODING(Spec),
ENCODING(RegI),
INSTR("j", &Jit::Comp_Jump, Dis_JumpType, Int_JumpType, IS_JUMP|IN_IMM26|DELAYSLOT),
INSTR("jal", &Jit::Comp_Jump, Dis_JumpType, Int_JumpType, IS_JUMP|IN_IMM26|OUT_RA|DELAYSLOT),
INSTR("beq", &Jit::Comp_RelBranch, Dis_RelBranch2, Int_RelBranch, IS_CONDBRANCH|IN_RS|IN_RT|DELAYSLOT),
INSTR("bne", &Jit::Comp_RelBranch, Dis_RelBranch2, Int_RelBranch, IS_CONDBRANCH|IN_RS|IN_RT|DELAYSLOT),
INSTR("blez", &Jit::Comp_RelBranch, Dis_RelBranch, Int_RelBranch, IS_CONDBRANCH|IN_RS|DELAYSLOT),
INSTR("bgtz", &Jit::Comp_RelBranch, Dis_RelBranch, Int_RelBranch, IS_CONDBRANCH|IN_RS|DELAYSLOT),
//8
INSTR("addi", &Jit::Comp_IType, Dis_addi, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("addiu", &Jit::Comp_IType, Dis_addi, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("slti", &Jit::Comp_IType, Dis_IType, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("sltiu", &Jit::Comp_IType, Dis_IType, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("andi", &Jit::Comp_IType, Dis_IType, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("ori", &Jit::Comp_IType, Dis_ori, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("xori", &Jit::Comp_IType, Dis_IType, Int_IType, IN_RS|IN_IMM16|OUT_RT),
INSTR("lui", &Jit::Comp_IType, Dis_IType1, Int_IType, IN_IMM16|OUT_RT),
//16
ENCODING(Cop0), //cop0
ENCODING(Cop1), //cop1
ENCODING(Cop2), //cop2
INVALID, //copU
INSTR("beql", &Jit::Comp_RelBranch, Dis_RelBranch2, Int_RelBranch, IS_CONDBRANCH|IN_RS|IN_RT|DELAYSLOT|LIKELY), //L = likely
INSTR("bnel", &Jit::Comp_RelBranch, Dis_RelBranch2, Int_RelBranch, IS_CONDBRANCH|IN_RS|IN_RT|DELAYSLOT|LIKELY),
INSTR("blezl", &Jit::Comp_RelBranch, Dis_RelBranch, Int_RelBranch, IS_CONDBRANCH|IN_RS|DELAYSLOT|LIKELY),
INSTR("bgtzl", &Jit::Comp_RelBranch, Dis_RelBranch, Int_RelBranch, IS_CONDBRANCH|IN_RS|DELAYSLOT|LIKELY),
//24
{VFPU0},
{VFPU1},
{Emu},
{VFPU3},
{Spe2},//special2
{-2}, //, "jalx", 0, Dis_JumpType, Int_JumpType},
{-2},
{Spe3},//special3
//32
INSTR("lb", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lh", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lwl", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lw", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lbu", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lhu", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
INSTR("lwr", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT),
{-2},
//40
INSTR("sb", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM),
INSTR("sh", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM),
INSTR("swl", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM),
INSTR("sw", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM),
{-2},
{-2},
INSTR("swr", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM),
INSTR("cache", &Jit::Comp_Generic, Dis_Generic, Int_Cache, 0),
//48
INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0),
INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_RT|IN_RS_ADDR),
INSTR("lv.s", &Jit::Comp_Generic, Dis_SV, Int_SV, IS_VFPU),
{-2}, // HIT THIS IN WIPEOUT
{VFPU4Jump},
INSTR("lv", &Jit::Comp_Generic, Dis_SVLRQ, Int_SVQ, IS_VFPU),
INSTR("lv.q", &Jit::Comp_Generic, Dis_SVQ, Int_SVQ, IS_VFPU), //copU
{VFPU5},
//56
INSTR("sc", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, 0),
INSTR("swc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, 0), //copU
INSTR("sv.s", &Jit::Comp_Generic, Dis_SV, Int_SV,IS_VFPU),
{-2},
//60
{VFPU6},
INSTR("sv", &Jit::Comp_Generic, Dis_SVLRQ, Int_SVQ, IS_VFPU), //copU
INSTR("sv.q", &Jit::Comp_Generic, Dis_SVQ, Int_SVQ, IS_VFPU),
INSTR("vflush", &Jit::Comp_Generic, Dis_Vflush, Int_Vflush, IS_VFPU),
};
const MIPSInstruction tableSpecial[64] = /// 000000 ...... ...... .......... xxxxxx
{
INSTR("sll", &Jit::Comp_ShiftType, Dis_ShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_SA),
{-2}, // copu
INSTR("srl", &Jit::Comp_ShiftType, Dis_ShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_SA),
INSTR("sra", &Jit::Comp_ShiftType, Dis_ShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_SA),
INSTR("sllv", &Jit::Comp_ShiftType, Dis_VarShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_RS_SHIFT),
{-2},
INSTR("srlv", &Jit::Comp_ShiftType, Dis_VarShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_RS_SHIFT),
INSTR("srav", &Jit::Comp_ShiftType, Dis_VarShiftType, Int_ShiftType, OUT_RD|IN_RT|IN_RS_SHIFT),
//8
INSTR("jr", &Jit::Comp_JumpReg, Dis_JumpRegType, Int_JumpRegType, DELAYSLOT),
INSTR("jalr", &Jit::Comp_JumpReg, Dis_JumpRegType, Int_JumpRegType, DELAYSLOT),
INSTR("movz", &Jit::Comp_RType3, Dis_RType3, Int_RType3, OUT_RD|IN_RS|IN_RT),
INSTR("movn", &Jit::Comp_RType3, Dis_RType3, Int_RType3, OUT_RD|IN_RS|IN_RT),
INSTR("syscall", &Jit::Comp_Syscall, Dis_Syscall, Int_Syscall,0),
INSTR("break", &Jit::Comp_Generic, Dis_Generic, Int_Break, 0),
{-2},
INSTR("sync", &Jit::Comp_Generic, Dis_Generic, Int_Sync, 0),
//16
INSTR("mfhi", &Jit::Comp_Generic, Dis_FromHiloTransfer, Int_MulDivType, OUT_RD|IN_OTHER),
INSTR("mthi", &Jit::Comp_Generic, Dis_ToHiloTransfer, Int_MulDivType, IN_RS|OUT_OTHER),
INSTR("mflo", &Jit::Comp_Generic, Dis_FromHiloTransfer, Int_MulDivType, OUT_RD|IN_OTHER),
INSTR("mtlo", &Jit::Comp_Generic, Dis_ToHiloTransfer, Int_MulDivType, IN_RS|OUT_OTHER),
{-2},
{-2},
INSTR("clz", &Jit::Comp_Generic, Dis_RType2, Int_RType2, OUT_RD|IN_RS|IN_RT),
INSTR("clo", &Jit::Comp_Generic, Dis_RType2, Int_RType2, OUT_RD|IN_RS|IN_RT),
//24
INSTR("mult", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("multu", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("div", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("divu", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("madd", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("maddu", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
{-2},
{-2},
//32
INSTR("add", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("addu", &Jit::Comp_RType3, Dis_addu, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("sub", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("subu", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("and", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("or", &Jit::Comp_RType3, Dis_addu, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("xor", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("nor", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
//40
{-2},
{-2},
INSTR("slt", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("sltu", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("max", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("min", &Jit::Comp_RType3, Dis_RType3, Int_RType3,IN_RS|IN_RT|OUT_RD),
INSTR("msub", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
INSTR("msubu", &Jit::Comp_Generic, Dis_MulDivType, Int_MulDivType, IN_RS|IN_RT|OUT_OTHER),
//48
INSTR("tge", &Jit::Comp_Generic, Dis_RType3, 0, 0),
INSTR("tgeu", &Jit::Comp_Generic, Dis_RType3, 0, 0),
INSTR("tlt", &Jit::Comp_Generic, Dis_RType3, 0, 0),
INSTR("tltu", &Jit::Comp_Generic, Dis_RType3, 0, 0),
INSTR("teq", &Jit::Comp_Generic, Dis_RType3, 0, 0),
{-2},
INSTR("tne", &Jit::Comp_Generic, Dis_RType3, 0, 0),
{-2},
//56
{-2}, {-2}, {-2}, {-2}, {-2},
{-2},
{-2},
{-2},
};
const MIPSInstruction tableSpecial2[64] =
{
INSTR("add.s", &Jit::Comp_FPU3op, Dis_FPU3op, Int_FPU3op, 0),
INSTR("sub.s", &Jit::Comp_FPU3op, Dis_FPU3op, Int_FPU3op, 0),
INSTR("mul.s", &Jit::Comp_FPU3op, Dis_FPU3op, Int_FPU3op, 0),
INSTR("div.s", &Jit::Comp_FPU3op, Dis_FPU3op, Int_FPU3op, 0),
INSTR("sqrt.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("abs.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("mov.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("neg.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
//8
{-2}, {-2}, {-2}, {-2},
INSTR("round.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("trunc.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("ceil.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
INSTR("floor.w.s", &Jit::Comp_FPU2op, Dis_FPU2op, Int_FPU2op, 0),
//16
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//24
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//32
INSTR("cvt.s.w", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
{-2}, {-2}, {-2},
//36
INSTR("cvt.w.s", &Jit::Comp_Generic, Dis_FPU2op, Int_FPU2op, 0),
{-2},
INSTR("dis.int", &Jit::Comp_Generic, Dis_Generic, Int_Interrupt, 0),
{-2},
//40
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//48
INSTR("c.f", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.un", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.eq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ueq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.olt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ult", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ole", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ule", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.sf", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ngle",&Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.seq", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ngl", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.lt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.nge", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.le", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
INSTR("c.ngt", &Jit::Comp_Generic, Dis_FPUComp, Int_FPUComp, OUT_FPUFLAG),
};
const MIPSInstruction tableSpecial3[64] =
{
INSTR("ext", &Jit::Comp_Generic, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
{-2},
{-2},
{-2},
INSTR("ins", &Jit::Comp_Generic, Dis_Special3, Int_Special3, IN_RS|OUT_RT),
{-2},
{-2},
{-2},
//8
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//16
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//32
{ALLEGREX0},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//40
{ALLEGREX0},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2},
INSTR("rdhwr", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2}, {-2}, {-2}, {-2},
};
const MIPSInstruction tableRegImm[32] =
{
INSTR("bltz", &Jit::Comp_RelBranchRI, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|DELAYSLOT),
INSTR("bgez", &Jit::Comp_RelBranchRI, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|DELAYSLOT),
INSTR("bltzl", &Jit::Comp_RelBranchRI, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|DELAYSLOT|LIKELY),
INSTR("bgezl", &Jit::Comp_RelBranchRI, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|DELAYSLOT|LIKELY),
{-2},
{-2},
{-2},
{-2},
INSTR("tgei", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("tgeiu", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("tlti", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("tltiu", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("teqi", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
INSTR("tnei", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
INSTR("bltzal", &Jit::Comp_Generic, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|OUT_RA|DELAYSLOT),
INSTR("bgezal", &Jit::Comp_Generic, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|OUT_RA|DELAYSLOT),
INSTR("bltzall", &Jit::Comp_Generic, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|OUT_RA|DELAYSLOT|LIKELY), //L = likely
INSTR("bgezall", &Jit::Comp_Generic, Dis_RelBranch, Int_RelBranchRI, IS_CONDBRANCH|IN_RS|OUT_RA|DELAYSLOT|LIKELY),
{-2},
{-2},
{-2},
{-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
INSTR("synci", &Jit::Comp_Generic, Dis_Generic, 0, 0),
};
const MIPSInstruction tableCop2[32] =
{
INSTR("mfc2", &Jit::Comp_Generic, Dis_Generic, 0, OUT_RT),
{-2},
INSTR("cfc2", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("mfv", &Jit::Comp_Generic, Dis_Mftv, Int_Mftv, 0),
INSTR("mtc2", &Jit::Comp_Generic, Dis_Generic, 0, IN_RT),
{-2},
INSTR("ctc2", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("mtv", &Jit::Comp_Generic, Dis_Mftv, Int_Mftv, 0),
{Cop2BC2},
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("??", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
};
const MIPSInstruction tableCop2BC2[4] =
{
INSTR("bvf", &Jit::Comp_VBranch, Dis_VBranch, Int_VBranch, IS_CONDBRANCH|DELAYSLOT),
INSTR("bvt", &Jit::Comp_VBranch, Dis_VBranch, Int_VBranch, IS_CONDBRANCH|DELAYSLOT),
INSTR("bvfl", &Jit::Comp_VBranch, Dis_VBranch, Int_VBranch, IS_CONDBRANCH|DELAYSLOT|LIKELY),
INSTR("bvtl", &Jit::Comp_VBranch, Dis_VBranch, Int_VBranch, IS_CONDBRANCH|DELAYSLOT|LIKELY),
};
const MIPSInstruction tableCop0[32] =
{
INSTR("mfc0", &Jit::Comp_Generic, Dis_Generic, 0, OUT_RT),
{-2},
{-2},
{-2},
INSTR("mtc0", &Jit::Comp_Generic, Dis_Generic, 0, IN_RT),
{-2},
{-2},
{-2},
{-2},
{-2},
INSTR("rdpgpr", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("mfmc0", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
{-2},
INSTR("wrpgpr", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},
{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},{Cop0CO},
};
//we won't encounter these since we only do user mode emulation
const MIPSInstruction tableCop0CO[64] =
{
{-2},
INSTR("tlbr", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("tlbwi", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
{-2},
{-2},
INSTR("tlbwr", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2},
INSTR("tlbp", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
INSTR("eret", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("iack", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2}, {-2}, {-2}, {-2}, {-2},
INSTR("deret", &Jit::Comp_Generic, Dis_Generic, 0, 0),
INSTR("wait", &Jit::Comp_Generic, Dis_Generic, 0, 0),
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
};
const MIPSInstruction tableCop1[32] =
{
INSTR("mfc1",&Jit::Comp_mxc1, Dis_mxc1,Int_mxc1, OUT_RT),
{-2},
INSTR("cfc1",&Jit::Comp_mxc1, Dis_mxc1,Int_mxc1, 0),
{-2},
INSTR("mtc1",&Jit::Comp_mxc1, Dis_mxc1,Int_mxc1, IN_RT),
{-2},
INSTR("ctc1",&Jit::Comp_mxc1, Dis_mxc1,Int_mxc1, 0),
{-2},
{Cop1BC}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
{Spe2}, {-2}, {-2}, {-2},
{Spe2}, {-2}, {-2}, {-2},
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
};
const MIPSInstruction tableCop1BC[32] =
{
{-1,"bc1f", &Jit::Comp_FPUBranch, Dis_FPUBranch, Int_FPUBranch, IS_CONDBRANCH|IN_FPUFLAG|DELAYSLOT},
{-1,"bc1t", &Jit::Comp_FPUBranch, Dis_FPUBranch, Int_FPUBranch, IS_CONDBRANCH|IN_FPUFLAG|DELAYSLOT},
{-1,"bc1fl", &Jit::Comp_FPUBranch, Dis_FPUBranch, Int_FPUBranch, IS_CONDBRANCH|IN_FPUFLAG|DELAYSLOT|LIKELY},
{-1,"bc1tl", &Jit::Comp_FPUBranch, Dis_FPUBranch, Int_FPUBranch, IS_CONDBRANCH|IN_FPUFLAG|DELAYSLOT|LIKELY},
{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
};
const MIPSInstruction tableVFPU0[8] =
{
INSTR("vadd",&Jit::Comp_Generic, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
INSTR("vsub",&Jit::Comp_Generic, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
INSTR("vsbn",&Jit::Comp_Generic, Dis_VectorSet3, 0, IS_VFPU),
{-2}, {-2}, {-2}, {-2},
INSTR("vdiv",&Jit::Comp_Generic, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
};
const MIPSInstruction tableVFPU1[8] =
{
INSTR("vmul",&Jit::Comp_Generic, Dis_VectorSet3, Int_VecDo3, IS_VFPU),
INSTR("vdot",&Jit::Comp_Generic, Dis_VectorDot, Int_VDot, IS_VFPU),
INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU),
{-2},
INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU),
INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU),
INSTR("vdet",&Jit::Comp_Generic, Dis_Generic, Int_Vdet, IS_VFPU),
{-2},
};
const MIPSInstruction tableVFPU3[8] = //011011 xxx
{
INSTR("vcmp",&Jit::Comp_Generic, Dis_Vcmp, Int_Vcmp, IS_VFPU),
{-2},
INSTR("vmin",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU),
INSTR("vmax",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vminmax, IS_VFPU),
{-2},
INSTR("vscmp",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vscmp, IS_VFPU),
INSTR("vsge",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vsge, IS_VFPU),
INSTR("vslt",&Jit::Comp_Generic, Dis_VectorSet3, Int_Vslt, IS_VFPU),
};
const MIPSInstruction tableVFPU4Jump[32] = //110100 xxxxx
{
{VFPU4},
{VFPU7},
{VFPU9},
INSTR("vcst", &Jit::Comp_Generic, Dis_Vcst, Int_Vcst, IS_VFPU),
{-2},{-2},{-2},{-2},
//8
{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},
//16
INSTR("vf2in", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
INSTR("vf2iz", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
INSTR("vf2iu", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
INSTR("vf2id", &Jit::Comp_Generic, Dis_Vf2i, Int_Vf2i, IS_VFPU),
//20
INSTR("vi2f", &Jit::Comp_Generic, Dis_Vf2i, Int_Vi2f, IS_VFPU),
INSTR("vcmov", &Jit::Comp_Generic, Dis_Vcmov,Int_Vcmov,IS_VFPU),
{-2},
{-2},
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
INSTR("vwbn.s", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
};
const MIPSInstruction tableVFPU7[32] =
{
INSTR("vrnds", &Jit::Comp_Generic, Dis_Generic, Int_Vrnds, IS_VFPU),
INSTR("vrndi", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
INSTR("vrndf1", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
INSTR("vrndf2", &Jit::Comp_Generic, Dis_Generic, Int_VrndX, IS_VFPU),
{-2},{-2},{-2},{-2},
//8
{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},
//16
{-2},
{-2},
INSTR("vf2h", &Jit::Comp_Generic, Dis_Generic, Int_Vf2h, IS_VFPU),
INSTR("vh2f", &Jit::Comp_Generic, Dis_Generic, Int_Vh2f, IS_VFPU),
{-2},
{-2},
{-2},
INSTR("vlgb", &Jit::Comp_Generic, Dis_Generic, 0, IS_VFPU),
//24
INSTR("vuc2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU), // Seen in BraveStory, initialization 110100 00001110000 000 0001 0000 0000
INSTR("vc2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU),
INSTR("vus2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU),
INSTR("vs2i", &Jit::Comp_Generic, Dis_Vs2i, Int_Vx2i, IS_VFPU),
INSTR("vi2uc", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
INSTR("vi2c", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
INSTR("vi2us", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
INSTR("vi2s", &Jit::Comp_Generic, Dis_Vi2x, Int_Vi2x, IS_VFPU),
};
// 110100 00000 10100 0000000000000000
// 110100 00000 10111 0000000000000000
const MIPSInstruction tableVFPU4[32] = //110100 00000 xxxxx
{
INSTR("vmov", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
INSTR("vabs", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
INSTR("vneg", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
INSTR("vidt", &Jit::Comp_Generic, Dis_VectorSet1, Int_Vidt,IS_VFPU),
INSTR("vsat0", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vsat1", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vzero", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU),
INSTR("vone", &Jit::Comp_Generic, Dis_VectorSet1, Int_VVectorInit, IS_VFPU),
//8
{-2},{-2},{-2},{-2},{-2},{-2},{-2},{-2},
//16
INSTR("vrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vrsq", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vcos", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vexp2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vlog2", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vsqrt", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
INSTR("vasin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
//24
INSTR("vnrcp", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
{-2},
INSTR("vnsin", &Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op,IS_VFPU),
{-2},
INSTR("vrexp2",&Jit::Comp_Generic, Dis_VectorSet2, Int_VV2Op, IS_VFPU),
{-2},{-2},{-2},
//32
};
MIPSInstruction tableVFPU5[8] = //110111 xxx
{
INSTR("vpfxs",&Jit::Comp_Generic, Dis_VPFXST, Int_VPFX, IS_VFPU),
INSTR("vpfxs",&Jit::Comp_Generic, Dis_VPFXST, Int_VPFX, IS_VFPU),
INSTR("vpfxt",&Jit::Comp_Generic, Dis_VPFXST, Int_VPFX, IS_VFPU),
INSTR("vpfxt",&Jit::Comp_Generic, Dis_VPFXST, Int_VPFX, IS_VFPU),
INSTR("vpfxd", &Jit::Comp_Generic, Dis_VPFXD, Int_VPFX, IS_VFPU),
INSTR("vpfxd", &Jit::Comp_Generic, Dis_VPFXD, Int_VPFX, IS_VFPU),
INSTR("viim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU),
INSTR("vfim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU),
};
const MIPSInstruction tableVFPU6[32] = //111100 xxx
{
//0
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
INSTR("vmmul",&Jit::Comp_Generic, Dis_MatrixMult, Int_Vmmul, IS_VFPU),
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm2",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
//8
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm3",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
INSTR("v(h)tfm4",&Jit::Comp_Generic, Dis_Vtfm, Int_Vtfm, IS_VFPU),
//16
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
INSTR("vmscl",&Jit::Comp_Generic, Dis_Generic, Int_Vmscl, IS_VFPU),
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
INSTR("vcrsp.t/vqmul.q",&Jit::Comp_Generic, Dis_CrossQuat, Int_CrossQuat, IS_VFPU),
//24
{-2},
{-2},
{-2},
{-2},
{VFPUMatrix1},
INSTR("vrot",&Jit::Comp_Generic, Dis_VRot, Int_Vrot, IS_VFPU),
{-2},
{-2},
};
const MIPSInstruction tableVFPUMatrixSet1[16] = //111100 11100 0xxxx (rm x is 16)
{
INSTR("vmmov",&Jit::Comp_Generic, Dis_MatrixSet2, Int_Vmmov, IS_VFPU),
{-2},
{-2},
INSTR("vmidt",&Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
{-2},
{-2},
INSTR("vmzero", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
INSTR("vmone", &Jit::Comp_Generic, Dis_MatrixSet1, Int_VMatrixInit, IS_VFPU),
{-2},{-2},{-2},{-2},
{-2},{-2},{-2},{-2},
};
const MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx
{
INSTR("vsrt1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt1, IS_VFPU),
INSTR("vsrt2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt2, IS_VFPU),
INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU),
INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU),
//4
INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU), // one's complement
INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU),
INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU),
INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU),
//8
INSTR("vsrt3", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt3, IS_VFPU),
INSTR("vsrt4", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt4, IS_VFPU),
INSTR("vsgn", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsgn, IS_VFPU),
{-2},
//12
{-2},
{-2},
{-2},
{-2},
//16
INSTR("vmfvc", &Jit::Comp_Generic, Dis_Generic, Int_Vmfvc, IS_VFPU),
INSTR("vmtvc", &Jit::Comp_Generic, Dis_Generic, Int_Vmtvc, IS_VFPU),
{-2},
{-2},
//20
{-2},{-2},{-2},{-2},
//24
{-2},
INSTR("vt4444", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU),
INSTR("vt5551", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU),
INSTR("vt5650", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU),
//28
{-2},{-2},{-2},{-2},
};
const MIPSInstruction tableALLEGREX0[32] = //111111
{
{-2},
{-2},
INSTR("wsbh",&Jit::Comp_Generic, Dis_Allegrex2,Int_Allegrex2,0),
INSTR("wsbw",&Jit::Comp_Generic, Dis_Allegrex2,Int_Allegrex2,0),
{-2}, {-2}, {-2}, {-2},
//8
{-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2}, {-2},
//16
INSTR("seb", &Jit::Comp_Allegrex, Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
{-2},
{-2},
{-2},
//20
INSTR("bitrev",&Jit::Comp_Generic, Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
{-2},
{-2},
{-2},
//24
INSTR("seh", &Jit::Comp_Allegrex, Dis_Allegrex,Int_Allegrex, IN_RT|OUT_RD),
{-2},
{-2},
{-2},
//28
{-2},
{-2},
{-2},
{-2},
};
const MIPSInstruction tableEMU[4] =
{
INSTR("RUNBLOCK",&Jit::Comp_RunBlock,Dis_Emuhack,Int_Emuhack, 0xFFFFFFFF),
INSTR("RetKrnl", 0,Dis_Emuhack,Int_Emuhack, 0),
{-2},
{-2},
};
const int encodingBits[NumEncodings][2] =
{
{26, 6}, //IMME
{0, 6}, //Special
{0, 6}, //special2
{0, 6}, //special3
{16, 5}, //RegImm
{21, 5}, //Cop0
{0, 6}, //Cop0CO
{21, 5}, //Cop1
{16, 5}, //Cop1BC
{21, 5}, //Cop2
{16, 2}, //Cop2BC2
{0, 0}, //Cop2Rese
{23, 3}, //VFPU0
{23, 3}, //VFPU1
{23, 3}, //VFPU3
{21, 5}, //VFPU4Jump
{16, 5}, //VFPU7
{16, 5}, //VFPU4
{23, 3}, //VFPU5
{21, 5}, //VFPU6
{16, 4}, //VFPUMatrix1
{16, 5}, //VFPU9
{6, 5}, //ALLEGREX0
{24, 2}, //EMUHACK
};
const MIPSInstruction *mipsTables[NumEncodings] =
{
tableImmediate,
tableSpecial,
tableSpecial2,
tableSpecial3,
tableRegImm,
tableCop0,
tableCop0CO,
tableCop1,
tableCop1BC,
tableCop2,
tableCop2BC2,
0,
tableVFPU0, //vfpu0
tableVFPU1, //vfpu1
tableVFPU3, //vfpu3
tableVFPU4Jump,
tableVFPU7, //vfpu4 110100 00001
tableVFPU4, //vfpu4 110100 00000
tableVFPU5, //vfpu5 110111
tableVFPU6, //vfpu6 111100
tableVFPUMatrixSet1,
tableVFPU9,
tableALLEGREX0,
tableEMU
};
//arm encoding table
//const MIPSInstruction mipsinstructions[] =
//{
//{Comp_Unimpl,Dis_Unimpl, Info_NN, 0, 0x601, 0x1FE,0}, //could be used for drec hook :) bits 5-24 plus 0-3 are available, 19 bits are more than enough
// DATA PROCESSING INSTRUCTIONS
// S
// {Comp_AND, Dis_AND, Info_DP, 0, DATAP(0, 0), 0x20F, {0}},
//};
//Todo : generate dispatcher functions from above tables
//instead of this horribly slow abomination
const MIPSInstruction *MIPSGetInstruction(u32 op)
{
MipsEncoding encoding = Imme;
const MIPSInstruction *instr = &tableImmediate[op>>26];
while (instr->altEncoding != -1)
{
const MIPSInstruction *table = mipsTables[encoding];
int mask = ((1<<encodingBits[encoding][1])-1);
int shift = encodingBits[encoding][0];
int subop = (op >> shift) & mask;
instr = &table[subop];
if (encoding == Rese)
return 0; //invalid instruction
if (!instr)
return 0;
if (instr->altEncoding == -2)
{
//ERROR_LOG(CPU, "Invalid instruction %08x in table %i, entry %i", op, (int)encoding, subop);
return 0; //invalid instruction
}
encoding = (MipsEncoding)instr->altEncoding;
}
//alright, we have a valid MIPS instruction!
return instr;
}
void MIPSCompileOp(u32 op)
{
if (op==0)
return;
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr)
{
if (instr->compile)
(MIPSComp::jit->*(instr->compile))(op); // woohoo, member functions pointers!
else
{
ERROR_LOG(CPU,"MIPSCompileOp %08x failed",op);
//MessageBox(0,"ARGH2",0,0);//compile an interpreter call
}
}
else
{
ERROR_LOG(CPU, "MIPSCompileOp: Invalid instruction %08x", op);
}
}
void MIPSDisAsm(u32 op, u32 pc, char *out, bool tabsToSpaces)
{
if (op == 0)
{
//ANDEQ R0,R0,R0 is probably not used for legitimate purposes :P
sprintf(out,"---\t---");
}
else
{
disPC = pc;
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr && instr->disasm) {
instr->disasm(op, out);
if (tabsToSpaces) {
while (*out) {
if (*out == '\t')
*out = ' ';
out++;
}
}
} else {
strcpy(out, "no instruction :(");
//__asm int 3
MIPSGetInstruction(op);
}
}
}
void MIPSInterpret(u32 op) //only for those rare ones
{
//if ((op&0xFFFFF000) == 0xd0110000)
// Crash();
//if (atable[CRUNCH_MIPS_OP(op)].interpret)
// atable[CRUNCH_MIPS_OP(op)].interpret(op);
// else
// _dbg_assert_msg_(MIPS,0,"Trying to interpret instruction that can't be interpreted");
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr && instr->interpret)
instr->interpret(op);
else
{
ERROR_LOG(CPU,"Unknown instruction %08x at %08x", op, currentMIPS->pc);
// Try to disassemble it
char disasm[256];
MIPSDisAsm(op, currentMIPS->pc, disasm);
_dbg_assert_msg_(CPU, 0, "%s", disasm);
currentMIPS->pc += 4;
}
}
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
#define _RD ((op>>11) & 0x1F)
#define R(i) (curMips->r[i])
int MIPSInterpret_RunUntil(u64 globalTicks)
{
MIPSState *curMips = currentMIPS;
while (coreState == CORE_RUNNING)
{
CoreTiming::Advance();
// NEVER stop in a delay slot!
while (curMips->downcount >= 0 && coreState == CORE_RUNNING)
{
// int cycles = 0;
{
again:
u32 op = Memory::Read_U32(curMips->pc);
//u32 op = Memory::Read_Opcode_JIT(mipsr4k.pc);
/*
// Choke on VFPU
u32 info = MIPSGetInfo(op);
if (info & IS_VFPU)
{
if (!Core_IsStepping() && !GetAsyncKeyState(VK_LSHIFT))
{
Core_EnableStepping(true);
return;
}
}*/
//2: check for breakpoint (VERY SLOW)
#if defined(_DEBUG)
if (CBreakPoints::IsAddressBreakPoint(curMips->pc))
{
Core_EnableStepping(true);
if (CBreakPoints::IsTempBreakPoint(curMips->pc))
CBreakPoints::RemoveBreakPoint(curMips->pc);
break;
}
#endif
bool wasInDelaySlot = curMips->inDelaySlot;
MIPSInterpret(op);
if (curMips->inDelaySlot)
{
// The reason we have to check this is the delay slot hack in Int_Syscall.
if (wasInDelaySlot)
{
curMips->pc = curMips->nextPC;
curMips->inDelaySlot = false;
}
curMips->downcount -= 1;
goto again;
}
}
curMips->downcount -= 1;
if (CoreTiming::GetTicks() > globalTicks)
{
// DEBUG_LOG(CPU, "Hit the max ticks, bailing 1 : %llu, %llu", globalTicks, CoreTiming::GetTicks());
return 1;
}
}
}
return 1;
}
static inline void DelayBranchTo(MIPSState *curMips, u32 where)
{
curMips->pc += 4;
curMips->nextPC = where;
curMips->inDelaySlot = true;
}
// Optimized interpreter loop that shortcuts the most common instructions.
// For slow platforms without JITs.
#define SIMM16 (s32)(s16)(op & 0xFFFF)
#define UIMM16 (u32)(u16)(op & 0xFFFF)
#define SUIMM16 (u32)(s32)(s16)(op & 0xFFFF)
int MIPSInterpret_RunFastUntil(u64 globalTicks)
{
MIPSState *curMips = currentMIPS;
while (coreState == CORE_RUNNING)
{
CoreTiming::Advance();
while (curMips->downcount >= 0 && coreState == CORE_RUNNING) // TODO: Try to get rid of the latter check
{
again:
bool wasInDelaySlot = curMips->inDelaySlot;
u32 op = Memory::ReadUnchecked_U32(curMips->pc);
switch (op >> 29)
{
case 0x0:
{
int imm = (s16)(op&0xFFFF) << 2;
int rs = _RS;
int rt = _RT;
u32 addr = curMips->pc + imm + 4;
switch (op >> 26)
{
case 4: if (R(rt) == R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //beq
case 5: if (R(rt) != R(rs)) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bne
case 6: if ((s32)R(rs) <= 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //blez
case 7: if ((s32)R(rs) > 0) DelayBranchTo(curMips, addr); else curMips->pc += 4; break; //bgtz
default:
goto interpret;
}
}
break;
case 0x1:
{
int rt = _RT;
int rs = _RS;
switch (op >> 26)
{
case 8: R(rt) = R(rs) + SIMM16; break; //addi
case 9: R(rt) = R(rs) + SIMM16; break; //addiu
case 10: R(rt) = (s32)R(rs) < SIMM16; break; //slti
case 11: R(rt) = R(rs) < SUIMM16; break; //sltiu
case 12: R(rt) = R(rs) & UIMM16; break; //andi
case 13: R(rt) = R(rs) | UIMM16; break; //ori
case 14: R(rt) = R(rs) ^ UIMM16; break; //xori
case 15: R(rt) = UIMM16 << 16; break; //lui
default:
goto interpret;
}
currentMIPS->pc += 4;
}
break;
case 0x4:
{
int rt = _RT;
int rs = _RS;
int imm = (s16)(op & 0xFFFF);
u32 addr = R(rs) + imm;
switch (op >> 26)
{
case 32: R(rt) = (u32)(s32)(s8) Memory::ReadUnchecked_U8(addr); break; //lb
case 33: R(rt) = (u32)(s32)(s16)Memory::ReadUnchecked_U16(addr); break; //lh
case 35: R(rt) = Memory::ReadUnchecked_U32(addr); break; //lw
case 36: R(rt) = Memory::ReadUnchecked_U8(addr); break; //lbu
case 37: R(rt) = Memory::ReadUnchecked_U16(addr); break; //lhu
default:
goto interpret;
}
currentMIPS->pc += 4;
}
break;
case 0x5:
{
int rt = _RT;
int rs = _RS;
int imm = (s16)(op & 0xFFFF);
u32 addr = R(rs) + imm;
switch (op >> 26)
{
case 40: Memory::WriteUnchecked_U8(R(rt), addr); break; //sb
case 41: Memory::WriteUnchecked_U16(R(rt), addr); break; //sh
case 43: Memory::WriteUnchecked_U32(R(rt), addr); break; //sw
default:
goto interpret;
}
currentMIPS->pc += 4;
}
break;
default:
interpret:
MIPSInterpret(op);
}
if (curMips->inDelaySlot)
{
// The reason we have to check this is the delay slot hack in Int_Syscall.
if (wasInDelaySlot)
{
curMips->pc = curMips->nextPC;
curMips->inDelaySlot = false;
}
curMips->downcount -= 1;
goto again;
}
}
}
return 1;
}
const char *MIPSGetName(u32 op)
{
static const char *noname = "unk";
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (!instr)
return noname;
else
return instr->name;
}
u32 MIPSGetInfo(u32 op)
{
// int crunch = CRUNCH_MIPS_OP(op);
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr)
return instr->flags;
else
return 0;
}
MIPSInterpretFunc MIPSGetInterpretFunc(u32 op)
{
const MIPSInstruction *instr = MIPSGetInstruction(op);
if (instr->interpret)
return instr->interpret;
else
return 0;
}
// TODO: Do something that makes sense here.
int MIPSGetInstructionCycleEstimate(u32 op)
{
u32 info = MIPSGetInfo(op);
if (info & DELAYSLOT)
return 2;
else
return 1;
}