private static void EmitCsel(AILEmitterCtx Context, CselOperation CselOp) { AOpCodeCsel Op = (AOpCodeCsel)Context.CurrOp; AILLabel LblTrue = new AILLabel(); AILLabel LblEnd = new AILLabel(); Context.EmitCondBranch(LblTrue, Op.Cond); Context.EmitLdintzr(Op.Rm); if (CselOp == CselOperation.Increment) { Context.EmitLdc_I(1); Context.Emit(OpCodes.Add); } else if (CselOp == CselOperation.Invert) { Context.Emit(OpCodes.Not); } else if (CselOp == CselOperation.Negate) { Context.Emit(OpCodes.Neg); } Context.Emit(OpCodes.Br_S, LblEnd); Context.MarkLabel(LblTrue); Context.EmitLdintzr(Op.Rn); Context.MarkLabel(LblEnd); Context.EmitStintzr(Op.Rd); }
public static void EmitDataLoadOper2(AILEmitterCtx Context) { switch (Context.CurrOp) { case IAOpCodeAluImm Op: Context.EmitLdc_I(Op.Imm); break; case IAOpCodeAluRs Op: Context.EmitLdintzr(Op.Rm); switch (Op.ShiftType) { case AShiftType.Lsl: Context.EmitLsl(Op.Shift); break; case AShiftType.Lsr: Context.EmitLsr(Op.Shift); break; case AShiftType.Asr: Context.EmitAsr(Op.Shift); break; case AShiftType.Ror: Context.EmitRor(Op.Shift); break; } break; case IAOpCodeAluRx Op: Context.EmitLdintzr(Op.Rm); Context.EmitCast(Op.IntType); Context.EmitLsl(Op.Shift); break; } }
private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair) { AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp; bool Ordered = (AccType & AccessType.Ordered) != 0; bool Exclusive = (AccType & AccessType.Exclusive) != 0; if (Ordered) { EmitBarrier(Context); } AILLabel LblEx = new AILLabel(); AILLabel LblEnd = new AILLabel(); if (Exclusive) { EmitMemoryCall(Context, nameof(AMemory.TestExclusive), Op.Rn); Context.Emit(OpCodes.Brtrue_S, LblEx); Context.EmitLdc_I8(1); Context.EmitStintzr(Op.Rs); Context.Emit(OpCodes.Br_S, LblEnd); } Context.MarkLabel(LblEx); Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdint(Op.Rn); Context.EmitLdintzr(Op.Rt); EmitWriteCall(Context, Op.Size); if (Pair) { Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdint(Op.Rn); Context.EmitLdc_I8(1 << Op.Size); Context.Emit(OpCodes.Add); Context.EmitLdintzr(Op.Rt2); EmitWriteCall(Context, Op.Size); } if (Exclusive) { Context.EmitLdc_I8(0); Context.EmitStintzr(Op.Rs); EmitMemoryCall(Context, nameof(AMemory.ClearExclusiveForStore)); } Context.MarkLabel(LblEnd); }
private static void EmitSse42Crc32(AILEmitterCtx Context, Type TCrc, Type TData) { AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdintzr(Op.Rm); Context.EmitCall(typeof(Sse42).GetMethod(nameof(Sse42.Crc32), new Type[] { TCrc, TData })); Context.EmitStintzr(Op.Rd); }
public static void Umulh(AILEmitterCtx Context) { AOpCodeMul Op = (AOpCodeMul)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdintzr(Op.Rm); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.UMulHi128)); Context.EmitStintzr(Op.Rd); }
public static void Sbfm(AILEmitterCtx Context) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; int BitsCount = Op.GetBitsCount(); if (Op.Pos + 1 == BitsCount) { EmitSbfmShift(Context); } else if (Op.Pos < Op.Shift) { EmitSbfiz(Context); } else if (Op.Pos == 7 && Op.Shift == 0) { EmitSbfmCast(Context, OpCodes.Conv_I1); } else if (Op.Pos == 15 && Op.Shift == 0) { EmitSbfmCast(Context, OpCodes.Conv_I2); } else if (Op.Pos == 31 && Op.Shift == 0) { EmitSbfmCast(Context, OpCodes.Conv_I4); } else if (Op.Shift == 0) { Context.EmitLdintzr(Op.Rn); Context.EmitLsl(BitsCount - 1 - Op.Pos); Context.EmitAsr(BitsCount - 1); Context.EmitStintzr(Op.Rd); } else { EmitBfmLoadRn(Context); Context.EmitLdintzr(Op.Rn); Context.EmitLsl(BitsCount - 1 - Op.Pos); Context.EmitAsr(BitsCount - 1); Context.EmitLdc_I(~Op.TMask); Context.Emit(OpCodes.And); Context.Emit(OpCodes.Or); Context.EmitStintzr(Op.Rd); } }
private static void EmitMul(AILEmitterCtx Context, OpCode ILOp) { AOpCodeMul Op = (AOpCodeMul)Context.CurrOp; Context.EmitLdintzr(Op.Ra); Context.EmitLdintzr(Op.Rn); Context.EmitLdintzr(Op.Rm); Context.Emit(OpCodes.Mul); Context.Emit(ILOp); Context.EmitStintzr(Op.Rd); }
public static void Msr(AILEmitterCtx Context) { AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitLdintzr(Op.Rt); string PropName; switch (GetPackedId(Op)) { case 0b11_011_0100_0100_000: PropName = nameof(AThreadState.Fpcr); break; case 0b11_011_0100_0100_001: PropName = nameof(AThreadState.Fpsr); break; case 0b11_011_1101_0000_010: PropName = nameof(AThreadState.TpidrEl0); break; default: throw new NotImplementedException($"Unknown MSR at {Op.Position:x16}"); } PropertyInfo PropInfo = typeof(AThreadState).GetProperty(PropName); if (PropInfo.PropertyType != typeof(long) && PropInfo.PropertyType != typeof(ulong)) { Context.Emit(OpCodes.Conv_U4); } Context.EmitCallPropSet(typeof(AThreadState), PropName); }
private static void EmitLoadAddress(AILEmitterCtx Context) { switch (Context.CurrOp) { case AOpCodeMemImm Op: Context.EmitLdint(Op.Rn); if (!Op.PostIdx) { //Pre-indexing. Context.EmitLdc_I(Op.Imm); Context.Emit(OpCodes.Add); } break; case AOpCodeMemReg Op: Context.EmitLdint(Op.Rn); Context.EmitLdintzr(Op.Rm); Context.EmitCast(Op.IntType); if (Op.Shift) { Context.EmitLsl(Op.Size); } Context.Emit(OpCodes.Add); break; } //Save address to Scratch var since the register value may change. Context.Emit(OpCodes.Dup); Context.EmitSttmp(); }
public static void Sys(AILEmitterCtx Context) { //This instruction is used to do some operations on the CPU like cache invalidation, //address translation and the like. //We treat it as no-op here since we don't have any cache being emulated anyway. AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp; switch (GetPackedId(Op)) { case 0b11_011_0111_0100_001: { //DC ZVA for (int Offs = 0; Offs < (4 << AThreadState.DczSizeLog2); Offs += 8) { Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdintzr(Op.Rt); Context.EmitLdc_I(Offs); Context.Emit(OpCodes.Add); Context.EmitLdc_I8(0); AInstEmitMemoryHelper.EmitWriteCall(Context, 3); } break; } //No-op case 0b11_011_0111_1110_001: //DC CIVAC break; } }
public static void Fmov_Itof(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitStvecsi(Op.Rd); }
public static void Br(AILEmitterCtx Context) { AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp; if (AOptimizations.GenerateCallStack) { Context.EmitLdarg(ATranslatedSub.StateArgIdx); Context.EmitLdintzr(Op.Rn); Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.JumpMethod)); } Context.EmitStoreState(); Context.EmitLdintzr(Op.Rn); Context.Emit(OpCodes.Ret); }
public static void Ins_Gp(AILEmitterCtx Context) { AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp; Context.EmitLdintzr(Op.Rn); EmitVectorInsert(Context, Op.Rd, Op.DstIndex, Op.Size); }
public static void Dup_Gp(AILEmitterCtx Context) { AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp; if (AOptimizations.UseSse2) { Context.EmitLdintzr(Op.Rn); switch (Op.Size) { case 0: Context.Emit(OpCodes.Conv_U1); break; case 1: Context.Emit(OpCodes.Conv_U2); break; case 2: Context.Emit(OpCodes.Conv_U4); break; } Type[] Types = new Type[] { UIntTypesPerSizeLog2[Op.Size] }; Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), Types)); EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size); if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } else { int Bytes = Op.GetBitsCount() >> 3; int Elems = Bytes >> Op.Size; for (int Index = 0; Index < Elems; Index++) { Context.EmitLdintzr(Op.Rn); EmitVectorInsert(Context, Op.Rd, Index, Op.Size); } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd); } } }
private static void EmitCb(AILEmitterCtx Context, OpCode ILOp) { AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp; Context.EmitLdintzr(Op.Rt); Context.EmitLdc_I(0); EmitBranch(Context, ILOp); }
public static void Br(AILEmitterCtx Context) { AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp; Context.EmitStoreState(); Context.EmitLdintzr(Op.Rn); Context.Emit(OpCodes.Ret); }
private static void EmitCb(AILEmitterCtx Context, OpCode ILOp) { AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp; Context.EmitLdintzr(Op.Rt); Context.EmitLdc_I(0); Context.Emit(ILOp, Context.GetLabel(Op.Imm)); }
private static void EmitBfmLsl(AILEmitterCtx Context) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLsl(Op.GetBitsCount() - Op.Shift); Context.EmitStintzr(Op.Rd); }
public static void Scvtf_Gp(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); EmitFloatCast(Context, Op.Size); Context.EmitStvecsf(Op.Rd); }
public static void Fmov_Itof(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); EmitIntZeroHigherIfNeeded(Context); EmitScalarSet(Context, Op.Rd, 3); }
public static void Fmov_Itof1(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); EmitIntZeroUpperIfNeeded(Context); EmitVectorInsert(Context, Op.Rd, 1, 3); }
public static void Rev64(AILEmitterCtx Context) { AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp; Context.EmitLdintzr(Op.Rn); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBytes64)); Context.EmitStintzr(Op.Rd); }
public static void Bfm(AILEmitterCtx Context) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; EmitBfmLoadRn(Context); Context.EmitLdintzr(Op.Rd); Context.EmitLdc_I(~Op.WMask & Op.TMask); Context.Emit(OpCodes.And); Context.Emit(OpCodes.Or); Context.EmitLdintzr(Op.Rd); Context.EmitLdc_I(~Op.TMask); Context.Emit(OpCodes.And); Context.Emit(OpCodes.Or); Context.EmitStintzr(Op.Rd); }
public static void Blr(AILEmitterCtx Context) { AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp; Context.EmitLdc_I(Op.Position + 4); Context.EmitStint(AThreadState.LRIndex); Context.EmitStoreState(); Context.EmitLdintzr(Op.Rn); Context.Emit(OpCodes.Ret); }
public static void Clz(AILEmitterCtx Context) { AOpCodeAlu Op = (AOpCodeAlu)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdc_I4(Op.RegisterSize == ARegisterSize.Int32 ? 32 : 64); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountLeadingZeros)); Context.EmitStintzr(Op.Rd); }
public static void Fmov_Itof1(AILEmitterCtx Context) { AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdc_I4(1); Context.EmitLdc_I4(3); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Fmov_S)); Context.EmitStvec(Op.Rd); }
private static void EmitBfmLoadRn(AILEmitterCtx Context) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitRor(Op.Shift); Context.EmitLdc_I(Op.WMask & Op.TMask); Context.Emit(OpCodes.And); }
private static void EmitCrc32(AILEmitterCtx Context, string Name) { AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp; Context.EmitLdintzr(Op.Rn); if (Op.RegisterSize != ARegisterSize.Int32) { Context.Emit(OpCodes.Conv_U4); } Context.EmitLdintzr(Op.Rm); ASoftFallback.EmitCall(Context, Name); if (Op.RegisterSize != ARegisterSize.Int32) { Context.Emit(OpCodes.Conv_U8); } Context.EmitStintzr(Op.Rd); }
private static void EmitBfmShift(AILEmitterCtx Context, bool Signed) { AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp; Context.EmitLdintzr(Op.Rn); Context.EmitLdc_I4(Op.Shift); Context.Emit(Signed ? OpCodes.Shr : OpCodes.Shr_Un); Context.EmitStintzr(Op.Rd); }
public static void Extr(AILEmitterCtx Context) { //TODO: Ensure that the Shift is valid for the Is64Bits. AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp; Context.EmitLdintzr(Op.Rm); if (Op.Shift > 0) { Context.EmitLdc_I4(Op.Shift); Context.Emit(OpCodes.Shr_Un); Context.EmitLdintzr(Op.Rn); Context.EmitLdc_I4(Op.GetBitsCount() - Op.Shift); Context.Emit(OpCodes.Shl); Context.Emit(OpCodes.Or); } EmitDataStore(Context); }