示例#1
0
        private static void EmitIscadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegB = OpCode.Read(48);
            bool NegA = OpCode.Read(49);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            ShaderIrOperImm Scale = OpCode.Imm5_39();

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = OpCode.Cbuf34();   break;

            case ShaderOper.Imm: OperB = OpCode.Imm19_20(); break;

            case ShaderOper.RR:  OperB = OpCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperA = GetAluIneg(OperA, NegA);
            OperB = GetAluIneg(OperB, NegB);

            ShaderIrOp ScaleOp = new ShaderIrOp(ShaderIrInst.Lsl, OperA, Scale);
            ShaderIrOp AddOp   = new ShaderIrOp(ShaderIrInst.Add, OperB, ScaleOp);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), AddOp)));
        }
示例#2
0
        private static void EmitIadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            ShaderIrNode OperA = GetOperGpr8(OpCode);
            ShaderIrNode OperB;

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;

            case ShaderOper.RR:  OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            bool NegA = ((OpCode >> 49) & 1) != 0;
            bool NegB = ((OpCode >> 48) & 1) != 0;

            OperA = GetAluIneg(OperA, NegA);
            OperB = GetAluIneg(OperB, NegB);

            ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Add, OperA, OperB);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#3
0
        private static void EmitF2f(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegA = ((OpCode >> 45) & 1) != 0;
            bool AbsA = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA;

            switch (Oper)
            {
            case ShaderOper.CR:   OperA = GetOperCbuf34(OpCode); break;

            case ShaderOper.Immf: OperA = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RR:   OperA = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperA = GetAluFabsFneg(OperA, AbsA, NegA);

            ShaderIrInst RoundInst = GetRoundInst(OpCode);

            if (RoundInst != ShaderIrInst.Invalid)
            {
                OperA = new ShaderIrOp(RoundInst, OperA);
            }

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode));
        }
示例#4
0
        private static void EmitFadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegB = OpCode.Read(45);
            bool AbsA = OpCode.Read(46);
            bool NegA = OpCode.Read(48);
            bool AbsB = OpCode.Read(49);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            OperA = GetAluFabsFneg(OperA, AbsA, NegA);

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluFabsFneg(OperB, AbsB, NegB);

            ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fadd, OperA, OperB);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
        }
示例#5
0
        private static void EmitAluBinaryF(
            ShaderIrBlock Block,
            long OpCode,
            ShaderOper Oper,
            ShaderIrInst Inst)
        {
            bool NegB = ((OpCode >> 45) & 1) != 0;
            bool AbsA = ((OpCode >> 46) & 1) != 0;
            bool NegA = ((OpCode >> 48) & 1) != 0;
            bool AbsB = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;

            if (Inst == ShaderIrInst.Fadd)
            {
                OperA = GetAluFabsFneg(OperA, AbsA, NegA);
            }

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RR:   OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluFabsFneg(OperB, AbsB, NegB);

            ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#6
0
        private static void EmitFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegB = OpCode.Read(48);
            bool NegC = OpCode.Read(49);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB, OperC;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RC:   OperB = OpCode.Gpr39();     break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluFneg(OperB, NegB);

            if (Oper == ShaderOper.RC)
            {
                OperC = GetAluFneg(OpCode.Cbuf34(), NegC);
            }
            else
            {
                OperC = GetAluFneg(OpCode.Gpr39(), NegC);
            }

            ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
        }
示例#7
0
        private static void EmitIscadd(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            bool negB = opCode.Read(48);
            bool negA = opCode.Read(49);

            ShaderIrNode operA = opCode.Gpr8(), operB;

            ShaderIrOperImm scale = opCode.Imm5_39();

            switch (oper)
            {
            case ShaderOper.Cr:  operB = opCode.Cbuf34();   break;

            case ShaderOper.Imm: operB = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  operB = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            operA = GetAluIneg(operA, negA);
            operB = GetAluIneg(operB, negB);

            ShaderIrOp scaleOp = new ShaderIrOp(ShaderIrInst.Lsl, operA, scale);
            ShaderIrOp addOp   = new ShaderIrOp(ShaderIrInst.Add, operB, scaleOp);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), addOp)));
        }
