mirror of https://github.com/PCSX2/pcsx2.git
676 lines
15 KiB
C++
676 lines
15 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 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 for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#include "PrecompiledHeader.h"
|
|
|
|
#include "Common.h"
|
|
#include "R5900OpcodeTables.h"
|
|
#include "iR5900.h"
|
|
|
|
using namespace x86Emitter;
|
|
|
|
namespace R5900 {
|
|
namespace Dynarec {
|
|
namespace OpcodeImpl
|
|
{
|
|
|
|
/*********************************************************
|
|
* Register arithmetic *
|
|
* Format: OP rd, rs, rt *
|
|
*********************************************************/
|
|
|
|
// TODO: overflow checks
|
|
|
|
#ifndef ARITHMETIC_RECOMPILE
|
|
|
|
namespace Interp = R5900::Interpreter::OpcodeImpl;
|
|
|
|
REC_FUNC_DEL(ADD, _Rd_);
|
|
REC_FUNC_DEL(ADDU, _Rd_);
|
|
REC_FUNC_DEL(DADD, _Rd_);
|
|
REC_FUNC_DEL(DADDU, _Rd_);
|
|
REC_FUNC_DEL(SUB, _Rd_);
|
|
REC_FUNC_DEL(SUBU, _Rd_);
|
|
REC_FUNC_DEL(DSUB, _Rd_);
|
|
REC_FUNC_DEL(DSUBU, _Rd_);
|
|
REC_FUNC_DEL(AND, _Rd_);
|
|
REC_FUNC_DEL(OR, _Rd_);
|
|
REC_FUNC_DEL(XOR, _Rd_);
|
|
REC_FUNC_DEL(NOR, _Rd_);
|
|
REC_FUNC_DEL(SLT, _Rd_);
|
|
REC_FUNC_DEL(SLTU, _Rd_);
|
|
|
|
#else
|
|
|
|
//// ADD
|
|
void recADD_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].SD[0] = g_cpuConstRegs[_Rs_].SL[0] + g_cpuConstRegs[_Rt_].SL[0];
|
|
}
|
|
|
|
void recADD_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
s32 cval = g_cpuConstRegs[creg].SL[0];
|
|
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].SL[0]]);
|
|
if (cval)
|
|
xADD(eax, cval);
|
|
eeSignExtendTo(_Rd_, _Rd_ == vreg && !cval);
|
|
}
|
|
|
|
// s is constant
|
|
void recADD_consts(int info)
|
|
{
|
|
recADD_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
// t is constant
|
|
void recADD_constt(int info)
|
|
{
|
|
recADD_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
// nothing is constant
|
|
void recADD_(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rs_].SL[0]]);
|
|
if (_Rs_ == _Rt_)
|
|
xADD(eax, eax);
|
|
else
|
|
xADD(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
eeSignExtendTo(_Rd_);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(ADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT);
|
|
|
|
//// ADDU
|
|
void recADDU(void)
|
|
{
|
|
recADD();
|
|
}
|
|
|
|
//// DADD
|
|
void recDADD_const(void)
|
|
{
|
|
g_cpuConstRegs[_Rd_].SD[0] = g_cpuConstRegs[_Rs_].SD[0] + g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
void recDADD_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[creg];
|
|
|
|
if (_Rd_ == vreg) {
|
|
if (!cval.SD[0])
|
|
return; // no-op
|
|
xADD(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], cval.SL[0]);
|
|
xADC(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], cval.SL[1]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].SL[0]]);
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[vreg].SL[1]]);
|
|
if (cval.SD[0]) {
|
|
xADD(eax, cval.SL[0]);
|
|
xADC(edx, cval.SL[1]);
|
|
}
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
}
|
|
}
|
|
|
|
void recDADD_consts(int info)
|
|
{
|
|
recDADD_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recDADD_constt(int info)
|
|
{
|
|
recDADD_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recDADD_(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
u32 rs = _Rs_, rt = _Rt_;
|
|
if (_Rd_ == _Rt_)
|
|
rs = _Rt_, rt = _Rs_;
|
|
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rt].SL[0]]);
|
|
|
|
if (_Rd_ == _Rs_ && _Rs_ == _Rt_) {
|
|
xSHLD(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], eax, 1);
|
|
xSHL(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], 1);
|
|
return;
|
|
}
|
|
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[rt].SL[1]]);
|
|
|
|
if (_Rd_ == rs) {
|
|
xADD(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xADC(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
return;
|
|
} else if (rs == rt) {
|
|
xADD(eax, eax);
|
|
xADC(edx, edx);
|
|
} else {
|
|
xADD(eax, ptr32[&cpuRegs.GPR.r[rs].SL[0]]);
|
|
xADC(edx, ptr32[&cpuRegs.GPR.r[rs].SL[1]]);
|
|
}
|
|
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(DADD, XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT);
|
|
|
|
//// DADDU
|
|
void recDADDU(void)
|
|
{
|
|
recDADD();
|
|
}
|
|
|
|
//// SUB
|
|
|
|
void recSUB_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].SD[0] = g_cpuConstRegs[_Rs_].SL[0] - g_cpuConstRegs[_Rt_].SL[0];
|
|
}
|
|
|
|
void recSUB_consts(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
s32 sval = g_cpuConstRegs[_Rs_].SL[0];
|
|
|
|
xMOV(eax, sval);
|
|
xSUB(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
eeSignExtendTo(_Rd_);
|
|
}
|
|
|
|
void recSUB_constt(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
s32 tval = g_cpuConstRegs[_Rt_].SL[0];
|
|
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rs_].SL[0]]);
|
|
if (tval)
|
|
xSUB(eax, tval);
|
|
eeSignExtendTo(_Rd_, _Rd_ == _Rs_ && !tval);
|
|
}
|
|
|
|
void recSUB_(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if (_Rs_ == _Rt_) {
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], 0);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], 0);
|
|
return;
|
|
}
|
|
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rs_].SL[0]]);
|
|
xSUB(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
eeSignExtendTo(_Rd_);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// SUBU
|
|
void recSUBU(void)
|
|
{
|
|
recSUB();
|
|
}
|
|
|
|
//// DSUB
|
|
void recDSUB_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].SD[0] = g_cpuConstRegs[_Rs_].SD[0] - g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
void recDSUB_consts(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 sval = g_cpuConstRegs[_Rs_];
|
|
|
|
if (!sval.SD[0] && _Rd_ == _Rt_) {
|
|
/* To understand this 64-bit negate, consider that a negate in 2's complement
|
|
* is a NOT then an ADD 1. The upper word should only have the NOT stage unless
|
|
* the ADD overflows. The ADD only overflows if the lower word is 0.
|
|
* Incrementing before a NEG is the same as a NOT and the carry flag is set for
|
|
* a non-zero lower word.
|
|
*/
|
|
xNEG(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]]);
|
|
xADC(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], 0);
|
|
xNEG(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]]);
|
|
return;
|
|
} else {
|
|
xMOV(eax, sval.SL[0]);
|
|
xMOV(edx, sval.SL[1]);
|
|
}
|
|
|
|
xSUB(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
xSBB(edx, ptr32[&cpuRegs.GPR.r[_Rt_].SL[1]]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
}
|
|
|
|
void recDSUB_constt(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 tval = g_cpuConstRegs[_Rt_];
|
|
|
|
if (_Rd_ == _Rs_) {
|
|
xSUB(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], tval.SL[0]);
|
|
xSBB(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], tval.SL[1]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rs_].SL[0]]);
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[_Rs_].SL[1]]);
|
|
if (tval.SD[0]) {
|
|
xSUB(eax, tval.SL[0]);
|
|
xSBB(edx, tval.SL[1]);
|
|
}
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
}
|
|
}
|
|
|
|
void recDSUB_(int info)
|
|
{
|
|
pxAssert( !(info&PROCESS_EE_XMM) );
|
|
|
|
if (_Rs_ == _Rt_) {
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], 0);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], 0);
|
|
} else if (_Rd_ == _Rs_) {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[_Rt_].SL[1]]);
|
|
xSUB(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xSBB(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rs_].SL[0]]);
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[_Rs_].SL[1]]);
|
|
xSUB(eax, ptr32[&cpuRegs.GPR.r[_Rt_].SL[0]]);
|
|
xSBB(edx, ptr32[&cpuRegs.GPR.r[_Rt_].SL[1]]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].SL[1]], edx);
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(DSUB, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// DSUBU
|
|
void recDSUBU(void)
|
|
{
|
|
recDSUB();
|
|
}
|
|
|
|
//// AND
|
|
void recAND_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] & g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recAND_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[creg];
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (!cval.UL[i]) {
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], 0);
|
|
} else if (_Rd_ == vreg) {
|
|
if (cval.SL[i] != -1)
|
|
xAND(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], cval.UL[i]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].UL[i]]);
|
|
if (cval.SL[i] != -1)
|
|
xAND(eax, cval.UL[i]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recAND_consts(int info)
|
|
{
|
|
recAND_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recAND_constt(int info)
|
|
{
|
|
recAND_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recAND_(int info)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
u32 rs = _Rs_, rt = _Rt_;
|
|
if (_Rd_ == _Rt_)
|
|
rs = _Rt_, rt = _Rs_;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_Rd_ == rs) {
|
|
if (rs == rt)
|
|
continue;
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xAND(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rs].UL[i]]);
|
|
if (rs != rt)
|
|
xAND(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(AND, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// OR
|
|
void recOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recOR_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[creg];
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (cval.SL[i] == -1) {
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], -1);
|
|
} else if (_Rd_ == vreg) {
|
|
if (cval.UL[i])
|
|
xOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], cval.UL[i]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].UL[i]]);
|
|
if (cval.UL[i])
|
|
xOR(eax, cval.UL[i]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recOR_consts(int info)
|
|
{
|
|
recOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recOR_constt(int info)
|
|
{
|
|
recOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recOR_(int info)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
u32 rs = _Rs_, rt = _Rt_;
|
|
if (_Rd_ == _Rt_)
|
|
rs = _Rt_, rt = _Rs_;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_Rd_ == rs) {
|
|
if (rs == rt)
|
|
continue;
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rs].UL[i]]);
|
|
if (rs != rt)
|
|
xOR(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(OR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// XOR
|
|
void recXOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] ^ g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recXOR_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[creg];
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_Rd_ == vreg) {
|
|
if (cval.UL[i])
|
|
xXOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], cval.UL[i]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].UL[i]]);
|
|
if (cval.UL[i])
|
|
xXOR(eax, cval.UL[i]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recXOR_consts(int info)
|
|
{
|
|
recXOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recXOR_constt(int info)
|
|
{
|
|
recXOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recXOR_(int info)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
u32 rs = _Rs_, rt = _Rt_;
|
|
if (_Rd_ == _Rt_)
|
|
rs = _Rt_, rt = _Rs_;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (rs == rt) {
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], 0);
|
|
} else if (_Rd_ == rs) {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xXOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rs].UL[i]]);
|
|
xXOR(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(XOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// NOR
|
|
void recNOR_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] =~(g_cpuConstRegs[_Rs_].UD[0] | g_cpuConstRegs[_Rt_].UD[0]);
|
|
}
|
|
|
|
void recNOR_constv(int info, int creg, u32 vreg)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[creg];
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_Rd_ == vreg) {
|
|
if (cval.UL[i])
|
|
xOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], cval.UL[i]);
|
|
xNOT(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[vreg].UL[i]]);
|
|
if (cval.UL[i])
|
|
xOR(eax, cval.UL[i]);
|
|
xNOT(eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
void recNOR_consts(int info)
|
|
{
|
|
recNOR_constv(info, _Rs_, _Rt_);
|
|
}
|
|
|
|
void recNOR_constt(int info)
|
|
{
|
|
recNOR_constv(info, _Rt_, _Rs_);
|
|
}
|
|
|
|
void recNOR_(int info)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
u32 rs = _Rs_, rt = _Rt_;
|
|
if (_Rd_ == _Rt_)
|
|
rs = _Rt_, rt = _Rs_;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_Rd_ == rs) {
|
|
if (rs == rt) {
|
|
xNOT(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]]);
|
|
continue;
|
|
}
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xOR(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
xNOT(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]]);
|
|
} else {
|
|
xMOV(eax, ptr32[&cpuRegs.GPR.r[rs].UL[i]]);
|
|
if (rs != rt)
|
|
xOR(eax, ptr32[&cpuRegs.GPR.r[rt].UL[i]]);
|
|
xNOT(eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[i]], eax);
|
|
}
|
|
}
|
|
}
|
|
|
|
EERECOMPILE_CODE0(NOR, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
//// SLT - test with silent hill, lemans
|
|
void recSLT_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].SD[0] < g_cpuConstRegs[_Rt_].SD[0];
|
|
}
|
|
|
|
void recSLTs_const(int info, int sign, int st)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
GPR_reg64 cval = g_cpuConstRegs[st ? _Rt_ : _Rs_];
|
|
|
|
xMOV(eax, 1);
|
|
|
|
xCMP(ptr32[&cpuRegs.GPR.r[st ? _Rs_ : _Rt_].UL[1]], cval.UL[1]);
|
|
xForwardJump8 pass1(st ? (sign ? Jcc_Less : Jcc_Below) : (sign ? Jcc_Greater : Jcc_Above));
|
|
xForwardJump8 fail(st ? (sign ? Jcc_Greater : Jcc_Above) : (sign ? Jcc_Less : Jcc_Below));
|
|
{
|
|
xCMP(ptr32[&cpuRegs.GPR.r[st ? _Rs_ : _Rt_].UL[0]], cval.UL[0]);
|
|
xForwardJump8 pass2(st ? Jcc_Below : Jcc_Above);
|
|
|
|
fail.SetTarget();
|
|
xMOV(eax, 0);
|
|
pass2.SetTarget();
|
|
}
|
|
pass1.SetTarget();
|
|
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[1]], 0);
|
|
}
|
|
|
|
void recSLTs_(int info, int sign)
|
|
{
|
|
pxAssert( !(info & PROCESS_EE_XMM) );
|
|
|
|
xMOV(eax, 1);
|
|
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[_Rs_].UL[1]]);
|
|
xCMP(edx, ptr32[&cpuRegs.GPR.r[_Rt_].UL[1]]);
|
|
xForwardJump8 pass1(sign ? Jcc_Less : Jcc_Below);
|
|
xForwardJump8 fail(sign ? Jcc_Greater : Jcc_Above);
|
|
{
|
|
xMOV(edx, ptr32[&cpuRegs.GPR.r[_Rs_].UL[0]]);
|
|
xCMP(edx, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]);
|
|
xForwardJump8 pass2(Jcc_Below);
|
|
|
|
fail.SetTarget();
|
|
xMOV(eax, 0);
|
|
pass2.SetTarget();
|
|
}
|
|
pass1.SetTarget();
|
|
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[0]], eax);
|
|
xMOV(ptr32[&cpuRegs.GPR.r[_Rd_].UL[1]], 0);
|
|
}
|
|
|
|
void recSLT_consts(int info)
|
|
{
|
|
recSLTs_const(info, 1, 0);
|
|
}
|
|
|
|
void recSLT_constt(int info)
|
|
{
|
|
recSLTs_const(info, 1, 1);
|
|
}
|
|
|
|
void recSLT_(int info)
|
|
{
|
|
recSLTs_(info, 1);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SLT, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
// SLTU - test with silent hill, lemans
|
|
void recSLTU_const()
|
|
{
|
|
g_cpuConstRegs[_Rd_].UD[0] = g_cpuConstRegs[_Rs_].UD[0] < g_cpuConstRegs[_Rt_].UD[0];
|
|
}
|
|
|
|
void recSLTU_consts(int info)
|
|
{
|
|
recSLTs_const(info, 0, 0);
|
|
}
|
|
|
|
void recSLTU_constt(int info)
|
|
{
|
|
recSLTs_const(info, 0, 1);
|
|
}
|
|
|
|
void recSLTU_(int info)
|
|
{
|
|
recSLTs_(info, 0);
|
|
}
|
|
|
|
EERECOMPILE_CODE0(SLTU, XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED);
|
|
|
|
#endif
|
|
|
|
} } }
|