Android project - Add mVU_SSE4 structure to VUDef.h header

This commit is contained in:
k2154
2025-08-16 08:02:11 +09:00
parent f5a2533be3
commit 990404c7c4
9 changed files with 226 additions and 147 deletions
+4
View File
@@ -58,6 +58,10 @@ uptr g_argPtrs[kMaxArgs];
void cpuReset()
{
//// cpuRegistersPack -> VIFregisters
g_cpuRegistersPack.vifRegs[0] = vif0Regs;
g_cpuRegistersPack.vifRegs[1] = vif1Regs;
////
std::memset(&cpuRegs, 0, sizeof(cpuRegs));
std::memset(&fpuRegs, 0, sizeof(fpuRegs));
std::memset(&tlb, 0, sizeof(tlb));
+72
View File
@@ -208,4 +208,76 @@ struct mVU_Globals
#undef __four
};
#define SINGLE(sign, exp, mant) (((u32)(sign) << 31) | ((u32)(exp) << 23) | (u32)(mant))
#define DOUBLE(sign, exp, mant) (((sign##ULL) << 63) | ((exp##ULL) << 52) | (mant##ULL))
struct FPUd_Globals
{
u32 neg[4], pos[4];
u32 pos_inf[4], neg_inf[4],
one_exp[4];
u64 dbl_one_exp[2];
u64 dbl_cvt_overflow, // needs special code if above or equal
dbl_ps2_overflow, // overflow & clamp if above or equal
dbl_underflow; // underflow if below
u64 padding;
u64 dbl_s_pos[2];
//u64 dlb_s_neg[2];
};
struct mVU_SSE4
{
u32 sse4_minvals[2][4] = {
{0xff7fffff, 0xffffffff, 0xffffffff, 0xffffffff}, //1000
{0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}, //1111
};
u32 sse4_maxvals[2][4] = {
{0x7f7fffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1000
{0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
};
////
u32 sse4_compvals[2][4] = {
{0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
{0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1111
};
////
u32 s_neg[4] = {0x80000000, 0xffffffff, 0xffffffff, 0xffffffff};
u32 s_pos[4] = {0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff};
////
u32 g_minvals[4] = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff};
u32 g_maxvals[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff};
////
FPUd_Globals s_const =
{
{0x80000000, 0xffffffff, 0xffffffff, 0xffffffff},
{0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff},
{SINGLE(0, 0xff, 0), 0, 0, 0},
{SINGLE(1, 0xff, 0), 0, 0, 0},
{SINGLE(0, 1, 0), 0, 0, 0},
{DOUBLE(0, 1, 0), 0},
DOUBLE(0, 1151, 0), // cvt_overflow
DOUBLE(0, 1152, 0), // ps2_overflow
DOUBLE(0, 897, 0), // underflow
0, // Padding!!
{0x7fffffffffffffffULL, 0},
//{0x8000000000000000ULL, 0},
};
////
u32 minmax_mask[8] =
{
0xffffffff, 0x80000000, 0, 0,
0, 0x40000000, 0, 0,
};
};
#endif //PCSX2_VUDEF_H
@@ -15,6 +15,8 @@ struct cpuRegistersPack
alignas(16) fpuRegisters fpuRegs{};
alignas(16) psxRegisters psxRegs{};
alignas(16) VURegs vuRegs[2];
alignas(16) VIFregisters vifRegs[2];
alignas(16) mVU_SSE4 mVUss4;
alignas(32) mVU_Globals mVUglob;
};
alignas(32) extern cpuRegistersPack g_cpuRegistersPack;
@@ -24,6 +26,7 @@ static fpuRegisters& fpuRegs = g_cpuRegistersPack.fpuRegs;
static psxRegisters& psxRegs = g_cpuRegistersPack.psxRegs;
static VURegs& VU0 = g_cpuRegistersPack.vuRegs[0];
static VURegs& VU1 = g_cpuRegistersPack.vuRegs[1];
static mVU_SSE4& mVUClamp = g_cpuRegistersPack.mVUss4;
static mVU_Globals& mVUglob = g_cpuRegistersPack.mVUglob;
#endif //PCSX2_CPUREGISTERSPACK_H
+36 -36
View File
@@ -10,8 +10,8 @@
using namespace x86Emitter;
#endif
alignas(16) const u32 g_minvals[4] = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff};
alignas(16) const u32 g_maxvals[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff};
//alignas(16) const u32 g_minvals[4] = {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff};
//alignas(16) const u32 g_maxvals[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff};
//------------------------------------------------------------------
namespace R5900 {
@@ -67,8 +67,8 @@ namespace DOUBLE
// Add/Sub opcodes produce the same results as the ps2
#define FPU_CORRECT_ADD_SUB 1
alignas(16) static const u32 s_neg[4] = {0x80000000, 0xffffffff, 0xffffffff, 0xffffffff};
alignas(16) static const u32 s_pos[4] = {0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff};
//alignas(16) static const u32 s_neg[4] = {0x80000000, 0xffffffff, 0xffffffff, 0xffffffff};
//alignas(16) static const u32 s_pos[4] = {0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff};
#define REC_FPUBRANCH(f) \
void f(); \
@@ -382,9 +382,9 @@ __fi void fpuFloat3(int regd) // +NaN -> +fMax, -NaN -> -fMax, +Inf -> +fMax, -I
auto regQ = a64::QRegister(regd);
// xPMIN.SD(xRegisterSSE(regd), ptr128[&g_maxvals[0]]);
armAsm->Smin(regQ.V4S(), regQ.V4S(), armLoadPtrV(&g_maxvals[0]).V4S());
armAsm->Smin(regQ.V4S(), regQ.V4S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).V4S());
// xPMIN.UD(xRegisterSSE(regd), ptr128[&g_minvals[0]]);
armAsm->Umin(regQ.V4S(), regQ.V4S(), armLoadPtrV(&g_minvals[0]).V4S());
armAsm->Umin(regQ.V4S(), regQ.V4S(), armLoadPtrV(PTR_CPU(mVUss4.g_minvals[0])).V4S());
}
__fi void fpuFloat(int regd) // +/-NaN -> +fMax, +Inf -> +fMax, -Inf -> -fMax
@@ -394,9 +394,9 @@ __fi void fpuFloat(int regd) // +/-NaN -> +fMax, +Inf -> +fMax, -Inf -> -fMax
auto regQ = a64::QRegister(regd);
// xMIN.SS(xRegisterSSE(regd), ptr[&g_maxvals[0]]); // MIN() must be before MAX()! So that NaN's become +Maximum
armAsm->Fminnm(regQ.S(), regQ.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regQ.S(), regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
// xMAX.SS(xRegisterSSE(regd), ptr[&g_minvals[0]]);
armAsm->Fmaxnm(regQ.S(), regQ.S(), armLoadPtrV(&g_minvals[0]).S());
armAsm->Fmaxnm(regQ.S(), regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.g_minvals[0])).S());
}
}
@@ -434,12 +434,12 @@ void recABS_S_xmm(int info)
}
// xAND.PS(xRegisterSSE(EEREC_D), ptr[&s_pos[0]]);
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(&s_pos[0]).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_pos[0])).V16B());
//xAND(ptr32[&fpuRegs.fprc[31]], ~(FPUflagO|FPUflagU)); // Clear O and U flags
if (CHECK_FPU_OVERFLOW) { // Only need to do positive clamp, since EEREC_D is positive
// xMIN.SS(xRegisterSSE(EEREC_D), ptr[&g_maxvals[0]]);
armAsm->Fminnm(regED.S(), regED.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regED.S(), regED.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
}
}
@@ -529,7 +529,7 @@ void FPU_ADD_SUB(int regd, int regt, int issub)
// xMOVAPS(xRegisterSSE(xmmtemp), xRegisterSSE(regt));
armAsm->Mov(regQTemp, regT);
// xAND.PS(xRegisterSSE(xmmtemp), ptr[s_neg]);
armAsm->And(regQTemp.V16B(), regQTemp.V16B(), armLoadPtrV(s_neg).V16B());
armAsm->And(regQTemp.V16B(), regQTemp.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_neg)).V16B());
if (issub) {
// xSUB.SS(xRegisterSSE(regd), xRegisterSSE(xmmtemp));
armAsm->Fsub(regD.S(), regD.S(), regQTemp.S());
@@ -569,7 +569,7 @@ void FPU_ADD_SUB(int regd, int regt, int issub)
armBind(&j8Ptr3);
//diff = -255 .. -25, expd < expt
// xAND.PS(xRegisterSSE(regd), ptr[s_neg]);
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(s_neg).V16B());
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_neg)).V16B());
if (issub) {
// xSUB.SS(xRegisterSSE(regd), xRegisterSSE(regt));
armAsm->Fsub(regD.S(), regD.S(), regT.S());
@@ -1340,9 +1340,9 @@ void recDIVhelper1(int regd, int regt) // Sets flags
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regt == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// ajmp32 = JZ32(0); //Skip if not set
armAsm->B(&ajmp32, a64::Condition::eq);
armAsm->Cbz(EAX, &ajmp32);
/*--- Check for 0/0 ---*/
// xXOR.PS(xRegisterSSE(t1reg), xRegisterSSE(t1reg));
@@ -1352,9 +1352,9 @@ void recDIVhelper1(int regd, int regt) // Sets flags
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regd == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp1 = JZ8(0); //Skip if not set
armAsm->B(&pjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp1);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags ( 0/0 )
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// pjmp2 = JMP8(0);
@@ -1370,9 +1370,9 @@ void recDIVhelper1(int regd, int regt) // Sets flags
// xXOR.PS(xRegisterSSE(regd), xRegisterSSE(regt)); // Make regd Positive or Negative
armAsm->Eor(regD.V16B(), regD.V16B(), regT.V16B());
// xAND.PS(xRegisterSSE(regd), ptr[&s_neg[0]]); // Get the sign bit
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(&s_neg[0]).V16B());
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_neg[0])).V16B());
// xOR.PS(xRegisterSSE(regd), ptr[&g_maxvals[0]]); // regd = +/- Maximum
armAsm->Orr(regD.V16B(), regD.V16B(), armLoadPtrV(&g_maxvals[0]).V16B());
armAsm->Orr(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).V16B());
//xMOVSSZX(xRegisterSSE(regd), ptr[&g_maxvals[0]]);
// bjmp32 = JMP32(0);
armAsm->B(&bjmp32);
@@ -2087,7 +2087,7 @@ void recNEG_S_xmm(int info)
//xAND(ptr32[&fpuRegs.fprc[31]], ~(FPUflagO|FPUflagU)); // Clear O and U flags
// xXOR.PS(xRegisterSSE(EEREC_D), ptr[&s_neg[0]]);
armAsm->Eor(regED.V16B(), regED.V16B(), armLoadPtrV(&s_neg[0]).V16B());
armAsm->Eor(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_neg[0])).V16B());
// Always preserve sign. Using float clamping here would result in
// +inf to become +fMax instead of -fMax, which is definitely wrong.
@@ -2235,25 +2235,25 @@ void recSQRT_S_xmm(int info)
// xMOVMSKPS(eax, xRegisterSSE(EEREC_D));
armMOVMSKPS(EAX, regED);
// xAND(eax, 1); //Check sign
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// u8* pjmp = JZ8(0); //Skip if none are
a64::Label pjmp;
armAsm->B(&pjmp, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// xAND.PS(xRegisterSSE(EEREC_D), ptr[&s_pos[0]]); // Make EEREC_D Positive
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(&s_pos[0]).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_pos[0])).V16B());
// x86SetJ8(pjmp);
armBind(&pjmp);
}
else {
// xAND.PS(xRegisterSSE(EEREC_D), ptr[&s_pos[0]]); // Make EEREC_D Positive
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(&s_pos[0]).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_pos[0])).V16B());
}
if (CHECK_FPU_OVERFLOW) { // Only need to do positive clamp, since EEREC_D is positive
// xMIN.SS(xRegisterSSE(EEREC_D), ptr[&g_maxvals[0]]);
armAsm->Fminnm(regED.S(), regED.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regED.S(), regED.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
}
// xSQRT.SS(xRegisterSSE(EEREC_D), xRegisterSSE(EEREC_D));
armAsm->Fsqrt(regED.S(), regED.S());
@@ -2294,13 +2294,13 @@ void recRSQRThelper1(int regd, int t0reg) // Preforms the RSQRT function when re
// xMOVMSKPS(eax, xRegisterSSE(t0reg));
armMOVMSKPS(EAX, regT0);
// xAND(eax, 1); //Check sign
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp2 = JZ8(0); //Skip if not set
armAsm->B(&pjmp2, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp2);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// xAND.PS(xRegisterSSE(t0reg), ptr[&s_pos[0]]); // Make t0reg Positive
armAsm->And(regT0.V16B(), regT0.V16B(), armLoadPtrV(&s_pos[0]).V16B()); // Make t0reg Positive
armAsm->And(regT0.V16B(), regT0.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_pos[0])).V16B()); // Make t0reg Positive
// x86SetJ8(pjmp2);
armBind(&pjmp2);
@@ -2312,9 +2312,9 @@ void recRSQRThelper1(int regd, int t0reg) // Preforms the RSQRT function when re
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, a64::QRegister(t1reg));
// xAND(eax, 1); //Check sign (if t0reg == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp1 = JZ8(0); //Skip if not set
armAsm->B(&pjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp1);
/*--- Check for 0/0 ---*/
// xXOR.PS(xRegisterSSE(t1reg), xRegisterSSE(t1reg));
armAsm->Eor(a64::QRegister(t1reg).V16B(), a64::QRegister(t1reg).V16B(), a64::QRegister(t1reg).V16B());
@@ -2323,9 +2323,9 @@ void recRSQRThelper1(int regd, int t0reg) // Preforms the RSQRT function when re
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, a64::QRegister(t1reg));
// xAND(eax, 1); //Check sign (if regd == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// qjmp1 = JZ8(0); //Skip if not set
armAsm->B(&qjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &qjmp1);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags ( 0/0 )
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// qjmp2 = JMP8(0);
@@ -2339,9 +2339,9 @@ void recRSQRThelper1(int regd, int t0reg) // Preforms the RSQRT function when re
/*--- Make regd +/- Maximum ---*/
// xAND.PS(xRegisterSSE(regd), ptr[&s_neg[0]]); // Get the sign bit
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(&s_neg[0]).V16B());
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_neg[0])).V16B());
// xOR.PS(xRegisterSSE(regd), ptr[&g_maxvals[0]]); // regd = +/- Maximum
armAsm->Orr(regD.V16B(), regD.V16B(), armLoadPtrV(&g_maxvals[0]).V16B());
armAsm->Orr(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).V16B());
// pjmp32 = JMP32(0);
armAsm->B(&pjmp32);
// x86SetJ8(pjmp1);
@@ -2350,7 +2350,7 @@ void recRSQRThelper1(int regd, int t0reg) // Preforms the RSQRT function when re
if (CHECK_FPU_EXTRA_OVERFLOW)
{
// xMIN.SS(xRegisterSSE(t0reg), ptr[&g_maxvals[0]]); // Only need to do positive clamp, since t0reg is positive
armAsm->Fminnm(regT0.S(), regT0.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regT0.S(), regT0.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
fpuFloat2(regd);
}
@@ -2372,11 +2372,11 @@ void recRSQRThelper2(int regd, int t0reg) // Preforms the RSQRT function when re
auto regT0 = a64::QRegister(t0reg);
// xAND.PS(xRegisterSSE(t0reg), ptr[&s_pos[0]]); // Make t0reg Positive
armAsm->And(regT0.V16B(), regT0.V16B(), armLoadPtrV(&s_pos[0]).V16B());
armAsm->And(regT0.V16B(), regT0.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_pos[0])).V16B());
if (CHECK_FPU_EXTRA_OVERFLOW)
{
// xMIN.SS(xRegisterSSE(t0reg), ptr[&g_maxvals[0]]); // Only need to do positive clamp, since t0reg is positive
armAsm->Fminnm(regT0.S(), regT0.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regT0.S(), regT0.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
fpuFloat2(regd);
}
// xSQRT.SS(xRegisterSSE(t0reg), xRegisterSSE(t0reg));
+87 -87
View File
@@ -80,48 +80,48 @@ namespace DOUBLE {
// PS2 -> DOUBLE
//------------------------------------------------------------------
#define SINGLE(sign, exp, mant) (((u32)(sign) << 31) | ((u32)(exp) << 23) | (u32)(mant))
#define DOUBLE(sign, exp, mant) (((sign##ULL) << 63) | ((exp##ULL) << 52) | (mant##ULL))
//#define SINGLE(sign, exp, mant) (((u32)(sign) << 31) | ((u32)(exp) << 23) | (u32)(mant))
//#define DOUBLE(sign, exp, mant) (((sign##ULL) << 63) | ((exp##ULL) << 52) | (mant##ULL))
struct FPUd_Globals
{
u32 neg[4], pos[4];
//struct FPUd_Globals
//{
// u32 neg[4], pos[4];
//
// u32 pos_inf[4], neg_inf[4],
// one_exp[4];
//
// u64 dbl_one_exp[2];
//
// u64 dbl_cvt_overflow, // needs special code if above or equal
// dbl_ps2_overflow, // overflow & clamp if above or equal
// dbl_underflow; // underflow if below
//
// u64 padding;
//
// u64 dbl_s_pos[2];
// //u64 dlb_s_neg[2];
//};
u32 pos_inf[4], neg_inf[4],
one_exp[4];
u64 dbl_one_exp[2];
u64 dbl_cvt_overflow, // needs special code if above or equal
dbl_ps2_overflow, // overflow & clamp if above or equal
dbl_underflow; // underflow if below
u64 padding;
u64 dbl_s_pos[2];
//u64 dlb_s_neg[2];
};
alignas(32) static const FPUd_Globals s_const =
{
{0x80000000, 0xffffffff, 0xffffffff, 0xffffffff},
{0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff},
{SINGLE(0, 0xff, 0), 0, 0, 0},
{SINGLE(1, 0xff, 0), 0, 0, 0},
{SINGLE(0, 1, 0), 0, 0, 0},
{DOUBLE(0, 1, 0), 0},
DOUBLE(0, 1151, 0), // cvt_overflow
DOUBLE(0, 1152, 0), // ps2_overflow
DOUBLE(0, 897, 0), // underflow
0, // Padding!!
{0x7fffffffffffffffULL, 0},
//{0x8000000000000000ULL, 0},
};
//alignas(32) static const FPUd_Globals s_const =
//{
// {0x80000000, 0xffffffff, 0xffffffff, 0xffffffff},
// {0x7fffffff, 0xffffffff, 0xffffffff, 0xffffffff},
//
// {SINGLE(0, 0xff, 0), 0, 0, 0},
// {SINGLE(1, 0xff, 0), 0, 0, 0},
// {SINGLE(0, 1, 0), 0, 0, 0},
//
// {DOUBLE(0, 1, 0), 0},
//
// DOUBLE(0, 1151, 0), // cvt_overflow
// DOUBLE(0, 1152, 0), // ps2_overflow
// DOUBLE(0, 897, 0), // underflow
//
// 0, // Padding!!
//
// {0x7fffffffffffffffULL, 0},
// //{0x8000000000000000ULL, 0},
//};
// ToDouble : converts single-precision PS2 float to double-precision IEEE float
@@ -131,12 +131,12 @@ void ToDouble(int reg)
auto regQ = a64::QRegister(reg);
// xUCOMI.SS(xRegisterSSE(reg), ptr[s_const.pos_inf]); // Sets ZF if reg is equal or incomparable to pos_inf
armAsm->Fcmp(regQ.S(), armLoadPtrV(s_const.pos_inf).S());
armAsm->Fcmp(regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos_inf)).S());
// u8* to_complex = JE8(0); // Complex conversion if positive infinity or NaN
a64::Label to_complex;
armAsm->B(&to_complex, a64::Condition::eq);
// xUCOMI.SS(xRegisterSSE(reg), ptr[s_const.neg_inf]);
armAsm->Fcmp(regQ.S(), armLoadPtrV(s_const.neg_inf).S());
armAsm->Fcmp(regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg_inf)).S());
// u8* to_complex2 = JE8(0); // Complex conversion if negative infinity
a64::Label to_complex2;
armAsm->B(&to_complex2, a64::Condition::eq);
@@ -154,11 +154,11 @@ void ToDouble(int reg)
// Special conversion for when IEEE sees the value in reg as an INF/NaN
// xPSUB.D(xRegisterSSE(reg), ptr[s_const.one_exp]); // Lower exponent by one
armAsm->Sub(regQ.V4S(), regQ.V4S(), armLoadPtrV(s_const.one_exp).V4S());
armAsm->Sub(regQ.V4S(), regQ.V4S(), armLoadPtrV(PTR_CPU(mVUss4.s_const.one_exp)).V4S());
// xCVTSS2SD(xRegisterSSE(reg), xRegisterSSE(reg));
armAsm->Fcvt(regQ.V1D(), regQ.S());
// xPADD.Q(xRegisterSSE(reg), ptr[s_const.dbl_one_exp]); // Raise exponent by one
armAsm->Fadd(regQ.V2D(), regQ.V2D(), armLoadPtrV(s_const.dbl_one_exp).V2D());
armAsm->Fadd(regQ.V2D(), regQ.V2D(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_one_exp)).V2D());
// x86SetJ8(end);
armBind(&end);
@@ -198,16 +198,16 @@ void ToPS2FPU_Full(int reg, bool flags, int absreg, bool acc, bool addsub)
// xMOVAPS(xRegisterSSE(absreg), xRegisterSSE(reg));
armAsm->Mov(regAbs, a64::QRegister(reg));
// xAND.PD(xRegisterSSE(absreg), ptr[&s_const.dbl_s_pos]);
armAsm->And(regAbs.V16B(), regAbs.V16B(), armLoadPtrV(&s_const.dbl_s_pos).V16B());
armAsm->And(regAbs.V16B(), regAbs.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_s_pos)).V16B());
// xUCOMI.SD(xRegisterSSE(absreg), ptr[&s_const.dbl_cvt_overflow]);
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(&s_const.dbl_cvt_overflow).V1D());
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_cvt_overflow)).V1D());
// u8* to_complex = JAE8(0);
a64::Label to_complex;
armAsm->B(&to_complex, a64::Condition::cs);
// xUCOMI.SD(xRegisterSSE(absreg), ptr[&s_const.dbl_underflow]);
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(&s_const.dbl_underflow).V1D());
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_underflow)).V1D());
// u8* to_underflow = JB8(0);
a64::Label to_underflow;
armAsm->B(&to_underflow, a64::Condition::cc);
@@ -222,17 +222,17 @@ void ToPS2FPU_Full(int reg, bool flags, int absreg, bool acc, bool addsub)
// x86SetJ8(to_complex);
armBind(&to_complex);
// xUCOMI.SD(xRegisterSSE(absreg), ptr[&s_const.dbl_ps2_overflow]);
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(&s_const.dbl_ps2_overflow).V1D());
armAsm->Fcmp(regAbs.V1D(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_ps2_overflow)).V1D());
// u8* to_overflow = JAE8(0);
a64::Label to_overflow;
armAsm->B(&to_overflow, a64::Condition::cs);
// xPSUB.Q(xRegisterSSE(reg), ptr[&s_const.dbl_one_exp]); //lower exponent
armAsm->Sub(regQ.V2D(), regQ.V2D(), armLoadPtrV(&s_const.dbl_one_exp).V2D());
armAsm->Sub(regQ.V2D(), regQ.V2D(), armLoadPtrV(PTR_CPU(mVUss4.s_const.dbl_one_exp)).V2D());
// xCVTSD2SS(xRegisterSSE(reg), xRegisterSSE(reg)); //convert
armAsm->Fcvt(regQ.S(), regQ.V1D());
// xPADD.D(xRegisterSSE(reg), ptr[s_const.one_exp]); //raise exponent
armAsm->Add(regQ.V4S(), regQ.V4S(), armLoadPtrV(s_const.one_exp).V4S());
armAsm->Add(regQ.V4S(), regQ.V4S(), armLoadPtrV(PTR_CPU(mVUss4.s_const.one_exp)).V4S());
// u32* end2 = JMP32(0);
a64::Label end2;
@@ -243,7 +243,7 @@ void ToPS2FPU_Full(int reg, bool flags, int absreg, bool acc, bool addsub)
// xCVTSD2SS(xRegisterSSE(reg), xRegisterSSE(reg));
armAsm->Fcvt(regQ.S(), regQ.V1D());
// xOR.PS(xRegisterSSE(reg), ptr[&s_const.pos]); //clamp
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(&s_const.pos).V16B());
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos)).V16B());
if (flags && FPU_FLAGS_OVERFLOW) {
// xOR(ptr32[&fpuRegs.fprc[31]], (FPUflagO | FPUflagSO));
armOrr(PTR_CPU(fpuRegs.fprc[31]), (FPUflagO | FPUflagSO));
@@ -299,7 +299,7 @@ void ToPS2FPU_Full(int reg, bool flags, int absreg, bool acc, bool addsub)
// xCVTSD2SS(xRegisterSSE(reg), xRegisterSSE(reg));
armAsm->Fcvt(regQ.S(), regQ.V1D());
// xAND.PS(xRegisterSSE(reg), ptr[s_const.neg]); //flush to zero
armAsm->And(regQ.V16B(), regQ.V16B(), armLoadPtrV(s_const.neg).V16B());
armAsm->And(regQ.V16B(), regQ.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg)).V16B());
// x86SetJ32(end);
armBind(&end);
@@ -326,9 +326,9 @@ void ToPS2FPU(int reg, bool flags, int absreg, bool acc, bool addsub = false)
// xCVTSD2SS(xRegisterSSE(reg), xRegisterSSE(reg)); //clamp
armAsm->Fcvt(regQ.S(), regQ.V1D());
// xMIN.SS(xRegisterSSE(reg), ptr[&g_maxvals[0]]);
armAsm->Fminnm(regQ.S(), regQ.S(), armLoadPtrV(&g_maxvals[0]).S());
armAsm->Fminnm(regQ.S(), regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).S());
// xMAX.SS(xRegisterSSE(reg), ptr[&g_minvals[0]]);
armAsm->Fmaxnm(regQ.S(), regQ.S(), armLoadPtrV(&g_minvals[0]).S());
armAsm->Fmaxnm(regQ.S(), regQ.S(), armLoadPtrV(PTR_CPU(mVUss4.g_minvals[0])).S());
}
}
@@ -339,14 +339,14 @@ void SetMaxValue(int regd)
if (FPU_RESULT) {
// xOR.PS(xRegisterSSE(regd), ptr[&s_const.pos[0]]); // set regd to maximum
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(&s_const.pos[0]).V16B());
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos[0])).V16B());
}
else
{
// xAND.PS(xRegisterSSE(regd), ptr[&s_const.neg[0]]); // Get the sign bit
armAsm->And(regQ.V16B(), regQ.V16B(), armLoadPtrV(&s_const.neg[0]).V16B());
armAsm->And(regQ.V16B(), regQ.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg[0])).V16B());
// xOR.PS(xRegisterSSE(regd), ptr[&g_maxvals[0]]); // regd = +/- Maximum (CLAMP)!
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(&g_maxvals[0]).V16B());
armAsm->Orr(regQ.V16B(), regQ.V16B(), armLoadPtrV(PTR_CPU(mVUss4.g_maxvals[0])).V16B());
}
}
@@ -410,7 +410,7 @@ void recABS_S_xmm(int info)
// xAND.PS(xRegisterSSE(EEREC_D), ptr[s_const.pos]);
auto regED = a64::QRegister(EEREC_D);
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(s_const.pos).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos)).V16B());
}
FPURECOMPILE_CONSTCODE(ABS_S, XMMINFO_WRITED | XMMINFO_READS);
@@ -489,7 +489,7 @@ void FPU_ADD_SUB(int tempd, int tempt) //tempd and tempt are overwritten, they a
armBind(&j8Ptr0);
//diff = 25 .. 255 , expt < expd
// xAND.PS(xRegisterSSE(tempt), ptr[s_const.neg]);
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(s_const.neg).V16B());
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg)).V16B());
// j8Ptr[5] = JMP8(0);
armAsm->B(&j8Ptr5);
@@ -513,7 +513,7 @@ void FPU_ADD_SUB(int tempd, int tempt) //tempd and tempt are overwritten, they a
armBind(&j8Ptr3);
//diff = -255 .. -25, expd < expt
// xAND.PS(xRegisterSSE(tempd), ptr[s_const.neg]);
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(s_const.neg).V16B());
armAsm->And(regD.V16B(), regD.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg)).V16B());
// x86SetJ8(j8Ptr[2]);
armBind(&j8Ptr2);
@@ -765,9 +765,9 @@ void recDIVhelper1(int regd, int regt) // Sets flags
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regt == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// ajmp32 = JZ32(0); //Skip if not set
armAsm->B(&ajmp32, a64::Condition::eq);
armAsm->Cbz(EAX, &ajmp32);
//--- Check for 0/0 ---
// xXOR.PS(xRegisterSSE(t1reg), xRegisterSSE(t1reg));
@@ -777,9 +777,9 @@ void recDIVhelper1(int regd, int regt) // Sets flags
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regd == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp1 = JZ8(0); //Skip if not set
armAsm->B(&pjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp1);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags ( 0/0 )
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// pjmp2 = JMP8(0);
@@ -912,7 +912,7 @@ void recMaddsub(int info, int regd, int op, bool acc)
armBind(&mulovf);
if (op == 1) { //sub
// xXOR.PS(xRegisterSSE(sreg), ptr[s_const.neg]);
armAsm->Eor(regS.V16B(), regS.V16B(), armLoadPtrV(s_const.neg).V16B());
armAsm->Eor(regS.V16B(), regS.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg)).V16B());
}
// xMOVAPS(xRegisterSSE(treg), xRegisterSSE(sreg)); //fall through below
armAsm->Mov(regT, regS);
@@ -978,11 +978,11 @@ FPURECOMPILE_CONSTCODE(MADDA_S, XMMINFO_WRITEACC | XMMINFO_READACC | XMMINFO_REA
// MAX / MIN XMM
//------------------------------------------------------------------
alignas(16) static const u32 minmax_mask[8] =
{
0xffffffff, 0x80000000, 0, 0,
0, 0x40000000, 0, 0,
};
//alignas(16) static const u32 minmax_mask[8] =
//{
// 0xffffffff, 0x80000000, 0, 0,
// 0, 0x40000000, 0, 0,
//};
// FPU's MAX/MIN work with all numbers (including "denormals"). Check VU's logical min max for more info.
void recMINMAX(int info, bool ismin)
{
@@ -997,15 +997,15 @@ void recMINMAX(int info, bool ismin)
// xPSHUF.D(xRegisterSSE(sreg), xRegisterSSE(sreg), 0x00);
armPSHUFD(regS, regS, 0x00);
// xPAND(xRegisterSSE(sreg), ptr[minmax_mask]);
armAsm->And(regS.V16B(), regS.V16B(), armLoadPtrV(minmax_mask).V16B());
armAsm->And(regS.V16B(), regS.V16B(), armLoadPtrV(PTR_CPU(mVUss4.minmax_mask)).V16B());
// xPOR(xRegisterSSE(sreg), ptr[&minmax_mask[4]]);
armAsm->Orr(regS.V16B(), regS.V16B(), armLoadPtrV(&minmax_mask[4]).V16B());
armAsm->Orr(regS.V16B(), regS.V16B(), armLoadPtrV(PTR_CPU(mVUss4.minmax_mask[4])).V16B());
// xPSHUF.D(xRegisterSSE(treg), xRegisterSSE(treg), 0x00);
armPSHUFD(regT, regT, 0x00);
// xPAND(xRegisterSSE(treg), ptr[minmax_mask]);
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(minmax_mask).V16B());
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(PTR_CPU(mVUss4.minmax_mask)).V16B());
// xPOR(xRegisterSSE(treg), ptr[&minmax_mask[4]]);
armAsm->Orr(regT.V16B(), regT.V16B(), armLoadPtrV(&minmax_mask[4]).V16B());
armAsm->Orr(regT.V16B(), regT.V16B(), armLoadPtrV(PTR_CPU(mVUss4.minmax_mask[4])).V16B());
if (ismin) {
// xMIN.SD(xRegisterSSE(sreg), xRegisterSSE(treg));
armAsm->Fminnm(regS.V1D(), regS.V1D(), regT.V1D());
@@ -1113,7 +1113,7 @@ void recNEG_S_xmm(int info)
CLEAR_OU_FLAGS;
// xXOR.PS(xRegisterSSE(EEREC_D), ptr[&s_const.neg[0]]);
armAsm->Eor(a64::QRegister(EEREC_D).V16B(), a64::QRegister(EEREC_D).V16B(), armLoadPtrV(&s_const.neg[0]).V16B());
armAsm->Eor(a64::QRegister(EEREC_D).V16B(), a64::QRegister(EEREC_D).V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.neg[0])).V16B());
}
FPURECOMPILE_CONSTCODE(NEG_S, XMMINFO_WRITED | XMMINFO_READS);
@@ -1177,21 +1177,21 @@ void recSQRT_S_xmm(int info)
// xMOVMSKPS(eax, xRegisterSSE(EEREC_D));
armMOVMSKPS(EAX, regED);
// xAND(eax, 1); //Check sign
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// u8* pjmp = JZ8(0); //Skip if none are
a64::Label pjmp;
armAsm->B(&pjmp, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// xAND.PS(xRegisterSSE(EEREC_D), ptr[&s_const.pos[0]]); // Make EEREC_D Positive
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(&s_const.pos[0]).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos[0])).V16B());
// x86SetJ8(pjmp);
armBind(&pjmp);
}
else
{
// xAND.PS(xRegisterSSE(EEREC_D), ptr[&s_const.pos[0]]); // Make EEREC_D Positive
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(&s_const.pos[0]).V16B());
armAsm->And(regED.V16B(), regED.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos[0])).V16B());
}
@@ -1239,13 +1239,13 @@ void recRSQRThelper1(int regd, int regt) // Preforms the RSQRT function when reg
// xMOVMSKPS(eax, xRegisterSSE(regt));
armMOVMSKPS(EAX, regT);
// xAND(eax, 1); //Check sign
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp2 = JZ8(0); //Skip if not set
armAsm->B(&pjmp2, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp2);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// xAND.PS(xRegisterSSE(regt), ptr[&s_const.pos[0]]); // Make regt Positive
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(&s_const.pos[0]).V16B());
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos[0])).V16B());
// x86SetJ8(pjmp2);
armBind(&pjmp2);
@@ -1257,9 +1257,9 @@ void recRSQRThelper1(int regd, int regt) // Preforms the RSQRT function when reg
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regt == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// pjmp1 = JZ8(0); //Skip if not set
armAsm->B(&pjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &pjmp1);
//--- Check for 0/0 ---
// xXOR.PS(xRegisterSSE(t1reg), xRegisterSSE(t1reg));
@@ -1269,9 +1269,9 @@ void recRSQRThelper1(int regd, int regt) // Preforms the RSQRT function when reg
// xMOVMSKPS(eax, xRegisterSSE(t1reg));
armMOVMSKPS(EAX, regT1);
// xAND(eax, 1); //Check sign (if regd == zero, sign will be set)
armAsm->Ands(EAX, EAX, 1);
armAsm->And(EAX, EAX, 1);
// qjmp1 = JZ8(0); //Skip if not set
armAsm->B(&qjmp1, a64::Condition::eq);
armAsm->Cbz(EAX, &qjmp1);
// xOR(ptr32[&fpuRegs.fprc[31]], FPUflagI | FPUflagSI); // Set I and SI flags ( 0/0 )
armOrr(PTR_CPU(fpuRegs.fprc[31]), FPUflagI | FPUflagSI);
// qjmp2 = JMP8(0);
@@ -1309,7 +1309,7 @@ void recRSQRThelper2(int regd, int regt) // Preforms the RSQRT function when reg
auto regT = a64::QRegister(regt);
// xAND.PS(xRegisterSSE(regt), ptr[&s_const.pos[0]]); // Make regt Positive
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(&s_const.pos[0]).V16B());
armAsm->And(regT.V16B(), regT.V16B(), armLoadPtrV(PTR_CPU(mVUss4.s_const.pos[0])).V16B());
ToDouble(regt); ToDouble(regd);
@@ -389,11 +389,11 @@ void recLWR()
auto reg32 = a64::WRegister(treg);
// xAND(temp, 3);
armAsm->Ands(temp, temp, 3);
armAsm->And(temp, temp, 3);
// xForwardJE8 nomask;
a64::Label nomask;
armAsm->B(&nomask, a64::Condition::eq);
armAsm->Cbz(temp, &nomask);
// xSHL(temp, 3);
armAsm->Lsl(temp, temp, 3);
// mask off bytes loaded
@@ -576,7 +576,7 @@ void recSWR()
// xMOV(temp, arg1regd);
armAsm->Mov(temp, ECX);
// xAND(arg1regd, ~3);
armAsm->And(ECX, ECX, ~3);
armAsm->Ands(ECX, ECX, ~3);
// xAND(temp, 3);
armAsm->Ands(temp, temp, 3);
@@ -1239,7 +1239,7 @@ void recSDR()
// xMOV(temp2, arg2reg);
armAsm->Mov(temp2, RDX);
// xAND(arg1regd, ~0x07);
armAsm->And(ECX, ECX, ~0x07);
armAsm->Ands(ECX, ECX, ~0x07);
// xAND(temp1, 0x7);
armAsm->Ands(temp1, temp1, 0x7);
+10 -10
View File
@@ -7,14 +7,14 @@
// Micro VU - Clamp Functions
//------------------------------------------------------------------
alignas(16) const u32 sse4_minvals[2][4] = {
{0xff7fffff, 0xffffffff, 0xffffffff, 0xffffffff}, //1000
{0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}, //1111
};
alignas(16) const u32 sse4_maxvals[2][4] = {
{0x7f7fffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1000
{0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
};
//alignas(16) const u32 sse4_minvals[2][4] = {
// {0xff7fffff, 0xffffffff, 0xffffffff, 0xffffffff}, //1000
// {0xff7fffff, 0xff7fffff, 0xff7fffff, 0xff7fffff}, //1111
//};
//alignas(16) const u32 sse4_maxvals[2][4] = {
// {0x7f7fffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1000
// {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
//};
// Used for Result Clamping
// Note: This function will not preserve NaN values' sign.
@@ -55,9 +55,9 @@ void mVUclamp2(microVU& mVU, const xmm& reg, const xmm& regT1in, int xyzw, bool
{
int i = (xyzw == 1 || xyzw == 2 || xyzw == 4 || xyzw == 8) ? 0 : 1;
// xPMIN.SD(reg, ptr128[&sse4_maxvals[i][0]]);
armAsm->Smin(reg.V4S(), reg.V4S(), armLoadPtrV(&sse4_maxvals[i][0]).V4S());
armAsm->Smin(reg.V4S(), reg.V4S(), armLoadPtrV(PTR_CPU(mVUss4.sse4_maxvals[i][0])).V4S());
// xPMIN.UD(reg, ptr128[&sse4_minvals[i][0]]);
armAsm->Umin(reg.V4S(), reg.V4S(), armLoadPtrV(&sse4_minvals[i][0]).V4S());
armAsm->Umin(reg.V4S(), reg.V4S(), armLoadPtrV(PTR_CPU(mVUss4.sse4_minvals[i][0])).V4S());
return;
}
else
+2 -2
View File
@@ -2071,7 +2071,7 @@ mVUop(mVU_XTOP)
if (mVU.index && THREAD_VU1) {
armAsm->Ldrh(regT, PTR_VU1(vifRegs.top));
} else {
armAsm->Ldrh(regT, armMemOperandPtr(&mVU.getVifRegs().top));
armAsm->Ldrh(regT, PTR_CPU(vifRegs[mVU.index].top));
}
mVU.regAlloc->clearNeeded(regT);
mVU.profiler.EmitOp(opXTOP);
@@ -2095,7 +2095,7 @@ mVUop(mVU_XITOP)
if (mVU.index && THREAD_VU1) {
armAsm->Ldrh(regT, PTR_VU1(vifRegs.itop));
} else {
armAsm->Ldrh(regT, armMemOperandPtr(&mVU.getVifRegs().itop));
armAsm->Ldrh(regT, PTR_CPU(vifRegs[mVU.index].itop));
}
// xAND(regT, isVU1 ? 0x3ff : 0xff);
armAsm->And(regT, regT, isVU1 ? 0x3ff : 0xff);
+8 -8
View File
@@ -18,10 +18,10 @@
} while (0)
alignas(16) const u32 sse4_compvals[2][4] = {
{0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
{0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1111
};
//alignas(16) const u32 sse4_compvals[2][4] = {
// {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff}, //1111
// {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1111
//};
const std::array<u16, 16> flipMask{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
@@ -96,16 +96,16 @@ static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = a64::NoVReg,
// xMOVAPS(regT1, regT2);
armAsm->Mov(regT1.Q(), regT2.Q());
// xAND.PS(regT1, ptr128[&sse4_compvals[1][0]]); // Remove sign flags (we don't care)
armAsm->And(regT1.V16B(), regT1.V16B(), armLoadPtrV(&sse4_compvals[1][0]).V16B());
armAsm->And(regT1.V16B(), regT1.V16B(), armLoadPtrV(PTR_CPU(mVUss4.sse4_compvals[1][0])).V16B());
// xCMPNLT.PS(regT1, ptr128[&sse4_compvals[0][0]]); // Compare if T1 == FLT_MAX
armAsm->Fcmge(regT1.V4S(), regT1.V4S(), armLoadPtrV(&sse4_compvals[0][0]).V4S());
armAsm->Fcmeq(regT1.V4S(), regT1.V4S(), armLoadPtrV(PTR_CPU(mVUss4.sse4_compvals[0][0])).V4S());
// xMOVMSKPS(gprT2, regT1); // Grab sign bits for equal results
armMOVMSKPS(gprT2, regT1);
// xAND(gprT2, AND_XYZW); // Grab "Is FLT_MAX" bits from the previous calculation
armAsm->Ands(gprT2, gprT2, AND_XYZW);
armAsm->And(gprT2, gprT2, AND_XYZW);
// xForwardJump32 oJMP(Jcc_Zero);
a64::Label oJMP;
armAsm->B(&oJMP, a64::Condition::eq);
armAsm->Cbz(gprT2, &oJMP);
// xOR(sReg, 0x820000);
armAsm->Orr(sReg, sReg, 0x820000);