public static void Fcvtn_V(ArmEmitterContext context) { OpCodeSimd op = (OpCodeSimd)context.CurrOp; int sizeF = op.Size & 1; if (Optimizations.UseSse2 && sizeF == 1) { Operand d = GetVec(op.Rd); Operand n = GetVec(op.Rn); Operand res = context.AddIntrinsic(Intrinsic.X86Movlhps, d, context.VectorZero()); Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtpd2ps, n); nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt); Intrinsic movInst = op.RegisterSize == RegisterSize.Simd128 ? Intrinsic.X86Movlhps : Intrinsic.X86Movhlps; res = context.AddIntrinsic(movInst, res, nInt); context.Copy(GetVec(op.Rd), res); } else { OperandType type = sizeF == 0 ? OperandType.FP32 : OperandType.FP64; int elems = 4 >> sizeF; int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0; Operand res = part == 0 ? context.VectorZero() : context.Copy(GetVec(op.Rd)); for (int index = 0; index < elems; index++) { Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0); if (sizeF == 0) { Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert); Operand e = context.Call(dlg, ne); e = context.ZeroExtend16(OperandType.I64, e); res = EmitVectorInsert(context, res, e, part + index, 1); } else /* if (sizeF == 1) */ { Operand e = context.ConvertToFP(OperandType.FP32, ne); res = context.VectorInsert(res, e, part + index); } } context.Copy(GetVec(op.Rd), res); } }
public static void Fcvt_S(ArmEmitterContext context) { OpCodeSimd op = (OpCodeSimd)context.CurrOp; if (op.Size == 0 && op.Opc == 1) // Single -> Double. { if (Optimizations.UseSse2) { Operand n = GetVec(op.Rn); Operand res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), n); context.Copy(GetVec(op.Rd), res); } else { Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0); Operand res = context.ConvertToFP(OperandType.FP64, ne); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); } } else if (op.Size == 1 && op.Opc == 0) // Double -> Single. { if (Optimizations.UseSse2) { Operand n = GetVec(op.Rn); Operand res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), n); context.Copy(GetVec(op.Rd), res); } else { Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0); Operand res = context.ConvertToFP(OperandType.FP32, ne); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); } } else if (op.Size == 0 && op.Opc == 3) // Single -> Half. { Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0); Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert); Operand res = context.Call(dlg, ne); res = context.ZeroExtend16(OperandType.I64, res); context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), res, 0, 1)); } else if (op.Size == 3 && op.Opc == 0) // Half -> Single. { Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1); Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert); Operand res = context.Call(dlg, ne); context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0)); } else if (op.Size == 1 && op.Opc == 3) // Double -> Half. { throw new NotImplementedException("Double-precision to half-precision."); } else if (op.Size == 3 && op.Opc == 1) // Double -> Half. { throw new NotImplementedException("Half-precision to double-precision."); } else // Invalid encoding. { Debug.Assert(false, $"type == {op.Size} && opc == {op.Opc}"); } }