| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- using Ryujinx.Graphics.Shader.Decoders;
- using Ryujinx.Graphics.Shader.IntermediateRepresentation;
- using Ryujinx.Graphics.Shader.Translation;
- using System;
- using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
- using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
- using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
- namespace Ryujinx.Graphics.Shader.Instructions
- {
- static partial class InstEmit
- {
- public static void DsetR(EmitterContext context)
- {
- InstDsetR op = context.GetOp<InstDsetR>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcReg(context, op.SrcB, isFP64: true);
- EmitFset(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.Dest,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.BVal,
- op.WriteCC,
- isFP64: true);
- }
- public static void DsetI(EmitterContext context)
- {
- InstDsetI op = context.GetOp<InstDsetI>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true);
- EmitFset(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.Dest,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.BVal,
- op.WriteCC,
- isFP64: true);
- }
- public static void DsetC(EmitterContext context)
- {
- InstDsetC op = context.GetOp<InstDsetC>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true);
- EmitFset(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.Dest,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.BVal,
- op.WriteCC,
- isFP64: true);
- }
- public static void DsetpR(EmitterContext context)
- {
- InstDsetpR op = context.GetOp<InstDsetpR>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcReg(context, op.SrcB, isFP64: true);
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- writeCC: false,
- isFP64: true);
- }
- public static void DsetpI(EmitterContext context)
- {
- InstDsetpI op = context.GetOp<InstDsetpI>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true);
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- writeCC: false,
- isFP64: true);
- }
- public static void DsetpC(EmitterContext context)
- {
- InstDsetpC op = context.GetOp<InstDsetpC>();
- var srcA = GetSrcReg(context, op.SrcA, isFP64: true);
- var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true);
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- writeCC: false,
- isFP64: true);
- }
- public static void FcmpR(EmitterContext context)
- {
- InstFcmpR op = context.GetOp<InstFcmpR>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcReg(context, op.SrcB);
- var srcC = GetSrcReg(context, op.SrcC);
- EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest);
- }
- public static void FcmpI(EmitterContext context)
- {
- InstFcmpI op = context.GetOp<InstFcmpI>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20));
- var srcC = GetSrcReg(context, op.SrcC);
- EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest);
- }
- public static void FcmpC(EmitterContext context)
- {
- InstFcmpC op = context.GetOp<InstFcmpC>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
- var srcC = GetSrcReg(context, op.SrcC);
- EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest);
- }
- public static void FcmpRc(EmitterContext context)
- {
- InstFcmpRc op = context.GetOp<InstFcmpRc>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcReg(context, op.SrcC);
- var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
- EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest);
- }
- public static void FsetR(EmitterContext context)
- {
- InstFsetR op = context.GetOp<InstFsetR>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcReg(context, op.SrcB);
- EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC);
- }
- public static void FsetC(EmitterContext context)
- {
- InstFsetC op = context.GetOp<InstFsetC>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
- EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC);
- }
- public static void FsetI(EmitterContext context)
- {
- InstFsetI op = context.GetOp<InstFsetI>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20));
- EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC);
- }
- public static void FsetpR(EmitterContext context)
- {
- InstFsetpR op = context.GetOp<InstFsetpR>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcReg(context, op.SrcB);
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.WriteCC);
- }
- public static void FsetpI(EmitterContext context)
- {
- InstFsetpI op = context.GetOp<InstFsetpI>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20));
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.WriteCC);
- }
- public static void FsetpC(EmitterContext context)
- {
- InstFsetpC op = context.GetOp<InstFsetpC>();
- var srcA = GetSrcReg(context, op.SrcA);
- var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
- EmitFsetp(
- context,
- op.FComp,
- op.Bop,
- srcA,
- srcB,
- op.SrcPred,
- op.SrcPredInv,
- op.DestPred,
- op.DestPredInv,
- op.AbsA,
- op.AbsB,
- op.NegA,
- op.NegB,
- op.WriteCC);
- }
- public static void Hset2R(EmitterContext context)
- {
- InstHset2R op = context.GetOp<InstHset2R>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB);
- EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval);
- }
- public static void Hset2I(EmitterContext context)
- {
- InstHset2I op = context.GetOp<InstHset2I>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1);
- EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval);
- }
- public static void Hset2C(EmitterContext context)
- {
- InstHset2C op = context.GetOp<InstHset2C>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, false);
- EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval);
- }
- public static void Hsetp2R(EmitterContext context)
- {
- InstHsetp2R op = context.GetOp<InstHsetp2R>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB);
- EmitHsetp2(context, op.FComp2, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd);
- }
- public static void Hsetp2I(EmitterContext context)
- {
- InstHsetp2I op = context.GetOp<InstHsetp2I>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1);
- EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd);
- }
- public static void Hsetp2C(EmitterContext context)
- {
- InstHsetp2C op = context.GetOp<InstHsetp2C>();
- var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA);
- var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, op.AbsB);
- EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd);
- }
- private static void EmitFcmp(EmitterContext context, FComp cmpOp, Operand srcA, Operand srcB, Operand srcC, int rd)
- {
- Operand cmpRes = GetFPComparison(context, cmpOp, srcC, ConstF(0));
- Operand res = context.ConditionalSelect(cmpRes, srcA, srcB);
- context.Copy(GetDest(rd), res);
- }
- private static void EmitFset(
- EmitterContext context,
- FComp cmpOp,
- BoolOp logicOp,
- Operand srcA,
- Operand srcB,
- int srcPred,
- bool srcPredInv,
- int rd,
- bool absoluteA,
- bool absoluteB,
- bool negateA,
- bool negateB,
- bool boolFloat,
- bool writeCC,
- bool isFP64 = false)
- {
- Instruction fpType = isFP64 ? Instruction.FP64 : Instruction.FP32;
- srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType);
- srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType);
- Operand res = GetFPComparison(context, cmpOp, srcA, srcB, fpType);
- Operand pred = GetPredicate(context, srcPred, srcPredInv);
- res = GetPredLogicalOp(context, logicOp, res, pred);
- Operand dest = GetDest(rd);
- if (boolFloat)
- {
- res = context.ConditionalSelect(res, ConstF(1), Const(0));
- context.Copy(dest, res);
- SetFPZnFlags(context, res, writeCC);
- }
- else
- {
- context.Copy(dest, res);
- SetZnFlags(context, res, writeCC, extended: false);
- }
- }
- private static void EmitFsetp(
- EmitterContext context,
- FComp cmpOp,
- BoolOp logicOp,
- Operand srcA,
- Operand srcB,
- int srcPred,
- bool srcPredInv,
- int destPred,
- int destPredInv,
- bool absoluteA,
- bool absoluteB,
- bool negateA,
- bool negateB,
- bool writeCC,
- bool isFP64 = false)
- {
- Instruction fpType = isFP64 ? Instruction.FP64 : Instruction.FP32;
- srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType);
- srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType);
- Operand p0Res = GetFPComparison(context, cmpOp, srcA, srcB, fpType);
- Operand p1Res = context.BitwiseNot(p0Res);
- Operand pred = GetPredicate(context, srcPred, srcPredInv);
- p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred);
- p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred);
- context.Copy(Register(destPred, RegisterType.Predicate), p0Res);
- context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res);
- }
- private static void EmitHset2(
- EmitterContext context,
- FComp cmpOp,
- BoolOp logicOp,
- Operand[] srcA,
- Operand[] srcB,
- int srcPred,
- bool srcPredInv,
- int rd,
- bool boolFloat)
- {
- Operand[] res = new Operand[2];
- res[0] = GetFPComparison(context, cmpOp, srcA[0], srcB[0]);
- res[1] = GetFPComparison(context, cmpOp, srcA[1], srcB[1]);
- Operand pred = GetPredicate(context, srcPred, srcPredInv);
- res[0] = GetPredLogicalOp(context, logicOp, res[0], pred);
- res[1] = GetPredLogicalOp(context, logicOp, res[1], pred);
- if (boolFloat)
- {
- res[0] = context.ConditionalSelect(res[0], ConstF(1), Const(0));
- res[1] = context.ConditionalSelect(res[1], ConstF(1), Const(0));
- context.Copy(GetDest(rd), context.PackHalf2x16(res[0], res[1]));
- }
- else
- {
- Operand low = context.BitwiseAnd(res[0], Const(0xffff));
- Operand high = context.ShiftLeft (res[1], Const(16));
- Operand packed = context.BitwiseOr(low, high);
- context.Copy(GetDest(rd), packed);
- }
- }
- private static void EmitHsetp2(
- EmitterContext context,
- FComp cmpOp,
- BoolOp logicOp,
- Operand[] srcA,
- Operand[] srcB,
- int srcPred,
- bool srcPredInv,
- int destPred,
- int destPredInv,
- bool hAnd)
- {
- Operand p0Res = GetFPComparison(context, cmpOp, srcA[0], srcB[0]);
- Operand p1Res = GetFPComparison(context, cmpOp, srcA[1], srcB[1]);
- if (hAnd)
- {
- p0Res = context.BitwiseAnd(p0Res, p1Res);
- p1Res = context.BitwiseNot(p0Res);
- }
- Operand pred = GetPredicate(context, srcPred, srcPredInv);
- p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred);
- p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred);
- context.Copy(Register(destPred, RegisterType.Predicate), p0Res);
- context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res);
- }
- private static Operand GetFPComparison(EmitterContext context, FComp cond, Operand srcA, Operand srcB, Instruction fpType = Instruction.FP32)
- {
- Operand res;
- if (cond == FComp.T)
- {
- res = Const(IrConsts.True);
- }
- else if (cond == FComp.F)
- {
- res = Const(IrConsts.False);
- }
- else if (cond == FComp.Nan || cond == FComp.Num)
- {
- res = context.BitwiseOr(context.IsNan(srcA, fpType), context.IsNan(srcB, fpType));
- if (cond == FComp.Num)
- {
- res = context.BitwiseNot(res);
- }
- }
- else
- {
- Instruction inst;
- switch (cond & ~FComp.Nan)
- {
- case FComp.Lt: inst = Instruction.CompareLess; break;
- case FComp.Eq: inst = Instruction.CompareEqual; break;
- case FComp.Le: inst = Instruction.CompareLessOrEqual; break;
- case FComp.Gt: inst = Instruction.CompareGreater; break;
- case FComp.Ne: inst = Instruction.CompareNotEqual; break;
- case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break;
- default: throw new ArgumentException($"Unexpected condition \"{cond}\".");
- }
- res = context.Add(inst | fpType, Local(), srcA, srcB);
- if ((cond & FComp.Nan) != 0)
- {
- res = context.BitwiseOr(res, context.IsNan(srcA, fpType));
- res = context.BitwiseOr(res, context.IsNan(srcB, fpType));
- }
- }
- return res;
- }
- }
- }
|