示例#8
0
        private static void EmitRro(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            //Note: this is a range reduction instruction and is supposed to
            //be used with Mufu, here it just moves the value and ignores the operation.
            bool NegA = OpCode.Read(45);
            bool AbsA = OpCode.Read(49);

            ShaderIrNode OperA;

            switch (Oper)
            {
            case ShaderOper.CR:   OperA = OpCode.Cbuf34();    break;

            case ShaderOper.Immf: OperA = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperA = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperA = GetAluFabsFneg(OperA, AbsA, NegA);

            Block.AddNode(new ShaderIrCmnt("Stubbed."));

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), OperA)));
        }
示例#9
0
        private static void EmitAluFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool Nb = ((OpCode >> 48) & 1) != 0;
            bool Nc = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB, OperC;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RC:   OperB = GetOperGpr39(OpCode); break;

            case ShaderOper.RR:   OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluNeg(OperB, Nb);

            if (Oper == ShaderOper.RC)
            {
                OperC = GetAluNeg(GetOperCbuf34(OpCode), Nc);
            }
            else
            {
                OperC = GetAluNeg(GetOperGpr39(OpCode), Nc);
            }

            ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#10
0
        private static void EmitFadd(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            bool negB = opCode.Read(45);
            bool absA = opCode.Read(46);
            bool negA = opCode.Read(48);
            bool absB = opCode.Read(49);
            bool sat  = opCode.Read(50);

            ShaderIrNode operA = opCode.Gpr8(), operB;

            operA = GetAluFabsFneg(operA, absA, negA);

            switch (oper)
            {
            case ShaderOper.Cr:   operB = opCode.Cbuf34();    break;

            case ShaderOper.Immf: operB = opCode.Immf19_20(); break;

            case ShaderOper.Rr:   operB = opCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(oper));
            }

            operB = GetAluFabsFneg(operB, absB, negB);

            ShaderIrNode op = new ShaderIrOp(ShaderIrInst.Fadd, operA, operB);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), GetAluFsat(op, sat))));
        }
示例#11
0
        private static void EmitF2F(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            bool negA = opCode.Read(45);
            bool absA = opCode.Read(49);

            ShaderIrNode operA;

            switch (oper)
            {
            case ShaderOper.Cr:   operA = opCode.Cbuf34();    break;

            case ShaderOper.Immf: operA = opCode.Immf19_20(); break;

            case ShaderOper.Rr:   operA = opCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(oper));
            }

            operA = GetAluFabsFneg(operA, absA, negA);

            ShaderIrInst roundInst = GetRoundInst(opCode);

            if (roundInst != ShaderIrInst.Invalid)
            {
                operA = new ShaderIrOp(roundInst, operA);
            }

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA)));
        }
