CpuTestSimdCvt32.cs
1 #define SimdCvt32 2 3 using ARMeilleure.State; 4 using NUnit.Framework; 5 using System; 6 using System.Collections.Generic; 7 8 namespace Ryujinx.Tests.Cpu 9 { 10 [Category("SimdCvt32")] 11 public sealed class CpuTestSimdCvt32 : CpuTest32 12 { 13 #if SimdCvt32 14 15 #region "ValueSource (Opcodes)" 16 private static uint[] _Vrint_AMNP_V_F32_() 17 { 18 return new[] 19 { 20 0xf3ba0500u, // VRINTA.F32 Q0, Q0 21 0xf3ba0680u, // VRINTM.F32 Q0, Q0 22 0xf3ba0400u, // VRINTN.F32 Q0, Q0 23 0xf3ba0780u, // VRINTP.F32 Q0, Q0 24 }; 25 } 26 #endregion 27 28 #region "ValueSource (Types)" 29 private static uint[] _1S_() 30 { 31 return new[] { 32 0x00000000u, 0x7FFFFFFFu, 33 0x80000000u, 0xFFFFFFFFu, 34 }; 35 } 36 37 private static IEnumerable<ulong> _1S_F_() 38 { 39 yield return 0x00000000FF7FFFFFul; // -Max Normal (float.MinValue) 40 yield return 0x0000000080800000ul; // -Min Normal 41 yield return 0x00000000807FFFFFul; // -Max Subnormal 42 yield return 0x0000000080000001ul; // -Min Subnormal (-float.Epsilon) 43 yield return 0x000000007F7FFFFFul; // +Max Normal (float.MaxValue) 44 yield return 0x0000000000800000ul; // +Min Normal 45 yield return 0x00000000007FFFFFul; // +Max Subnormal 46 yield return 0x0000000000000001ul; // +Min Subnormal (float.Epsilon) 47 48 if (!_noZeros) 49 { 50 yield return 0x0000000080000000ul; // -Zero 51 yield return 0x0000000000000000ul; // +Zero 52 } 53 54 if (!_noInfs) 55 { 56 yield return 0x00000000FF800000ul; // -Infinity 57 yield return 0x000000007F800000ul; // +Infinity 58 } 59 60 if (!_noNaNs) 61 { 62 yield return 0x00000000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) 63 yield return 0x00000000FFBFFFFFul; // -SNaN (all ones payload) 64 yield return 0x000000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN) 65 yield return 0x000000007FBFFFFFul; // +SNaN (all ones payload) 66 } 67 68 for (int cnt = 1; cnt <= RndCnt; cnt++) 69 { 70 ulong grbg = TestContext.CurrentContext.Random.NextUInt(); 71 ulong rnd1 = GenNormalS(); 72 ulong rnd2 = GenSubnormalS(); 73 74 yield return (grbg << 32) | rnd1; 75 yield return (grbg << 32) | rnd2; 76 } 77 } 78 79 private static IEnumerable<ulong> _2S_F_() 80 { 81 yield return 0xFF7FFFFFFF7FFFFFul; // -Max Normal (float.MinValue) 82 yield return 0x8080000080800000ul; // -Min Normal 83 yield return 0x807FFFFF807FFFFFul; // -Max Subnormal 84 yield return 0x8000000180000001ul; // -Min Subnormal (-float.Epsilon) 85 yield return 0x7F7FFFFF7F7FFFFFul; // +Max Normal (float.MaxValue) 86 yield return 0x0080000000800000ul; // +Min Normal 87 yield return 0x007FFFFF007FFFFFul; // +Max Subnormal 88 yield return 0x0000000100000001ul; // +Min Subnormal (float.Epsilon) 89 90 if (!_noZeros) 91 { 92 yield return 0x8000000080000000ul; // -Zero 93 yield return 0x0000000000000000ul; // +Zero 94 } 95 96 if (!_noInfs) 97 { 98 yield return 0xFF800000FF800000ul; // -Infinity 99 yield return 0x7F8000007F800000ul; // +Infinity 100 } 101 102 if (!_noNaNs) 103 { 104 yield return 0xFFC00000FFC00000ul; // -QNaN (all zeros payload) (float.NaN) 105 yield return 0xFFBFFFFFFFBFFFFFul; // -SNaN (all ones payload) 106 yield return 0x7FC000007FC00000ul; // +QNaN (all zeros payload) (-float.NaN) (DefaultNaN) 107 yield return 0x7FBFFFFF7FBFFFFFul; // +SNaN (all ones payload) 108 } 109 110 for (int cnt = 1; cnt <= RndCnt; cnt++) 111 { 112 ulong rnd1 = GenNormalS(); 113 ulong rnd2 = GenSubnormalS(); 114 115 yield return (rnd1 << 32) | rnd1; 116 yield return (rnd2 << 32) | rnd2; 117 } 118 } 119 120 private static IEnumerable<ulong> _1D_F_() 121 { 122 yield return 0xFFEFFFFFFFFFFFFFul; // -Max Normal (double.MinValue) 123 yield return 0x8010000000000000ul; // -Min Normal 124 yield return 0x800FFFFFFFFFFFFFul; // -Max Subnormal 125 yield return 0x8000000000000001ul; // -Min Subnormal (-double.Epsilon) 126 yield return 0x7FEFFFFFFFFFFFFFul; // +Max Normal (double.MaxValue) 127 yield return 0x0010000000000000ul; // +Min Normal 128 yield return 0x000FFFFFFFFFFFFFul; // +Max Subnormal 129 yield return 0x0000000000000001ul; // +Min Subnormal (double.Epsilon) 130 131 if (!_noZeros) 132 { 133 yield return 0x8000000000000000ul; // -Zero 134 yield return 0x0000000000000000ul; // +Zero 135 } 136 137 if (!_noInfs) 138 { 139 yield return 0xFFF0000000000000ul; // -Infinity 140 yield return 0x7FF0000000000000ul; // +Infinity 141 } 142 143 if (!_noNaNs) 144 { 145 yield return 0xFFF8000000000000ul; // -QNaN (all zeros payload) (double.NaN) 146 yield return 0xFFF7FFFFFFFFFFFFul; // -SNaN (all ones payload) 147 yield return 0x7FF8000000000000ul; // +QNaN (all zeros payload) (-double.NaN) (DefaultNaN) 148 yield return 0x7FF7FFFFFFFFFFFFul; // +SNaN (all ones payload) 149 } 150 151 for (int cnt = 1; cnt <= RndCnt; cnt++) 152 { 153 ulong rnd1 = GenNormalD(); 154 ulong rnd2 = GenSubnormalD(); 155 156 yield return rnd1; 157 yield return rnd2; 158 } 159 } 160 #endregion 161 162 private const int RndCnt = 2; 163 164 private static readonly bool _noZeros = false; 165 private static readonly bool _noInfs = false; 166 private static readonly bool _noNaNs = false; 167 168 [Explicit] 169 [Test, Pairwise, Description("VCVT.<dt>.F32 <Sd>, <Sm>")] 170 public void Vcvt_F32_I32([Values(0u, 1u, 2u, 3u)] uint rd, 171 [Values(0u, 1u, 2u, 3u)] uint rm, 172 [ValueSource(nameof(_1S_F_))] ulong s0, 173 [ValueSource(nameof(_1S_F_))] ulong s1, 174 [ValueSource(nameof(_1S_F_))] ulong s2, 175 [ValueSource(nameof(_1S_F_))] ulong s3, 176 [Values] bool unsigned) // <U32, S32> 177 { 178 uint opcode = 0xeebc0ac0u; // VCVT.U32.F32 S0, S0 179 180 if (!unsigned) 181 { 182 opcode |= 1 << 16; // opc2<0> 183 } 184 185 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 186 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 187 188 V128 v0 = MakeVectorE0E1E2E3((uint)s0, (uint)s1, (uint)s2, (uint)s3); 189 190 SingleOpcode(opcode, v0: v0); 191 192 CompareAgainstUnicorn(); 193 } 194 195 [Explicit] 196 [Test, Pairwise, Description("VCVT.<dt>.F64 <Sd>, <Dm>")] 197 public void Vcvt_F64_I32([Values(0u, 1u, 2u, 3u)] uint rd, 198 [Values(0u, 1u)] uint rm, 199 [ValueSource(nameof(_1D_F_))] ulong d0, 200 [ValueSource(nameof(_1D_F_))] ulong d1, 201 [Values] bool unsigned) // <U32, S32> 202 { 203 uint opcode = 0xeebc0bc0u; // VCVT.U32.F64 S0, D0 204 205 if (!unsigned) 206 { 207 opcode |= 1 << 16; // opc2<0> 208 } 209 210 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 211 opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); 212 213 V128 v0 = MakeVectorE0E1(d0, d1); 214 215 SingleOpcode(opcode, v0: v0); 216 217 CompareAgainstUnicorn(); 218 } 219 220 [Explicit] 221 [Test, Pairwise, Description("VCVT.F32.<dt> <Sd>, <Sm>")] 222 public void Vcvt_I32_F32([Values(0u, 1u, 2u, 3u)] uint rd, 223 [Values(0u, 1u, 2u, 3u)] uint rm, 224 [ValueSource(nameof(_1S_))] uint s0, 225 [ValueSource(nameof(_1S_))] uint s1, 226 [ValueSource(nameof(_1S_))] uint s2, 227 [ValueSource(nameof(_1S_))] uint s3, 228 [Values] bool unsigned, // <U32, S32> 229 [Values(RMode.Rn)] RMode rMode) 230 { 231 uint opcode = 0xeeb80a40u; // VCVT.F32.U32 S0, S0 232 233 if (!unsigned) 234 { 235 opcode |= 1 << 7; // op 236 } 237 238 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 239 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 240 241 V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3); 242 243 int fpscr = (int)rMode << (int)Fpcr.RMode; 244 245 SingleOpcode(opcode, v0: v0, fpscr: fpscr); 246 247 CompareAgainstUnicorn(); 248 } 249 250 [Explicit] 251 [Test, Pairwise, Description("VCVT.F64.<dt> <Dd>, <Sm>")] 252 public void Vcvt_I32_F64([Values(0u, 1u)] uint rd, 253 [Values(0u, 1u, 2u, 3u)] uint rm, 254 [ValueSource(nameof(_1S_))] uint s0, 255 [ValueSource(nameof(_1S_))] uint s1, 256 [ValueSource(nameof(_1S_))] uint s2, 257 [ValueSource(nameof(_1S_))] uint s3, 258 [Values] bool unsigned, // <U32, S32> 259 [Values(RMode.Rn)] RMode rMode) 260 { 261 uint opcode = 0xeeb80b40u; // VCVT.F64.U32 D0, S0 262 263 if (!unsigned) 264 { 265 opcode |= 1 << 7; // op 266 } 267 268 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 269 opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); 270 271 V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3); 272 273 int fpscr = (int)rMode << (int)Fpcr.RMode; 274 275 SingleOpcode(opcode, v0: v0, fpscr: fpscr); 276 277 CompareAgainstUnicorn(); 278 } 279 280 [Test, Pairwise] 281 [Explicit] 282 public void Vrint_AMNP_V_F32([ValueSource(nameof(_Vrint_AMNP_V_F32_))] uint opcode, 283 [Values(0u, 1u, 2u, 3u)] uint rd, 284 [Values(0u, 1u, 2u, 3u)] uint rm, 285 [ValueSource(nameof(_2S_F_))] ulong d0, 286 [ValueSource(nameof(_2S_F_))] ulong d1, 287 [ValueSource(nameof(_2S_F_))] ulong d2, 288 [ValueSource(nameof(_2S_F_))] ulong d3, 289 [Values] bool q) 290 { 291 if (q) 292 { 293 opcode |= 1 << 6; 294 295 rd >>= 1; 296 rd <<= 1; 297 rm >>= 1; 298 rm <<= 1; 299 } 300 301 opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); 302 opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); 303 304 V128 v0 = MakeVectorE0E1(d0, d1); 305 V128 v1 = MakeVectorE0E1(d2, d3); 306 307 SingleOpcode(opcode, v0: v0, v1: v1); 308 309 CompareAgainstUnicorn(); 310 } 311 312 [Test, Pairwise, Description("VRINTX.F<size> <Sd>, <Sm>")] 313 public void Vrintx_S([Values(0u, 1u)] uint rd, 314 [Values(0u, 1u)] uint rm, 315 [Values(2u, 3u)] uint size, 316 [ValueSource(nameof(_1D_F_))] ulong s0, 317 [ValueSource(nameof(_1D_F_))] ulong s1, 318 [ValueSource(nameof(_1D_F_))] ulong s2, 319 [Values(RMode.Rn, RMode.Rm, RMode.Rp)] RMode rMode) 320 { 321 uint opcode = 0xEB70A40; 322 V128 v0, v1, v2; 323 if (size == 2) 324 { 325 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 326 opcode |= ((rd & 0x1e) >> 11) | ((rm & 0x1) << 22); 327 v0 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s0), (uint)BitConverter.SingleToInt32Bits(s0)); 328 v1 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s1), (uint)BitConverter.SingleToInt32Bits(s0)); 329 v2 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s2), (uint)BitConverter.SingleToInt32Bits(s1)); 330 } 331 else 332 { 333 opcode |= ((rm & 0xf) << 0) | ((rd & 0x10) << 1); 334 opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); 335 v0 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s0), (uint)BitConverter.DoubleToInt64Bits(s0)); 336 v1 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s1), (uint)BitConverter.DoubleToInt64Bits(s0)); 337 v2 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s2), (uint)BitConverter.DoubleToInt64Bits(s1)); 338 } 339 340 opcode |= ((size & 3) << 8); 341 342 int fpscr = (int)rMode << (int)Fpcr.RMode; 343 SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr); 344 345 CompareAgainstUnicorn(); 346 } 347 348 [Explicit] 349 [Test, Pairwise, Description("VCVT<top>.F16.F32 <Sd>, <Dm>")] 350 public void Vcvt_F32_F16([Values(0u, 1u, 2u, 3u)] uint rd, 351 [Values(0u, 1u, 2u, 3u)] uint rm, 352 [ValueSource(nameof(_1S_))] uint s0, 353 [ValueSource(nameof(_1S_))] uint s1, 354 [ValueSource(nameof(_1S_))] uint s2, 355 [ValueSource(nameof(_1S_))] uint s3, 356 [Values] bool top) 357 { 358 uint opcode = 0xeeb30a40; // VCVTB.F16.F32 S0, D0 359 360 if (top) 361 { 362 opcode |= 1 << 7; 363 } 364 365 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 366 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 367 368 V128 v0 = MakeVectorE0E1E2E3(s0, s1, s2, s3); 369 370 SingleOpcode(opcode, v0: v0); 371 372 CompareAgainstUnicorn(); 373 } 374 375 [Explicit] 376 [Test, Pairwise, Description("VCVT<top>.F16.F64 <Sd>, <Dm>")] 377 public void Vcvt_F64_F16([Values(0u, 1u, 2u, 3u)] uint rd, 378 [Values(0u, 1u)] uint rm, 379 [ValueSource(nameof(_1D_F_))] ulong d0, 380 [ValueSource(nameof(_1D_F_))] ulong d1, 381 [Values] bool top) 382 { 383 uint opcode = 0xeeb30b40; // VCVTB.F16.F64 S0, D0 384 385 if (top) 386 { 387 opcode |= 1 << 7; 388 } 389 390 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 391 opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); 392 393 V128 v0 = MakeVectorE0E1(d0, d1); 394 395 SingleOpcode(opcode, v0: v0); 396 397 CompareAgainstUnicorn(); 398 } 399 400 [Explicit] 401 [Test, Pairwise, Description("VCVT<top>.F<size>.F16 <Vd>, <Sm>")] 402 public void Vcvt_F16_Fx([Values(0u, 1u, 2u, 3u)] uint rd, 403 [Values(0u, 1u, 2u, 3u)] uint rm, 404 [ValueSource(nameof(_1D_F_))] ulong d0, 405 [ValueSource(nameof(_1D_F_))] ulong d1, 406 [Values] bool top, 407 [Values] bool sz) 408 { 409 uint opcode = 0xeeb20a40; // VCVTB.F32.F16 S0, S0 410 411 if (top) 412 { 413 opcode |= 1 << 7; 414 } 415 416 if (sz) 417 { 418 opcode |= 1 << 8; 419 opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); 420 } 421 else 422 { 423 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 424 } 425 426 opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); 427 428 V128 v0 = MakeVectorE0E1(d0, d1); 429 430 SingleOpcode(opcode, v0: v0); 431 432 CompareAgainstUnicorn(); 433 } 434 435 [Test, Pairwise, Description("VCVT.I32.F32 <Vd>, <Vm>, #<fbits>")] 436 public void Vcvt_V_Fixed_F32_I32([Values(0u, 1u, 2u, 3u)] uint vd, 437 [Values(0u, 1u, 2u, 3u)] uint vm, 438 [ValueSource(nameof(_1S_F_))][Random(RndCnt)] ulong s0, 439 [ValueSource(nameof(_1S_F_))][Random(RndCnt)] ulong s1, 440 [ValueSource(nameof(_1S_F_))][Random(RndCnt)] ulong s2, 441 [ValueSource(nameof(_1S_F_))][Random(RndCnt)] ulong s3, 442 [Random(32u, 63u, 1)] uint fixImm, 443 [Values] bool unsigned, 444 [Values] bool q) 445 { 446 uint opcode = 0xF2800F10u; // VCVT.U32.F32 D0, D0, #0 447 448 if (q) 449 { 450 opcode |= 1 << 6; 451 vm <<= 1; 452 vd <<= 1; 453 } 454 455 if (unsigned) 456 { 457 opcode |= 1 << 24; 458 } 459 460 opcode |= ((vm & 0x10) << 1); 461 opcode |= ((vm & 0xf) << 0); 462 463 opcode |= ((vd & 0x10) << 18); 464 opcode |= ((vd & 0xf) << 12); 465 466 opcode |= (fixImm & 0x3f) << 16; 467 468 var v0 = new V128((uint)s0, (uint)s1, (uint)s2, (uint)s3); 469 470 SingleOpcode(opcode, v0: v0); 471 472 CompareAgainstUnicorn(); 473 } 474 475 [Test, Pairwise, Description("VCVT.F32.I32 <Vd>, <Vm>, #<fbits>")] 476 public void Vcvt_V_Fixed_I32_F32([Values(0u, 1u, 2u, 3u)] uint vd, 477 [Values(0u, 1u, 2u, 3u)] uint vm, 478 [ValueSource(nameof(_1S_))][Random(RndCnt)] uint s0, 479 [ValueSource(nameof(_1S_))][Random(RndCnt)] uint s1, 480 [ValueSource(nameof(_1S_))][Random(RndCnt)] uint s2, 481 [ValueSource(nameof(_1S_))][Random(RndCnt)] uint s3, 482 [Range(32u, 63u, 1)] uint fixImm, 483 [Values] bool unsigned, 484 [Values] bool q) 485 { 486 uint opcode = 0xF2800E10u; // VCVT.F32.U32 D0, D0, #0 487 488 if (q) 489 { 490 opcode |= 1 << 6; 491 vm <<= 1; 492 vd <<= 1; 493 } 494 495 if (unsigned) 496 { 497 opcode |= 1 << 24; 498 } 499 500 opcode |= ((vm & 0x10) << 1); 501 opcode |= ((vm & 0xf) << 0); 502 503 opcode |= ((vd & 0x10) << 18); 504 opcode |= ((vd & 0xf) << 12); 505 506 opcode |= (fixImm & 0x3f) << 16; 507 508 var v0 = new V128(s0, s1, s2, s3); 509 510 SingleOpcode(opcode, v0: v0); 511 512 CompareAgainstUnicorn(); 513 } 514 515 [Test, Pairwise, Description("VRINTR.F<size> <Sd>, <Sm>")] 516 [Platform(Exclude = "Linux,MacOsX")] // Instruction isn't testable due to Unicorn. 517 public void Vrintr([Values(0u, 1u)] uint rd, 518 [Values(0u, 1u)] uint rm, 519 [Values(2u, 3u)] uint size, 520 [ValueSource(nameof(_1D_F_))] ulong s0, 521 [ValueSource(nameof(_1D_F_))] ulong s1, 522 [ValueSource(nameof(_1D_F_))] ulong s2, 523 [Values(RMode.Rn, RMode.Rm, RMode.Rp)] RMode rMode) 524 { 525 uint opcode = 0xEEB60A40; 526 527 V128 v0, v1, v2; 528 529 if (size == 2) 530 { 531 opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5); 532 opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22); 533 v0 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s0), (uint)BitConverter.SingleToInt32Bits(s0)); 534 v1 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s1), (uint)BitConverter.SingleToInt32Bits(s0)); 535 v2 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s2), (uint)BitConverter.SingleToInt32Bits(s1)); 536 } 537 else 538 { 539 opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1); 540 opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18); 541 v0 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s0), (uint)BitConverter.DoubleToInt64Bits(s0)); 542 v1 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s1), (uint)BitConverter.DoubleToInt64Bits(s0)); 543 v2 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s2), (uint)BitConverter.DoubleToInt64Bits(s1)); 544 } 545 546 opcode |= ((size & 3) << 8); 547 548 int fpscr = (int)rMode << (int)Fpcr.RMode; 549 SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr); 550 551 CompareAgainstUnicorn(); 552 } 553 #endif 554 } 555 }