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 EmitF2i(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(); } 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); } bool Signed = Type >= IntType.S8; int Size = 8 << ((int)Type & 3); if (Size < 32) { uint Mask = uint.MaxValue >> (32 - Size); float CMin = 0; float CMax = Mask; if (Signed) { uint HalfMask = Mask >> 1; CMin -= HalfMask + 1; CMax = HalfMask; } ShaderIrOperImmf IMin = new ShaderIrOperImmf(CMin); ShaderIrOperImmf IMax = new ShaderIrOperImmf(CMax); OperA = new ShaderIrOp(ShaderIrInst.Fclamp, OperA, IMin, IMax); } ShaderIrInst Inst = Signed ? ShaderIrInst.Ftos : ShaderIrInst.Ftou; ShaderIrNode Op = new ShaderIrOp(Inst, OperA); Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode)); }
private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper) { bool Na = ((OpCode >> 43) & 1) != 0; bool Ab = ((OpCode >> 44) & 1) != 0; bool Nb = ((OpCode >> 53) & 1) != 0; bool Aa = ((OpCode >> 54) & 1) != 0; ShaderIrNode OperA = GetOperGpr8(OpCode), OperB; switch (Oper) { case ShaderOper.CR: OperB = GetOperCbuf34(OpCode); break; case ShaderOper.Imm: OperB = GetOperImm19_20(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; if (IsFloat) { OperA = GetAluAbsNeg(OperA, Aa, Na); OperB = GetAluAbsNeg(OperB, Ab, Nb); CmpInst = GetCmpF(OpCode); } else { CmpInst = GetCmp(OpCode); } ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB); ShaderIrInst LopInst = GetBLop(OpCode); ShaderIrOperPred PNode = GetOperPred39(OpCode); ShaderIrOperImmf Imm0 = new ShaderIrOperImmf(0); ShaderIrOperImmf Imm1 = new ShaderIrOperImmf(1); ShaderIrNode Asg0 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm0); ShaderIrNode Asg1 = new ShaderIrAsg(GetOperGpr0(OpCode), 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(GetPredNode(Asg0, OpCode)); Block.AddNode(GetPredNode(Asg1, OpCode)); }
private static void EmitF2I(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(); } 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); } bool signed = type >= IntType.S8; int size = 8 << ((int)type & 3); if (size < 32) { uint mask = uint.MaxValue >> (32 - size); float cMin = 0; float cMax = mask; if (signed) { uint halfMask = mask >> 1; cMin -= halfMask + 1; cMax = halfMask; } ShaderIrOperImmf min = new ShaderIrOperImmf(cMin); ShaderIrOperImmf max = new ShaderIrOperImmf(cMax); operA = new ShaderIrOp(ShaderIrInst.Fclamp, operA, min, max); } ShaderIrInst inst = signed ? ShaderIrInst.Ftos : ShaderIrInst.Ftou; ShaderIrNode op = new ShaderIrOp(inst, operA); block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); }
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)); }