示例#12
0
        private static void EmitI2f(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            IntType Type = GetIntType(OpCode);

            if (Type == IntType.U64 ||
                Type == IntType.S64)
            {
                //TODO: 64-bits support.
                //Note: GLSL doesn't support 64-bits integers.
                throw new NotImplementedException();
            }

            int Sel = (int)(OpCode >> 41) & 3;

            bool Na = ((OpCode >> 45) & 1) != 0;
            bool Aa = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA;

            switch (Oper)
            {
            case ShaderOper.CR:  OperA = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm: OperA = GetOperImm19_20(OpCode); break;

            case ShaderOper.RR:  OperA = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperA = GetAluAbsNeg(OperA, Aa, Na);

            bool Signed = Type >= IntType.S8;

            int Shift = Sel * 8;

            int Size = 8 << ((int)Type & 3);

            ulong Mask = ulong.MaxValue >> (64 - Size);

            int Mask32 = (int)Mask;

            if (Shift != 0)
            {
                OperA = new ShaderIrOp(ShaderIrInst.Asr, OperA, new ShaderIrOperImm(Shift));
            }

            if (Mask != uint.MaxValue)
            {
                OperA = new ShaderIrOp(ShaderIrInst.And, OperA, new ShaderIrOperImm(Mask32));
            }

            ShaderIrInst Inst = Signed
                ? ShaderIrInst.Stof
                : ShaderIrInst.Utof;

            ShaderIrNode Op = new ShaderIrOp(Inst, OperA);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#13
0
        private static void EmitBfe(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            //TODO: Handle the case where position + length
            //is greater than the word size, in this case the sign bit
            //needs to be replicated to fill the remaining space.
            bool negB = opCode.Read(48);
            bool negA = opCode.Read(49);

            ShaderIrNode operA = opCode.Gpr8(), operB;

            switch (oper)
            {
            case ShaderOper.Cr:  operB = opCode.Cbuf34();   break;

            case ShaderOper.Imm: operB = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  operB = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            ShaderIrNode op;

            bool signed = opCode.Read(48); //?

            if (operB is ShaderIrOperImm posLen)
            {
                int position = (posLen.Value >> 0) & 0xff;
                int length   = (posLen.Value >> 8) & 0xff;

                int lSh = 32 - (position + length);

                ShaderIrInst rightShift = signed
                    ? ShaderIrInst.Asr
                    : ShaderIrInst.Lsr;

                op = new ShaderIrOp(ShaderIrInst.Lsl, operA, new ShaderIrOperImm(lSh));
                op = new ShaderIrOp(rightShift, op, new ShaderIrOperImm(lSh + position));
            }
            else
            {
                ShaderIrOperImm shift = new ShaderIrOperImm(8);
                ShaderIrOperImm mask  = new ShaderIrOperImm(0xff);

                ShaderIrNode opPos, opLen;

                opPos = new ShaderIrOp(ShaderIrInst.And, operB, mask);
                opLen = new ShaderIrOp(ShaderIrInst.Lsr, operB, shift);
                opLen = new ShaderIrOp(ShaderIrInst.And, opLen, mask);

                op = new ShaderIrOp(ShaderIrInst.Lsr, operA, opPos);

                op = ExtendTo32(op, signed, opLen);
            }

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
        }
示例#14
0
        private static void EmitBfe(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            //TODO: Handle the case where position + length
            //is greater than the word size, in this case the sign bit
            //needs to be replicated to fill the remaining space.
            bool NegB = OpCode.Read(48);
            bool NegA = OpCode.Read(49);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = OpCode.Cbuf34();   break;

            case ShaderOper.Imm: OperB = OpCode.Imm19_20(); break;

            case ShaderOper.RR:  OperB = OpCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrNode Op;

            bool Signed = OpCode.Read(48); //?

            if (OperB is ShaderIrOperImm PosLen)
            {
                int Position = (PosLen.Value >> 0) & 0xff;
                int Length   = (PosLen.Value >> 8) & 0xff;

                int LSh = 32 - (Position + Length);

                ShaderIrInst RightShift = Signed
                    ? ShaderIrInst.Asr
                    : ShaderIrInst.Lsr;

                Op = new ShaderIrOp(ShaderIrInst.Lsl, OperA, new ShaderIrOperImm(LSh));
                Op = new ShaderIrOp(RightShift, Op, new ShaderIrOperImm(LSh + Position));
            }
            else
            {
                ShaderIrOperImm Shift = new ShaderIrOperImm(8);
                ShaderIrOperImm Mask  = new ShaderIrOperImm(0xff);

                ShaderIrNode OpPos, OpLen;

                OpPos = new ShaderIrOp(ShaderIrInst.And, OperB, Mask);
                OpLen = new ShaderIrOp(ShaderIrInst.Lsr, OperB, Shift);
                OpLen = new ShaderIrOp(ShaderIrInst.And, OpLen, Mask);

                Op = new ShaderIrOp(ShaderIrInst.Lsr, OperA, OpPos);

                Op = ExtendTo32(Op, Signed, OpLen);
            }

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
        }
示例#15
0
        private static void EmitFsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool Aa = ((OpCode >> 7) & 1) != 0;
            bool Np = ((OpCode >> 42) & 1) != 0;
            bool Na = ((OpCode >> 43) & 1) != 0;
            bool Ab = ((OpCode >> 44) & 1) != 0;

            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RR:   OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrInst CmpInst = GetCmp(OpCode);

            ShaderIrOp Op = new ShaderIrOp(CmpInst,
                                           GetAluAbsNeg(OperA, Aa, Na),
                                           GetAluAbs(OperB, Ab));

            ShaderIrOperPred P0Node = GetOperPred3(OpCode);
            ShaderIrOperPred P1Node = GetOperPred0(OpCode);
            ShaderIrOperPred P2Node = GetOperPred39(OpCode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));

            ShaderIrInst LopInst = GetBLop(OpCode);

            if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
            {
                return;
            }

            ShaderIrNode P2NNode = P2Node;

            if (Np)
            {
                P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
            }

            Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);

            Op = new ShaderIrOp(LopInst, Op, P2NNode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));

            Op = new ShaderIrOp(LopInst, P0Node, P2NNode);

            Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
        }
