1 2 /*---------------------------------------------------------------*/ 3 /*--- begin host_mips_defs.c ---*/ 4 /*---------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2010-2012 RT-RK 11 mips-valgrind (at) rt-rk.com 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #include "libvex_basictypes.h" 32 #include "libvex.h" 33 #include "libvex_trc_values.h" 34 35 #include "main_util.h" 36 #include "host_generic_regs.h" 37 #include "host_mips_defs.h" 38 39 /*---------------- Registers ----------------*/ 40 41 void ppHRegMIPS(HReg reg, Bool mode64) 42 { 43 Int r; 44 static HChar *ireg32_names[35] 45 = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", 46 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", 47 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", 48 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31", 49 "%32", "%33", "%34", 50 }; 51 52 static HChar *freg32_names[32] 53 = { "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", 54 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", 55 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", 56 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "f30", "$f31" 57 }; 58 59 static HChar *freg64_names[32] 60 = { "$d0", "$d1", "$d2", "$d3", "$d4", "$d5", "$d6", "$d7", 61 "$d8", "$d9", "$d10", "$d11", "$d12", "$d13", "$d14", "$d15", 62 }; 63 64 /* Be generic for all virtual regs. */ 65 if (hregIsVirtual(reg)) { 66 ppHReg(reg); 67 return; 68 } 69 70 /* But specific for real regs. */ 71 vassert(hregClass(reg) == HRcInt32 || hregClass(reg) == HRcInt64 || 72 hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64); 73 74 /* But specific for real regs. */ 75 { 76 switch (hregClass(reg)) { 77 case HRcInt32: 78 r = hregNumber(reg); 79 vassert(r >= 0 && r < 32); 80 vex_printf("%s", ireg32_names[r]); 81 return; 82 case HRcFlt32: 83 r = hregNumber(reg); 84 vassert(r >= 0 && r < 32); 85 vex_printf("%s", freg32_names[r]); 86 return; 87 case HRcFlt64: 88 r = hregNumber(reg); 89 vassert(r >= 0 && r < 32); 90 vex_printf("%s", freg64_names[r]); 91 return; 92 default: 93 vpanic("ppHRegMIPS"); 94 break; 95 } 96 } 97 98 return; 99 } 100 101 #define MkHRegGPR(_n, _mode64) \ 102 mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False) 103 104 HReg hregMIPS_GPR0(Bool mode64) 105 { 106 return MkHRegGPR(0, mode64); 107 } 108 109 HReg hregMIPS_GPR1(Bool mode64) 110 { 111 return MkHRegGPR(1, mode64); 112 } 113 114 HReg hregMIPS_GPR2(Bool mode64) 115 { 116 return MkHRegGPR(2, mode64); 117 } 118 119 HReg hregMIPS_GPR3(Bool mode64) 120 { 121 return MkHRegGPR(3, mode64); 122 } 123 124 HReg hregMIPS_GPR4(Bool mode64) 125 { 126 return MkHRegGPR(4, mode64); 127 } 128 129 HReg hregMIPS_GPR5(Bool mode64) 130 { 131 return MkHRegGPR(5, mode64); 132 } 133 134 HReg hregMIPS_GPR6(Bool mode64) 135 { 136 return MkHRegGPR(6, mode64); 137 } 138 139 HReg hregMIPS_GPR7(Bool mode64) 140 { 141 return MkHRegGPR(7, mode64); 142 } 143 144 HReg hregMIPS_GPR8(Bool mode64) 145 { 146 return MkHRegGPR(8, mode64); 147 } 148 149 HReg hregMIPS_GPR9(Bool mode64) 150 { 151 return MkHRegGPR(9, mode64); 152 } 153 154 HReg hregMIPS_GPR10(Bool mode64) 155 { 156 return MkHRegGPR(10, mode64); 157 } 158 159 HReg hregMIPS_GPR11(Bool mode64) 160 { 161 return MkHRegGPR(11, mode64); 162 } 163 164 HReg hregMIPS_GPR12(Bool mode64) 165 { 166 return MkHRegGPR(12, mode64); 167 } 168 169 HReg hregMIPS_GPR13(Bool mode64) 170 { 171 return MkHRegGPR(13, mode64); 172 } 173 174 HReg hregMIPS_GPR14(Bool mode64) 175 { 176 return MkHRegGPR(14, mode64); 177 } 178 179 HReg hregMIPS_GPR15(Bool mode64) 180 { 181 return MkHRegGPR(15, mode64); 182 } 183 184 HReg hregMIPS_GPR16(Bool mode64) 185 { 186 return MkHRegGPR(16, mode64); 187 } 188 189 HReg hregMIPS_GPR17(Bool mode64) 190 { 191 return MkHRegGPR(17, mode64); 192 } 193 194 HReg hregMIPS_GPR18(Bool mode64) 195 { 196 return MkHRegGPR(18, mode64); 197 } 198 199 HReg hregMIPS_GPR19(Bool mode64) 200 { 201 return MkHRegGPR(19, mode64); 202 } 203 204 HReg hregMIPS_GPR20(Bool mode64) 205 { 206 return MkHRegGPR(20, mode64); 207 } 208 209 HReg hregMIPS_GPR21(Bool mode64) 210 { 211 return MkHRegGPR(21, mode64); 212 } 213 214 HReg hregMIPS_GPR22(Bool mode64) 215 { 216 return MkHRegGPR(22, mode64); 217 } 218 219 HReg hregMIPS_GPR23(Bool mode64) 220 { 221 return MkHRegGPR(23, mode64); 222 } 223 224 HReg hregMIPS_GPR24(Bool mode64) 225 { 226 return MkHRegGPR(24, mode64); 227 } 228 229 HReg hregMIPS_GPR25(Bool mode64) 230 { 231 return MkHRegGPR(25, mode64); 232 } 233 234 HReg hregMIPS_GPR26(Bool mode64) 235 { 236 return MkHRegGPR(26, mode64); 237 } 238 239 HReg hregMIPS_GPR27(Bool mode64) 240 { 241 return MkHRegGPR(27, mode64); 242 } 243 244 HReg hregMIPS_GPR28(Bool mode64) 245 { 246 return MkHRegGPR(28, mode64); 247 } 248 249 HReg hregMIPS_GPR29(Bool mode64) 250 { 251 return MkHRegGPR(29, mode64); 252 } 253 254 HReg hregMIPS_GPR30(Bool mode64) 255 { 256 return MkHRegGPR(30, mode64); 257 } 258 259 HReg hregMIPS_GPR31(Bool mode64) 260 { 261 return MkHRegGPR(31, mode64); 262 } 263 264 #define MkHRegFPR(_n, _mode64) \ 265 mkHReg(_n, _mode64 ? HRcFlt64 : HRcFlt32, False) 266 267 HReg hregMIPS_F0(Bool mode64) 268 { 269 return MkHRegFPR(0, mode64); 270 } 271 272 HReg hregMIPS_F1(Bool mode64) 273 { 274 return MkHRegFPR(1, mode64); 275 } 276 277 HReg hregMIPS_F2(Bool mode64) 278 { 279 return MkHRegFPR(2, mode64); 280 } 281 282 HReg hregMIPS_F3(Bool mode64) 283 { 284 return MkHRegFPR(3, mode64); 285 } 286 287 HReg hregMIPS_F4(Bool mode64) 288 { 289 return MkHRegFPR(4, mode64); 290 } 291 292 HReg hregMIPS_F5(Bool mode64) 293 { 294 return MkHRegFPR(5, mode64); 295 } 296 297 HReg hregMIPS_F6(Bool mode64) 298 { 299 return MkHRegFPR(6, mode64); 300 } 301 302 HReg hregMIPS_F7(Bool mode64) 303 { 304 return MkHRegFPR(7, mode64); 305 } 306 307 HReg hregMIPS_F8(Bool mode64) 308 { 309 return MkHRegFPR(8, mode64); 310 } 311 312 HReg hregMIPS_F9(Bool mode64) 313 { 314 return MkHRegFPR(9, mode64); 315 } 316 317 HReg hregMIPS_F10(Bool mode64) 318 { 319 return MkHRegFPR(10, mode64); 320 } 321 322 HReg hregMIPS_F11(Bool mode64) 323 { 324 return MkHRegFPR(11, mode64); 325 } 326 327 HReg hregMIPS_F12(Bool mode64) 328 { 329 return MkHRegFPR(12, mode64); 330 } 331 332 HReg hregMIPS_F13(Bool mode64) 333 { 334 return MkHRegFPR(13, mode64); 335 } 336 337 HReg hregMIPS_F14(Bool mode64) 338 { 339 return MkHRegFPR(14, mode64); 340 } 341 342 HReg hregMIPS_F15(Bool mode64) 343 { 344 return MkHRegFPR(15, mode64); 345 } 346 347 HReg hregMIPS_F16(Bool mode64) 348 { 349 return MkHRegFPR(16, mode64); 350 } 351 352 HReg hregMIPS_F17(Bool mode64) 353 { 354 return MkHRegFPR(17, mode64); 355 } 356 357 HReg hregMIPS_F18(Bool mode64) 358 { 359 return MkHRegFPR(18, mode64); 360 } 361 362 HReg hregMIPS_F19(Bool mode64) 363 { 364 return MkHRegFPR(19, mode64); 365 } 366 367 HReg hregMIPS_F20(Bool mode64) 368 { 369 return MkHRegFPR(20, mode64); 370 } 371 372 HReg hregMIPS_F21(Bool mode64) 373 { 374 return MkHRegFPR(21, mode64); 375 } 376 377 HReg hregMIPS_F22(Bool mode64) 378 { 379 return MkHRegFPR(22, mode64); 380 } 381 382 HReg hregMIPS_F23(Bool mode64) 383 { 384 return MkHRegFPR(23, mode64); 385 } 386 387 HReg hregMIPS_F24(Bool mode64) 388 { 389 return MkHRegFPR(24, mode64); 390 } 391 392 HReg hregMIPS_F25(Bool mode64) 393 { 394 return MkHRegFPR(25, mode64); 395 } 396 397 HReg hregMIPS_F26(Bool mode64) 398 { 399 return MkHRegFPR(26, mode64); 400 } 401 402 HReg hregMIPS_F27(Bool mode64) 403 { 404 return MkHRegFPR(27, mode64); 405 } 406 407 HReg hregMIPS_F28(Bool mode64) 408 { 409 return MkHRegFPR(28, mode64); 410 } 411 412 HReg hregMIPS_F29(Bool mode64) 413 { 414 return MkHRegFPR(29, mode64); 415 } 416 417 HReg hregMIPS_F30(Bool mode64) 418 { 419 return MkHRegFPR(30, mode64); 420 } 421 422 HReg hregMIPS_F31(Bool mode64) 423 { 424 return MkHRegFPR(31, mode64); 425 } 426 427 HReg hregMIPS_PC(Bool mode64) 428 { 429 return mkHReg(32, mode64 ? HRcFlt64 : HRcFlt32, False); 430 } 431 432 HReg hregMIPS_HI(Bool mode64) 433 { 434 return mkHReg(33, mode64 ? HRcFlt64 : HRcFlt32, False); 435 } 436 437 HReg hregMIPS_LO(Bool mode64) 438 { 439 return mkHReg(34, mode64 ? HRcFlt64 : HRcFlt32, False); 440 } 441 442 HReg hregMIPS_D0(void) 443 { 444 return mkHReg(0, HRcFlt64, False); 445 } 446 447 HReg hregMIPS_D1(void) 448 { 449 return mkHReg(2, HRcFlt64, False); 450 } 451 452 HReg hregMIPS_D2(void) 453 { 454 return mkHReg(4, HRcFlt64, False); 455 } 456 457 HReg hregMIPS_D3(void) 458 { 459 return mkHReg(6, HRcFlt64, False); 460 } 461 462 HReg hregMIPS_D4(void) 463 { 464 return mkHReg(8, HRcFlt64, False); 465 } 466 467 HReg hregMIPS_D5(void) 468 { 469 return mkHReg(10, HRcFlt64, False); 470 } 471 472 HReg hregMIPS_D6(void) 473 { 474 return mkHReg(12, HRcFlt64, False); 475 } 476 477 HReg hregMIPS_D7(void) 478 { 479 return mkHReg(14, HRcFlt64, False); 480 } 481 482 HReg hregMIPS_D8(void) 483 { 484 return mkHReg(16, HRcFlt64, False); 485 } 486 487 HReg hregMIPS_D9(void) 488 { 489 return mkHReg(18, HRcFlt64, False); 490 } 491 492 HReg hregMIPS_D10(void) 493 { 494 return mkHReg(20, HRcFlt64, False); 495 } 496 497 HReg hregMIPS_D11(void) 498 { 499 return mkHReg(22, HRcFlt64, False); 500 } 501 502 HReg hregMIPS_D12(void) 503 { 504 return mkHReg(24, HRcFlt64, False); 505 } 506 507 HReg hregMIPS_D13(void) 508 { 509 return mkHReg(26, HRcFlt64, False); 510 } 511 512 HReg hregMIPS_D14(void) 513 { 514 return mkHReg(28, HRcFlt64, False); 515 } 516 517 HReg hregMIPS_D15(void) 518 { 519 return mkHReg(30, HRcFlt64, False); 520 } 521 522 HReg hregMIPS_FIR(void) 523 { 524 return mkHReg(35, HRcInt32, False); 525 } 526 527 HReg hregMIPS_FCCR(void) 528 { 529 return mkHReg(36, HRcInt32, False); 530 } 531 532 HReg hregMIPS_FEXR(void) 533 { 534 return mkHReg(37, HRcInt32, False); 535 } 536 537 HReg hregMIPS_FENR(void) 538 { 539 return mkHReg(38, HRcInt32, False); 540 } 541 542 HReg hregMIPS_FCSR(void) 543 { 544 return mkHReg(39, HRcInt32, False); 545 } 546 547 HReg hregMIPS_COND(void) 548 { 549 return mkHReg(47, HRcInt32, False); 550 } 551 552 void getAllocableRegs_MIPS(Int * nregs, HReg ** arr, Bool mode64) 553 { 554 if (mode64) 555 *nregs = 27; 556 else 557 *nregs = 34; 558 UInt i = 0; 559 *arr = LibVEX_Alloc(*nregs * sizeof(HReg)); 560 561 //ZERO = constant 0 562 //AT = assembler temporary 563 // callee saves ones are listed first, since we prefer them 564 // if they're available 565 (*arr)[i++] = hregMIPS_GPR16(mode64); 566 (*arr)[i++] = hregMIPS_GPR17(mode64); 567 (*arr)[i++] = hregMIPS_GPR18(mode64); 568 (*arr)[i++] = hregMIPS_GPR19(mode64); 569 (*arr)[i++] = hregMIPS_GPR20(mode64); 570 (*arr)[i++] = hregMIPS_GPR21(mode64); 571 (*arr)[i++] = hregMIPS_GPR22(mode64); 572 if (!mode64) 573 (*arr)[i++] = hregMIPS_GPR23(mode64); 574 575 // otherwise we'll have to slum it out with caller-saves ones 576 if (mode64) { 577 (*arr)[i++] = hregMIPS_GPR8(mode64); 578 (*arr)[i++] = hregMIPS_GPR9(mode64); 579 (*arr)[i++] = hregMIPS_GPR10(mode64); 580 (*arr)[i++] = hregMIPS_GPR11(mode64); 581 } 582 (*arr)[i++] = hregMIPS_GPR12(mode64); 583 (*arr)[i++] = hregMIPS_GPR13(mode64); 584 (*arr)[i++] = hregMIPS_GPR14(mode64); 585 (*arr)[i++] = hregMIPS_GPR15(mode64); 586 (*arr)[i++] = hregMIPS_GPR24(mode64); 587 /***********mips32********************/ 588 // t0 (=dispatch_ctr) 589 // t1 spill reg temp 590 // t2 (=guest_state) 591 // t3 (=PC = next guest address) 592 // K0 and K1 are reserved for OS kernel 593 // GP = global pointer 594 // SP = stack pointer 595 // FP = frame pointer 596 // RA = link register 597 // + PC, HI and LO 598 (*arr)[i++] = hregMIPS_F20(mode64); 599 (*arr)[i++] = hregMIPS_F21(mode64); 600 (*arr)[i++] = hregMIPS_F22(mode64); 601 (*arr)[i++] = hregMIPS_F23(mode64); 602 (*arr)[i++] = hregMIPS_F24(mode64); 603 (*arr)[i++] = hregMIPS_F25(mode64); 604 (*arr)[i++] = hregMIPS_F26(mode64); 605 (*arr)[i++] = hregMIPS_F27(mode64); 606 (*arr)[i++] = hregMIPS_F28(mode64); 607 (*arr)[i++] = hregMIPS_F29(mode64); 608 (*arr)[i++] = hregMIPS_F30(mode64); 609 if (!mode64) { 610 /* Fake double floating point */ 611 (*arr)[i++] = hregMIPS_D0(); 612 (*arr)[i++] = hregMIPS_D1(); 613 (*arr)[i++] = hregMIPS_D2(); 614 (*arr)[i++] = hregMIPS_D3(); 615 (*arr)[i++] = hregMIPS_D4(); 616 (*arr)[i++] = hregMIPS_D5(); 617 (*arr)[i++] = hregMIPS_D6(); 618 (*arr)[i++] = hregMIPS_D7(); 619 (*arr)[i++] = hregMIPS_D8(); 620 (*arr)[i++] = hregMIPS_D9(); 621 } 622 vassert(i == *nregs); 623 624 } 625 626 /*----------------- Condition Codes ----------------------*/ 627 628 HChar *showMIPSCondCode(MIPSCondCode cond) 629 { 630 HChar* ret; 631 switch (cond) { 632 case MIPScc_EQ: 633 ret = "EQ"; /* equal */ 634 break; 635 case MIPScc_NE: 636 ret = "NEQ"; /* not equal */ 637 break; 638 case MIPScc_HS: 639 ret = "GE"; /* >=u (Greater Than or Equal) */ 640 break; 641 case MIPScc_LO: 642 ret = "LT"; /* <u (lower) */ 643 break; 644 case MIPScc_MI: 645 ret = "mi"; /* minus (negative) */ 646 break; 647 case MIPScc_PL: 648 ret = "pl"; /* plus (zero or +ve) */ 649 break; 650 case MIPScc_VS: 651 ret = "vs"; /* overflow */ 652 break; 653 case MIPScc_VC: 654 ret = "vc"; /* no overflow */ 655 break; 656 case MIPScc_HI: 657 ret = "hi"; /* >u (higher) */ 658 break; 659 case MIPScc_LS: 660 ret = "ls"; /* <=u (lower or same) */ 661 break; 662 case MIPScc_GE: 663 ret = "ge"; /* >=s (signed greater or equal) */ 664 break; 665 case MIPScc_LT: 666 ret = "lt"; /* <s (signed less than) */ 667 break; 668 case MIPScc_GT: 669 ret = "gt"; /* >s (signed greater) */ 670 break; 671 case MIPScc_LE: 672 ret = "le"; /* <=s (signed less or equal) */ 673 break; 674 case MIPScc_AL: 675 ret = "al"; /* always (unconditional) */ 676 break; 677 case MIPScc_NV: 678 ret = "nv"; /* never (unconditional): */ 679 break; 680 default: 681 vpanic("showMIPSCondCode"); 682 break; 683 } 684 return ret; 685 } 686 687 HChar *showMIPSFpOp(MIPSFpOp op) 688 { 689 HChar *ret; 690 switch (op) { 691 case Mfp_ADDD: 692 ret = "ADD.D"; 693 break; 694 case Mfp_SUBD: 695 ret = "SUB.D"; 696 break; 697 case Mfp_MULD: 698 ret = "MUL.D"; 699 break; 700 case Mfp_DIVD: 701 ret = "DIV.D"; 702 break; 703 case Mfp_MADDD: 704 ret = "MADD.D"; 705 break; 706 case Mfp_MSUBD: 707 ret = "MSUB.D"; 708 break; 709 case Mfp_MADDS: 710 ret = "MADD.S"; 711 break; 712 case Mfp_MSUBS: 713 ret = "MSUB.S"; 714 break; 715 case Mfp_ADDS: 716 ret = "ADD.S"; 717 break; 718 case Mfp_SUBS: 719 ret = "SUB.S"; 720 break; 721 case Mfp_MULS: 722 ret = "MUL.S"; 723 break; 724 case Mfp_DIVS: 725 ret = "DIV.S"; 726 break; 727 case Mfp_SQRTS: 728 ret = "SQRT.S"; 729 break; 730 case Mfp_SQRTD: 731 ret = "SQRT.D"; 732 break; 733 case Mfp_RSQRTS: 734 ret = "RSQRT.S"; 735 break; 736 case Mfp_RSQRTD: 737 ret = "RSQRT.D"; 738 break; 739 case Mfp_RECIPS: 740 ret = "RECIP.S"; 741 break; 742 case Mfp_RECIPD: 743 ret = "RECIP.D"; 744 break; 745 case Mfp_ABSS: 746 ret = "ABS.S"; 747 break; 748 case Mfp_ABSD: 749 ret = "ABS.D"; 750 break; 751 case Mfp_NEGS: 752 ret = "NEG.S"; 753 break; 754 case Mfp_NEGD: 755 ret = "NEG.D"; 756 break; 757 case Mfp_MOVS: 758 ret = "MOV.S"; 759 break; 760 case Mfp_MOVD: 761 ret = "MOV.D"; 762 break; 763 case Mfp_RES: 764 ret = "RES"; 765 break; 766 case Mfp_ROUNDWS: 767 ret = "ROUND.W.S"; 768 break; 769 case Mfp_ROUNDWD: 770 ret = "ROUND.W.D"; 771 break; 772 case Mfp_FLOORWS: 773 ret = "FLOOR.W.S"; 774 break; 775 case Mfp_FLOORWD: 776 ret = "FLOOR.W.D"; 777 break; 778 case Mfp_RSQRTE: 779 ret = "frsqrte"; 780 break; 781 case Mfp_CVTDW: 782 case Mfp_CVTD: 783 ret = "CVT.D"; 784 break; 785 case Mfp_CVTSD: 786 case Mfp_CVTSW: 787 ret = "CVT.S"; 788 break; 789 case Mfp_CVTWS: 790 case Mfp_CVTWD: 791 ret = "CVT.W"; 792 break; 793 case Mfp_TRUWD: 794 case Mfp_TRUWS: 795 ret = "TRUNC.W"; 796 break; 797 case Mfp_TRULD: 798 case Mfp_TRULS: 799 ret = "TRUNC.L"; 800 break; 801 case Mfp_CEILWS: 802 case Mfp_CEILWD: 803 ret = "CEIL.W"; 804 break; 805 case Mfp_CEILLS: 806 case Mfp_CEILLD: 807 ret = "CEIL.L"; 808 break; 809 case Mfp_CMP: 810 ret = "C.cond.d"; 811 break; 812 default: 813 vpanic("showMIPSFpOp"); 814 break; 815 } 816 return ret; 817 } 818 819 /* --------- MIPSAMode: memory address expressions. --------- */ 820 821 MIPSAMode *MIPSAMode_IR(Int idx, HReg base) 822 { 823 MIPSAMode *am = LibVEX_Alloc(sizeof(MIPSAMode)); 824 am->tag = Mam_IR; 825 am->Mam.IR.base = base; 826 am->Mam.IR.index = idx; 827 828 return am; 829 } 830 831 MIPSAMode *MIPSAMode_RR(HReg idx, HReg base) 832 { 833 MIPSAMode *am = LibVEX_Alloc(sizeof(MIPSAMode)); 834 am->tag = Mam_RR; 835 am->Mam.RR.base = base; 836 am->Mam.RR.index = idx; 837 838 return am; 839 } 840 841 MIPSAMode *dopyMIPSAMode(MIPSAMode * am) 842 { 843 MIPSAMode* ret; 844 switch (am->tag) { 845 case Mam_IR: 846 ret = MIPSAMode_IR(am->Mam.IR.index, am->Mam.IR.base); 847 break; 848 case Mam_RR: 849 ret = MIPSAMode_RR(am->Mam.RR.index, am->Mam.RR.base); 850 break; 851 default: 852 vpanic("dopyMIPSAMode"); 853 break; 854 } 855 return ret; 856 } 857 858 MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am) 859 { 860 MIPSAMode* ret; 861 switch (am->tag) { 862 case Mam_IR: 863 ret = MIPSAMode_IR(am->Mam.IR.index + 8, am->Mam.IR.base); 864 break; 865 case Mam_RR: 866 ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base); 867 break; 868 default: 869 vpanic("dopyMIPSAMode"); 870 break; 871 } 872 return ret; 873 } 874 875 MIPSAMode *nextMIPSAModeInt(MIPSAMode * am) 876 { 877 MIPSAMode* ret; 878 switch (am->tag) { 879 case Mam_IR: 880 ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base); 881 break; 882 case Mam_RR: 883 ret = MIPSAMode_RR(am->Mam.RR.index + 1, am->Mam.RR.base); 884 break; 885 default: 886 vpanic("dopyMIPSAMode"); 887 break; 888 } 889 return ret; 890 } 891 892 void ppMIPSAMode(MIPSAMode * am, Bool mode64) 893 { 894 switch (am->tag) { 895 case Mam_IR: 896 if (am->Mam.IR.index == 0) 897 vex_printf("0("); 898 else 899 vex_printf("%d(", (Int) am->Mam.IR.index); 900 ppHRegMIPS(am->Mam.IR.base, mode64); 901 vex_printf(")"); 902 return; 903 case Mam_RR: 904 ppHRegMIPS(am->Mam.RR.base, mode64); 905 vex_printf(", "); 906 ppHRegMIPS(am->Mam.RR.index, mode64); 907 return; 908 default: 909 vpanic("ppMIPSAMode"); 910 break; 911 } 912 } 913 914 static void addRegUsage_MIPSAMode(HRegUsage * u, MIPSAMode * am) 915 { 916 switch (am->tag) { 917 case Mam_IR: 918 addHRegUse(u, HRmRead, am->Mam.IR.base); 919 return; 920 case Mam_RR: 921 addHRegUse(u, HRmRead, am->Mam.RR.base); 922 addHRegUse(u, HRmRead, am->Mam.RR.index); 923 return; 924 default: 925 vpanic("addRegUsage_MIPSAMode"); 926 break; 927 } 928 } 929 930 static void mapRegs_MIPSAMode(HRegRemap * m, MIPSAMode * am) 931 { 932 switch (am->tag) { 933 case Mam_IR: 934 am->Mam.IR.base = lookupHRegRemap(m, am->Mam.IR.base); 935 return; 936 case Mam_RR: 937 am->Mam.RR.base = lookupHRegRemap(m, am->Mam.RR.base); 938 am->Mam.RR.index = lookupHRegRemap(m, am->Mam.RR.index); 939 return; 940 default: 941 vpanic("mapRegs_MIPSAMode"); 942 break; 943 } 944 } 945 946 /* --------- Operand, which can be a reg or a u16/s16. --------- */ 947 948 MIPSRH *MIPSRH_Imm(Bool syned, UShort imm16) 949 { 950 MIPSRH *op = LibVEX_Alloc(sizeof(MIPSRH)); 951 op->tag = Mrh_Imm; 952 op->Mrh.Imm.syned = syned; 953 op->Mrh.Imm.imm16 = imm16; 954 /* If this is a signed value, ensure it's not -32768, so that we 955 are guaranteed always to be able to negate if needed. */ 956 if (syned) 957 vassert(imm16 != 0x8000); 958 vassert(syned == True || syned == False); 959 return op; 960 } 961 962 MIPSRH *MIPSRH_Reg(HReg reg) 963 { 964 MIPSRH *op = LibVEX_Alloc(sizeof(MIPSRH)); 965 op->tag = Mrh_Reg; 966 op->Mrh.Reg.reg = reg; 967 return op; 968 } 969 970 void ppMIPSRH(MIPSRH * op, Bool mode64) 971 { 972 MIPSRHTag tag = op->tag; 973 switch (tag) { 974 case Mrh_Imm: 975 if (op->Mrh.Imm.syned) 976 vex_printf("%d", (Int) (Short) op->Mrh.Imm.imm16); 977 else 978 vex_printf("%u", (UInt) (UShort) op->Mrh.Imm.imm16); 979 return; 980 case Mrh_Reg: 981 ppHRegMIPS(op->Mrh.Reg.reg, mode64); 982 return; 983 default: 984 vpanic("ppMIPSRH"); 985 break; 986 } 987 } 988 989 /* An MIPSRH can only be used in a "read" context (what would it mean 990 to write or modify a literal?) and so we enumerate its registers 991 accordingly. */ 992 static void addRegUsage_MIPSRH(HRegUsage * u, MIPSRH * op) 993 { 994 switch (op->tag) { 995 case Mrh_Imm: 996 return; 997 case Mrh_Reg: 998 addHRegUse(u, HRmRead, op->Mrh.Reg.reg); 999 return; 1000 default: 1001 vpanic("addRegUsage_MIPSRH"); 1002 break; 1003 } 1004 } 1005 1006 static void mapRegs_MIPSRH(HRegRemap * m, MIPSRH * op) 1007 { 1008 switch (op->tag) { 1009 case Mrh_Imm: 1010 return; 1011 case Mrh_Reg: 1012 op->Mrh.Reg.reg = lookupHRegRemap(m, op->Mrh.Reg.reg); 1013 return; 1014 default: 1015 vpanic("mapRegs_MIPSRH"); 1016 break; 1017 } 1018 } 1019 1020 /* --------- Instructions. --------- */ 1021 1022 HChar *showMIPSUnaryOp(MIPSUnaryOp op) 1023 { 1024 HChar* ret; 1025 switch (op) { 1026 case Mun_CLO: 1027 ret = "clo"; 1028 break; 1029 case Mun_CLZ: 1030 ret = "clz"; 1031 break; 1032 case Mun_NOP: 1033 ret = "nop"; 1034 break; 1035 default: 1036 vpanic("showMIPSUnaryOp"); 1037 break; 1038 } 1039 return ret; 1040 } 1041 1042 HChar *showMIPSAluOp(MIPSAluOp op, Bool immR) 1043 { 1044 HChar* ret; 1045 switch (op) { 1046 case Malu_ADD: 1047 ret = immR ? "addiu" : "addu"; 1048 break; 1049 case Malu_SUB: 1050 ret = "subu"; 1051 break; 1052 case Malu_AND: 1053 ret = immR ? "andi" : "and"; 1054 break; 1055 case Malu_OR: 1056 ret = immR ? "ori" : "or"; 1057 break; 1058 case Malu_NOR: 1059 vassert(immR == False); /*there's no nor with an immediate operand!? */ 1060 ret = "nor"; 1061 break; 1062 case Malu_XOR: 1063 ret = immR ? "xori" : "xor"; 1064 break; 1065 default: 1066 vpanic("showMIPSAluOp"); 1067 break; 1068 } 1069 return ret; 1070 } 1071 1072 HChar *showMIPSShftOp(MIPSShftOp op, Bool immR, Bool sz32) 1073 { 1074 HChar *ret; 1075 switch (op) { 1076 case Mshft_SRA: 1077 ret = immR ? (sz32 ? "sar" : "dsar") : (sz32 ? "sarv" : "dsrav"); 1078 break; 1079 case Mshft_SLL: 1080 ret = immR ? (sz32 ? "sll" : "dsll") : (sz32 ? "sllv" : "dsllv"); 1081 break; 1082 case Mshft_SRL: 1083 ret = immR ? (sz32 ? "srl" : "dsrl") : (sz32 ? "srlv" : "dsrlv"); 1084 break; 1085 default: 1086 vpanic("showMIPSShftOp"); 1087 break; 1088 } 1089 return ret; 1090 } 1091 1092 HChar *showMIPSMaccOp(MIPSMaccOp op, Bool variable) 1093 { 1094 HChar *ret; 1095 switch (op) { 1096 case Macc_ADD: 1097 ret = variable ? "madd" : "maddu"; 1098 break; 1099 case Macc_SUB: 1100 ret = variable ? "msub" : "msubu"; 1101 break; 1102 default: 1103 vpanic("showMIPSAccOp"); 1104 break; 1105 } 1106 return ret; 1107 } 1108 1109 MIPSInstr *MIPSInstr_LI(HReg dst, ULong imm) 1110 { 1111 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1112 i->tag = Min_LI; 1113 i->Min.LI.dst = dst; 1114 i->Min.LI.imm = imm; 1115 return i; 1116 } 1117 1118 MIPSInstr *MIPSInstr_Alu(MIPSAluOp op, HReg dst, HReg srcL, MIPSRH * srcR) 1119 { 1120 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1121 i->tag = Min_Alu; 1122 i->Min.Alu.op = op; 1123 i->Min.Alu.dst = dst; 1124 i->Min.Alu.srcL = srcL; 1125 i->Min.Alu.srcR = srcR; 1126 return i; 1127 } 1128 1129 MIPSInstr *MIPSInstr_Shft(MIPSShftOp op, Bool sz32, HReg dst, HReg srcL, 1130 MIPSRH * srcR) 1131 { 1132 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1133 i->tag = Min_Shft; 1134 i->Min.Shft.op = op; 1135 i->Min.Shft.sz32 = sz32; 1136 i->Min.Shft.dst = dst; 1137 i->Min.Shft.srcL = srcL; 1138 i->Min.Shft.srcR = srcR; 1139 return i; 1140 } 1141 1142 MIPSInstr *MIPSInstr_Unary(MIPSUnaryOp op, HReg dst, HReg src) 1143 { 1144 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1145 i->tag = Min_Unary; 1146 i->Min.Unary.op = op; 1147 i->Min.Unary.dst = dst; 1148 i->Min.Unary.src = src; 1149 return i; 1150 } 1151 1152 MIPSInstr *MIPSInstr_Cmp(Bool syned, Bool sz32, HReg dst, HReg srcL, HReg srcR, 1153 MIPSCondCode cond) 1154 { 1155 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1156 i->tag = Min_Cmp; 1157 i->Min.Cmp.syned = syned; 1158 i->Min.Cmp.sz32 = sz32; 1159 i->Min.Cmp.dst = dst; 1160 i->Min.Cmp.srcL = srcL; 1161 i->Min.Cmp.srcR = srcR; 1162 i->Min.Cmp.cond = cond; 1163 return i; 1164 } 1165 1166 /* multiply */ 1167 MIPSInstr *MIPSInstr_Mul(Bool syned, Bool wid, Bool sz32, HReg dst, HReg srcL, 1168 HReg srcR) 1169 { 1170 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1171 i->tag = Min_Mul; 1172 i->Min.Mul.syned = syned; 1173 i->Min.Mul.widening = wid; /* widen=True else False */ 1174 i->Min.Mul.sz32 = sz32; /* True = 32 bits */ 1175 i->Min.Mul.dst = dst; 1176 i->Min.Mul.srcL = srcL; 1177 i->Min.Mul.srcR = srcR; 1178 return i; 1179 } 1180 1181 /* msub */ 1182 MIPSInstr *MIPSInstr_Msub(Bool syned, HReg srcL, HReg srcR) 1183 { 1184 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1185 i->tag = Min_Macc; 1186 1187 i->Min.Macc.op = Macc_SUB; 1188 i->Min.Macc.syned = syned; 1189 i->Min.Macc.srcL = srcL; 1190 i->Min.Macc.srcR = srcR; 1191 return i; 1192 } 1193 1194 /* madd */ 1195 MIPSInstr *MIPSInstr_Madd(Bool syned, HReg srcL, HReg srcR) 1196 { 1197 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1198 i->tag = Min_Macc; 1199 1200 i->Min.Macc.op = Macc_ADD; 1201 i->Min.Macc.syned = syned; 1202 i->Min.Macc.srcL = srcL; 1203 i->Min.Macc.srcR = srcR; 1204 return i; 1205 } 1206 1207 /* div */ 1208 MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg srcL, HReg srcR) 1209 { 1210 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1211 i->tag = Min_Div; 1212 i->Min.Div.syned = syned; 1213 i->Min.Div.sz32 = sz32; /* True = 32 bits */ 1214 i->Min.Div.srcL = srcL; 1215 i->Min.Div.srcR = srcR; 1216 return i; 1217 } 1218 1219 MIPSInstr *MIPSInstr_Call(MIPSCondCode cond, Addr32 target, UInt argiregs, 1220 HReg src) 1221 { 1222 UInt mask; 1223 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1224 i->tag = Min_Call; 1225 i->Min.Call.cond = cond; 1226 i->Min.Call.target = target; 1227 i->Min.Call.argiregs = argiregs; 1228 i->Min.Call.src = src; 1229 /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */ 1230 mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); 1231 vassert(0 == (argiregs & ~mask)); 1232 return i; 1233 } 1234 1235 MIPSInstr *MIPSInstr_CallAlways(MIPSCondCode cond, Addr32 target, UInt argiregs) 1236 { 1237 UInt mask; 1238 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1239 i->tag = Min_Call; 1240 i->Min.Call.cond = cond; 1241 i->Min.Call.target = target; 1242 i->Min.Call.argiregs = argiregs; 1243 /* Only r4 .. r7 inclusive may be used as arg regs. Hence: */ 1244 mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); 1245 vassert(0 == (argiregs & ~mask)); 1246 return i; 1247 } 1248 1249 MIPSInstr *MIPSInstr_XDirect ( Addr32 dstGA, MIPSAMode* amPC, 1250 MIPSCondCode cond, Bool toFastEP ) { 1251 MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr)); 1252 i->tag = Min_XDirect; 1253 i->Min.XDirect.dstGA = dstGA; 1254 i->Min.XDirect.amPC = amPC; 1255 i->Min.XDirect.cond = cond; 1256 i->Min.XDirect.toFastEP = toFastEP; 1257 return i; 1258 } 1259 1260 MIPSInstr *MIPSInstr_XIndir ( HReg dstGA, MIPSAMode* amPC, 1261 MIPSCondCode cond ) { 1262 MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr)); 1263 i->tag = Min_XIndir; 1264 i->Min.XIndir.dstGA = dstGA; 1265 i->Min.XIndir.amPC = amPC; 1266 i->Min.XIndir.cond = cond; 1267 return i; 1268 } 1269 1270 MIPSInstr *MIPSInstr_XAssisted ( HReg dstGA, MIPSAMode* amPC, 1271 MIPSCondCode cond, IRJumpKind jk ) { 1272 MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr)); 1273 i->tag = Min_XAssisted; 1274 i->Min.XAssisted.dstGA = dstGA; 1275 i->Min.XAssisted.amPC = amPC; 1276 i->Min.XAssisted.cond = cond; 1277 i->Min.XAssisted.jk = jk; 1278 return i; 1279 } 1280 1281 MIPSInstr *MIPSInstr_Load(UChar sz, HReg dst, MIPSAMode * src, Bool mode64) 1282 { 1283 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1284 i->tag = Min_Load; 1285 i->Min.Load.sz = sz; 1286 i->Min.Load.src = src; 1287 i->Min.Load.dst = dst; 1288 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 1289 1290 if (sz == 8) 1291 vassert(mode64); 1292 return i; 1293 } 1294 1295 MIPSInstr *MIPSInstr_Store(UChar sz, MIPSAMode * dst, HReg src, Bool mode64) 1296 { 1297 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1298 i->tag = Min_Store; 1299 i->Min.Store.sz = sz; 1300 i->Min.Store.src = src; 1301 i->Min.Store.dst = dst; 1302 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8); 1303 1304 if (sz == 8) 1305 vassert(mode64); 1306 return i; 1307 } 1308 1309 MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src, Bool mode64) 1310 { 1311 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1312 i->tag = Min_LoadL; 1313 i->Min.LoadL.sz = sz; 1314 i->Min.LoadL.src = src; 1315 i->Min.LoadL.dst = dst; 1316 vassert(sz == 4 || sz == 8); 1317 1318 if (sz == 8) 1319 vassert(mode64); 1320 return i; 1321 } 1322 1323 MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src, Bool mode64) 1324 { 1325 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1326 i->tag = Min_StoreC; 1327 i->Min.StoreC.sz = sz; 1328 i->Min.StoreC.src = src; 1329 i->Min.StoreC.dst = dst; 1330 vassert(sz == 4 || sz == 8); 1331 1332 if (sz == 8) 1333 vassert(mode64); 1334 return i; 1335 } 1336 1337 MIPSInstr *MIPSInstr_Mthi(HReg src) 1338 { 1339 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1340 i->tag = Min_Mthi; 1341 i->Min.MtHL.src = src; 1342 return i; 1343 } 1344 1345 MIPSInstr *MIPSInstr_Mtlo(HReg src) 1346 { 1347 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1348 i->tag = Min_Mtlo; 1349 i->Min.MtHL.src = src; 1350 return i; 1351 } 1352 1353 MIPSInstr *MIPSInstr_Mfhi(HReg dst) 1354 { 1355 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1356 i->tag = Min_Mfhi; 1357 i->Min.MfHL.dst = dst; 1358 return i; 1359 } 1360 1361 MIPSInstr *MIPSInstr_Mflo(HReg dst) 1362 { 1363 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1364 i->tag = Min_Mflo; 1365 i->Min.MfHL.dst = dst; 1366 return i; 1367 } 1368 1369 /* Read/Write Link Register */ 1370 MIPSInstr *MIPSInstr_RdWrLR(Bool wrLR, HReg gpr) 1371 { 1372 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1373 i->tag = Min_RdWrLR; 1374 i->Min.RdWrLR.wrLR = wrLR; 1375 i->Min.RdWrLR.gpr = gpr; 1376 return i; 1377 } 1378 1379 MIPSInstr *MIPSInstr_FpLdSt(Bool isLoad, UChar sz, HReg reg, MIPSAMode * addr) 1380 { 1381 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1382 i->tag = Min_FpLdSt; 1383 i->Min.FpLdSt.isLoad = isLoad; 1384 i->Min.FpLdSt.sz = sz; 1385 i->Min.FpLdSt.reg = reg; 1386 i->Min.FpLdSt.addr = addr; 1387 vassert(sz == 4 || sz == 8); 1388 return i; 1389 } 1390 1391 MIPSInstr *MIPSInstr_FpUnary(MIPSFpOp op, HReg dst, HReg src) 1392 { 1393 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1394 i->tag = Min_FpUnary; 1395 i->Min.FpUnary.op = op; 1396 i->Min.FpUnary.dst = dst; 1397 i->Min.FpUnary.src = src; 1398 return i; 1399 } 1400 1401 MIPSInstr *MIPSInstr_FpBinary(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR) 1402 { 1403 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1404 i->tag = Min_FpBinary; 1405 i->Min.FpBinary.op = op; 1406 i->Min.FpBinary.dst = dst; 1407 i->Min.FpBinary.srcL = srcL; 1408 i->Min.FpBinary.srcR = srcR; 1409 return i; 1410 } 1411 1412 MIPSInstr *MIPSInstr_FpConvert(MIPSFpOp op, HReg dst, HReg src) 1413 { 1414 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1415 i->tag = Min_FpConvert; 1416 i->Min.FpConvert.op = op; 1417 i->Min.FpConvert.dst = dst; 1418 i->Min.FpConvert.src = src; 1419 return i; 1420 1421 } 1422 1423 MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR, 1424 UChar cond1) 1425 { 1426 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1427 i->tag = Min_FpCompare; 1428 i->Min.FpCompare.op = op; 1429 i->Min.FpCompare.dst = dst; 1430 i->Min.FpCompare.srcL = srcL; 1431 i->Min.FpCompare.srcR = srcR; 1432 i->Min.FpCompare.cond1 = cond1; 1433 return i; 1434 } 1435 1436 MIPSInstr *MIPSInstr_MovCond(HReg dst, HReg argL, MIPSRH * argR, HReg condR, 1437 MIPSCondCode cond) 1438 { 1439 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1440 i->tag = Min_MovCond; 1441 i->Min.MovCond.dst = dst; 1442 i->Min.MovCond.srcL = argL; 1443 i->Min.MovCond.srcR = argR; 1444 i->Min.MovCond.condR = condR; 1445 i->Min.MovCond.cond = cond; 1446 return i; 1447 } 1448 1449 MIPSInstr *MIPSInstr_MtFCSR(HReg src) 1450 { 1451 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1452 i->tag = Min_MtFCSR; 1453 i->Min.MtFCSR.src = src; 1454 return i; 1455 } 1456 1457 MIPSInstr *MIPSInstr_MfFCSR(HReg dst) 1458 { 1459 MIPSInstr *i = LibVEX_Alloc(sizeof(MIPSInstr)); 1460 i->tag = Min_MfFCSR; 1461 i->Min.MfFCSR.dst = dst; 1462 return i; 1463 } 1464 1465 MIPSInstr *MIPSInstr_EvCheck ( MIPSAMode* amCounter, 1466 MIPSAMode* amFailAddr ) { 1467 MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr)); 1468 i->tag = Min_EvCheck; 1469 i->Min.EvCheck.amCounter = amCounter; 1470 i->Min.EvCheck.amFailAddr = amFailAddr; 1471 return i; 1472 } 1473 1474 MIPSInstr* MIPSInstr_ProfInc ( void ) { 1475 MIPSInstr* i = LibVEX_Alloc(sizeof(MIPSInstr)); 1476 i->tag = Min_ProfInc; 1477 return i; 1478 } 1479 1480 /* -------- Pretty Print instructions ------------- */ 1481 static void ppLoadImm(HReg dst, ULong imm, Bool mode64) 1482 { 1483 vex_printf("li "); 1484 ppHRegMIPS(dst, mode64); 1485 vex_printf(",0x%016llx", imm); 1486 } 1487 1488 void ppMIPSInstr(MIPSInstr * i, Bool mode64) 1489 { 1490 switch (i->tag) { 1491 case Min_LI: 1492 ppLoadImm(i->Min.LI.dst, i->Min.LI.imm, mode64); 1493 break; 1494 case Min_Alu: { 1495 HReg r_srcL = i->Min.Alu.srcL; 1496 MIPSRH *rh_srcR = i->Min.Alu.srcR; 1497 /* generic */ 1498 vex_printf("%s ", showMIPSAluOp(i->Min.Alu.op, 1499 toBool(rh_srcR->tag == Mrh_Imm))); 1500 ppHRegMIPS(i->Min.Alu.dst, mode64); 1501 vex_printf(","); 1502 ppHRegMIPS(r_srcL, mode64); 1503 vex_printf(","); 1504 ppMIPSRH(rh_srcR, mode64); 1505 return; 1506 } 1507 case Min_Shft: { 1508 HReg r_srcL = i->Min.Shft.srcL; 1509 MIPSRH *rh_srcR = i->Min.Shft.srcR; 1510 vex_printf("%s ", showMIPSShftOp(i->Min.Shft.op, 1511 toBool(rh_srcR->tag == Mrh_Imm), 1512 i->Min.Shft.sz32)); 1513 ppHRegMIPS(i->Min.Shft.dst, mode64); 1514 vex_printf(","); 1515 ppHRegMIPS(r_srcL, mode64); 1516 vex_printf(","); 1517 ppMIPSRH(rh_srcR, mode64); 1518 return; 1519 } 1520 case Min_Unary: { 1521 vex_printf("%s ", showMIPSUnaryOp(i->Min.Unary.op)); 1522 ppHRegMIPS(i->Min.Unary.dst, mode64); 1523 vex_printf(","); 1524 ppHRegMIPS(i->Min.Unary.src, mode64); 1525 return; 1526 } 1527 case Min_Cmp: { 1528 vex_printf("word_compare "); 1529 ppHRegMIPS(i->Min.Cmp.dst, mode64); 1530 vex_printf(" = %s ( ", showMIPSCondCode(i->Min.Cmp.cond)); 1531 ppHRegMIPS(i->Min.Cmp.srcL, mode64); 1532 vex_printf(", "); 1533 ppHRegMIPS(i->Min.Cmp.srcR, mode64); 1534 vex_printf(" )"); 1535 1536 return; 1537 } 1538 case Min_Mul: { 1539 switch (i->Min.Mul.widening) { 1540 case False: 1541 vex_printf("mul "); 1542 ppHRegMIPS(i->Min.Mul.dst, mode64); 1543 vex_printf(", "); 1544 ppHRegMIPS(i->Min.Mul.srcL, mode64); 1545 vex_printf(", "); 1546 ppHRegMIPS(i->Min.Mul.srcR, mode64); 1547 return; 1548 case True: 1549 vex_printf("%s%s ", i->Min.Mul.sz32 ? "mult" : "dmult", 1550 i->Min.Mul.syned ? "" : "u"); 1551 ppHRegMIPS(i->Min.Mul.dst, mode64); 1552 vex_printf(", "); 1553 ppHRegMIPS(i->Min.Mul.srcL, mode64); 1554 vex_printf(", "); 1555 ppHRegMIPS(i->Min.Mul.srcR, mode64); 1556 return; 1557 } 1558 break; 1559 } 1560 case Min_Mthi: { 1561 vex_printf("mthi "); 1562 ppHRegMIPS(i->Min.MtHL.src, mode64); 1563 return; 1564 } 1565 case Min_Mtlo: { 1566 vex_printf("mtlo "); 1567 ppHRegMIPS(i->Min.MtHL.src, mode64); 1568 return; 1569 } 1570 case Min_Mfhi: { 1571 vex_printf("mfhi "); 1572 ppHRegMIPS(i->Min.MfHL.dst, mode64); 1573 return; 1574 } 1575 case Min_Mflo: { 1576 vex_printf("mflo "); 1577 ppHRegMIPS(i->Min.MfHL.dst, mode64); 1578 return; 1579 } 1580 case Min_Macc: { 1581 vex_printf("%s ", showMIPSMaccOp(i->Min.Macc.op, i->Min.Macc.syned)); 1582 ppHRegMIPS(i->Min.Macc.srcL, mode64); 1583 vex_printf(", "); 1584 ppHRegMIPS(i->Min.Macc.srcR, mode64); 1585 return; 1586 } 1587 case Min_Div: { 1588 if (!i->Min.Div.sz32) 1589 vex_printf("d"); 1590 vex_printf("div"); 1591 vex_printf("%s ", i->Min.Div.syned ? "s" : "u"); 1592 ppHRegMIPS(i->Min.Div.srcL, mode64); 1593 vex_printf(", "); 1594 ppHRegMIPS(i->Min.Div.srcR, mode64); 1595 return; 1596 } 1597 case Min_Call: { 1598 Int n; 1599 vex_printf("call: "); 1600 if (i->Min.Call.cond != MIPScc_AL) { 1601 vex_printf("if (%s) ", showMIPSCondCode(i->Min.Call.cond)); 1602 } 1603 vex_printf("{ "); 1604 ppLoadImm(hregMIPS_GPR11(mode64), i->Min.Call.target, mode64); 1605 1606 vex_printf(" ; mtctr r10 ; bctrl ["); 1607 for (n = 0; n < 32; n++) { 1608 if (i->Min.Call.argiregs & (1 << n)) { 1609 vex_printf("r%d", n); 1610 if ((i->Min.Call.argiregs >> n) > 1) 1611 vex_printf(","); 1612 } 1613 } 1614 vex_printf("] }"); 1615 break; 1616 } 1617 case Min_XDirect: 1618 vex_printf("(xDirect) "); 1619 vex_printf("if (guest_COND.%s) { ", 1620 showMIPSCondCode(i->Min.XDirect.cond)); 1621 vex_printf("move $9, 0x%x,", i->Min.XDirect.dstGA); 1622 vex_printf("; sw $9, "); 1623 ppMIPSAMode(i->Min.XDirect.amPC, mode64); 1624 vex_printf("; move $9, $disp_cp_chain_me_to_%sEP; jalr $9; nop}", 1625 i->Min.XDirect.toFastEP ? "fast" : "slow"); 1626 return; 1627 case Min_XIndir: 1628 vex_printf("(xIndir) "); 1629 vex_printf("if (guest_COND.%s) { sw ", 1630 showMIPSCondCode(i->Min.XIndir.cond)); 1631 ppHRegMIPS(i->Min.XIndir.dstGA, mode64); 1632 vex_printf(", "); 1633 ppMIPSAMode(i->Min.XIndir.amPC, mode64); 1634 vex_printf("; move $9, $disp_indir; jalr $9; nop}"); 1635 return; 1636 case Min_XAssisted: 1637 vex_printf("(xAssisted) "); 1638 vex_printf("if (guest_COND.%s) { ", 1639 showMIPSCondCode(i->Min.XAssisted.cond)); 1640 vex_printf("sw "); 1641 ppHRegMIPS(i->Min.XAssisted.dstGA, mode64); 1642 vex_printf(", "); 1643 ppMIPSAMode(i->Min.XAssisted.amPC, mode64); 1644 vex_printf("; move $9, $IRJumpKind_to_TRCVAL(%d)", 1645 (Int)i->Min.XAssisted.jk); 1646 vex_printf("; move $9, $disp_assisted; jalr $9; nop; }"); 1647 return; 1648 case Min_Load: { 1649 Bool idxd = toBool(i->Min.Load.src->tag == Mam_RR); 1650 UChar sz = i->Min.Load.sz; 1651 UChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd'; 1652 vex_printf("l%c%s ", c_sz, idxd ? "x" : ""); 1653 ppHRegMIPS(i->Min.Load.dst, mode64); 1654 vex_printf(","); 1655 ppMIPSAMode(i->Min.Load.src, mode64); 1656 return; 1657 } 1658 case Min_Store: { 1659 UChar sz = i->Min.Store.sz; 1660 Bool idxd = toBool(i->Min.Store.dst->tag == Mam_RR); 1661 UChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd'; 1662 vex_printf("s%c%s ", c_sz, idxd ? "x" : ""); 1663 ppHRegMIPS(i->Min.Store.src, mode64); 1664 vex_printf(","); 1665 ppMIPSAMode(i->Min.Store.dst, mode64); 1666 return; 1667 } 1668 case Min_LoadL: { 1669 vex_printf("ll "); 1670 ppHRegMIPS(i->Min.LoadL.dst, mode64); 1671 vex_printf(","); 1672 ppMIPSAMode(i->Min.LoadL.src, mode64); 1673 return; 1674 } 1675 case Min_StoreC: { 1676 vex_printf("sc "); 1677 ppHRegMIPS(i->Min.StoreC.src, mode64); 1678 vex_printf(","); 1679 ppMIPSAMode(i->Min.StoreC.dst, mode64); 1680 return; 1681 } 1682 case Min_RdWrLR: { 1683 vex_printf("%s ", i->Min.RdWrLR.wrLR ? "mtlr" : "mflr"); 1684 ppHRegMIPS(i->Min.RdWrLR.gpr, mode64); 1685 return; 1686 } 1687 case Min_FpUnary: 1688 vex_printf("%s ", showMIPSFpOp(i->Min.FpUnary.op)); 1689 ppHRegMIPS(i->Min.FpUnary.dst, mode64); 1690 vex_printf(","); 1691 ppHRegMIPS(i->Min.FpUnary.src, mode64); 1692 return; 1693 case Min_FpBinary: 1694 vex_printf("%s", showMIPSFpOp(i->Min.FpBinary.op)); 1695 ppHRegMIPS(i->Min.FpBinary.dst, mode64); 1696 vex_printf(","); 1697 ppHRegMIPS(i->Min.FpBinary.srcL, mode64); 1698 vex_printf(","); 1699 ppHRegMIPS(i->Min.FpBinary.srcR, mode64); 1700 return; 1701 case Min_FpConvert: 1702 vex_printf("%s", showMIPSFpOp(i->Min.FpConvert.op)); 1703 ppHRegMIPS(i->Min.FpConvert.dst, mode64); 1704 vex_printf(","); 1705 ppHRegMIPS(i->Min.FpConvert.src, mode64); 1706 return; 1707 case Min_FpCompare: 1708 vex_printf("%s ", showMIPSFpOp(i->Min.FpCompare.op)); 1709 ppHRegMIPS(i->Min.FpCompare.srcL, mode64); 1710 vex_printf(","); 1711 ppHRegMIPS(i->Min.FpCompare.srcR, mode64); 1712 vex_printf(" cond: %c", i->Min.FpCompare.cond1); 1713 return; 1714 case Min_FpMulAcc: 1715 vex_printf("%s ", showMIPSFpOp(i->Min.FpMulAcc.op)); 1716 ppHRegMIPS(i->Min.FpMulAcc.dst, mode64); 1717 vex_printf(","); 1718 ppHRegMIPS(i->Min.FpMulAcc.srcML, mode64); 1719 vex_printf(","); 1720 ppHRegMIPS(i->Min.FpMulAcc.srcMR, mode64); 1721 vex_printf(","); 1722 ppHRegMIPS(i->Min.FpMulAcc.srcAcc, mode64); 1723 return; 1724 case Min_FpLdSt: { 1725 if (i->Min.FpLdSt.sz == 4) { 1726 if (i->Min.FpLdSt.isLoad) { 1727 vex_printf("lwc1 "); 1728 ppHRegMIPS(i->Min.FpLdSt.reg, mode64); 1729 vex_printf(","); 1730 ppMIPSAMode(i->Min.FpLdSt.addr, mode64); 1731 } else { 1732 vex_printf("swc1 "); 1733 ppHRegMIPS(i->Min.FpLdSt.reg, mode64); 1734 vex_printf(","); 1735 ppMIPSAMode(i->Min.FpLdSt.addr, mode64); 1736 } 1737 } else if (i->Min.FpLdSt.sz == 8) { 1738 if (i->Min.FpLdSt.isLoad) { 1739 if (mode64) 1740 vex_printf("ldc1 "); 1741 else 1742 vex_printf("lwc1 "); 1743 ppHRegMIPS(i->Min.FpLdSt.reg, mode64); 1744 vex_printf(","); 1745 ppMIPSAMode(i->Min.FpLdSt.addr, mode64); 1746 } else { 1747 if (mode64) 1748 vex_printf("sdc1 "); 1749 else 1750 vex_printf("swc1 "); 1751 ppHRegMIPS(i->Min.FpLdSt.reg, mode64); 1752 vex_printf(","); 1753 ppMIPSAMode(i->Min.FpLdSt.addr, mode64); 1754 } 1755 } 1756 return; 1757 } 1758 case Min_MovCond: { 1759 if (i->Min.MovCond.cond == MIPScc_MI) { 1760 vex_printf("\ncond move\n"); 1761 return; 1762 1763 } 1764 break; 1765 } 1766 case Min_MtFCSR: { 1767 vex_printf("ctc1 "); 1768 ppHRegMIPS(i->Min.MtFCSR.src, mode64); 1769 vex_printf(", $31"); 1770 return; 1771 } 1772 1773 case Min_MfFCSR: { 1774 vex_printf("ctc1 "); 1775 ppHRegMIPS(i->Min.MfFCSR.dst, mode64); 1776 vex_printf(", $31"); 1777 return; 1778 } 1779 case Min_EvCheck: 1780 vex_printf("(evCheck) lw $9, "); 1781 ppMIPSAMode(i->Min.EvCheck.amCounter, mode64); 1782 vex_printf("; addiu $9, $9, -1"); 1783 vex_printf("; sw $9, "); 1784 ppMIPSAMode(i->Min.EvCheck.amCounter, mode64); 1785 vex_printf("; bgez $t9, nofail; jalr *"); 1786 ppMIPSAMode(i->Min.EvCheck.amFailAddr, mode64); 1787 vex_printf("; nofail:"); 1788 return; 1789 case Min_ProfInc: 1790 vex_printf("(profInc) move $9, ($NotKnownYet); " 1791 "lw $8, 0($9); " 1792 "addiu $8, $8, 1; " 1793 "sw $8, 0($9); " 1794 "sltiu $1, $8, 1; " 1795 "lw $8, 4($9); " 1796 "addu $8, $8, $1; " 1797 "sw $8, 4($9); " ); 1798 return; 1799 default: 1800 vpanic("ppMIPSInstr"); 1801 break; 1802 } 1803 } 1804 1805 /* --------- Helpers for register allocation. --------- */ 1806 1807 void getRegUsage_MIPSInstr(HRegUsage * u, MIPSInstr * i, Bool mode64) 1808 { 1809 initHRegUsage(u); 1810 switch (i->tag) { 1811 case Min_LI: 1812 addHRegUse(u, HRmWrite, i->Min.LI.dst); 1813 break; 1814 case Min_Alu: 1815 addHRegUse(u, HRmRead, i->Min.Alu.srcL); 1816 addRegUsage_MIPSRH(u, i->Min.Alu.srcR); 1817 addHRegUse(u, HRmWrite, i->Min.Alu.dst); 1818 return; 1819 case Min_Shft: 1820 addHRegUse(u, HRmRead, i->Min.Shft.srcL); 1821 addRegUsage_MIPSRH(u, i->Min.Shft.srcR); 1822 addHRegUse(u, HRmWrite, i->Min.Shft.dst); 1823 return; 1824 case Min_Cmp: 1825 addHRegUse(u, HRmRead, i->Min.Cmp.srcL); 1826 addHRegUse(u, HRmRead, i->Min.Cmp.srcR); 1827 addHRegUse(u, HRmWrite, i->Min.Cmp.dst); 1828 return; 1829 case Min_Unary: 1830 addHRegUse(u, HRmRead, i->Min.Unary.src); 1831 addHRegUse(u, HRmWrite, i->Min.Unary.dst); 1832 return; 1833 case Min_Mul: 1834 addHRegUse(u, HRmWrite, i->Min.Mul.dst); 1835 addHRegUse(u, HRmRead, i->Min.Mul.srcL); 1836 addHRegUse(u, HRmRead, i->Min.Mul.srcR); 1837 return; 1838 case Min_Mthi: 1839 case Min_Mtlo: 1840 addHRegUse(u, HRmWrite, hregMIPS_HI(mode64)); 1841 addHRegUse(u, HRmWrite, hregMIPS_LO(mode64)); 1842 addHRegUse(u, HRmRead, i->Min.MtHL.src); 1843 return; 1844 case Min_Mfhi: 1845 case Min_Mflo: 1846 addHRegUse(u, HRmRead, hregMIPS_HI(mode64)); 1847 addHRegUse(u, HRmRead, hregMIPS_LO(mode64)); 1848 addHRegUse(u, HRmWrite, i->Min.MfHL.dst); 1849 return; 1850 case Min_MtFCSR: 1851 addHRegUse(u, HRmRead, i->Min.MtFCSR.src); 1852 return; 1853 case Min_MfFCSR: 1854 addHRegUse(u, HRmWrite, i->Min.MfFCSR.dst); 1855 return; 1856 case Min_Macc: 1857 addHRegUse(u, HRmModify, hregMIPS_HI(mode64)); 1858 addHRegUse(u, HRmModify, hregMIPS_LO(mode64)); 1859 addHRegUse(u, HRmRead, i->Min.Macc.srcL); 1860 addHRegUse(u, HRmRead, i->Min.Macc.srcR); 1861 return; 1862 case Min_Div: 1863 addHRegUse(u, HRmWrite, hregMIPS_HI(mode64)); 1864 addHRegUse(u, HRmWrite, hregMIPS_LO(mode64)); 1865 addHRegUse(u, HRmRead, i->Min.Div.srcL); 1866 addHRegUse(u, HRmRead, i->Min.Div.srcR); 1867 return; 1868 case Min_Call: { 1869 if (i->Min.Call.cond != MIPScc_AL) 1870 addHRegUse(u, HRmRead, i->Min.Call.src); 1871 UInt argir; 1872 addHRegUse(u, HRmWrite, hregMIPS_GPR1(mode64)); 1873 1874 addHRegUse(u, HRmWrite, hregMIPS_GPR2(mode64)); 1875 addHRegUse(u, HRmWrite, hregMIPS_GPR3(mode64)); 1876 1877 addHRegUse(u, HRmWrite, hregMIPS_GPR4(mode64)); 1878 addHRegUse(u, HRmWrite, hregMIPS_GPR5(mode64)); 1879 addHRegUse(u, HRmWrite, hregMIPS_GPR6(mode64)); 1880 addHRegUse(u, HRmWrite, hregMIPS_GPR7(mode64)); 1881 1882 addHRegUse(u, HRmWrite, hregMIPS_GPR8(mode64)); 1883 addHRegUse(u, HRmWrite, hregMIPS_GPR9(mode64)); 1884 addHRegUse(u, HRmWrite, hregMIPS_GPR10(mode64)); 1885 addHRegUse(u, HRmWrite, hregMIPS_GPR11(mode64)); 1886 addHRegUse(u, HRmWrite, hregMIPS_GPR12(mode64)); 1887 addHRegUse(u, HRmWrite, hregMIPS_GPR13(mode64)); 1888 addHRegUse(u, HRmWrite, hregMIPS_GPR14(mode64)); 1889 addHRegUse(u, HRmWrite, hregMIPS_GPR15(mode64)); 1890 1891 addHRegUse(u, HRmWrite, hregMIPS_GPR24(mode64)); 1892 addHRegUse(u, HRmWrite, hregMIPS_GPR25(mode64)); 1893 addHRegUse(u, HRmWrite, hregMIPS_GPR26(mode64)); 1894 addHRegUse(u, HRmWrite, hregMIPS_GPR27(mode64)); 1895 1896 /* Now we have to state any parameter-carrying registers 1897 which might be read. This depends on the argiregs field. */ 1898 argir = i->Min.Call.argiregs; 1899 if (argir & (1 << 7)) 1900 addHRegUse(u, HRmRead, hregMIPS_GPR7(mode64)); 1901 if (argir & (1 << 6)) 1902 addHRegUse(u, HRmRead, hregMIPS_GPR6(mode64)); 1903 if (argir & (1 << 5)) 1904 addHRegUse(u, HRmRead, hregMIPS_GPR5(mode64)); 1905 if (argir & (1 << 4)) 1906 addHRegUse(u, HRmRead, hregMIPS_GPR4(mode64)); 1907 1908 vassert(0 == (argir & ~((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)))); 1909 return; 1910 } 1911 /* XDirect/XIndir/XAssisted are also a bit subtle. They 1912 conditionally exit the block. Hence we only need to list (1) 1913 the registers that they read, and (2) the registers that they 1914 write in the case where the block is not exited. (2) is 1915 empty, hence only (1) is relevant here. */ 1916 case Min_XDirect: 1917 addRegUsage_MIPSAMode(u, i->Min.XDirect.amPC); 1918 return; 1919 case Min_XIndir: 1920 addHRegUse(u, HRmRead, i->Min.XIndir.dstGA); 1921 addRegUsage_MIPSAMode(u, i->Min.XIndir.amPC); 1922 return; 1923 case Min_XAssisted: 1924 addHRegUse(u, HRmRead, i->Min.XAssisted.dstGA); 1925 addRegUsage_MIPSAMode(u, i->Min.XAssisted.amPC); 1926 return; 1927 case Min_Load: 1928 addRegUsage_MIPSAMode(u, i->Min.Load.src); 1929 addHRegUse(u, HRmWrite, i->Min.Load.dst); 1930 return; 1931 case Min_Store: 1932 addHRegUse(u, HRmRead, i->Min.Store.src); 1933 addRegUsage_MIPSAMode(u, i->Min.Store.dst); 1934 return; 1935 case Min_LoadL: 1936 addRegUsage_MIPSAMode(u, i->Min.LoadL.src); 1937 addHRegUse(u, HRmWrite, i->Min.LoadL.dst); 1938 return; 1939 case Min_StoreC: 1940 addHRegUse(u, HRmWrite, i->Min.StoreC.src); 1941 addHRegUse(u, HRmRead, i->Min.StoreC.src); 1942 addRegUsage_MIPSAMode(u, i->Min.StoreC.dst); 1943 return; 1944 case Min_RdWrLR: 1945 addHRegUse(u, (i->Min.RdWrLR.wrLR ? HRmRead : HRmWrite), 1946 i->Min.RdWrLR.gpr); 1947 return; 1948 case Min_FpLdSt: 1949 if (i->Min.FpLdSt.sz == 4) { 1950 addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), 1951 i->Min.FpLdSt.reg); 1952 addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); 1953 return; 1954 } else if (i->Min.FpLdSt.sz == 8) { 1955 if (mode64) { 1956 addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), 1957 i->Min.FpLdSt.reg); 1958 addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); 1959 } else { 1960 addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead), 1961 i->Min.FpLdSt.reg); 1962 addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr); 1963 addRegUsage_MIPSAMode(u, nextMIPSAModeFloat(i->Min.FpLdSt.addr)); 1964 } 1965 return; 1966 } 1967 break; 1968 case Min_FpUnary: 1969 if (i->Min.FpUnary.op == Mfp_CVTD) { 1970 addHRegUse(u, HRmWrite, i->Min.FpUnary.dst); 1971 addHRegUse(u, HRmRead, i->Min.FpUnary.src); 1972 return; 1973 } else { 1974 addHRegUse(u, HRmWrite, i->Min.FpUnary.dst); 1975 addHRegUse(u, HRmRead, i->Min.FpUnary.src); 1976 return; 1977 } 1978 case Min_FpBinary: 1979 addHRegUse(u, HRmWrite, i->Min.FpBinary.dst); 1980 addHRegUse(u, HRmRead, i->Min.FpBinary.srcL); 1981 addHRegUse(u, HRmRead, i->Min.FpBinary.srcR); 1982 return; 1983 case Min_FpConvert: 1984 addHRegUse(u, HRmWrite, i->Min.FpConvert.dst); 1985 addHRegUse(u, HRmRead, i->Min.FpConvert.src); 1986 return; 1987 case Min_FpCompare: 1988 addHRegUse(u, HRmWrite, i->Min.FpCompare.dst); 1989 addHRegUse(u, HRmRead, i->Min.FpCompare.srcL); 1990 addHRegUse(u, HRmRead, i->Min.FpCompare.srcR); 1991 return; 1992 case Min_MovCond: 1993 if (i->Min.MovCond.srcR->tag == Mrh_Reg) { 1994 addHRegUse(u, HRmRead, i->Min.MovCond.srcR->Mrh.Reg.reg); 1995 } 1996 addHRegUse(u, HRmRead, i->Min.MovCond.srcL); 1997 addHRegUse(u, HRmRead, i->Min.MovCond.condR); 1998 addHRegUse(u, HRmWrite, i->Min.MovCond.dst); 1999 return; 2000 case Min_EvCheck: 2001 /* We expect both amodes only to mention %ebp, so this is in 2002 fact pointless, since %ebp isn't allocatable, but anyway.. */ 2003 addRegUsage_MIPSAMode(u, i->Min.EvCheck.amCounter); 2004 addRegUsage_MIPSAMode(u, i->Min.EvCheck.amFailAddr); 2005 return; 2006 case Min_ProfInc: 2007 /* does not use any registers. */ 2008 return; 2009 default: 2010 ppMIPSInstr(i, mode64); 2011 vpanic("getRegUsage_MIPSInstr"); 2012 break; 2013 } 2014 } 2015 2016 /* local helper */ 2017 static void mapReg(HRegRemap * m, HReg * r) 2018 { 2019 *r = lookupHRegRemap(m, *r); 2020 } 2021 2022 void mapRegs_MIPSInstr(HRegRemap * m, MIPSInstr * i, Bool mode64) 2023 { 2024 switch (i->tag) { 2025 case Min_LI: 2026 mapReg(m, &i->Min.LI.dst); 2027 break; 2028 case Min_Alu: 2029 mapReg(m, &i->Min.Alu.srcL); 2030 mapRegs_MIPSRH(m, i->Min.Alu.srcR); 2031 mapReg(m, &i->Min.Alu.dst); 2032 return; 2033 case Min_Shft: 2034 mapReg(m, &i->Min.Shft.srcL); 2035 mapRegs_MIPSRH(m, i->Min.Shft.srcR); 2036 mapReg(m, &i->Min.Shft.dst); 2037 return; 2038 case Min_Cmp: 2039 mapReg(m, &i->Min.Cmp.srcL); 2040 mapReg(m, &i->Min.Cmp.srcR); 2041 mapReg(m, &i->Min.Cmp.dst); 2042 return; 2043 case Min_Unary: 2044 mapReg(m, &i->Min.Unary.src); 2045 mapReg(m, &i->Min.Unary.dst); 2046 return; 2047 case Min_Mul: 2048 mapReg(m, &i->Min.Mul.dst); 2049 mapReg(m, &i->Min.Mul.srcL); 2050 mapReg(m, &i->Min.Mul.srcR); 2051 return; 2052 case Min_Mthi: 2053 case Min_Mtlo: 2054 mapReg(m, &i->Min.MtHL.src); 2055 return; 2056 case Min_Mfhi: 2057 case Min_Mflo: 2058 mapReg(m, &i->Min.MfHL.dst); 2059 return; 2060 case Min_Macc: 2061 mapReg(m, &i->Min.Macc.srcL); 2062 mapReg(m, &i->Min.Macc.srcR); 2063 return; 2064 case Min_Div: 2065 mapReg(m, &i->Min.Div.srcL); 2066 mapReg(m, &i->Min.Div.srcR); 2067 return; 2068 case Min_Call: 2069 { 2070 if (i->Min.Call.cond != MIPScc_AL) 2071 mapReg(m, &i->Min.Call.src); 2072 return; 2073 } 2074 case Min_XDirect: 2075 mapRegs_MIPSAMode(m, i->Min.XDirect.amPC); 2076 return; 2077 case Min_XIndir: 2078 mapReg(m, &i->Min.XIndir.dstGA); 2079 mapRegs_MIPSAMode(m, i->Min.XIndir.amPC); 2080 return; 2081 case Min_XAssisted: 2082 mapReg(m, &i->Min.XAssisted.dstGA); 2083 mapRegs_MIPSAMode(m, i->Min.XAssisted.amPC); 2084 return; 2085 case Min_Load: 2086 mapRegs_MIPSAMode(m, i->Min.Load.src); 2087 mapReg(m, &i->Min.Load.dst); 2088 return; 2089 case Min_Store: 2090 mapReg(m, &i->Min.Store.src); 2091 mapRegs_MIPSAMode(m, i->Min.Store.dst); 2092 return; 2093 case Min_LoadL: 2094 mapRegs_MIPSAMode(m, i->Min.LoadL.src); 2095 mapReg(m, &i->Min.LoadL.dst); 2096 return; 2097 case Min_StoreC: 2098 mapReg(m, &i->Min.StoreC.src); 2099 mapRegs_MIPSAMode(m, i->Min.StoreC.dst); 2100 return; 2101 case Min_RdWrLR: 2102 mapReg(m, &i->Min.RdWrLR.gpr); 2103 return; 2104 case Min_FpLdSt: 2105 if (i->Min.FpLdSt.sz == 4) { 2106 mapReg(m, &i->Min.FpLdSt.reg); 2107 mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); 2108 return; 2109 } else if (i->Min.FpLdSt.sz == 8) { 2110 if (mode64) { 2111 mapReg(m, &i->Min.FpLdSt.reg); 2112 mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); 2113 } else { 2114 mapReg(m, &i->Min.FpLdSt.reg); 2115 mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr); 2116 mapRegs_MIPSAMode(m, nextMIPSAModeFloat(i->Min.FpLdSt.addr)); 2117 } 2118 return; 2119 } 2120 break; 2121 case Min_FpUnary: 2122 if (i->Min.FpUnary.op == Mfp_CVTD) { 2123 mapReg(m, &i->Min.FpUnary.dst); 2124 mapReg(m, &i->Min.FpUnary.src); 2125 return; 2126 } else { 2127 mapReg(m, &i->Min.FpUnary.dst); 2128 mapReg(m, &i->Min.FpUnary.src); 2129 return; 2130 } 2131 case Min_FpBinary: 2132 mapReg(m, &i->Min.FpBinary.dst); 2133 mapReg(m, &i->Min.FpBinary.srcL); 2134 mapReg(m, &i->Min.FpBinary.srcR); 2135 return; 2136 case Min_FpConvert: 2137 mapReg(m, &i->Min.FpConvert.dst); 2138 mapReg(m, &i->Min.FpConvert.src); 2139 return; 2140 case Min_FpCompare: 2141 mapReg(m, &i->Min.FpCompare.dst); 2142 mapReg(m, &i->Min.FpCompare.srcL); 2143 mapReg(m, &i->Min.FpCompare.srcR); 2144 return; 2145 case Min_MtFCSR: 2146 mapReg(m, &i->Min.MtFCSR.src); 2147 return; 2148 case Min_MfFCSR: 2149 mapReg(m, &i->Min.MfFCSR.dst); 2150 return; 2151 case Min_MovCond: 2152 if (i->Min.MovCond.srcR->tag == Mrh_Reg) { 2153 mapReg(m, &(i->Min.MovCond.srcR->Mrh.Reg.reg)); 2154 } 2155 mapReg(m, &i->Min.MovCond.srcL); 2156 mapReg(m, &i->Min.MovCond.condR); 2157 mapReg(m, &i->Min.MovCond.dst); 2158 2159 return; 2160 case Min_EvCheck: 2161 /* We expect both amodes only to mention %ebp, so this is in 2162 fact pointless, since %ebp isn't allocatable, but anyway.. */ 2163 mapRegs_MIPSAMode(m, i->Min.EvCheck.amCounter); 2164 mapRegs_MIPSAMode(m, i->Min.EvCheck.amFailAddr); 2165 return; 2166 case Min_ProfInc: 2167 /* does not use any registers. */ 2168 return; 2169 default: 2170 ppMIPSInstr(i, mode64); 2171 vpanic("mapRegs_MIPSInstr"); 2172 break; 2173 } 2174 2175 } 2176 2177 /* Figure out if i represents a reg-reg move, and if so assign the 2178 source and destination to *src and *dst. If in doubt say No. Used 2179 by the register allocator to do move coalescing. 2180 */ 2181 Bool isMove_MIPSInstr(MIPSInstr * i, HReg * src, HReg * dst) 2182 { 2183 /* Moves between integer regs */ 2184 if (i->tag == Min_Alu) { 2185 // or Rd,Rs,Rs == mr Rd,Rs 2186 if (i->Min.Alu.op != Malu_OR) 2187 return False; 2188 if (i->Min.Alu.srcR->tag != Mrh_Reg) 2189 return False; 2190 if (i->Min.Alu.srcR->Mrh.Reg.reg != i->Min.Alu.srcL) 2191 return False; 2192 *src = i->Min.Alu.srcL; 2193 *dst = i->Min.Alu.dst; 2194 return True; 2195 } 2196 return False; 2197 } 2198 2199 /* Generate mips spill/reload instructions under the direction of the 2200 register allocator. 2201 */ 2202 void genSpill_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg, 2203 Int offsetB, Bool mode64) 2204 { 2205 MIPSAMode *am; 2206 vassert(offsetB >= 0); 2207 vassert(!hregIsVirtual(rreg)); 2208 *i1 = *i2 = NULL; 2209 am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64)); 2210 2211 switch (hregClass(rreg)) { 2212 case HRcInt64: 2213 vassert(mode64); 2214 *i1 = MIPSInstr_Store(8, am, rreg, mode64); 2215 break; 2216 case HRcInt32: 2217 vassert(!mode64); 2218 *i1 = MIPSInstr_Store(4, am, rreg, mode64); 2219 break; 2220 case HRcFlt32: 2221 vassert(!mode64); 2222 *i1 = MIPSInstr_FpLdSt(False /*Store */ , 4, rreg, am); 2223 break; 2224 case HRcFlt64: 2225 *i1 = MIPSInstr_FpLdSt(False /*Store */ , 8, rreg, am); 2226 break; 2227 default: 2228 ppHRegClass(hregClass(rreg)); 2229 vpanic("genSpill_MIPS: unimplemented regclass"); 2230 break; 2231 } 2232 } 2233 2234 void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg, 2235 Int offsetB, Bool mode64) 2236 { 2237 MIPSAMode *am; 2238 vassert(!hregIsVirtual(rreg)); 2239 am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64)); 2240 2241 switch (hregClass(rreg)) { 2242 case HRcInt64: 2243 vassert(mode64); 2244 *i1 = MIPSInstr_Load(8, rreg, am, mode64); 2245 break; 2246 case HRcInt32: 2247 vassert(!mode64); 2248 *i1 = MIPSInstr_Load(4, rreg, am, mode64); 2249 break; 2250 case HRcFlt32: 2251 if (mode64) 2252 *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am); 2253 else 2254 *i1 = MIPSInstr_FpLdSt(True /*Load */ , 4, rreg, am); 2255 break; 2256 case HRcFlt64: 2257 *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am); 2258 break; 2259 default: 2260 ppHRegClass(hregClass(rreg)); 2261 vpanic("genReload_MIPS: unimplemented regclass"); 2262 break; 2263 } 2264 } 2265 2266 /* --------- The mips assembler --------- */ 2267 2268 static UInt iregNo(HReg r, Bool mode64) 2269 { 2270 UInt n; 2271 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32); 2272 vassert(!hregIsVirtual(r)); 2273 n = hregNumber(r); 2274 vassert(n <= 32); 2275 return n; 2276 } 2277 2278 static UChar fregNo(HReg r, Bool mode64) 2279 { 2280 UInt n; 2281 vassert(hregClass(r) == mode64 ? HRcFlt64 : HRcFlt32); 2282 vassert(!hregIsVirtual(r)); 2283 n = hregNumber(r); 2284 vassert(n <= 31); 2285 return n; 2286 } 2287 2288 static UChar dregNo(HReg r) 2289 { 2290 UInt n; 2291 vassert(hregClass(r) == HRcFlt64); 2292 vassert(!hregIsVirtual(r)); 2293 n = hregNumber(r); 2294 vassert(n <= 31); 2295 return n; 2296 } 2297 2298 /* Emit 32bit instruction */ 2299 static UChar *emit32(UChar * p, UInt w32) 2300 { 2301 #if defined (_MIPSEL) 2302 *p++ = toUChar(w32 & 0x000000FF); 2303 *p++ = toUChar((w32 >> 8) & 0x000000FF); 2304 *p++ = toUChar((w32 >> 16) & 0x000000FF); 2305 *p++ = toUChar((w32 >> 24) & 0x000000FF); 2306 #elif defined (_MIPSEB) 2307 *p++ = toUChar((w32 >> 24) & 0x000000FF); 2308 *p++ = toUChar((w32 >> 16) & 0x000000FF); 2309 *p++ = toUChar((w32 >> 8) & 0x000000FF); 2310 *p++ = toUChar(w32 & 0x000000FF); 2311 #endif 2312 return p; 2313 } 2314 /* Fetch an instruction */ 2315 static UInt fetch32 ( UChar* p ) 2316 { 2317 UInt w32 = 0; 2318 #if defined (_MIPSEL) 2319 w32 |= ((0xFF & (UInt)p[0]) << 0); 2320 w32 |= ((0xFF & (UInt)p[1]) << 8); 2321 w32 |= ((0xFF & (UInt)p[2]) << 16); 2322 w32 |= ((0xFF & (UInt)p[3]) << 24); 2323 #elif defined (_MIPSEB) 2324 w32 |= ((0xFF & (UInt)p[0]) << 24); 2325 w32 |= ((0xFF & (UInt)p[1]) << 16); 2326 w32 |= ((0xFF & (UInt)p[2]) << 8); 2327 w32 |= ((0xFF & (UInt)p[3]) << 0); 2328 #endif 2329 return w32; 2330 } 2331 2332 /* physical structure of mips instructions */ 2333 /* type I : opcode - 6 bits 2334 rs - 5 bits 2335 rt - 5 bits 2336 immediate - 16 bits 2337 */ 2338 static UChar *mkFormI(UChar * p, UInt opc, UInt rs, UInt rt, UInt imm) 2339 { 2340 UInt theInstr; 2341 vassert(opc < 0x40); 2342 vassert(rs < 0x20); 2343 vassert(rt < 0x20); 2344 imm = imm & 0xFFFF; 2345 theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (imm)); 2346 return emit32(p, theInstr); 2347 } 2348 2349 /* type R: opcode - 6 bits 2350 rs - 5 bits 2351 rt - 5 bits 2352 rd - 5 bits 2353 sa - 5 bits 2354 func - 6 bits 2355 */ 2356 static UChar *mkFormR(UChar * p, UInt opc, UInt rs, UInt rt, UInt rd, UInt sa, 2357 UInt func) 2358 { 2359 if (rs >= 0x20) 2360 vex_printf("rs = %d\n", rs); 2361 UInt theInstr; 2362 vassert(opc < 0x40); 2363 vassert(rs < 0x20); 2364 vassert(rt < 0x20); 2365 vassert(rd < 0x20); 2366 vassert(sa < 0x20); 2367 func = func & 0xFFFF; 2368 theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (rd << 11) | (sa << 6) | 2369 (func)); 2370 2371 return emit32(p, theInstr); 2372 } 2373 2374 static UChar *mkFormS(UChar * p, UInt opc1, UInt rRD, UInt rRS, UInt rRT, 2375 UInt sa, UInt opc2) 2376 { 2377 UInt theInstr; 2378 vassert(opc1 <= 0x3F); 2379 vassert(rRD < 0x20); 2380 vassert(rRS < 0x20); 2381 vassert(rRT < 0x20); 2382 vassert(opc2 <= 0x3F); 2383 vassert(sa >= 0 && sa <= 0x3F); 2384 2385 theInstr = ((opc1 << 26) | (rRS << 21) | (rRT << 16) | (rRD << 11) | 2386 ((sa & 0x1F) << 6) | (opc2)); 2387 2388 return emit32(p, theInstr); 2389 } 2390 2391 static UChar *doAMode_IR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am, 2392 Bool mode64) 2393 { 2394 UInt rA, idx, r_dst; 2395 vassert(am->tag == Mam_IR); 2396 vassert(am->Mam.IR.index < 0x10000); 2397 2398 rA = iregNo(am->Mam.IR.base, mode64); 2399 idx = am->Mam.IR.index; 2400 2401 if (rSD == 33 || rSD == 34) 2402 r_dst = 24; 2403 else 2404 r_dst = rSD; 2405 2406 if (opc1 < 40) { 2407 //load 2408 if (rSD == 33) 2409 /* mfhi */ 2410 p = mkFormR(p, 0, 0, 0, r_dst, 0, 16); 2411 else if (rSD == 34) 2412 /* mflo */ 2413 p = mkFormR(p, 0, 0, 0, r_dst, 0, 18); 2414 } 2415 2416 p = mkFormI(p, opc1, rA, r_dst, idx); 2417 2418 if (opc1 >= 40) { 2419 //store 2420 if (rSD == 33) 2421 /* mthi */ 2422 p = mkFormR(p, 0, r_dst, 0, 0, 0, 17); 2423 else if (rSD == 34) 2424 /* mtlo */ 2425 p = mkFormR(p, 0, r_dst, 0, 0, 0, 19); 2426 } 2427 2428 return p; 2429 } 2430 2431 static UChar *doAMode_RR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am, 2432 Bool mode64) 2433 { 2434 UInt rA, rB, r_dst; 2435 vassert(am->tag == Mam_RR); 2436 2437 rA = iregNo(am->Mam.RR.base, mode64); 2438 rB = iregNo(am->Mam.RR.index, mode64); 2439 2440 if (rSD == 33 || rSD == 34) 2441 r_dst = 24; 2442 else 2443 r_dst = rSD; 2444 2445 if (opc1 < 40) { 2446 //load 2447 if (rSD == 33) 2448 /* mfhi */ 2449 p = mkFormR(p, 0, 0, 0, r_dst, 0, 16); 2450 else if (rSD == 34) 2451 /* mflo */ 2452 p = mkFormR(p, 0, 0, 0, r_dst, 0, 18); 2453 } 2454 /* addiu sp, sp, -4 2455 * sw rA, 0(sp) 2456 * addu rA, rA, rB 2457 * sw/lw r_dst, 0(rA) 2458 * lw rA, 0(sp) 2459 * addiu sp, sp, 4 */ 2460 if (mode64) { 2461 p = mkFormI(p, 25, 29, 29, 0xFFFC); 2462 p = mkFormI(p, 63, 29, rA, 0); 2463 p = mkFormR(p, 0, rA, rB, rA, 0, 45); 2464 p = mkFormI(p, opc1, rA, r_dst, 0); 2465 p = mkFormI(p, 55, 29, rA, 0); 2466 p = mkFormI(p, 25, 29, 29, 4); 2467 } else { 2468 p = mkFormI(p, 9, 29, 29, 0xFFFC); 2469 p = mkFormI(p, 43, 29, rA, 0); 2470 p = mkFormR(p, 0, rA, rB, rA, 0, 33); 2471 p = mkFormI(p, opc1, rA, r_dst, 0); 2472 p = mkFormI(p, 35, 29, rA, 0); 2473 p = mkFormI(p, 9, 29, 29, 4); 2474 } 2475 if (opc1 >= 40) { 2476 //store 2477 if (rSD == 33) 2478 /* mthi */ 2479 p = mkFormR(p, 0, r_dst, 0, 0, 0, 17); 2480 else if (rSD == 34) 2481 /* mtlo */ 2482 p = mkFormR(p, 0, r_dst, 0, 0, 0, 19); 2483 } 2484 2485 return p; 2486 } 2487 2488 /* Load imm to r_dst */ 2489 static UChar *mkLoadImm(UChar * p, UInt r_dst, ULong imm, Bool mode64) 2490 { 2491 if (!mode64) { 2492 vassert(r_dst < 0x20); 2493 UInt u32 = (UInt) imm; 2494 Int s32 = (Int) u32; 2495 Long s64 = (Long) s32; 2496 imm = (ULong) s64; 2497 } 2498 2499 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) { 2500 // sign-extendable from 16 bits 2501 // addiu r_dst,0,imm => li r_dst,imm 2502 p = mkFormI(p, 9, 0, r_dst, imm & 0xFFFF); 2503 } else { 2504 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) { 2505 // sign-extendable from 32 bits 2506 // addiu r_dst,r0,(imm>>16) => lis r_dst, (imm>>16) 2507 // lui r_dst, (imm>>16) 2508 p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF); 2509 // ori r_dst, r_dst, (imm & 0xFFFF) 2510 p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF); 2511 } else { 2512 vassert(mode64); 2513 // lui load in upper half of low word 2514 p = mkFormI(p, 15, 0, r_dst, (imm >> 48) & 0xFFFF); 2515 // ori 2516 p = mkFormI(p, 13, r_dst, r_dst, (imm >> 32) & 0xFFFF); 2517 //shift 2518 p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56); 2519 // ori 2520 p = mkFormI(p, 13, r_dst, r_dst, (imm >> 16) & 0xFFFF); 2521 //shift 2522 p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56); 2523 // ori 2524 p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF); 2525 } 2526 } 2527 return p; 2528 } 2529 2530 /* A simplified version of mkLoadImm that always generates 2 or 5 2531 instructions (32 or 64 bits respectively) even if it could generate 2532 fewer. This is needed for generating fixed sized patchable 2533 sequences. */ 2534 static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p, 2535 UInt r_dst, ULong imm, Bool mode64 ) 2536 { 2537 vassert(r_dst < 0x20); 2538 2539 if (!mode64) { 2540 /* In 32-bit mode, make sure the top 32 bits of imm are a sign 2541 extension of the bottom 32 bits. (Probably unnecessary.) */ 2542 UInt u32 = (UInt)imm; 2543 Int s32 = (Int)u32; 2544 Long s64 = (Long)s32; 2545 imm = (ULong)s64; 2546 } 2547 2548 if (!mode64) { 2549 // sign-extendable from 32 bits 2550 // addiu r_dst,r0,(imm>>16) => lis r_dst, (imm>>16) 2551 // lui r_dst, (imm>>16) 2552 p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF); 2553 // ori r_dst, r_dst, (imm & 0xFFFF) 2554 p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF); 2555 } else { 2556 vassert(0); 2557 } 2558 return p; 2559 } 2560 2561 /* Checks whether the sequence of bytes at p was indeed created 2562 by mkLoadImm_EXACTLY2or5 with the given parameters. */ 2563 static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check, 2564 UInt r_dst, ULong imm, Bool mode64 ) 2565 { 2566 vassert(r_dst < 0x20); 2567 Bool ret; 2568 if (!mode64) { 2569 /* In 32-bit mode, make sure the top 32 bits of imm are a sign 2570 extension of the bottom 32 bits. (Probably unnecessary.) */ 2571 UInt u32 = (UInt)imm; 2572 Int s32 = (Int)u32; 2573 Long s64 = (Long)s32; 2574 imm = (ULong)s64; 2575 } 2576 2577 if (!mode64) { 2578 UInt expect[2] = { 0, 0 }; 2579 UChar* p = (UChar*)&expect[0]; 2580 // lui r_dst, (imm>>16) 2581 p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF); 2582 // ori r_dst, r_dst, (imm & 0xFFFF) 2583 p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF); 2584 vassert(p == (UChar*)&expect[2]); 2585 2586 ret = fetch32(p_to_check + 0) == expect[0] 2587 && fetch32(p_to_check + 4) == expect[1]; 2588 2589 } else { 2590 vassert(0); 2591 } 2592 return ret; 2593 } 2594 2595 /* Generate a machine-word sized load or store. Simplified version of 2596 the Min_Load and Min_Store cases below. */ 2597 static UChar* do_load_or_store_machine_word ( 2598 UChar* p, Bool isLoad, 2599 UInt reg, MIPSAMode* am, Bool mode64 ) 2600 { 2601 if (isLoad) { /* load */ 2602 UInt opc1, sz = mode64 ? 8 : 4; 2603 switch (am->tag) { 2604 case Mam_IR: 2605 if (mode64) { 2606 vassert(0 == (am->Mam.IR.index & 3)); 2607 } 2608 switch (sz) { 2609 case 1: 2610 opc1 = 32; 2611 break; 2612 case 2: 2613 opc1 = 33; 2614 break; 2615 case 4: 2616 opc1 = 35; 2617 break; 2618 case 8: 2619 opc1 = 55; 2620 vassert(mode64); 2621 break; 2622 default: 2623 vassert(0); 2624 break; 2625 } 2626 p = doAMode_IR(p, opc1, reg, am, mode64); 2627 break; 2628 case Mam_RR: 2629 /* we could handle this case, but we don't expect to ever 2630 need to. */ 2631 vassert(0); 2632 break; 2633 default: 2634 vassert(0); 2635 break; 2636 } 2637 } else /* store */ { 2638 UInt opc1, sz = mode64 ? 8 : 4; 2639 switch (am->tag) { 2640 case Mam_IR: 2641 if (mode64) { 2642 vassert(0 == (am->Mam.IR.index & 3)); 2643 } 2644 switch (sz) { 2645 case 1: 2646 opc1 = 40; 2647 break; 2648 case 2: 2649 opc1 = 41; 2650 break; 2651 case 4: 2652 opc1 = 43; 2653 break; 2654 case 8: 2655 vassert(mode64); 2656 opc1 = 63; 2657 break; 2658 default: 2659 vassert(0); 2660 break; 2661 } 2662 p = doAMode_IR(p, opc1, reg, am, mode64); 2663 break; 2664 case Mam_RR: 2665 /* we could handle this case, but we don't expect to ever 2666 need to. */ 2667 vassert(0); 2668 break; 2669 default: 2670 vassert(0); 2671 break; 2672 } 2673 } 2674 return p; 2675 } 2676 2677 /* Move r_dst to r_src */ 2678 static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src) 2679 { 2680 vassert(r_dst < 0x20); 2681 vassert(r_src < 0x20); 2682 2683 if (r_dst != r_src) { 2684 /* or r_dst, r_src, r_src */ 2685 p = mkFormR(p, 0, r_src, r_src, r_dst, 0, 37); 2686 } 2687 return p; 2688 } 2689 2690 /* Emit an instruction into buf and return the number of bytes used. 2691 Note that buf is not the insn's final place, and therefore it is 2692 imperative to emit position-independent code. If the emitted 2693 instruction was a profiler inc, set *is_profInc to True, else 2694 leave it unchanged. */ 2695 Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc, 2696 UChar* buf, Int nbuf, MIPSInstr* i, 2697 Bool mode64, 2698 void* disp_cp_chain_me_to_slowEP, 2699 void* disp_cp_chain_me_to_fastEP, 2700 void* disp_cp_xindir, 2701 void* disp_cp_xassisted ) 2702 { 2703 UChar *p = &buf[0]; 2704 UChar *ptmp = p; 2705 vassert(nbuf >= 32); 2706 2707 switch (i->tag) { 2708 case Min_MovCond: { 2709 MIPSRH *srcR = i->Min.MovCond.srcR; 2710 UInt condR = iregNo(i->Min.MovCond.condR, mode64); 2711 UInt dst = iregNo(i->Min.MovCond.dst, mode64); 2712 2713 UInt srcL = iregNo(i->Min.MovCond.srcL, mode64); 2714 2715 p = mkMoveReg(p, dst, srcL); 2716 if (i->Min.MovCond.cond == MIPScc_MI) { 2717 p = mkFormI(p, 7, condR, 0, 2); //bgtz cond,2 2718 } 2719 2720 p = mkFormR(p, 0, 0, 0, 0, 0, 0); //nop 2721 2722 if (srcR->tag == Mrh_Reg) { 2723 //or dst,src,src 2724 p = mkMoveReg(p, dst, iregNo(srcR->Mrh.Reg.reg, mode64)); 2725 /*p = mkFormR(p, 0, dst, iregNo(src->Mrh.Reg.reg, mode64), 2726 iregNo(src->Mrh.Reg.reg, mode64), 0, 37);*/ 2727 } else { 2728 p = mkLoadImm(p, dst, srcR->Mrh.Imm.imm16, mode64); 2729 } 2730 } 2731 goto done; 2732 2733 case Min_LI: 2734 p = mkLoadImm(p, iregNo(i->Min.LI.dst, mode64), i->Min.LI.imm, mode64); 2735 goto done; 2736 2737 case Min_Alu: { 2738 MIPSRH *srcR = i->Min.Alu.srcR; 2739 Bool immR = toBool(srcR->tag == Mrh_Imm); 2740 UInt r_dst = iregNo(i->Min.Alu.dst, mode64); 2741 UInt r_srcL = iregNo(i->Min.Alu.srcL, mode64); 2742 UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg, mode64); 2743 2744 switch (i->Min.Alu.op) { 2745 /*Malu_ADD, Malu_SUB, Malu_AND, Malu_OR, Malu_NOR, Malu_XOR */ 2746 case Malu_ADD: 2747 if (immR) { 2748 vassert(srcR->Mrh.Imm.imm16 != 0x8000); 2749 if (srcR->Mrh.Imm.syned) 2750 /* addi */ 2751 p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16); 2752 else 2753 /* addiu */ 2754 p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16); 2755 } else { 2756 /* addu */ 2757 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 33); 2758 } 2759 break; 2760 case Malu_SUB: 2761 if (immR) { 2762 /* addi , but with negated imm */ 2763 vassert(srcR->Mrh.Imm.syned); 2764 vassert(srcR->Mrh.Imm.imm16 != 0x8000); 2765 p = mkFormI(p, 8, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16)); 2766 } else { 2767 /* subu */ 2768 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 35); 2769 } 2770 break; 2771 case Malu_AND: 2772 if (immR) { 2773 /* andi */ 2774 vassert(!srcR->Mrh.Imm.syned); 2775 p = mkFormI(p, 12, r_srcL, r_dst, srcR->Mrh.Imm.imm16); 2776 } else { 2777 /* and */ 2778 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 36); 2779 } 2780 break; 2781 case Malu_OR: 2782 if (immR) { 2783 /* ori */ 2784 vassert(!srcR->Mrh.Imm.syned); 2785 p = mkFormI(p, 13, r_srcL, r_dst, srcR->Mrh.Imm.imm16); 2786 } else { 2787 /* or */ 2788 if (r_srcL == 33) 2789 //MFHI 2790 p = mkFormR(p, 0, 0, 0, r_dst, 0, 16); 2791 else if (r_srcL == 34) 2792 //MFLO 2793 p = mkFormR(p, 0, 0, 0, r_dst, 0, 18); 2794 else if (r_dst == 33) 2795 //MTHI 2796 p = mkFormR(p, 0, r_srcL, 0, 0, 0, 17); 2797 else if (r_dst == 34) 2798 //MTLO 2799 p = mkFormR(p, 0, r_srcL, 0, 0, 0, 19); 2800 else 2801 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 37); 2802 } 2803 break; 2804 case Malu_NOR: 2805 /* nor */ 2806 vassert(!immR); 2807 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 39); 2808 break; 2809 case Malu_XOR: 2810 if (immR) { 2811 /* xori */ 2812 vassert(!srcR->Mrh.Imm.syned); 2813 p = mkFormI(p, 14, r_srcL, r_dst, srcR->Mrh.Imm.imm16); 2814 } else { 2815 /* xor */ 2816 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38); 2817 } 2818 break; 2819 2820 default: 2821 goto bad; 2822 } 2823 goto done; 2824 } 2825 2826 case Min_Shft: { 2827 MIPSRH *srcR = i->Min.Shft.srcR; 2828 Bool sz32 = i->Min.Shft.sz32; 2829 Bool immR = toBool(srcR->tag == Mrh_Imm); 2830 UInt r_dst = iregNo(i->Min.Shft.dst, mode64); 2831 UInt r_srcL = iregNo(i->Min.Shft.srcL, mode64); 2832 UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg, 2833 mode64); 2834 if (!mode64) 2835 vassert(sz32); 2836 switch (i->Min.Shft.op) { 2837 case Mshft_SLL: 2838 if (sz32) { 2839 if (immR) { 2840 UInt n = srcR->Mrh.Imm.imm16; 2841 vassert(n >= 0 && n < 32); 2842 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 0); 2843 } else { 2844 /* shift variable */ 2845 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 4); 2846 } 2847 } else { 2848 if (immR) { 2849 UInt n = srcR->Mrh.Imm.imm16; 2850 vassert((n >= 0 && n < 32) || (n > 31 && n < 64)); 2851 if (n >= 0 && n < 32) { 2852 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 56); 2853 } else { 2854 p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 60); 2855 } 2856 } else { 2857 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 20); 2858 } 2859 } 2860 break; 2861 2862 case Mshft_SRL: 2863 if (sz32) { 2864 // SRL, SRLV 2865 if (immR) { 2866 UInt n = srcR->Mrh.Imm.imm16; 2867 vassert(n >= 0 && n < 32); 2868 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 2); 2869 } else { 2870 /* shift variable */ 2871 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 6); 2872 } 2873 } else { 2874 // DSRL, DSRL32, DSRLV 2875 if (immR) { 2876 UInt n = srcR->Mrh.Imm.imm16; 2877 vassert((n >= 0 && n < 32) || (n > 31 && n < 64)); 2878 if (n >= 0 && n < 32) { 2879 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 58); 2880 } else { 2881 p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 62); 2882 } 2883 } else { 2884 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 22); 2885 } 2886 } 2887 break; 2888 2889 case Mshft_SRA: 2890 if (sz32) { 2891 // SRA, SRAV 2892 if (immR) { 2893 UInt n = srcR->Mrh.Imm.imm16; 2894 vassert(n >= 0 && n < 32); 2895 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 3); 2896 } else { 2897 /* shift variable */ 2898 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 7); 2899 } 2900 } else { 2901 // DSRA, DSRA32, DSRAV 2902 if (immR) { 2903 UInt n = srcR->Mrh.Imm.imm16; 2904 vassert((n >= 0 && n < 32) || (n > 31 && n < 64)); 2905 if (n >= 0 && n < 32) { 2906 p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 59); 2907 } else { 2908 p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 63); 2909 } 2910 } else { 2911 p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 23); 2912 } 2913 } 2914 break; 2915 2916 default: 2917 goto bad; 2918 } 2919 2920 goto done; 2921 } 2922 2923 case Min_Unary: { 2924 UInt r_dst = iregNo(i->Min.Unary.dst, mode64); 2925 UInt r_src = iregNo(i->Min.Unary.src, mode64); 2926 2927 switch (i->Min.Unary.op) { 2928 /*Mun_CLO, Mun_CLZ, Mun_NOP */ 2929 case Mun_CLO: //clo 2930 p = mkFormR(p, 28, r_src, 0 /*whatever */ , r_dst, 0, 33); 2931 break; 2932 case Mun_CLZ: //clz 2933 p = mkFormR(p, 28, r_src, 0 /*whatever */ , r_dst, 0, 32); 2934 break; 2935 case Mun_NOP: //nop (sll r0,r0,0) 2936 p = mkFormR(p, 0, 0, 0, 0, 0, 0); 2937 break; 2938 } 2939 goto done; 2940 } 2941 2942 case Min_Cmp: { 2943 UInt r_srcL = iregNo(i->Min.Cmp.srcL, mode64); 2944 UInt r_srcR = iregNo(i->Min.Cmp.srcR, mode64); 2945 UInt r_dst = iregNo(i->Min.Cmp.dst, mode64); 2946 2947 switch (i->Min.Cmp.cond) { 2948 case MIPScc_EQ: 2949 /* addiu r_dst, r0, 1 2950 beq r_srcL, r_srcR, 2 2951 nop 2952 addiu r_dst, r0, 0 2953 */ 2954 p = mkFormI(p, 9, 0, r_dst, 1); 2955 p = mkFormI(p, 4, r_srcL, r_srcR, 2); 2956 p = mkFormR(p, 0, 0, 0, 0, 0, 0); 2957 p = mkFormI(p, 9, 0, r_dst, 0); 2958 break; 2959 case MIPScc_NE: 2960 /* addiu r_dst, r0, 1 2961 bne r_srcL, r_srcR, 2 2962 nop 2963 addiu r_dst, r0, 0 2964 */ 2965 p = mkFormI(p, 9, 0, r_dst, 1); 2966 p = mkFormI(p, 5, r_srcL, r_srcR, 2); 2967 p = mkFormR(p, 0, 0, 0, 0, 0, 0); 2968 p = mkFormI(p, 9, 0, r_dst, 0); 2969 break; 2970 case MIPScc_LT: 2971 /* slt r_dst, r_srcL, r_srcR */ 2972 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42); 2973 break; 2974 case MIPScc_LO: 2975 /* sltu r_dst, r_srcL, r_srcR */ 2976 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43); 2977 break; 2978 case MIPScc_LE: 2979 /* addiu r_dst, r0, 1 2980 beq r_srcL, r_srcR, 2 2981 nop 2982 slt r_dst, r_srcL, r_srcR */ 2983 p = mkFormI(p, 9, 0, r_dst, 1); 2984 p = mkFormI(p, 4, r_srcL, r_srcR, 2); 2985 p = mkFormR(p, 0, 0, 0, 0, 0, 0); 2986 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42); 2987 break; 2988 case MIPScc_LS: 2989 /* addiu r_dst, r0, 1 2990 beq r_srcL, r_srcR, 2 2991 nop 2992 sltu r_dst, r_srcL, r_srcR */ 2993 p = mkFormI(p, 9, 0, r_dst, 1); 2994 p = mkFormI(p, 4, r_srcL, r_srcR, 2); 2995 p = mkFormR(p, 0, 0, 0, 0, 0, 0); 2996 p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43); 2997 break; 2998 default: 2999 goto bad; 3000 } 3001 goto done; 3002 } 3003 3004 case Min_Mul: { 3005 Bool syned = i->Min.Mul.syned; 3006 Bool widening = i->Min.Mul.widening; 3007 Bool sz32 = i->Min.Mul.sz32; 3008 UInt r_srcL = iregNo(i->Min.Mul.srcL, mode64); 3009 UInt r_srcR = iregNo(i->Min.Mul.srcR, mode64); 3010 UInt r_dst = iregNo(i->Min.Mul.dst, mode64); 3011 3012 if (widening) { 3013 if (sz32) { 3014 if (syned) 3015 /* mult */ 3016 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24); 3017 else 3018 /* multu */ 3019 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25); 3020 } else { 3021 if (syned) /* DMULT r_dst,r_srcL,r_srcR */ 3022 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28); 3023 else /* DMULTU r_dst,r_srcL,r_srcR */ 3024 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29); 3025 } 3026 } else { 3027 if (sz32) 3028 /* mul */ 3029 p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2); 3030 else if (mode64 && !sz32) 3031 p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2); 3032 else 3033 goto bad; 3034 } 3035 goto done; 3036 } 3037 3038 case Min_Macc: { 3039 Bool syned = i->Min.Macc.syned; 3040 UInt r_srcL = iregNo(i->Min.Macc.srcL, mode64); 3041 UInt r_srcR = iregNo(i->Min.Macc.srcR, mode64); 3042 3043 if (syned) { 3044 switch (i->Min.Macc.op) { 3045 case Macc_ADD: 3046 //madd 3047 p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 0); 3048 break; 3049 case Macc_SUB: 3050 //msub 3051 p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 3052 4); 3053 break; 3054 default: 3055 goto bad; 3056 } 3057 } else { 3058 switch (i->Min.Macc.op) { 3059 case Macc_ADD: 3060 //maddu 3061 p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 3062 1); 3063 break; 3064 case Macc_SUB: 3065 //msubu 3066 p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 3067 5); 3068 break; 3069 default: 3070 goto bad; 3071 } 3072 } 3073 3074 goto done; 3075 } 3076 3077 case Min_Div: { 3078 Bool syned = i->Min.Div.syned; 3079 Bool sz32 = i->Min.Div.sz32; 3080 UInt r_srcL = iregNo(i->Min.Div.srcL, mode64); 3081 UInt r_srcR = iregNo(i->Min.Div.srcR, mode64); 3082 if (sz32) { 3083 if (syned) { 3084 /* div */ 3085 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 26); 3086 } else 3087 /* divu */ 3088 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 27); 3089 goto done; 3090 } else { 3091 if (syned) { 3092 /* ddiv */ 3093 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 30); 3094 } else 3095 /* ddivu */ 3096 p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 31); 3097 goto done; 3098 } 3099 } 3100 3101 case Min_Mthi: { 3102 UInt r_src = iregNo(i->Min.MtHL.src, mode64); 3103 p = mkFormR(p, 0, r_src, 0, 0, 0, 17); 3104 goto done; 3105 } 3106 3107 case Min_Mtlo: { 3108 UInt r_src = iregNo(i->Min.MtHL.src, mode64); 3109 p = mkFormR(p, 0, r_src, 0, 0, 0, 19); 3110 goto done; 3111 } 3112 3113 case Min_Mfhi: { 3114 UInt r_dst = iregNo(i->Min.MfHL.dst, mode64); 3115 p = mkFormR(p, 0, 0, 0, r_dst, 0, 16); 3116 goto done; 3117 } 3118 3119 case Min_Mflo: { 3120 UInt r_dst = iregNo(i->Min.MfHL.dst, mode64); 3121 p = mkFormR(p, 0, 0, 0, r_dst, 0, 18); 3122 goto done; 3123 } 3124 3125 case Min_MtFCSR: { 3126 UInt r_src = iregNo(i->Min.MtFCSR.src, mode64); 3127 /* ctc1 */ 3128 p = mkFormR(p, 17, 6, r_src, 31, 0, 0); 3129 goto done; 3130 } 3131 3132 case Min_MfFCSR: { 3133 UInt r_dst = iregNo(i->Min.MfFCSR.dst, mode64); 3134 /* cfc1 */ 3135 p = mkFormR(p, 17, 2, r_dst, 31, 0, 0); 3136 goto done; 3137 } 3138 3139 case Min_Call: { 3140 MIPSCondCode cond = i->Min.Call.cond; 3141 UInt r_dst = 25; /* using %r25 as address temporary - 3142 see getRegUsage_MIPSInstr */ 3143 3144 /* jump over the following insns if condition does not hold */ 3145 if (cond != MIPScc_AL) { 3146 /* jmp fwds if !condition */ 3147 /* don't know how many bytes to jump over yet... 3148 make space for a jump instruction + nop!!! and fill in later. */ 3149 ptmp = p; /* fill in this bit later */ 3150 p += 8; // p += 8 3151 } 3152 3153 /* load target to r_dst */// p += 4|8 3154 p = mkLoadImm(p, r_dst, i->Min.Call.target, mode64); 3155 3156 /* jalr %r_dst */ 3157 p = mkFormR(p, 0, r_dst, 0, 31, 0, 9); // p += 4 3158 p = mkFormR(p, 0, 0, 0, 0, 0, 0); // p += 4 3159 3160 /* Fix up the conditional jump, if there was one. */ 3161 if (cond != MIPScc_AL) { 3162 UInt r_src = iregNo(i->Min.Call.src, mode64); 3163 Int delta = p - ptmp; 3164 3165 vassert(delta >= 20 && delta <= 32); 3166 /* bc !ct,cf,delta/4 */ 3167 /* blez r_src, delta/4-1 */ 3168 vassert(cond == MIPScc_EQ); 3169 ptmp = mkFormI(ptmp, 6, r_src, 0, delta / 4 - 1); 3170 ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0); 3171 } 3172 goto done; 3173 } 3174 3175 case Min_XDirect: { 3176 /* NB: what goes on here has to be very closely coordinated 3177 with the chainXDirect_MIPS and unchainXDirect_MIPS below. */ 3178 /* We're generating chain-me requests here, so we need to be 3179 sure this is actually allowed -- no-redir translations 3180 can't use chain-me's. Hence: */ 3181 vassert(disp_cp_chain_me_to_slowEP != NULL); 3182 vassert(disp_cp_chain_me_to_fastEP != NULL); 3183 3184 /* Use ptmp for backpatching conditional jumps. */ 3185 ptmp = NULL; 3186 3187 /* First off, if this is conditional, create a conditional 3188 jump over the rest of it. Or at least, leave a space for 3189 it that we will shortly fill in. */ 3190 if (i->Min.XDirect.cond != MIPScc_AL) { 3191 vassert(i->Min.XDirect.cond != MIPScc_NV); 3192 ptmp = p; 3193 p += 12; 3194 } 3195 3196 /* Update the guest PC. */ 3197 /* move r9, dstGA */ 3198 /* sw r9, amPC */ 3199 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 3200 (ULong)i->Min.XDirect.dstGA, mode64); 3201 p = do_load_or_store_machine_word(p, False/*!isLoad*/, 3202 /*r*/9, i->Min.XDirect.amPC, mode64); 3203 3204 /* --- FIRST PATCHABLE BYTE follows --- */ 3205 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're 3206 calling to) backs up the return address, so as to find the 3207 address of the first patchable byte. So: don't change the 3208 number of instructions (3) below. */ 3209 /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */ 3210 /* jr r9 */ 3211 void* disp_cp_chain_me 3212 = i->Min.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP 3213 : disp_cp_chain_me_to_slowEP; 3214 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 3215 Ptr_to_ULong(disp_cp_chain_me), mode64); 3216 /* jalr $9 */ 3217 /* nop */ 3218 p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4 3219 p = mkFormR(p, 0, 0, 0, 0, 0, 0); // p += 4 3220 /* --- END of PATCHABLE BYTES --- */ 3221 3222 /* Fix up the conditional jump, if there was one. */ 3223 if (i->Min.XDirect.cond != MIPScc_AL) { 3224 Int delta = p - ptmp; 3225 delta = delta / 4 - 3; 3226 vassert(delta > 0 && delta < 40); 3227 /* lw $9, 316($10) // guest_COND 3228 beq $9, $0, 2 3229 nop*/ 3230 ptmp = mkFormI(ptmp, 35, 10, 9, 316); 3231 ptmp = mkFormI(ptmp, 4, 0, 9, (delta)); 3232 ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0); 3233 } 3234 goto done; 3235 } 3236 3237 case Min_XIndir: { 3238 /* We're generating transfers that could lead indirectly to a 3239 chain-me, so we need to be sure this is actually allowed -- 3240 no-redir translations are not allowed to reach normal 3241 translations without going through the scheduler. That means 3242 no XDirects or XIndirs out from no-redir translations. 3243 Hence: */ 3244 vassert(disp_cp_xindir != NULL); 3245 3246 /* Use ptmp for backpatching conditional jumps. */ 3247 ptmp = NULL; 3248 3249 /* First off, if this is conditional, create a conditional 3250 jump over the rest of it. */ 3251 if (i->Min.XIndir.cond != MIPScc_AL) { 3252 vassert(i->Min.XIndir.cond != MIPScc_NV); 3253 ptmp = p; 3254 p += 12; 3255 } 3256 3257 /* Update the guest PC. */ 3258 /* sw r-dstGA, amPC */ 3259 p = do_load_or_store_machine_word(p, False/*!isLoad*/, 3260 iregNo(i->Min.XIndir.dstGA, mode64), 3261 i->Min.XIndir.amPC, mode64); 3262 3263 /* move r9, VG_(disp_cp_xindir) */ 3264 /* jalr r9 */ 3265 /* nop */ 3266 p = mkLoadImm_EXACTLY2or5 ( p, /*r*/9, 3267 Ptr_to_ULong(disp_cp_xindir), mode64); 3268 p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4 3269 p = mkFormR(p, 0, 0, 0, 0, 0, 0); // p += 4 3270 3271 /* Fix up the conditional jump, if there was one. */ 3272 if (i->Min.XIndir.cond != MIPScc_AL) { 3273 Int delta = p - ptmp; 3274 delta = delta / 4 - 3; 3275 vassert(delta > 0 && delta < 40); 3276 /* lw $9, 316($10) // guest_COND 3277 beq $9, $0, 2 3278 nop*/ 3279 ptmp = mkFormI(ptmp, 35, 10, 9, 316); 3280 ptmp = mkFormI(ptmp, 4, 0, 9, (delta)); 3281 ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0); 3282 } 3283 goto done; 3284 } 3285 3286 case Min_XAssisted: { 3287 /* First off, if this is conditional, create a conditional jump 3288 over the rest of it. Or at least, leave a space for it that 3289 we will shortly fill in. */ 3290 ptmp = NULL; 3291 if (i->Min.XAssisted.cond != MIPScc_AL) { 3292 vassert(i->Min.XAssisted.cond != MIPScc_NV); 3293 ptmp = p; 3294 p += 12; 3295 } 3296 3297 /* Update the guest PC. */ 3298 /* sw r-dstGA, amPC */ 3299 p = do_load_or_store_machine_word(p, False/*!isLoad*/, 3300 iregNo(i->Min.XIndir.dstGA, mode64), 3301 i->Min.XIndir.amPC, mode64); 3302 3303 /* imm32/64 r31, $magic_number */ 3304 UInt trcval = 0; 3305 switch (i->Min.XAssisted.jk) { 3306 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break; 3307 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break; 3308 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break; 3309 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break; 3310 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break; 3311 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break; 3312 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break; 3313 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break; 3314 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break; 3315 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break; 3316 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break; 3317 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break; 3318 case Ijk_SigBUS: trcval = VEX_TRC_JMP_SIGBUS; break; 3319 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break; 3320 /* We don't expect to see the following being assisted. */ 3321 //case Ijk_Ret: 3322 //case Ijk_Call: 3323 /* fallthrough */ 3324 default: 3325 ppIRJumpKind(i->Min.XAssisted.jk); 3326 vpanic("emit_MIPSInstr.Min_XAssisted: unexpected jump kind"); 3327 } 3328 vassert(trcval != 0); 3329 p = mkLoadImm_EXACTLY2or5(p, /*r*/10, trcval, mode64); 3330 3331 /* move r9, VG_(disp_cp_xassisted) */ 3332 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 3333 (ULong)Ptr_to_ULong(disp_cp_xassisted), mode64); 3334 /* jalr $9 3335 nop */ 3336 p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4 3337 p = mkFormR(p, 0, 0, 0, 0, 0, 0); // p += 4 3338 3339 /* Fix up the conditional jump, if there was one. */ 3340 if (i->Min.XAssisted.cond != MIPScc_AL) { 3341 Int delta = p - ptmp; 3342 delta = delta / 4 - 3; 3343 vassert(delta > 0 && delta < 40); 3344 /* lw $9, 316($10) // guest_COND 3345 beq $9, $0, 2 3346 nop*/ 3347 ptmp = mkFormI(ptmp, 35, 10, 9, 316); 3348 ptmp = mkFormI(ptmp, 4, 0, 9, (delta)); 3349 ptmp = mkFormR(ptmp, 0, 0, 0, 0, 0, 0); 3350 } 3351 goto done; 3352 } 3353 3354 case Min_Load: { 3355 MIPSAMode *am_addr = i->Min.Load.src; 3356 if (am_addr->tag == Mam_IR) { 3357 UInt r_dst = iregNo(i->Min.Load.dst, mode64); 3358 UInt opc, sz = i->Min.Load.sz; 3359 if (mode64 && (sz == 4 || sz == 8)) { 3360 /* should be guaranteed to us by iselWordExpr_AMode */ 3361 vassert(0 == (am_addr->Mam.IR.index & 3)); 3362 } 3363 switch (sz) { 3364 case 1: 3365 opc = 32; 3366 break; 3367 case 2: 3368 opc = 33; 3369 break; 3370 case 4: 3371 opc = 35; 3372 break; 3373 case 8: 3374 opc = 55; 3375 vassert(mode64); 3376 break; 3377 default: 3378 goto bad; 3379 } 3380 3381 p = doAMode_IR(p, opc, r_dst, am_addr, mode64); 3382 goto done; 3383 } else if (am_addr->tag == Mam_RR) { 3384 UInt r_dst = iregNo(i->Min.Load.dst, mode64); 3385 UInt opc, sz = i->Min.Load.sz; 3386 3387 switch (sz) { 3388 case 1: 3389 opc = 32; 3390 break; 3391 case 2: 3392 opc = 33; 3393 break; 3394 case 4: 3395 opc = 35; 3396 break; 3397 case 8: 3398 opc = 55; 3399 vassert(mode64); 3400 break; 3401 default: 3402 goto bad; 3403 } 3404 3405 p = doAMode_RR(p, opc, r_dst, am_addr, mode64); 3406 goto done; 3407 } 3408 break; 3409 } 3410 3411 case Min_Store: { 3412 MIPSAMode *am_addr = i->Min.Store.dst; 3413 if (am_addr->tag == Mam_IR) { 3414 UInt r_src = iregNo(i->Min.Store.src, mode64); 3415 UInt opc, sz = i->Min.Store.sz; 3416 if (mode64 && (sz == 4 || sz == 8)) { 3417 /* should be guaranteed to us by iselWordExpr_AMode */ 3418 vassert(0 == (am_addr->Mam.IR.index & 3)); 3419 } 3420 switch (sz) { 3421 case 1: 3422 opc = 40; 3423 break; 3424 case 2: 3425 opc = 41; 3426 break; 3427 case 4: 3428 opc = 43; 3429 break; 3430 case 8: 3431 vassert(mode64); 3432 opc = 63; 3433 break; 3434 default: 3435 goto bad; 3436 } 3437 3438 p = doAMode_IR(p, opc, r_src, am_addr, mode64); 3439 goto done; 3440 } else if (am_addr->tag == Mam_RR) { 3441 UInt r_src = iregNo(i->Min.Store.src, mode64); 3442 UInt opc, sz = i->Min.Store.sz; 3443 3444 switch (sz) { 3445 case 1: 3446 opc = 40; 3447 break; 3448 case 2: 3449 opc = 41; 3450 break; 3451 case 4: 3452 opc = 43; 3453 break; 3454 case 8: 3455 vassert(mode64); 3456 opc = 63; 3457 break; 3458 default: 3459 goto bad; 3460 } 3461 3462 p = doAMode_RR(p, opc, r_src, am_addr, mode64); 3463 goto done; 3464 } 3465 break; 3466 } 3467 case Min_LoadL: { 3468 MIPSAMode *am_addr = i->Min.LoadL.src; 3469 UInt r_src = iregNo(am_addr->Mam.IR.base, mode64); 3470 UInt idx = am_addr->Mam.IR.index; 3471 UInt r_dst = iregNo(i->Min.LoadL.dst, mode64); 3472 3473 p = mkFormI(p, 0x30, r_src, r_dst, idx); 3474 goto done; 3475 } 3476 case Min_StoreC: { 3477 MIPSAMode *am_addr = i->Min.StoreC.dst; 3478 UInt r_src = iregNo(i->Min.StoreC.src, mode64); 3479 UInt idx = am_addr->Mam.IR.index; 3480 UInt r_dst = iregNo(am_addr->Mam.IR.base, mode64); 3481 3482 p = mkFormI(p, 0x38, r_dst, r_src, idx); 3483 goto done; 3484 } 3485 case Min_RdWrLR: { 3486 UInt reg = iregNo(i->Min.RdWrLR.gpr, mode64); 3487 Bool wrLR = i->Min.RdWrLR.wrLR; 3488 if (wrLR) 3489 p = mkMoveReg(p, 31, reg); 3490 else 3491 p = mkMoveReg(p, reg, 31); 3492 goto done; 3493 } 3494 3495 // Floating point 3496 3497 case Min_FpLdSt: { 3498 MIPSAMode *am_addr = i->Min.FpLdSt.addr; 3499 UChar sz = i->Min.FpLdSt.sz; 3500 vassert(sz == 4 || sz == 8); 3501 if (sz == 4) { 3502 UInt f_reg = fregNo(i->Min.FpLdSt.reg, mode64); 3503 if (i->Min.FpLdSt.isLoad) { 3504 if (am_addr->tag == Mam_IR) 3505 p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64); 3506 else if (am_addr->tag == Mam_RR) 3507 p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64); 3508 } else { 3509 if (am_addr->tag == Mam_IR) 3510 p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64); 3511 else if (am_addr->tag == Mam_RR) 3512 p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64); 3513 } 3514 } else if (sz == 8) { 3515 UInt f_reg = dregNo(i->Min.FpLdSt.reg); 3516 if (i->Min.FpLdSt.isLoad) { 3517 if (am_addr->tag == Mam_IR) { 3518 if (mode64) { 3519 p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64); 3520 } else { 3521 p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64); 3522 p = doAMode_IR(p, 0x31, f_reg + 1, 3523 nextMIPSAModeFloat(am_addr), mode64); 3524 } 3525 } else if (am_addr->tag == Mam_RR) { 3526 if (mode64) { 3527 p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64); 3528 } else { 3529 p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64); 3530 p = doAMode_RR(p, 0x31, f_reg + 1, 3531 nextMIPSAModeFloat(am_addr), mode64); 3532 } 3533 } 3534 } else { 3535 if (am_addr->tag == Mam_IR) { 3536 if (mode64) { 3537 p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64); 3538 } else { 3539 p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64); 3540 p = doAMode_IR(p, 0x39, f_reg + 1, 3541 nextMIPSAModeFloat(am_addr), mode64); 3542 } 3543 } else if (am_addr->tag == Mam_RR) { 3544 if (mode64) { 3545 p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64); 3546 } else { 3547 p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64); 3548 p = doAMode_RR(p, 0x39, f_reg + 1, 3549 nextMIPSAModeFloat(am_addr), mode64); 3550 } 3551 } 3552 } 3553 } 3554 goto done; 3555 } 3556 3557 case Min_FpUnary: { 3558 switch (i->Min.FpUnary.op) { 3559 case Mfp_MOVS: { // FP move 3560 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3561 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3562 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x6); 3563 break; 3564 } 3565 case Mfp_MOVD: { // FP move 3566 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3567 UInt fr_src = dregNo(i->Min.FpUnary.src); 3568 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x6); 3569 break; 3570 } 3571 case Mfp_ABSS: { // ABSS 3572 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3573 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3574 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x5); 3575 break; 3576 } 3577 case Mfp_ABSD: { // ABSD 3578 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3579 UInt fr_src = dregNo(i->Min.FpUnary.src); 3580 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x5); 3581 break; 3582 } 3583 case Mfp_NEGS: { // ABSS 3584 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3585 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3586 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x7); 3587 break; 3588 } 3589 case Mfp_NEGD: { // ABSD 3590 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3591 UInt fr_src = dregNo(i->Min.FpUnary.src); 3592 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x7); 3593 break; 3594 } 3595 case Mfp_CVTD: { //CVT.D 3596 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3597 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3598 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x21); 3599 break; 3600 } 3601 case Mfp_SQRTS: { //SQRT.S 3602 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3603 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3604 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x04); 3605 break; 3606 } 3607 case Mfp_SQRTD: { //SQRT.D 3608 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3609 UInt fr_src = dregNo(i->Min.FpUnary.src); 3610 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x04); 3611 break; 3612 } 3613 case Mfp_RSQRTS: { //RSQRT.S 3614 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3615 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3616 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x16); 3617 break; 3618 } 3619 case Mfp_RSQRTD: { //RSQRT.D 3620 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3621 UInt fr_src = dregNo(i->Min.FpUnary.src); 3622 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x16); 3623 break; 3624 } 3625 case Mfp_RECIPS: { //RECIP.S 3626 UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64); 3627 UInt fr_src = fregNo(i->Min.FpUnary.src, mode64); 3628 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x15); 3629 break; 3630 } 3631 case Mfp_RECIPD: { //RECIP.D 3632 UInt fr_dst = dregNo(i->Min.FpUnary.dst); 3633 UInt fr_src = dregNo(i->Min.FpUnary.src); 3634 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x15); 3635 break; 3636 } 3637 default: 3638 goto bad; 3639 } 3640 goto done; 3641 } 3642 3643 case Min_FpBinary: { 3644 switch (i->Min.FpBinary.op) { 3645 case Mfp_ADDS: { 3646 UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64); 3647 UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64); 3648 UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64); 3649 p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 0); 3650 break; 3651 } 3652 case Mfp_SUBS: { 3653 UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64); 3654 UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64); 3655 UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64); 3656 p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 1); 3657 break; 3658 } 3659 case Mfp_MULS: { 3660 UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64); 3661 UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64); 3662 UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64); 3663 p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 2); 3664 break; 3665 } 3666 case Mfp_DIVS: { 3667 UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64); 3668 UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64); 3669 UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64); 3670 p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 3); 3671 break; 3672 } 3673 case Mfp_ADDD: { 3674 UInt fr_dst = dregNo(i->Min.FpBinary.dst); 3675 UInt fr_srcL = dregNo(i->Min.FpBinary.srcL); 3676 UInt fr_srcR = dregNo(i->Min.FpBinary.srcR); 3677 p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 0); 3678 break; 3679 } 3680 case Mfp_SUBD: { 3681 UInt fr_dst = dregNo(i->Min.FpBinary.dst); 3682 UInt fr_srcL = dregNo(i->Min.FpBinary.srcL); 3683 UInt fr_srcR = dregNo(i->Min.FpBinary.srcR); 3684 p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 1); 3685 break; 3686 } 3687 case Mfp_MULD: { 3688 UInt fr_dst = dregNo(i->Min.FpBinary.dst); 3689 UInt fr_srcL = dregNo(i->Min.FpBinary.srcL); 3690 UInt fr_srcR = dregNo(i->Min.FpBinary.srcR); 3691 p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 2); 3692 break; 3693 } 3694 case Mfp_DIVD: { 3695 UInt fr_dst = dregNo(i->Min.FpBinary.dst); 3696 UInt fr_srcL = dregNo(i->Min.FpBinary.srcL); 3697 UInt fr_srcR = dregNo(i->Min.FpBinary.srcR); 3698 p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 3); 3699 break; 3700 } 3701 default: 3702 goto bad; 3703 } 3704 goto done; 3705 } 3706 3707 case Min_FpConvert: { 3708 switch (i->Min.FpConvert.op) { 3709 UInt fr_dst, fr_src; 3710 case Mfp_CVTSD: 3711 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3712 fr_src = dregNo(i->Min.FpConvert.src); 3713 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x20); 3714 break; 3715 case Mfp_CVTSW: 3716 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3717 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3718 p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x20); 3719 break; 3720 case Mfp_CVTWD: 3721 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3722 fr_src = dregNo(i->Min.FpConvert.src); 3723 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x24); 3724 break; 3725 case Mfp_CVTWS: 3726 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3727 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3728 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x24); 3729 break; 3730 case Mfp_CVTDW: 3731 fr_dst = dregNo(i->Min.FpConvert.dst); 3732 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3733 p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x21); 3734 break; 3735 case Mfp_TRUWS: 3736 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3737 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3738 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0D); 3739 break; 3740 case Mfp_TRUWD: 3741 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3742 fr_src = dregNo(i->Min.FpConvert.src); 3743 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0D); 3744 break; 3745 case Mfp_TRULS: 3746 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3747 fr_src = dregNo(i->Min.FpConvert.src); 3748 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x09); 3749 break; 3750 case Mfp_TRULD: 3751 fr_dst = dregNo(i->Min.FpConvert.dst); 3752 fr_src = dregNo(i->Min.FpConvert.src); 3753 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x09); 3754 break; 3755 case Mfp_CEILWS: 3756 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3757 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3758 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0E); 3759 break; 3760 case Mfp_CEILWD: 3761 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3762 fr_src = dregNo(i->Min.FpConvert.src); 3763 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0E); 3764 break; 3765 case Mfp_CEILLS: 3766 fr_dst = dregNo(i->Min.FpConvert.dst); 3767 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3768 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0A); 3769 break; 3770 case Mfp_CEILLD: 3771 fr_dst = dregNo(i->Min.FpConvert.dst); 3772 fr_src = dregNo(i->Min.FpConvert.src); 3773 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0A); 3774 break; 3775 case Mfp_ROUNDWS: 3776 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3777 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3778 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0C); 3779 break; 3780 case Mfp_ROUNDWD: 3781 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3782 fr_src = dregNo(i->Min.FpConvert.src); 3783 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0C); 3784 break; 3785 case Mfp_FLOORWS: 3786 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3787 fr_src = fregNo(i->Min.FpConvert.src, mode64); 3788 p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0F); 3789 break; 3790 case Mfp_FLOORWD: 3791 fr_dst = fregNo(i->Min.FpConvert.dst, mode64); 3792 fr_src = dregNo(i->Min.FpConvert.src); 3793 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0F); 3794 break; 3795 3796 default: 3797 goto bad; 3798 } 3799 goto done; 3800 } 3801 3802 case Min_FpCompare: { 3803 UInt r_dst = iregNo(i->Min.FpCompare.dst, mode64); 3804 UInt fr_srcL = dregNo(i->Min.FpCompare.srcL); 3805 UInt fr_srcR = dregNo(i->Min.FpCompare.srcR); 3806 3807 switch (i->Min.FpConvert.op) { 3808 case Mfp_CMP: 3809 p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0, 3810 (i->Min.FpCompare.cond1 + 48)); 3811 p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0); 3812 break; 3813 default: 3814 goto bad; 3815 } 3816 goto done; 3817 } 3818 case Min_EvCheck: { 3819 /* This requires a 32-bit dec/test in 32 mode. */ 3820 /* We generate: 3821 lw r9, amCounter 3822 addiu r9, r9, -1 3823 sw r9, amCounter 3824 bgez r9, nofail 3825 lw r9, amFailAddr 3826 jalr r9 3827 nop 3828 nofail: 3829 */ 3830 UChar* p0 = p; 3831 /* lw r9, amCounter */ 3832 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/9, 3833 i->Min.EvCheck.amCounter, mode64); 3834 /* addiu r9,r9,-1 */ 3835 p = mkFormI(p, 9, 9, 9, 0xFFFF); 3836 /* sw r30, amCounter */ 3837 p = do_load_or_store_machine_word(p, False/*!isLoad*/, /*r*/9, 3838 i->Min.EvCheck.amCounter, mode64); 3839 /* bgez t9, nofail */ 3840 p = mkFormI(p, 1, 9, 1, 3); 3841 /* lw r9, amFailAddr */ 3842 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/9, 3843 i->Min.EvCheck.amFailAddr, mode64); 3844 /* jalr $9 */ 3845 p = mkFormR(p, 0, 9, 0, 31, 0, 9); // p += 4 3846 p = mkFormR(p, 0, 0, 0, 0, 0, 0); // p += 4 3847 /* nofail: */ 3848 3849 /* Crosscheck */ 3850 vassert(evCheckSzB_MIPS() == (UChar*)p - (UChar*)p0); 3851 goto done; 3852 } 3853 3854 case Min_ProfInc: { 3855 /* Generate a code template to increment a memory location whose 3856 address will be known later as an immediate value. This code 3857 template will be patched once the memory location is known. 3858 For now we do this with address == 0x65556555. 3859 32-bit: 3860 3861 move r9, 0x65556555 3862 lw r8, 0(r9) 3863 addiu r8, r8, 1 # add least significant word 3864 sw r8, 0(r9) 3865 sltiu r1, r8, 1 # set carry-in bit 3866 lw r8, 4(r9) 3867 addu r8, r8, r1 3868 sw r8, 4(r9) */ 3869 3870 if (mode64) { 3871 vassert(0); 3872 } else { 3873 // move r9, 0x65556555 3874 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 0x65556555ULL, 3875 False/*!mode64*/); 3876 // lw r8, 0(r9) 3877 p = mkFormI(p, 35, 9, 8, 0); 3878 3879 // addiu r8, r8, 1 # add least significant word 3880 p = mkFormI(p, 9, 8, 8, 1); 3881 3882 // sw r8, 0(r9) 3883 p = mkFormI(p, 43, 9, 8, 0); 3884 3885 // sltiu r1, r8, 1 # set carry-in bit 3886 p = mkFormI(p, 11, 8, 1, 1); 3887 3888 // lw r8, 4(r9) 3889 p = mkFormI(p, 35, 9, 8, 4); 3890 3891 // addu r8, r8, r1 3892 p = mkFormR(p, 0, 8, 1, 8, 0, 33); 3893 3894 // sw r8, 4(r9) 3895 p = mkFormI(p, 43, 9, 8, 4); 3896 3897 } 3898 /* Tell the caller .. */ 3899 vassert(!(*is_profInc)); 3900 *is_profInc = True; 3901 goto done; 3902 } 3903 3904 default: 3905 goto bad; 3906 3907 } 3908 3909 bad: 3910 vex_printf("\n=> "); 3911 ppMIPSInstr(i, mode64); 3912 vpanic("emit_MIPSInstr"); 3913 /*NOTREACHED*/ done: 3914 //vassert(p - &buf[0] <= 32); 3915 return p - &buf[0]; 3916 } 3917 3918 /* How big is an event check? See case for Min_EvCheck in 3919 emit_MIPSInstr just above. That crosschecks what this returns, so 3920 we can tell if we're inconsistent. */ 3921 Int evCheckSzB_MIPS ( void ) 3922 { 3923 UInt kInstrSize = 4; 3924 return 7*kInstrSize; 3925 } 3926 3927 /* NB: what goes on here has to be very closely coordinated with the 3928 emitInstr case for XDirect, above. */ 3929 VexInvalRange chainXDirect_MIPS ( void* place_to_chain, 3930 void* disp_cp_chain_me_EXPECTED, 3931 void* place_to_jump_to, 3932 Bool mode64 ) 3933 { 3934 /* What we're expecting to see is: 3935 move r9, disp_cp_chain_me_to_EXPECTED 3936 jalr r9 3937 nop 3938 viz 3939 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5> 3940 0x120F809 // jalr r9 3941 0x00000000 // nop 3942 */ 3943 UChar* p = (UChar*)place_to_chain; 3944 vassert(0 == (3 & (HWord)p)); 3945 vassert(isLoadImm_EXACTLY2or5(p, /*r*/9, 3946 (UInt)Ptr_to_ULong(disp_cp_chain_me_EXPECTED), 3947 mode64)); 3948 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x120F809); 3949 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x00000000); 3950 /* And what we want to change it to is either: 3951 move r9, place_to_jump_to 3952 jalr r9 3953 nop 3954 viz 3955 <8 bytes generated by mkLoadImm_EXACTLY2or5> 3956 0x120F809 // jalr r9 3957 0x00000000 // nop 3958 3959 The replacement has the same length as the original. 3960 */ 3961 3962 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 3963 Ptr_to_ULong(place_to_jump_to), mode64); 3964 p = emit32(p, 0x120F809); 3965 p = emit32(p, 0x00000000); 3966 3967 Int len = p - (UChar*)place_to_chain; 3968 vassert(len == (mode64 ? 28 : 16)); /* stay sane */ 3969 VexInvalRange vir = {(HWord)place_to_chain, len}; 3970 return vir; 3971 } 3972 3973 /* NB: what goes on here has to be very closely coordinated with the 3974 emitInstr case for XDirect, above. */ 3975 VexInvalRange unchainXDirect_MIPS ( void* place_to_unchain, 3976 void* place_to_jump_to_EXPECTED, 3977 void* disp_cp_chain_me, 3978 Bool mode64 ) 3979 { 3980 /* What we're expecting to see is: 3981 move r9, place_to_jump_to_EXPECTED 3982 jalr r9 3983 nop 3984 viz 3985 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5> 3986 0x120F809 // jalr r9 3987 0x00000000 // nop 3988 */ 3989 UChar* p = (UChar*)place_to_unchain; 3990 vassert(0 == (3 & (HWord)p)); 3991 vassert(isLoadImm_EXACTLY2or5(p, /*r*/9, 3992 Ptr_to_ULong(place_to_jump_to_EXPECTED), 3993 mode64)); 3994 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x120F809); 3995 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x00000000); 3996 /* And what we want to change it to is: 3997 move r9, disp_cp_chain_me 3998 jalr r9 3999 nop 4000 viz 4001 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5> 4002 0x120F809 // jalr r9 4003 0x00000000 // nop 4004 The replacement has the same length as the original. 4005 */ 4006 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 4007 Ptr_to_ULong(disp_cp_chain_me), mode64); 4008 p = emit32(p, 0x120F809); 4009 p = emit32(p, 0x00000000); 4010 4011 Int len = p - (UChar*)place_to_unchain; 4012 vassert(len == (mode64 ? 28 : 16)); /* stay sane */ 4013 VexInvalRange vir = {(HWord)place_to_unchain, len}; 4014 return vir; 4015 } 4016 4017 /* Patch the counter address into a profile inc point, as previously 4018 created by the Min_ProfInc case for emit_MIPSInstr. */ 4019 VexInvalRange patchProfInc_MIPS ( void* place_to_patch, 4020 ULong* location_of_counter, Bool mode64 ) 4021 { 4022 vassert(sizeof(ULong*) == 4); 4023 UChar* p = (UChar*)place_to_patch; 4024 vassert(0 == (3 & (HWord)p)); 4025 vassert(isLoadImm_EXACTLY2or5((UChar *)p, /*r*/9, 0x65556555, mode64)); 4026 4027 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x8D280000); 4028 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x25080001); 4029 vassert(fetch32(p + (mode64 ? 20 : 8) + 8) == 0xAD280000); 4030 vassert(fetch32(p + (mode64 ? 20 : 8) + 12) == 0x2d010001); 4031 vassert(fetch32(p + (mode64 ? 20 : 8) + 16) == 0x8d280004); 4032 vassert(fetch32(p + (mode64 ? 20 : 8) + 20) == 0x01014021); 4033 vassert(fetch32(p + (mode64 ? 20 : 8) + 24) == 0xad280004); 4034 4035 p = mkLoadImm_EXACTLY2or5(p, /*r*/9, 4036 Ptr_to_ULong(location_of_counter), mode64); 4037 4038 VexInvalRange vir = {(HWord)p, 8}; 4039 return vir; 4040 } 4041 4042 4043 /*---------------------------------------------------------------*/ 4044 /*--- end host_mips_defs.c ---*/ 4045 /*---------------------------------------------------------------*/ 4046