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 }