using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; 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 BfeR(EmitterContext context) { InstBfeR op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcReg(context, op.SrcB); EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); } public static void BfeI(EmitterContext context) { InstBfeI op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); } public static void BfeC(EmitterContext context) { InstBfeC op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); } public static void BfiR(EmitterContext context) { InstBfiR op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcReg(context, op.SrcB); var srcC = GetSrcReg(context, op.SrcC); EmitBfi(context, srcA, srcB, srcC, op.Dest); } public static void BfiI(EmitterContext context) { InstBfiI op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); var srcC = GetSrcReg(context, op.SrcC); EmitBfi(context, srcA, srcB, srcC, op.Dest); } public static void BfiC(EmitterContext context) { InstBfiC op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); var srcC = GetSrcReg(context, op.SrcC); EmitBfi(context, srcA, srcB, srcC, op.Dest); } public static void BfiRc(EmitterContext context) { InstBfiRc op = context.GetOp(); var srcA = GetSrcReg(context, op.SrcA); var srcB = GetSrcReg(context, op.SrcC); var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); EmitBfi(context, srcA, srcB, srcC, op.Dest); } public static void FloR(EmitterContext context) { InstFloR op = context.GetOp(); EmitFlo(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB, op.Sh, op.Signed); } public static void FloI(EmitterContext context) { InstFloI op = context.GetOp(); EmitFlo(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB, op.Sh, op.Signed); } public static void FloC(EmitterContext context) { InstFloC op = context.GetOp(); EmitFlo(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB, op.Sh, op.Signed); } public static void PopcR(EmitterContext context) { InstPopcR op = context.GetOp(); EmitPopc(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB); } public static void PopcI(EmitterContext context) { InstPopcI op = context.GetOp(); EmitPopc(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB); } public static void PopcC(EmitterContext context) { InstPopcC op = context.GetOp(); EmitPopc(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB); } private static void EmitBfe( EmitterContext context, Operand srcA, Operand srcB, int rd, bool bitReverse, bool isSigned) { if (bitReverse) { srcA = context.BitfieldReverse(srcA); } Operand position = context.BitwiseAnd(srcB, Const(0xff)); Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); Operand res = isSigned ? context.BitfieldExtractS32(srcA, position, size) : context.BitfieldExtractU32(srcA, position, size); context.Copy(GetDest(rd), res); // TODO: CC, X, corner cases. } private static void EmitBfi(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int rd) { Operand position = context.BitwiseAnd(srcB, Const(0xff)); Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); Operand res = context.BitfieldInsert(srcC, srcA, position, size); context.Copy(GetDest(rd), res); } private static void EmitFlo(EmitterContext context, Operand src, int rd, bool invert, bool sh, bool isSigned) { Operand srcB = context.BitwiseNot(src, invert); Operand res; if (sh) { res = context.FindLSB(context.BitfieldReverse(srcB)); } else { res = isSigned ? context.FindMSBS32(srcB) : context.FindMSBU32(srcB); } context.Copy(GetDest(rd), res); } private static void EmitPopc(EmitterContext context, Operand src, int rd, bool invert) { Operand srcB = context.BitwiseNot(src, invert); Operand res = context.BitCount(srcB); context.Copy(GetDest(rd), res); } } }