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); }
private static void EmitFmul( EmitterContext context, Instruction fpType, MultiplyScale scale, Operand srcA, Operand srcB, int rd, bool negateB, bool saturate, bool writeCC) { bool isFP64 = fpType == Instruction.FP64; srcB = context.FPNegate(srcB, negateB, fpType); if (scale != MultiplyScale.NoScale) { Operand scaleConst = scale switch { MultiplyScale.D2 => ConstF(0.5f), MultiplyScale.D4 => ConstF(0.25f), MultiplyScale.D8 => ConstF(0.125f), MultiplyScale.M2 => ConstF(2f), MultiplyScale.M4 => ConstF(4f), MultiplyScale.M8 => ConstF(8f), _ => ConstF(1f) // Invalid, behave as if it had no scale. }; if (scaleConst.AsFloat() == 1f) { context.Config.GpuAccessor.Log($"Invalid FP multiply scale \"{scale}\"."); } if (isFP64) { scaleConst = context.FP32ConvertToFP64(scaleConst); } srcA = context.FPMultiply(srcA, scaleConst, fpType); } Operand res = context.FPSaturate(context.FPMultiply(srcA, srcB, fpType), saturate, fpType); SetDest(context, res, rd, isFP64); SetFPZnFlags(context, res, writeCC, fpType); }