diff options
| author | Soren Jorvang <soren.jorvang@gmail.com> | 2010-12-19 16:03:39 +0000 |
|---|---|---|
| committer | Soren Jorvang <soren.jorvang@gmail.com> | 2010-12-19 16:03:39 +0000 |
| commit | 38a46ddf9443c4144cd176ea2fc8b7ae7e385fa0 (patch) | |
| tree | 7d0c3ba7dc967dee5884bcfe2847abfbb1162d57 /Source/Core/DSPCore | |
| parent | c68ae8e91e6e15ad89552975bf7664c39f314958 (diff) | |
Avoid shadowing variables.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6613 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore')
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp | 2302 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp | 572 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp | 734 | ||||
| -rw-r--r-- | Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp | 30 |
4 files changed, 1820 insertions, 1818 deletions
diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp index 54924be7e6..3278f6f26e 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitArithmetic.cpp @@ -1,1151 +1,1151 @@ -// 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;
-
-// CLR $acR
-// 1000 r001 xxxx xxxx
-// Clears accumulator $acR
-//
-// flags out: --10 0100
-//void DSPEmitter::clr(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 11) & 0x1;
-
-// dsp_set_long_acc(reg, 0);
-// Update_SR_Register64(0);
-// zeroWriteBackLog();
-//}
-
-// CLRL $acR.l
-// 1111 110r xxxx xxxx
-// Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR.
-//
-// flags out: --xx xx00
-//void DSPEmitter::clrl(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-// s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg));
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(reg, acc);
-// Update_SR_Register64(acc);
-//}
-
-//----
-
-// ANDCF $acD.m, #I
-// 0000 001r 1100 0000
-// iiii iiii iiii iiii
-// Set logic zero (LZ) flag in status register $sr if result of logic AND of
-// accumulator mid part $acD.m with immediate value I is equal I.
-//
-// flags out: -x-- ----
-//void DSPEmitter::andcf(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-
-// u16 imm = dsp_fetch_code();
-// u16 val = dsp_get_acc_m(reg);
-// Update_SR_LZ(((val & imm) == imm) ? true : false);
-//}
-
-// ANDF $acD.m, #I
-// 0000 001r 1010 0000
-// iiii iiii iiii iiii
-// Set logic zero (LZ) flag in status register $sr if result of logical AND
-// operation of accumulator mid part $acD.m with immediate value I is equal
-// immediate value 0.
-//
-// flags out: -x-- ----
-//void DSPEmitter::andf(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-
-// u16 imm = dsp_fetch_code();
-// u16 val = dsp_get_acc_m(reg);
-// Update_SR_LZ(((val & imm) == 0) ? true : false);
-//}
-
-//----
-
-// TST
-// 1011 r001 xxxx xxxx
-// Test accumulator %acR.
-//
-// flags out: --xx xx00
-//void DSPEmitter::tst(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 11) & 0x1;
-
-// s64 acc = dsp_get_long_acc(reg);
-// Update_SR_Register64(acc);
-// zeroWriteBackLog();
-//}
-
-// TSTAXH $axR.h
-// 1000 011r xxxx xxxx
-// Test high part of secondary accumulator $axR.h.
-//
-// flags out: --x0 xx00
-//void DSPEmitter::tstaxh(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-
-// s16 val = dsp_get_ax_h(reg);
-// Update_SR_Register16(val);
-// zeroWriteBackLog();
-//}
-
-//----
-
-// CMP
-// 1000 0010 xxxx xxxx
-// Compares accumulator $ac0 with accumulator $ac1.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::cmp(const UDSPInstruction opc)
-//{
-// s64 acc0 = dsp_get_long_acc(0);
-// s64 acc1 = dsp_get_long_acc(1);
-// s64 res = dsp_convert_long_acc(acc0 - acc1);
-//
-// Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100
-// zeroWriteBackLog();
-//}
-
-// CMPAR $acS axR.h
-// 1100 0001 xxxx xxxx
-// Compares accumulator $acS with accumulator axR.h.
-// Not described by Duddie's doc - at least not as a separate instruction.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::cmpar(const UDSPInstruction opc)
-//{
-// u8 rreg = ((opc >> 12) & 0x1) + DSP_REG_AXH0;
-// u8 sreg = (opc >> 11) & 0x1;
-
-// s64 sr = dsp_get_long_acc(sreg);
-// s64 rr = (s16)g_dsp.r[rreg];
-// rr <<= 16;
-// s64 res = dsp_convert_long_acc(sr - rr);
-//
-// Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res));
-// zeroWriteBackLog();
-//}
-
-// CMPI $amD, #I
-// 0000 001r 1000 0000
-// iiii iiii iiii iiii
-// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I.
-// Although flags are being set regarding whole accumulator register.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::cmpi(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-
-// s64 val = dsp_get_long_acc(reg);
-// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator.
-// s64 res = dsp_convert_long_acc(val - imm);
-
-// Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res));
-//}
-
-// CMPIS $acD, #I
-// 0000 011d iiii iiii
-// Compares accumulator with short immediate. Comaprison is executed
-// by subtracting short immediate (8bit sign extended) from mid accumulator
-// $acD.hm and computing flags based on whole accumulator $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::cmpis(const UDSPInstruction opc)
-//{
-// u8 areg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(areg);
-// s64 val = (s8)opc;
-// val <<= 16;
-// s64 res = dsp_convert_long_acc(acc - val);
-
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res));
-//}
-
-//----
-
-// XORR $acD.m, $axS.h
-// 0011 00sd 0xxx xxxx
-// Logic XOR (exclusive or) middle part of accumulator $acD.m with
-// high part of secondary accumulator $axS.h.
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::xorr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_AXH0 + sreg];
-//
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// ANDR $acD.m, $axS.h
-// 0011 01sd 0xxx xxxx
-// Logic AND middle part of accumulator $acD.m with high part of
-// secondary accumulator $axS.h.
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::andr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_AXH0 + sreg];
-//
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// ORR $acD.m, $axS.h
-// 0011 10sd 0xxx xxxx
-// Logic OR middle part of accumulator $acD.m with high part of
-// secondary accumulator $axS.h.
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::orr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_AXH0 + sreg];
-//
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// ANDC $acD.m, $ac(1-D).m
-// 0011 110d 0xxx xxxx
-// Logic AND middle part of accumulator $acD.m with middle part of
-// accumulator $ac(1-D).m
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::andc(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_ACM0 + (1 - dreg)];
-//
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// ORC $acD.m, $ac(1-D).m
-// 0011 111d 0xxx xxxx
-// Logic OR middle part of accumulator $acD.m with middle part of
-// accumulator $ac(1-D).m.
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::orc(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_ACM0 + (1 - dreg)];
-//
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// XORC $acD.m
-// 0011 000d 1xxx xxxx
-// Logic XOR (exclusive or) middle part of accumulator $acD.m with $ac(1-D).m
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::xorc(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_ACM0 + (1 - dreg)];
-
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// NOT $acD.m
-// 0011 001d 1xxx xxxx
-// Invert all bits in dest reg, aka xor with 0xffff
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::notc(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ 0xffff;
-
-// zeroWriteBackLogPreserveAcc(dreg);
-
-// g_dsp.r[DSP_REG_ACM0 + dreg] = accm;
-// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
-//}
-
-// XORI $acD.m, #I
-// 0000 001r 0010 0000
-// iiii iiii iiii iiii
-// Logic exclusive or (XOR) of accumulator mid part $acD.m with
-// immediate value I.
-//
-// flags out: --xx xx00
-//void DSPEmitter::xori(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-// u16 imm = dsp_fetch_code();
-// g_dsp.r[DSP_REG_ACM0 + reg] ^= imm;
-
-// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg)));
-//}
-
-// ANDI $acD.m, #I
-// 0000 001r 0100 0000
-// iiii iiii iiii iiii
-// Logic AND of accumulator mid part $acD.m with immediate value I.
-//
-// flags out: --xx xx00
-//void DSPEmitter::andi(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-// u16 imm = dsp_fetch_code();
-// g_dsp.r[DSP_REG_ACM0 + reg] &= imm;
-
-// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg)));
-//}
-
-// ORI $acD.m, #I
-// 0000 001r 0110 0000
-// iiii iiii iiii iiii
-// Logic OR of accumulator mid part $acD.m with immediate value I.
-//
-// flags out: --xx xx00
-//void DSPEmitter::ori(const UDSPInstruction opc)
-//{
-// u8 reg = (opc >> 8) & 0x1;
-// u16 imm = dsp_fetch_code();
-// g_dsp.r[DSP_REG_ACM0 + reg] |= imm;
-
-// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg)));
-//}
-
-//----
-
-// ADDR $acD.M, $axS.L
-// 0100 0ssd xxxx xxxx
-// Adds register $axS.L to accumulator $acD.M register.
-//
-// flags out: x-xx xxxx
-void DSPEmitter::addr(const UDSPInstruction opc)
-{
-#ifdef _M_X64
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
-
- MOV(64, R(R11), ImmPtr(&g_dsp.r));
-// s64 acc = dsp_get_long_acc(dreg);
- get_long_acc(dreg);
- PUSH(64, R(RAX));
-// s64 ax = (s16)g_dsp.r[sreg];
- MOVSX(64, 16, RDX, MDisp(R11, sreg * 2));
-// ax <<= 16;
- SHL(64, R(RDX), Imm8(16));
-// s64 res = acc + ax;
- ADD(64, R(RAX), R(RDX));
-// dsp_set_long_acc(dreg, res);
- set_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res));
- XOR(8, R(RSI), R(RSI));
- POP(64, R(RCX));
- CMP(64, R(RCX), R(RAX));
-
- // Carry = (acc>res)
- FixupBranch noCarry = J_CC(CC_G);
- OR(8, R(RSI), Imm8(1));
- SetJumpTarget(noCarry);
-
- // Overflow = ((acc ^ res) & (ax ^ res)) < 0
- XOR(64, R(RCX), R(RAX));
- XOR(64, R(RDX), R(RAX));
- AND(64, R(RCX), R(RDX));
- CMP(64, R(RCX), Imm8(0));
- FixupBranch noOverflow = J_CC(CC_L);
- OR(8, R(RSI), Imm8(2));
- SetJumpTarget(noOverflow);
-
- Update_SR_Register64();
-#else
- Default(opc);
-#endif
-}
-
-// ADDAX $acD, $axS
-// 0100 10sd xxxx xxxx
-// Adds secondary accumulator $axS to accumulator register $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::addax(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 ax = dsp_get_long_acx(sreg);
-// s64 res = acc + ax;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res));
-//}
-
-// ADD $acD, $ac(1-D)
-// 0100 110d xxxx xxxx
-// Adds accumulator $ac(1-D) to accumulator register $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::add(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc0 = dsp_get_long_acc(dreg);
-// s64 acc1 = dsp_get_long_acc(1 - dreg);
-// s64 res = acc0 + acc1;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res));
-//}
-
-// ADDP $acD
-// 0100 111d xxxx xxxx
-// Adds product register to accumulator register.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::addp(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 prod = dsp_get_long_prod();
-// s64 res = acc + prod;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res));
-//}
-
-// ADDAXL $acD, $axS.l
-// 0111 00sd xxxx xxxx
-// Adds secondary accumulator $axS.l to accumulator register $acD.
-// should be unsigned values!!
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::addaxl(const UDSPInstruction opc)
-//{
-// u8 sreg = (opc >> 9) & 0x1;
-// u8 dreg = (opc >> 8) & 0x1;
-
-// u64 acc = dsp_get_long_acc(dreg);
-// u16 acx = (u16)dsp_get_ax_l(sreg);
-
-// u64 res = acc + acx;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, (s64)res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res));
-//}
-
-// ADDI $amR, #I
-// 0000 001r 0000 0000
-// iiii iiii iiii iiii
-// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::addi(const UDSPInstruction opc)
-//{
-// u8 areg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(areg);
-// s64 imm = (s16)dsp_fetch_code();
-// imm <<= 16;
-// s64 res = acc + imm;
-
-// dsp_set_long_acc(areg, res);
-// res = dsp_get_long_acc(areg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res));
-//}
-
-// ADDIS $acD, #I
-// 0000 010d iiii iiii
-// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::addis(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 imm = (s8)(u8)opc;
-// imm <<= 16;
-// s64 res = acc + imm;
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res));
-//}
-
-// INCM $acsD
-// 0111 010d xxxx xxxx
-// Increment 24-bit mid-accumulator $acsD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::incm(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 sub = 0x10000;
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 res = acc + sub;
-
-// zeroWriteBackLog();
-//
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, sub, res));
-//}
-
-// INC $acD
-// 0111 011d xxxx xxxx
-// Increment accumulator $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::inc(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 res = acc + 1;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, 1, res));
-//}
-
-//----
-
-// SUBR $acD.M, $axS.L
-// 0101 0ssd xxxx xxxx
-// Subtracts register $axS.L from accumulator $acD.M register.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::subr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 ax = (s16)g_dsp.r[sreg];
-// ax <<= 16;
-// s64 res = acc - ax;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -ax, res));
-//}
-
-// SUBAX $acD, $axS
-// 0101 10sd xxxx xxxx
-// Subtracts secondary accumulator $axS from accumulator register $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::subax(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 acx = dsp_get_long_acx(sreg);
-// s64 res = acc - acx;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -acx, res));
-//}
-
-// SUB $acD, $ac(1-D)
-// 0101 110d xxxx xxxx
-// Subtracts accumulator $ac(1-D) from accumulator register $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::sub(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc1 = dsp_get_long_acc(dreg);
-// s64 acc2 = dsp_get_long_acc(1 - dreg);
-// s64 res = acc1 - acc2;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res));
-//}
-
-// SUBP $acD
-// 0101 111d xxxx xxxx
-// Subtracts product register from accumulator register.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::subp(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 prod = dsp_get_long_prod();
-// s64 res = acc - prod;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -prod, res));
-//}
-
-// DECM $acsD
-// 0111 100d xxxx xxxx
-// Decrement 24-bit mid-accumulator $acsD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::decm(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x01;
-
-// s64 sub = 0x10000;
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 res = acc - sub;
-
-// zeroWriteBackLog();
-//
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -sub, res));
-//}
-
-// DEC $acD
-// 0111 101d xxxx xxxx
-// Decrement accumulator $acD.
-//
-// flags out: x-xx xxxx
-//void DSPEmitter::dec(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x01;
-
-// s64 acc = dsp_get_long_acc(dreg);
-// s64 res = acc - 1;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, res);
-// res = dsp_get_long_acc(dreg);
-// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -1, res));
-//}
-
-//----
-
-// NEG $acD
-// 0111 110d xxxx xxxx
-// Negate accumulator $acD.
-//
-// flags out: --xx xx00
-//void DSPEmitter::neg(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-//
-// s64 acc = dsp_get_long_acc(dreg);
-// acc = 0 - acc;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-// ABS $acD
-// 1010 d001 xxxx xxxx
-// absolute value of $acD
-//
-// flags out: --xx xx00
-//void DSPEmitter::abs(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 11) & 0x1;
-
-// s64 acc = dsp_get_long_acc(dreg);
-
-// if (acc < 0)
-// acc = 0 - acc;
-//
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-//----
-
-// MOVR $acD, $axS.R
-// 0110 0srd xxxx xxxx
-// Moves register $axS.R (sign extended) to middle accumulator $acD.hm.
-// Sets $acD.l to 0.
-// TODO: Check what happens to acD.h.
-//
-// flags out: --xx xx00
-//void DSPEmitter::movr(const UDSPInstruction opc)
-//{
-// u8 areg = (opc >> 8) & 0x1;
-// u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
-//
-// s64 acc = (s16)g_dsp.r[sreg];
-// acc <<= 16;
-// acc &= ~0xffff;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(areg, acc);
-// Update_SR_Register64(acc);
-//}
-
-// MOVAX $acD, $axS
-// 0110 10sd xxxx xxxx
-// Moves secondary accumulator $axS to accumulator $axD.
-//
-// flags out: --xx xx00
-//void DSPEmitter::movax(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-
-// s64 acx = dsp_get_long_acx(sreg);
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acx);
-// Update_SR_Register64(acx);
-//}
-
-// MOV $acD, $ac(1-D)
-// 0110 110d xxxx xxxx
-// Moves accumulator $ax(1-D) to accumulator $axD.
-//
-// flags out: --x0 xx00
-//void DSPEmitter::mov(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u64 acc = dsp_get_long_acc(1 - dreg);
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(acc);
-//}
-
-//----
-
-// LSL16 $acR
-// 1111 000r xxxx xxxx
-// Logically shifts left accumulator $acR by 16.
-//
-// flags out: --xx xx00
-void DSPEmitter::lsl16(const UDSPInstruction opc)
-{
-#ifdef _M_X64
- u8 areg = (opc >> 8) & 0x1;
-// s64 acc = dsp_get_long_acc(areg);
- get_long_acc(areg);
-// acc <<= 16;
- SHL(64, R(RAX), Imm8(16));
-// dsp_set_long_acc(areg, acc);
- set_long_acc(areg);
-// Update_SR_Register64(dsp_get_long_acc(areg));
- Update_SR_Register64();
-#else
- Default(opc);
-#endif
-}
-
-// LSR16 $acR
-// 1111 010r xxxx xxxx
-// Logically shifts right accumulator $acR by 16.
-//
-// flags out: --xx xx00
-//void DSPEmitter::lsr16(const UDSPInstruction opc)
-//{
-// u8 areg = (opc >> 8) & 0x1;
-
-// u64 acc = dsp_get_long_acc(areg);
-// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes
-// acc >>= 16;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(areg, (s64)acc);
-// Update_SR_Register64(dsp_get_long_acc(areg));
-//}
-
-// ASR16 $acR
-// 1001 r001 xxxx xxxx
-// Arithmetically shifts right accumulator $acR by 16.
-//
-// flags out: --xx xx00
-//void DSPEmitter::asr16(const UDSPInstruction opc)
-//{
-// u8 areg = (opc >> 11) & 0x1;
-
-// s64 acc = dsp_get_long_acc(areg);
-// acc >>= 16;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(areg, acc);
-// Update_SR_Register64(dsp_get_long_acc(areg));
-//}
-
-// LSL $acR, #I
-// 0001 010r 00ii iiii
-// Logically shifts left accumulator $acR by number specified by value I.
-//
-// flags out: --xx xx00
-void DSPEmitter::lsl(const UDSPInstruction opc)
-{
-#ifdef _M_X64
- u8 rreg = (opc >> 8) & 0x01;
- u16 shift = opc & 0x3f;
-// u64 acc = dsp_get_long_acc(rreg);
- get_long_acc(rreg);
-
-// acc <<= shift;
- SHL(64, R(RAX), Imm8(shift));
-
-// dsp_set_long_acc(rreg, acc);
- set_long_acc(rreg);
-// Update_SR_Register64(dsp_get_long_acc(rreg));
- Update_SR_Register64();
-#else
- Default(opc);
-#endif
-}
-
-// LSR $acR, #I
-// 0001 010r 01ii iiii
-// Logically shifts right accumulator $acR by number specified by value
-// calculated by negating sign extended bits 0-6.
-//
-// flags out: --xx xx00
-//void DSPEmitter::lsr(const UDSPInstruction opc)
-//{
-// u8 rreg = (opc >> 8) & 0x01;
-// u16 shift;
-// u64 acc = dsp_get_long_acc(rreg);
-// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes
-
-// if ((opc & 0x3f) == 0)
-// shift = 0;
-// else
-// shift = 0x40 - (opc & 0x3f);
-
-// acc >>= shift;
-//
-// dsp_set_long_acc(rreg, (s64)acc);
-// Update_SR_Register64(dsp_get_long_acc(rreg));
-//}
-
-// ASL $acR, #I
-// 0001 010r 10ii iiii
-// Logically shifts left accumulator $acR by number specified by value I.
-//
-// flags out: --xx xx00
-//void DSPEmitter::asl(const UDSPInstruction opc)
-//{
-// u8 rreg = (opc >> 8) & 0x01;
-// u16 shift = opc & 0x3f;
-// u64 acc = dsp_get_long_acc(rreg);
-
-// acc <<= shift;
-//
-// dsp_set_long_acc(rreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(rreg));
-//}
-
-// ASR $acR, #I
-// 0001 010r 11ii iiii
-// Arithmetically shifts right accumulator $acR by number specified by
-// value calculated by negating sign extended bits 0-6.
-//
-// flags out: --xx xx00
-//void DSPEmitter::asr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x01;
-// u16 shift;
-
-// if ((opc & 0x3f) == 0)
-// shift = 0;
-// else
-// shift = 0x40 - (opc & 0x3f);
-
-// // arithmetic shift
-// s64 acc = dsp_get_long_acc(dreg);
-// acc >>= shift;
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-// LSRN (fixed parameters)
-// 0000 0010 1100 1010
-// Logically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M
-// (if value negative, becomes left shift).
-//
-// flags out: --xx xx00
-//void DSPEmitter::lsrn(const UDSPInstruction opc)
-//{
-// s16 shift;
-// u16 accm = (u16)dsp_get_acc_m(1);
-// u64 acc = dsp_get_long_acc(0);
-// acc &= 0x000000FFFFFFFFFFULL;
-
-// if ((accm & 0x3f) == 0)
-// shift = 0;
-// else if (accm & 0x40)
-// shift = -0x40 + (accm & 0x3f);
-// else
-// shift = accm & 0x3f;
-
-// if (shift > 0) {
-// acc >>= shift;
-// } else if (shift < 0) {
-// acc <<= -shift;
-// }
-
-// dsp_set_long_acc(0, (s64)acc);
-// Update_SR_Register64(dsp_get_long_acc(0));
-//}
-
-// ASRN (fixed parameters)
-// 0000 0010 1100 1011
-// Arithmetically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M
-// (if value negative, becomes left shift).
-//
-// flags out: --xx xx00
-//void DSPEmitter::asrn(const UDSPInstruction opc)
-//{
-// s16 shift;
-// u16 accm = (u16)dsp_get_acc_m(1);
-// s64 acc = dsp_get_long_acc(0);
-
-// if ((accm & 0x3f) == 0)
-// shift = 0;
-// else if (accm & 0x40)
-// shift = -0x40 + (accm & 0x3f);
-// else
-// shift = accm & 0x3f;
-
-// if (shift > 0) {
-// acc >>= shift;
-// } else if (shift < 0) {
-// acc <<= -shift;
-// }
-
-// dsp_set_long_acc(0, acc);
-// Update_SR_Register64(dsp_get_long_acc(0));
-//}
-
-// LSRNRX $acD, $axS.h
-// 0011 01sd 1xxx xxxx
-// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::lsrnrx(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-
-// s16 shift;
-// u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg];
-// u64 acc = dsp_get_long_acc(dreg);
-// acc &= 0x000000FFFFFFFFFFULL;
-
-// if ((axh & 0x3f) == 0)
-// shift = 0;
-// else if (axh & 0x40)
-// shift = -0x40 + (axh & 0x3f);
-// else
-// shift = axh & 0x3f;
-
-// if (shift > 0) {
-// acc <<= shift;
-// } else if (shift < 0) {
-// acc >>= -shift;
-// }
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, (s64)acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-// ASRNRX $acD, $axS.h
-// 0011 10sd 1xxx xxxx
-// Arithmetically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::asrnrx(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-// u8 sreg = (opc >> 9) & 0x1;
-
-// s16 shift;
-// u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg];
-// s64 acc = dsp_get_long_acc(dreg);
-
-// if ((axh & 0x3f) == 0)
-// shift = 0;
-// else if (axh & 0x40)
-// shift = -0x40 + (axh & 0x3f);
-// else
-// shift = axh & 0x3f;
-
-// if (shift > 0) {
-// acc <<= shift;
-// } else if (shift < 0) {
-// acc >>= -shift;
-// }
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-// LSRNR $acD
-// 0011 110d 1xxx xxxx
-// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::lsrnr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s16 shift;
-// u16 accm = (u16)dsp_get_acc_m(1 - dreg);
-// u64 acc = dsp_get_long_acc(dreg);
-// acc &= 0x000000FFFFFFFFFFULL;
-
-// if ((accm & 0x3f) == 0)
-// shift = 0;
-// else if (accm & 0x40)
-// shift = -0x40 + (accm & 0x3f);
-// else
-// shift = accm & 0x3f;
-
-// if (shift > 0)
-// acc <<= shift;
-// else if (shift < 0)
-// acc >>= -shift;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, (s64)acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-// ASRNR $acD
-// 0011 111d 1xxx xxxx
-// Arithmeticaly shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M
-// x = extension (7 bits!!)
-//
-// flags out: --xx xx00
-//void DSPEmitter::asrnr(const UDSPInstruction opc)
-//{
-// u8 dreg = (opc >> 8) & 0x1;
-
-// s16 shift;
-// u16 accm = (u16)dsp_get_acc_m(1 - dreg);
-// s64 acc = dsp_get_long_acc(dreg);
-
-// if ((accm & 0x3f) == 0)
-// shift = 0;
-// else if (accm & 0x40)
-// shift = -0x40 + (accm & 0x3f);
-// else
-// shift = accm & 0x3f;
-
-// if (shift > 0)
-// acc <<= shift;
-// else if (shift < 0)
-// acc >>= -shift;
-
-// zeroWriteBackLog();
-
-// dsp_set_long_acc(dreg, acc);
-// Update_SR_Register64(dsp_get_long_acc(dreg));
-//}
-
-
-//} // 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; + +// CLR $acR +// 1000 r001 xxxx xxxx +// Clears accumulator $acR +// +// flags out: --10 0100 +//void DSPEmitter::clr(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 11) & 0x1; + +// dsp_set_long_acc(reg, 0); +// Update_SR_Register64(0); +// zeroWriteBackLog(); +//} + +// CLRL $acR.l +// 1111 110r xxxx xxxx +// Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR. +// +// flags out: --xx xx00 +//void DSPEmitter::clrl(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; +// s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg)); + +// zeroWriteBackLog(); + +// dsp_set_long_acc(reg, acc); +// Update_SR_Register64(acc); +//} + +//---- + +// ANDCF $acD.m, #I +// 0000 001r 1100 0000 +// iiii iiii iiii iiii +// Set logic zero (LZ) flag in status register $sr if result of logic AND of +// accumulator mid part $acD.m with immediate value I is equal I. +// +// flags out: -x-- ---- +//void DSPEmitter::andcf(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; + +// u16 imm = dsp_fetch_code(); +// u16 val = dsp_get_acc_m(reg); +// Update_SR_LZ(((val & imm) == imm) ? true : false); +//} + +// ANDF $acD.m, #I +// 0000 001r 1010 0000 +// iiii iiii iiii iiii +// Set logic zero (LZ) flag in status register $sr if result of logical AND +// operation of accumulator mid part $acD.m with immediate value I is equal +// immediate value 0. +// +// flags out: -x-- ---- +//void DSPEmitter::andf(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; + +// u16 imm = dsp_fetch_code(); +// u16 val = dsp_get_acc_m(reg); +// Update_SR_LZ(((val & imm) == 0) ? true : false); +//} + +//---- + +// TST +// 1011 r001 xxxx xxxx +// Test accumulator %acR. +// +// flags out: --xx xx00 +//void DSPEmitter::tst(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 11) & 0x1; + +// s64 acc = dsp_get_long_acc(reg); +// Update_SR_Register64(acc); +// zeroWriteBackLog(); +//} + +// TSTAXH $axR.h +// 1000 011r xxxx xxxx +// Test high part of secondary accumulator $axR.h. +// +// flags out: --x0 xx00 +//void DSPEmitter::tstaxh(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; + +// s16 val = dsp_get_ax_h(reg); +// Update_SR_Register16(val); +// zeroWriteBackLog(); +//} + +//---- + +// CMP +// 1000 0010 xxxx xxxx +// Compares accumulator $ac0 with accumulator $ac1. +// +// flags out: x-xx xxxx +//void DSPEmitter::cmp(const UDSPInstruction opc) +//{ +// s64 acc0 = dsp_get_long_acc(0); +// s64 acc1 = dsp_get_long_acc(1); +// s64 res = dsp_convert_long_acc(acc0 - acc1); +// +// Update_SR_Register64(res, isCarry2(acc0, res), isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100 +// zeroWriteBackLog(); +//} + +// CMPAR $acS axR.h +// 1100 0001 xxxx xxxx +// Compares accumulator $acS with accumulator axR.h. +// Not described by Duddie's doc - at least not as a separate instruction. +// +// flags out: x-xx xxxx +//void DSPEmitter::cmpar(const UDSPInstruction opc) +//{ +// u8 rreg = ((opc >> 12) & 0x1) + DSP_REG_AXH0; +// u8 sreg = (opc >> 11) & 0x1; + +// s64 sr = dsp_get_long_acc(sreg); +// s64 rr = (s16)g_dsp.r[rreg]; +// rr <<= 16; +// s64 res = dsp_convert_long_acc(sr - rr); +// +// Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res)); +// zeroWriteBackLog(); +//} + +// CMPI $amD, #I +// 0000 001r 1000 0000 +// iiii iiii iiii iiii +// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I. +// Although flags are being set regarding whole accumulator register. +// +// flags out: x-xx xxxx +//void DSPEmitter::cmpi(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; + +// s64 val = dsp_get_long_acc(reg); +// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in the 40-bit accumulator. +// s64 res = dsp_convert_long_acc(val - imm); + +// Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res)); +//} + +// CMPIS $acD, #I +// 0000 011d iiii iiii +// Compares accumulator with short immediate. Comaprison is executed +// by subtracting short immediate (8bit sign extended) from mid accumulator +// $acD.hm and computing flags based on whole accumulator $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::cmpis(const UDSPInstruction opc) +//{ +// u8 areg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(areg); +// s64 val = (s8)opc; +// val <<= 16; +// s64 res = dsp_convert_long_acc(acc - val); + +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res)); +//} + +//---- + +// XORR $acD.m, $axS.h +// 0011 00sd 0xxx xxxx +// Logic XOR (exclusive or) middle part of accumulator $acD.m with +// high part of secondary accumulator $axS.h. +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::xorr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_AXH0 + sreg]; +// +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// ANDR $acD.m, $axS.h +// 0011 01sd 0xxx xxxx +// Logic AND middle part of accumulator $acD.m with high part of +// secondary accumulator $axS.h. +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::andr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_AXH0 + sreg]; +// +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// ORR $acD.m, $axS.h +// 0011 10sd 0xxx xxxx +// Logic OR middle part of accumulator $acD.m with high part of +// secondary accumulator $axS.h. +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::orr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_AXH0 + sreg]; +// +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// ANDC $acD.m, $ac(1-D).m +// 0011 110d 0xxx xxxx +// Logic AND middle part of accumulator $acD.m with middle part of +// accumulator $ac(1-D).m +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::andc(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] & g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; +// +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// ORC $acD.m, $ac(1-D).m +// 0011 111d 0xxx xxxx +// Logic OR middle part of accumulator $acD.m with middle part of +// accumulator $ac(1-D).m. +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::orc(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] | g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; +// +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// XORC $acD.m +// 0011 000d 1xxx xxxx +// Logic XOR (exclusive or) middle part of accumulator $acD.m with $ac(1-D).m +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::xorc(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ g_dsp.r[DSP_REG_ACM0 + (1 - dreg)]; + +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// NOT $acD.m +// 0011 001d 1xxx xxxx +// Invert all bits in dest reg, aka xor with 0xffff +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::notc(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u16 accm = g_dsp.r[DSP_REG_ACM0 + dreg] ^ 0xffff; + +// zeroWriteBackLogPreserveAcc(dreg); + +// g_dsp.r[DSP_REG_ACM0 + dreg] = accm; +// Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg))); +//} + +// XORI $acD.m, #I +// 0000 001r 0010 0000 +// iiii iiii iiii iiii +// Logic exclusive or (XOR) of accumulator mid part $acD.m with +// immediate value I. +// +// flags out: --xx xx00 +//void DSPEmitter::xori(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; +// u16 imm = dsp_fetch_code(); +// g_dsp.r[DSP_REG_ACM0 + reg] ^= imm; + +// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); +//} + +// ANDI $acD.m, #I +// 0000 001r 0100 0000 +// iiii iiii iiii iiii +// Logic AND of accumulator mid part $acD.m with immediate value I. +// +// flags out: --xx xx00 +//void DSPEmitter::andi(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; +// u16 imm = dsp_fetch_code(); +// g_dsp.r[DSP_REG_ACM0 + reg] &= imm; + +// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); +//} + +// ORI $acD.m, #I +// 0000 001r 0110 0000 +// iiii iiii iiii iiii +// Logic OR of accumulator mid part $acD.m with immediate value I. +// +// flags out: --xx xx00 +//void DSPEmitter::ori(const UDSPInstruction opc) +//{ +// u8 reg = (opc >> 8) & 0x1; +// u16 imm = dsp_fetch_code(); +// g_dsp.r[DSP_REG_ACM0 + reg] |= imm; + +// Update_SR_Register16((s16)g_dsp.r[DSP_REG_ACM0 + reg], false, false, isOverS32(dsp_get_long_acc(reg))); +//} + +//---- + +// ADDR $acD.M, $axS.L +// 0100 0ssd xxxx xxxx +// Adds register $axS.L to accumulator $acD.M register. +// +// flags out: x-xx xxxx +void DSPEmitter::addr(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 dreg = (opc >> 8) & 0x1; + u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; + + MOV(64, R(R11), ImmPtr(&g_dsp.r)); +// s64 acc = dsp_get_long_acc(dreg); + get_long_acc(dreg); + PUSH(64, R(RAX)); +// s64 ax = (s16)g_dsp.r[sreg]; + MOVSX(64, 16, RDX, MDisp(R11, sreg * 2)); +// ax <<= 16; + SHL(64, R(RDX), Imm8(16)); +// s64 res = acc + ax; + ADD(64, R(RAX), R(RDX)); +// dsp_set_long_acc(dreg, res); + set_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); + XOR(8, R(RSI), R(RSI)); + POP(64, R(RCX)); + CMP(64, R(RCX), R(RAX)); + + // Carry = (acc>res) + FixupBranch noCarry = J_CC(CC_G); + OR(8, R(RSI), Imm8(1)); + SetJumpTarget(noCarry); + + // Overflow = ((acc ^ res) & (ax ^ res)) < 0 + XOR(64, R(RCX), R(RAX)); + XOR(64, R(RDX), R(RAX)); + AND(64, R(RCX), R(RDX)); + CMP(64, R(RCX), Imm8(0)); + FixupBranch noOverflow = J_CC(CC_L); + OR(8, R(RSI), Imm8(2)); + SetJumpTarget(noOverflow); + + Update_SR_Register64(); +#else + Default(opc); +#endif +} + +// ADDAX $acD, $axS +// 0100 10sd xxxx xxxx +// Adds secondary accumulator $axS to accumulator register $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::addax(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 ax = dsp_get_long_acx(sreg); +// s64 res = acc + ax; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res)); +//} + +// ADD $acD, $ac(1-D) +// 0100 110d xxxx xxxx +// Adds accumulator $ac(1-D) to accumulator register $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::add(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc0 = dsp_get_long_acc(dreg); +// s64 acc1 = dsp_get_long_acc(1 - dreg); +// s64 res = acc0 + acc1; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res)); +//} + +// ADDP $acD +// 0100 111d xxxx xxxx +// Adds product register to accumulator register. +// +// flags out: x-xx xxxx +//void DSPEmitter::addp(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 prod = dsp_get_long_prod(); +// s64 res = acc + prod; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, prod, res)); +//} + +// ADDAXL $acD, $axS.l +// 0111 00sd xxxx xxxx +// Adds secondary accumulator $axS.l to accumulator register $acD. +// should be unsigned values!! +// +// flags out: x-xx xxxx +//void DSPEmitter::addaxl(const UDSPInstruction opc) +//{ +// u8 sreg = (opc >> 9) & 0x1; +// u8 dreg = (opc >> 8) & 0x1; + +// u64 acc = dsp_get_long_acc(dreg); +// u16 acx = (u16)dsp_get_ax_l(sreg); + +// u64 res = acc + acx; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, (s64)res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res)); +//} + +// ADDI $amR, #I +// 0000 001r 0000 0000 +// iiii iiii iiii iiii +// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm. +// +// flags out: x-xx xxxx +//void DSPEmitter::addi(const UDSPInstruction opc) +//{ +// u8 areg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(areg); +// s64 imm = (s16)dsp_fetch_code(); +// imm <<= 16; +// s64 res = acc + imm; + +// dsp_set_long_acc(areg, res); +// res = dsp_get_long_acc(areg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); +//} + +// ADDIS $acD, #I +// 0000 010d iiii iiii +// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm. +// +// flags out: x-xx xxxx +//void DSPEmitter::addis(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 imm = (s8)(u8)opc; +// imm <<= 16; +// s64 res = acc + imm; + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res)); +//} + +// INCM $acsD +// 0111 010d xxxx xxxx +// Increment 24-bit mid-accumulator $acsD. +// +// flags out: x-xx xxxx +//void DSPEmitter::incm(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 sub = 0x10000; +// s64 acc = dsp_get_long_acc(dreg); +// s64 res = acc + sub; + +// zeroWriteBackLog(); +// +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, sub, res)); +//} + +// INC $acD +// 0111 011d xxxx xxxx +// Increment accumulator $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::inc(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 res = acc + 1; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, 1, res)); +//} + +//---- + +// SUBR $acD.M, $axS.L +// 0101 0ssd xxxx xxxx +// Subtracts register $axS.L from accumulator $acD.M register. +// +// flags out: x-xx xxxx +//void DSPEmitter::subr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 ax = (s16)g_dsp.r[sreg]; +// ax <<= 16; +// s64 res = acc - ax; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -ax, res)); +//} + +// SUBAX $acD, $axS +// 0101 10sd xxxx xxxx +// Subtracts secondary accumulator $axS from accumulator register $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::subax(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 acx = dsp_get_long_acx(sreg); +// s64 res = acc - acx; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -acx, res)); +//} + +// SUB $acD, $ac(1-D) +// 0101 110d xxxx xxxx +// Subtracts accumulator $ac(1-D) from accumulator register $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::sub(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc1 = dsp_get_long_acc(dreg); +// s64 acc2 = dsp_get_long_acc(1 - dreg); +// s64 res = acc1 - acc2; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res)); +//} + +// SUBP $acD +// 0101 111d xxxx xxxx +// Subtracts product register from accumulator register. +// +// flags out: x-xx xxxx +//void DSPEmitter::subp(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 prod = dsp_get_long_prod(); +// s64 res = acc - prod; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -prod, res)); +//} + +// DECM $acsD +// 0111 100d xxxx xxxx +// Decrement 24-bit mid-accumulator $acsD. +// +// flags out: x-xx xxxx +//void DSPEmitter::decm(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x01; + +// s64 sub = 0x10000; +// s64 acc = dsp_get_long_acc(dreg); +// s64 res = acc - sub; + +// zeroWriteBackLog(); +// +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -sub, res)); +//} + +// DEC $acD +// 0111 101d xxxx xxxx +// Decrement accumulator $acD. +// +// flags out: x-xx xxxx +//void DSPEmitter::dec(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x01; + +// s64 acc = dsp_get_long_acc(dreg); +// s64 res = acc - 1; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, res); +// res = dsp_get_long_acc(dreg); +// Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -1, res)); +//} + +//---- + +// NEG $acD +// 0111 110d xxxx xxxx +// Negate accumulator $acD. +// +// flags out: --xx xx00 +//void DSPEmitter::neg(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// +// s64 acc = dsp_get_long_acc(dreg); +// acc = 0 - acc; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + +// ABS $acD +// 1010 d001 xxxx xxxx +// absolute value of $acD +// +// flags out: --xx xx00 +//void DSPEmitter::abs(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 11) & 0x1; + +// s64 acc = dsp_get_long_acc(dreg); + +// if (acc < 0) +// acc = 0 - acc; +// +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} +//---- + +// MOVR $acD, $axS.R +// 0110 0srd xxxx xxxx +// Moves register $axS.R (sign extended) to middle accumulator $acD.hm. +// Sets $acD.l to 0. +// TODO: Check what happens to acD.h. +// +// flags out: --xx xx00 +//void DSPEmitter::movr(const UDSPInstruction opc) +//{ +// u8 areg = (opc >> 8) & 0x1; +// u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0; +// +// s64 acc = (s16)g_dsp.r[sreg]; +// acc <<= 16; +// acc &= ~0xffff; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(areg, acc); +// Update_SR_Register64(acc); +//} + +// MOVAX $acD, $axS +// 0110 10sd xxxx xxxx +// Moves secondary accumulator $axS to accumulator $axD. +// +// flags out: --xx xx00 +//void DSPEmitter::movax(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; + +// s64 acx = dsp_get_long_acx(sreg); + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acx); +// Update_SR_Register64(acx); +//} + +// MOV $acD, $ac(1-D) +// 0110 110d xxxx xxxx +// Moves accumulator $ax(1-D) to accumulator $axD. +// +// flags out: --x0 xx00 +//void DSPEmitter::mov(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u64 acc = dsp_get_long_acc(1 - dreg); + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(acc); +//} + +//---- + +// LSL16 $acR +// 1111 000r xxxx xxxx +// Logically shifts left accumulator $acR by 16. +// +// flags out: --xx xx00 +void DSPEmitter::lsl16(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 areg = (opc >> 8) & 0x1; +// s64 acc = dsp_get_long_acc(areg); + get_long_acc(areg); +// acc <<= 16; + SHL(64, R(RAX), Imm8(16)); +// dsp_set_long_acc(areg, acc); + set_long_acc(areg); +// Update_SR_Register64(dsp_get_long_acc(areg)); + Update_SR_Register64(); +#else + Default(opc); +#endif +} + +// LSR16 $acR +// 1111 010r xxxx xxxx +// Logically shifts right accumulator $acR by 16. +// +// flags out: --xx xx00 +//void DSPEmitter::lsr16(const UDSPInstruction opc) +//{ +// u8 areg = (opc >> 8) & 0x1; + +// u64 acc = dsp_get_long_acc(areg); +// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes +// acc >>= 16; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(areg, (s64)acc); +// Update_SR_Register64(dsp_get_long_acc(areg)); +//} + +// ASR16 $acR +// 1001 r001 xxxx xxxx +// Arithmetically shifts right accumulator $acR by 16. +// +// flags out: --xx xx00 +//void DSPEmitter::asr16(const UDSPInstruction opc) +//{ +// u8 areg = (opc >> 11) & 0x1; + +// s64 acc = dsp_get_long_acc(areg); +// acc >>= 16; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(areg, acc); +// Update_SR_Register64(dsp_get_long_acc(areg)); +//} + +// LSL $acR, #I +// 0001 010r 00ii iiii +// Logically shifts left accumulator $acR by number specified by value I. +// +// flags out: --xx xx00 +void DSPEmitter::lsl(const UDSPInstruction opc) +{ +#ifdef _M_X64 + u8 rreg = (opc >> 8) & 0x01; + u16 shift = opc & 0x3f; +// u64 acc = dsp_get_long_acc(rreg); + get_long_acc(rreg); + +// acc <<= shift; + SHL(64, R(RAX), Imm8(shift)); + +// dsp_set_long_acc(rreg, acc); + set_long_acc(rreg); +// Update_SR_Register64(dsp_get_long_acc(rreg)); + Update_SR_Register64(); +#else + Default(opc); +#endif +} + +// LSR $acR, #I +// 0001 010r 01ii iiii +// Logically shifts right accumulator $acR by number specified by value +// calculated by negating sign extended bits 0-6. +// +// flags out: --xx xx00 +//void DSPEmitter::lsr(const UDSPInstruction opc) +//{ +// u8 rreg = (opc >> 8) & 0x01; +// u16 shift; +// u64 acc = dsp_get_long_acc(rreg); +// acc &= 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes + +// if ((opc & 0x3f) == 0) +// shift = 0; +// else +// shift = 0x40 - (opc & 0x3f); + +// acc >>= shift; +// +// dsp_set_long_acc(rreg, (s64)acc); +// Update_SR_Register64(dsp_get_long_acc(rreg)); +//} + +// ASL $acR, #I +// 0001 010r 10ii iiii +// Logically shifts left accumulator $acR by number specified by value I. +// +// flags out: --xx xx00 +//void DSPEmitter::asl(const UDSPInstruction opc) +//{ +// u8 rreg = (opc >> 8) & 0x01; +// u16 shift = opc & 0x3f; +// u64 acc = dsp_get_long_acc(rreg); + +// acc <<= shift; +// +// dsp_set_long_acc(rreg, acc); +// Update_SR_Register64(dsp_get_long_acc(rreg)); +//} + +// ASR $acR, #I +// 0001 010r 11ii iiii +// Arithmetically shifts right accumulator $acR by number specified by +// value calculated by negating sign extended bits 0-6. +// +// flags out: --xx xx00 +//void DSPEmitter::asr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x01; +// u16 shift; + +// if ((opc & 0x3f) == 0) +// shift = 0; +// else +// shift = 0x40 - (opc & 0x3f); + +// // arithmetic shift +// s64 acc = dsp_get_long_acc(dreg); +// acc >>= shift; + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + +// LSRN (fixed parameters) +// 0000 0010 1100 1010 +// Logically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M +// (if value negative, becomes left shift). +// +// flags out: --xx xx00 +//void DSPEmitter::lsrn(const UDSPInstruction opc) +//{ +// s16 shift; +// u16 accm = (u16)dsp_get_acc_m(1); +// u64 acc = dsp_get_long_acc(0); +// acc &= 0x000000FFFFFFFFFFULL; + +// if ((accm & 0x3f) == 0) +// shift = 0; +// else if (accm & 0x40) +// shift = -0x40 + (accm & 0x3f); +// else +// shift = accm & 0x3f; + +// if (shift > 0) { +// acc >>= shift; +// } else if (shift < 0) { +// acc <<= -shift; +// } + +// dsp_set_long_acc(0, (s64)acc); +// Update_SR_Register64(dsp_get_long_acc(0)); +//} + +// ASRN (fixed parameters) +// 0000 0010 1100 1011 +// Arithmetically shifts right accumulator $ACC0 by lower 7-bit (signed) value in $AC1.M +// (if value negative, becomes left shift). +// +// flags out: --xx xx00 +//void DSPEmitter::asrn(const UDSPInstruction opc) +//{ +// s16 shift; +// u16 accm = (u16)dsp_get_acc_m(1); +// s64 acc = dsp_get_long_acc(0); + +// if ((accm & 0x3f) == 0) +// shift = 0; +// else if (accm & 0x40) +// shift = -0x40 + (accm & 0x3f); +// else +// shift = accm & 0x3f; + +// if (shift > 0) { +// acc >>= shift; +// } else if (shift < 0) { +// acc <<= -shift; +// } + +// dsp_set_long_acc(0, acc); +// Update_SR_Register64(dsp_get_long_acc(0)); +//} + +// LSRNRX $acD, $axS.h +// 0011 01sd 1xxx xxxx +// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::lsrnrx(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; + +// s16 shift; +// u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg]; +// u64 acc = dsp_get_long_acc(dreg); +// acc &= 0x000000FFFFFFFFFFULL; + +// if ((axh & 0x3f) == 0) +// shift = 0; +// else if (axh & 0x40) +// shift = -0x40 + (axh & 0x3f); +// else +// shift = axh & 0x3f; + +// if (shift > 0) { +// acc <<= shift; +// } else if (shift < 0) { +// acc >>= -shift; +// } + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, (s64)acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + +// ASRNRX $acD, $axS.h +// 0011 10sd 1xxx xxxx +// Arithmetically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AX[S].H +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::asrnrx(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; +// u8 sreg = (opc >> 9) & 0x1; + +// s16 shift; +// u16 axh = g_dsp.r[DSP_REG_AXH0 + sreg]; +// s64 acc = dsp_get_long_acc(dreg); + +// if ((axh & 0x3f) == 0) +// shift = 0; +// else if (axh & 0x40) +// shift = -0x40 + (axh & 0x3f); +// else +// shift = axh & 0x3f; + +// if (shift > 0) { +// acc <<= shift; +// } else if (shift < 0) { +// acc >>= -shift; +// } + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + +// LSRNR $acD +// 0011 110d 1xxx xxxx +// Logically shifts left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::lsrnr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s16 shift; +// u16 accm = (u16)dsp_get_acc_m(1 - dreg); +// u64 acc = dsp_get_long_acc(dreg); +// acc &= 0x000000FFFFFFFFFFULL; + +// if ((accm & 0x3f) == 0) +// shift = 0; +// else if (accm & 0x40) +// shift = -0x40 + (accm & 0x3f); +// else +// shift = accm & 0x3f; + +// if (shift > 0) +// acc <<= shift; +// else if (shift < 0) +// acc >>= -shift; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, (s64)acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + +// ASRNR $acD +// 0011 111d 1xxx xxxx +// Arithmeticaly shift left/right accumulator $ACC[D] by lower 7-bit (signed) value in $AC[1-D].M +// x = extension (7 bits!!) +// +// flags out: --xx xx00 +//void DSPEmitter::asrnr(const UDSPInstruction opc) +//{ +// u8 dreg = (opc >> 8) & 0x1; + +// s16 shift; +// u16 accm = (u16)dsp_get_acc_m(1 - dreg); +// s64 acc = dsp_get_long_acc(dreg); + +// if ((accm & 0x3f) == 0) +// shift = 0; +// else if (accm & 0x40) +// shift = -0x40 + (accm & 0x3f); +// else +// shift = accm & 0x3f; + +// if (shift > 0) +// acc <<= shift; +// else if (shift < 0) +// acc >>= -shift; + +// zeroWriteBackLog(); + +// dsp_set_long_acc(dreg, acc); +// Update_SR_Register64(dsp_get_long_acc(dreg)); +//} + + +//} // namespace + +// diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp index 04769bfef3..77afef2566 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitBranch.cpp @@ -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); +} diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp index c98c5c067c..a488cd2a1d 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitLoadStore.cpp @@ -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
-//
\ No newline at end of file +// 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 +// diff --git a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp index 3d0cb8d38f..08b3ea5062 100644 --- a/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp +++ b/Source/Core/DSPCore/Src/Jit/DSPJitUtil.cpp @@ -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); } } |