示例#16
0
        private static void EmitI2f(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            IntType Type = GetIntType(OpCode);

            if (Type == IntType.U64 ||
                Type == IntType.S64)
            {
                //TODO: 64-bits support.
                //Note: GLSL doesn't support 64-bits integers.
                throw new NotImplementedException();
            }

            int Sel = OpCode.Read(41, 3);

            bool NegA = OpCode.Read(45);
            bool AbsA = OpCode.Read(49);

            ShaderIrNode OperA;

            switch (Oper)
            {
            case ShaderOper.CR:  OperA = OpCode.Cbuf34();   break;

            case ShaderOper.Imm: OperA = OpCode.Imm19_20(); break;

            case ShaderOper.RR:  OperA = OpCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperA = GetAluIabsIneg(OperA, AbsA, NegA);

            bool Signed = Type >= IntType.S8;

            int Shift = Sel * 8;

            int Size = 8 << ((int)Type & 3);

            if (Shift != 0)
            {
                OperA = new ShaderIrOp(ShaderIrInst.Asr, OperA, new ShaderIrOperImm(Shift));
            }

            if (Size < 32)
            {
                OperA = ExtendTo32(OperA, Signed, Size);
            }

            ShaderIrInst Inst = Signed
                ? ShaderIrInst.Stof
                : ShaderIrInst.Utof;

            ShaderIrNode Op = new ShaderIrOp(Inst, OperA);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
        }
示例#17
0
        private static void EmitI2F(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            IntType type = GetIntType(opCode);

            if (type == IntType.U64 ||
                type == IntType.S64)
            {
                //TODO: 64-bits support.
                //Note: GLSL doesn't support 64-bits integers.
                throw new NotImplementedException();
            }

            int sel = opCode.Read(41, 3);

            bool negA = opCode.Read(45);
            bool absA = opCode.Read(49);

            ShaderIrNode operA;

            switch (oper)
            {
            case ShaderOper.Cr:  operA = opCode.Cbuf34();   break;

            case ShaderOper.Imm: operA = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  operA = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            operA = GetAluIabsIneg(operA, absA, negA);

            bool signed = type >= IntType.S8;

            int shift = sel * 8;

            int size = 8 << ((int)type & 3);

            if (shift != 0)
            {
                operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift));
            }

            if (size < 32)
            {
                operA = ExtendTo32(operA, signed, size);
            }

            ShaderIrInst inst = signed
                ? ShaderIrInst.Stof
                : ShaderIrInst.Utof;

            ShaderIrNode op = new ShaderIrOp(inst, operA);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
        }
示例#18
0
        private static void EmitFmnmx(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegB = ((OpCode >> 45) & 1) != 0;
            bool AbsA = ((OpCode >> 46) & 1) != 0;
            bool NegA = ((OpCode >> 48) & 1) != 0;
            bool AbsB = ((OpCode >> 49) & 1) != 0;

            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;

            OperA = GetAluFabsFneg(OperA, AbsA, NegA);

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;

            case ShaderOper.RR:   OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluFabsFneg(OperB, AbsB, NegB);

            ShaderIrOperPred Pred = GetOperPred39(OpCode);

            ShaderIrOp Op;

            if (Pred.IsConst)
            {
                bool IsMax = ((OpCode >> 42) & 1) != 0;

                Op = new ShaderIrOp(IsMax
                    ? ShaderIrInst.Fmax
                    : ShaderIrInst.Fmin, OperA, OperB);

                Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
            }
            else
            {
                ShaderIrNode PredN = GetOperPred39N(OpCode);

                ShaderIrOp OpMax = new ShaderIrOp(ShaderIrInst.Fmax, OperA, OperB);
                ShaderIrOp OpMin = new ShaderIrOp(ShaderIrInst.Fmin, OperA, OperB);

                ShaderIrAsg AsgMax = new ShaderIrAsg(GetOperGpr0(OpCode), OpMax);
                ShaderIrAsg AsgMin = new ShaderIrAsg(GetOperGpr0(OpCode), OpMin);

                Block.AddNode(GetPredNode(new ShaderIrCond(PredN, AsgMax, Not: true), OpCode));
                Block.AddNode(GetPredNode(new ShaderIrCond(PredN, AsgMin, Not: false), OpCode));
            }
        }
