public static void EmitSubsVCheck(ArmEmitterContext context, Operand n, Operand m, Operand d) { // V = (Rd ^ Rn) & (Rn ^ Rm) < 0 Operand vOut = context.BitwiseExclusiveOr(d, n); vOut = context.BitwiseAnd(vOut, context.BitwiseExclusiveOr(n, m)); vOut = context.ICompareLess(vOut, Const(vOut.Type, 0)); SetFlag(context, PState.VFlag, vOut); }
private static void EmitSat16(ArmEmitterContext context, int intMin, int intMax) { OpCode32Sat16 op = (OpCode32Sat16)context.CurrOp; void SetD(int part, Operand value) { if (part == 0) { SetIntA32(context, op.Rd, context.ZeroExtend16(OperandType.I32, value)); } else { SetIntA32(context, op.Rd, context.BitwiseOr(GetIntA32(context, op.Rd), context.ShiftLeft(value, Const(16)))); } } Operand n = GetIntA32(context, op.Rn); Operand nLow = context.SignExtend16(OperandType.I32, n); Operand nHigh = context.ShiftRightSI(n, Const(16)); for (int part = 0; part < 2; part++) { Operand nPart = part == 0 ? nLow : nHigh; Operand lblCheckLtIntMin = Label(); Operand lblNoSat = Label(); Operand lblEnd = Label(); context.BranchIfFalse(lblCheckLtIntMin, context.ICompareGreater(nPart, Const(intMax))); SetFlag(context, PState.QFlag, Const(1)); SetD(part, Const(intMax)); context.Branch(lblEnd); context.MarkLabel(lblCheckLtIntMin); context.BranchIfFalse(lblNoSat, context.ICompareLess(nPart, Const(intMin))); SetFlag(context, PState.QFlag, Const(1)); SetD(part, Const(intMin)); context.Branch(lblEnd); context.MarkLabel(lblNoSat); SetD(part, nPart); context.MarkLabel(lblEnd); } }
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))); } }
private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath) { int ptLevelBits = context.Memory.AddressSpaceBits - 12; // 12 = Number of page bits. int ptLevelSize = 1 << ptLevelBits; int ptLevelMask = ptLevelSize - 1; Operand pte = Ptc.State == PtcState.Disabled ? Const(context.Memory.PageTablePointer.ToInt64()) : Const(context.Memory.PageTablePointer.ToInt64(), true, Ptc.PageTablePointerIndex); int bit = PageBits; do { Operand addrPart = context.ShiftRightUI(address, Const(bit)); bit += ptLevelBits; if (bit < context.Memory.AddressSpaceBits) { addrPart = context.BitwiseAnd(addrPart, Const(addrPart.Type, ptLevelMask)); } Operand pteOffset = context.ShiftLeft(addrPart, Const(3)); if (pteOffset.Type == OperandType.I32) { pteOffset = context.ZeroExtend32(OperandType.I64, pteOffset); } Operand pteAddress = context.Add(pte, pteOffset); pte = context.Load(OperandType.I64, pteAddress); }while (bit < context.Memory.AddressSpaceBits); context.BranchIfTrue(lblSlowPath, context.ICompareLess(pte, Const(0L))); Operand pageOffset = context.BitwiseAnd(address, Const(address.Type, PageMask)); if (pageOffset.Type == OperandType.I32) { pageOffset = context.ZeroExtend32(OperandType.I64, pageOffset); } return(context.Add(pte, pageOffset)); }
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); } }
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); }
public static void Cmlt_V(ArmEmitterContext context) { if (Optimizations.UseSse42) { OpCodeSimd op = (OpCodeSimd)context.CurrOp; Operand n = GetVec(op.Rn); Intrinsic cmpInst = X86PcmpgtInstruction[op.Size]; Operand res = context.AddIntrinsic(cmpInst, context.VectorZero(), n); if (op.RegisterSize == RegisterSize.Simd64) { res = context.VectorZeroUpper64(res); } context.Copy(GetVec(op.Rd), res); } else { EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: false); } }
public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d) { SetFlag(context, PState.NFlag, context.ICompareLess(d, Const(d.Type, 0))); SetFlag(context, PState.ZFlag, context.ICompareEqual(d, Const(d.Type, 0))); }
public static void Cmlt_S(ArmEmitterContext context) { EmitCmpOp(context, (op1, op2) => context.ICompareLess(op1, op2), scalar: true); }
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)); } }