Add FRSQRTS and FCM* instructions
This commit is contained in:
parent
39f20d8d1a
commit
f15b1c76a1
3 changed files with 208 additions and 18 deletions
|
@ -110,13 +110,84 @@ namespace ChocolArm64.Instruction
|
|||
Fccmp_S(Context);
|
||||
}
|
||||
|
||||
public static void Fcmeq_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Beq_S);
|
||||
}
|
||||
|
||||
public static void Fcmeq_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Beq_S);
|
||||
}
|
||||
|
||||
public static void Fcmge_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Bge_S);
|
||||
}
|
||||
|
||||
public static void Fcmge_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Bge_S);
|
||||
}
|
||||
|
||||
public static void Fcmgt_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Bgt_S);
|
||||
}
|
||||
|
||||
public static void Fcmgt_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Bgt_S);
|
||||
}
|
||||
|
||||
public static void Fcmhi_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Bgt_Un_S);
|
||||
}
|
||||
|
||||
public static void Fcmhi_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Bgt_Un_S);
|
||||
}
|
||||
|
||||
public static void Fcmhs_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Bge_Un_S);
|
||||
}
|
||||
|
||||
public static void Fcmhs_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Bge_Un_S);
|
||||
}
|
||||
|
||||
public static void Fcmle_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Ble_S);
|
||||
}
|
||||
|
||||
public static void Fcmle_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Ble_S);
|
||||
}
|
||||
|
||||
public static void Fcmlt_S(AILEmitterCtx Context)
|
||||
{
|
||||
EmitScalarFcmp(Context, OpCodes.Blt_S);
|
||||
}
|
||||
|
||||
public static void Fcmlt_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorFcmp(Context, OpCodes.Blt_S);
|
||||
}
|
||||
|
||||
public static void Fcmp_S(AILEmitterCtx Context)
|
||||
{
|
||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||
|
||||
bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
|
||||
|
||||
//Handle NaN case. If any number is NaN, then NZCV = 0011.
|
||||
//Handle NaN case.
|
||||
//If any number is NaN, then NZCV = 0011.
|
||||
if (CmpWithZero)
|
||||
{
|
||||
EmitNaNCheck(Context, Op.Rn);
|
||||
|
@ -140,7 +211,14 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
if (CmpWithZero)
|
||||
{
|
||||
EmitLdcImmF(Context, 0, Op.Size);
|
||||
if (Op.Size == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(0);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -190,22 +268,6 @@ namespace ChocolArm64.Instruction
|
|||
Fcmp_S(Context);
|
||||
}
|
||||
|
||||
private static void EmitLdcImmF(AILEmitterCtx Context, double ImmF, int Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Context.EmitLdc_R4((float)ImmF);
|
||||
}
|
||||
else if (Size == 1)
|
||||
{
|
||||
Context.EmitLdc_R8(ImmF);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitNaNCheck(AILEmitterCtx Context, int Reg)
|
||||
{
|
||||
IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;
|
||||
|
@ -268,5 +330,74 @@ namespace ChocolArm64.Instruction
|
|||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitScalarFcmp(AILEmitterCtx Context, OpCode ILOp)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
EmitFcmp(Context, ILOp, 0);
|
||||
|
||||
EmitScalarSetF(Context, Op.Rd, SizeF);
|
||||
}
|
||||
|
||||
private static void EmitVectorFcmp(AILEmitterCtx Context, OpCode ILOp)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||
|
||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||
{
|
||||
EmitFcmp(Context, ILOp, Index);
|
||||
}
|
||||
|
||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||
{
|
||||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitFcmp(AILEmitterCtx Context, OpCode ILOp, int Index)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int SizeF = Op.Size & 1;
|
||||
|
||||
ulong SzMask = ulong.MaxValue >> (64 - (32 << SizeF));
|
||||
|
||||
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||
|
||||
if (Op is AOpCodeSimdReg BinOp)
|
||||
{
|
||||
EmitVectorExtractF(Context, BinOp.Rm, Index, SizeF);
|
||||
}
|
||||
else if (SizeF == 0)
|
||||
{
|
||||
Context.EmitLdc_R4(0);
|
||||
}
|
||||
else /* if (SizeF == 1) */
|
||||
{
|
||||
Context.EmitLdc_R8(0);
|
||||
}
|
||||
|
||||
AILLabel LblTrue = new AILLabel();
|
||||
AILLabel LblEnd = new AILLabel();
|
||||
|
||||
Context.Emit(ILOp, LblTrue);
|
||||
|
||||
EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, 0);
|
||||
|
||||
Context.Emit(OpCodes.Br_S, LblEnd);
|
||||
|
||||
Context.MarkLabel(LblTrue);
|
||||
|
||||
EmitVectorInsert(Context, Op.Rd, Index, SizeF + 2, (long)SzMask);
|
||||
|
||||
Context.MarkLabel(LblEnd);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue