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))); }
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)); }
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)); }
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))); }
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)); }
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))); }
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))); }
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))); }
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)); }
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)))); }
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))); }
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)); }
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))); }
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))); }
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)); }
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))); }
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))); }
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)); } }
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))); }
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)); }
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))); }
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))); }
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))); }
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)); }
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)); }
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)))); }
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)))); }
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)); }
private static void EmitIset(ShaderIrBlock Block, long OpCode, ShaderOper Oper) { EmitSet(Block, OpCode, false, Oper); }
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))); } }