Avoid shadowing variables.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6613 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
c68ae8e91e
commit
38a46ddf94
|
@ -1,100 +1,100 @@
|
|||
// Copyright (C) 2003 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 "Sram.h"
|
||||
#include "../ConfigManager.h"
|
||||
// english
|
||||
SRAM sram_dump = {{
|
||||
0x04, 0x6B,
|
||||
0xFB, 0x91,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x40,
|
||||
0x05,
|
||||
0x00,
|
||||
0x00,
|
||||
0x2C,
|
||||
0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41,
|
||||
0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x6E, 0x6D,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
}};
|
||||
|
||||
// german
|
||||
SRAM sram_dump_german = {{
|
||||
0x1F, 0x66,
|
||||
0xE0, 0x96,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0xEA, 0x19, 0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x3C,
|
||||
0x12, 0xD5, 0xEA, 0xD3, 0x00, 0xFA, 0x2D, 0x33, 0x13, 0x41, 0x26, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x84, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
}};
|
||||
|
||||
void initSRAM()
|
||||
{
|
||||
FILE *file = fopen(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strSRAM.c_str(), "rb");
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(&g_SRAM, 1, 64, file) < 64) {
|
||||
ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: Could not read all of SRAM");
|
||||
g_SRAM = sram_dump;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_SRAM = sram_dump;
|
||||
}
|
||||
}
|
||||
|
||||
void SetCardFlashID(u8* buffer, u8 card_index)
|
||||
{
|
||||
u64 rand = Common::swap64( *(u64*)&(buffer[12]));
|
||||
u8 csum=0;
|
||||
for(int i = 0; i < 12; i++)
|
||||
{
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
csum += g_SRAM.flash_id[card_index][i] = buffer[i] - ((u8)rand&0xff);
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
rand &= (u64)0x0000000000007fffULL;
|
||||
}
|
||||
g_SRAM.flashID_chksum[card_index] = csum^0xFF;
|
||||
}
|
||||
|
||||
// Copyright (C) 2003 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 "Sram.h"
|
||||
#include "../ConfigManager.h"
|
||||
// english
|
||||
SRAM sram_dump = {{
|
||||
0x04, 0x6B,
|
||||
0xFB, 0x91,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0x40,
|
||||
0x05,
|
||||
0x00,
|
||||
0x00,
|
||||
0x2C,
|
||||
0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41,
|
||||
0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x6E, 0x6D,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
}};
|
||||
|
||||
// german
|
||||
SRAM sram_dump_german = {{
|
||||
0x1F, 0x66,
|
||||
0xE0, 0x96,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0xEA, 0x19, 0x40,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x3C,
|
||||
0x12, 0xD5, 0xEA, 0xD3, 0x00, 0xFA, 0x2D, 0x33, 0x13, 0x41, 0x26, 0x03,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x84, 0xFF,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
}};
|
||||
|
||||
void initSRAM()
|
||||
{
|
||||
FILE *file = fopen(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strSRAM.c_str(), "rb");
|
||||
if (file != NULL)
|
||||
{
|
||||
if (fread(&g_SRAM, 1, 64, file) < 64) {
|
||||
ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: Could not read all of SRAM");
|
||||
g_SRAM = sram_dump;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_SRAM = sram_dump;
|
||||
}
|
||||
}
|
||||
|
||||
void SetCardFlashID(u8* buffer, u8 card_index)
|
||||
{
|
||||
u64 rand = Common::swap64( *(u64*)&(buffer[12]));
|
||||
u8 csum=0;
|
||||
for(int i = 0; i < 12; i++)
|
||||
{
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
csum += g_SRAM.flash_id[card_index][i] = buffer[i] - ((u8)rand&0xff);
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
rand &= (u64)0x0000000000007fffULL;
|
||||
}
|
||||
g_SRAM.flashID_chksum[card_index] = csum^0xFF;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,286 +1,286 @@
|
|||
// 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;
|
||||
}
|
||||
|
||||
const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
||||
{
|
||||
if (cond == 0xf) // Always true.
|
||||
return NULL;
|
||||
//emitter.INT3();
|
||||
FixupBranch skipCode2;
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r[DSP_REG_SR]));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
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)));
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r[DSP_REG_SR]));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
//}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.JMPptr(M(&emitter.blockLinks[dest]));
|
||||
}
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), Imm16(dest));
|
||||
|
||||
// Jump directly to the next block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.MOV(64, R(RAX), ImmPtr((void *)(emitter.blockLinks[dest])));
|
||||
emitter.JMPptr(R(RAX));
|
||||
emitter.ClearCallFlag();
|
||||
}
|
||||
#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)
|
||||
{
|
||||
// Disabled as jcc has issues in games
|
||||
Default(opc); return;
|
||||
#if 0
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
|
||||
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(64, R(RSI), ImmPtr(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), 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((void *)dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 2);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.JMPptr(M(&emitter.blockLinks[dest]));
|
||||
}
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.MOV(64, R(RAX), ImmPtr((void *)(emitter.blockLinks[dest])));
|
||||
emitter.JMPptr(R(RAX));
|
||||
emitter.ClearCallFlag();
|
||||
}
|
||||
#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((void *)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(64, R(RSI), ImmPtr(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
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);
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
const u8* CheckCondition(DSPEmitter& emitter, u8 cond, u8 skipCodeSize)
|
||||
{
|
||||
if (cond == 0xf) // Always true.
|
||||
return NULL;
|
||||
//emitter.INT3();
|
||||
FixupBranch skipCode2;
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r[DSP_REG_SR]));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
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)));
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, R(EAX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&g_dsp.r[DSP_REG_SR]));
|
||||
emitter.MOV(16, R(EAX), MatR(RAX));
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
//}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.JMPptr(M(&emitter.blockLinks[dest]));
|
||||
}
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), Imm16(dest));
|
||||
|
||||
// Jump directly to the next block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.MOV(64, R(RAX), ImmPtr((void *)(emitter.blockLinks[dest])));
|
||||
emitter.JMPptr(R(RAX));
|
||||
emitter.ClearCallFlag();
|
||||
}
|
||||
#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)
|
||||
{
|
||||
// Disabled as jcc has issues in games
|
||||
Default(opc); return;
|
||||
#if 0
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
|
||||
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(64, R(RSI), ImmPtr(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MatR(RAX), 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((void *)dsp_reg_store_stack, DSP_STACK_C, emitter.compilePC + 2);
|
||||
#ifdef _M_IX86 // All32
|
||||
emitter.MOV(16, M(&(g_dsp.pc)), Imm16(dest));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.JMPptr(M(&emitter.blockLinks[dest]));
|
||||
}
|
||||
#else
|
||||
emitter.MOV(64, R(RAX), ImmPtr(&(g_dsp.pc)));
|
||||
emitter.MOV(16, MDisp(RAX,0), Imm16(dest));
|
||||
|
||||
// Jump directly to the called block if it has already been compiled.
|
||||
// TODO: Subtract cycles from cyclesLeft
|
||||
if (emitter.blockLinks[dest])
|
||||
{
|
||||
emitter.MOV(64, R(RAX), ImmPtr((void *)(emitter.blockLinks[dest])));
|
||||
emitter.JMPptr(R(RAX));
|
||||
emitter.ClearCallFlag();
|
||||
}
|
||||
#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((void *)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(64, R(RSI), ImmPtr(&g_dsp.r[reg]));
|
||||
emitter.MOV(16, R(RSI), MatR(RSI));
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,367 +1,367 @@
|
|||
// Copyright (C) 2003 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "../DSPIntCCUtil.h"
|
||||
#include "../DSPIntUtil.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
using namespace Gen;
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address
|
||||
// CR[0-7] | M. That is, the upper 8 bits of the address are the
|
||||
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void DSPEmitter::srs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
MOVZX(32, 8, EAX, M(&g_dsp.r[DSP_REG_CR]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
MOVZX(64, 8, RAX, MDisp(R11,DSP_REG_CR*2));
|
||||
#endif
|
||||
SHL(16, R(EAX), Imm8(8));
|
||||
OR(8, R(EAX), Imm8(opc & 0xFF));
|
||||
dmem_write();
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register
|
||||
// $(0x18+D). That is, the upper 8 bits of the address are the bottom 8 bits
|
||||
// from CR, and the lower 8 bits are from the 8-bit immediate.
|
||||
void DSPEmitter::lrs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 8, ECX, M(&g_dsp.r[DSP_REG_CR]));
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
MOV(16, M(&g_dsp.r[reg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 8, RCX, MDisp(R11,DSP_REG_CR*2));
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,reg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lr(const UDSPInstruction opc)
|
||||
{
|
||||
int reg = opc & DSP_REG_MASK;
|
||||
u16 addr = dsp_imem_read(compilePC + 1);
|
||||
dmem_read_imm(addr);
|
||||
dsp_op_write_reg(reg, EAX);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::sr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = opc & DSP_REG_MASK;
|
||||
u16 addr = dsp_imem_read(compilePC + 1);
|
||||
dsp_op_read_reg(reg, ECX);
|
||||
dmem_write_imm(addr);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
void DSPEmitter::si(const UDSPInstruction opc)
|
||||
{
|
||||
u16 addr = (s8)opc;
|
||||
u16 imm = dsp_imem_read(compilePC + 1);
|
||||
MOV(32, R(ECX), Imm32((u32)imm));
|
||||
dmem_write_imm(addr);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
//void DSPEmitter::lrrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 sreg = (opc >> 5) & 0x3;
|
||||
// u8 dreg = opc & 0x1f;
|
||||
|
||||
// u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
|
||||
// dsp_op_write_reg(dreg, val);
|
||||
// dsp_conditional_extend_accum(dreg);
|
||||
// g_dsp.r[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
//}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
//void DSPEmitter::srrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 dreg = (opc >> 5) & 0x3;
|
||||
// u8 sreg = opc & 0x1f;
|
||||
|
||||
// u16 val = dsp_op_read_reg(sreg);
|
||||
// dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
//}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void DSPEmitter::ilrr(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void DSPEmitter::ilrrd(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void DSPEmitter::ilrri(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
//void DSPEmitter::ilrrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u16 reg = opc & 0x3;
|
||||
// u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
// g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
// dsp_conditional_extend_accum(dreg);
|
||||
// g_dsp.r[reg] = dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
//}
|
||||
|
||||
//} // namespace
|
||||
//
|
||||
// Copyright (C) 2003 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/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "../DSPIntCCUtil.h"
|
||||
#include "../DSPIntUtil.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
using namespace Gen;
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address
|
||||
// CR[0-7] | M. That is, the upper 8 bits of the address are the
|
||||
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void DSPEmitter::srs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
MOVZX(32, 8, EAX, M(&g_dsp.r[DSP_REG_CR]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
MOVZX(64, 8, RAX, MDisp(R11,DSP_REG_CR*2));
|
||||
#endif
|
||||
SHL(16, R(EAX), Imm8(8));
|
||||
OR(8, R(EAX), Imm8(opc & 0xFF));
|
||||
dmem_write();
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register
|
||||
// $(0x18+D). That is, the upper 8 bits of the address are the bottom 8 bits
|
||||
// from CR, and the lower 8 bits are from the 8-bit immediate.
|
||||
void DSPEmitter::lrs(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + 0x18;
|
||||
//u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc & 0xFF);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 8, ECX, M(&g_dsp.r[DSP_REG_CR]));
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
MOV(16, M(&g_dsp.r[reg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 8, RCX, MDisp(R11,DSP_REG_CR*2));
|
||||
SHL(16, R(ECX), Imm8(8));
|
||||
OR(8, R(ECX), Imm8(opc & 0xFF));
|
||||
dmem_read();
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,reg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lr(const UDSPInstruction opc)
|
||||
{
|
||||
int reg = opc & DSP_REG_MASK;
|
||||
u16 address = dsp_imem_read(compilePC + 1);
|
||||
dmem_read_imm(address);
|
||||
dsp_op_write_reg(reg, EAX);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
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);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
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);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lrri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = (opc >> 5) & 0x3;
|
||||
u8 dreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, R(ECX));
|
||||
#else
|
||||
MOVZX(64, 16, ECX, R(ECX));
|
||||
#endif
|
||||
dmem_read();
|
||||
dsp_op_write_reg(dreg, EAX);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
//void DSPEmitter::lrrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 sreg = (opc >> 5) & 0x3;
|
||||
// u8 dreg = opc & 0x1f;
|
||||
|
||||
// u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
|
||||
// dsp_op_write_reg(dreg, val);
|
||||
// dsp_conditional_extend_accum(dreg);
|
||||
// g_dsp.r[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
//}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srrd(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void DSPEmitter::srri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 dreg = (opc >> 5) & 0x3;
|
||||
u8 sreg = opc & 0x1f;
|
||||
|
||||
dsp_op_read_reg(sreg, ECX);
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, EAX, M(&g_dsp.r[dreg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RAX, MDisp(R11,dreg*2));
|
||||
#endif
|
||||
dmem_write();
|
||||
increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
//void DSPEmitter::srrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u8 dreg = (opc >> 5) & 0x3;
|
||||
// u8 sreg = opc & 0x1f;
|
||||
|
||||
// u16 val = dsp_op_read_reg(sreg);
|
||||
// dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
//}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void DSPEmitter::ilrr(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void DSPEmitter::ilrrd(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void DSPEmitter::ilrri(const UDSPInstruction opc)
|
||||
{
|
||||
u16 reg = opc & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
#ifdef _M_IX86 // All32
|
||||
MOVZX(32, 16, ECX, M(&g_dsp.r[reg]));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOVZX(64, 16, RCX, MDisp(R11,reg*2));
|
||||
#endif
|
||||
imem_read();
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.r[dreg]), R(EAX));
|
||||
#else
|
||||
MOV(64, R(R11), ImmPtr(g_dsp.r));
|
||||
MOV(16, MDisp(R11,dreg*2), R(RAX));
|
||||
#endif
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
//void DSPEmitter::ilrrn(const UDSPInstruction opc)
|
||||
//{
|
||||
// u16 reg = opc & 0x3;
|
||||
// u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
|
||||
|
||||
// g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
// dsp_conditional_extend_accum(dreg);
|
||||
// g_dsp.r[reg] = dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
//}
|
||||
|
||||
//} // namespace
|
||||
//
|
||||
|
|
|
@ -333,26 +333,27 @@ void DSPEmitter::dmem_write()
|
|||
}
|
||||
|
||||
// ECX - value
|
||||
void DSPEmitter::dmem_write_imm(u16 addr)
|
||||
void DSPEmitter::dmem_write_imm(u16 address)
|
||||
{
|
||||
switch (addr >> 12)
|
||||
switch (address >> 12)
|
||||
{
|
||||
case 0x0: // 0xxx DRAM
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, M(&g_dsp.dram[addr & DSP_DRAM_MASK]), R(ECX));
|
||||
MOV(16, M(&g_dsp.dram[address & DSP_DRAM_MASK]), R(ECX));
|
||||
#else
|
||||
MOV(64, R(RDX), ImmPtr(g_dsp.dram));
|
||||
MOV(16, MDisp(RDX,(addr & DSP_DRAM_MASK)*2), R(ECX));
|
||||
MOV(16, MDisp(RDX,(address & DSP_DRAM_MASK)*2), R(ECX));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xf: // Fxxx HW regs
|
||||
MOV(16, R(EAX), Imm16(addr));
|
||||
MOV(16, R(EAX), Imm16(address));
|
||||
ABI_CallFunctionRR((void *)gdsp_ifx_write, EAX, ECX);
|
||||
break;
|
||||
|
||||
default: // Unmapped/non-existing memory
|
||||
ERROR_LOG(DSPLLE, "%04x DSP ERROR: Write to UNKNOWN (%04x) memory", g_dsp.pc, addr);
|
||||
ERROR_LOG(DSPLLE, "%04x DSP ERROR: Write to UNKNOWN (%04x) memory",
|
||||
g_dsp.pc, address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -431,34 +432,35 @@ void DSPEmitter::dmem_read()
|
|||
SetJumpTarget(end2);
|
||||
}
|
||||
|
||||
void DSPEmitter::dmem_read_imm(u16 addr)
|
||||
void DSPEmitter::dmem_read_imm(u16 address)
|
||||
{
|
||||
switch (addr >> 12)
|
||||
switch (address >> 12)
|
||||
{
|
||||
case 0x0: // 0xxx DRAM
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(EAX), M(&g_dsp.dram[addr & DSP_DRAM_MASK]));
|
||||
MOV(16, R(EAX), M(&g_dsp.dram[address & DSP_DRAM_MASK]));
|
||||
#else
|
||||
MOV(64, R(RDX), ImmPtr(g_dsp.dram));
|
||||
MOV(16, R(EAX), MDisp(RDX,(addr & DSP_DRAM_MASK)*2));
|
||||
MOV(16, R(EAX), MDisp(RDX,(address & DSP_DRAM_MASK)*2));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x1: // 1xxx COEF
|
||||
#ifdef _M_IX86 // All32
|
||||
MOV(16, R(EAX), Imm16(g_dsp.coef[addr & DSP_COEF_MASK]));
|
||||
MOV(16, R(EAX), Imm16(g_dsp.coef[address & DSP_COEF_MASK]));
|
||||
#else
|
||||
MOV(64, R(RDX), ImmPtr(g_dsp.coef));
|
||||
MOV(16, R(EAX), MDisp(RDX,(addr & DSP_COEF_MASK)*2));
|
||||
MOV(16, R(EAX), MDisp(RDX,(address & DSP_COEF_MASK)*2));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0xf: // Fxxx HW regs
|
||||
ABI_CallFunctionC16((void *)gdsp_ifx_read, addr);
|
||||
ABI_CallFunctionC16((void *)gdsp_ifx_read, address);
|
||||
break;
|
||||
|
||||
default: // Unmapped/non-existing memory
|
||||
ERROR_LOG(DSPLLE, "%04x DSP ERROR: Read from UNKNOWN (%04x) memory", g_dsp.pc, addr);
|
||||
ERROR_LOG(DSPLLE, "%04x DSP ERROR: Read from UNKNOWN (%04x) memory",
|
||||
g_dsp.pc, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ void TexDecoder_OpenCL_Initialize()
|
|||
char *header = NULL;
|
||||
size_t nDevices = 0;
|
||||
cl_device_id *devices = NULL;
|
||||
cl_program program = NULL;
|
||||
size_t *binary_sizes = NULL;
|
||||
char **binaries = NULL;
|
||||
char filename[1024];
|
||||
|
|
Loading…
Reference in New Issue