示例#19
0
        private static void EmitLop(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            int SubOp = OpCode.Read(41, 3);

            bool InvA = OpCode.Read(39);
            bool InvB = OpCode.Read(40);

            ShaderIrInst Inst = 0;

            switch (SubOp)
            {
            case 0: Inst = ShaderIrInst.And; break;

            case 1: Inst = ShaderIrInst.Or;  break;

            case 2: Inst = ShaderIrInst.Xor; break;
            }

            ShaderIrNode OperA = GetAluNot(OpCode.Gpr8(), InvA);
            ShaderIrNode OperB;

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = OpCode.Cbuf34();   break;

            case ShaderOper.Imm: OperB = OpCode.Imm19_20(); break;

            case ShaderOper.RR:  OperB = OpCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluNot(OperB, InvB);

            ShaderIrNode Op;

            if (SubOp < 3)
            {
                Op = new ShaderIrOp(Inst, OperA, OperB);
            }
            else
            {
                Op = OperB;
            }

            ShaderIrNode Compare = new ShaderIrOp(ShaderIrInst.Cne, Op, new ShaderIrOperImm(0));

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Pred48(), Compare)));

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
        }
示例#20
0
        private static void EmitLop(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            int SubOp = (int)(OpCode >> 41) & 3;

            bool InvA = ((OpCode >> 39) & 1) != 0;
            bool InvB = ((OpCode >> 40) & 1) != 0;

            ShaderIrInst Inst = 0;

            switch (SubOp)
            {
            case 0: Inst = ShaderIrInst.And; break;

            case 1: Inst = ShaderIrInst.Or;  break;

            case 2: Inst = ShaderIrInst.Xor; break;
            }

            ShaderIrNode OperA = GetAluNot(GetOperGpr8(OpCode), InvA);
            ShaderIrNode OperB;

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;

            case ShaderOper.RR:  OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluNot(OperB, InvB);

            ShaderIrNode Op;

            if (SubOp < 3)
            {
                Op = new ShaderIrOp(Inst, OperA, OperB);
            }
            else
            {
                Op = OperB;
            }

            ShaderIrNode Compare = new ShaderIrOp(ShaderIrInst.Cne, Op, new ShaderIrOperImm(0));

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperPred48(OpCode), Compare), OpCode));

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#21
0
        private static void EmitLop(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            int subOp = opCode.Read(41, 3);

            bool invA = opCode.Read(39);
            bool invB = opCode.Read(40);

            ShaderIrInst inst = 0;

            switch (subOp)
            {
            case 0: inst = ShaderIrInst.And; break;

            case 1: inst = ShaderIrInst.Or;  break;

            case 2: inst = ShaderIrInst.Xor; break;
            }

            ShaderIrNode operA = GetAluNot(opCode.Gpr8(), invA);
            ShaderIrNode operB;

            switch (oper)
            {
            case ShaderOper.Cr:  operB = opCode.Cbuf34();   break;

            case ShaderOper.Imm: operB = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  operB = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            operB = GetAluNot(operB, invB);

            ShaderIrNode op;

            if (subOp < 3)
            {
                op = new ShaderIrOp(inst, operA, operB);
            }
            else
            {
                op = operB;
            }

            ShaderIrNode compare = new ShaderIrOp(ShaderIrInst.Cne, op, new ShaderIrOperImm(0));

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Pred48(), compare)));

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
        }
