Fix Arm32 double to int/uint conversion on Arm64 (#5292)

* Fix Arm32 double to int/uint conversion on Arm64

* PPTC version bump
This commit is contained in:
gdkchan 2023-06-14 00:57:02 -03:00 committed by GitHub
parent 4d804ed45e
commit 105c9712c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 24 deletions

View file

@ -165,7 +165,7 @@ namespace ARMeilleure.Instructions
{ {
Operand m = GetVecA32(op.Vm >> 1); Operand m = GetVecA32(op.Vm >> 1);
Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, doubleSize); Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble; Intrinsic inst = (unsigned ? Intrinsic.Arm64FcvtzuGp : Intrinsic.Arm64FcvtzsGp) | Intrinsic.Arm64VDouble;
@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, unsigned ? Intrinsic.Arm64FcvtzuS : Intrinsic.Arm64FcvtzsS, false);
} }
} }
else if (!roundWithFpscr && Optimizations.UseSse41) else if (!roundWithFpscr && Optimizations.UseSse41)
@ -260,28 +260,64 @@ namespace ARMeilleure.Instructions
if (Optimizations.UseAdvSimd) if (Optimizations.UseAdvSimd)
{ {
if (unsigned) bool doubleSize = floatSize == OperandType.FP64;
if (doubleSize)
{ {
inst = rm switch { Operand m = GetVecA32(op.Vm >> 1);
0b00 => Intrinsic.Arm64FcvtauS,
0b01 => Intrinsic.Arm64FcvtnuS, Operand toConvert = InstEmitSimdHelper32Arm64.EmitExtractScalar(context, m, op.Vm, true);
0b10 => Intrinsic.Arm64FcvtpuS,
0b11 => Intrinsic.Arm64FcvtmuS, if (unsigned)
_ => throw new ArgumentOutOfRangeException(nameof(rm)) {
}; inst = rm switch {
0b00 => Intrinsic.Arm64FcvtauGp,
0b01 => Intrinsic.Arm64FcvtnuGp,
0b10 => Intrinsic.Arm64FcvtpuGp,
0b11 => Intrinsic.Arm64FcvtmuGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasGp,
0b01 => Intrinsic.Arm64FcvtnsGp,
0b10 => Intrinsic.Arm64FcvtpsGp,
0b11 => Intrinsic.Arm64FcvtmsGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
Operand asInteger = context.AddIntrinsicInt(inst | Intrinsic.Arm64VDouble, toConvert);
InsertScalar(context, op.Vd, asInteger);
} }
else else
{ {
inst = rm switch { if (unsigned)
0b00 => Intrinsic.Arm64FcvtasS, {
0b01 => Intrinsic.Arm64FcvtnsS, inst = rm switch {
0b10 => Intrinsic.Arm64FcvtpsS, 0b00 => Intrinsic.Arm64FcvtauS,
0b11 => Intrinsic.Arm64FcvtmsS, 0b01 => Intrinsic.Arm64FcvtnuS,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) 0b10 => Intrinsic.Arm64FcvtpuS,
}; 0b11 => Intrinsic.Arm64FcvtmuS,
} _ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
else
{
inst = rm switch {
0b00 => Intrinsic.Arm64FcvtasS,
0b01 => Intrinsic.Arm64FcvtnsS,
0b10 => Intrinsic.Arm64FcvtpsS,
0b11 => Intrinsic.Arm64FcvtmsS,
_ => throw new ArgumentOutOfRangeException(nameof(rm))
};
}
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
}
} }
else if (Optimizations.UseSse41) else if (Optimizations.UseSse41)
{ {

View file

@ -192,11 +192,10 @@ namespace ARMeilleure.Instructions
EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m)); EmitVectorTernaryOpSimd32(context, (d, n, m) => context.AddIntrinsic(inst, d, n, m));
} }
public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc) public static void EmitScalarUnaryOpSimd32(ArmEmitterContext context, Func1I scalarFunc, bool doubleSize)
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
bool doubleSize = (op.Size & 1) != 0;
int shift = doubleSize ? 1 : 2; int shift = doubleSize ? 1 : 2;
Operand m = GetVecA32(op.Vm >> shift); Operand m = GetVecA32(op.Vm >> shift);
Operand d = GetVecA32(op.Vd >> shift); Operand d = GetVecA32(op.Vd >> shift);
@ -215,8 +214,13 @@ namespace ARMeilleure.Instructions
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128; EmitScalarUnaryOpF32(context, inst, (op.Size & 1) != 0);
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m)); }
public static void EmitScalarUnaryOpF32(ArmEmitterContext context, Intrinsic inst, bool doubleSize)
{
inst |= (doubleSize ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
EmitScalarUnaryOpSimd32(context, (m) => (inst == 0) ? m : context.AddIntrinsic(inst, m), doubleSize);
} }
public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc) public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc)

View file

@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 5281; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 5292; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";