mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
LLE JIT:
* Optimised the updating of g_dsp.pc in the compile loop (code by kiesel-stein) * Added JIT version of LRI (code by kiesel-stein) * Added JIT versions of the branch instructions (code by Jack Frost) * DSP_SendAIBuffer fix (code by Mylek) * Marked instructions that update g_dsp.pc in the DSP table and updated PC based on the table (speed up) * Fixed the signed bits not being set properly in the addr instruction * Created a MainOpFallback function to use interpreted versions of the instructions if necessary (code by kiesel-stein) * Disabled the jit versions of subarn and addarn as they are slowing down NSMBW The above work in both x86 and x64 modes. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6582 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -73,6 +73,14 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) {
|
||||
ABI_RestoreStack(1 * 2);
|
||||
}
|
||||
|
||||
void XEmitter::ABI_CallFunctionCC16(void *func, u32 param1, u16 param2) {
|
||||
ABI_AlignStack(1 * 2 + 1 * 4);
|
||||
PUSH(16, Imm16(param2));
|
||||
PUSH(32, Imm32(param1));
|
||||
CALL(func);
|
||||
ABI_RestoreStack(1 * 2 + 1 * 4);
|
||||
}
|
||||
|
||||
void XEmitter::ABI_CallFunctionC(void *func, u32 param1) {
|
||||
ABI_AlignStack(1 * 4);
|
||||
PUSH(32, Imm32(param1));
|
||||
@@ -231,6 +239,12 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) {
|
||||
}
|
||||
}
|
||||
|
||||
void XEmitter::ABI_CallFunctionCC16(void *func, u32 param1, u16 param2) {
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1));
|
||||
MOV(32, R(ABI_PARAM2), Imm32((u32)param2));
|
||||
CALL(func);
|
||||
}
|
||||
|
||||
void XEmitter::ABI_CallFunctionC(void *func, u32 param1) {
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1));
|
||||
u64 distance = u64(func) - (u64(code) + 5);
|
||||
|
||||
@@ -597,6 +597,7 @@ public:
|
||||
void ABI_CallFunction(void *func);
|
||||
|
||||
void ABI_CallFunctionC16(void *func, u16 param1);
|
||||
void ABI_CallFunctionCC16(void *func, u32 param1, u16 param2);
|
||||
|
||||
// These only support u32 parameters, but that's enough for a lot of uses.
|
||||
// These will destroy the 1 or 2 first "parameter regs".
|
||||
|
||||
@@ -618,13 +618,12 @@ void UpdateAudioDMA()
|
||||
// external audio fifo in the emulator, to be mixed with the disc
|
||||
// streaming output. If that audio queue fills up, we delay the
|
||||
// emulator.
|
||||
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.ReadAddress, 8);
|
||||
|
||||
g_audioDMA.ReadAddress += 32;
|
||||
g_audioDMA.BlocksLeft--;
|
||||
|
||||
if (g_audioDMA.BlocksLeft == 0)
|
||||
{
|
||||
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, 8*g_audioDMA.AudioDMAControl.NumBlocks);
|
||||
GenerateDSPInterrupt(DSP::INT_AID);
|
||||
if (g_audioDMA.AudioDMAControl.Enable)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ set(SRCS Src/assemble.cpp
|
||||
Src/DSPCore.cpp
|
||||
Src/DSPTables.cpp
|
||||
Src/Jit/DSPJitExtOps.cpp
|
||||
Src/Jit/DSPJitBranch.cpp
|
||||
Src/Jit/DSPJitCCUtil.cpp
|
||||
Src/Jit/DSPJitArithmetic.cpp
|
||||
Src/Jit/DSPJitMultiplier.cpp
|
||||
|
||||
@@ -470,6 +470,10 @@
|
||||
RelativePath=".\Src\Jit\DSPJitExtOps.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitBranch.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitMisc.cpp"
|
||||
>
|
||||
|
||||
@@ -73,7 +73,8 @@ void DSPEmitter::ClearIRAM() {
|
||||
}
|
||||
|
||||
// Must go out of block if exception is detected
|
||||
void DSPEmitter::checkExceptions(u32 retval) {
|
||||
void DSPEmitter::checkExceptions(u32 retval)
|
||||
{
|
||||
// Check for interrupts and exceptions
|
||||
#ifdef _M_IX86 // All32
|
||||
TEST(8, M(&g_dsp.exceptions), Imm8(0xff));
|
||||
@@ -82,17 +83,43 @@ void DSPEmitter::checkExceptions(u32 retval) {
|
||||
TEST(8, MDisp(RAX,0), Imm8(0xff));
|
||||
#endif
|
||||
FixupBranch skipCheck = J_CC(CC_Z);
|
||||
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC));
|
||||
#endif
|
||||
|
||||
ABI_CallFunction((void *)&DSPCore_CheckExceptions);
|
||||
|
||||
|
||||
// ABI_RestoreStack(0);
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
MOV(32,R(EAX),Imm32(retval));
|
||||
RET();
|
||||
|
||||
|
||||
SetJumpTarget(skipCheck);
|
||||
}
|
||||
|
||||
void DSPEmitter::MainOpFallback(UDSPInstruction inst)
|
||||
{
|
||||
if (opTable[inst]->reads_pc)
|
||||
{
|
||||
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block.
|
||||
// Fallbacks to interpreter need this for fetching immediate values
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC + 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fall back to interpreter
|
||||
ABI_CallFunctionC16((void*)opTable[inst]->intFunc, inst);
|
||||
}
|
||||
|
||||
void DSPEmitter::EmitInstruction(UDSPInstruction inst)
|
||||
{
|
||||
const DSPOPCTemplate *tinst = GetOpTemplate(inst);
|
||||
@@ -123,8 +150,7 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
|
||||
|
||||
// Main instruction
|
||||
if (!opTable[inst]->jitFunc) {
|
||||
// Fall back to interpreter
|
||||
ABI_CallFunctionC16((void*)opTable[inst]->intFunc, inst);
|
||||
MainOpFallback(inst);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,32 +204,27 @@ void DSPEmitter::Compile(int start_addr)
|
||||
*/
|
||||
ABI_CallFunction((void *)&DSPCore_CheckExternalInterrupt);
|
||||
|
||||
int addr = start_addr;
|
||||
compilePC = start_addr;
|
||||
bool fixup_pc = false;
|
||||
blockSize[start_addr] = 0;
|
||||
while (addr < start_addr + MAX_BLOCK_SIZE)
|
||||
|
||||
while (compilePC < start_addr + MAX_BLOCK_SIZE)
|
||||
{
|
||||
checkExceptions(blockSize[start_addr]);
|
||||
|
||||
UDSPInstruction inst = dsp_imem_read(addr);
|
||||
UDSPInstruction inst = dsp_imem_read(compilePC);
|
||||
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
||||
|
||||
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end of block.
|
||||
// Fallbacks to interpreter need this for fetching immediate values
|
||||
#ifdef _M_IX86 // All32
|
||||
ADD(16, M(&(g_dsp.pc)), Imm16(1));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
ADD(16, MDisp(RAX,0), Imm16(1));
|
||||
#endif
|
||||
|
||||
EmitInstruction(inst);
|
||||
|
||||
blockSize[start_addr]++;
|
||||
addr += opcode->size;
|
||||
compilePC += opcode->size;
|
||||
|
||||
fixup_pc = true;
|
||||
|
||||
// Handle loop condition, only if current instruction was flagged as a loop destination
|
||||
// by the analyzer.
|
||||
if (DSPAnalyzer::code_flags[addr-1] & DSPAnalyzer::CODE_LOOP_END)
|
||||
if (DSPAnalyzer::code_flags[compilePC-1] & DSPAnalyzer::CODE_LOOP_END)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&(g_dsp.r[DSP_REG_ST2])));
|
||||
@@ -222,6 +243,17 @@ void DSPEmitter::Compile(int start_addr)
|
||||
CMP(32, R(EAX), Imm32(0));
|
||||
FixupBranch rLoopCounterExit = J_CC(CC_LE);
|
||||
|
||||
if (!opcode->branch)
|
||||
{
|
||||
//branch insns update the g_dsp.pc
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC));
|
||||
#endif
|
||||
}
|
||||
|
||||
// These functions branch and therefore only need to be called in the
|
||||
// end of each block and in this order
|
||||
ABI_CallFunction((void *)&DSPInterpreter::HandleLoop);
|
||||
@@ -243,6 +275,8 @@ void DSPEmitter::Compile(int start_addr)
|
||||
|
||||
if (opcode->branch)
|
||||
{
|
||||
//don't update g_dsp.pc -- the branch insn already did
|
||||
fixup_pc = false;
|
||||
if (opcode->uncond_branch)
|
||||
{
|
||||
break;
|
||||
@@ -256,9 +290,10 @@ void DSPEmitter::Compile(int start_addr)
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, R(AX), MDisp(RAX,0));
|
||||
#endif
|
||||
CMP(16, R(AX), Imm16(addr));
|
||||
CMP(16, R(AX), Imm16(compilePC));
|
||||
FixupBranch rNoBranch = J_CC(CC_Z);
|
||||
|
||||
//don't update g_dsp.pc -- the branch insn already did
|
||||
// ABI_RestoreStack(0);
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
if (DSPAnalyzer::code_flags[start_addr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
@@ -276,12 +311,21 @@ void DSPEmitter::Compile(int start_addr)
|
||||
}
|
||||
|
||||
// End the block if we're before an idle skip address
|
||||
if (DSPAnalyzer::code_flags[addr] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
if (DSPAnalyzer::code_flags[compilePC] & DSPAnalyzer::CODE_IDLE_SKIP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fixup_pc) {
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC));
|
||||
#endif
|
||||
}
|
||||
|
||||
blocks[start_addr] = (CompiledCode)entryPoint;
|
||||
if (blockSize[start_addr] == 0)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,8 @@ public:
|
||||
const u8 *CompileStub();
|
||||
void Compile(int start_addr);
|
||||
|
||||
void MainOpFallback(UDSPInstruction inst);
|
||||
|
||||
int STACKALIGN RunForCycles(int cycles);
|
||||
|
||||
// CC Util
|
||||
@@ -112,10 +114,16 @@ public:
|
||||
void sbclr(const UDSPInstruction opc);
|
||||
void sbset(const UDSPInstruction opc);
|
||||
void srbith(const UDSPInstruction opc);
|
||||
void lri(const UDSPInstruction opc);
|
||||
void lris(const UDSPInstruction opc);
|
||||
void mrr(const UDSPInstruction opc);
|
||||
void nx(const UDSPInstruction opc);
|
||||
|
||||
void jcc(const UDSPInstruction opc);
|
||||
void jmprcc(const UDSPInstruction opc);
|
||||
void call(const UDSPInstruction opc);
|
||||
void callr(const UDSPInstruction opc);
|
||||
|
||||
// Arithmetic
|
||||
void addr(const UDSPInstruction opc);
|
||||
void lsl16(const UDSPInstruction opc);
|
||||
@@ -147,6 +155,7 @@ public:
|
||||
|
||||
// CALL this to start the dispatcher
|
||||
const u8 *enterDispatcher;
|
||||
u16 compilePC;
|
||||
|
||||
private:
|
||||
CompiledCode *blocks;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,7 @@ typedef struct
|
||||
bool extended;
|
||||
bool branch;
|
||||
bool uncond_branch;
|
||||
bool reads_pc;
|
||||
} DSPOPCTemplate;
|
||||
|
||||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
@@ -386,7 +386,7 @@ void DSPEmitter::addr(const UDSPInstruction opc)
|
||||
get_long_acc(dreg);
|
||||
PUSH(64, R(RAX));
|
||||
// s64 ax = (s16)g_dsp.r[sreg];
|
||||
MOV(16, R(RDX), MDisp(R11, sreg * 2));
|
||||
MOVSX(64, 16, RDX, MDisp(R11, sreg * 2));
|
||||
// ax <<= 16;
|
||||
SHL(64, R(RDX), Imm8(16));
|
||||
// s64 res = acc + ax;
|
||||
@@ -414,7 +414,7 @@ void DSPEmitter::addr(const UDSPInstruction opc)
|
||||
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::addr, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -821,7 +821,7 @@ void DSPEmitter::lsl16(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(areg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::lsl16, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -883,7 +883,7 @@ void DSPEmitter::lsl(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::lsl, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
// Copyright (C) 2010 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#include "../DSPMemoryMap.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "../DSPStacks.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
const int GetCodeSize(void(*jitCode)(const UDSPInstruction, DSPEmitter&), const UDSPInstruction opc, DSPEmitter &emitter)
|
||||
{
|
||||
u16 pc = g_dsp.pc;
|
||||
const u8* ptr = emitter.GetCodePtr();
|
||||
jitCode(opc, emitter);
|
||||
//emitter.JMP(emitter.GetCodePtr());
|
||||
int size = (int)(emitter.GetCodePtr() - ptr);
|
||||
emitter.SetCodePtr((u8*)ptr);
|
||||
g_dsp.pc = pc;
|
||||
return size;
|
||||
}
|
||||
|
||||
template <void(*jitCode)(const UDSPInstruction, DSPEmitter&)>
|
||||
void ReJitConditional(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
static const int codeSize = GetCodeSize(jitCode, opc, emitter);
|
||||
//emitter.INT3();
|
||||
const u8* codePtr = CheckCondition(emitter, opc & 0xf, codeSize);
|
||||
const u8* afterSkip = emitter.GetCodePtr();
|
||||
if (codePtr != NULL)
|
||||
emitter.SetCodePtr((u8*)codePtr);
|
||||
jitCode(opc, emitter);
|
||||
//if (codePtr != NULL)
|
||||
//{
|
||||
// emitter.JMP(afterSkip + 4 + sizeof(void*));
|
||||
// emitter.SetCodePtr((u8*)afterSkip);
|
||||
// emitter.ADD(16, M(&g_dsp.pc), Imm8(1)); //4 bytes + pointer
|
||||
//}
|
||||
}
|
||||
|
||||
const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
||||
{
|
||||
if (cond == 0xf) // Always true.
|
||||
return NULL;
|
||||
//emitter.INT3();
|
||||
FixupBranch skipCode2;
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
switch(cond)
|
||||
{
|
||||
case 0x0: // GE - Greater Equal
|
||||
case 0x1: // L - Less
|
||||
case 0x2: // G - Greater
|
||||
case 0x3: // LE - Less Equal
|
||||
emitter.MOV(16, R(EDX), R(EAX));
|
||||
emitter.SHR(16, R(EDX), Imm8(3)); //SR_SIGN flag
|
||||
emitter.NOT(16, R(EDX));
|
||||
emitter.SHR(16, R(EAX), Imm8(1)); //SR_OVERFLOW flag
|
||||
emitter.NOT(16, R(EAX));
|
||||
emitter.XOR(16, R(EAX), R(EDX));
|
||||
emitter.TEST(16, R(EAX), Imm16(1));
|
||||
if (cond < 0x2)
|
||||
break;
|
||||
|
||||
//LE: problem in here, half the tests fail
|
||||
skipCode2 = emitter.J_CC(CC_NE);
|
||||
//skipCode2 = emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
break;
|
||||
case 0x4: // NZ - Not Zero
|
||||
case 0x5: // Z - Zero
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
break;
|
||||
case 0x6: // NC - Not carry
|
||||
case 0x7: // C - Carry
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_CARRY));
|
||||
break;
|
||||
case 0x8: // ? - Not over s32
|
||||
case 0x9: // ? - Over s32
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32));
|
||||
break;
|
||||
case 0xa: // ?
|
||||
case 0xb: // ?
|
||||
{
|
||||
//full of fail, both
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS));
|
||||
FixupBranch skipArithZero = emitter.J_CC(CC_E);
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
FixupBranch setZero = emitter.J_CC(CC_NE);
|
||||
|
||||
emitter.MOV(16, R(EAX), Imm16(1));
|
||||
FixupBranch toEnd = emitter.J();
|
||||
|
||||
emitter.SetJumpTarget(skipArithZero);
|
||||
emitter.SetJumpTarget(setZero);
|
||||
emitter.XOR(16, R(EAX), R(EAX));
|
||||
emitter.SetJumpTarget(toEnd);
|
||||
emitter.SETcc(CC_E, R(EAX));
|
||||
emitter.TEST(8, R(EAX), R(EAX));
|
||||
break;
|
||||
//emitter.TEST(16, R(EAX), Imm16(SR_OVER_S32 | SR_TOP2BITS));
|
||||
//skipCode2 = emitter.J_CC((CCFlags)(CC_E + (cond & 1)));
|
||||
//emitter.TEST(16, R(EAX), Imm16(SR_ARITH_ZERO));
|
||||
//break;
|
||||
}
|
||||
case 0xc: // LNZ - Logic Not Zero
|
||||
case 0xd: // LZ - Logic Zero
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_LOGIC_ZERO));
|
||||
break;
|
||||
case 0xe: // 0 - Overflow
|
||||
emitter.TEST(16, R(EAX), Imm16(SR_OVERFLOW));
|
||||
break;
|
||||
}
|
||||
FixupBranch skipCode = cond == 0xe ? emitter.J_CC(CC_E) : emitter.J_CC((CCFlags)(CC_NE - (cond & 1)));
|
||||
const u8* res = emitter.GetCodePtr();
|
||||
emitter.NOP(skipCodeSize);
|
||||
emitter.SetJumpTarget(skipCode);
|
||||
if ((cond | 1) == 0x3) // || (cond | 1) == 0xb)
|
||||
emitter.SetJumpTarget(skipCode2);
|
||||
return res;
|
||||
}
|
||||
|
||||
void r_jcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u16 dest = dsp_imem_read(emitter.compilePC + 1);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
|
||||
#endif
|
||||
}
|
||||
// Generic jmp implementation
|
||||
// Jcc addressA
|
||||
// 0000 0010 1001 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Jump to addressA if condition cc has been met. Set program counter to
|
||||
// address represented by value that follows this "jmp" instruction.
|
||||
void DSPEmitter::jcc(const UDSPInstruction opc)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC + 1));
|
||||
#endif
|
||||
ReJitConditional<r_jcc>(opc, *this);
|
||||
}
|
||||
|
||||
void r_jmprcc(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u8 reg = (opc >> 5) & 0x7;
|
||||
//reg can only be DSP_REG_ARx and DSP_REG_IXx now,
|
||||
//no need to handle DSP_REG_STx.
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
#else
|
||||
emitter.MOV(16, R(RSI), M(&g_dsp.r[reg]));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), R(RSI));
|
||||
#endif
|
||||
}
|
||||
// Generic jmpr implementation
|
||||
// JMPcc $R
|
||||
// 0001 0111 rrr0 cccc
|
||||
// Jump to address; set program counter to a value from register $R.
|
||||
void DSPEmitter::jmprcc(const UDSPInstruction opc)
|
||||
{
|
||||
ReJitConditional<r_jmprcc>(opc, *this);
|
||||
}
|
||||
|
||||
void r_call(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u16 dest = dsp_imem_read(emitter.compilePC + 1);
|
||||
emitter.ABI_CallFunctionCC16(dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 2);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
|
||||
#endif
|
||||
}
|
||||
// Generic call implementation
|
||||
// CALLcc addressA
|
||||
// 0000 0010 1011 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to $st0. Set program counter to address
|
||||
// represented by value that follows this "call" instruction.
|
||||
void DSPEmitter::call(const UDSPInstruction opc)
|
||||
{
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&(g_dsp.pc)), Imm16(compilePC + 1));
|
||||
#else
|
||||
MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
MOV(16, MDisp(RAX,0), Imm16(compilePC + 1));
|
||||
#endif
|
||||
ReJitConditional<r_call>(opc, *this);
|
||||
}
|
||||
|
||||
void r_callr(const UDSPInstruction opc, DSPEmitter& emitter)
|
||||
{
|
||||
u8 reg = (opc >> 5) & 0x7;
|
||||
emitter.ABI_CallFunctionCC16(dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 1);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, M(&g_dsp.pc), R(EAX));
|
||||
#else
|
||||
emitter.MOV(16, R(RSI), M(&g_dsp.r[reg]));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), R(RSI));
|
||||
#endif
|
||||
}
|
||||
// Generic callr implementation
|
||||
// CALLRcc $R
|
||||
// 0001 0111 rrr1 cccc
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to call stack $st0. Set program counter to
|
||||
// register $R.
|
||||
void DSPEmitter::callr(const UDSPInstruction opc)
|
||||
{
|
||||
ReJitConditional<r_callr>(opc, *this);
|
||||
}
|
||||
@@ -321,12 +321,10 @@ void DSPEmitter::mrr(const UDSPInstruction opc)
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// 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.
|
||||
// Load immediate value I to register $D.
|
||||
//
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a
|
||||
// register, has a different behaviour in S40 mode if loaded to AC0.M: The
|
||||
@@ -335,11 +333,10 @@ void DSPEmitter::mrr(const UDSPInstruction opc)
|
||||
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);
|
||||
u16 imm = dsp_imem_read(compilePC+1);
|
||||
dsp_op_write_reg_imm(reg, imm);
|
||||
dsp_conditional_extend_accum_imm(reg, imm);
|
||||
}
|
||||
#endif
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
|
||||
@@ -154,7 +154,7 @@ void DSPEmitter::clrp(const UDSPInstruction opc)
|
||||
// g_dsp.r[DSP_REG_PRODM2] = 0x0010;
|
||||
MOV(16, MDisp(R11, DSP_REG_PRODM2 * 2), Imm16(0x0010));
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::clrp, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ void DSPEmitter::tstprod(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(prod);
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::tstprod, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ void DSPEmitter::movp(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(acc);
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::movp, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ void DSPEmitter::movnp(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(acc);
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::movnp, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ void DSPEmitter::movpz(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(acc);
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::movpz, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ void DSPEmitter::mulaxh(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulaxh, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ void DSPEmitter::mul(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mul, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ void DSPEmitter::mulac(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulac, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ void DSPEmitter::mulmv(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulmv, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ void DSPEmitter::mulmvz(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulmvz, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ void DSPEmitter::mulc(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulc, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ void DSPEmitter::mulcac(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulcac, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ void DSPEmitter::mulcmv(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulcmv, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ void DSPEmitter::mulcmvz(const UDSPInstruction opc)
|
||||
// Update_SR_Register64(dsp_get_long_acc(rreg));
|
||||
Update_SR_Register64();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::mulcmvz, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -696,7 +696,7 @@ void DSPEmitter::maddc(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::maddc, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ void DSPEmitter::msubc(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::msubc, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -745,7 +745,7 @@ void DSPEmitter::madd(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::madd, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -769,6 +769,6 @@ void DSPEmitter::msub(const UDSPInstruction opc)
|
||||
// dsp_set_long_prod(prod);
|
||||
set_long_prod();
|
||||
#else
|
||||
ABI_CallFunctionC((void *)&DSPInterpreter::msub, opc);
|
||||
MainOpFallback(opc);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ files = [
|
||||
"DSPCore.cpp",
|
||||
"DSPTables.cpp",
|
||||
"Jit/DSPJitExtOps.cpp",
|
||||
"Jit/DSPJitBranch.cpp",
|
||||
"Jit/DSPJitUtil.cpp",
|
||||
"Jit/DSPJitCCUtil.cpp",
|
||||
"Jit/DSPJitArithmetic.cpp",
|
||||
|
||||
Reference in New Issue
Block a user