InstEmitSimdHelperArm64.cs
1 using ARMeilleure.Decoders; 2 using ARMeilleure.IntermediateRepresentation; 3 using ARMeilleure.State; 4 using ARMeilleure.Translation; 5 6 using static ARMeilleure.Instructions.InstEmitHelper; 7 using static ARMeilleure.IntermediateRepresentation.Operand.Factory; 8 9 namespace ARMeilleure.Instructions 10 { 11 static class InstEmitSimdHelperArm64 12 { 13 public static void EmitScalarUnaryOpF(ArmEmitterContext context, Intrinsic inst) 14 { 15 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 16 17 Operand n = GetVec(op.Rn); 18 19 if ((op.Size & 1) != 0) 20 { 21 inst |= Intrinsic.Arm64VDouble; 22 } 23 24 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n)); 25 } 26 27 public static void EmitScalarUnaryOpFFromGp(ArmEmitterContext context, Intrinsic inst) 28 { 29 OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; 30 31 Operand n = GetIntOrZR(context, op.Rn); 32 33 if ((op.Size & 1) != 0) 34 { 35 inst |= Intrinsic.Arm64VDouble; 36 } 37 38 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n)); 39 } 40 41 public static void EmitScalarUnaryOpFToGp(ArmEmitterContext context, Intrinsic inst) 42 { 43 OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp; 44 45 Operand n = GetVec(op.Rn); 46 47 if ((op.Size & 1) != 0) 48 { 49 inst |= Intrinsic.Arm64VDouble; 50 } 51 52 SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32 53 ? context.AddIntrinsicInt(inst, n) 54 : context.AddIntrinsicLong(inst, n)); 55 } 56 57 public static void EmitScalarBinaryOpF(ArmEmitterContext context, Intrinsic inst) 58 { 59 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 60 61 Operand n = GetVec(op.Rn); 62 Operand m = GetVec(op.Rm); 63 64 if ((op.Size & 1) != 0) 65 { 66 inst |= Intrinsic.Arm64VDouble; 67 } 68 69 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m)); 70 } 71 72 public static void EmitScalarBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst) 73 { 74 OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; 75 76 Operand n = GetVec(op.Rn); 77 Operand m = GetVec(op.Rm); 78 79 if ((op.Size & 1) != 0) 80 { 81 inst |= Intrinsic.Arm64VDouble; 82 } 83 84 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index))); 85 } 86 87 public static void EmitScalarTernaryOpF(ArmEmitterContext context, Intrinsic inst) 88 { 89 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 90 91 Operand n = GetVec(op.Rn); 92 Operand m = GetVec(op.Rm); 93 Operand a = GetVec(op.Ra); 94 95 if ((op.Size & 1) != 0) 96 { 97 inst |= Intrinsic.Arm64VDouble; 98 } 99 100 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, a, n, m)); 101 } 102 103 public static void EmitScalarTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst) 104 { 105 OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; 106 107 Operand d = GetVec(op.Rd); 108 Operand n = GetVec(op.Rn); 109 Operand m = GetVec(op.Rm); 110 111 if ((op.Size & 1) != 0) 112 { 113 inst |= Intrinsic.Arm64VDouble; 114 } 115 116 context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index))); 117 } 118 119 public static void EmitScalarUnaryOp(ArmEmitterContext context, Intrinsic inst) 120 { 121 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 122 123 Operand n = GetVec(op.Rn); 124 125 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 126 127 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n)); 128 } 129 130 public static void EmitScalarBinaryOp(ArmEmitterContext context, Intrinsic inst) 131 { 132 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 133 134 Operand n = GetVec(op.Rn); 135 Operand m = GetVec(op.Rm); 136 137 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 138 139 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m)); 140 } 141 142 public static void EmitScalarBinaryOpRd(ArmEmitterContext context, Intrinsic inst) 143 { 144 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 145 146 Operand d = GetVec(op.Rd); 147 Operand n = GetVec(op.Rn); 148 149 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 150 151 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n)); 152 } 153 154 public static void EmitScalarTernaryOpRd(ArmEmitterContext context, Intrinsic inst) 155 { 156 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 157 158 Operand d = GetVec(op.Rd); 159 Operand n = GetVec(op.Rn); 160 Operand m = GetVec(op.Rm); 161 162 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 163 164 context.Copy(d, context.AddIntrinsic(inst, d, n, m)); 165 } 166 167 public static void EmitScalarShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift) 168 { 169 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 170 171 Operand n = GetVec(op.Rn); 172 173 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 174 175 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift))); 176 } 177 178 public static void EmitScalarShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift) 179 { 180 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 181 182 Operand d = GetVec(op.Rd); 183 Operand n = GetVec(op.Rn); 184 185 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 186 187 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift))); 188 } 189 190 public static void EmitScalarSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift) 191 { 192 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 193 194 Operand d = GetVec(op.Rd); 195 Operand n = GetVec(op.Rn); 196 197 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 198 199 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift))); 200 201 context.SetPendingQcFlagSync(); 202 } 203 204 public static void EmitScalarSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst) 205 { 206 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 207 208 Operand n = GetVec(op.Rn); 209 210 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 211 212 Operand result = context.AddIntrinsic(inst, n); 213 214 context.Copy(GetVec(op.Rd), result); 215 216 context.SetPendingQcFlagSync(); 217 } 218 219 public static void EmitScalarSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst) 220 { 221 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 222 223 Operand n = GetVec(op.Rn); 224 Operand m = GetVec(op.Rm); 225 226 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 227 228 Operand result = context.AddIntrinsic(inst, n, m); 229 230 context.Copy(GetVec(op.Rd), result); 231 232 context.SetPendingQcFlagSync(); 233 } 234 235 public static void EmitScalarSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst) 236 { 237 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 238 239 Operand d = GetVec(op.Rd); 240 Operand n = GetVec(op.Rn); 241 242 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 243 244 Operand result = context.AddIntrinsic(inst, d, n); 245 246 context.Copy(GetVec(op.Rd), result); 247 248 context.SetPendingQcFlagSync(); 249 } 250 251 public static void EmitScalarConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits) 252 { 253 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 254 255 Operand n = GetVec(op.Rn); 256 257 if ((op.Size & 1) != 0) 258 { 259 inst |= Intrinsic.Arm64VDouble; 260 } 261 262 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits))); 263 } 264 265 public static void EmitScalarConvertBinaryOpFFromGp(ArmEmitterContext context, Intrinsic inst, int fBits) 266 { 267 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 268 269 Operand n = GetIntOrZR(context, op.Rn); 270 271 if ((op.Size & 1) != 0) 272 { 273 inst |= Intrinsic.Arm64VDouble; 274 } 275 276 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits))); 277 } 278 279 public static void EmitScalarConvertBinaryOpFToGp(ArmEmitterContext context, Intrinsic inst, int fBits) 280 { 281 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 282 283 Operand n = GetVec(op.Rn); 284 285 if ((op.Size & 1) != 0) 286 { 287 inst |= Intrinsic.Arm64VDouble; 288 } 289 290 SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32 291 ? context.AddIntrinsicInt(inst, n, Const(fBits)) 292 : context.AddIntrinsicLong(inst, n, Const(fBits))); 293 } 294 295 public static void EmitVectorUnaryOpF(ArmEmitterContext context, Intrinsic inst) 296 { 297 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 298 299 Operand n = GetVec(op.Rn); 300 301 if ((op.Size & 1) != 0) 302 { 303 inst |= Intrinsic.Arm64VDouble; 304 } 305 306 if (op.RegisterSize == RegisterSize.Simd128) 307 { 308 inst |= Intrinsic.Arm64V128; 309 } 310 311 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n)); 312 } 313 314 public static void EmitVectorBinaryOpF(ArmEmitterContext context, Intrinsic inst) 315 { 316 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 317 318 Operand n = GetVec(op.Rn); 319 Operand m = GetVec(op.Rm); 320 321 if ((op.Size & 1) != 0) 322 { 323 inst |= Intrinsic.Arm64VDouble; 324 } 325 326 if (op.RegisterSize == RegisterSize.Simd128) 327 { 328 inst |= Intrinsic.Arm64V128; 329 } 330 331 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m)); 332 } 333 334 public static void EmitVectorBinaryOpFRd(ArmEmitterContext context, Intrinsic inst) 335 { 336 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 337 338 Operand d = GetVec(op.Rd); 339 Operand n = GetVec(op.Rn); 340 341 if ((op.Size & 1) != 0) 342 { 343 inst |= Intrinsic.Arm64VDouble; 344 } 345 346 if (op.RegisterSize == RegisterSize.Simd128) 347 { 348 inst |= Intrinsic.Arm64V128; 349 } 350 351 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n)); 352 } 353 354 public static void EmitVectorBinaryOpFByElem(ArmEmitterContext context, Intrinsic inst) 355 { 356 OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; 357 358 Operand n = GetVec(op.Rn); 359 Operand m = GetVec(op.Rm); 360 361 if ((op.Size & 1) != 0) 362 { 363 inst |= Intrinsic.Arm64VDouble; 364 } 365 366 if (op.RegisterSize == RegisterSize.Simd128) 367 { 368 inst |= Intrinsic.Arm64V128; 369 } 370 371 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index))); 372 } 373 374 public static void EmitVectorTernaryOpFRd(ArmEmitterContext context, Intrinsic inst) 375 { 376 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 377 378 Operand d = GetVec(op.Rd); 379 Operand n = GetVec(op.Rn); 380 Operand m = GetVec(op.Rm); 381 382 if ((op.Size & 1) != 0) 383 { 384 inst |= Intrinsic.Arm64VDouble; 385 } 386 387 if (op.RegisterSize == RegisterSize.Simd128) 388 { 389 inst |= Intrinsic.Arm64V128; 390 } 391 392 context.Copy(d, context.AddIntrinsic(inst, d, n, m)); 393 } 394 395 public static void EmitVectorTernaryOpFRdByElem(ArmEmitterContext context, Intrinsic inst) 396 { 397 OpCodeSimdRegElemF op = (OpCodeSimdRegElemF)context.CurrOp; 398 399 Operand d = GetVec(op.Rd); 400 Operand n = GetVec(op.Rn); 401 Operand m = GetVec(op.Rm); 402 403 if ((op.Size & 1) != 0) 404 { 405 inst |= Intrinsic.Arm64VDouble; 406 } 407 408 if (op.RegisterSize == RegisterSize.Simd128) 409 { 410 inst |= Intrinsic.Arm64V128; 411 } 412 413 context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index))); 414 } 415 416 public static void EmitVectorUnaryOp(ArmEmitterContext context, Intrinsic inst) 417 { 418 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 419 420 Operand n = GetVec(op.Rn); 421 422 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 423 424 if (op.RegisterSize == RegisterSize.Simd128) 425 { 426 inst |= Intrinsic.Arm64V128; 427 } 428 429 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n)); 430 } 431 432 public static void EmitVectorBinaryOp(ArmEmitterContext context, Intrinsic inst) 433 { 434 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 435 436 Operand n = GetVec(op.Rn); 437 Operand m = GetVec(op.Rm); 438 439 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 440 441 if (op.RegisterSize == RegisterSize.Simd128) 442 { 443 inst |= Intrinsic.Arm64V128; 444 } 445 446 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m)); 447 } 448 449 public static void EmitVectorBinaryOpRd(ArmEmitterContext context, Intrinsic inst) 450 { 451 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 452 453 Operand d = GetVec(op.Rd); 454 Operand n = GetVec(op.Rn); 455 456 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 457 458 if (op.RegisterSize == RegisterSize.Simd128) 459 { 460 inst |= Intrinsic.Arm64V128; 461 } 462 463 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n)); 464 } 465 466 public static void EmitVectorBinaryOpByElem(ArmEmitterContext context, Intrinsic inst) 467 { 468 OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; 469 470 Operand n = GetVec(op.Rn); 471 Operand m = GetVec(op.Rm); 472 473 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 474 475 if (op.RegisterSize == RegisterSize.Simd128) 476 { 477 inst |= Intrinsic.Arm64V128; 478 } 479 480 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, m, Const(op.Index))); 481 } 482 483 public static void EmitVectorTernaryOpRd(ArmEmitterContext context, Intrinsic inst) 484 { 485 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 486 487 Operand d = GetVec(op.Rd); 488 Operand n = GetVec(op.Rn); 489 Operand m = GetVec(op.Rm); 490 491 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 492 493 if (op.RegisterSize == RegisterSize.Simd128) 494 { 495 inst |= Intrinsic.Arm64V128; 496 } 497 498 context.Copy(d, context.AddIntrinsic(inst, d, n, m)); 499 } 500 501 public static void EmitVectorTernaryOpRdByElem(ArmEmitterContext context, Intrinsic inst) 502 { 503 OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; 504 505 Operand d = GetVec(op.Rd); 506 Operand n = GetVec(op.Rn); 507 Operand m = GetVec(op.Rm); 508 509 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 510 511 if (op.RegisterSize == RegisterSize.Simd128) 512 { 513 inst |= Intrinsic.Arm64V128; 514 } 515 516 context.Copy(d, context.AddIntrinsic(inst, d, n, m, Const(op.Index))); 517 } 518 519 public static void EmitVectorShiftBinaryOp(ArmEmitterContext context, Intrinsic inst, int shift) 520 { 521 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 522 523 Operand n = GetVec(op.Rn); 524 525 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 526 527 if (op.RegisterSize == RegisterSize.Simd128) 528 { 529 inst |= Intrinsic.Arm64V128; 530 } 531 532 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(shift))); 533 } 534 535 public static void EmitVectorShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift) 536 { 537 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 538 539 Operand d = GetVec(op.Rd); 540 Operand n = GetVec(op.Rn); 541 542 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 543 544 if (op.RegisterSize == RegisterSize.Simd128) 545 { 546 inst |= Intrinsic.Arm64V128; 547 } 548 549 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift))); 550 } 551 552 public static void EmitVectorSaturatingShiftTernaryOpRd(ArmEmitterContext context, Intrinsic inst, int shift) 553 { 554 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 555 556 Operand d = GetVec(op.Rd); 557 Operand n = GetVec(op.Rn); 558 559 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 560 561 if (op.RegisterSize == RegisterSize.Simd128) 562 { 563 inst |= Intrinsic.Arm64V128; 564 } 565 566 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, d, n, Const(shift))); 567 568 context.SetPendingQcFlagSync(); 569 } 570 571 public static void EmitVectorSaturatingUnaryOp(ArmEmitterContext context, Intrinsic inst) 572 { 573 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 574 575 Operand n = GetVec(op.Rn); 576 577 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 578 579 if (op.RegisterSize == RegisterSize.Simd128) 580 { 581 inst |= Intrinsic.Arm64V128; 582 } 583 584 Operand result = context.AddIntrinsic(inst, n); 585 586 context.Copy(GetVec(op.Rd), result); 587 588 context.SetPendingQcFlagSync(); 589 } 590 591 public static void EmitVectorSaturatingBinaryOp(ArmEmitterContext context, Intrinsic inst) 592 { 593 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 594 595 Operand n = GetVec(op.Rn); 596 Operand m = GetVec(op.Rm); 597 598 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 599 600 if (op.RegisterSize == RegisterSize.Simd128) 601 { 602 inst |= Intrinsic.Arm64V128; 603 } 604 605 Operand result = context.AddIntrinsic(inst, n, m); 606 607 context.Copy(GetVec(op.Rd), result); 608 609 context.SetPendingQcFlagSync(); 610 } 611 612 public static void EmitVectorSaturatingBinaryOpRd(ArmEmitterContext context, Intrinsic inst) 613 { 614 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 615 616 Operand d = GetVec(op.Rd); 617 Operand n = GetVec(op.Rn); 618 619 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 620 621 if (op.RegisterSize == RegisterSize.Simd128) 622 { 623 inst |= Intrinsic.Arm64V128; 624 } 625 626 Operand result = context.AddIntrinsic(inst, d, n); 627 628 context.Copy(GetVec(op.Rd), result); 629 630 context.SetPendingQcFlagSync(); 631 } 632 633 public static void EmitVectorSaturatingBinaryOpByElem(ArmEmitterContext context, Intrinsic inst) 634 { 635 OpCodeSimdRegElem op = (OpCodeSimdRegElem)context.CurrOp; 636 637 Operand n = GetVec(op.Rn); 638 Operand m = GetVec(op.Rm); 639 640 inst |= (Intrinsic)(op.Size << (int)Intrinsic.Arm64VSizeShift); 641 642 if (op.RegisterSize == RegisterSize.Simd128) 643 { 644 inst |= Intrinsic.Arm64V128; 645 } 646 647 Operand result = context.AddIntrinsic(inst, n, m, Const(op.Index)); 648 649 context.Copy(GetVec(op.Rd), result); 650 651 context.SetPendingQcFlagSync(); 652 } 653 654 public static void EmitVectorConvertBinaryOpF(ArmEmitterContext context, Intrinsic inst, int fBits) 655 { 656 OpCodeSimd op = (OpCodeSimd)context.CurrOp; 657 658 Operand n = GetVec(op.Rn); 659 660 if ((op.Size & 1) != 0) 661 { 662 inst |= Intrinsic.Arm64VDouble; 663 } 664 665 if (op.RegisterSize == RegisterSize.Simd128) 666 { 667 inst |= Intrinsic.Arm64V128; 668 } 669 670 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, n, Const(fBits))); 671 } 672 673 public static void EmitVectorLookupTable(ArmEmitterContext context, Intrinsic inst) 674 { 675 OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp; 676 677 Operand[] operands = new Operand[op.Size + 1]; 678 679 operands[op.Size] = GetVec(op.Rm); 680 681 for (int index = 0; index < op.Size; index++) 682 { 683 operands[index] = GetVec((op.Rn + index) & 0x1F); 684 } 685 686 if (op.RegisterSize == RegisterSize.Simd128) 687 { 688 inst |= Intrinsic.Arm64V128; 689 } 690 691 context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst, operands)); 692 } 693 694 public static void EmitFcmpOrFcmpe(ArmEmitterContext context, bool signalNaNs) 695 { 696 OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 697 698 bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3; 699 700 Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS; 701 702 if ((op.Size & 1) != 0) 703 { 704 inst |= Intrinsic.Arm64VDouble; 705 } 706 707 Operand n = GetVec(op.Rn); 708 Operand m = cmpWithZero ? Const(0) : GetVec(op.Rm); 709 710 Operand nzcv = context.AddIntrinsicInt(inst, n, m); 711 712 Operand one = Const(1); 713 714 SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(28)), one)); 715 SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(29)), one)); 716 SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(30)), one)); 717 SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(31)), one)); 718 } 719 } 720 }