From d9507260418d233faea32b2c07acc254455a4089 Mon Sep 17 00:00:00 2001 From: nakeee Date: Sun, 11 Apr 2010 18:06:29 +0000 Subject: [PATCH] DSP Jit: Jit some more AR action and added compile SR which suppose to hold the status for flags such as S40 which we can use to optimize compile. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5331 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/DSPCore.vcproj | 4 + Source/Core/DSPCore/Src/DSPCore.cpp | 2 +- Source/Core/DSPCore/Src/DSPEmitter.cpp | 3 + Source/Core/DSPCore/Src/DSPEmitter.h | 14 ++ Source/Core/DSPCore/Src/DSPTables.cpp | 24 +-- Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp | 217 +++++++++++++++++++++ Source/Core/DSPCore/Src/SConscript | 2 +- 7 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 Source/Core/DSPCore/Src/Jit/DSPJitMisc.cpp diff --git a/Source/Core/DSPCore/DSPCore.vcproj b/Source/Core/DSPCore/DSPCore.vcproj index 16157c4d3d..05917ca096 100644 --- a/Source/Core/DSPCore/DSPCore.vcproj +++ b/Source/Core/DSPCore/DSPCore.vcproj @@ -457,6 +457,10 @@ RelativePath=".\Src\Jit\DSPJitUtil.cpp" > + + > 5) & 0x1f; + + u16 val = dsp_op_read_reg(sreg); + dsp_op_write_reg(dreg, val); + dsp_conditional_extend_accum(dreg); +} +*/ + +// LRI $D, #I +// 0000 0000 100d dddd +// iiii iiii iiii iiii +// Load immediate value I to register $D. +// FIXME: Perform additional operation depending on destination register. +// +// DSPSpy discovery: This, and possibly other instructions that load a +// register, has a different behaviour in S40 mode if loaded to AC0.M: The +// value gets sign extended to the whole accumulator! This does not happen in +// S16 mode. +/*void DSPEmitter::lri(const UDSPInstruction opc) +{ + u8 reg = opc & DSP_REG_MASK; + u16 imm = dsp_fetch_code(); + dsp_op_write_reg(reg, imm); + dsp_conditional_extend_accum(reg); +} + + +// LRIS $(0x18+D), #I +// 0000 1ddd iiii iiii +// Load immediate value I (8-bit sign extended) to accumulator register. +// FIXME: Perform additional operation depending on destination register. +void DSPEmitter::lris(const UDSPInstruction opc) +{ + u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0; + u16 imm = (s8)opc; + dsp_op_write_reg(reg, imm); + dsp_conditional_extend_accum(reg); +} + +//---- + +// NX +// 1000 -000 xxxx xxxx +// No operation, but can be extended with extended opcode. +// This opcode is supposed to do nothing - it's used if you want to use +// an opcode extension but not do anything. At least according to duddie. +void DSPEmitter::nx(const UDSPInstruction opc) +{ + zeroWriteBackLog(); +} +*/ +//---- + +// DAR $arD +// 0000 0000 0000 01dd +// Decrement address register $arD. +void DSPEmitter::dar(const UDSPInstruction opc) +{ + // g_dsp.r[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3); + decrement_addr_reg(opc & 0x3); + +} + +// IAR $arD +// 0000 0000 0000 10dd +// Increment address register $arD. +void DSPEmitter::iar(const UDSPInstruction opc) +{ + // g_dsp.r[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3); + increment_addr_reg(opc & 0x3); +} + +// SUBARN $arD +// 0000 0000 0000 11dd +// Subtract indexing register $ixD from an addressing register $arD. +// used only in IPL-NTSC ucode +void DSPEmitter::subarn(const UDSPInstruction opc) +{ + // u8 dreg = opc & 0x3; + // g_dsp.r[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]); + decrease_addr_reg(opc & 0x3); +} + +// ADDARN $arD, $ixS +// 0000 0000 0001 ssdd +// Adds indexing register $ixS to an addressing register $arD. +// It is critical for the Zelda ucode that this one wraps correctly. +void DSPEmitter::addarn(const UDSPInstruction opc) +{ + // u8 dreg = opc & 0x3; + // u8 sreg = (opc >> 2) & 0x3; + // g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]); + + // From looking around it is always called with the matching index register + increase_addr_reg(opc & 0x3); +} + +//---- + + +void DSPEmitter::setSR(u16 bit) { + + // (1 << bit) + MOV(32, R(EAX), Imm32(1)); + SHR(32, R(EAX), Imm32(bit)); + + // g_dsp.r[DSP_REG_SR] |= EAX + MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR])); + OR(32, R(ECX), R(EAX)); + + compileSR |= (1 << bit); +} + +void DSPEmitter::clrSR(u16 bit) { + // ~(1 << bit) + MOV(32, R(EAX), Imm32(1)); + SHR(32, R(EAX), Imm32(bit)); + NOT(32, R(EAX)); + + // g_dsp.r[DSP_REG_SR] &= EAX + MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR])); + AND(32, R(ECX), R(EAX)); + + compileSR &= ~(1 << bit); +} +// SBCLR #I +// 0001 0011 aaaa aiii +// bit of status register $sr. Bit number is calculated by adding 6 to +// immediate value I. +void DSPEmitter::sbclr(const UDSPInstruction opc) +{ + u16 bit = (opc & 0x7) + 6; + + clrSR(bit); +} + +// SBSET #I +// 0001 0010 aaaa aiii +// Set bit of status register $sr. Bit number is calculated by adding 6 to +// immediate value I. +void DSPEmitter::sbset(const UDSPInstruction opc) +{ + u8 bit = (opc & 0x7) + 6; + setSR(bit); +} + +// This is a bunch of flag setters, flipping bits in SR. So far so good, +// but it's harder to know exactly what effect they have. +void DSPEmitter::srbith(const UDSPInstruction opc) +{ + ABI_CallFunction((void *)zeroWriteBackLog); + switch ((opc >> 8) & 0xf) + { + // M0/M2 change the multiplier mode (it can multiply by 2 for free). + case 0xa: // M2 + clrSR(SR_MUL_MODIFY); + break; + case 0xb: // M0 + setSR(SR_MUL_MODIFY); + break; + + // If set, treat multiplicands as unsigned. + // If clear, treat them as signed. + case 0xc: // CLR15 + clrSR(SR_MUL_UNSIGNED); + break; + case 0xd: // SET15 + setSR(SR_MUL_UNSIGNED); + break; + + // Automatic 40-bit sign extension when loading ACx.M. + // SET40 changes something very important: see the LRI instruction above. + case 0xe: // SET16 (CLR40) + clrSR(SR_40_MODE_BIT); + break; + + case 0xf: // SET40 + setSR(SR_40_MODE_BIT); + g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT; + break; + + default: + break; + } +} + diff --git a/Source/Core/DSPCore/Src/SConscript b/Source/Core/DSPCore/Src/SConscript index 8433d084a1..61b7016bb7 100644 --- a/Source/Core/DSPCore/Src/SConscript +++ b/Source/Core/DSPCore/Src/SConscript @@ -26,7 +26,7 @@ files = [ "DSPTables.cpp", "Jit/DSPJitExtOps.cpp", "Jit/DSPJitUtil.cpp", - + "Jit/DSPJitMisc.cpp", ] acenv = env.Clone()