Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ares/ares/node/debugger/tracer/instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ struct Instruction : Tracer {
for(auto& history : _history) history = ~0ull;
}

auto setEnabled(bool enabled) -> void {
//Tracer::setEnabled(enabled); // @TODO
if(!enabled) {
_omitted = 0;
setMask(_mask);
setDepth(_depth);
}
}

auto address(u64 address) -> bool {
address &= ~0ull >> (64 - _addressBits); //mask upper bits of address
_address = address;
Expand Down
5 changes: 5 additions & 0 deletions ares/n64/rsp/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ auto RSP::Debugger::instruction() -> void {
rsp.disassembler.showColors = 1;
}
}

if(tracer.instructionCountdown) {
if (--tracer.instructionCountdown == 0)
tracer.instruction->setEnabled(false);
}
}

auto RSP::Debugger::ioSCC(bool mode, u32 address, u32 data) -> void {
Expand Down
133 changes: 133 additions & 0 deletions ares/n64/rsp/emux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
auto RSP::TNE(cr32& rs, cr32& rt, u32 code) -> void {
if(&rs != &rt) return INVALID();
EMUX(rt, code);
}

auto RSP::EMUX(cr32& rt, u32 code) -> void {
switch (code) {
case 0x20: // trace(start)
debugger.tracer.instruction->setEnabled(true);
debugger.tracer.instructionCountdown = 0;
break;
case 0x21: // trace(count)
printf("[emux] trace(count): %08x\n", rt.u32);
debugger.tracer.instruction->setEnabled(true);
debugger.tracer.instructionCountdown = rt.u32;
break;
case 0x22: // trace(stop)
debugger.tracer.instruction->setEnabled(false);
break;
case 0x30: // log(byte)
fputc(rt.u32 & 0xFF, stdout);
break;
case 0x31: { // log(string)
u32 i = 0;
do {
char c = dmem.read<Byte>(rt.u32 + i);
if (c == '\0') break;
fputc(c, stdout);
} while (++i < 4096);
} break;
case 0x32: // log(buflen)
emux.buflen = rt.u32;
break;
case 0x33: // log(buf)
for (auto i : range(emux.buflen)) {
fputc(dmem.read<Byte>(rt.u32 + i), stdout);
}
break;
case 0x40: case 0x48: { // dump_regs(gpr)
static const char *mips_reg_names[32] = { "zr", "at", "v0", "v1", "a0",
"a1", "a2", "a3", "t0", "t1",
"t2", "t3", "t4", "t5", "t6",
"t7", "s0", "s1", "s2", "s3",
"s4", "s5", "s6", "s7", "t8",
"t9", "k0", "k1", "gp", "sp",
"fp", "ra" };
n32 mask = rt.u32;
const char *fmt = code & 0x8 ? "%s: %-12d" : "%s: %04x %04x";
bool partial = false;
for (u32 i : range(32)) {
if (mask && !mask.bit(i)) continue;
u32 val = ipu.r[i].u32;
fprintf(stdout, fmt, mips_reg_names[i], val >> 16, val & 0xFFFF);
if (i % 4 == 3) fputc('\n', stdout), partial = false;
else fputs(" ", stdout), partial = true;
}
if (partial) fputc('\n', stdout);
} break;
case 0x41: case 0x44: { // dump_regs(cop0)
static const char *cop0_reg_names[16] = {
"dma_spaddr", "dma_ramaddr", "dma_read", "dma_write",
"sp_status", "dma_full", "dma_busy", "semaphore",
"dp_start", "dp_end", "dp_current", "dp_status",
"dp_clock", "dp_busy", "dp_pipe_busy", "dp_tmem_busy"
};
n32 mask = rt.u32;
const char *fmt = code & 0x8 ? "%s: %-12d" : "%s: %04x %04x";
bool partial = false;
Thread dummyThread{};
for (u32 i : range(16)) {
if (mask && !mask.bit(i)) continue;
u32 val;
if (i == 7) val = status.semaphore; // avoid side effects
else val = (i & 8) ? Nintendo64::rdp.readWord(i & 7, *this) : Nintendo64::rsp.ioRead(i & 7, dummyThread);
fprintf(stdout, fmt, cop0_reg_names[i], val >> 16, val & 0xFFFF);
if (i % 4 == 3) fputc('\n', stdout), partial = false;
else fputs(" ", stdout), partial = true;
}
if (partial) fputc('\n', stdout);
} break;
case 0x42: case 0x46: case 0x4A: case 0x4C: { // dump_regs(cop2)
auto dump_vr = [&](r128& vr) {
for (auto i : range(8)) {
if (code & 0x8) fprintf(stdout, "%-6d", vr.s16(i));
else fprintf(stdout, "%04x", vr.u16(i));
if (i < 7) fputc(' ', stdout);
if (i == 3) fputc(' ', stdout);
}
};

n32 mask = rt.u32;
bool partial = false;
for (u32 i : range(32)) {
if (mask && !mask.bit(i)) continue;
fprintf(stdout, "v%02d: ", i);
dump_vr(vpu.r[i]);
if (i % 2 == 1) fputc('\n', stdout), partial = false;
else fputs(" ", stdout), partial = true;
}
if (partial) fputc('\n', stdout);
if (code & 0x4) {
r128* accs[3] = { &vpu.acch, &vpu.accm, &vpu.accl };
const char *accnames[] = { "acch", "accm", "accl" };

auto dump_vc8 = [&](r128& vc) {
for (auto i : range(8)) {
fprintf(stdout, "%c", vc.get(i) ? '1' : '-');
if (i == 3) fputc(' ', stdout);
}
};
auto dump_vc16 = [&](r128& vch, r128& vcl) {
dump_vc8(vch);
fputc(' ', stdout);
dump_vc8(vcl);
};

for (auto i : range(3)) {
fprintf(stdout, "%s: ", accnames[i]);
dump_vr(*accs[i]);
fputs(" ", stdout);
switch (i) {
case 0: fprintf(stdout, "vco: "); dump_vc16(vpu.vcoh, vpu.vcol); fprintf(stdout, "\n"); break;
case 1: fprintf(stdout, "vcc: "); dump_vc16(vpu.vcch, vpu.vccl); fprintf(stdout, "\n"); break;
case 2: fprintf(stdout, "vce: "); dump_vc8(vpu.vce); fprintf(stdout, "\n"); break;
}
}
}
} break;
default:
printf("[emux] unknown emux code: %08x\n", code);
break;
}
}
3 changes: 2 additions & 1 deletion ares/n64/rsp/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define RDn (OP >> 11 & 31)
#define RTn (OP >> 16 & 31)
#define RSn (OP >> 21 & 31)
#define CODE (OP >> 6 & 1023)
#define VDn (OP >> 6 & 31)
#define VSn (OP >> 11 & 31)
#define VTn (OP >> 16 & 31)
Expand Down Expand Up @@ -166,7 +167,7 @@ auto RSP::interpreterSPECIAL() -> void {
op(0x33, INVALID); //TLTU
op(0x34, INVALID); //TEQ
op(0x35, INVALID);
op(0x36, INVALID); //TNE
op(0x36, TNE, RS, RT, CODE); //TNE
op(0x37, INVALID);
op(0x38, INVALID); //DSLL
op(0x39, INVALID);
Expand Down
18 changes: 17 additions & 1 deletion ares/n64/rsp/recompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ auto RSP::Recompiler::emit(u12 address) -> Block* {
#define Vdn (instruction >> 6 & 31)
#define Vsn (instruction >> 11 & 31)
#define Vtn (instruction >> 16 & 31)
#define Code (instruction >> 6 & 1023)
#define Rd sreg(1), offsetof(IPU, r) + Rdn * sizeof(r32)
#define Rt sreg(1), offsetof(IPU, r) + Rtn * sizeof(r32)
#define Rs sreg(1), offsetof(IPU, r) + Rsn * sizeof(r32)
Expand Down Expand Up @@ -547,7 +548,21 @@ auto RSP::Recompiler::emitSPECIAL(u32 instruction) -> bool {
}

//INVALID
case range20(0x2c, 0x3f): {
case range10(0x2c, 0x35): {
return 0;
}

//TNE Rs,Rt,Code
case 0x36: {
lea(reg(1), Rs);
lea(reg(2), Rt);
mov32(reg(3), imm(Code));
call(&RSP::TNE);
return 0;
}

//INVALID
case range9(0x37, 0x3f): {
return 0;
}

Expand Down Expand Up @@ -1486,6 +1501,7 @@ auto RSP::Recompiler::isTerminal(u32 instruction) -> bool {
#undef Vd
#undef Vs
#undef Vt
#undef Code
#undef i16
#undef n16
#undef n26
Expand Down
1 change: 1 addition & 0 deletions ares/n64/rsp/rsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ RSP rsp;
#include "debugger.cpp"
#include "serialization.cpp"
#include "disassembler.cpp"
#include "emux.cpp"

auto RSP::load(Node::Object parent) -> void {
node = parent->append<Node::Object>("RSP");
Expand Down
8 changes: 8 additions & 0 deletions ares/n64/rsp/rsp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct RSP : Thread, Memory::RCP<RSP> {
struct Tracer {
Node::Debugger::Tracer::Instruction instruction;
Node::Debugger::Tracer::Notification io;
i32 instructionCountdown = 0;
} tracer;
} debugger;

Expand Down Expand Up @@ -476,6 +477,13 @@ struct RSP : Thread, Memory::RCP<RSP> {
template<u8 e> auto VXOR(r128& rd, cr128& vs, cr128& vt) -> void;
template<u8 e> auto VZERO(r128& rd, cr128& vs, cr128& vt) -> void;

//emux.cpp
auto TNE(cr32& rt, cr32& rs, u32 code) -> void;
auto EMUX(cr32& rt, u32 code) -> void;
struct {
u32 buflen;
} emux;

//unserialized:
u16 reciprocals[512];
u16 inverseSquareRoots[512];
Expand Down