/ src / Ryujinx.Tests / Cpu / CpuTestSimdTbl.cs
CpuTestSimdTbl.cs
  1  #define SimdTbl
  2  
  3  using ARMeilleure.State;
  4  using NUnit.Framework;
  5  using System.Collections.Generic;
  6  
  7  namespace Ryujinx.Tests.Cpu
  8  {
  9      [Category("SimdTbl")]
 10      public sealed class CpuTestSimdTbl : CpuTest
 11      {
 12  #if SimdTbl
 13  
 14          #region "Helper methods"
 15          private static ulong GenIdxsForTbls(int regs)
 16          {
 17              const byte IdxInRngMin = 0;
 18              byte idxInRngMax = (byte)((16 * regs) - 1);
 19              byte idxOutRngMin = (byte)(16 * regs);
 20              const byte IdxOutRngMax = 255;
 21  
 22              ulong idxs = 0ul;
 23  
 24              for (int cnt = 1; cnt <= 8; cnt++)
 25              {
 26                  ulong idxInRng = TestContext.CurrentContext.Random.NextByte(IdxInRngMin, idxInRngMax);
 27                  ulong idxOutRng = TestContext.CurrentContext.Random.NextByte(idxOutRngMin, IdxOutRngMax);
 28  
 29                  ulong idx = TestContext.CurrentContext.Random.NextBool() ? idxInRng : idxOutRng;
 30  
 31                  idxs = (idxs << 8) | idx;
 32              }
 33  
 34              return idxs;
 35          }
 36          #endregion
 37  
 38          #region "ValueSource (Types)"
 39          private static ulong[] _8B_()
 40          {
 41              return new[] {
 42                  0x0000000000000000ul, 0x7F7F7F7F7F7F7F7Ful,
 43                  0x8080808080808080ul, 0xFFFFFFFFFFFFFFFFul,
 44              };
 45          }
 46  
 47          private static IEnumerable<ulong> _GenIdxsForTbl1_()
 48          {
 49              yield return 0x0000000000000000ul;
 50              yield return 0x7F7F7F7F7F7F7F7Ful;
 51              yield return 0x8080808080808080ul;
 52              yield return 0xFFFFFFFFFFFFFFFFul;
 53  
 54              for (int cnt = 1; cnt <= RndCntIdxs; cnt++)
 55              {
 56                  yield return GenIdxsForTbls(regs: 1);
 57              }
 58          }
 59  
 60          private static IEnumerable<ulong> _GenIdxsForTbl2_()
 61          {
 62              yield return 0x0000000000000000ul;
 63              yield return 0x7F7F7F7F7F7F7F7Ful;
 64              yield return 0x8080808080808080ul;
 65              yield return 0xFFFFFFFFFFFFFFFFul;
 66  
 67              for (int cnt = 1; cnt <= RndCntIdxs; cnt++)
 68              {
 69                  yield return GenIdxsForTbls(regs: 2);
 70              }
 71          }
 72  
 73          private static IEnumerable<ulong> _GenIdxsForTbl3_()
 74          {
 75              yield return 0x0000000000000000ul;
 76              yield return 0x7F7F7F7F7F7F7F7Ful;
 77              yield return 0x8080808080808080ul;
 78              yield return 0xFFFFFFFFFFFFFFFFul;
 79  
 80              for (int cnt = 1; cnt <= RndCntIdxs; cnt++)
 81              {
 82                  yield return GenIdxsForTbls(regs: 3);
 83              }
 84          }
 85  
 86          private static IEnumerable<ulong> _GenIdxsForTbl4_()
 87          {
 88              yield return 0x0000000000000000ul;
 89              yield return 0x7F7F7F7F7F7F7F7Ful;
 90              yield return 0x8080808080808080ul;
 91              yield return 0xFFFFFFFFFFFFFFFFul;
 92  
 93              for (int cnt = 1; cnt <= RndCntIdxs; cnt++)
 94              {
 95                  yield return GenIdxsForTbls(regs: 4);
 96              }
 97          }
 98          #endregion
 99  
100          #region "ValueSource (Opcodes)"
101          private static uint[] _SingleRegisterTable_V_8B_16B_()
102          {
103              return new[]
104              {
105                  0x0E000000u, // TBL V0.8B, { V0.16B }, V0.8B
106                  0x0E001000u, // TBX V0.8B, { V0.16B }, V0.8B
107              };
108          }
109  
110          private static uint[] _TwoRegisterTable_V_8B_16B_()
111          {
112              return new[]
113              {
114                  0x0E002000u, // TBL V0.8B, { V0.16B, V1.16B }, V0.8B
115                  0x0E003000u, // TBX V0.8B, { V0.16B, V1.16B }, V0.8B
116              };
117          }
118  
119          private static uint[] _ThreeRegisterTable_V_8B_16B_()
120          {
121              return new[]
122              {
123                  0x0E004000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
124                  0x0E005000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B }, V0.8B
125              };
126          }
127  
128          private static uint[] _FourRegisterTable_V_8B_16B_()
129          {
130              return new[]
131              {
132                  0x0E006000u, // TBL V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
133                  0x0E006000u, // TBX V0.8B, { V0.16B, V1.16B, V2.16B, V3.16B }, V0.8B
134              };
135          }
136          #endregion
137  
138          private const int RndCntIdxs = 2;
139  
140          [Test, Pairwise]
141          public void SingleRegisterTable_V_8B_16B([ValueSource(nameof(_SingleRegisterTable_V_8B_16B_))] uint opcodes,
142                                                   [Values(0u)] uint rd,
143                                                   [Values(1u)] uint rn,
144                                                   [Values(2u)] uint rm,
145                                                   [ValueSource(nameof(_8B_))] ulong z,
146                                                   [ValueSource(nameof(_8B_))] ulong table0,
147                                                   [ValueSource(nameof(_GenIdxsForTbl1_))] ulong indexes,
148                                                   [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
149          {
150              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
151              opcodes |= ((q & 1) << 30);
152  
153              V128 v0 = MakeVectorE0E1(z, z);
154              V128 v1 = MakeVectorE0E1(table0, table0);
155              V128 v2 = MakeVectorE0E1(indexes, q == 1u ? indexes : 0ul);
156  
157              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2);
158  
159              CompareAgainstUnicorn();
160          }
161  
162          [Test, Pairwise]
163          public void TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes,
164                                                [Values(0u)] uint rd,
165                                                [Values(1u)] uint rn,
166                                                [Values(3u)] uint rm,
167                                                [ValueSource(nameof(_8B_))] ulong z,
168                                                [ValueSource(nameof(_8B_))] ulong table0,
169                                                [ValueSource(nameof(_8B_))] ulong table1,
170                                                [ValueSource(nameof(_GenIdxsForTbl2_))] ulong indexes,
171                                                [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
172          {
173              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
174              opcodes |= ((q & 1) << 30);
175  
176              V128 v0 = MakeVectorE0E1(z, z);
177              V128 v1 = MakeVectorE0E1(table0, table0);
178              V128 v2 = MakeVectorE0E1(table1, table1);
179              V128 v3 = MakeVectorE0E1(indexes, q == 1u ? indexes : 0ul);
180  
181              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3);
182  
183              CompareAgainstUnicorn();
184          }
185  
186          [Test, Pairwise]
187          public void Mod_TwoRegisterTable_V_8B_16B([ValueSource(nameof(_TwoRegisterTable_V_8B_16B_))] uint opcodes,
188                                                    [Values(30u, 1u)] uint rd,
189                                                    [Values(31u)] uint rn,
190                                                    [Values(1u, 30u)] uint rm,
191                                                    [ValueSource(nameof(_8B_))] ulong z,
192                                                    [ValueSource(nameof(_8B_))] ulong table0,
193                                                    [ValueSource(nameof(_8B_))] ulong table1,
194                                                    [ValueSource(nameof(_GenIdxsForTbl2_))] ulong indexes,
195                                                    [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
196          {
197              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
198              opcodes |= ((q & 1) << 30);
199  
200              V128 v30 = MakeVectorE0E1(z, z);
201              V128 v31 = MakeVectorE0E1(table0, table0);
202              V128 v0 = MakeVectorE0E1(table1, table1);
203              V128 v1 = MakeVectorE0E1(indexes, indexes);
204  
205              SingleOpcode(opcodes, v0: v0, v1: v1, v30: v30, v31: v31);
206  
207              CompareAgainstUnicorn();
208          }
209  
210          [Test, Pairwise]
211          public void ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes,
212                                                  [Values(0u)] uint rd,
213                                                  [Values(1u)] uint rn,
214                                                  [Values(4u)] uint rm,
215                                                  [ValueSource(nameof(_8B_))] ulong z,
216                                                  [ValueSource(nameof(_8B_))] ulong table0,
217                                                  [ValueSource(nameof(_8B_))] ulong table1,
218                                                  [ValueSource(nameof(_8B_))] ulong table2,
219                                                  [ValueSource(nameof(_GenIdxsForTbl3_))] ulong indexes,
220                                                  [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
221          {
222              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
223              opcodes |= ((q & 1) << 30);
224  
225              V128 v0 = MakeVectorE0E1(z, z);
226              V128 v1 = MakeVectorE0E1(table0, table0);
227              V128 v2 = MakeVectorE0E1(table1, table1);
228              V128 v3 = MakeVectorE0E1(table2, table2);
229              V128 v4 = MakeVectorE0E1(indexes, q == 1u ? indexes : 0ul);
230  
231              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4);
232  
233              CompareAgainstUnicorn();
234          }
235  
236          [Test, Pairwise]
237          public void Mod_ThreeRegisterTable_V_8B_16B([ValueSource(nameof(_ThreeRegisterTable_V_8B_16B_))] uint opcodes,
238                                                      [Values(30u, 2u)] uint rd,
239                                                      [Values(31u)] uint rn,
240                                                      [Values(2u, 30u)] uint rm,
241                                                      [ValueSource(nameof(_8B_))] ulong z,
242                                                      [ValueSource(nameof(_8B_))] ulong table0,
243                                                      [ValueSource(nameof(_8B_))] ulong table1,
244                                                      [ValueSource(nameof(_8B_))] ulong table2,
245                                                      [ValueSource(nameof(_GenIdxsForTbl3_))] ulong indexes,
246                                                      [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
247          {
248              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
249              opcodes |= ((q & 1) << 30);
250  
251              V128 v30 = MakeVectorE0E1(z, z);
252              V128 v31 = MakeVectorE0E1(table0, table0);
253              V128 v0 = MakeVectorE0E1(table1, table1);
254              V128 v1 = MakeVectorE0E1(table2, table2);
255              V128 v2 = MakeVectorE0E1(indexes, indexes);
256  
257              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v30: v30, v31: v31);
258  
259              CompareAgainstUnicorn();
260          }
261  
262          [Test, Pairwise]
263          public void FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes,
264                                                 [Values(0u)] uint rd,
265                                                 [Values(1u)] uint rn,
266                                                 [Values(5u)] uint rm,
267                                                 [ValueSource(nameof(_8B_))] ulong z,
268                                                 [ValueSource(nameof(_8B_))] ulong table0,
269                                                 [ValueSource(nameof(_8B_))] ulong table1,
270                                                 [ValueSource(nameof(_8B_))] ulong table2,
271                                                 [ValueSource(nameof(_8B_))] ulong table3,
272                                                 [ValueSource(nameof(_GenIdxsForTbl4_))] ulong indexes,
273                                                 [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
274          {
275              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
276              opcodes |= ((q & 1) << 30);
277  
278              V128 v0 = MakeVectorE0E1(z, z);
279              V128 v1 = MakeVectorE0E1(table0, table0);
280              V128 v2 = MakeVectorE0E1(table1, table1);
281              V128 v3 = MakeVectorE0E1(table2, table2);
282              V128 v4 = MakeVectorE0E1(table3, table3);
283              V128 v5 = MakeVectorE0E1(indexes, q == 1u ? indexes : 0ul);
284  
285              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3, v4: v4, v5: v5);
286  
287              CompareAgainstUnicorn();
288          }
289  
290          [Test, Pairwise]
291          public void Mod_FourRegisterTable_V_8B_16B([ValueSource(nameof(_FourRegisterTable_V_8B_16B_))] uint opcodes,
292                                                     [Values(30u, 3u)] uint rd,
293                                                     [Values(31u)] uint rn,
294                                                     [Values(3u, 30u)] uint rm,
295                                                     [ValueSource(nameof(_8B_))] ulong z,
296                                                     [ValueSource(nameof(_8B_))] ulong table0,
297                                                     [ValueSource(nameof(_8B_))] ulong table1,
298                                                     [ValueSource(nameof(_8B_))] ulong table2,
299                                                     [ValueSource(nameof(_8B_))] ulong table3,
300                                                     [ValueSource(nameof(_GenIdxsForTbl4_))] ulong indexes,
301                                                     [Values(0b0u, 0b1u)] uint q) // <8B, 16B>
302          {
303              opcodes |= ((rm & 31) << 16) | ((rn & 31) << 5) | ((rd & 31) << 0);
304              opcodes |= ((q & 1) << 30);
305  
306              V128 v30 = MakeVectorE0E1(z, z);
307              V128 v31 = MakeVectorE0E1(table0, table0);
308              V128 v0 = MakeVectorE0E1(table1, table1);
309              V128 v1 = MakeVectorE0E1(table2, table2);
310              V128 v2 = MakeVectorE0E1(table3, table3);
311              V128 v3 = MakeVectorE0E1(indexes, indexes);
312  
313              SingleOpcode(opcodes, v0: v0, v1: v1, v2: v2, v3: v3, v30: v30, v31: v31);
314  
315              CompareAgainstUnicorn();
316          }
317  #endif
318      }
319  }