DSP Jit: Jit some more AR action and added compile SR which suppose to hold the status for
flags such as S40 which we can use to optimize compile. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5331 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
524a6dd2bb
commit
d950726041
|
@ -457,6 +457,10 @@
|
|||
RelativePath=".\Src\Jit\DSPJitUtil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitMisc.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Src\assemble.cpp"
|
||||
|
|
|
@ -44,6 +44,9 @@ DSPEmitter::DSPEmitter()
|
|||
blockSize[i] = 0;
|
||||
endBlock[i] = false;
|
||||
}
|
||||
compileSR = 0;
|
||||
compileSR |= SR_INT_ENABLE;
|
||||
compileSR |= SR_EXT_INT_ENABLE;
|
||||
}
|
||||
|
||||
DSPEmitter::~DSPEmitter()
|
||||
|
|
|
@ -32,6 +32,7 @@ class DSPEmitter : public Gen::XCodeBlock
|
|||
CompiledCode *blocks;
|
||||
u16 blockSize[0x10000];
|
||||
bool *endBlock;
|
||||
u16 compileSR;
|
||||
DISALLOW_COPY_AND_ASSIGN(DSPEmitter);
|
||||
|
||||
public:
|
||||
|
@ -48,6 +49,10 @@ public:
|
|||
|
||||
void STACKALIGN RunBlock(int cycles);
|
||||
|
||||
// Register helpers
|
||||
void setSR(u16 bit);
|
||||
void clrSR(u16 bit);
|
||||
|
||||
// Memory helper functions
|
||||
void increment_addr_reg(int reg);
|
||||
void decrement_addr_reg(int reg);
|
||||
|
@ -79,6 +84,15 @@ public:
|
|||
void ir(const UDSPInstruction opc);
|
||||
void nr(const UDSPInstruction opc);
|
||||
void nop(const UDSPInstruction opc) {}
|
||||
|
||||
// Commands
|
||||
void dar(const UDSPInstruction opc);
|
||||
void iar(const UDSPInstruction opc);
|
||||
void subarn(const UDSPInstruction opc);
|
||||
void addarn(const UDSPInstruction opc);
|
||||
void sbclr(const UDSPInstruction opc);
|
||||
void sbset(const UDSPInstruction opc);
|
||||
void srbith(const UDSPInstruction opc);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ const DSPOPCTemplate opcodes[] =
|
|||
{
|
||||
{"NOP", 0x0000, 0xfffc, nop, &DSPEmitter::nop, 1, 0, {}, false, false},
|
||||
|
||||
{"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"SUBARN", 0x000c, 0xfffc, DSPInterpreter::subarn, NULL, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, NULL, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false, false},
|
||||
{"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, &DSPEmitter::dar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, &DSPEmitter::iar, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"SUBARN", 0x000c, 0xfffc, DSPInterpreter::subarn, &DSPEmitter::subarn, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false},
|
||||
{"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, &DSPEmitter::addarn, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, false, false},
|
||||
|
||||
{"HALT", 0x0021, 0xffff, DSPInterpreter::halt, NULL, 1, 0, {}, false, true},
|
||||
|
||||
|
@ -146,8 +146,8 @@ const DSPOPCTemplate opcodes[] =
|
|||
{"CALLRO", 0x171e, 0xff1f, DSPInterpreter::callr, NULL, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||
{"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, NULL, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, false, true},
|
||||
|
||||
{"SBCLR", 0x1200, 0xff00, DSPInterpreter::sbclr, NULL, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
|
||||
{"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, NULL, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
|
||||
{"SBCLR", 0x1200, 0xff00, DSPInterpreter::sbclr, &DSPEmitter::sbclr, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
|
||||
{"SBSET", 0x1300, 0xff00, DSPInterpreter::sbset, &DSPEmitter::sbset, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, false, false},
|
||||
|
||||
{"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false},
|
||||
{"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, false, false},
|
||||
|
@ -255,12 +255,12 @@ const DSPOPCTemplate opcodes[] =
|
|||
{"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, NULL, 1 , 0, {}, true, false},
|
||||
{"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, NULL, 1 , 0, {}, true, false},
|
||||
{"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, NULL, 1 , 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false},
|
||||
{"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, NULL, 1 , 0, {}, true, false},
|
||||
{"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
{"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
{"CLR15", 0x8c00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
{"SET15", 0x8d00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
{"SET16", 0x8e00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
{"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1 , 0, {}, true, false},
|
||||
|
||||
//9
|
||||
{"MUL", 0x9000, 0xf700, DSPInterpreter::mul, NULL, 1 , 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false},
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
// 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 "DSPIntUtil.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
using namespace Gen;
|
||||
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
/*void DSPEmitter::mrr(const UDSPInstruction opc)
|
||||
{
|
||||
u8 sreg = opc & 0x1f;
|
||||
u8 dreg = (opc >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_conditional_extend_accum(dreg);
|
||||
}
|
||||
*/
|
||||
|
||||
// LRI $D, #I
|
||||
// 0000 0000 100d dddd
|
||||
// iiii iiii iiii iiii
|
||||
// Load immediate value I to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
//
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a
|
||||
// register, has a different behaviour in S40 mode if loaded to AC0.M: The
|
||||
// value gets sign extended to the whole accumulator! This does not happen in
|
||||
// S16 mode.
|
||||
/*void DSPEmitter::lri(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = opc & DSP_REG_MASK;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void DSPEmitter::lris(const UDSPInstruction opc)
|
||||
{
|
||||
u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
|
||||
u16 imm = (s8)opc;
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
// NX
|
||||
// 1000 -000 xxxx xxxx
|
||||
// No operation, but can be extended with extended opcode.
|
||||
// This opcode is supposed to do nothing - it's used if you want to use
|
||||
// an opcode extension but not do anything. At least according to duddie.
|
||||
void DSPEmitter::nx(const UDSPInstruction opc)
|
||||
{
|
||||
zeroWriteBackLog();
|
||||
}
|
||||
*/
|
||||
//----
|
||||
|
||||
// DAR $arD
|
||||
// 0000 0000 0000 01dd
|
||||
// Decrement address register $arD.
|
||||
void DSPEmitter::dar(const UDSPInstruction opc)
|
||||
{
|
||||
// g_dsp.r[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3);
|
||||
decrement_addr_reg(opc & 0x3);
|
||||
|
||||
}
|
||||
|
||||
// IAR $arD
|
||||
// 0000 0000 0000 10dd
|
||||
// Increment address register $arD.
|
||||
void DSPEmitter::iar(const UDSPInstruction opc)
|
||||
{
|
||||
// g_dsp.r[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3);
|
||||
increment_addr_reg(opc & 0x3);
|
||||
}
|
||||
|
||||
// SUBARN $arD
|
||||
// 0000 0000 0000 11dd
|
||||
// Subtract indexing register $ixD from an addressing register $arD.
|
||||
// used only in IPL-NTSC ucode
|
||||
void DSPEmitter::subarn(const UDSPInstruction opc)
|
||||
{
|
||||
// u8 dreg = opc & 0x3;
|
||||
// g_dsp.r[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
decrease_addr_reg(opc & 0x3);
|
||||
}
|
||||
|
||||
// ADDARN $arD, $ixS
|
||||
// 0000 0000 0001 ssdd
|
||||
// Adds indexing register $ixS to an addressing register $arD.
|
||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||
void DSPEmitter::addarn(const UDSPInstruction opc)
|
||||
{
|
||||
// u8 dreg = opc & 0x3;
|
||||
// u8 sreg = (opc >> 2) & 0x3;
|
||||
// g_dsp.r[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
|
||||
// From looking around it is always called with the matching index register
|
||||
increase_addr_reg(opc & 0x3);
|
||||
}
|
||||
|
||||
//----
|
||||
|
||||
|
||||
void DSPEmitter::setSR(u16 bit) {
|
||||
|
||||
// (1 << bit)
|
||||
MOV(32, R(EAX), Imm32(1));
|
||||
SHR(32, R(EAX), Imm32(bit));
|
||||
|
||||
// g_dsp.r[DSP_REG_SR] |= EAX
|
||||
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
OR(32, R(ECX), R(EAX));
|
||||
|
||||
compileSR |= (1 << bit);
|
||||
}
|
||||
|
||||
void DSPEmitter::clrSR(u16 bit) {
|
||||
// ~(1 << bit)
|
||||
MOV(32, R(EAX), Imm32(1));
|
||||
SHR(32, R(EAX), Imm32(bit));
|
||||
NOT(32, R(EAX));
|
||||
|
||||
// g_dsp.r[DSP_REG_SR] &= EAX
|
||||
MOV(16, R(ECX), M(&g_dsp.r[DSP_REG_SR]));
|
||||
AND(32, R(ECX), R(EAX));
|
||||
|
||||
compileSR &= ~(1 << bit);
|
||||
}
|
||||
// SBCLR #I
|
||||
// 0001 0011 aaaa aiii
|
||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void DSPEmitter::sbclr(const UDSPInstruction opc)
|
||||
{
|
||||
u16 bit = (opc & 0x7) + 6;
|
||||
|
||||
clrSR(bit);
|
||||
}
|
||||
|
||||
// SBSET #I
|
||||
// 0001 0010 aaaa aiii
|
||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void DSPEmitter::sbset(const UDSPInstruction opc)
|
||||
{
|
||||
u8 bit = (opc & 0x7) + 6;
|
||||
setSR(bit);
|
||||
}
|
||||
|
||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||
// but it's harder to know exactly what effect they have.
|
||||
void DSPEmitter::srbith(const UDSPInstruction opc)
|
||||
{
|
||||
ABI_CallFunction((void *)zeroWriteBackLog);
|
||||
switch ((opc >> 8) & 0xf)
|
||||
{
|
||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||
case 0xa: // M2
|
||||
clrSR(SR_MUL_MODIFY);
|
||||
break;
|
||||
case 0xb: // M0
|
||||
setSR(SR_MUL_MODIFY);
|
||||
break;
|
||||
|
||||
// If set, treat multiplicands as unsigned.
|
||||
// If clear, treat them as signed.
|
||||
case 0xc: // CLR15
|
||||
clrSR(SR_MUL_UNSIGNED);
|
||||
break;
|
||||
case 0xd: // SET15
|
||||
setSR(SR_MUL_UNSIGNED);
|
||||
break;
|
||||
|
||||
// Automatic 40-bit sign extension when loading ACx.M.
|
||||
// SET40 changes something very important: see the LRI instruction above.
|
||||
case 0xe: // SET16 (CLR40)
|
||||
clrSR(SR_40_MODE_BIT);
|
||||
break;
|
||||
|
||||
case 0xf: // SET40
|
||||
setSR(SR_40_MODE_BIT);
|
||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ files = [
|
|||
"DSPTables.cpp",
|
||||
"Jit/DSPJitExtOps.cpp",
|
||||
"Jit/DSPJitUtil.cpp",
|
||||
|
||||
"Jit/DSPJitMisc.cpp",
|
||||
]
|
||||
|
||||
acenv = env.Clone()
|
||||
|
|
Loading…
Reference in New Issue