diff --git a/Source/Core/Core/Src/HW/Sram.cpp b/Source/Core/Core/Src/HW/Sram.cpp index bdabecb00f..515b343b64 100644 --- a/Source/Core/Core/Src/HW/Sram.cpp +++ b/Source/Core/Core/Src/HW/Sram.cpp @@ -1,100 +1,100 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Sram.h" -#include "../ConfigManager.h" -// english -SRAM sram_dump = {{ - 0x04, 0x6B, - 0xFB, 0x91, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0x40, - 0x05, - 0x00, - 0x00, - 0x2C, - 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41, - 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, - 0x00, - 0x6E, 0x6D, - 0x00, 0x00, - 0x00, 0x00 -}}; - -// german -SRAM sram_dump_german = {{ - 0x1F, 0x66, - 0xE0, 0x96, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x04, 0xEA, 0x19, 0x40, - 0x00, - 0x00, - 0x01, - 0x3C, - 0x12, 0xD5, 0xEA, 0xD3, 0x00, 0xFA, 0x2D, 0x33, 0x13, 0x41, 0x26, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - 0x00, - 0x00, - 0x84, 0xFF, - 0x00, 0x00, - 0x00, 0x00 -}}; - -void initSRAM() -{ - FILE *file = fopen(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strSRAM.c_str(), "rb"); - if (file != NULL) - { - if (fread(&g_SRAM, 1, 64, file) < 64) { - ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: Could not read all of SRAM"); - g_SRAM = sram_dump; - } - fclose(file); - } - else - { - g_SRAM = sram_dump; - } -} - -void SetCardFlashID(u8* buffer, u8 card_index) -{ - u64 rand = Common::swap64( *(u64*)&(buffer[12])); - u8 csum=0; - for(int i = 0; i < 12; i++) - { - rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); - csum += g_SRAM.flash_id[card_index][i] = buffer[i] - ((u8)rand&0xff); - rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); - rand &= (u64)0x0000000000007fffULL; - } - g_SRAM.flashID_chksum[card_index] = csum^0xFF; -} - +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Sram.h" +#include "../ConfigManager.h" +// english +SRAM sram_dump = {{ + 0x04, 0x6B, + 0xFB, 0x91, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x40, + 0x05, + 0x00, + 0x00, + 0x2C, + 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x41, + 0x44, 0x4F, 0x4C, 0x50, 0x48, 0x49, 0x4E, 0x53, 0x4C, 0x4F, 0x54, 0x42, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, + 0x00, + 0x6E, 0x6D, + 0x00, 0x00, + 0x00, 0x00 +}}; + +// german +SRAM sram_dump_german = {{ + 0x1F, 0x66, + 0xE0, 0x96, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x04, 0xEA, 0x19, 0x40, + 0x00, + 0x00, + 0x01, + 0x3C, + 0x12, 0xD5, 0xEA, 0xD3, 0x00, 0xFA, 0x2D, 0x33, 0x13, 0x41, 0x26, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, + 0x00, + 0x84, 0xFF, + 0x00, 0x00, + 0x00, 0x00 +}}; + +void initSRAM() +{ + FILE *file = fopen(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strSRAM.c_str(), "rb"); + if (file != NULL) + { + if (fread(&g_SRAM, 1, 64, file) < 64) { + ERROR_LOG(EXPANSIONINTERFACE, "EXI IPL-DEV: Could not read all of SRAM"); + g_SRAM = sram_dump; + } + fclose(file); + } + else + { + g_SRAM = sram_dump; + } +} + +void SetCardFlashID(u8* buffer, u8 card_index) +{ + u64 rand = Common::swap64( *(u64*)&(buffer[12])); + u8 csum=0; + for(int i = 0; i < 12; i++) + { + rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); + csum += g_SRAM.flash_id[card_index][i] = buffer[i] - ((u8)rand&0xff); + rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16); + rand &= (u64)0x0000000000007fffULL; + } + g_SRAM.flashID_chksum[card_index] = csum^0xFF; +} + 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 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(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(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(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(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 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(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(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(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(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); } } diff --git a/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp b/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp index cb0bb04866..9fef8e68a9 100644 --- a/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/OpenCL/OCLTextureDecoder.cpp @@ -98,7 +98,6 @@ void TexDecoder_OpenCL_Initialize() char *header = NULL; size_t nDevices = 0; cl_device_id *devices = NULL; - cl_program program = NULL; size_t *binary_sizes = NULL; char **binaries = NULL; char filename[1024];