mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user