Fixes floating point conversion rounding bugs

When floats and doubles were converting to integers we weren't doing the correct transformation.
AArch64 provides direct ops for all four of the op types. So lets use them
  - f32 -> int64
  - f32 -> int32
  - f64 -> int64
  - f64 -> int32

Doesn't fully fix the case of overflow for AArch64 since overflow behaviour is different.
x86 returns 0x8000'0000 or 0x8000'0000'0000'0000 while AArch64 saturates to the maximum signed
integers. Can't work around that without checking overflow flags.

This does solve the typical case though.
Fixes audio problems in all FMod games.
This commit is contained in:
Ryan Houdek committed 2021-06-08 06:54:10 -07:00
1 parent 18fe049976
commit d57a034220
11 files changed
+160 -397

No files matched your search

@@ -3349,22 +3349,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_UTOF: {
auto Op = IROp->C<IR::IROp_Vector_UToF>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
uint8_t Tmp[16];
uint8_t Elements = OpSize / Op->Header.ElementSize;
auto Func = [](auto a, auto min, auto max) { return a; };
switch (Op->Header.ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(4, float, uint32_t, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, double, uint64_t, Func, 0, 0)
default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break;
}
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_STOF: {
auto Op = IROp->C<IR::IROp_Vector_SToF>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
@@ -3381,22 +3365,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_FTOZU: {
auto Op = IROp->C<IR::IROp_Vector_FToZU>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
uint8_t Tmp[16];
uint8_t Elements = OpSize / Op->Header.ElementSize;
auto Func = [](auto a, auto min, auto max) { return a; };
switch (Op->Header.ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, float, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, double, Func, 0, 0)
default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break;
}
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_FTOZS: {
auto Op = IROp->C<IR::IROp_Vector_FToZS>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
@@ -3404,7 +3372,7 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
uint8_t Elements = OpSize / Op->Header.ElementSize;
auto Func = [](auto a, auto min, auto max) { return a; };
auto Func = [](auto a, auto min, auto max) { return std::trunc(a); };
switch (Op->Header.ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(4, int32_t, float, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, int64_t, double, Func, 0, 0)
@@ -3413,22 +3381,6 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_FTOU: {
auto Op = IROp->C<IR::IROp_Vector_FToU>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
uint8_t Tmp[16];
uint8_t Elements = OpSize / Op->Header.ElementSize;
auto Func = [](auto a, auto min, auto max) { return a; };
switch (Op->Header.ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(4, uint32_t, float, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, uint64_t, double, Func, 0, 0)
default: LOGMAN_MSG_A("Unknown Element Size: %d", Op->Header.ElementSize); break;
}
memcpy(GDP, Tmp, OpSize);
break;
}
case IR::OP_VECTOR_FTOS: {
auto Op = IROp->C<IR::IROp_Vector_FToS>();
void *Src = GetSrc<void*>(SSAData, Op->Header.Args[0]);
@@ -3436,7 +3388,7 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
uint8_t Elements = OpSize / Op->Header.ElementSize;
auto Func = [](auto a, auto min, auto max) { return a; };
auto Func = [](auto a, auto min, auto max) { return std::nearbyint(a); };
switch (Op->Header.ElementSize) {
DO_VECTOR_1SRC_2TYPE_OP(4, int32_t, float, Func, 0, 0)
DO_VECTOR_1SRC_2TYPE_OP(8, int64_t, double, Func, 0, 0)
@@ -4381,78 +4333,57 @@ void InterpreterOps::InterpretIR(FEXCore::Core::InternalThreadState *Thread, uin
}
break;
}
case IR::OP_FLOAT_FROMGPR_U: {
auto Op = IROp->C<IR::IROp_Float_FromGPR_U>();
uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize;
switch (Conv) {
case 0x0404: { // Float <- int32_t
float Dst = (float)*GetSrc<uint32_t*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
break;
}
case 0x0408: { // Float <- int64_t
float Dst = (float)*GetSrc<uint64_t*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
break;
}
case 0x0804: { // Double <- int32_t
double Dst = (double)*GetSrc<uint32_t*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
break;
}
case 0x0808: { // Double <- int64_t
double Dst = (double)*GetSrc<uint64_t*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
break;
}
}
break;
}
case IR::OP_FLOAT_TOGPR_ZS: {
auto Op = IROp->C<IR::IROp_Float_ToGPR_ZS>();
if (Op->Header.ElementSize == 8) {
int64_t Dst = (int64_t)*GetSrc<double*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
else {
int32_t Dst = (int32_t)*GetSrc<float*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
break;
}
case IR::OP_FLOAT_TOGPR_ZU: {
auto Op = IROp->C<IR::IROp_Float_ToGPR_ZU>();
if (Op->Header.ElementSize == 8) {
uint64_t Dst = (uint64_t)*GetSrc<double*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
else {
uint32_t Dst = (uint32_t)*GetSrc<float*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize;
switch (Conv) {
case 0x0804: { // int64_t <- float
int64_t Dst = (int64_t)std::trunc(*GetSrc<float*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0808: { // int64_t <- double
int64_t Dst = (int64_t)std::trunc(*GetSrc<double*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0404: { // int32_t <- float
int32_t Dst = (int32_t)std::trunc(*GetSrc<float*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0408: { // int32_t <- double
int32_t Dst = (int32_t)std::trunc(*GetSrc<double*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
}
break;
}
case IR::OP_FLOAT_TOGPR_S: {
auto Op = IROp->C<IR::IROp_Float_ToGPR_S>();
if (Op->Header.ElementSize == 8) {
int64_t Dst = (int64_t)*GetSrc<double*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
else {
int32_t Dst = (int32_t)*GetSrc<float*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
break;
}
case IR::OP_FLOAT_TOGPR_U: {
auto Op = IROp->C<IR::IROp_Float_ToGPR_U>();
if (Op->Header.ElementSize == 8) {
uint64_t Dst = (uint64_t)*GetSrc<double*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
}
else {
uint32_t Dst = (uint32_t)*GetSrc<float*>(SSAData, Op->Header.Args[0]);
memcpy(GDP, &Dst, Op->Header.ElementSize);
uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize;
switch (Conv) {
case 0x0804: { // int64_t <- float
int64_t Dst = (int64_t)std::nearbyint(*GetSrc<float*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0808: { // int64_t <- double
int64_t Dst = (int64_t)std::nearbyint(*GetSrc<double*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0404: { // int32_t <- float
int32_t Dst = (int32_t)std::nearbyint(*GetSrc<float*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
case 0x0408: { // int32_t <- double
int32_t Dst = (int32_t)std::nearbyint(*GetSrc<double*>(SSAData, Op->Header.Args[0]));
memcpy(GDP, &Dst, IROp->Size);
break;
}
}
break;
}
+28 -15
View File
@@ -969,34 +969,49 @@ DEF_OP(VExtractToGPR) {
}
}
DEF_OP(Float_ToGPR_ZU) {
LogMan::Msg::D("Unimplemented");
}
DEF_OP(Float_ToGPR_ZS) {
auto Op = IROp->C<IR::IROp_Float_ToGPR_ZS>();
if (Op->Header.ElementSize == 8) {
fcvtzs(GetReg<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()).D());
aarch64::Register Dst{};
aarch64::VRegister Src{};
if (Op->SrcElementSize == 8) {
Src = GetSrc(Op->Header.Args[0].ID()).D();
}
else {
fcvtzs(GetReg<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()).S());
Src = GetSrc(Op->Header.Args[0].ID()).S();
}
}
DEF_OP(Float_ToGPR_U) {
LogMan::Msg::D("Unimplemented");
if (IROp->Size == 8) {
Dst = GetReg<RA_64>(Node);
}
else {
Dst = GetReg<RA_32>(Node);
}
fcvtzs(Dst, Src);
}
DEF_OP(Float_ToGPR_S) {
auto Op = IROp->C<IR::IROp_Float_ToGPR_S>();
if (Op->Header.ElementSize == 8) {
aarch64::Register Dst{};
aarch64::VRegister Src{};
if (Op->SrcElementSize == 8) {
frinti(VTMP1.D(), GetSrc(Op->Header.Args[0].ID()).D());
fcvtzs(GetReg<RA_64>(Node), VTMP1.D());
Src = VTMP1.D();
}
else {
frinti(VTMP1.S(), GetSrc(Op->Header.Args[0].ID()).S());
fcvtzs(GetReg<RA_32>(Node), VTMP1.S());
Src = VTMP1.S();
}
if (IROp->Size == 8) {
Dst = GetReg<RA_64>(Node);
}
else {
Dst = GetReg<RA_32>(Node);
}
fcvtzs(Dst, Src);
}
DEF_OP(FCmp) {
@@ -1087,9 +1102,7 @@ void Arm64JITCore::RegisterALUHandlers() {
REGISTER_OP(SBFE, Sbfe);
REGISTER_OP(SELECT, Select);
REGISTER_OP(VEXTRACTTOGPR, VExtractToGPR);
REGISTER_OP(FLOAT_TOGPR_ZU, Float_ToGPR_ZU);
REGISTER_OP(FLOAT_TOGPR_ZS, Float_ToGPR_ZS);
REGISTER_OP(FLOAT_TOGPR_U, Float_ToGPR_U);
REGISTER_OP(FLOAT_TOGPR_S, Float_ToGPR_S);
REGISTER_OP(FCMP, FCmp);
@@ -56,10 +56,6 @@ DEF_OP(VCastFromGPR) {
}
}
DEF_OP(Float_FromGPR_U) {
LOGMAN_MSG_A("Unimplemented");
}
DEF_OP(Float_FromGPR_S) {
auto Op = IROp->C<IR::IROp_Float_FromGPR_S>();
uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize;
@@ -99,19 +95,6 @@ DEF_OP(Float_FToF) {
}
}
DEF_OP(Vector_UToF) {
auto Op = IROp->C<IR::IROp_Vector_UToF>();
switch (Op->Header.ElementSize) {
case 4:
ucvtf(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S());
break;
case 8:
ucvtf(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D());
break;
default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize);
}
}
DEF_OP(Vector_SToF) {
auto Op = IROp->C<IR::IROp_Vector_SToF>();
switch (Op->Header.ElementSize) {
@@ -125,19 +108,6 @@ DEF_OP(Vector_SToF) {
}
}
DEF_OP(Vector_FToZU) {
auto Op = IROp->C<IR::IROp_Vector_FToZU>();
switch (Op->Header.ElementSize) {
case 4:
fcvtzu(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S());
break;
case 8:
fcvtzu(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D());
break;
default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize);
}
}
DEF_OP(Vector_FToZS) {
auto Op = IROp->C<IR::IROp_Vector_FToZS>();
switch (Op->Header.ElementSize) {
@@ -151,21 +121,6 @@ DEF_OP(Vector_FToZS) {
}
}
DEF_OP(Vector_FToU) {
auto Op = IROp->C<IR::IROp_Vector_FToU>();
switch (Op->Header.ElementSize) {
case 4:
frinti(GetDst(Node).V4S(), GetSrc(Op->Header.Args[0].ID()).V4S());
fcvtzu(GetDst(Node).V4S(), GetDst(Node).V4S());
break;
case 8:
frinti(GetDst(Node).V2D(), GetSrc(Op->Header.Args[0].ID()).V2D());
fcvtzu(GetDst(Node).V2D(), GetDst(Node).V2D());
break;
default: LOGMAN_MSG_A("Unknown castGPR element size: %d", Op->Header.ElementSize);
}
}
DEF_OP(Vector_FToS) {
auto Op = IROp->C<IR::IROp_Vector_FToS>();
switch (Op->Header.ElementSize) {
@@ -259,14 +214,10 @@ void Arm64JITCore::RegisterConversionHandlers() {
#define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &Arm64JITCore::Op_##x
REGISTER_OP(VINSGPR, VInsGPR);
REGISTER_OP(VCASTFROMGPR, VCastFromGPR);
REGISTER_OP(FLOAT_FROMGPR_U, Float_FromGPR_U);
REGISTER_OP(FLOAT_FROMGPR_S, Float_FromGPR_S);
REGISTER_OP(FLOAT_FTOF, Float_FToF);
REGISTER_OP(VECTOR_UTOF, Vector_UToF);
REGISTER_OP(VECTOR_STOF, Vector_SToF);
REGISTER_OP(VECTOR_FTOZU, Vector_FToZU);
REGISTER_OP(VECTOR_FTOZS, Vector_FToZS);
REGISTER_OP(VECTOR_FTOU, Vector_FToU);
REGISTER_OP(VECTOR_FTOS, Vector_FToS);
REGISTER_OP(VECTOR_FTOF, Vector_FToF);
REGISTER_OP(VECTOR_FTOI, Vector_FToI);
@@ -240,7 +240,6 @@ private:
DEF_OP(VExtractToGPR);
DEF_OP(Float_ToGPR_ZU);
DEF_OP(Float_ToGPR_ZS);
DEF_OP(Float_ToGPR_U);
DEF_OP(Float_ToGPR_S);
DEF_OP(FCmp);
@@ -277,14 +276,10 @@ private:
///< Conversion ops
DEF_OP(VInsGPR);
DEF_OP(VCastFromGPR);
DEF_OP(Float_FromGPR_U);
DEF_OP(Float_FromGPR_S);
DEF_OP(Float_FToF);
DEF_OP(Vector_UToF);
DEF_OP(Vector_SToF);
DEF_OP(Vector_FToZU);
DEF_OP(Vector_FToZS);
DEF_OP(Vector_FToU);
DEF_OP(Vector_FToS);
DEF_OP(Vector_FToF);
DEF_OP(Vector_FToI);
+42 -23
View File
@@ -1108,42 +1108,63 @@ DEF_OP(VExtractToGPR) {
}
}
DEF_OP(Float_ToGPR_ZU) {
LogMan::Msg::D("Unimplemented");
}
DEF_OP(Float_ToGPR_ZS) {
auto Op = IROp->C<IR::IROp_Float_ToGPR_ZS>();
if (Op->Header.ElementSize == 8) {
cvttsd2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
}
else {
cvttss2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
}
}
DEF_OP(Float_ToGPR_U) {
LogMan::Msg::D("Unimplemented");
uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize;
switch (Conv) {
case 0x0804: // int64_t <- float
cvttss2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0808: // int64_t <- double
cvttsd2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0404: // int32_t <- float
cvttss2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0408: // int32_t <- double
cvttsd2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
}
}
DEF_OP(Float_ToGPR_S) {
auto Op = IROp->C<IR::IROp_Float_ToGPR_S>();
if (Op->Header.ElementSize == 8) {
cvtsd2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
}
else {
cvtss2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
uint16_t Conv = (IROp->Size << 8) | Op->SrcElementSize;
switch (Conv) {
case 0x0804: // int64_t <- float
cvtss2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0808: // int64_t <- double
cvtsd2si(GetDst<RA_64>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0404: // int32_t <- float
cvtss2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
case 0x0408: // int32_t <- double
cvtsd2si(GetDst<RA_32>(Node), GetSrc(Op->Header.Args[0].ID()));
break;
}
}
DEF_OP(FCmp) {
auto Op = IROp->C<IR::IROp_FCmp>();
if (Op->ElementSize == 4) {
ucomiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
if (Op->Flags & (1 << IR::FCMP_FLAG_UNORDERED)) {
if (Op->ElementSize == 4) {
ucomiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
}
else {
ucomisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
}
}
else {
ucomisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
if (Op->ElementSize == 4) {
comiss(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
}
else {
comisd(GetSrc(Op->Header.Args[0].ID()), GetSrc(Op->Header.Args[1].ID()));
}
}
mov (rdx, 0);
@@ -1217,9 +1238,7 @@ void X86JITCore::RegisterALUHandlers() {
REGISTER_OP(SBFE, Sbfe);
REGISTER_OP(SELECT, Select);
REGISTER_OP(VEXTRACTTOGPR, VExtractToGPR);
REGISTER_OP(FLOAT_TOGPR_ZU, Float_ToGPR_ZU);
REGISTER_OP(FLOAT_TOGPR_ZS, Float_ToGPR_ZS);
REGISTER_OP(FLOAT_TOGPR_U, Float_ToGPR_U);
REGISTER_OP(FLOAT_TOGPR_S, Float_ToGPR_S);
REGISTER_OP(FCMP, FCmp);
#undef REGISTER_OP
@@ -56,10 +56,6 @@ DEF_OP(VCastFromGPR) {
}
}
DEF_OP(Float_FromGPR_U) {
LOGMAN_MSG_A("Unimplemented");
}
DEF_OP(Float_FromGPR_S) {
auto Op = IROp->C<IR::IROp_Float_FromGPR_S>();
uint16_t Conv = (Op->Header.ElementSize << 8) | Op->SrcElementSize;
@@ -99,10 +95,6 @@ DEF_OP(Float_FToF) {
}
}
DEF_OP(Vector_UToF) {
LOGMAN_MSG_A("Unimplemented");
}
DEF_OP(Vector_SToF) {
auto Op = IROp->C<IR::IROp_Vector_SToF>();
switch (Op->Header.ElementSize) {
@@ -125,10 +117,6 @@ DEF_OP(Vector_SToF) {
}
}
DEF_OP(Vector_FToZU) {
LOGMAN_MSG_A("Unimplemented");
}
DEF_OP(Vector_FToZS) {
auto Op = IROp->C<IR::IROp_Vector_FToZS>();
switch (Op->Header.ElementSize) {
@@ -142,10 +130,6 @@ DEF_OP(Vector_FToZS) {
}
}
DEF_OP(Vector_FToU) {
LOGMAN_MSG_A("Unimplemented");
}
DEF_OP(Vector_FToS) {
auto Op = IROp->C<IR::IROp_Vector_FToS>();
switch (Op->Header.ElementSize) {
@@ -213,14 +197,10 @@ void X86JITCore::RegisterConversionHandlers() {
#define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &X86JITCore::Op_##x
REGISTER_OP(VINSGPR, VInsGPR);
REGISTER_OP(VCASTFROMGPR, VCastFromGPR);
REGISTER_OP(FLOAT_FROMGPR_U, Float_FromGPR_U);
REGISTER_OP(FLOAT_FROMGPR_S, Float_FromGPR_S);
REGISTER_OP(FLOAT_FTOF, Float_FToF);
REGISTER_OP(VECTOR_UTOF, Vector_UToF);
REGISTER_OP(VECTOR_STOF, Vector_SToF);
REGISTER_OP(VECTOR_FTOZU, Vector_FToZU);
REGISTER_OP(VECTOR_FTOZS, Vector_FToZS);
REGISTER_OP(VECTOR_FTOU, Vector_FToU);
REGISTER_OP(VECTOR_FTOS, Vector_FToS);
REGISTER_OP(VECTOR_FTOF, Vector_FToF);
REGISTER_OP(VECTOR_FTOI, Vector_FToI);
@@ -241,9 +241,7 @@ private:
DEF_OP(Sbfe);
DEF_OP(Select);
DEF_OP(VExtractToGPR);
DEF_OP(Float_ToGPR_ZU);
DEF_OP(Float_ToGPR_ZS);
DEF_OP(Float_ToGPR_U);
DEF_OP(Float_ToGPR_S);
DEF_OP(FCmp);
DEF_OP(F80Cmp);
@@ -281,14 +279,11 @@ private:
///< Conversion ops
DEF_OP(VInsGPR);
DEF_OP(VCastFromGPR);
DEF_OP(Float_FromGPR_U);
DEF_OP(Float_FromGPR_S);
DEF_OP(Float_FToF);
DEF_OP(Vector_UToF);
DEF_OP(Vector_SToF);
DEF_OP(Vector_FToZU);
DEF_OP(Vector_FToZS);
DEF_OP(Vector_FToU);
DEF_OP(Vector_FToS);
DEF_OP(Vector_FToF);
DEF_OP(Vector_FToI);
+30 -62
View File
@@ -6163,16 +6163,13 @@ void OpDispatchBuilder::MOVDDUPOp(OpcodeArgs) {
StoreResult(FPRClass, Op, Res, -1);
}
template<size_t DstElementSize, bool Signed>
template<size_t DstElementSize>
void OpDispatchBuilder::CVTGPR_To_FPR(OpcodeArgs) {
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
size_t GPRSize = GetSrcSize(Op);
if (Signed)
Src = _Float_FromGPR_S(DstElementSize, GPRSize, Src);
else
Src = _Float_FromGPR_U(DstElementSize, GPRSize, Src);
Src = _Float_FromGPR_S(DstElementSize, GPRSize, Src);
OrderedNode *Dest = LoadSource_WithOpSize(FPRClass, Op, Op->Dest, 16, Op->Flags, -1);
@@ -6181,7 +6178,7 @@ void OpDispatchBuilder::CVTGPR_To_FPR(OpcodeArgs) {
StoreResult(FPRClass, Op, Src, -1);
}
template<size_t SrcElementSize, bool Signed, bool HostRoundingMode>
template<size_t SrcElementSize, bool HostRoundingMode>
void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) {
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
@@ -6189,32 +6186,18 @@ void OpDispatchBuilder::CVTFPR_To_GPR(OpcodeArgs) {
// Source Element size is determined by instruction
size_t GPRSize = GetDstSize(Op);
size_t ElementSize = SrcElementSize;
if (HostRoundingMode) {
if (Signed)
Src = _Float_ToGPR_S(Src, SrcElementSize);
else
Src = _Float_ToGPR_U(Src, SrcElementSize);
Src = _Float_ToGPR_S(Src, ElementSize, GPRSize);
}
else {
if (Signed)
Src = _Float_ToGPR_ZS(Src, SrcElementSize);
else
Src = _Float_ToGPR_ZU(Src, SrcElementSize);
}
if (GPRSize > SrcElementSize) {
if (Signed) {
Src = _Sext(SrcElementSize * 8, Src);
}
else {
Src = _Bfe(SrcElementSize * 8, 0, Src);
}
Src = _Float_ToGPR_ZS(Src, ElementSize, GPRSize);
}
StoreResult_WithOpSize(GPRClass, Op, Op->Dest, Src, GPRSize, -1);
}
template<size_t SrcElementSize, bool Signed, bool Widen>
template<size_t SrcElementSize, bool Widen>
void OpDispatchBuilder::Vector_CVT_Int_To_Float(OpcodeArgs) {
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
@@ -6225,15 +6208,12 @@ void OpDispatchBuilder::Vector_CVT_Int_To_Float(OpcodeArgs) {
ElementSize <<= 1;
}
if (Signed)
Src = _Vector_SToF(Src, Size, ElementSize);
else
Src = _Vector_UToF(Src, Size, ElementSize);
Src = _Vector_SToF(Src, Size, ElementSize);
StoreResult(FPRClass, Op, Src, -1);
}
template<size_t SrcElementSize, bool Signed, bool Narrow, bool HostRoundingMode>
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
void OpDispatchBuilder::Vector_CVT_Float_To_Int(OpcodeArgs) {
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
@@ -6246,16 +6226,10 @@ void OpDispatchBuilder::Vector_CVT_Float_To_Int(OpcodeArgs) {
}
if (HostRoundingMode) {
if (Signed)
Src = _Vector_FToS(Src, Size, ElementSize);
else
Src = _Vector_FToU(Src, Size, ElementSize);
Src = _Vector_FToS(Src, Size, ElementSize);
}
else {
if (Signed)
Src = _Vector_FToZS(Src, Size, ElementSize);
else
Src = _Vector_FToZU(Src, Size, ElementSize);
Src = _Vector_FToZS(Src, Size, ElementSize);
}
StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Src, Size, -1);
@@ -6317,7 +6291,7 @@ void OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs) {
StoreResult(FPRClass, Op, Dest, -1);
}
template<size_t SrcElementSize, bool Signed, bool Narrow, bool HostRoundingMode>
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) {
OrderedNode *Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags, -1);
@@ -6330,16 +6304,10 @@ void OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs) {
}
if (HostRoundingMode) {
if (Signed)
Src = _Vector_FToS(Src, Size, ElementSize);
else
Src = _Vector_FToU(Src, Size, ElementSize);
Src = _Vector_FToS(Src, Size, ElementSize);
}
else {
if (Signed)
Src = _Vector_FToZS(Src, Size, ElementSize);
else
Src = _Vector_FToZU(Src, Size, ElementSize);
Src = _Vector_FToZS(Src, Size, ElementSize);
}
StoreResult_WithOpSize(FPRClass, Op, Op->Dest, Src, Size, -1);
@@ -8846,8 +8814,8 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x28, 2, &OpDispatchBuilder::MOVUPSOp},
{0x2A, 1, &OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float<4, true, false>},
{0x2B, 1, &OpDispatchBuilder::MOVAPSOp},
{0x2C, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, false>},
{0x2D, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, true>},
{0x2C, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, false>},
{0x2D, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, true>},
{0x2E, 2, &OpDispatchBuilder::UCOMISxOp<4>},
{0x50, 1, &OpDispatchBuilder::MOVMSKOp<4>},
{0x51, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFSQRT, 4, false>},
@@ -8860,7 +8828,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x58, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFADD, 4>},
{0x59, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFMUL, 4>},
{0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<8, 4>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, false>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, false>},
{0x5C, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFSUB, 4>},
{0x5D, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFMIN, 4>},
{0x5E, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFDIV, 4>},
@@ -9072,17 +9040,17 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x12, 1, &OpDispatchBuilder::MOVSLDUPOp},
{0x16, 1, &OpDispatchBuilder::MOVSHDUPOp},
{0x19, 7, &OpDispatchBuilder::NOPOp},
{0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<4, true>},
{0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<4>},
{0x2B, 1, &OpDispatchBuilder::MOVVectorOp},
{0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true, false>},
{0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true, true>},
{0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, false>},
{0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<4, true>},
{0x51, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFSQRT, 4, true>},
{0x52, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFRSQRT, 4, true>},
{0x53, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFRECP, 4, true>},
{0x58, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFADD, 4>},
{0x59, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFMUL, 4>},
{0x5A, 1, &OpDispatchBuilder::Scalar_CVT_Float_To_Float<8, 4>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, false>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, false>},
{0x5C, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFSUB, 4>},
{0x5D, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFMIN, 4>},
{0x5E, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFDIV, 4>},
@@ -9096,17 +9064,17 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0xBD, 1, &OpDispatchBuilder::LZCNT},
{0xC2, 1, &OpDispatchBuilder::VFCMPOp<4, true>},
{0xD6, 1, &OpDispatchBuilder::MOVQ2DQ<true>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true, true>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Int_To_Float<4, true>},
};
const std::vector<std::tuple<uint8_t, uint8_t, FEXCore::X86Tables::OpDispatchPtr>> RepNEModOpTable = {
{0x10, 2, &OpDispatchBuilder::MOVSDOp},
{0x12, 1, &OpDispatchBuilder::MOVDDUPOp},
{0x19, 7, &OpDispatchBuilder::NOPOp},
{0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<8, true>},
{0x2A, 1, &OpDispatchBuilder::CVTGPR_To_FPR<8>},
{0x2B, 1, &OpDispatchBuilder::MOVVectorOp},
{0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true, false>},
{0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true, true>},
{0x2C, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, false>},
{0x2D, 1, &OpDispatchBuilder::CVTFPR_To_GPR<8, true>},
{0x51, 1, &OpDispatchBuilder::VectorUnaryOp<IR::OP_VFSQRT, 8, true>},
//x52 = Invalid
{0x58, 1, &OpDispatchBuilder::VectorScalarALUOp<IR::OP_VFADD, 8>},
@@ -9122,7 +9090,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0xD0, 1, &OpDispatchBuilder::ADDSUBPOp<4>},
{0xD6, 1, &OpDispatchBuilder::MOVQ2DQ<false>},
{0xC2, 1, &OpDispatchBuilder::VFCMPOp<8, true>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true, true>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true>},
{0xF0, 1, &OpDispatchBuilder::MOVVectorOp},
};
@@ -9136,8 +9104,8 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x28, 2, &OpDispatchBuilder::MOVAPSOp},
{0x2A, 1, &OpDispatchBuilder::MMX_To_XMM_Vector_CVT_Int_To_Float<4, true, true>},
{0x2B, 1, &OpDispatchBuilder::MOVAPSOp},
{0x2C, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true, false>},
{0x2D, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true, true>},
{0x2C, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, false>},
{0x2D, 1, &OpDispatchBuilder::XMM_To_MMX_Vector_CVT_Float_To_Int<8, true, true>},
{0x2E, 2, &OpDispatchBuilder::UCOMISxOp<8>},
{0x40, 16, &OpDispatchBuilder::CMOVOp},
@@ -9150,7 +9118,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0x58, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFADD, 8>},
{0x59, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFMUL, 8>},
{0x5A, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Float<4, 8>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, true, false, true>},
{0x5B, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<4, false, true>},
{0x5C, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFSUB, 8>},
{0x5D, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFMIN, 8>},
{0x5E, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VFDIV, 8>},
@@ -9208,7 +9176,7 @@ void InstallOpcodeHandlers(Context::OperatingMode Mode) {
{0xE3, 1, &OpDispatchBuilder::PAVGOp<2>},
{0xE4, 1, &OpDispatchBuilder::PMULHW<false>},
{0xE5, 1, &OpDispatchBuilder::PMULHW<true>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, true, false>},
{0xE6, 1, &OpDispatchBuilder::Vector_CVT_Float_To_Int<8, true, false>},
{0xE7, 1, &OpDispatchBuilder::MOVVectorOp},
{0xE8, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VSQSUB, 1>},
{0xE9, 1, &OpDispatchBuilder::VectorALUOp<IR::OP_VSQSUB, 2>},
+5 -5
View File
@@ -287,21 +287,21 @@ public:
template<size_t ElementSize>
void PAVGOp(OpcodeArgs);
void MOVDDUPOp(OpcodeArgs);
template<size_t DstElementSize, bool Signed>
template<size_t DstElementSize>
void CVTGPR_To_FPR(OpcodeArgs);
template<size_t SrcElementSize, bool Signed, bool HostRoundingMode>
template<size_t SrcElementSize, bool HostRoundingMode>
void CVTFPR_To_GPR(OpcodeArgs);
template<size_t SrcElementSize, bool Signed, bool Widen>
template<size_t SrcElementSize, bool Widen>
void Vector_CVT_Int_To_Float(OpcodeArgs);
template<size_t DstElementSize, size_t SrcElementSize>
void Scalar_CVT_Float_To_Float(OpcodeArgs);
template<size_t DstElementSize, size_t SrcElementSize>
void Vector_CVT_Float_To_Float(OpcodeArgs);
template<size_t SrcElementSize, bool Signed, bool Narrow, bool HostRoundingMode>
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
void Vector_CVT_Float_To_Int(OpcodeArgs);
template<size_t SrcElementSize, bool Signed, bool Widen>
void MMX_To_XMM_Vector_CVT_Int_To_Float(OpcodeArgs);
template<size_t SrcElementSize, bool Signed, bool Narrow, bool HostRoundingMode>
template<size_t SrcElementSize, bool Narrow, bool HostRoundingMode>
void XMM_To_MMX_Vector_CVT_Float_To_Int(OpcodeArgs);
void MASKMOVOp(OpcodeArgs);
void MOVBetweenGPR_FPR(OpcodeArgs);
+9 -95
View File
@@ -1483,24 +1483,6 @@
]
},
"Float_ToGPR_U": {
"Desc": ["Moves the scalar element to a GPR with conversion",
"Converts the 32bit or 64bit float to an unsigned integer",
"Rounding mode determined by host flag's rounding mode"
],
"OpClass": "ALU",
"HasDest": true,
"DestClass": "GPR",
"DestSize": "ElementSize",
"SSAArgs": "1",
"SSANames": [
"Scalar"
],
"Args": [
"uint8_t", "ElementSize"
]
},
"Float_ToGPR_S": {
"Desc": ["Moves the scalar element to a GPR with conversion",
"Converts the 32bit or 64bit float to an signed integer",
@@ -1509,30 +1491,16 @@
"OpClass": "ALU",
"HasDest": true,
"DestClass": "GPR",
"DestSize": "ElementSize",
"DestSize": "DestElementSize",
"SSAArgs": "1",
"SSANames": [
"Scalar"
],
"Args": [
"uint8_t", "ElementSize"
]
},
"Float_ToGPR_ZU": {
"Desc": ["Moves the scalar element to a GPR with conversion",
"Converts the 32bit or 64bit float to an unsigned integer rounding towards zero (Truncating)"
],
"OpClass": "ALU",
"HasDest": true,
"DestClass": "GPR",
"DestSize": "ElementSize",
"SSAArgs": "1",
"SSANames": [
"Scalar"
"HelperArgs": [
"uint8_t", "DestElementSize"
],
"Args": [
"uint8_t", "ElementSize"
"uint8_t", "SrcElementSize"
]
},
@@ -1543,13 +1511,16 @@
"OpClass": "ALU",
"HasDest": true,
"DestClass": "GPR",
"DestSize": "ElementSize",
"DestSize": "DestElementSize",
"SSAArgs": "1",
"SSANames": [
"Scalar"
],
"HelperArgs": [
"uint8_t", "DestElementSize"
],
"Args": [
"uint8_t", "ElementSize"
"uint8_t", "SrcElementSize"
]
},
@@ -3049,27 +3020,6 @@
]
},
"Float_FromGPR_U": {
"OpClass": "Conv",
"Desc": ["Scalar op: Converts unsigned GPR to Scalar float",
"Zeroes the upper bits of the vector register"
],
"HasDest": true,
"DestClass": "FPR",
"DestSize": "DstElementSize",
"NumElements": "1",
"SSAArgs": "1",
"SSANames": [
"GPR"
],
"HelperArgs": [
"uint8_t", "DstElementSize"
],
"Args": [
"uint8_t", "SrcElementSize"
]
},
"Float_FromGPR_S": {
"OpClass": "Conv",
"Desc": ["Scalar op: Converts signed GPR to Scalar float",
@@ -3146,25 +3096,6 @@
]
},
"Vector_FToU": {
"OpClass": "Conv",
"Desc": ["Vector op: Converts float to unsigned integer",
"Rounding mode determined by host rounding mode"
],
"HasDest": true,
"DestClass": "FPR",
"DestSize": "RegisterSize",
"NumElements": "RegisterSize / ElementSize",
"SSAArgs": "1",
"SSANames": [
"Vector"
],
"HelperArgs": [
"uint8_t", "RegisterSize",
"uint8_t", "ElementSize"
]
},
"Vector_FToS": {
"OpClass": "Conv",
"Desc": ["Vector op: Converts float to signed integer, rounding towards zero",
@@ -3184,23 +3115,6 @@
]
},
"Vector_FToZU": {
"OpClass": "Conv",
"Desc": "Vector op: Converts float to unsigned integer, rounding towards zero",
"HasDest": true,
"DestClass": "FPR",
"DestSize": "RegisterSize",
"NumElements": "RegisterSize / ElementSize",
"SSAArgs": "1",
"SSANames": [
"Vector"
],
"HelperArgs": [
"uint8_t", "RegisterSize",
"uint8_t", "ElementSize"
]
},
"Vector_FToZS": {
"OpClass": "Conv",
"Desc": "Vector op: Converts float to signed integer, rounding towards zero",
-3
View File
@@ -315,9 +315,6 @@ friend class FEXCore::IR::PassManager;
IRPair<IROp_Vector_FToF> _Vector_FToF(uint8_t RegisterSize, uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) {
return _Vector_FToF(ssa0, SrcElementSize, RegisterSize, DstElementSize);
}
IRPair<IROp_Float_FromGPR_U> _Float_FromGPR_U(uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) {
return _Float_FromGPR_U(ssa0, SrcElementSize, DstElementSize);
}
IRPair<IROp_Float_FromGPR_S> _Float_FromGPR_S(uint8_t DstElementSize, uint8_t SrcElementSize, OrderedNode *ssa0) {
return _Float_FromGPR_S(ssa0, SrcElementSize, DstElementSize);
}