public static void Vmin_I(ArmEmitterContext context) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; if (op.U) { if (Optimizations.UseSse2) { EmitVectorBinaryOpSimd32(context, (op1, op2) => context.AddIntrinsic(X86PminuInstruction[op.Size], op1, op2)); } else { EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLessUI(op1, op2), op1, op2)); } } else { if (Optimizations.UseSse2) { EmitVectorBinaryOpSimd32(context, (op1, op2) => context.AddIntrinsic(X86PminsInstruction[op.Size], op1, op2)); } else { EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLess(op1, op2), op1, op2)); } } }
public static void Vmin_I(ArmEmitterContext context) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; if (op.U) { EmitVectorBinaryOpZx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLessUI(op1, op2), op1, op2)); } else { EmitVectorBinaryOpSx32(context, (op1, op2) => context.ConditionalSelect(context.ICompareLess(op1, op2), op1, op2)); } }
private static void EmitCsel(ArmEmitterContext context, CselOperation cselOp) { OpCodeCsel op = (OpCodeCsel)context.CurrOp; Operand n = GetIntOrZR(context, op.Rn); Operand m = GetIntOrZR(context, op.Rm); if (cselOp == CselOperation.Increment) { m = context.Add(m, Const(m.Type, 1)); } else if (cselOp == CselOperation.Invert) { m = context.BitwiseNot(m); } else if (cselOp == CselOperation.Negate) { m = context.Negate(m); } Operand condTrue = GetCondTrue(context, op.Cond); Operand d = context.ConditionalSelect(condTrue, n, m); SetIntOrZR(context, op.Rd, d); }
private static void EmitCmtstOp(ArmEmitterContext context, bool scalar) { OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; Operand res = context.VectorZero(); int elems = !scalar?op.GetBytesCount() >> op.Size : 1; ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size)); for (int index = 0; index < elems; index++) { Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size); Operand test = context.BitwiseAnd(ne, me); Operand isTrue = context.ICompareNotEqual(test, Const(0L)); Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L)); res = EmitVectorInsert(context, res, mask, index, op.Size); } context.Copy(GetVec(op.Rd), res); }
private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar) { OpCodeSimd op = (OpCodeSimd)context.CurrOp; Operand res = context.VectorZero(); int elems = !scalar?op.GetBytesCount() >> op.Size : 1; ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size)); for (int index = 0; index < elems; index++) { Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size); Operand me; if (op is OpCodeSimdReg binOp) { me = EmitVectorExtractSx(context, binOp.Rm, index, op.Size); } else { me = Const(0L); } Operand isTrue = emitCmp(ne, me); Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L)); res = EmitVectorInsert(context, res, mask, index, op.Size); } context.Copy(GetVec(op.Rd), res); }
public static Operand EmitAsrC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero) { Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32 && shiftIsZero.Type == OperandType.I32); Operand l32Result; Operand ge32Result; Operand less32 = context.ICompareLess(shift, Const(32)); ge32Result = context.ShiftRightSI(m, Const(31)); if (setCarry) { EmitIfHelper(context, context.BitwiseOr(less32, shiftIsZero), () => { SetCarryMLsb(context, ge32Result); }, false); } l32Result = context.ShiftRightSI(m, shift); if (setCarry) { EmitIfHelper(context, context.BitwiseAnd(less32, context.BitwiseNot(shiftIsZero)), () => { Operand cOut = context.ShiftRightUI(m, context.Subtract(shift, Const(1))); cOut = context.BitwiseAnd(cOut, Const(1)); SetFlag(context, PState.CFlag, cOut); }); } return(context.ConditionalSelect(less32, l32Result, ge32Result)); }
public static void Vsel(ArmEmitterContext context) { OpCode32SimdSel op = (OpCode32SimdSel)context.CurrOp; Operand condition = null; switch (op.Cc) { case OpCode32SimdSelMode.Eq: condition = GetCondTrue(context, Condition.Eq); break; case OpCode32SimdSelMode.Ge: condition = GetCondTrue(context, Condition.Ge); break; case OpCode32SimdSelMode.Gt: condition = GetCondTrue(context, Condition.Gt); break; case OpCode32SimdSelMode.Vs: condition = GetCondTrue(context, Condition.Vs); break; } EmitScalarBinaryOpI32(context, (op1, op2) => { return(context.ConditionalSelect(condition, op1, op2)); }); }
public static void Vtst(ArmEmitterContext context) { EmitVectorBinaryOpZx32(context, (op1, op2) => { Operand isZero = context.ICompareEqual(context.BitwiseAnd(op1, op2), Const(0)); return(context.ConditionalSelect(isZero, Const(0), Const(-1))); }); }
public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0) { bool isReturn = sourceRegister == RegisterAlias.Aarch32Lr || IsA32Return(context); Operand mode = context.BitwiseAnd(pc, Const(1)); SetFlag(context, PState.TFlag, mode); Operand addr = context.ConditionalSelect(mode, context.BitwiseAnd(pc, Const(~1)), context.BitwiseAnd(pc, Const(~3))); InstEmitFlowHelper.EmitVirtualJump(context, addr, isReturn); }
private static Operand EmitUnsignedShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size) { Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); Debug.Assert((uint)size < 4u); Operand negShiftLsB = context.Negate(shiftLsB); Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0)); Operand shl = context.ShiftLeft(op, shiftLsB); Operand shr = context.ShiftRightUI(op, negShiftLsB); Operand res = context.ConditionalSelect(isPositive, shl, shr); Operand isOutOfRange = context.BitwiseOr( context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)), context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size))); return(context.ConditionalSelect(isOutOfRange, Const(0UL), res)); }
private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool unsigned) { if (shiftLsB.Type == OperandType.I64) { shiftLsB = context.ConvertI64ToI32(shiftLsB); } shiftLsB = context.SignExtend8(OperandType.I32, shiftLsB); Debug.Assert((uint)size < 4u); Operand negShiftLsB = context.Negate(shiftLsB); Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0)); Operand shl = context.ShiftLeft(op, shiftLsB); Operand shr = unsigned ? context.ShiftRightUI(op, negShiftLsB) : context.ShiftRightSI(op, negShiftLsB); Operand res = context.ConditionalSelect(isPositive, shl, shr); if (unsigned) { Operand isOutOfRange = context.BitwiseOr( context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)), context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size))); return(context.ConditionalSelect(isOutOfRange, Const(op.Type, 0), res)); } else { Operand isOutOfRange0 = context.ICompareGreaterOrEqual(shiftLsB, Const(8 << size)); Operand isOutOfRangeN = context.ICompareGreaterOrEqual(negShiftLsB, Const(8 << size)); // Also zero if shift is too negative, but value was positive. isOutOfRange0 = context.BitwiseOr(isOutOfRange0, context.BitwiseAnd(isOutOfRangeN, context.ICompareGreaterOrEqual(op, Const(op.Type, 0)))); Operand min = (op.Type == OperandType.I64) ? Const(-1L) : Const(-1); return(context.ConditionalSelect(isOutOfRange0, Const(op.Type, 0), context.ConditionalSelect(isOutOfRangeN, min, res))); } }
public static Operand EmitLsrC(ArmEmitterContext context, Operand m, bool setCarry, Operand shift, Operand shiftIsZero) { Debug.Assert(m.Type == OperandType.I32 && shift.Type == OperandType.I32 && shiftIsZero.Type == OperandType.I32); Operand shiftLarge = context.ICompareGreaterOrEqual(shift, Const(32)); Operand result = context.ShiftRightUI(m, shift); if (setCarry) { EmitIfHelper(context, shiftIsZero, () => { Operand cOut = context.ShiftRightUI(m, context.Subtract(shift, Const(1))); cOut = context.BitwiseAnd(cOut, Const(1)); cOut = context.ConditionalSelect(context.ICompareGreater(shift, Const(32)), Const(0), cOut); SetFlag(context, PState.CFlag, cOut); }, false); } return(context.ConditionalSelect(shiftLarge, Const(0), result)); }
private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed) { Debug.Assert(eSize <= 32); long intMin = signed ? -(1L << (eSize - 1)) : 0; long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1; Operand gt = context.ICompareGreater(value, Const(value.Type, intMax)); Operand lt = context.ICompareLess(value, Const(value.Type, intMin)); value = context.ConditionalSelect(gt, Const(value.Type, intMax), value); value = context.ConditionalSelect(lt, Const(value.Type, intMin), value); Operand lblNoSat = Label(); context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt)); context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); context.MarkLabel(lblNoSat); return(value); }
private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed) { Debug.Assert(eSize <= 32); long intMin = signed ? -(1L << (eSize - 1)) : 0; long intMax = signed ? (1L << (eSize - 1)) - 1 : (1L << eSize) - 1; Operand gt = context.ICompareGreater(value, Const(value.Type, intMax)); Operand lt = context.ICompareLess(value, Const(value.Type, intMin)); value = context.ConditionalSelect(gt, Const(value.Type, intMax), value); value = context.ConditionalSelect(lt, Const(value.Type, intMin), value); Operand lblNoSat = Label(); context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt)); // TODO: Set QC (to 1) on FPSCR here. context.MarkLabel(lblNoSat); return(value); }
private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed) { Debug.Assert(op.Type == OperandType.I64); Debug.Assert(shiftLsB.Type == OperandType.I32); Debug.Assert((uint)size < 4u); Operand negShiftLsB = context.Negate(shiftLsB); Operand isInRange = context.BitwiseAnd( context.ICompareLess(shiftLsB, Const(8 << size)), context.ICompareLess(negShiftLsB, Const(8 << size))); Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0)); Operand shl = context.ShiftLeft(op, shiftLsB); Operand sarOrShr = signed ? context.ShiftRightSI(op, negShiftLsB) : context.ShiftRightUI(op, negShiftLsB); Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr); if (signed) { Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L)); Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L)); res2 = context.ConditionalSelect(isPositive, Const(0L), res2); return(context.ConditionalSelect(isInRange, res, res2)); } else { return(context.ConditionalSelect(isInRange, res, Const(0UL))); } }
public static void Vpmin_I(ArmEmitterContext context) { OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp; if (Optimizations.UseSsse3) { EmitSsse3VectorPairwiseOp32(context, op.U ? X86PminuInstruction : X86PminsInstruction); } else { EmitVectorPairwiseOpI32(context, (op1, op2) => { Operand greater = op.U ? context.ICompareLessUI(op1, op2) : context.ICompareLess(op1, op2); return(context.ConditionalSelect(greater, op1, op2)); }, !op.U); } }
public static Operand GetMShiftedByReg(ArmEmitterContext context, IOpCode32AluRsReg op, bool setCarry) { Operand m = GetIntA32(context, op.Rm); Operand s = context.ZeroExtend8(OperandType.I32, GetIntA32(context, op.Rs)); Operand shiftIsZero = context.ICompareEqual(s, Const(0)); Operand zeroResult = m; Operand shiftResult = m; setCarry &= ShouldSetFlags(context); switch (op.ShiftType) { case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break; case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break; case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break; case ShiftType.Ror: shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero); break; } return(context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult)); }
private static Operand ZerosOrOnes(ArmEmitterContext context, Operand fromBool, OperandType baseType) { var ones = (baseType == OperandType.I64) ? Const(-1L) : Const(-1); return(context.ConditionalSelect(fromBool, ones, Const(baseType, 0L))); }
private static Operand EmitAbs(ArmEmitterContext context, Operand value) { Operand isPositive = context.ICompareGreaterOrEqual(value, Const(value.Type, 0)); return(context.ConditionalSelect(isPositive, value, context.Negate(value))); }