forked from Mirror/Ryujinx
Implement fixed-point variant of the UCVTF and SCVTF instructions (#578)
* Add fixed-point variant of the UCVTF instruction * Change encoding of some fixed-point instructions to not allow invalid encodings * Fix Fcvtzu_Gp_Fixed encoding * Add SCVTF (fixed-point GP to Scalar) instruction * Simplify *Fixed encodings
This commit is contained in:
parent
7ed2b4cc39
commit
9679896b94
3 changed files with 76 additions and 47 deletions
|
@ -8,18 +8,9 @@ namespace ChocolArm64.Decoders
|
|||
|
||||
public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||
{
|
||||
//TODO:
|
||||
//Und of Fixed Point variants.
|
||||
int scale = (opCode >> 10) & 0x3f;
|
||||
int sf = (opCode >> 31) & 0x1;
|
||||
|
||||
/*if (Type != SF && !(Type == 2 && SF == 1))
|
||||
{
|
||||
Emitter = AInstEmit.Und;
|
||||
|
||||
return;
|
||||
}*/
|
||||
|
||||
FBits = 64 - scale;
|
||||
|
||||
RegisterSize = sf != 0
|
||||
|
|
|
@ -244,7 +244,7 @@ namespace ChocolArm64.Instructions
|
|||
|
||||
public static void Fcvtzs_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtzs_Gp_Fix(context);
|
||||
EmitFcvtzs_Gp_Fixed(context);
|
||||
}
|
||||
|
||||
public static void Fcvtzs_S(ILEmitterCtx context)
|
||||
|
@ -264,7 +264,7 @@ namespace ChocolArm64.Instructions
|
|||
|
||||
public static void Fcvtzu_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtzu_Gp_Fix(context);
|
||||
EmitFcvtzu_Gp_Fixed(context);
|
||||
}
|
||||
|
||||
public static void Fcvtzu_S(ILEmitterCtx context)
|
||||
|
@ -293,6 +293,24 @@ namespace ChocolArm64.Instructions
|
|||
EmitScalarSetF(context, op.Rd, op.Size);
|
||||
}
|
||||
|
||||
public static void Scvtf_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
|
||||
|
||||
context.EmitLdintzr(op.Rn);
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_I4);
|
||||
}
|
||||
|
||||
EmitFloatCast(context, op.Size);
|
||||
|
||||
EmitI2fFBitsMul(context, op.Size, op.FBits);
|
||||
|
||||
EmitScalarSetF(context, op.Rd, op.Size);
|
||||
}
|
||||
|
||||
public static void Scvtf_S(ILEmitterCtx context)
|
||||
{
|
||||
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
|
||||
|
@ -349,6 +367,26 @@ namespace ChocolArm64.Instructions
|
|||
EmitScalarSetF(context, op.Rd, op.Size);
|
||||
}
|
||||
|
||||
public static void Ucvtf_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
|
||||
|
||||
context.EmitLdintzr(op.Rn);
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_U4);
|
||||
}
|
||||
|
||||
context.Emit(OpCodes.Conv_R_Un);
|
||||
|
||||
EmitFloatCast(context, op.Size);
|
||||
|
||||
EmitI2fFBitsMul(context, op.Size, op.FBits);
|
||||
|
||||
EmitScalarSetF(context, op.Rd, op.Size);
|
||||
}
|
||||
|
||||
public static void Ucvtf_S(ILEmitterCtx context)
|
||||
{
|
||||
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
|
||||
|
@ -367,32 +405,6 @@ namespace ChocolArm64.Instructions
|
|||
EmitVectorCvtf(context, signed: false);
|
||||
}
|
||||
|
||||
private static int GetFBits(ILEmitterCtx context)
|
||||
{
|
||||
if (context.CurrOp is OpCodeSimdShImm64 op)
|
||||
{
|
||||
return GetImmShr(op);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void EmitFloatCast(ILEmitterCtx context, int size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_R4);
|
||||
}
|
||||
else if (size == 1)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_R8);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar)
|
||||
{
|
||||
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
|
||||
|
@ -476,17 +488,17 @@ namespace ChocolArm64.Instructions
|
|||
context.EmitStintzr(op.Rd);
|
||||
}
|
||||
|
||||
private static void EmitFcvtzs_Gp_Fix(ILEmitterCtx context)
|
||||
private static void EmitFcvtzs_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtz__Gp_Fix(context, true);
|
||||
EmitFcvtz__Gp_Fixed(context, true);
|
||||
}
|
||||
|
||||
private static void EmitFcvtzu_Gp_Fix(ILEmitterCtx context)
|
||||
private static void EmitFcvtzu_Gp_Fixed(ILEmitterCtx context)
|
||||
{
|
||||
EmitFcvtz__Gp_Fix(context, false);
|
||||
EmitFcvtz__Gp_Fixed(context, false);
|
||||
}
|
||||
|
||||
private static void EmitFcvtz__Gp_Fix(ILEmitterCtx context, bool signed)
|
||||
private static void EmitFcvtz__Gp_Fixed(ILEmitterCtx context, bool signed)
|
||||
{
|
||||
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
|
||||
|
||||
|
@ -530,9 +542,7 @@ namespace ChocolArm64.Instructions
|
|||
context.Emit(OpCodes.Conv_R_Un);
|
||||
}
|
||||
|
||||
context.Emit(sizeF == 0
|
||||
? OpCodes.Conv_R4
|
||||
: OpCodes.Conv_R8);
|
||||
EmitFloatCast(context, sizeF);
|
||||
|
||||
EmitI2fFBitsMul(context, sizeF, fBits);
|
||||
|
||||
|
@ -644,6 +654,32 @@ namespace ChocolArm64.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
private static int GetFBits(ILEmitterCtx context)
|
||||
{
|
||||
if (context.CurrOp is OpCodeSimdShImm64 op)
|
||||
{
|
||||
return GetImmShr(op);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void EmitFloatCast(ILEmitterCtx context, int size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_R4);
|
||||
}
|
||||
else if (size == 1)
|
||||
{
|
||||
context.Emit(OpCodes.Conv_R8);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitScalarFcvts(ILEmitterCtx context, int size, int fBits)
|
||||
{
|
||||
if (size < 0 || size > 1)
|
||||
|
|
|
@ -310,12 +310,12 @@ namespace ChocolArm64
|
|||
SetA64("x00111100x101000000000xxxxxxxxxx", InstEmit.Fcvtps_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64("x00111100x101001000000xxxxxxxxxx", InstEmit.Fcvtpu_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64("x00111100x111000000000xxxxxxxxxx", InstEmit.Fcvtzs_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64("x00111100x011000xxxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64(">00111100x011000>xxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64("010111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzs_S, typeof(OpCodeSimd64));
|
||||
SetA64("0>0011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimd64));
|
||||
SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimdShImm64));
|
||||
SetA64("x00111100x111001000000xxxxxxxxxx", InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64("x00111100x011001xxxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64(">00111100x011001>xxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64("011111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzu_S, typeof(OpCodeSimd64));
|
||||
SetA64("0>1011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimd64));
|
||||
SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimdShImm64));
|
||||
|
@ -434,6 +434,7 @@ namespace ChocolArm64
|
|||
SetA64("0x001110<<100000001010xxxxxxxxxx", InstEmit.Saddlp_V, typeof(OpCodeSimd64));
|
||||
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstEmit.Saddw_V, typeof(OpCodeSimdReg64));
|
||||
SetA64("x00111100x100010000000xxxxxxxxxx", InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64("010111100x100001110110xxxxxxxxxx", InstEmit.Scvtf_S, typeof(OpCodeSimd64));
|
||||
SetA64("0>0011100<100001110110xxxxxxxxxx", InstEmit.Scvtf_V, typeof(OpCodeSimd64));
|
||||
SetA64("01011110000xxxxx000000xxxxxxxxxx", InstEmit.Sha1c_V, typeof(OpCodeSimdReg64));
|
||||
|
@ -542,6 +543,7 @@ namespace ChocolArm64
|
|||
SetA64("01101110<<110000001110xxxxxxxxxx", InstEmit.Uaddlv_V, typeof(OpCodeSimd64));
|
||||
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstEmit.Uaddw_V, typeof(OpCodeSimdReg64));
|
||||
SetA64("x00111100x100011000000xxxxxxxxxx", InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt64));
|
||||
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
|
||||
SetA64("011111100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_S, typeof(OpCodeSimd64));
|
||||
SetA64("0>1011100<100001110110xxxxxxxxxx", InstEmit.Ucvtf_V, typeof(OpCodeSimd64));
|
||||
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstEmit.Uhadd_V, typeof(OpCodeSimdReg64));
|
||||
|
|
Loading…
Reference in a new issue