Full disasm and register dumping ...

This commit is contained in:
Hans-Kristian Arntzen 2020-02-01 01:42:56 +01:00
parent 313f1761a5
commit 07a02d26c1
6 changed files with 701 additions and 114 deletions

View File

@ -15,6 +15,7 @@ add_library(parallel-rsp STATIC
rsp.cpp rsp.hpp
rsp_jit.cpp rsp_jit.hpp
debug_jit.cpp debug_jit.hpp
rsp_disasm.cpp rsp_disasm.hpp
rsp/ls.cpp rsp/pipeline.h
rsp/reciprocal.cpp rsp/reciprocal.h
rsp_1.1.h

113
rsp.cpp
View File

@ -1,4 +1,5 @@
#include "rsp.hpp"
#include "rsp_disasm.hpp"
#include <utility>
using namespace std;
@ -43,18 +44,13 @@ CPU::~CPU()
{
}
static const char *reg_names[32] = {
"zero", "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", "s8", "ra",
};
#define NAME(reg) reg_names[reg]
void CPU::init_symbol_table()
{
#define S(sym) symbol_table["RSP_" #sym] = reinterpret_cast<uint64_t>(RSP_##sym)
S(EXIT);
S(CALL);
S(RETURN);
S(REPORT_PC);
#ifdef INTENSE_DEBUG
S(DEBUG);
@ -501,10 +497,11 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND("unsigned *dmem = STATE->dmem;\n");
for (unsigned i = 0; i < count; i++)
{
uint32_t instr = state.imem[pc + i];
APPEND("pc_%03x:\n", (pc + i) * 4);
APPEND("RSP_REPORT_PC(STATE, %u, %u);\n", (pc + i) * 4, instr);
PIPELINE_BRANCH();
uint32_t instr = state.imem[pc + i];
uint32_t type = instr >> 26;
uint32_t rd, rs, rt, shift, imm;
int16_t simm;
@ -561,34 +558,34 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND_RD_NOT_R0("r%u = r%u << %u;\n", rd, rt, shift);
if (instr)
DISASM("sll %s, %s, %u\n", NAME(rd), NAME(rt), shift);
DISASM("sll %s, %s, %u\n", register_name(rd), register_name(rt), shift);
else
DISASM("nop\n");
break;
case 002: // SRL
APPEND_RD_NOT_R0("r%u = r%u >> %u;\n", rd, rt, shift);
DISASM("srl %s, %s, %u\n", NAME(rd), NAME(rt), shift);
DISASM("srl %s, %s, %u\n", register_name(rd), register_name(rt), shift);
break;
case 003: // SRA
APPEND_RD_NOT_R0("r%u = (int)r%u >> (int)%u;\n", rd, rt, shift);
DISASM("sra %s, %s, %u\n", NAME(rd), NAME(rt), shift);
DISASM("sra %s, %s, %u\n", register_name(rd), register_name(rt), shift);
break;
case 004: // SLLV
APPEND_RD_NOT_R0("r%u = r%u << MASK_SA(r%u);\n", rd, rt, rs);
DISASM("sllv %s, %s, $%u\n", NAME(rd), NAME(rt), rs);
DISASM("sllv %s, %s, $%u\n", register_name(rd), register_name(rt), rs);
break;
case 006: // SRLV
APPEND_RD_NOT_R0("r%u = r%u >> MASK_SA(r%u);\n", rd, rt, rs);
DISASM("srlv %s, %s, $%u\n", NAME(rd), NAME(rt), rs);
DISASM("srlv %s, %s, $%u\n", register_name(rd), register_name(rt), rs);
break;
case 007: // SRAV
APPEND_RD_NOT_R0("r%u = (int)r%u >> (int)MASK_SA(r%u);\n", rd, rt, rs);
DISASM("srav %s, %s, $%u\n", NAME(rd), NAME(rt), rs);
DISASM("srav %s, %s, $%u\n", register_name(rd), register_name(rt), rs);
break;
case 011: // JALR
@ -598,7 +595,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
}
set_pc_indirect(rs);
pipe_pending_indirect_call = true;
DISASM("jalr %s\n", NAME(rs));
DISASM("jalr %s\n", register_name(rs));
#ifdef INTENSE_DEBUG
APPEND("RSP_DEBUG(STATE, \"JALR\", pipe_branch_delay * 4, 0);\n");
#endif
@ -606,7 +603,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
case 010: // JR
set_pc_indirect(rs);
pipe_pending_return = true;
DISASM("jr %s\n", NAME(rs));
DISASM("jr %s\n", register_name(rs));
#ifdef INTENSE_DEBUG
APPEND("RSP_DEBUG(STATE, \"JR\", pipe_branch_delay * 4, 0);\n");
#endif
@ -619,43 +616,43 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
case 040: // ADD
case 041: // ADDU
APPEND_RD_NOT_R0("r%u = r%u + r%u;\n", rd, rs, rt);
DISASM("add %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("add %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 042: // SUB
case 043: // SUBU
APPEND_RD_NOT_R0("r%u = r%u - r%u;\n", rd, rs, rt);
DISASM("sub %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("sub %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 044: // AND
APPEND_RD_NOT_R0("r%u = r%u & r%u;\n", rd, rs, rt);
DISASM("and %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("and %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 045: // OR
APPEND_RD_NOT_R0("r%u = r%u | r%u;\n", rd, rs, rt);
DISASM("or %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("or %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 046: // XOR
APPEND_RD_NOT_R0("r%u = r%u ^ r%u;\n", rd, rs, rt);
DISASM("xor %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("xor %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 047: // NOR
APPEND_RD_NOT_R0("r%u = ~(r%u | r%u);\n", rd, rs, rt);
DISASM("nor %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("nor %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 052: // SLT
APPEND_RD_NOT_R0("r%u = (int)r%u < (int)r%u;\n", rd, rs, rt);
DISASM("slt %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("slt %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
case 053: // SLTU
APPEND_RD_NOT_R0("r%u = r%u < r%u;\n", rd, rs, rt);
DISASM("sltu %s, %s, %s\n", NAME(rd), NAME(rs), NAME(rt));
DISASM("sltu %s, %s, %s\n", register_name(rd), register_name(rs), register_name(rt));
break;
default:
@ -674,14 +671,14 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u < 0);\n", rs);
DISASM("bltzal %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
DISASM("bltzal %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
break;
case 000: // BLTZ
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u < 0);\n", rs);
DISASM("bltz %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
DISASM("bltz %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
break;
case 021: // BGEZAL
@ -689,14 +686,14 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u >= 0);\n", rs);
DISASM("bgezal %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
DISASM("bgezal %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
break;
case 001: // BGEZ
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u >= 0);\n", rs);
DISASM("bgez %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
DISASM("bgez %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) << 2) & 0xffc);
break;
default:
@ -728,7 +725,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rt = (instr >> 16) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF(r%u == r%u);\n", rs, rt);
DISASM("beq %s, %s, 0x%x\n", NAME(rs), NAME(rt), ((pc + i + 1 + instr) & 0x3ff) << 2);
DISASM("beq %s, %s, 0x%x\n", register_name(rs), register_name(rt), ((pc + i + 1 + instr) & 0x3ff) << 2);
break;
case 005: // BNE
@ -736,21 +733,21 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rt = (instr >> 16) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF(r%u != r%u);\n", rs, rt);
DISASM("bne %s, %s, 0x%x\n", NAME(rs), NAME(rt), ((pc + i + 1 + instr) & 0x3ff) << 2);
DISASM("bne %s, %s, 0x%x\n", register_name(rs), register_name(rt), ((pc + i + 1 + instr) & 0x3ff) << 2);
break;
case 006: // BLEZ
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u <= 0);\n", rs);
DISASM("blez %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) & 0x3ff) << 2);
DISASM("blez %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) & 0x3ff) << 2);
break;
case 007: // BGTZ
rs = (instr >> 21) & 31;
set_pc(pc + i + 1 + instr);
APPEND("BRANCH_IF((int)r%u > 0);\n", rs);
DISASM("bgtz %s, 0x%x\n", NAME(rs), ((pc + i + 1 + instr) & 0x3ff) << 2);
DISASM("bgtz %s, 0x%x\n", register_name(rs), ((pc + i + 1 + instr) & 0x3ff) << 2);
break;
case 010:
@ -761,9 +758,9 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND_RT_NOT_R0("r%u = (int)r%u + %d;\n", rt, rs, simm);
if (rs != 0)
DISASM("addi %s, %s, %d\n", NAME(rt), NAME(rs), simm);
DISASM("addi %s, %s, %d\n", register_name(rt), register_name(rs), simm);
else
DISASM("li %s, %d\n", NAME(rt), simm);
DISASM("li %s, %d\n", register_name(rt), simm);
break;
case 012: // SLTI
@ -771,7 +768,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = (int)r%u < %d;\n", rt, rs, simm);
DISASM("slti %s, %s, %d\n", NAME(rt), NAME(rs), simm);
DISASM("slti %s, %s, %d\n", register_name(rt), register_name(rs), simm);
break;
case 013: // SLTIU
@ -779,7 +776,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = r%u < %u;\n", rt, rs, imm);
DISASM("sltiu %s, %s, %u\n", NAME(rt), NAME(rs), imm);
DISASM("sltiu %s, %s, %u\n", register_name(rt), register_name(rs), imm);
break;
case 014: // ANDI
@ -787,7 +784,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = r%u & %u;\n", rt, rs, imm);
DISASM("andi %s, %s, 0x%x\n", NAME(rt), NAME(rs), imm);
DISASM("andi %s, %s, 0x%x\n", register_name(rt), register_name(rs), imm);
break;
case 015: // ORI
@ -795,7 +792,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = r%u | %u;\n", rt, rs, imm);
DISASM("ori %s, %s, 0x%x\n", NAME(rt), NAME(rs), imm);
DISASM("ori %s, %s, 0x%x\n", register_name(rt), register_name(rs), imm);
break;
case 016: // XORI
@ -803,14 +800,14 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rs = (instr >> 21) & 31;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = r%u ^ %u;\n", rt, rs, imm);
DISASM("xori %s, %s, 0x%x\n", NAME(rt), NAME(rs), imm);
DISASM("xori %s, %s, 0x%x\n", register_name(rt), register_name(rs), imm);
break;
case 017: // LUI
imm = instr & 0xffff;
rt = (instr >> 16) & 31;
APPEND_RT_NOT_R0("r%u = %uu << 16u;\n", rt, imm);
DISASM("lui %s, 0x%x\n", NAME(rt), imm);
DISASM("lui %s, 0x%x\n", register_name(rt), imm);
break;
case 020: // COP0
@ -885,7 +882,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
{
APPEND("r%u = (signed char)READ_MEM_U8(dmem, (r%u + (%d)) & 0xfff);\n", rt, rs, simm);
}
DISASM("lb %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("lb %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 041: // LH
@ -900,7 +897,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND("else\n");
APPEND(" r%u = (signed short)READ_MEM_U16(dmem, addr);\n", rt);
}
DISASM("lh %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("lh %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 043: // LW
@ -915,7 +912,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND("else\n");
APPEND(" r%u = READ_MEM_U32(dmem, addr);\n", rt);
}
DISASM("lw %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("lw %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 044: // LBU
@ -926,7 +923,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
{
APPEND("r%u = READ_MEM_U8(dmem, (r%u + (%d)) & 0xfff);\n", rt, rs, simm);
}
DISASM("lbu %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("lbu %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 045: // LHU
@ -942,7 +939,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND("else\n");
APPEND(" r%u = READ_MEM_U16(dmem, addr);\n", rt);
}
DISASM("lhu %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("lhu %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 050: // SB
@ -950,7 +947,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
rt = (instr >> 16) & 31;
rs = (instr >> 21) & 31;
APPEND("WRITE_MEM_U8(dmem, ((r%u + (%d)) & 0xfff), r%u);\n", rs, simm, rt);
DISASM("sb %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("sb %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 051: // SH
@ -962,7 +959,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND(" WRITE_MEM_U16_UNALIGNED(dmem, addr, r%u);\n", rt);
APPEND("else\n");
APPEND(" WRITE_MEM_U16(dmem, addr, r%u);\n", rt);
DISASM("sh %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("sh %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 053: // SW
@ -974,7 +971,7 @@ Func CPU::jit_region(uint64_t hash, unsigned pc, unsigned count)
APPEND(" WRITE_MEM_U32_UNALIGNED(dmem, addr, r%u);\n", rt);
APPEND("else\n");
APPEND(" WRITE_MEM_U32(dmem, addr, r%u);\n", rt);
DISASM("sw %s, %d(%s)\n", NAME(rt), simm, NAME(rs));
DISASM("sw %s, %d(%s)\n", register_name(rt), simm, register_name(rs));
break;
case 062: // LWC2
@ -1103,6 +1100,8 @@ extern void RSP_MFC2(struct cpu_state *STATE, unsigned rt, unsigned vs, unsigned
extern void RSP_CFC2(struct cpu_state *STATE, unsigned rt, unsigned rd);
extern void RSP_CTC2(struct cpu_state *STATE, unsigned rt, unsigned rd);
extern void RSP_REPORT_PC(struct cpu_state *STATE, unsigned pc, unsigned instr);
#define DECL_LS(op) \
extern void RSP_##op(struct cpu_state *STATE, unsigned rt, unsigned element, int offset, unsigned base)
@ -1254,7 +1253,7 @@ void CPU::print_registers()
fprintf(DUMP_FILE, "RSP state:\n");
fprintf(DUMP_FILE, " PC: 0x%03x\n", state.pc);
for (unsigned i = 1; i < 32; i++)
fprintf(DUMP_FILE, " SR[%s] = 0x%08x\n", NAME(i), state.sr[i]);
fprintf(DUMP_FILE, " SR[%s] = 0x%08x\n", register_name(i), state.sr[i]);
fprintf(DUMP_FILE, "\n");
for (unsigned i = 0; i < 32; i++)
{
@ -1334,6 +1333,24 @@ extern "C"
{
static_cast<CPU *>(cpu)->exit(static_cast<ReturnMode>(mode));
}
void RSP_REPORT_PC(void *cpu, unsigned pc, unsigned instr)
{
auto *state = static_cast<const CPUState *>(cpu);
auto disasm = disassemble(pc, instr);
puts(disasm.c_str());
for (unsigned i = 0; i < 32; i++)
{
if (i == 0)
printf(" ");
else
printf("[%s = 0x%08x] ", register_name(i), state->sr[i]);
if ((i & 7) == 7)
printf("\n");
}
printf("\n");
}
}
void CPU::enter(uint32_t pc)

585
rsp_disasm.cpp Normal file
View File

@ -0,0 +1,585 @@
#include "rsp_disasm.hpp"
#include <assert.h>
namespace RSP
{
#define DISASM(asmfmt, ...) do { \
char buf[1024]; \
sprintf(buf, "0x%03x " asmfmt, pc, __VA_ARGS__); \
return buf; \
} while(0)
#define DISASM_NOP() do { \
char buf[1024]; \
sprintf(buf, "0x%03x nop", pc); \
return buf; \
} while(0)
static const char *reg_names[32] = {
"zero", "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", "s8", "ra",
};
#define NAME(reg) reg_names[reg]
const char *register_name(unsigned reg_index)
{
assert(reg_index < 32);
return reg_names[reg_index];
}
std::string disassemble(uint32_t pc, uint32_t instr)
{
// VU
if ((instr >> 25) == 0x25)
{
// VU instruction. COP2, and high bit of opcode is set.
uint32_t op = instr & 63;
uint32_t vd = (instr >> 6) & 31;
uint32_t vs = (instr >> 11) & 31;
uint32_t vt = (instr >> 16) & 31;
uint32_t e = (instr >> 21) & 15;
static const char *ops_str[64] = {
"VMULF", "VMULU", nullptr, nullptr, "VMUDL", "VMUDM", "VMUDN", "VMUDH", "VMACF", "VMACU", nullptr,
nullptr, "VMADL", "VMADM", "VMADN", "VMADH", "VADD", "VSUB", nullptr, "VABS", "VADDC", "VSUBC",
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "VSAR", nullptr, nullptr, "VLT",
"VEQ", "VNE", "VGE", "VCL", "VCH", "VCR", "VMRG", "VAND", "VNAND", "VOR", "VNOR",
"VXOR", "VNXOR", nullptr, nullptr, "VRCP", "VRCPL", "VRCPH", "VMOV", "VRSQ", "VRSQL", "VRSQH",
"VNOP",
};
if (ops_str[op])
DISASM("%s v%u, v%u, v%u[%u]", ops_str[op], vd, vs, vt, e);
else
DISASM("cop2 %u reserved", op);
}
// TODO: Meaningful register allocation.
// For now, always flush register state to memory after an instruction for simplicity.
// Should be red-hot in L1 cache, so probably won't be that bad.
// On x86 and x64, we unfortunately have an anemic register bank to work with in Lightning.
uint32_t type = instr >> 26;
#define NOP_IF_RD_ZERO() if (rd == 0) { DISASM_NOP(); break; }
#define NOP_IF_RT_ZERO() if (rt == 0) { DISASM_NOP(); break; }
switch (type)
{
case 000:
{
auto rd = (instr >> 11) & 31;
auto rt = (instr >> 16) & 31;
auto shift = (instr >> 6) & 31;
auto rs = (instr >> 21) & 31;
switch (instr & 63)
{
#define FIXED_SHIFT_OP(asmop) \
NOP_IF_RD_ZERO(); \
DISASM(#asmop " %s, %s, %u", NAME(rd), NAME(rt), shift)
case 000: // SLL
{
FIXED_SHIFT_OP(sll);
break;
}
case 002: // SRL
{
FIXED_SHIFT_OP(srl);
break;
}
case 003: // SRA
{
FIXED_SHIFT_OP(sra);
break;
}
#define VARIABLE_SHIFT_OP(asmop) \
NOP_IF_RD_ZERO(); \
DISASM(#asmop " %s, %s, %s", NAME(rd), NAME(rt), NAME(rs))
case 004: // SLLV
{
VARIABLE_SHIFT_OP(sllv);
break;
}
case 006: // SRLV
{
VARIABLE_SHIFT_OP(srlv);
break;
}
case 007: // SRAV
{
VARIABLE_SHIFT_OP(srav);
break;
}
// If the last instruction is also a branch instruction, we will need to do some funky handling
// so make sure we save the old branch taken register.
case 010: // JR
{
DISASM("jr %s", NAME(rs));
break;
}
case 011: // JALR
{
DISASM("jalr %s", NAME(rs));
break;
}
case 015: // BREAK
{
DISASM("break %u", 0);
break;
}
#define THREE_REG_OP(asmop) \
NOP_IF_RD_ZERO(); \
DISASM(#asmop " %s, %s, %s", NAME(rd), NAME(rt), NAME(rs))
case 040: // ADD
case 041: // ADDU
{
THREE_REG_OP(addu);
break;
}
case 042: // SUB
case 043: // SUBU
{
THREE_REG_OP(subu);
break;
}
case 044: // AND
{
THREE_REG_OP(and);
break;
}
case 045: // OR
{
THREE_REG_OP(or);
break;
}
case 046: // XOR
{
THREE_REG_OP(xor);
break;
}
case 047: // NOR
{
NOP_IF_RD_ZERO();
DISASM("nor %s, %s, %s", NAME(rd), NAME(rt), NAME(rs));
break;
}
case 052: // SLT
{
THREE_REG_OP(slt);
break;
}
case 053: // SLTU
{
THREE_REG_OP(sltu);
break;
}
default:
break;
}
break;
}
case 001: // REGIMM
{
unsigned rt = (instr >> 16) & 31;
switch (rt)
{
case 020: // BLTZAL
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bltzal %s, 0x%03x", NAME(rs), target_pc);
break;
}
case 000: // BLTZ
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bltz %s, 0x%03x", NAME(rs), target_pc);
break;
}
case 021: // BGEZAL
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bltzal %s, 0x%03x", NAME(rs), target_pc);
break;
}
case 001: // BGEZ
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bgez %s, 0x%03x", NAME(rs), target_pc);
break;
}
default:
break;
}
break;
}
case 003: // JAL
{
uint32_t target_pc = (instr & 0x3ffu) << 2;
DISASM("jal 0x%03x", target_pc);
break;
}
case 002: // J
{
uint32_t target_pc = (instr & 0x3ffu) << 2;
DISASM("j 0x%03x", target_pc);
break;
}
case 004: // BEQ
{
unsigned rs = (instr >> 21) & 31;
unsigned rt = (instr >> 16) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("beq %s, %s, 0x%03x", NAME(rs), NAME(rt), target_pc);
break;
}
case 005: // BNE
{
unsigned rs = (instr >> 21) & 31;
unsigned rt = (instr >> 16) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bne %s, %s, 0x%03x", NAME(rs), NAME(rt), target_pc);
break;
}
case 006: // BLEZ
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("blez %s, 0x%03x", NAME(rs), target_pc);
break;
}
case 007: // BGTZ
{
unsigned rs = (instr >> 21) & 31;
uint32_t target_pc = (pc + 4 + (instr << 2)) & 0xffc;
DISASM("bgtz %s, 0x%03x", NAME(rs), target_pc);
break;
}
#define TWO_REG_IMM_OP(asmop, immtype) \
unsigned rt = (instr >> 16) & 31; \
NOP_IF_RT_ZERO(); \
unsigned rs = (instr >> 21) & 31; \
DISASM(#asmop " %s, %s, %d", NAME(rt), NAME(rs), immtype(instr))
case 010: // ADDI
case 011:
{
TWO_REG_IMM_OP(addi, int16_t);
break;
}
case 012: // SLTI
{
TWO_REG_IMM_OP(slti, int16_t);
break;
}
case 013: // SLTIU
{
TWO_REG_IMM_OP(sltiu, uint16_t);
break;
}
case 014: // ANDI
{
TWO_REG_IMM_OP(andi, uint16_t);
break;
}
case 015: // ORI
{
TWO_REG_IMM_OP(ori, uint16_t);
break;
}
case 016: // XORI
{
TWO_REG_IMM_OP(xori, uint16_t);
break;
}
case 017: // LUI
{
unsigned rt = (instr >> 16) & 31;
NOP_IF_RT_ZERO();
int16_t imm = int16_t(instr);
DISASM("lui %s, %d", NAME(rt), imm);
break;
}
case 020: // COP0
{
unsigned rd = (instr >> 11) & 31;
unsigned rs = (instr >> 21) & 31;
unsigned rt = (instr >> 16) & 31;
switch (rs)
{
case 000: // MFC0
{
DISASM("mfc0 %s, %s", NAME(rt), NAME(rd));
break;
}
case 004: // MTC0
{
DISASM("mtc0 %s, %s", NAME(rd), NAME(rt));
break;
}
default:
break;
}
break;
}
case 022: // COP2
{
unsigned rd = (instr >> 11) & 31;
unsigned rs = (instr >> 21) & 31;
unsigned rt = (instr >> 16) & 31;
unsigned imm = (instr >> 7) & 15;
switch (rs)
{
case 000: // MFC2
{
DISASM("mfc2 %s, %s, %u", NAME(rt), NAME(rd), imm);
break;
}
case 002: // CFC2
{
DISASM("cfc2 %s, %s", NAME(rt), NAME(rd));
break;
}
case 004: // MTC2
{
DISASM("mtc2 %s, %s, %u", NAME(rt), NAME(rd), imm);
break;
}
case 006: // CTC2
{
DISASM("ctc2 %s, %s", NAME(rt), NAME(rd));
break;
}
default:
break;
}
break;
}
case 040: // LB
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("lb %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 041: // LH
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("lh %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 043: // LW
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("lw %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 044: // LBU
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("lbu %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 045: // LHU
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("lhu %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 050: // SB
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("sb %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 051: // SH
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("sh %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 053: // SW
{
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
break;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
DISASM("sw %s, %d(%s)", NAME(rt), simm, NAME(rs));
break;
}
case 062: // LWC2
{
unsigned rt = (instr >> 16) & 31;
int16_t simm = instr;
// Sign-extend.
simm <<= 9;
simm >>= 9;
unsigned rs = (instr >> 21) & 31;
unsigned rd = (instr >> 11) & 31;
unsigned imm = (instr >> 7) & 15;
static const char *lwc2_ops[32] = {
"LBV", "LSV", "LLV", "LDV", "LQV", "LRV", "LPV", "LUV", "LHV", nullptr, nullptr, "LTV",
};
const char *op = lwc2_ops[rd];
if (op)
DISASM("%s v%u, %u, %d(%s)", op, rt, imm, simm, NAME(rs));
else
DISASM_NOP();
break;
}
case 072: // SWC2
{
unsigned rt = (instr >> 16) & 31;
int16_t simm = instr;
// Sign-extend.
simm <<= 9;
simm >>= 9;
unsigned rs = (instr >> 21) & 31;
unsigned rd = (instr >> 11) & 31;
unsigned imm = (instr >> 7) & 15;
static const char *swc2_ops[32] = {
"SBV", "SSV", "SLV", "SDV", "SQV", "SRV", "SPV", "SUV", "SHV", "SFV", nullptr, "STV",
};
const char *op = swc2_ops[rd];
if (op)
DISASM("%s v%u, %u, %d(%s)", op, rt, imm, simm, NAME(rs));
else
DISASM_NOP();
break;
}
default:
break;
}
return "???";
}
}

12
rsp_disasm.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef RSP_DISASM_HPP_
#define RSP_DISASM_HPP_
#include <string>
namespace RSP
{
std::string disassemble(uint32_t pc, uint32_t instr);
const char *register_name(unsigned reg_index);
}
#endif

View File

@ -1,4 +1,5 @@
#include "rsp_jit.hpp"
#include "rsp_disasm.hpp"
#include <utility>
#include <assert.h>
@ -24,12 +25,6 @@ namespace RSP
{
namespace JIT
{
static const char *reg_names[32] = {
"zero", "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", "s8", "ra",
};
#define NAME(reg) reg_names[reg]
CPU::CPU()
{
cleanup_jit_states.reserve(16 * 1024);
@ -263,6 +258,22 @@ extern "C"
dram[off2] = (data >> 8) & 0xff;
dram[off3] = (data >> 0) & 0xff;
}
static void rsp_report_pc(const CPUState *state, jit_uword_t pc, jit_uword_t instr)
{
auto disasm = disassemble(pc, instr);
puts(disasm.c_str());
for (unsigned i = 0; i < 32; i++)
{
if (i == 0)
printf(" ");
else
printf("[%s = 0x%08x] ", register_name(i), state->sr[i]);
if ((i & 7) == 7)
printf("\n");
}
printf("\n");
}
}
void CPU::jit_save_cond_branch_taken(jit_state_t *_jit)
@ -583,18 +594,6 @@ void CPU::jit_store_register(jit_state_t *_jit, unsigned jit_register, unsigned
jit_stxi_i(offsetof(CPUState, sr) + 4 * mips_register, JIT_REGISTER_STATE, jit_register);
}
#define DISASM(asmfmt, ...) do { \
char buf[1024]; \
sprintf(buf, "0x%03x " asmfmt, pc, __VA_ARGS__); \
mips_disasm += buf; \
} while(0)
#define DISASM_NOP() do { \
char buf[1024]; \
sprintf(buf, "0x%03x nop\n", pc); \
mips_disasm += buf; \
} while(0)
void CPU::jit_emit_store_operation(jit_state_t *_jit,
uint32_t pc, uint32_t instr,
void (*jit_emitter)(jit_state_t *jit, unsigned, unsigned, unsigned), const char *asmop,
@ -649,7 +648,6 @@ void CPU::jit_emit_store_operation(jit_state_t *_jit,
if (align_mask)
jit_patch(aligned);
DISASM("%s %s, %d(%s)\n", asmop, NAME(rt), simm, NAME(rs));
}
// The RSP may or may not have a load-delay slot, but it doesn't seem to matter in practice, so just emulate without
@ -665,10 +663,7 @@ void CPU::jit_emit_load_operation(jit_state_t *_jit,
uint32_t align_mask = endian_flip ^ 3;
unsigned rt = (instr >> 16) & 31;
if (rt == 0)
{
DISASM_NOP();
return;
}
int16_t simm = int16_t(instr);
unsigned rs = (instr >> 21) & 31;
@ -716,13 +711,22 @@ void CPU::jit_emit_load_operation(jit_state_t *_jit,
if (align_mask)
jit_patch(aligned);
DISASM("%s %s, %d(%s)\n", asmop, NAME(rt), simm, NAME(rs));
}
void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
InstructionInfo &info, const InstructionInfo &last_info,
bool first_instruction, bool next_instruction_is_branch_target)
{
if (last_info.conditional)
jit_save_cond_branch_taken(_jit);
jit_prepare();
jit_pushargr(JIT_REGISTER_STATE);
jit_pushargi(pc);
jit_pushargi(instr);
jit_finishi(reinterpret_cast<jit_pointer_t>(rsp_report_pc));
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
// VU
if ((instr >> 25) == 0x25)
{
@ -757,12 +761,10 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
VUOp vuop;
if (op_str)
{
DISASM("%s v%u, v%u, v%u[%u]\n", op_str, vd, vs, vt, e);
vuop = ops[op];
}
else
{
DISASM("cop2 %u reserved\n", op);
vuop = RSP_RESERVED;
}
@ -790,8 +792,8 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
uint32_t type = instr >> 26;
#define NOP_IF_RD_ZERO() if (rd == 0) { DISASM_NOP(); break; }
#define NOP_IF_RT_ZERO() if (rt == 0) { DISASM_NOP(); break; }
#define NOP_IF_RD_ZERO() if (rd == 0) { break; }
#define NOP_IF_RT_ZERO() if (rt == 0) { break; }
switch (type)
{
@ -808,8 +810,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
NOP_IF_RD_ZERO(); \
jit_load_register(_jit, JIT_REGISTER_TMP0, rt); \
jit_##op(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, shift); \
jit_store_register(_jit, JIT_REGISTER_TMP0, rd); \
DISASM(#asmop " %s, %s, %u\n", NAME(rd), NAME(rt), shift)
jit_store_register(_jit, JIT_REGISTER_TMP0, rd)
case 000: // SLL
{
@ -835,8 +836,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_load_register(_jit, JIT_REGISTER_TMP1, rs); \
jit_andi(JIT_REGISTER_TMP1, JIT_REGISTER_TMP1, 31); \
jit_##op(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, JIT_REGISTER_TMP1); \
jit_store_register(_jit, JIT_REGISTER_TMP0, rd); \
DISASM(#asmop " %s, %s, %s\n", NAME(rd), NAME(rt), NAME(rs))
jit_store_register(_jit, JIT_REGISTER_TMP0, rd)
case 004: // SLLV
{
@ -876,7 +876,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.conditional = true;
jit_movi(JIT_REGISTER_COND_BRANCH_TAKEN, 1);
}
DISASM("jr %s\n", NAME(rs));
break;
}
@ -897,7 +896,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.conditional = true;
jit_movi(JIT_REGISTER_COND_BRANCH_TAKEN, 1);
}
DISASM("jalr %s\n", NAME(rs));
break;
}
@ -905,7 +903,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
{
jit_exit(_jit, pc, last_info, MODE_BREAK, first_instruction);
info.handles_delay_slot = true;
DISASM("break %u\n", 0);
break;
}
@ -914,8 +911,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_load_register(_jit, JIT_REGISTER_TMP0, rs); \
jit_load_register(_jit, JIT_REGISTER_TMP1, rt); \
jit_##op(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, JIT_REGISTER_TMP1); \
jit_store_register(_jit, JIT_REGISTER_TMP0, rd); \
DISASM(#asmop " %s, %s, %s\n", NAME(rd), NAME(rt), NAME(rs))
jit_store_register(_jit, JIT_REGISTER_TMP0, rd)
case 040: // ADD
case 041: // ADDU
@ -957,7 +953,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_orr(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, JIT_REGISTER_TMP1);
jit_xori(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, jit_word_t(-1));
jit_store_register(_jit, JIT_REGISTER_TMP0, rd);
DISASM("nor %s, %s, %s\n", NAME(rd), NAME(rt), NAME(rs));
break;
}
@ -1000,7 +995,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bltzal %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1014,7 +1008,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bltz %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1033,7 +1026,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bltzal %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1047,7 +1039,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bgez %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1070,7 +1061,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.conditional = true;
jit_movi(JIT_REGISTER_COND_BRANCH_TAKEN, 1);
}
DISASM("jal 0x%03x\n", target_pc);
break;
}
@ -1085,7 +1075,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.conditional = true;
jit_movi(JIT_REGISTER_COND_BRANCH_TAKEN, 1);
}
DISASM("j 0x%03x\n", target_pc);
break;
}
@ -1101,7 +1090,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("beq %s, %s, 0x%03x\n", NAME(rs), NAME(rt), target_pc);
break;
}
@ -1117,7 +1105,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bne %s, %s, 0x%03x\n", NAME(rs), NAME(rt), target_pc);
break;
}
@ -1131,7 +1118,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("blez %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1145,7 +1131,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
info.branch = true;
info.conditional = true;
info.branch_target = target_pc;
DISASM("bgtz %s, 0x%03x\n", NAME(rs), target_pc);
break;
}
@ -1155,8 +1140,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
unsigned rs = (instr >> 21) & 31; \
jit_load_register(_jit, JIT_REGISTER_TMP0, rs); \
jit_##op(JIT_REGISTER_TMP0, JIT_REGISTER_TMP0, immtype(instr)); \
jit_store_register(_jit, JIT_REGISTER_TMP0, rt); \
DISASM(#asmop " %s, %s, %d\n", NAME(rt), NAME(rs), immtype(instr))
jit_store_register(_jit, JIT_REGISTER_TMP0, rt)
case 010: // ADDI
case 011:
@ -1202,7 +1186,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
int16_t imm = int16_t(instr);
jit_movi(JIT_REGISTER_TMP0, imm << 16);
jit_store_register(_jit, JIT_REGISTER_TMP0, rt);
DISASM("lui %s, %d\n", NAME(rt), imm);
break;
}
@ -1233,7 +1216,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_exit_dynamic(_jit, pc, last_info, first_instruction);
jit_patch(noexit);
DISASM("mfc0 %s, %s\n", NAME(rt), NAME(rd));
break;
}
@ -1256,7 +1238,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_exit_dynamic(_jit, pc, last_info, first_instruction);
jit_patch(noexit);
DISASM("mtc0 %s, %s\n", NAME(rd), NAME(rt));
break;
}
@ -1290,7 +1271,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("mfc2 %s, %s, %u\n", NAME(rt), NAME(rd), imm);
break;
}
@ -1308,7 +1288,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("cfc2 %s, %s\n", NAME(rt), NAME(rd));
break;
}
@ -1327,7 +1306,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("mtc2 %s, %s, %u\n", NAME(rt), NAME(rd), imm);
break;
}
@ -1345,7 +1323,6 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("ctc2 %s, %s\n", NAME(rt), NAME(rd));
break;
}
@ -1469,10 +1446,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_finishi(reinterpret_cast<jit_pointer_t>(ops[rd]));
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("%s v%u, %u, %d(%s)\n", op, rt, imm, simm, NAME(rs));
}
else
DISASM_NOP();
break;
}
@ -1511,10 +1485,7 @@ void CPU::jit_instruction(jit_state_t *_jit, uint32_t pc, uint32_t instr,
jit_finishi(reinterpret_cast<jit_pointer_t>(ops[rd]));
if (last_info.conditional)
jit_restore_cond_branch_taken(_jit);
DISASM("%s v%u, %u, %d(%s)\n", op, rt, imm, simm, NAME(rs));
}
else
DISASM_NOP();
break;
}
@ -1683,11 +1654,11 @@ Func CPU::jit_region(uint64_t hash, unsigned pc_word, unsigned instruction_count
auto ret = reinterpret_cast<Func>(jit_emit());
//printf(" === DISASM ===\n");
//fprintf(stderr, " === DISASM ===\n");
//jit_disassemble();
jit_clear_state();
//printf("%s\n", mips_disasm.c_str());
//printf(" === DISASM END ===\n\n");
//fprintf(stderr, "%s\n", mips_disasm.c_str());
//fprintf(stderr, " === DISASM END ===\n\n");
cleanup_jit_states.push_back(_jit);
return ret;
}
@ -1725,7 +1696,7 @@ void CPU::print_registers()
fprintf(DUMP_FILE, "RSP state:\n");
fprintf(DUMP_FILE, " PC: 0x%03x\n", state.pc);
for (unsigned i = 1; i < 32; i++)
fprintf(DUMP_FILE, " SR[%s] = 0x%08x\n", NAME(i), state.sr[i]);
fprintf(DUMP_FILE, " SR[%s] = 0x%08x\n", register_name(i), state.sr[i]);
fprintf(DUMP_FILE, "\n");
for (unsigned i = 0; i < 32; i++)
{

View File

@ -16,6 +16,7 @@ extern "C"
void RSP_CALL(void *opaque, unsigned target, unsigned ret);
void RSP_RETURN(void *opaque, unsigned pc);
void RSP_EXIT(void *opaque, int mode);
void RSP_REPORT_PC(void *rsp, unsigned pc, unsigned instr);
#define DECL_LS(op) void RSP_##op(RSP::CPUState *rsp, unsigned rt, unsigned element, int offset, unsigned base)