Add SMULL (vector), USHR (scalar), FCCMPE, FNMSUB, fixed a some instructions
This commit is contained in:
parent
01b7538560
commit
b4a1cfde10
10 changed files with 205 additions and 130 deletions
|
@ -47,6 +47,7 @@ namespace ChocolArm64
|
||||||
Set("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
|
Set("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
|
||||||
Set("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
|
Set("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
|
||||||
Set("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
|
Set("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
|
||||||
|
Set("x1001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eon, typeof(AOpCodeAluRs));
|
||||||
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
||||||
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
||||||
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
||||||
|
@ -147,6 +148,7 @@ namespace ChocolArm64
|
||||||
Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
|
||||||
Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
|
Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
|
Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
|
||||||
|
Set("00011110xx1xxxxxxxxx01xxxxx1xxxx", AInstEmit.Fccmpe_S, typeof(AOpCodeSimdFcond));
|
||||||
Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx001000xxxxx1x000", AInstEmit.Fcmpe_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
|
Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
|
||||||
|
@ -183,6 +185,7 @@ namespace ChocolArm64
|
||||||
Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
|
Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElem));
|
Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElem));
|
||||||
Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg));
|
||||||
|
Set("00011111xx1xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fnmsub_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
||||||
Set("00011110xx100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
Set("00011110xx100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
||||||
|
@ -225,6 +228,7 @@ namespace ChocolArm64
|
||||||
Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
|
Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
|
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
||||||
|
Set("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
|
Set("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||||
|
@ -251,6 +255,7 @@ namespace ChocolArm64
|
||||||
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
|
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
|
||||||
Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
||||||
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
||||||
|
Set("011111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
||||||
|
|
|
@ -107,6 +107,16 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStintzr(Op.Rd);
|
Context.EmitStintzr(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Eon(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitDataLoadOpers(Context);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Not);
|
||||||
|
Context.Emit(OpCodes.Xor);
|
||||||
|
|
||||||
|
EmitDataStore(Context);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor);
|
public static void Eor(AILEmitterCtx Context) => EmitDataOp(Context, OpCodes.Xor);
|
||||||
|
|
||||||
public static void Extr(AILEmitterCtx Context)
|
public static void Extr(AILEmitterCtx Context)
|
||||||
|
|
|
@ -145,5 +145,24 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStint(Op.Rd);
|
Context.EmitStint(Op.Rd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV)
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I4((NZCV >> 0) & 1);
|
||||||
|
|
||||||
|
Context.EmitStflg((int)APState.VBit);
|
||||||
|
|
||||||
|
Context.EmitLdc_I4((NZCV >> 1) & 1);
|
||||||
|
|
||||||
|
Context.EmitStflg((int)APState.CBit);
|
||||||
|
|
||||||
|
Context.EmitLdc_I4((NZCV >> 2) & 1);
|
||||||
|
|
||||||
|
Context.EmitStflg((int)APState.ZBit);
|
||||||
|
|
||||||
|
Context.EmitLdc_I4((NZCV >> 3) & 1);
|
||||||
|
|
||||||
|
Context.EmitStflg((int)APState.NBit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -36,7 +36,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
if (Op.Pos + 1 == BitsCount)
|
if (Op.Pos + 1 == BitsCount)
|
||||||
{
|
{
|
||||||
EmitBfmShift(Context, OpCodes.Shr);
|
EmitSbfmShift(Context);
|
||||||
}
|
}
|
||||||
else if (Op.Pos < Op.Shift)
|
else if (Op.Pos < Op.Shift)
|
||||||
{
|
{
|
||||||
|
@ -87,7 +87,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
if (Op.Pos + 1 == Op.GetBitsCount())
|
if (Op.Pos + 1 == Op.GetBitsCount())
|
||||||
{
|
{
|
||||||
EmitBfmShift(Context, OpCodes.Shr_Un);
|
EmitUbfmShift(Context);
|
||||||
}
|
}
|
||||||
else if (Op.Pos < Op.Shift)
|
else if (Op.Pos < Op.Shift)
|
||||||
{
|
{
|
||||||
|
@ -166,19 +166,28 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStintzr(Op.Rd);
|
Context.EmitStintzr(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitBfmShift(AILEmitterCtx Context, OpCode ILOp)
|
private static void EmitSbfmShift(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitBfmShift(Context, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitUbfmShift(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitBfmShift(Context, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
|
||||||
{
|
{
|
||||||
AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
|
AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
|
||||||
|
|
||||||
if (Op.Shift > 0)
|
Context.EmitLdintzr(Op.Rn);
|
||||||
{
|
Context.EmitLdc_I4(Op.Shift);
|
||||||
Context.EmitLdintzr(Op.Rn);
|
|
||||||
Context.EmitLdc_I4(Op.Shift);
|
|
||||||
|
|
||||||
Context.Emit(ILOp);
|
Context.Emit(Signed
|
||||||
|
? OpCodes.Shr
|
||||||
|
: OpCodes.Shr_Un);
|
||||||
|
|
||||||
Context.EmitStintzr(Op.Rd);
|
Context.EmitStintzr(Op.Rd);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitBfmLsl(AILEmitterCtx Context)
|
private static void EmitBfmLsl(AILEmitterCtx Context)
|
||||||
|
|
|
@ -215,6 +215,24 @@ namespace ChocolArm64.Instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fnmsub_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
|
EmitVectorExtractF(Context, Op.Rn, 0, SizeF);
|
||||||
|
EmitVectorExtractF(Context, Op.Rm, 0, SizeF);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Mul);
|
||||||
|
|
||||||
|
EmitVectorExtractF(Context, Op.Ra, 0, SizeF);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Sub);
|
||||||
|
|
||||||
|
EmitScalarSetF(Context, Op.Rd, SizeF);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Frinta_S(AILEmitterCtx Context)
|
public static void Frinta_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
@ -282,7 +300,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Saddw_V(AILEmitterCtx Context)
|
public static void Saddw_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorWidenBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
|
EmitVectorWidenRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Add));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Smax_V(AILEmitterCtx Context)
|
public static void Smax_V(AILEmitterCtx Context)
|
||||||
|
@ -303,6 +321,11 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
|
EmitVectorBinaryOpSx(Context, () => Context.EmitCall(MthdInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Smull_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Sub_S(AILEmitterCtx Context)
|
public static void Sub_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
|
EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
|
||||||
|
@ -333,7 +356,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Uaddw_V(AILEmitterCtx Context)
|
public static void Uaddw_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorWidenBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
|
EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@ using ChocolArm64.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
|
using static ChocolArm64.Instruction.AInstEmitAluHelper;
|
||||||
using static ChocolArm64.Instruction.AInstEmitSimdHelper;
|
using static ChocolArm64.Instruction.AInstEmitSimdHelper;
|
||||||
|
|
||||||
namespace ChocolArm64.Instruction
|
namespace ChocolArm64.Instruction
|
||||||
|
@ -54,24 +55,9 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
Context.EmitCondBranch(LblTrue, Op.Cond);
|
Context.EmitCondBranch(LblTrue, Op.Cond);
|
||||||
|
|
||||||
//TODO: Share this logic with Ccmp.
|
EmitSetNZCV(Context, Op.NZCV);
|
||||||
Context.EmitLdc_I4((Op.NZCV >> 0) & 1);
|
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.VBit);
|
Context.Emit(OpCodes.Br, LblEnd);
|
||||||
|
|
||||||
Context.EmitLdc_I4((Op.NZCV >> 1) & 1);
|
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.CBit);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4((Op.NZCV >> 2) & 1);
|
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.ZBit);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4((Op.NZCV >> 3) & 1);
|
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.NBit);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Br_S, LblEnd);
|
|
||||||
|
|
||||||
Context.MarkLabel(LblTrue);
|
Context.MarkLabel(LblTrue);
|
||||||
|
|
||||||
|
@ -80,12 +66,35 @@ namespace ChocolArm64.Instruction
|
||||||
Context.MarkLabel(LblEnd);
|
Context.MarkLabel(LblEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fccmpe_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
Fccmp_S(Context);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fcmp_S(AILEmitterCtx Context)
|
public static void Fcmp_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
|
bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;
|
||||||
|
|
||||||
|
//Handle NaN case. If any number is NaN, then NZCV = 0011.
|
||||||
|
if (CmpWithZero)
|
||||||
|
{
|
||||||
|
EmitNaNCheck(Context, Op.Rn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitNaNCheck(Context, Op.Rn);
|
||||||
|
EmitNaNCheck(Context, Op.Rm);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Or);
|
||||||
|
}
|
||||||
|
|
||||||
|
AILLabel LblNaN = new AILLabel();
|
||||||
|
AILLabel LblEnd = new AILLabel();
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Brtrue_S, LblNaN);
|
||||||
|
|
||||||
void EmitLoadOpers()
|
void EmitLoadOpers()
|
||||||
{
|
{
|
||||||
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
|
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
|
||||||
|
@ -123,30 +132,18 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.NBit);
|
Context.EmitStflg((int)APState.NBit);
|
||||||
|
|
||||||
//Handle NaN case. If any number is NaN, then NZCV = 0011.
|
//V = 0
|
||||||
AILLabel LblNotNaN = new AILLabel();
|
Context.EmitLdc_I4(0);
|
||||||
|
|
||||||
if (CmpWithZero)
|
|
||||||
{
|
|
||||||
EmitNaNCheck(Context, Op.Rn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EmitNaNCheck(Context, Op.Rn);
|
|
||||||
EmitNaNCheck(Context, Op.Rm);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Or);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Brfalse_S, LblNotNaN);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4(1);
|
|
||||||
Context.EmitLdc_I4(1);
|
|
||||||
|
|
||||||
Context.EmitStflg((int)APState.CBit);
|
|
||||||
Context.EmitStflg((int)APState.VBit);
|
Context.EmitStflg((int)APState.VBit);
|
||||||
|
|
||||||
Context.MarkLabel(LblNotNaN);
|
Context.Emit(OpCodes.Br_S, LblEnd);
|
||||||
|
|
||||||
|
Context.MarkLabel(LblNaN);
|
||||||
|
|
||||||
|
EmitSetNZCV(Context, 0b0011);
|
||||||
|
|
||||||
|
Context.MarkLabel(LblEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Fcmpe_S(AILEmitterCtx Context)
|
public static void Fcmpe_S(AILEmitterCtx Context)
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
EmitVectorExtractSx(Context, Op.Rd, 0, Op.Size + 2);
|
EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size + 2);
|
||||||
|
|
||||||
EmitFloatCast(Context, Op.Size);
|
EmitFloatCast(Context, Op.Size);
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
|
public static void EmitScalarOp(AILEmitterCtx Context, Action Emit, OperFlags Opers, bool Signed)
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
if (Opers.HasFlag(OperFlags.Rd))
|
if (Opers.HasFlag(OperFlags.Rd))
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
if (Opers.HasFlag(OperFlags.Rm))
|
if (Opers.HasFlag(OperFlags.Rm))
|
||||||
{
|
{
|
||||||
EmitVectorExtract(Context, Op.Rm, 0, Op.Size, Signed);
|
EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, 0, Op.Size, Signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
Emit();
|
Emit();
|
||||||
|
@ -383,17 +383,17 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitVectorWidenBinaryOpSx(AILEmitterCtx Context, Action Emit)
|
public static void EmitVectorWidenRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
|
||||||
{
|
{
|
||||||
EmitVectorWidenBinaryOp(Context, Emit, true);
|
EmitVectorWidenRmBinaryOp(Context, Emit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitVectorWidenBinaryOpZx(AILEmitterCtx Context, Action Emit)
|
public static void EmitVectorWidenRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
|
||||||
{
|
{
|
||||||
EmitVectorWidenBinaryOp(Context, Emit, false);
|
EmitVectorWidenRmBinaryOp(Context, Emit, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitVectorWidenBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
|
public static void EmitVectorWidenRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
|
@ -415,6 +415,38 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorWidenRnRmBinaryOpSx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitVectorWidenRnRmBinaryOp(Context, Emit, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorWidenRnRmBinaryOpZx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitVectorWidenRnRmBinaryOp(Context, Emit, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorWidenRnRmBinaryOp(AILEmitterCtx Context, Action Emit, bool Signed)
|
||||||
|
{
|
||||||
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
|
int Elems = 8 >> Op.Size;
|
||||||
|
|
||||||
|
int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
|
{
|
||||||
|
EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);
|
||||||
|
EmitVectorExtract(Context, Op.Rm, Part + Index, Op.Size, Signed);
|
||||||
|
|
||||||
|
Emit();
|
||||||
|
|
||||||
|
EmitVectorInsertTmp(Context, Index, Op.Size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.EmitLdvectmp();
|
||||||
|
Context.EmitStvec(Op.Rd);
|
||||||
|
}
|
||||||
|
|
||||||
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
|
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
|
||||||
{
|
{
|
||||||
EmitVectorZeroAll(Context, Reg);
|
EmitVectorZeroAll(Context, Reg);
|
||||||
|
|
|
@ -10,15 +10,6 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
static partial class AInstEmit
|
static partial class AInstEmit
|
||||||
{
|
{
|
||||||
[Flags]
|
|
||||||
private enum ShrFlags
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Signed = 1 << 0,
|
|
||||||
Rounding = 1 << 1,
|
|
||||||
Accumulate = 1 << 2
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Shl_S(AILEmitterCtx Context)
|
public static void Shl_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
@ -100,14 +91,43 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
|
EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Ushr_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
EmitScalarUnaryOpZx(Context, () =>
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I4(GetImmShr(Op));
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Shr_Un);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static void Ushr_V(AILEmitterCtx Context)
|
public static void Ushr_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorShr(Context, ShrFlags.None);
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
EmitVectorUnaryOpZx(Context, () =>
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I4(GetImmShr(Op));
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Shr_Un);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Usra_V(AILEmitterCtx Context)
|
public static void Usra_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorShr(Context, ShrFlags.Accumulate);
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
Action Emit = () =>
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I4(GetImmShr(Op));
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Shr_Un);
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
|
private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
|
||||||
|
@ -173,35 +193,6 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags)
|
|
||||||
{
|
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
|
||||||
|
|
||||||
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
|
|
||||||
|
|
||||||
if (Flags.HasFlag(ShrFlags.Accumulate))
|
|
||||||
{
|
|
||||||
Action Emit = () =>
|
|
||||||
{
|
|
||||||
Context.EmitLdc_I4(Shift);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Shr_Un);
|
|
||||||
Context.Emit(OpCodes.Add);
|
|
||||||
};
|
|
||||||
|
|
||||||
EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EmitVectorUnaryOpZx(Context, () =>
|
|
||||||
{
|
|
||||||
Context.EmitLdc_I4(Shift);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Shr_Un);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
||||||
{
|
{
|
||||||
EmitVectorShImmBinaryOp(Context, Emit, Imm, true);
|
EmitVectorShImmBinaryOp(Context, Emit, Imm, true);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using ChocolArm64.Translation;
|
using ChocolArm64.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace ChocolArm64.Instruction
|
namespace ChocolArm64.Instruction
|
||||||
|
@ -101,6 +102,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static int SatF32ToS32(float Value)
|
public static int SatF32ToS32(float Value)
|
||||||
{
|
{
|
||||||
|
if (float.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > int.MaxValue ? int.MaxValue :
|
return Value > int.MaxValue ? int.MaxValue :
|
||||||
Value < int.MinValue ? int.MinValue : (int)Value;
|
Value < int.MinValue ? int.MinValue : (int)Value;
|
||||||
}
|
}
|
||||||
|
@ -108,6 +111,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static long SatF32ToS64(float Value)
|
public static long SatF32ToS64(float Value)
|
||||||
{
|
{
|
||||||
|
if (float.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > long.MaxValue ? long.MaxValue :
|
return Value > long.MaxValue ? long.MaxValue :
|
||||||
Value < long.MinValue ? long.MinValue : (long)Value;
|
Value < long.MinValue ? long.MinValue : (long)Value;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +120,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static uint SatF32ToU32(float Value)
|
public static uint SatF32ToU32(float Value)
|
||||||
{
|
{
|
||||||
|
if (float.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > uint.MaxValue ? uint.MaxValue :
|
return Value > uint.MaxValue ? uint.MaxValue :
|
||||||
Value < uint.MinValue ? uint.MinValue : (uint)Value;
|
Value < uint.MinValue ? uint.MinValue : (uint)Value;
|
||||||
}
|
}
|
||||||
|
@ -122,6 +129,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong SatF32ToU64(float Value)
|
public static ulong SatF32ToU64(float Value)
|
||||||
{
|
{
|
||||||
|
if (float.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > ulong.MaxValue ? ulong.MaxValue :
|
return Value > ulong.MaxValue ? ulong.MaxValue :
|
||||||
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
|
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
|
||||||
}
|
}
|
||||||
|
@ -129,6 +138,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static int SatF64ToS32(double Value)
|
public static int SatF64ToS32(double Value)
|
||||||
{
|
{
|
||||||
|
if (double.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > int.MaxValue ? int.MaxValue :
|
return Value > int.MaxValue ? int.MaxValue :
|
||||||
Value < int.MinValue ? int.MinValue : (int)Value;
|
Value < int.MinValue ? int.MinValue : (int)Value;
|
||||||
}
|
}
|
||||||
|
@ -136,6 +147,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static long SatF64ToS64(double Value)
|
public static long SatF64ToS64(double Value)
|
||||||
{
|
{
|
||||||
|
if (double.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > long.MaxValue ? long.MaxValue :
|
return Value > long.MaxValue ? long.MaxValue :
|
||||||
Value < long.MinValue ? long.MinValue : (long)Value;
|
Value < long.MinValue ? long.MinValue : (long)Value;
|
||||||
}
|
}
|
||||||
|
@ -143,6 +156,8 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static uint SatF64ToU32(double Value)
|
public static uint SatF64ToU32(double Value)
|
||||||
{
|
{
|
||||||
|
if (double.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > uint.MaxValue ? uint.MaxValue :
|
return Value > uint.MaxValue ? uint.MaxValue :
|
||||||
Value < uint.MinValue ? uint.MinValue : (uint)Value;
|
Value < uint.MinValue ? uint.MinValue : (uint)Value;
|
||||||
}
|
}
|
||||||
|
@ -150,46 +165,20 @@ namespace ChocolArm64.Instruction
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong SatF64ToU64(double Value)
|
public static ulong SatF64ToU64(double Value)
|
||||||
{
|
{
|
||||||
|
if (double.IsNaN(Value)) return 0;
|
||||||
|
|
||||||
return Value > ulong.MaxValue ? ulong.MaxValue :
|
return Value > ulong.MaxValue ? ulong.MaxValue :
|
||||||
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
|
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong SMulHi128(ulong LHS, ulong RHS)
|
public static long SMulHi128(long LHS, long RHS)
|
||||||
{
|
{
|
||||||
long LLo = (uint)(LHS >> 0);
|
return (long)(BigInteger.Multiply(LHS, RHS) >> 64);
|
||||||
long LHi = (int)(LHS >> 32);
|
|
||||||
long RLo = (uint)(RHS >> 0);
|
|
||||||
long RHi = (int)(RHS >> 32);
|
|
||||||
|
|
||||||
long LHiRHi = LHi * RHi;
|
|
||||||
long LHiRLo = LHi * RLo;
|
|
||||||
long LLoRHi = LLo * RHi;
|
|
||||||
long LLoRLo = LLo * RLo;
|
|
||||||
|
|
||||||
long Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32;
|
|
||||||
|
|
||||||
long ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry;
|
|
||||||
|
|
||||||
return (ulong)ResHi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong UMulHi128(ulong LHS, ulong RHS)
|
public static ulong UMulHi128(ulong LHS, ulong RHS)
|
||||||
{
|
{
|
||||||
ulong LLo = (uint)(LHS >> 0);
|
return (ulong)(BigInteger.Multiply(LHS, RHS) >> 64);
|
||||||
ulong LHi = (uint)(LHS >> 32);
|
|
||||||
ulong RLo = (uint)(RHS >> 0);
|
|
||||||
ulong RHi = (uint)(RHS >> 32);
|
|
||||||
|
|
||||||
ulong LHiRHi = LHi * RHi;
|
|
||||||
ulong LHiRLo = LHi * RLo;
|
|
||||||
ulong LLoRHi = LLo * RHi;
|
|
||||||
ulong LLoRLo = LLo * RLo;
|
|
||||||
|
|
||||||
ulong Carry = ((uint)LHiRLo + ((uint)LLoRHi + (LLoRLo >> 32))) >> 32;
|
|
||||||
|
|
||||||
ulong ResHi = LHiRHi + (LHiRLo >> 32) + (LLoRHi >> 32) + Carry;
|
|
||||||
|
|
||||||
return ResHi;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountSetBits8(byte Value)
|
public static int CountSetBits8(byte Value)
|
||||||
|
|
Reference in a new issue