mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 07:39:26 +01:00
DSPLLE: Implement conditional variants of RTI
This commit is contained in:
parent
f9e36bfa67
commit
9b1d370478
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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},
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
|
||||
|
55
Source/DSPSpy/tests/rti_test.ds
Normal file
55
Source/DSPSpy/tests/rti_test.ds
Normal 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
|
Loading…
x
Reference in New Issue
Block a user