Core/DSP: Access all registers except ST* through the regcache

No speed difference, probably because our basic blocks are
too small to contain more than one access to any register
or used too seldom for multiple accesses to make a difference.



git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7260 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
pierre
2011-02-27 18:04:35 +00:00
parent ff62f492e6
commit d56390407f
12 changed files with 1483 additions and 774 deletions
+18 -15
View File
@@ -87,10 +87,11 @@ void DSPEmitter::checkExceptions(u32 retval)
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
DSPJitRegCache c(gpr);
SaveDSPRegs();
gpr.saveRegs();
ABI_CallFunction((void *)&DSPCore_CheckExceptions);
MOV(32, R(EAX), Imm32(retval));
JMP(returnDispatcher, true);
gpr.loadRegs(false);
gpr.flushRegs(c,false);
SetJumpTarget(skipCheck);
@@ -107,9 +108,9 @@ void DSPEmitter::Default(UDSPInstruction inst)
}
// Fall back to interpreter
SaveDSPRegs();
gpr.pushRegs();
ABI_CallFunctionC16((void*)opTable[inst]->intFunc, inst);
LoadDSPRegs();
gpr.popRegs();
}
void DSPEmitter::EmitInstruction(UDSPInstruction inst)
@@ -122,9 +123,9 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
if ((inst >> 12) == 0x3) {
if (! extOpTable[inst & 0x7F]->jitFunc) {
// Fall back to interpreter
SaveDSPRegs();
gpr.pushRegs();
ABI_CallFunctionC16((void*)extOpTable[inst & 0x7F]->intFunc, inst);
LoadDSPRegs();
gpr.popRegs();
INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x\n", inst);
ext_is_jit = false;
} else {
@@ -134,9 +135,9 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
} else {
if (!extOpTable[inst & 0xFF]->jitFunc) {
// Fall back to interpreter
SaveDSPRegs();
gpr.pushRegs();
ABI_CallFunctionC16((void*)extOpTable[inst & 0xFF]->intFunc, inst);
LoadDSPRegs();
gpr.popRegs();
INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x\n", inst);
ext_is_jit = false;
} else {
@@ -161,9 +162,9 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
if (!ext_is_jit) {
//need to call the online cleanup function because
//the writeBackLog gets populated at runtime
SaveDSPRegs();
gpr.pushRegs();
ABI_CallFunction((void*)::applyWriteBackLog);
LoadDSPRegs();
gpr.popRegs();
} else {
popExtValueToReg();
}
@@ -189,10 +190,10 @@ void DSPEmitter::Compile(u16 start_addr)
return;
if (g_dsp.exceptions == 0)
return;
return;
*/
LoadDSPRegs();
gpr.loadRegs();
blockLinkEntry = GetCodePtr();
@@ -240,7 +241,7 @@ void DSPEmitter::Compile(u16 start_addr)
// end of each block and in this order
DSPJitRegCache c(gpr);
HandleLoop();
SaveDSPRegs();
gpr.saveRegs();
if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
@@ -250,6 +251,7 @@ void DSPEmitter::Compile(u16 start_addr)
MOV(16, R(EAX), Imm16(blockSize[start_addr]));
}
JMP(returnDispatcher, true);
gpr.loadRegs(false);
gpr.flushRegs(c,false);
SetJumpTarget(rLoopAddressExit);
@@ -273,7 +275,7 @@ void DSPEmitter::Compile(u16 start_addr)
DSPJitRegCache c(gpr);
//don't update g_dsp.pc -- the branch insn already did
SaveDSPRegs();
gpr.saveRegs();
if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
@@ -283,6 +285,7 @@ void DSPEmitter::Compile(u16 start_addr)
MOV(16, R(EAX), Imm16(blockSize[start_addr]));
}
JMP(returnDispatcher, true);
gpr.loadRegs(false);
gpr.flushRegs(c,false);
SetJumpTarget(rNoBranch);
@@ -334,7 +337,7 @@ void DSPEmitter::Compile(u16 start_addr)
blockSize[start_addr] = 1;
}
SaveDSPRegs();
gpr.saveRegs();
if (!DSPHost_OnThread() && DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
MOV(16, R(EAX), Imm16(DSP_IDLE_SKIP_CYCLES));
@@ -342,7 +345,7 @@ void DSPEmitter::Compile(u16 start_addr)
else
{
MOV(16, R(EAX), Imm16(blockSize[start_addr]));
}
}
JMP(returnDispatcher, true);
}
+10 -15
View File
@@ -52,8 +52,10 @@ public:
// CC Util
void Update_SR_Register64(Gen::X64Reg val = Gen::EAX);
void Update_SR_Register64_Carry(Gen::X64Reg val = Gen::EAX);
void Update_SR_Register64_Carry2(Gen::X64Reg val = Gen::EAX);
void Update_SR_Register64_Carry(Gen::X64Reg val,
Gen::X64Reg carry_ovfl);
void Update_SR_Register64_Carry2(Gen::X64Reg val,
Gen::X64Reg carry_ovfl);
void Update_SR_Register16(Gen::X64Reg val = Gen::EAX);
void Update_SR_Register16_OverS32(Gen::X64Reg val = Gen::EAX);
@@ -65,13 +67,13 @@ public:
// Memory helper functions
void increment_addr_reg(int reg);
void decrement_addr_reg(int reg);
void increase_addr_reg(int reg);
void increase_addr_reg(int reg, int ix_reg);
void decrease_addr_reg(int reg);
void imem_read();
void dmem_read();
void imem_read(Gen::X64Reg address);
void dmem_read(Gen::X64Reg address);
void dmem_read_imm(u16 addr);
void dmem_write();
void dmem_write_imm(u16 addr);
void dmem_write(Gen::X64Reg value);
void dmem_write_imm(u16 addr, Gen::X64Reg value);
// Ext command helpers
void pushExtValueFromReg(u16 dreg, u16 sreg);
@@ -250,6 +252,7 @@ public:
// CALL this to start the dispatcher
const u8 *enterDispatcher;
const u8 *reenterDispatcher;
const u8 *stubEntryPoint;
const u8 *returnDispatcher;
u16 compilePC;
@@ -259,10 +262,6 @@ public:
std::list<u16> *unresolvedJumps;
DSPJitRegCache gpr;
void LoadDSPRegs();
void SaveDSPRegs();
private:
DSPCompiledCode *blocks;
Block blockLinkEntry;
@@ -275,12 +274,8 @@ private:
// Counts down.
// int cycles;
void Update_SR_Register(Gen::X64Reg val = Gen::EAX);
void ToMask(Gen::X64Reg value_reg = Gen::EDI);
void dsp_increment_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
void dsp_decrement_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
void get_long_prod(Gen::X64Reg long_prod = Gen::RAX);
void get_long_prod_round_prodl(Gen::X64Reg long_prod = Gen::RAX);
void set_long_prod();
File diff suppressed because it is too large Load Diff
+14 -9
View File
@@ -56,8 +56,8 @@ static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
emitter.TEST(16, R(EAX), Imm16(1));
//LE: problem in here, half the tests fail
skipCode2 = emitter.J_CC(CC_NE);
//skipCode2 = emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
skipCode2 = emitter.J_CC(CC_NE, true);
//skipCode2 = emitter.J_CC((CCFlags)(CC_NE - (cond & 1)), true);
emitter.dsp_op_read_reg(DSP_REG_SR, RAX);
emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
break;
@@ -94,7 +94,7 @@ static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
break;
//c2 = emitter.gpr;
//emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS));
//skipCode2 = emitter.J_CC((CCFlags)(CC_E + (cond & 1)));
//skipCode2 = emitter.J_CC((CCFlags)(CC_E + (cond & 1)), true);
//emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
//break;
}
@@ -107,7 +107,7 @@ static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
break;
}
DSPJitRegCache c1(emitter.gpr);
FixupBranch skipCode = cond == 0xe ? emitter.J_CC(CC_E) : emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
FixupBranch skipCode = cond == 0xe ? emitter.J_CC(CC_E,true) : emitter.J_CC((CCFlags)(CC_NE - (cond & 1)),true);
jitCode(opc,emitter);
emitter.gpr.flushRegs(c1);
emitter.SetJumpTarget(skipCode);
@@ -121,7 +121,8 @@ static void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
static void WriteBranchExit(DSPEmitter& emitter)
{
emitter.SaveDSPRegs();
DSPJitRegCache c(emitter.gpr);
emitter.gpr.saveRegs();
if (DSPAnalyzer::code_flags[emitter.startAddr] & DSPAnalyzer::CODE_IDLE_SKIP)
{
emitter.MOV(16, R(EAX), Imm16(0x1000));
@@ -131,6 +132,8 @@ static void WriteBranchExit(DSPEmitter& emitter)
emitter.MOV(16, R(EAX), Imm16(emitter.blockSize[emitter.startAddr]));
}
emitter.JMP(emitter.returnDispatcher, true);
emitter.gpr.loadRegs(false);
emitter.gpr.flushRegs(c,false);
}
static void WriteBlockLink(DSPEmitter& emitter, u16 dest)
@@ -142,12 +145,12 @@ static void WriteBlockLink(DSPEmitter& emitter, u16 dest)
{
emitter.gpr.flushRegs();
// Check if we have enough cycles to execute the next block
emitter.MOV(16, R(ESI), M(&cyclesLeft));
emitter.CMP(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
emitter.MOV(16, R(ECX), M(&cyclesLeft));
emitter.CMP(16, R(ECX), Imm16(emitter.blockSize[emitter.startAddr] + emitter.blockSize[dest]));
FixupBranch notEnoughCycles = emitter.J_CC(CC_BE);
emitter.SUB(16, R(ESI), Imm16(emitter.blockSize[emitter.startAddr]));
emitter.MOV(16, M(&cyclesLeft), R(ESI));
emitter.SUB(16, R(ECX), Imm16(emitter.blockSize[emitter.startAddr]));
emitter.MOV(16, M(&cyclesLeft), R(ECX));
emitter.JMP(emitter.blockLinks[dest], true);
emitter.SetJumpTarget(notEnoughCycles);
}
@@ -339,9 +342,11 @@ void DSPEmitter::HandleLoop()
FixupBranch loopUpdated = J(true);
SetJumpTarget(loadStack);
DSPJitRegCache c(gpr);
dsp_reg_load_stack(0);
dsp_reg_load_stack(2);
dsp_reg_load_stack(3);
gpr.flushRegs(c);
SetJumpTarget(loopUpdated);
SetJumpTarget(rLoopAddrG);
+19 -22
View File
@@ -22,12 +22,12 @@
#include "../DSPIntUtil.h"
#include "../DSPEmitter.h"
#include "DSPJitUtil.h"
#include "x64Emitter.h"
#include "ABI.h"
using namespace Gen;
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register(Gen::X64Reg val)
{
@@ -72,7 +72,6 @@ void DSPEmitter::Update_SR_Register(Gen::X64Reg val)
}
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register64(Gen::X64Reg val)
{
@@ -86,18 +85,18 @@ void DSPEmitter::Update_SR_Register64(Gen::X64Reg val)
#endif
}
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// In: (val): s64 _Value
// In: (carry_ovfl): 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
{
void DSPEmitter::Update_SR_Register64_Carry(X64Reg val, X64Reg carry_ovfl)
{
#ifdef _M_X64
OpArg sr_reg;
gpr.getReg(DSP_REG_SR,sr_reg);
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
CMP(64, R(RCX), R(val));
CMP(64, R(carry_ovfl), R(val));
// 0x01
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
@@ -110,10 +109,10 @@ void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW;
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY;
// Overflow = ((acc ^ res) & (ax ^ res)) < 0
XOR(64, R(RCX), R(val));
XOR(64, R(carry_ovfl), R(val));
XOR(64, R(RDX), R(val));
AND(64, R(RCX), R(RDX));
CMP(64, R(RCX), Imm8(0));
AND(64, R(carry_ovfl), R(RDX));
CMP(64, R(carry_ovfl), Imm8(0));
FixupBranch noOverflow = J_CC(CC_GE);
OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
SetJumpTarget(noOverflow);
@@ -123,10 +122,10 @@ void DSPEmitter::Update_SR_Register64_Carry(Gen::X64Reg val)
#endif
}
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// In: (val): s64 _Value
// In: (carry_ovfl): 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
void DSPEmitter::Update_SR_Register64_Carry2(X64Reg val, X64Reg carry_ovfl)
{
#ifdef _M_X64
OpArg sr_reg;
@@ -134,7 +133,7 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
AND(16, sr_reg, Imm16(~SR_CMP_MASK));
CMP(64, R(RCX), R(val));
CMP(64, R(carry_ovfl), R(val));
// 0x01
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
@@ -147,10 +146,10 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW;
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY;
// Overflow = ((acc ^ res) & (ax ^ res)) < 0
XOR(64, R(RCX), R(val));
XOR(64, R(carry_ovfl), R(val));
XOR(64, R(RDX), R(val));
AND(64, R(RCX), R(RDX));
CMP(64, R(RCX), Imm8(0));
AND(64, R(carry_ovfl), R(RDX));
CMP(64, R(carry_ovfl), Imm8(0));
FixupBranch noOverflow = J_CC(CC_GE);
OR(16, sr_reg, Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
SetJumpTarget(noOverflow);
@@ -171,9 +170,8 @@ void DSPEmitter::Update_SR_Register64_Carry2(Gen::X64Reg val)
//}
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
void DSPEmitter::Update_SR_Register16(X64Reg val)
{
#ifdef _M_X64
OpArg sr_reg;
@@ -214,7 +212,6 @@ void DSPEmitter::Update_SR_Register16(Gen::X64Reg val)
}
// In: RAX: s64 _Value
// In: RCX: 1 = carry, 2 = overflow
// Clobbers RDX
void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val)
{
@@ -225,8 +222,8 @@ void DSPEmitter::Update_SR_Register16_OverS32(Gen::X64Reg val)
// // 0x10
// if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
MOVSX(64, 32, RSI, R(val));
CMP(64, R(RSI), R(val));
MOVSX(64, 32, RCX, R(val));
CMP(64, R(RCX), R(val));
FixupBranch noOverS32 = J_CC(CC_E);
OR(16, sr_reg, Imm16(SR_OVER_S32));
SetJumpTarget(noOverS32);
File diff suppressed because it is too large Load Diff
+135 -38
View File
@@ -35,11 +35,18 @@ void DSPEmitter::srs(const UDSPInstruction opc)
{
u8 reg = ((opc >> 8) & 0x7) + 0x18;
//u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
dsp_op_read_reg(reg, RCX, ZERO);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1, ZERO);
dsp_op_read_reg(DSP_REG_CR, RAX, ZERO);
SHL(16, R(EAX), Imm8(8));
OR(8, R(EAX), Imm8(opc & 0xFF));
dmem_write();
OR(16, R(EAX), Imm16(opc & 0xFF));
dmem_write(tmp1);
gpr.putXReg(tmp1);
}
// LRS $(0x18+D), @M
@@ -50,11 +57,18 @@ void DSPEmitter::srs(const UDSPInstruction opc)
void DSPEmitter::lrs(const UDSPInstruction opc)
{
u8 reg = ((opc >> 8) & 0x7) + 0x18;
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
dsp_op_read_reg(DSP_REG_CR, RCX, ZERO);
SHL(16, R(ECX), Imm8(8));
OR(8, R(ECX), Imm8(opc & 0xFF));
dmem_read();
dsp_op_read_reg(DSP_REG_CR, tmp1, ZERO);
SHL(16, R(tmp1), Imm8(8));
OR(16, R(tmp1), Imm16(opc & 0xFF));
dmem_read(tmp1);
gpr.putXReg(tmp1);
dsp_op_write_reg(reg, RAX);
dsp_conditional_extend_accum(reg);
}
@@ -82,8 +96,14 @@ void DSPEmitter::sr(const UDSPInstruction opc)
{
u8 reg = opc & DSP_REG_MASK;
u16 address = dsp_imem_read(compilePC + 1);
dsp_op_read_reg(reg, ECX);
dmem_write_imm(address);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1);
dmem_write_imm(address, tmp1);
gpr.putXReg(tmp1);
}
// SI @M, #I
@@ -95,8 +115,14 @@ void DSPEmitter::si(const UDSPInstruction opc)
{
u16 address = (s8)opc;
u16 imm = dsp_imem_read(compilePC + 1);
MOV(32, R(ECX), Imm32((u32)imm));
dmem_write_imm(address);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
MOV(32, R(tmp1), Imm32((u32)imm));
dmem_write_imm(address, tmp1);
gpr.putXReg(tmp1);
}
// LRR $D, @$S
@@ -108,8 +134,14 @@ void DSPEmitter::lrr(const UDSPInstruction opc)
u8 sreg = (opc >> 5) & 0x3;
u8 dreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
dmem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dmem_read(tmp1);
gpr.putXReg(tmp1);
dsp_op_write_reg(dreg, EAX);
dsp_conditional_extend_accum(dreg);
}
@@ -124,8 +156,14 @@ void DSPEmitter::lrrd(const UDSPInstruction opc)
u8 sreg = (opc >> 5) & 0x3;
u8 dreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
dmem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dmem_read(tmp1);
gpr.putXReg(tmp1);
dsp_op_write_reg(dreg, EAX);
dsp_conditional_extend_accum(dreg);
decrement_addr_reg(sreg);
@@ -141,8 +179,14 @@ void DSPEmitter::lrri(const UDSPInstruction opc)
u8 sreg = (opc >> 5) & 0x3;
u8 dreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
dmem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dmem_read(tmp1);
gpr.putXReg(tmp1);
dsp_op_write_reg(dreg, EAX);
dsp_conditional_extend_accum(dreg);
increment_addr_reg(sreg);
@@ -158,11 +202,17 @@ void DSPEmitter::lrrn(const UDSPInstruction opc)
u8 sreg = (opc >> 5) & 0x3;
u8 dreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
dmem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dmem_read(tmp1);
gpr.putXReg(tmp1);
dsp_op_write_reg(dreg, EAX);
dsp_conditional_extend_accum(dreg);
increase_addr_reg(sreg);
increase_addr_reg(sreg, sreg);
}
// SRR @$D, $S
@@ -175,9 +225,14 @@ void DSPEmitter::srr(const UDSPInstruction opc)
u8 dreg = (opc >> 5) & 0x3;
u8 sreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dsp_op_read_reg(dreg, RAX, ZERO);
dmem_write();
dmem_write(tmp1);
gpr.putXReg(tmp1);
}
// SRRD @$D, $S
@@ -190,9 +245,15 @@ void DSPEmitter::srrd(const UDSPInstruction opc)
u8 dreg = (opc >> 5) & 0x3;
u8 sreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dsp_op_read_reg(dreg, RAX, ZERO);
dmem_write();
dmem_write(tmp1);
gpr.putXReg(tmp1);
decrement_addr_reg(dreg);
}
@@ -206,9 +267,15 @@ void DSPEmitter::srri(const UDSPInstruction opc)
u8 dreg = (opc >> 5) & 0x3;
u8 sreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dsp_op_read_reg(dreg, RAX, ZERO);
dmem_write();
dmem_write(tmp1);
gpr.putXReg(tmp1);
increment_addr_reg(dreg);
}
@@ -222,10 +289,16 @@ void DSPEmitter::srrn(const UDSPInstruction opc)
u8 dreg = (opc >> 5) & 0x3;
u8 sreg = opc & 0x1f;
dsp_op_read_reg(sreg, ECX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(sreg, tmp1);
dsp_op_read_reg(dreg, RAX, ZERO);
dmem_write();
increase_addr_reg(dreg);
dmem_write(tmp1);
gpr.putXReg(tmp1);
increase_addr_reg(dreg, dreg);
}
// ILRR $acD.m, @$arS
@@ -237,8 +310,14 @@ void DSPEmitter::ilrr(const UDSPInstruction opc)
u16 reg = opc & 0x3;
u16 dreg = (opc >> 8) & 1;
dsp_op_read_reg(reg, RCX, ZERO);
imem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1, ZERO);
imem_read(tmp1);
gpr.putXReg(tmp1);
set_acc_m(dreg, R(RAX));
dsp_conditional_extend_accum(dreg);
}
@@ -252,8 +331,14 @@ void DSPEmitter::ilrrd(const UDSPInstruction opc)
u16 reg = opc & 0x3;
u16 dreg = (opc >> 8) & 1;
dsp_op_read_reg(reg, RCX, ZERO);
imem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1, ZERO);
imem_read(tmp1);
gpr.putXReg(tmp1);
set_acc_m(dreg, R(RAX));
dsp_conditional_extend_accum(dreg);
decrement_addr_reg(reg);
@@ -268,8 +353,14 @@ void DSPEmitter::ilrri(const UDSPInstruction opc)
u16 reg = opc & 0x3;
u16 dreg = (opc >> 8) & 1;
dsp_op_read_reg(reg, RCX, ZERO);
imem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1, ZERO);
imem_read(tmp1);
gpr.putXReg(tmp1);
set_acc_m(dreg, R(RAX));
dsp_conditional_extend_accum(dreg);
increment_addr_reg(reg);
@@ -285,10 +376,16 @@ void DSPEmitter::ilrrn(const UDSPInstruction opc)
u16 reg = opc & 0x3;
u16 dreg = (opc >> 8) & 1;
dsp_op_read_reg(reg, RCX, ZERO);
imem_read();
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
dsp_op_read_reg(reg, tmp1, ZERO);
imem_read(tmp1);
gpr.putXReg(tmp1);
set_acc_m(dreg, R(RAX));
dsp_conditional_extend_accum(dreg);
increase_addr_reg(reg);
increase_addr_reg(reg, reg);
}
+19 -11
View File
@@ -25,7 +25,7 @@ using namespace Gen;
//clobbers:
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
//expects:
void DSPEmitter::dsp_reg_stack_push(int stack_reg)
{
//g_dsp.reg_stack_ptr[stack_reg]++;
@@ -35,30 +35,38 @@ void DSPEmitter::dsp_reg_stack_push(int stack_reg)
AND(8, R(AL), Imm8(DSP_STACK_MASK));
MOV(8, M(&g_dsp.reg_stack_ptr[stack_reg]), R(AL));
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
//g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
MOV(16, R(CX), M(&g_dsp.r.st[stack_reg]));
MOV(16, R(tmp1), M(&g_dsp.r.st[stack_reg]));
#ifdef _M_IX86 // All32
MOVZX(32, 8, EAX, R(AL));
#else
MOVZX(64, 8, RAX, R(AL));
#endif
MOV(16, MComplex(EAX, EAX, 1, (u64)&g_dsp.reg_stack[stack_reg][0]), R(CX));
MOV(16, MComplex(EAX, EAX, 1,
PtrOffset(&g_dsp.reg_stack[stack_reg][0],0)), R(tmp1));
gpr.putXReg(tmp1);
}
//clobbers:
//EAX = (s8)g_dsp.reg_stack_ptr[stack_reg]
//CX = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]]
//expects:
void DSPEmitter::dsp_reg_stack_pop(int stack_reg)
{
//g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
MOV(8, R(AL), M(&g_dsp.reg_stack_ptr[stack_reg]));
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
#ifdef _M_IX86 // All32
MOVZX(32, 8, EAX, R(AL));
#else
MOVZX(64, 8, RAX, R(AL));
#endif
MOV(16, R(CX), MComplex(EAX, EAX, 1, (u64)&g_dsp.reg_stack[stack_reg][0]));
MOV(16, M(&g_dsp.r.st[stack_reg]), R(CX));
MOV(16, R(tmp1), MComplex(EAX, EAX, 1,
PtrOffset(&g_dsp.reg_stack[stack_reg][0],0)));
MOV(16, M(&g_dsp.r.st[stack_reg]), R(tmp1));
gpr.putXReg(tmp1);
//g_dsp.reg_stack_ptr[stack_reg]--;
//g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
@@ -165,7 +173,7 @@ void DSPEmitter::dsp_conditional_extend_accum(int reg)
//}
gpr.flushRegs(c);
SetJumpTarget(not_40bit);
gpr.putReg(DSP_REG_SR);
gpr.putReg(DSP_REG_SR, false);
}
}
}
@@ -181,7 +189,7 @@ void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val)
gpr.getReg(DSP_REG_SR,sr_reg);
DSPJitRegCache c(gpr);
TEST(16, sr_reg, Imm16(SR_40_MODE_BIT));
FixupBranch not_40bit = J_CC(CC_Z);
FixupBranch not_40bit = J_CC(CC_Z, true);
//if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT)
//{
// Sign extend into whole accum.
@@ -192,7 +200,7 @@ void DSPEmitter::dsp_conditional_extend_accum_imm(int reg, u16 val)
//}
gpr.flushRegs(c);
SetJumpTarget(not_40bit);
gpr.putReg(DSP_REG_SR);
gpr.putReg(DSP_REG_SR, false);
}
}
}
@@ -327,9 +335,9 @@ 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);
increase_addr_reg(opc & 0x3, (opc >> 2) & 0x3);
}
//----
@@ -31,13 +31,12 @@
using namespace Gen;
// Returns s64 in RAX
// In: RSI = s16 a, RDI = s16 b
// In: RCX = s16 a, RAX = s16 b
void DSPEmitter::multiply()
{
#ifdef _M_X64
// prod = (s16)a * (s16)b; //signed
MOV(64, R(EAX), R(RDI));
IMUL(64, R(ESI));
IMUL(64, R(ECX));
// Conditionally multiply by 2.
// if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0)
@@ -46,9 +45,9 @@ void DSPEmitter::multiply()
TEST(16, sr_reg, Imm16(SR_MUL_MODIFY));
FixupBranch noMult2 = J_CC(CC_NZ);
// prod <<= 1;
SHL(64, R(EAX), Imm8(1));
LEA(64, RAX, MRegSum(RAX,RAX));
SetJumpTarget(noMult2);
gpr.putReg(DSP_REG_SR);
gpr.putReg(DSP_REG_SR, false);
// return prod;
#endif
}
@@ -60,7 +59,7 @@ void DSPEmitter::multiply_add()
// s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign);
multiply();
MOV(64, R(RDX), R(RAX));
get_long_prod();
get_long_prod();
ADD(64, R(RAX), R(RDX));
// return prod;
}
@@ -72,14 +71,14 @@ void DSPEmitter::multiply_sub()
// s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign);
multiply();
MOV(64, R(RDX), R(RAX));
get_long_prod();
get_long_prod();
SUB(64, R(RAX), R(RDX));
// return prod;
}
// Only MULX family instructions have unsigned/mixed support.
// Returns s64 in EAX
// In: RSI = s16 a, RDI = s16 b
// In: RCX = s16 a, RAX = s16 b
// Returns s64 in RAX
void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
{
@@ -101,41 +100,48 @@ void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
TEST(16, sr_reg, Imm16(SR_MUL_UNSIGNED));
FixupBranch unsignedMul = J_CC(CC_NZ);
// prod = (s16)a * (s16)b; //signed
MOVSX(64, 16, RAX, R(RDI));
IMUL(64, R(RSI));
FixupBranch signedMul = J();
MOVSX(64, 16, RAX, R(RAX));
IMUL(64, R(RCX));
FixupBranch signedMul = J(true);
SetJumpTarget(unsignedMul);
DSPJitRegCache c(gpr);
gpr.putReg(DSP_REG_SR, false);
if ((axh0==0) && (axh1==0))
{
// unsigned support ON if both ax?.l regs are used
// prod = (u32)(a * b);
MOVZX(64, 16, RSI, R(RSI));
MOVZX(64, 16, RAX, R(RDI));
MUL(64, R(RSI));
MOVZX(64, 16, RCX, R(RCX));
MOVZX(64, 16, RAX, R(RAX));
MUL(64, R(RCX));
}
else if ((axh0==0) && (axh1==1))
{
// mixed support ON (u16)axl.0 * (s16)axh.1
// prod = a * (s16)b;
MOVZX(64, 16, RAX, R(RSI));
IMUL(64, R(RDI));
X64Reg tmp;
gpr.getFreeXReg(tmp);
MOV(64, R(tmp), R(RAX));
MOVZX(64, 16, RAX, R(RCX));
IMUL(64, R(tmp));
gpr.putXReg(tmp);
}
else if ((axh0==1) && (axh1==0))
{
// mixed support ON (u16)axl.1 * (s16)axh.0
// prod = (s16)a * b;
MOVZX(64, 16, RAX, R(RDI));
IMUL(64, R(RSI));
MOVZX(64, 16, RAX, R(RAX));
IMUL(64, R(RCX));
}
else
{
// unsigned support OFF if both ax?.h regs are used
// prod = (s16)a * (s16)b; //signed
MOVSX(64, 16, RAX, R(RDI));
IMUL(64, R(RSI));
MOVSX(64, 16, RAX, R(RAX));
IMUL(64, R(RCX));
}
gpr.flushRegs(c);
SetJumpTarget(signedMul);
// Conditionally multiply by 2.
@@ -143,9 +149,9 @@ void DSPEmitter::multiply_mulx(u8 axh0, u8 axh1)
TEST(16, sr_reg, Imm16(SR_MUL_MODIFY));
FixupBranch noMult2 = J_CC(CC_NZ);
// prod <<= 1;
SHL(64, R(RAX), Imm8(1));
LEA(64, RAX, MRegSum(RAX,RAX));
SetJumpTarget(noMult2);
gpr.putReg(DSP_REG_SR);
gpr.putReg(DSP_REG_SR, false);
// return prod;
}
@@ -169,7 +175,7 @@ void DSPEmitter::clrp(const UDSPInstruction opc)
// g_dsp.r[DSP_REG_PRODM2] = 0x0010;
//64bit move to memory does not work. use 2 32bits
MOV(32, M(&g_dsp.r.prod.val), Imm32(0xfff00000U));
MOV(32, M((u8*)(&g_dsp.r.prod.val)+4), Imm32(0x001000ffU));
MOV(32, M(&g_dsp.r.prod.val+4), Imm32(0x001000ffU));
#else
Default(opc);
#endif
@@ -285,14 +291,16 @@ void DSPEmitter::addpaxz(const UDSPInstruction opc)
u8 sreg = (opc >> 9) & 0x1;
// s64 ax = dsp_get_long_acx(sreg);
get_long_acx(sreg, RCX);
MOV(64, R(RDI), R(RCX));
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
get_long_acx(sreg, tmp1);
MOV(64, R(RDX), R(tmp1));
// s64 res = prod + (ax & ~0xffff);
MOV(64, R(RDX), Imm64(~0xffff));
AND(64, R(RDI), R(RDX));
MOV(64, R(RAX), Imm64(~0xffff));
AND(64, R(RDX), R(RAX));
// s64 prod = dsp_get_long_prod_round_prodl();
get_long_prod_round_prodl();
ADD(64, R(RAX), R(RDI));
ADD(64, R(RAX), R(RDX));
// s64 oldprod = dsp_get_long_prod();
// dsp_set_long_acc(dreg, res);
@@ -301,14 +309,15 @@ void DSPEmitter::addpaxz(const UDSPInstruction opc)
if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR))
{
get_long_prod(RDX);
MOV(64, R(RSI), R(RAX));
set_long_acc(dreg, RSI);
Update_SR_Register64_Carry();
MOV(64, R(RCX), R(RAX));
set_long_acc(dreg, RCX);
Update_SR_Register64_Carry(EAX, tmp1);
}
else
{
set_long_acc(dreg, RAX);
}
gpr.putXReg(tmp1);
#else
Default(opc);
#endif
@@ -323,8 +332,8 @@ void DSPEmitter::mulaxh(const UDSPInstruction opc)
{
#ifdef _M_X64
// s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0));
dsp_op_read_reg(DSP_REG_AXH0, RSI, SIGN);
MOV(64, R(RDI), R(RSI));
dsp_op_read_reg(DSP_REG_AXH0, RCX, SIGN);
MOV(64, R(RAX), R(RCX));
multiply();
// dsp_set_long_prod(prod);
set_long_prod();
@@ -345,9 +354,9 @@ void DSPEmitter::mul(const UDSPInstruction opc)
u8 sreg = (opc >> 11) & 0x1;
// u16 axl = dsp_get_ax_l(sreg);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RCX, SIGN);
// u16 axh = dsp_get_ax_h(sreg);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RAX, SIGN);
// s64 prod = dsp_multiply(axh, axl);
multiply();
// dsp_set_long_prod(prod);
@@ -377,9 +386,9 @@ void DSPEmitter::mulac(const UDSPInstruction opc)
ADD(64, R(RAX), R(RDX));
PUSH(64, R(RAX));
// u16 axl = dsp_get_ax_l(sreg);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RCX, SIGN);
// u16 axh = dsp_get_ax_h(sreg);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RAX, SIGN);
// s64 prod = dsp_multiply(axl, axh);
multiply();
// dsp_set_long_prod(prod);
@@ -467,9 +476,9 @@ void DSPEmitter::mulx(const UDSPInstruction opc)
u8 sreg = ((opc >> 12) & 0x1);
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
multiply_mulx(sreg, treg);
// dsp_set_long_prod(prod);
@@ -494,25 +503,28 @@ void DSPEmitter::mulxac(const UDSPInstruction opc)
u8 sreg = (opc >> 12) & 0x1;
// s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
get_long_acc(rreg, RCX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
get_long_acc(rreg, tmp1);
get_long_prod();
ADD(64, R(RCX), R(RAX));
ADD(64, R(tmp1), R(RAX));
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
multiply_mulx(sreg, treg);
// dsp_set_long_prod(prod);
set_long_prod();
// dsp_set_long_acc(rreg, acc);
set_long_acc(rreg, RCX);
set_long_acc(rreg, tmp1);
// Update_SR_Register64(dsp_get_long_acc(rreg));
if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR))
{
Update_SR_Register64(RCX);
Update_SR_Register64(tmp1);
}
gpr.putXReg(tmp1);
#else
Default(opc);
#endif
@@ -533,23 +545,26 @@ void DSPEmitter::mulxmv(const UDSPInstruction opc)
u8 sreg = (opc >> 12) & 0x1;
// s64 acc = dsp_get_long_prod();
get_long_prod(RCX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
get_long_prod(tmp1);
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
multiply_mulx(sreg, treg);
// dsp_set_long_prod(prod);
set_long_prod();
// dsp_set_long_acc(rreg, acc);
set_long_acc(rreg, RCX);
set_long_acc(rreg, tmp1);
// Update_SR_Register64(dsp_get_long_acc(rreg));
if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR))
{
Update_SR_Register64(RCX);
Update_SR_Register64(tmp1);
}
gpr.putXReg(tmp1);
#else
Default(opc);
#endif
@@ -571,23 +586,26 @@ void DSPEmitter::mulxmvz(const UDSPInstruction opc)
u8 sreg = (opc >> 12) & 0x1;
// s64 acc = dsp_get_long_prod_round_prodl();
get_long_prod_round_prodl(RCX);
X64Reg tmp1;
gpr.getFreeXReg(tmp1);
get_long_prod_round_prodl(tmp1);
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
multiply_mulx(sreg, treg);
// dsp_set_long_prod(prod);
set_long_prod();
// dsp_set_long_acc(rreg, acc);
set_long_acc(rreg, RCX);
set_long_acc(rreg, tmp1);
// Update_SR_Register64(dsp_get_long_acc(rreg));
if (!(DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_START_OF_INST) || (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_UPDATE_SR))
{
Update_SR_Register64(RCX);
Update_SR_Register64(tmp1);
}
gpr.putXReg(tmp1);
#else
Default(opc);
#endif
@@ -606,9 +624,9 @@ void DSPEmitter::mulc(const UDSPInstruction opc)
u8 sreg = (opc >> 12) & 0x1;
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply(accm, axh);
multiply();
// dsp_set_long_prod(prod);
@@ -639,9 +657,9 @@ void DSPEmitter::mulcac(const UDSPInstruction opc)
ADD(64, R(RAX), R(RDX));
PUSH(64, R(RAX));
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply(accm, axh);
multiply();
// dsp_set_long_prod(prod);
@@ -678,9 +696,9 @@ void DSPEmitter::mulcmv(const UDSPInstruction opc)
get_long_prod();
PUSH(64, R(RAX));
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply(accm, axh);
multiply();
// dsp_set_long_prod(prod);
@@ -718,9 +736,9 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc)
get_long_prod_round_prodl();
PUSH(64, R(RAX));
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply(accm, axh);
multiply();
// dsp_set_long_prod(prod);
@@ -752,9 +770,9 @@ void DSPEmitter::maddx(const UDSPInstruction opc)
u8 sreg = (opc >> 9) & 0x1;
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_add(val1, val2);
multiply_add();
// dsp_set_long_prod(prod);
@@ -776,9 +794,9 @@ void DSPEmitter::msubx(const UDSPInstruction opc)
u8 sreg = (opc >> 9) & 0x1;
// u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0 + sreg*2, RCX, SIGN);
// u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXL1 + treg*2, RAX, SIGN);
// s64 prod = dsp_multiply_sub(val1, val2);
multiply_sub();
// dsp_set_long_prod(prod);
@@ -800,9 +818,9 @@ void DSPEmitter::maddc(const UDSPInstruction opc)
u8 sreg = (opc >> 9) & 0x1;
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply_add(accm, axh);
multiply_add();
// dsp_set_long_prod(prod);
@@ -824,9 +842,9 @@ void DSPEmitter::msubc(const UDSPInstruction opc)
u8 sreg = (opc >> 9) & 0x1;
// u16 accm = dsp_get_acc_m(sreg);
get_acc_m(sreg, ESI);
get_acc_m(sreg, ECX);
// u16 axh = dsp_get_ax_h(treg);
dsp_op_read_reg(DSP_REG_AXH0+treg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+treg, RAX, SIGN);
// s64 prod = dsp_multiply_sub(accm, axh);
multiply_sub();
// dsp_set_long_prod(prod);
@@ -847,9 +865,9 @@ void DSPEmitter::madd(const UDSPInstruction opc)
u8 sreg = (opc >> 8) & 0x1;
// u16 axl = dsp_get_ax_l(sreg);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RCX, SIGN);
// u16 axh = dsp_get_ax_h(sreg);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RAX, SIGN);
// s64 prod = dsp_multiply_add(axl, axh);
multiply_add();
// dsp_set_long_prod(prod);
@@ -870,9 +888,9 @@ void DSPEmitter::msub(const UDSPInstruction opc)
u8 sreg = (opc >> 8) & 0x1;
// u16 axl = dsp_get_ax_l(sreg);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RSI, SIGN);
dsp_op_read_reg(DSP_REG_AXL0+sreg, RCX, SIGN);
// u16 axh = dsp_get_ax_h(sreg);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RDI, SIGN);
dsp_op_read_reg(DSP_REG_AXH0+sreg, RAX, SIGN);
// s64 prod = dsp_multiply_sub(axl, axh);
multiply_sub();
// dsp_set_long_prod(prod);
File diff suppressed because it is too large Load Diff
+44 -17
View File
@@ -23,12 +23,16 @@
class DSPEmitter;
enum DSPJitRegSpecial {
DSP_REG_ACC0_64 =32,
DSP_REG_ACC1_64 =33,
DSP_REG_AX0_32 =34,
DSP_REG_AX1_32 =35,
DSP_REG_AX0_32 =32,
DSP_REG_AX1_32 =33,
#ifdef _M_X64
DSP_REG_ACC0_64 =34,
DSP_REG_ACC1_64 =35,
DSP_REG_PROD_64 =36,
DSP_REG_MAX_MEM_BACKED = 36,
#else
DSP_REG_MAX_MEM_BACKED = 33,
#endif
DSP_REG_USED =253,
DSP_REG_STATIC =254,
@@ -50,24 +54,28 @@ private:
struct X64CachedReg
{
int guest_reg; //including DSPJitRegSpecial
bool pushed;
};
struct DynamicReg {
Gen::OpArg loc;
void *mem;
size_t size;
bool dirty;
};
#ifdef _M_X64
//when there is a way to do this efficiently in x86, uncondition
struct {
Gen::X64Reg host_reg;
int shift;
bool dirty;
bool used;
Gen::X64Reg tmp_reg;
} acc[2];
#endif
int last_use_ctr;
int parentReg;
int shift;//current shift if parentReg == DSP_REG_NONE
//otherwise the shift this part can be found at
Gen::X64Reg host_reg;
/* todo:
+ drop sameReg
+ add parentReg
+ add shift:
- if parentReg != DSP_REG_NONE, this is the shift where this
register is found in the parentReg
- if parentReg == DSP_REG_NONE, this is the current shift _state_
*/
};
DynamicReg regs[DSP_REG_MAX_MEM_BACKED+1];
X64CachedReg xregs[NUMXREGS];
@@ -75,11 +83,21 @@ private:
DSPEmitter &emitter;
bool temporary;
bool merged;
int use_ctr;
private:
//find a free host reg
Gen::X64Reg findFreeXReg();
Gen::X64Reg spillXReg();
Gen::X64Reg findSpillFreeXReg();
void spillXReg(Gen::X64Reg reg);
void movToHostReg(int reg, Gen::X64Reg host_reg, bool load);
void movToHostReg(int reg, bool load);
void rotateHostReg(int reg, int shift, bool emit);
void movToMemory(int reg);
void flushMemBackedRegs();
public:
DSPJitRegCache(DSPEmitter &_emitter);
@@ -147,10 +165,19 @@ public:
//prepare state so that another flushed DSPJitRegCache can take over
void flushRegs();
void loadStaticRegs();//load statically allocated regs from memory
void saveStaticRegs();//save statically allocated regs to memory
void loadRegs(bool emit=true);//load statically allocated regs from memory
void saveRegs();//save statically allocated regs to memory
void pushRegs();//save registers before abi call
void popRegs();//restore registers after abi call
//returns a register with the same contents as reg that is safe
//to use through saveStaticRegs and for ABI-calls
Gen::X64Reg makeABICallSafe(Gen::X64Reg reg);
//gives no SCALE_RIP with abs(offset) >= 0x80000000
//32/64 bit writes allowed when the register has a _64 or _32 suffix
//only 16 bit writes allowed without any suffix.
void getReg(int reg, Gen::OpArg &oparg, bool load = true);
//done with all usages of OpArg above
void putReg(int reg, bool dirty = true);
File diff suppressed because it is too large Load Diff