InstEmitBitfield.cs
1 using Ryujinx.Graphics.Shader.Decoders; 2 using Ryujinx.Graphics.Shader.IntermediateRepresentation; 3 using Ryujinx.Graphics.Shader.Translation; 4 5 using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; 6 using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; 7 8 namespace Ryujinx.Graphics.Shader.Instructions 9 { 10 static partial class InstEmit 11 { 12 public static void BfeR(EmitterContext context) 13 { 14 InstBfeR op = context.GetOp<InstBfeR>(); 15 16 var srcA = GetSrcReg(context, op.SrcA); 17 var srcB = GetSrcReg(context, op.SrcB); 18 19 EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); 20 } 21 22 public static void BfeI(EmitterContext context) 23 { 24 InstBfeI op = context.GetOp<InstBfeI>(); 25 26 var srcA = GetSrcReg(context, op.SrcA); 27 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 28 29 EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); 30 } 31 32 public static void BfeC(EmitterContext context) 33 { 34 InstBfeC op = context.GetOp<InstBfeC>(); 35 36 var srcA = GetSrcReg(context, op.SrcA); 37 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 38 39 EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); 40 } 41 42 public static void BfiR(EmitterContext context) 43 { 44 InstBfiR op = context.GetOp<InstBfiR>(); 45 46 var srcA = GetSrcReg(context, op.SrcA); 47 var srcB = GetSrcReg(context, op.SrcB); 48 var srcC = GetSrcReg(context, op.SrcC); 49 50 EmitBfi(context, srcA, srcB, srcC, op.Dest); 51 } 52 53 public static void BfiI(EmitterContext context) 54 { 55 InstBfiI op = context.GetOp<InstBfiI>(); 56 57 var srcA = GetSrcReg(context, op.SrcA); 58 var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); 59 var srcC = GetSrcReg(context, op.SrcC); 60 61 EmitBfi(context, srcA, srcB, srcC, op.Dest); 62 } 63 64 public static void BfiC(EmitterContext context) 65 { 66 InstBfiC op = context.GetOp<InstBfiC>(); 67 68 var srcA = GetSrcReg(context, op.SrcA); 69 var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 70 var srcC = GetSrcReg(context, op.SrcC); 71 72 EmitBfi(context, srcA, srcB, srcC, op.Dest); 73 } 74 75 public static void BfiRc(EmitterContext context) 76 { 77 InstBfiRc op = context.GetOp<InstBfiRc>(); 78 79 var srcA = GetSrcReg(context, op.SrcA); 80 var srcB = GetSrcReg(context, op.SrcC); 81 var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); 82 83 EmitBfi(context, srcA, srcB, srcC, op.Dest); 84 } 85 86 public static void FloR(EmitterContext context) 87 { 88 InstFloR op = context.GetOp<InstFloR>(); 89 90 EmitFlo(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB, op.Sh, op.Signed); 91 } 92 93 public static void FloI(EmitterContext context) 94 { 95 InstFloI op = context.GetOp<InstFloI>(); 96 97 EmitFlo(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB, op.Sh, op.Signed); 98 } 99 100 public static void FloC(EmitterContext context) 101 { 102 InstFloC op = context.GetOp<InstFloC>(); 103 104 EmitFlo(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB, op.Sh, op.Signed); 105 } 106 107 public static void PopcR(EmitterContext context) 108 { 109 InstPopcR op = context.GetOp<InstPopcR>(); 110 111 EmitPopc(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB); 112 } 113 114 public static void PopcI(EmitterContext context) 115 { 116 InstPopcI op = context.GetOp<InstPopcI>(); 117 118 EmitPopc(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB); 119 } 120 121 public static void PopcC(EmitterContext context) 122 { 123 InstPopcC op = context.GetOp<InstPopcC>(); 124 125 EmitPopc(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB); 126 } 127 128 private static void EmitBfe( 129 EmitterContext context, 130 Operand srcA, 131 Operand srcB, 132 int rd, 133 bool bitReverse, 134 bool isSigned) 135 { 136 if (bitReverse) 137 { 138 srcA = context.BitfieldReverse(srcA); 139 } 140 141 Operand position = context.BitwiseAnd(srcB, Const(0xff)); 142 143 Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); 144 145 Operand res = isSigned 146 ? context.BitfieldExtractS32(srcA, position, size) 147 : context.BitfieldExtractU32(srcA, position, size); 148 149 context.Copy(GetDest(rd), res); 150 151 // TODO: CC, X, corner cases. 152 } 153 154 private static void EmitBfi(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int rd) 155 { 156 Operand position = context.BitwiseAnd(srcB, Const(0xff)); 157 158 Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); 159 160 Operand res = context.BitfieldInsert(srcC, srcA, position, size); 161 162 context.Copy(GetDest(rd), res); 163 } 164 165 private static void EmitFlo(EmitterContext context, Operand src, int rd, bool invert, bool sh, bool isSigned) 166 { 167 Operand srcB = context.BitwiseNot(src, invert); 168 169 Operand res; 170 171 if (sh) 172 { 173 res = context.FindLSB(context.BitfieldReverse(srcB)); 174 } 175 else 176 { 177 res = isSigned 178 ? context.FindMSBS32(srcB) 179 : context.FindMSBU32(srcB); 180 } 181 182 context.Copy(GetDest(rd), res); 183 } 184 185 private static void EmitPopc(EmitterContext context, Operand src, int rd, bool invert) 186 { 187 Operand srcB = context.BitwiseNot(src, invert); 188 189 Operand res = context.BitCount(srcB); 190 191 context.Copy(GetDest(rd), res); 192 } 193 } 194 }