mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
LLE JIT: Implemented some of the DSP multiplier functions in the JIT compiler. Only the x64 version has been implemented so far.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6511 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -19,6 +19,8 @@ set(SRCS Src/assemble.cpp
|
||||
Src/DSPCore.cpp
|
||||
Src/DSPTables.cpp
|
||||
Src/Jit/DSPJitExtOps.cpp
|
||||
Src/Jit/DSPJitCCUtil.cpp
|
||||
Src/Jit/DSPJitMultiplier.cpp
|
||||
Src/Jit/DSPJitUtil.cpp
|
||||
Src/Jit/DSPJitMisc.cpp)
|
||||
|
||||
|
||||
@@ -458,6 +458,10 @@
|
||||
RelativePath=".\Src\DSPEmitter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitCCUtil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitExtOps.cpp"
|
||||
>
|
||||
@@ -466,6 +470,10 @@
|
||||
RelativePath=".\Src\Jit\DSPJitMisc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitMultiplier.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Jit\DSPJitUtil.cpp"
|
||||
>
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
|
||||
int STACKALIGN RunForCycles(int cycles);
|
||||
|
||||
// CC Util
|
||||
void Update_SR_Register64(bool carry = false, bool overflow = false);
|
||||
|
||||
// Register helpers
|
||||
void setCompileSR(u16 bit);
|
||||
void clrCompileSR(u16 bit);
|
||||
@@ -113,6 +116,20 @@ public:
|
||||
void mrr(const UDSPInstruction opc);
|
||||
void nx(const UDSPInstruction opc);
|
||||
|
||||
// Multipliers
|
||||
void get_multiply_prod();
|
||||
void multiply();
|
||||
void clrp(const UDSPInstruction opc);
|
||||
void tstprod(const UDSPInstruction opc);
|
||||
void movp(const UDSPInstruction opc);
|
||||
void movnp(const UDSPInstruction opc);
|
||||
void movpz(const UDSPInstruction opc);
|
||||
void mulaxh(const UDSPInstruction opc);
|
||||
void mul(const UDSPInstruction opc);
|
||||
void mulmv(const UDSPInstruction opc);
|
||||
void mulmvz(const UDSPInstruction opc);
|
||||
void mulc(const UDSPInstruction opc);
|
||||
|
||||
// CALL this to start the dispatcher
|
||||
const u8 *enterDispatcher;
|
||||
|
||||
@@ -131,7 +148,15 @@ private:
|
||||
void ToMask(Gen::X64Reg value_reg = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
|
||||
void dsp_increment_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
|
||||
void dsp_decrement_one(Gen::X64Reg ar = Gen::EAX, Gen::X64Reg wr = Gen::EDX, Gen::X64Reg wr_pow = Gen::EDI, Gen::X64Reg temp_reg = Gen::ESI);
|
||||
};
|
||||
void get_long_prod();
|
||||
void get_long_prod_round_prodl();
|
||||
void set_long_prod();
|
||||
void set_long_acc(int _reg);
|
||||
void get_acc_m(int _reg);
|
||||
void get_ax_l(int _reg);
|
||||
void get_ax_h(int _reg);
|
||||
void get_long_acc(int _reg);
|
||||
};
|
||||
|
||||
|
||||
#endif // _DSPEMITTER_H
|
||||
|
||||
@@ -235,7 +235,7 @@ const DSPOPCTemplate opcodes[] =
|
||||
{"MOVR", 0x6000, 0xf800, DSPInterpreter::movr, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, true, false, false},
|
||||
{"MOVAX", 0x6800, 0xfc00, DSPInterpreter::movax, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}}, true, false, false},
|
||||
{"MOV", 0x6c00, 0xfe00, DSPInterpreter::mov, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, NULL, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MOVP", 0x6e00, 0xfe00, DSPInterpreter::movp, &DSPEmitter::movp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
|
||||
//7
|
||||
{"ADDAXL", 0x7000, 0xfc00, DSPInterpreter::addaxl, NULL, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, true, false, false},
|
||||
@@ -244,15 +244,15 @@ const DSPOPCTemplate opcodes[] =
|
||||
{"DECM", 0x7800, 0xfe00, DSPInterpreter::decm, NULL, 1, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"DEC", 0x7a00, 0xfe00, DSPInterpreter::dec, NULL, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"NEG", 0x7c00, 0xfe00, DSPInterpreter::neg, NULL, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MOVNP", 0x7e00, 0xfe00, DSPInterpreter::movnp, NULL, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MOVNP", 0x7e00, 0xfe00, DSPInterpreter::movnp, &DSPEmitter::movnp, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
|
||||
//8
|
||||
{"NX", 0x8000, 0xf700, DSPInterpreter::nx, &DSPEmitter::nx, 1, 0, {}, true, false, false},
|
||||
{"CLR", 0x8100, 0xf700, DSPInterpreter::clr, NULL, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"CMP", 0x8200, 0xff00, DSPInterpreter::cmp, NULL, 1, 0, {}, true, false, false},
|
||||
{"MULAXH", 0x8300, 0xff00, DSPInterpreter::mulaxh, NULL, 1, 0, {}, true, false, false},
|
||||
{"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, NULL, 1, 0, {}, true, false, false},
|
||||
{"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, NULL, 1, 0, {}, true, false, false},
|
||||
{"MULAXH", 0x8300, 0xff00, DSPInterpreter::mulaxh, &DSPEmitter::mulaxh, 1, 0, {}, true, false, false},
|
||||
{"CLRP", 0x8400, 0xff00, DSPInterpreter::clrp, &DSPEmitter::clrp, 1, 0, {}, true, false, false},
|
||||
{"TSTPROD", 0x8500, 0xff00, DSPInterpreter::tstprod, &DSPEmitter::tstprod,1, 0, {}, true, false, false},
|
||||
{"TSTAXH", 0x8600, 0xfe00, DSPInterpreter::tstaxh, NULL, 1, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"M2", 0x8a00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false},
|
||||
{"M0", 0x8b00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false},
|
||||
@@ -262,11 +262,11 @@ const DSPOPCTemplate opcodes[] =
|
||||
{"SET40", 0x8f00, 0xff00, DSPInterpreter::srbith, &DSPEmitter::srbith, 1, 0, {}, true, false, false},
|
||||
|
||||
//9
|
||||
{"MUL", 0x9000, 0xf700, DSPInterpreter::mul, NULL, 1, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"MUL", 0x9000, 0xf700, DSPInterpreter::mul, &DSPEmitter::mul, 1, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"ASR16", 0x9100, 0xf700, DSPInterpreter::asr16, NULL, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"MULMVZ", 0x9200, 0xf600, DSPInterpreter::mulmvz, NULL, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MULMVZ", 0x9200, 0xf600, DSPInterpreter::mulmvz, &DSPEmitter::mulmvz, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MULAC", 0x9400, 0xf600, DSPInterpreter::mulac, NULL, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MULMV", 0x9600, 0xf600, DSPInterpreter::mulmv, NULL, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MULMV", 0x9600, 0xf600, DSPInterpreter::mulmv, &DSPEmitter::mulmv, 1, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
|
||||
//a-b
|
||||
{"MULX", 0xa000, 0xe700, DSPInterpreter::mulx, NULL, 1, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, true, false, false},
|
||||
@@ -277,7 +277,7 @@ const DSPOPCTemplate opcodes[] =
|
||||
{"TST", 0xb100, 0xf700, DSPInterpreter::tst, NULL, 1, 1, {{P_ACC, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
|
||||
//c-d
|
||||
{"MULC", 0xc000, 0xe700, DSPInterpreter::mulc, NULL, 1, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"MULC", 0xc000, 0xe700, DSPInterpreter::mulc, &DSPEmitter::mulc, 1, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"CMPAR" , 0xc100, 0xe700, DSPInterpreter::cmpar, NULL, 1, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"MULCMVZ", 0xc200, 0xe600, DSPInterpreter::mulcmvz, NULL, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MULCAC", 0xc400, 0xe600, DSPInterpreter::mulcac, NULL, 1, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
@@ -296,7 +296,7 @@ const DSPOPCTemplate opcodes[] =
|
||||
{"MSUB", 0xf600, 0xfe00, DSPInterpreter::msub, NULL, 1, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"ADDPAXZ", 0xf800, 0xfc00, DSPInterpreter::addpaxz, NULL, 1, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"CLRL", 0xfc00, 0xfe00, DSPInterpreter::clrl, NULL, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false},
|
||||
{"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, NULL, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
{"MOVPZ", 0xfe00, 0xfe00, DSPInterpreter::movpz, &DSPEmitter::movpz, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false},
|
||||
};
|
||||
|
||||
const DSPOPCTemplate cw =
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
// 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
|
||||
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#include "../DSPIntUtil.h"
|
||||
#include "../DSPEmitter.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
using namespace Gen;
|
||||
|
||||
// In: RAX: s64 _Value,
|
||||
// Clobbers RDX
|
||||
void DSPEmitter::Update_SR_Register64(bool carry, bool overflow)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
AND(16, MDisp(R11, DSP_REG_SR * 2), Imm16(~SR_CMP_MASK));
|
||||
|
||||
// 0x01
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
|
||||
if (carry)
|
||||
{
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_CARRY));
|
||||
}
|
||||
|
||||
// 0x02 and 0x80
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW;
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY;
|
||||
if (overflow)
|
||||
{
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_OVERFLOW | SR_OVERFLOW_STICKY));
|
||||
}
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0) g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
TEST(64, R(RAX), R(RAX));
|
||||
FixupBranch notZero = J_CC(CC_NZ);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_ARITH_ZERO));
|
||||
SetJumpTarget(notZero);
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0) g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
FixupBranch greaterThanEqual = J_CC(CC_NS);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_SIGN));
|
||||
SetJumpTarget(greaterThanEqual);
|
||||
|
||||
// // 0x10
|
||||
// if (_Value != (s32)_Value) g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
MOVSX(64, 32, RDX, R(RAX));
|
||||
CMP(64, R(RDX), R(RAX));
|
||||
FixupBranch noOverS32 = J_CC(CC_E);
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_OVER_S32));
|
||||
SetJumpTarget(noOverS32);
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000))
|
||||
AND(32, R(EAX), Imm32(0xc0000000));
|
||||
CMP(32, R(EAX), Imm32(0));
|
||||
FixupBranch zeroC = J_CC(CC_E);
|
||||
CMP(32, R(EAX), Imm32(0xc0000000));
|
||||
FixupBranch cC = J_CC(CC_NE);
|
||||
SetJumpTarget(zeroC);
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||
OR(16, MDisp(R11, DSP_REG_SR * 2), Imm16(SR_TOP2BITS));
|
||||
SetJumpTarget(cC);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//void DSPEmitter::Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32)
|
||||
//{
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
// // 0x01
|
||||
// if (carry)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_CARRY;
|
||||
// }
|
||||
|
||||
// // 0x02 and 0x80
|
||||
// if (overflow)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW;
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVERFLOW_STICKY;
|
||||
// }
|
||||
|
||||
// // 0x04
|
||||
// if (_Value == 0)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
// }
|
||||
|
||||
// // 0x08
|
||||
// if (_Value < 0)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
// }
|
||||
|
||||
// // 0x10
|
||||
// if (overS32)
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_OVER_S32;
|
||||
// }
|
||||
|
||||
// // 0x20 - Checks if top bits of m are equal
|
||||
// if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
|
||||
// {
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_TOP2BITS;
|
||||
// }
|
||||
//}
|
||||
|
||||
//void DSPEmitter::Update_SR_LZ(bool value) {
|
||||
|
||||
// if (value == true)
|
||||
// g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||
// else
|
||||
// g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||
//}
|
||||
|
||||
//inline int GetMultiplyModifier()
|
||||
//{
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)?1:2;
|
||||
//}
|
||||
|
||||
//inline bool isCarry() {
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||
//}
|
||||
|
||||
//inline bool isOverflow() {
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_OVERFLOW) ? true : false;
|
||||
//}
|
||||
|
||||
//inline bool isOverS32() {
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_OVER_S32) ? true : false;
|
||||
//}
|
||||
|
||||
//inline bool isLess() {
|
||||
// return (!(g_dsp.r[DSP_REG_SR] & SR_OVERFLOW) != !(g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||
//}
|
||||
|
||||
//inline bool isZero() {
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||
//}
|
||||
|
||||
//inline bool isLogicZero() {
|
||||
// return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) ? true : false;
|
||||
//}
|
||||
|
||||
//inline bool isConditionA() {
|
||||
// return (((g_dsp.r[DSP_REG_SR] & SR_OVER_S32) || (g_dsp.r[DSP_REG_SR] & SR_TOP2BITS)) && !(g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO)) ? true : false;
|
||||
//}
|
||||
|
||||
//see DSPCore.h for flags
|
||||
//bool CheckCondition(u8 _Condition)
|
||||
//{
|
||||
// switch (_Condition & 0xf)
|
||||
// {
|
||||
// case 0xf: // Always true.
|
||||
// return true;
|
||||
// case 0x0: // GE - Greater Equal
|
||||
// return !isLess();
|
||||
// case 0x1: // L - Less
|
||||
// return isLess();
|
||||
// case 0x2: // G - Greater
|
||||
// return !isLess() && !isZero();
|
||||
// case 0x3: // LE - Less Equal
|
||||
// return isLess() || isZero();
|
||||
// case 0x4: // NZ - Not Zero
|
||||
// return !isZero();
|
||||
// case 0x5: // Z - Zero
|
||||
// return isZero();
|
||||
// case 0x6: // NC - Not carry
|
||||
// return !isCarry();
|
||||
// case 0x7: // C - Carry
|
||||
// return isCarry();
|
||||
// case 0x8: // ? - Not over s32
|
||||
// return !isOverS32();
|
||||
// case 0x9: // ? - Over s32
|
||||
// return isOverS32();
|
||||
// case 0xa: // ?
|
||||
// return isConditionA();
|
||||
// case 0xb: // ?
|
||||
// return !isConditionA();
|
||||
// case 0xc: // LNZ - Logic Not Zero
|
||||
// return !isLogicZero();
|
||||
// case 0xd: // LZ - Logic Zero
|
||||
// return isLogicZero();
|
||||
// case 0xe: // 0 - Overflow
|
||||
// return isOverflow();
|
||||
// default:
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -402,4 +402,144 @@ void DSPEmitter::ext_dmem_read(u16 addr)
|
||||
SetJumpTarget(end2);
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
// Clobbers RSI
|
||||
void DSPEmitter::get_long_prod()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
//s64 val = (s8)(u8)g_dsp.r[DSP_REG_PRODH];
|
||||
MOVSX(64, 8, RAX, MDisp(R11,DSP_REG_PRODH*2));
|
||||
//val <<= 32;
|
||||
SHL(64, R(RAX), Imm8(32));
|
||||
//s64 low_prod = g_dsp.r[DSP_REG_PRODM];
|
||||
MOVSX(64, 16, RSI, MDisp(R11,DSP_REG_PRODM*2));
|
||||
//low_prod += g_dsp.r[DSP_REG_PRODM2];
|
||||
MOVSX(64, 16, EDI, MDisp(R11,DSP_REG_PRODM2*2));
|
||||
ADD(16, R(RSI), R(EDI));
|
||||
//low_prod <<= 16;
|
||||
SHL(64, R(RSI), Imm8(16));
|
||||
OR(64, R(RAX), R(RSI));
|
||||
//low_prod |= g_dsp.r[DSP_REG_PRODL];
|
||||
MOV(16, R(RAX), MDisp(R11,DSP_REG_PRODL*2));
|
||||
//return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
// Clobbers RSI
|
||||
void DSPEmitter::get_long_prod_round_prodl()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
//s64 prod = dsp_get_long_prod();
|
||||
get_long_prod();
|
||||
|
||||
//if (prod & 0x10000) prod = (prod + 0x8000) & ~0xffff;
|
||||
TEST(32, R(EAX), Imm32(0x10000));
|
||||
FixupBranch jump = J_CC(CC_Z);
|
||||
ADD(64, R(RAX), Imm32(0x8000));
|
||||
MOV(64, R(ESI), Imm64(~0xffff));
|
||||
AND(64, R(RAX), R(RSI));
|
||||
FixupBranch ret = J();
|
||||
//else prod = (prod + 0x7fff) & ~0xffff;
|
||||
SetJumpTarget(jump);
|
||||
ADD(64, R(RAX), Imm32(0x7fff));
|
||||
MOV(64, R(RSI), Imm64(~0xffff));
|
||||
AND(64, R(RAX), R(RSI));
|
||||
SetJumpTarget(ret);
|
||||
//return prod;
|
||||
#endif
|
||||
}
|
||||
|
||||
// For accurate emulation, this is wrong - but the real prod registers behave
|
||||
// in completely bizarre ways. Probably not meaningful to emulate them accurately.
|
||||
// In: RAX = s64 val
|
||||
void DSPEmitter::set_long_prod()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
// g_dsp.r[DSP_REG_PRODL] = (u16)val;
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, DSP_REG_PRODL * 2), R(AX));
|
||||
// val >>= 16;
|
||||
SHR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_PRODM] = (u16)val;
|
||||
MOV(16, MDisp(R11, DSP_REG_PRODM * 2), R(AX));
|
||||
// val >>= 16;
|
||||
SHR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_PRODH] = (u8)val;
|
||||
MOVZX(64, 8, RAX, R(AL));
|
||||
MOV(8, MDisp(R11, DSP_REG_PRODH * 2), R(AL));
|
||||
// g_dsp.r[DSP_REG_PRODM2] = 0;
|
||||
MOV(16, MDisp(R11, DSP_REG_PRODM2 * 2), Imm16(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s64 in RAX
|
||||
// Clobbers ESI
|
||||
void DSPEmitter::get_long_acc(int _reg)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
// s64 high = (s64)(s8)g_dsp.r[DSP_REG_ACH0 + reg] << 32;
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOVSX(64, 8, EAX, MDisp(R11, (DSP_REG_ACH0 + _reg) * 2));
|
||||
SHL(64, R(EAX), Imm8(32));
|
||||
// u32 mid_low = ((u32)g_dsp.r[DSP_REG_ACM0 + reg] << 16) | g_dsp.r[DSP_REG_ACL0 + reg];
|
||||
MOVZX(64, 16, RSI, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2));
|
||||
SHL(32, R(RSI), Imm8(16));
|
||||
OR(64, R(EAX), R(RSI));
|
||||
MOVZX(64, 16, RSI, MDisp(R11, (DSP_REG_ACL0 + _reg) * 2));
|
||||
OR(64, R(EAX), R(RSI));
|
||||
// return high | mid_low;
|
||||
#endif
|
||||
}
|
||||
|
||||
// In: RAX = s64 val
|
||||
void DSPEmitter::set_long_acc(int _reg)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
// g_dsp.r[DSP_REG_ACL0 + _reg] = (u16)val;
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, MDisp(R11, (DSP_REG_ACL0 + _reg) * 2), R(AX));
|
||||
// val >>= 16;
|
||||
SHR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_ACM0 + _reg] = (u16)val;
|
||||
MOV(16, MDisp(R11, (DSP_REG_ACM0 + _reg) * 2), R(AX));
|
||||
// val >>= 16;
|
||||
SHR(64, R(RAX), Imm8(16));
|
||||
// g_dsp.r[DSP_REG_ACH0 + _reg] = (u16)(s16)(s8)(u8)val;
|
||||
MOVSX(16, 8, AX, R(AX));
|
||||
MOV(16, MDisp(R11, (DSP_REG_ACH0 + _reg) * 2), R(AX));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in AX
|
||||
void DSPEmitter::get_acc_m(int _reg)
|
||||
{
|
||||
// return g_dsp.r[DSP_REG_ACM0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(EAX), MDisp(R11, (DSP_REG_ACM0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_l(int _reg)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXL0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(EAX), MDisp(R11, (DSP_REG_AXL0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns s16 in EAX
|
||||
void DSPEmitter::get_ax_h(int _reg)
|
||||
{
|
||||
// return (s16)g_dsp.r[DSP_REG_AXH0 + _reg];
|
||||
#ifdef _M_X64
|
||||
MOV(64, R(R11), ImmPtr(&g_dsp.r));
|
||||
MOV(16, R(EAX), MDisp(R11, (DSP_REG_AXH0 + _reg) * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,8 @@ files = [
|
||||
"DSPTables.cpp",
|
||||
"Jit/DSPJitExtOps.cpp",
|
||||
"Jit/DSPJitUtil.cpp",
|
||||
"Jit/DSPJitCCUtil.cpp",
|
||||
"Jit/DSPJitMultiplier.cpp",
|
||||
"Jit/DSPJitMisc.cpp",
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user