示例#22
0
        private static void EmitAluBinary(
            ShaderIrBlock block,
            long opCode,
            ShaderOper oper,
            ShaderIrInst inst)
        {
            ShaderIrNode operA = opCode.Gpr8(), operB;

            switch (oper)
            {
            case ShaderOper.Cr:  operB = opCode.Cbuf34();   break;

            case ShaderOper.Imm: operB = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  operB = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            ShaderIrNode op = new ShaderIrOp(inst, operA, operB);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op)));
        }
示例#23
0
        private static void EmitSel(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            ShaderIrOperGpr dst  = opCode.Gpr0();
            ShaderIrNode    pred = opCode.Pred39N();

            ShaderIrNode resultA = opCode.Gpr8();
            ShaderIrNode resultB;

            switch (oper)
            {
            case ShaderOper.Cr:  resultB = opCode.Cbuf34();   break;

            case ShaderOper.Imm: resultB = opCode.Imm19_20(); break;

            case ShaderOper.Rr:  resultB = opCode.Gpr20();    break;

            default: throw new ArgumentException(nameof(oper));
            }

            block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultA), false)));

            block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultB), true)));
        }
示例#24
0
        private static void EmitAluBinary(
            ShaderIrBlock Block,
            long OpCode,
            ShaderOper Oper,
            ShaderIrInst Inst)
        {
            ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:  OperB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;

            case ShaderOper.RR:  OperB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);

            Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
        }
示例#25
0
        private static void EmitSel(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            ShaderIrOperGpr Dst  = GetOperGpr0(OpCode);
            ShaderIrNode    Pred = GetOperPred39N(OpCode);

            ShaderIrNode ResultA = GetOperGpr8(OpCode);
            ShaderIrNode ResultB;

            switch (Oper)
            {
            case ShaderOper.CR:  ResultB = GetOperCbuf34(OpCode); break;

            case ShaderOper.Imm: ResultB = GetOperImm19_20(OpCode); break;

            case ShaderOper.RR:  ResultB = GetOperGpr20(OpCode); break;

            default: throw new ArgumentException(nameof(Oper));
            }

            Block.AddNode(GetPredNode(new ShaderIrCond(Pred, new ShaderIrAsg(Dst, ResultA), false), OpCode));

            Block.AddNode(GetPredNode(new ShaderIrCond(Pred, new ShaderIrAsg(Dst, ResultB), true), OpCode));
        }
示例#26
0
        private static void EmitFfma(ShaderIrBlock block, long opCode, ShaderOper oper)
        {
            bool negB = opCode.Read(48);
            bool negC = opCode.Read(49);
            bool sat  = opCode.Read(50);

            ShaderIrNode operA = opCode.Gpr8(), operB, operC;

            switch (oper)
            {
            case ShaderOper.Cr:   operB = opCode.Cbuf34();    break;

            case ShaderOper.Immf: operB = opCode.Immf19_20(); break;

            case ShaderOper.Rc:   operB = opCode.Gpr39();     break;

            case ShaderOper.Rr:   operB = opCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(oper));
            }

            operB = GetAluFneg(operB, negB);

            if (oper == ShaderOper.Rc)
            {
                operC = GetAluFneg(opCode.Cbuf34(), negC);
            }
            else
            {
                operC = GetAluFneg(opCode.Gpr39(), negC);
            }

            ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Ffma, operA, operB, operC);

            block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), GetAluFsat(op, sat))));
        }
示例#27
0
        private static void EmitFmul(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
        {
            bool NegB = OpCode.Read(48);
            bool Sat  = OpCode.Read(50);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            OperB = GetAluFneg(OperB, NegB);

            ShaderIrNode Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB);

            Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), GetAluFsat(Op, Sat))));
        }
