DSPLLE: Implement conditional variants of RTI

This commit is contained in:
Pokechu22 2021-08-16 00:10:21 -07:00
parent f9e36bfa67
commit 9b1d370478
7 changed files with 96 additions and 12 deletions

View file

@ -18,7 +18,7 @@
namespace DSP
{
// clang-format off
const std::array<DSPOPCTemplate, 215> s_opcodes =
const std::array<DSPOPCTemplate, 230> s_opcodes =
{{
// # of parameters----+ {type, size, loc, lshift, mask} branch reads PC // instruction approximation
// name opcode mask size-V V param 1 param 2 param 3 extendable uncond. updates SR
@ -48,7 +48,22 @@ const std::array<DSPOPCTemplate, 215> s_opcodes =
{"RETO", 0x02de, 0xffff, 1, 0, {}, false, true, false, true, false}, // return if overflow
{"RET", 0x02df, 0xffff, 1, 0, {}, false, true, true, false, false}, // unconditional return
{"RTI", 0x02ff, 0xffff, 1, 0, {}, false, true, true, false, false}, // return from interrupt
{"RTIGE", 0x02f0, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if greater or equal
{"RTIL", 0x02f1, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if less
{"RTIG", 0x02f2, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if greater
{"RTILE", 0x02f3, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if less or equal
{"RTINZ", 0x02f4, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if not zero
{"RTIZ", 0x02f5, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if zero
{"RTINC", 0x02f6, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if not carry
{"RTIC", 0x02f7, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if carry
{"RTIx8", 0x02f8, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if TODO
{"RTIx9", 0x02f9, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if TODO
{"RTIxA", 0x02fa, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if TODO
{"RTIxB", 0x02fb, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if TODO
{"RTILNZ", 0x02fc, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if logic not zero
{"RTILZ", 0x02fd, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if logic zero
{"RTIO", 0x02fe, 0xffff, 1, 0, {}, false, true, false, true, false}, // return from interrupt if overflow
{"RTI", 0x02ff, 0xffff, 1, 0, {}, false, true, true, false, false}, // return from interrupt unconditionally
{"CALLGE", 0x02b0, 0xffff, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, // call if greater or equal
{"CALLL", 0x02b1, 0xffff, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, false, true, false, true, false}, // call if less

View file

@ -104,13 +104,17 @@ void Interpreter::ret(const UDSPInstruction opc)
state.pc = state.PopStack(StackRegister::Call);
}
// RTI
// RTIcc
// 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
void Interpreter::rti(const UDSPInstruction)
// This instruction has a conditional form, but it is not used by any official ucode.
void Interpreter::rti(const UDSPInstruction opc)
{
if (!CheckCondition(opc & 0xf))
return;
auto& state = m_dsp_core.DSPState();
state.r.sr = state.PopStack(StackRegister::Data);
state.pc = state.PopStack(StackRegister::Call);

View file

@ -32,7 +32,7 @@ constexpr std::array<InterpreterOpInfo, 125> s_opcodes
{0x02d0, 0xfff0, &Interpreter::ret},
{0x02ff, 0xffff, &Interpreter::rti},
{0x02f0, 0xfff0, &Interpreter::rti},
{0x02b0, 0xfff0, &Interpreter::call},

View file

@ -221,6 +221,7 @@ private:
void r_callr(UDSPInstruction opc);
void r_ifcc(UDSPInstruction opc);
void r_ret(UDSPInstruction opc);
void r_rti(UDSPInstruction opc);
void Update_SR_Register(Gen::X64Reg val = Gen::EAX, Gen::X64Reg scratch = Gen::EDX);

View file

@ -255,12 +255,7 @@ void DSPEmitter::ret(const UDSPInstruction opc)
ReJitConditional(opc, &DSPEmitter::r_ret);
}
// RTI
// 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
void DSPEmitter::rti(const UDSPInstruction opc)
void DSPEmitter::r_rti(const UDSPInstruction opc)
{
// g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(StackRegister::Data);
dsp_reg_load_stack(StackRegister::Data);
@ -268,6 +263,20 @@ void DSPEmitter::rti(const UDSPInstruction opc)
// g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
dsp_reg_load_stack(StackRegister::Call);
MOV(16, M_SDSP_pc(), R(DX));
WriteBranchExit();
}
// RTIcc
// 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
// This instruction has a conditional form, but it is not used by any official ucode.
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
void DSPEmitter::rti(const UDSPInstruction opc)
{
MOV(16, M_SDSP_pc(), Imm16(m_compile_pc + 1));
ReJitConditional(opc, &DSPEmitter::r_rti);
}
// HALT

View file

@ -32,7 +32,7 @@ const std::array<JITOpInfo, 125> s_opcodes =
{0x02d0, 0xfff0, &DSPEmitter::ret},
{0x02ff, 0xffff, &DSPEmitter::rti},
{0x02f0, 0xfff0, &DSPEmitter::rti},
{0x02b0, 0xfff0, &DSPEmitter::call},

View file

@ -0,0 +1,55 @@
; This test needs to manually specify IRQs
jmp irq0
jmp irq1
jmp irq2
jmp irq3
jmp irq4
jmp accov_irq
jmp irq6
jmp irq7
incdir "tests"
include "dsp_base_noirq.inc"
test_main:
; Use the accelerator to generate an IRQ by setting the start and end address to 0
; This will result in an interrupt on every read
SI @0xffda, #0 ; pred_scale
SI @0xffdb, #0 ; yn1
SI @0xffdc, #0 ; yn2
SI @0xffd1, #0 ; SampleFormat
SI @ACSAH, #0
SI @ACCAH, #0
SI @ACSAL, #0
SI @ACCAL, #0
SI @ACEAH, #0
SI @ACEAL, #0
LRI $AX1.H, #0x0000
LRS $AX0.L, @ARAM ; Trigger interrupt
CALL send_back
LRI $AX1.H, #0x0001
LRS $AX0.L, @ARAM ; Trigger interrupt
CALL send_back
LRI $AX1.H, #0x0000
LRS $AX0.L, @ARAM ; Trigger interrupt
CALL send_back
jmp end_of_test
accov_irq:
; Restore registers, otherwise no new interrupt will be generated
SI @0xffda, #0 ; pred_scale
SI @0xffdb, #0 ; yn1
SI @0xffdc, #0 ; yn2
TSTAXH $AX1.H
LRI $AX1.L, #0x1111
cw 0x02f4 ; RTINZ if it exists
LRI $AX1.L, #0x2222
cw 0x02f5 ; RTIZ if it exists
LRI $AX1.L, #0x3333
RTI