public static void Fmul(EmitterContext context) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool negateB = !(op is OpCodeFArithImm32) && op.RawOpCode.Extract(48); Operand srcA = GetSrcA(context); Operand srcB = context.FPNegate(GetSrcB(context), negateB); switch (op.Scale) { case FmulScale.None: break; case FmulScale.Divide2: srcA = context.FPDivide(srcA, ConstF(2)); break; case FmulScale.Divide4: srcA = context.FPDivide(srcA, ConstF(4)); break; case FmulScale.Divide8: srcA = context.FPDivide(srcA, ConstF(8)); break; case FmulScale.Multiply2: srcA = context.FPMultiply(srcA, ConstF(2)); break; case FmulScale.Multiply4: srcA = context.FPMultiply(srcA, ConstF(4)); break; case FmulScale.Multiply8: srcA = context.FPMultiply(srcA, ConstF(8)); break; default: break; //TODO: Warning. } Operand dest = GetDest(context); context.Copy(dest, context.FPSaturate(context.FPMultiply(srcA, srcB), op.Saturate)); SetFPZnFlags(context, dest, op.SetCondCode); }
public static void Fadd(EmitterContext context) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool absoluteA = op.AbsoluteA, absoluteB, negateA, negateB; if (op is OpCodeFArithImm32) { negateB = op.RawOpCode.Extract(53); negateA = op.RawOpCode.Extract(56); absoluteB = op.RawOpCode.Extract(57); } else { negateB = op.RawOpCode.Extract(45); negateA = op.RawOpCode.Extract(48); absoluteB = op.RawOpCode.Extract(49); } Operand srcA = context.FPAbsNeg(GetSrcA(context), absoluteA, negateA); Operand srcB = context.FPAbsNeg(GetSrcB(context), absoluteB, negateB); Operand dest = GetDest(context); context.Copy(dest, context.FPSaturate(context.FPAdd(srcA, srcB), op.Saturate)); SetFPZnFlags(context, dest, op.SetCondCode); }
private static void EmitFPAdd(EmitterContext context, Instruction fpType) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool isFP64 = fpType == Instruction.FP64; bool absoluteA = op.AbsoluteA, absoluteB, negateA, negateB; if (op is OpCodeFArithImm32) { negateB = op.RawOpCode.Extract(53); negateA = op.RawOpCode.Extract(56); absoluteB = op.RawOpCode.Extract(57); } else { negateB = op.RawOpCode.Extract(45); negateA = op.RawOpCode.Extract(48); absoluteB = op.RawOpCode.Extract(49); } Operand srcA = context.FPAbsNeg(GetSrcA(context, isFP64), absoluteA, negateA, fpType); Operand srcB = context.FPAbsNeg(GetSrcB(context, isFP64), absoluteB, negateB, fpType); Operand res = context.FPSaturate(context.FPAdd(srcA, srcB, fpType), op.Saturate, fpType); SetDest(context, res, isFP64); SetFPZnFlags(context, res, op.SetCondCode, fpType); }
private static void EmitFPMultiply(EmitterContext context, Instruction fpType) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool isFP64 = fpType == Instruction.FP64; bool isImm32 = op is OpCodeFArithImm32; bool negateB = !isImm32 && op.RawOpCode.Extract(48); Operand srcA = GetSrcA(context, isFP64); Operand srcB = context.FPNegate(GetSrcB(context, isFP64), negateB, fpType); if (op.Scale != FPMultiplyScale.None) { Operand scale = op.Scale switch { FPMultiplyScale.Divide2 => ConstF(0.5f), FPMultiplyScale.Divide4 => ConstF(0.25f), FPMultiplyScale.Divide8 => ConstF(0.125f), FPMultiplyScale.Multiply2 => ConstF(2f), FPMultiplyScale.Multiply4 => ConstF(4f), FPMultiplyScale.Multiply8 => ConstF(8f), _ => ConstF(1) // Invalid, behave as if it had no scale. }; if (scale.AsFloat() == 1) { context.Config.PrintLog($"Invalid FP multiply scale \"{op.Scale}\"."); } if (isFP64) { scale = context.FP32ConvertToFP64(scale); } srcA = context.FPMultiply(srcA, scale, fpType); } bool saturate = isImm32 ? op.RawOpCode.Extract(55) : op.Saturate; Operand res = context.FPSaturate(context.FPMultiply(srcA, srcB, fpType), saturate, fpType); SetDest(context, res, isFP64); SetFPZnFlags(context, res, op.SetCondCode, fpType); }
public static void Mufu(EmitterContext context) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool negateB = op.RawOpCode.Extract(48); Operand res = context.FPAbsNeg(GetSrcA(context), op.AbsoluteA, negateB); MufuOperation subOp = (MufuOperation)context.CurrOp.RawOpCode.Extract(20, 4); switch (subOp) { case MufuOperation.Cosine: res = context.FPCosine(res); break; case MufuOperation.Sine: res = context.FPSine(res); break; case MufuOperation.ExponentB2: res = context.FPExponentB2(res); break; case MufuOperation.LogarithmB2: res = context.FPLogarithmB2(res); break; case MufuOperation.Reciprocal: res = context.FPReciprocal(res); break; case MufuOperation.ReciprocalSquareRoot: res = context.FPReciprocalSquareRoot(res); break; case MufuOperation.SquareRoot: res = context.FPSquareRoot(res); break; default: /* TODO */ break; } context.Copy(GetDest(context), context.FPSaturate(res, op.Saturate)); }
public static void Ffma(EmitterContext context) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool negateB = op.RawOpCode.Extract(48); bool negateC = op.RawOpCode.Extract(49); Operand srcA = GetSrcA(context); Operand srcB = context.FPNegate(GetSrcB(context), negateB); Operand srcC = context.FPNegate(GetSrcC(context), negateC); Operand dest = GetDest(context); context.Copy(dest, context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC), op.Saturate)); SetFPZnFlags(context, dest, op.SetCondCode); }
private static void EmitFPFma(EmitterContext context, Instruction fpType) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool isFP64 = fpType == Instruction.FP64; bool negateB = op.RawOpCode.Extract(48); bool negateC = op.RawOpCode.Extract(49); Operand srcA = GetSrcA(context, isFP64); Operand srcB = context.FPNegate(GetSrcB(context, isFP64), negateB, fpType); Operand srcC = context.FPNegate(GetSrcC(context, isFP64), negateC, fpType); Operand res = context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC, fpType), op.Saturate, fpType); SetDest(context, res, isFP64); SetFPZnFlags(context, res, op.SetCondCode, fpType); }
public static void Fmnmx(EmitterContext context) { IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; bool absoluteA = op.AbsoluteA; bool negateB = op.RawOpCode.Extract(45); bool negateA = op.RawOpCode.Extract(48); bool absoluteB = op.RawOpCode.Extract(49); Operand srcA = context.FPAbsNeg(GetSrcA(context), absoluteA, negateA); Operand srcB = context.FPAbsNeg(GetSrcB(context), absoluteB, negateB); Operand resMin = context.FPMinimum(srcA, srcB); Operand resMax = context.FPMaximum(srcA, srcB); Operand pred = GetPredicate39(context); Operand dest = GetDest(context); context.Copy(dest, context.ConditionalSelect(pred, resMin, resMax)); SetFPZnFlags(context, dest, op.SetCondCode); }