mirror of
https://github.com/mupen64plus-ae/parallel-rsp.git
synced 2024-11-23 05:29:39 +00:00
Full disasm and register dumping ...
This commit is contained in:
parent
313f1761a5
commit
07a02d26c1
@ -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
113
rsp.cpp
@ -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
585
rsp_disasm.cpp
Normal 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
12
rsp_disasm.hpp
Normal 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
|
103
rsp_jit.cpp
103
rsp_jit.cpp
@ -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++)
|
||||
{
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user