示例#28
0
        private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool NegA = OpCode.Read(43);
            bool AbsB = OpCode.Read(44);
            bool NegB = OpCode.Read(53);
            bool AbsA = OpCode.Read(54);

            bool BoolFloat = OpCode.Read(IsFloat ? 52 : 44);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Imm:  OperB = OpCode.Imm19_20();  break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            ShaderIrInst CmpInst;

            if (IsFloat)
            {
                OperA = GetAluFabsFneg(OperA, AbsA, NegA);
                OperB = GetAluFabsFneg(OperB, AbsB, NegB);

                CmpInst = OpCode.CmpF();
            }
            else
            {
                CmpInst = OpCode.Cmp();
            }

            ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);

            ShaderIrInst LopInst = OpCode.BLop45();

            ShaderIrOperPred PNode = OpCode.Pred39();

            ShaderIrNode Imm0, Imm1;

            if (BoolFloat)
            {
                Imm0 = new ShaderIrOperImmf(0);
                Imm1 = new ShaderIrOperImmf(1);
            }
            else
            {
                Imm0 = new ShaderIrOperImm(0);
                Imm1 = new ShaderIrOperImm(-1);
            }

            ShaderIrNode Asg0 = new ShaderIrAsg(OpCode.Gpr0(), Imm0);
            ShaderIrNode Asg1 = new ShaderIrAsg(OpCode.Gpr0(), Imm1);

            if (LopInst != ShaderIrInst.Band || !PNode.IsConst)
            {
                ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode);

                Asg0 = new ShaderIrCond(Op2, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op2, Asg1, Not: false);
            }
            else
            {
                Asg0 = new ShaderIrCond(Op, Asg0, Not: true);
                Asg1 = new ShaderIrCond(Op, Asg1, Not: false);
            }

            Block.AddNode(OpCode.PredNode(Asg0));
            Block.AddNode(OpCode.PredNode(Asg1));
        }
示例#29
0
 private static void EmitIset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
 {
     EmitSet(Block, OpCode, false, Oper);
 }
示例#30
0
        private static void EmitMnmx(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
        {
            bool NegB = OpCode.Read(45);
            bool AbsA = OpCode.Read(46);
            bool NegA = OpCode.Read(48);
            bool AbsB = OpCode.Read(49);

            ShaderIrNode OperA = OpCode.Gpr8(), OperB;

            if (IsFloat)
            {
                OperA = GetAluFabsFneg(OperA, AbsA, NegA);
            }
            else
            {
                OperA = GetAluIabsIneg(OperA, AbsA, NegA);
            }

            switch (Oper)
            {
            case ShaderOper.CR:   OperB = OpCode.Cbuf34();    break;

            case ShaderOper.Imm:  OperB = OpCode.Imm19_20();  break;

            case ShaderOper.Immf: OperB = OpCode.Immf19_20(); break;

            case ShaderOper.RR:   OperB = OpCode.Gpr20();     break;

            default: throw new ArgumentException(nameof(Oper));
            }

            if (IsFloat)
            {
                OperB = GetAluFabsFneg(OperB, AbsB, NegB);
            }
            else
            {
                OperB = GetAluIabsIneg(OperB, AbsB, NegB);
            }

            ShaderIrOperPred Pred = OpCode.Pred39();

            ShaderIrOp Op;

            ShaderIrInst MaxInst = IsFloat ? ShaderIrInst.Fmax : ShaderIrInst.Max;
            ShaderIrInst MinInst = IsFloat ? ShaderIrInst.Fmin : ShaderIrInst.Min;

            if (Pred.IsConst)
            {
                bool IsMax = OpCode.Read(42);

                Op = new ShaderIrOp(IsMax
                    ? MaxInst
                    : MinInst, OperA, OperB);

                Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
            }
            else
            {
                ShaderIrNode PredN = OpCode.Pred39N();

                ShaderIrOp OpMax = new ShaderIrOp(MaxInst, OperA, OperB);
                ShaderIrOp OpMin = new ShaderIrOp(MinInst, OperA, OperB);

                ShaderIrAsg AsgMax = new ShaderIrAsg(OpCode.Gpr0(), OpMax);
                ShaderIrAsg AsgMin = new ShaderIrAsg(OpCode.Gpr0(), OpMin);

                Block.AddNode(OpCode.PredNode(new ShaderIrCond(PredN, AsgMax, Not: true)));
                Block.AddNode(OpCode.PredNode(new ShaderIrCond(PredN, AsgMin, Not: false)));
            }
        }