예제 #1
0
        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);
        }
예제 #2
0
        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);
        }