DSPLLE: Split SRS into SRS and SRSH

Hardware testing indicated that SRS uses a different list of registers than LRS (specifically, acS.h can be used with SRSH but not LRS, and SRS does not support AX registers, and there are 2 encodings that do nothing).
This commit is contained in:
Pokechu22
2021-08-15 15:31:23 -07:00
parent 51c26d82a5
commit f9e36bfa67
9 changed files with 186 additions and 18 deletions

View File

@ -18,7 +18,7 @@
namespace DSP
{
// clang-format off
const std::array<DSPOPCTemplate, 214> s_opcodes =
const std::array<DSPOPCTemplate, 215> 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
@ -192,7 +192,8 @@ const std::array<DSPOPCTemplate, 214> s_opcodes =
//2
{"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, false, false, false, false, false}, // $(D+24) = MEM[($cr[0-7] << 8) | I]
{"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, false, false, false, false, false}, // MEM[($cr[0-7] << 8) | I] = $(S+24)
{"SRSH", 0x2800, 0xfe00, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_ACCH, 1, 0, 8, 0x0100}}, false, false, false, false, false}, // MEM[($cr[0-7] << 8) | I] = $acS.h
{"SRS", 0x2c00, 0xfc00, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG1C, 1, 0, 8, 0x0300}}, false, false, false, false, false}, // MEM[($cr[0-7] << 8) | I] = $(S+24)
// opcodes that can be extended

View File

@ -44,16 +44,13 @@ enum partype_t
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
// The following are not in gcdsptool
P_ACCM_D = P_REG | 0x1e80,
P_ACC = P_REG | 0x2000, // used for full accum.
P_ACC = P_REG | 0x2000, // used for full accum.
P_ACCH = P_REG | 0x1000, // used for high part of accum
P_ACC_D = P_REG | 0x2080,
P_AX = P_REG | 0x2200,
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
P_REF = P_REG | 0x4000,
P_PRG = P_REF | P_REG,
// The following seem like junk:
// P_REG10 = P_REG | 0x1000,
// P_AX_D = P_REG | 0x2280,
};
struct param2_t

View File

@ -8,15 +8,29 @@
namespace DSP::Interpreter
{
// SRS @M, $(0x18+S)
// 0010 1sss mmmm mmmm
// Move value from register $(0x18+S) to data memory pointed by address
// SRSH @M, $acS.h
// 0010 10ss mmmm mmmm
// Move value from register $acS.h to data memory pointed by address
// CR[0-7] | M. That is, the upper 8 bits of the address are the
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
void Interpreter::srsh(const UDSPInstruction opc)
{
auto& state = m_dsp_core.DSPState();
const auto reg = static_cast<u8>(((opc >> 8) & 0x1) + DSP_REG_ACH0);
const auto addr = static_cast<u16>((state.r.cr << 8) | (opc & 0xFF));
state.WriteDMEM(addr, OpReadRegister(reg));
}
// SRS @M, $(0x1C+S)
// 0010 11ss mmmm mmmm
// Move value from register $(0x1C+S) to data memory pointed by address
// CR[0-7] | M. That is, the upper 8 bits of the address are the
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
void Interpreter::srs(const UDSPInstruction opc)
{
auto& state = m_dsp_core.DSPState();
const auto reg = static_cast<u8>(((opc >> 8) & 0x7) + 0x18);
const auto reg = static_cast<u8>(((opc >> 8) & 0x3) + DSP_REG_ACL0);
const auto addr = static_cast<u16>((state.r.cr << 8) | (opc & 0xFF));
if (reg >= DSP_REG_ACM0)

View File

@ -19,7 +19,7 @@ struct InterpreterOpInfo
};
// clang-format off
constexpr std::array<InterpreterOpInfo, 124> s_opcodes
constexpr std::array<InterpreterOpInfo, 125> s_opcodes
{{
{0x0000, 0xfffc, &Interpreter::nop},
@ -101,7 +101,8 @@ constexpr std::array<InterpreterOpInfo, 124> s_opcodes
// 2
{0x2000, 0xf800, &Interpreter::lrs},
{0x2800, 0xf800, &Interpreter::srs},
{0x2800, 0xfe00, &Interpreter::srsh},
{0x2c00, 0xfc00, &Interpreter::srs},
// opcodes that can be extended

View File

@ -149,6 +149,7 @@ public:
void srri(UDSPInstruction opc);
void srrn(UDSPInstruction opc);
void srs(UDSPInstruction opc);
void srsh(UDSPInstruction opc);
void sub(UDSPInstruction opc);
void subarn(UDSPInstruction opc);
void subax(UDSPInstruction opc);

View File

@ -88,6 +88,7 @@ public:
void bloopi(UDSPInstruction opc);
// Load/Store
void srsh(UDSPInstruction opc);
void srs(UDSPInstruction opc);
void lrs(UDSPInstruction opc);
void lr(UDSPInstruction opc);

View File

@ -12,14 +12,35 @@ using namespace Gen;
namespace DSP::JIT::x64
{
// SRS @M, $(0x18+S)
// SRSH @M, $acS.h
// 0010 1sss mmmm mmmm
// Move value from register $(0x18+S) to data memory pointed by address
// Move value from register $acS.h to data memory pointed by address
// CR[0-7] | M. That is, the upper 8 bits of the address are the
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
void DSPEmitter::srsh(const UDSPInstruction opc)
{
u8 reg = ((opc >> 8) & 0x1) + DSP_REG_ACH0;
// u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
X64Reg tmp1 = m_gpr.GetFreeXReg();
dsp_op_read_reg(reg, tmp1, RegisterExtension::Zero);
dsp_op_read_reg(DSP_REG_CR, RAX, RegisterExtension::Zero);
SHL(16, R(EAX), Imm8(8));
OR(16, R(EAX), Imm16(opc & 0xFF));
dmem_write(tmp1);
m_gpr.PutXReg(tmp1);
}
// SRS @M, $(0x1C+S)
// 0010 1sss mmmm mmmm
// Move value from register $(0x1C+S) to data memory pointed by address
// CR[0-7] | M. That is, the upper 8 bits of the address are the
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
void DSPEmitter::srs(const UDSPInstruction opc)
{
u8 reg = ((opc >> 8) & 0x7) + 0x18;
u8 reg = ((opc >> 8) & 0x3) + DSP_REG_ACL0;
// u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
X64Reg tmp1 = m_gpr.GetFreeXReg();

View File

@ -19,7 +19,7 @@ struct JITOpInfo
};
// clang-format off
const std::array<JITOpInfo, 124> s_opcodes =
const std::array<JITOpInfo, 125> s_opcodes =
{{
{0x0000, 0xfffc, &DSPEmitter::nop},
@ -101,7 +101,8 @@ const std::array<JITOpInfo, 124> s_opcodes =
// 2
{0x2000, 0xf800, &DSPEmitter::lrs},
{0x2800, 0xf800, &DSPEmitter::srs},
{0x2800, 0xfe00, &DSPEmitter::srsh},
{0x2c00, 0xfc00, &DSPEmitter::srs},
// opcodes that can be extended