1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_mips_toIR.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 /* Translates MIPS code to IR. */ 32 33 #include "libvex_basictypes.h" 34 #include "libvex_ir.h" 35 #include "libvex.h" 36 #include "libvex_guest_mips32.h" 37 38 #include "main_util.h" 39 #include "main_globals.h" 40 #include "guest_generic_bb_to_IR.h" 41 #include "guest_mips_defs.h" 42 43 /*------------------------------------------------------------*/ 44 /*--- Globals ---*/ 45 /*------------------------------------------------------------*/ 46 47 /* These are set at the start of the translation of a instruction, so 48 that we don't have to pass them around endlessly. CONST means does 49 not change during translation of the instruction. 50 */ 51 52 /* CONST: is the host bigendian? This has to do with float vs double 53 register accesses on VFP, but it's complex and not properly thought 54 out. */ 55 static Bool host_is_bigendian; 56 57 /* Pointer to the guest code area. */ 58 static UChar *guest_code; 59 60 /* The guest address corresponding to guest_code[0]. */ 61 static Addr32 guest_PC_bbstart; 62 63 /* CONST: The guest address for the instruction currently being 64 translated. */ 65 static Addr32 guest_PC_curr_instr; 66 67 /* MOD: The IRSB* into which we're generating code. */ 68 static IRSB *irsb; 69 70 /* Is our guest binary 32 or 64bit? Set at each call to 71 disInstr_MIPS below. */ 72 static Bool mode64 = False; 73 74 /*------------------------------------------------------------*/ 75 /*--- Debugging output ---*/ 76 /*------------------------------------------------------------*/ 77 78 #define DIP(format, args...) \ 79 if (vex_traceflags & VEX_TRACE_FE) \ 80 vex_printf(format, ## args) 81 82 /*------------------------------------------------------------*/ 83 /*--- Helper bits and pieces for deconstructing the ---*/ 84 /*--- mips insn stream. ---*/ 85 /*------------------------------------------------------------*/ 86 87 /* ---------------- Integer registers ---------------- */ 88 89 static UInt integerGuestRegOffset(UInt iregNo) 90 { 91 /* Do we care about endianness here? We do if sub-parts of integer 92 registers are accessed, but I don't think that ever happens on 93 MIPS. */ 94 UInt ret; 95 switch (iregNo) { 96 case 0: 97 ret = offsetof(VexGuestMIPS32State, guest_r0); break; 98 case 1: 99 ret = offsetof(VexGuestMIPS32State, guest_r1); break; 100 case 2: 101 ret = offsetof(VexGuestMIPS32State, guest_r2); break; 102 case 3: 103 ret = offsetof(VexGuestMIPS32State, guest_r3); break; 104 case 4: 105 ret = offsetof(VexGuestMIPS32State, guest_r4); break; 106 case 5: 107 ret = offsetof(VexGuestMIPS32State, guest_r5); break; 108 case 6: 109 ret = offsetof(VexGuestMIPS32State, guest_r6); break; 110 case 7: 111 ret = offsetof(VexGuestMIPS32State, guest_r7); break; 112 case 8: 113 ret = offsetof(VexGuestMIPS32State, guest_r8); break; 114 case 9: 115 ret = offsetof(VexGuestMIPS32State, guest_r9); break; 116 case 10: 117 ret = offsetof(VexGuestMIPS32State, guest_r10); break; 118 case 11: 119 ret = offsetof(VexGuestMIPS32State, guest_r11); break; 120 case 12: 121 ret = offsetof(VexGuestMIPS32State, guest_r12); break; 122 case 13: 123 ret = offsetof(VexGuestMIPS32State, guest_r13); break; 124 case 14: 125 ret = offsetof(VexGuestMIPS32State, guest_r14); break; 126 case 15: 127 ret = offsetof(VexGuestMIPS32State, guest_r15); break; 128 case 16: 129 ret = offsetof(VexGuestMIPS32State, guest_r16); break; 130 case 17: 131 ret = offsetof(VexGuestMIPS32State, guest_r17); break; 132 case 18: 133 ret = offsetof(VexGuestMIPS32State, guest_r18); break; 134 case 19: 135 ret = offsetof(VexGuestMIPS32State, guest_r19); break; 136 case 20: 137 ret = offsetof(VexGuestMIPS32State, guest_r20); break; 138 case 21: 139 ret = offsetof(VexGuestMIPS32State, guest_r21); break; 140 case 22: 141 ret = offsetof(VexGuestMIPS32State, guest_r22); break; 142 case 23: 143 ret = offsetof(VexGuestMIPS32State, guest_r23); break; 144 case 24: 145 ret = offsetof(VexGuestMIPS32State, guest_r24); break; 146 case 25: 147 ret = offsetof(VexGuestMIPS32State, guest_r25); break; 148 case 26: 149 ret = offsetof(VexGuestMIPS32State, guest_r26); break; 150 case 27: 151 ret = offsetof(VexGuestMIPS32State, guest_r27); break; 152 case 28: 153 ret = offsetof(VexGuestMIPS32State, guest_r28); break; 154 case 29: 155 ret = offsetof(VexGuestMIPS32State, guest_r29); break; 156 case 30: 157 ret = offsetof(VexGuestMIPS32State, guest_r30); break; 158 case 31: 159 ret = offsetof(VexGuestMIPS32State, guest_r31); break; 160 default: 161 vassert(0); 162 break; 163 } 164 return ret; 165 } 166 167 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC) 168 169 /* ---------------- Floating point registers ---------------- */ 170 171 static UInt floatGuestRegOffset(UInt fregNo) 172 { 173 vassert(fregNo < 32); 174 UInt ret; 175 switch (fregNo) { 176 case 0: 177 ret = offsetof(VexGuestMIPS32State, guest_f0); break; 178 case 1: 179 ret = offsetof(VexGuestMIPS32State, guest_f1); break; 180 case 2: 181 ret = offsetof(VexGuestMIPS32State, guest_f2); break; 182 case 3: 183 ret = offsetof(VexGuestMIPS32State, guest_f3); break; 184 case 4: 185 ret = offsetof(VexGuestMIPS32State, guest_f4); break; 186 case 5: 187 ret = offsetof(VexGuestMIPS32State, guest_f5); break; 188 case 6: 189 ret = offsetof(VexGuestMIPS32State, guest_f6); break; 190 case 7: 191 ret = offsetof(VexGuestMIPS32State, guest_f7); break; 192 case 8: 193 ret = offsetof(VexGuestMIPS32State, guest_f8); break; 194 case 9: 195 ret = offsetof(VexGuestMIPS32State, guest_f9); break; 196 case 10: 197 ret = offsetof(VexGuestMIPS32State, guest_f10); break; 198 case 11: 199 ret = offsetof(VexGuestMIPS32State, guest_f11); break; 200 case 12: 201 ret = offsetof(VexGuestMIPS32State, guest_f12); break; 202 case 13: 203 ret = offsetof(VexGuestMIPS32State, guest_f13); break; 204 case 14: 205 ret = offsetof(VexGuestMIPS32State, guest_f14); break; 206 case 15: 207 ret = offsetof(VexGuestMIPS32State, guest_f15); break; 208 case 16: 209 ret = offsetof(VexGuestMIPS32State, guest_f16); break; 210 case 17: 211 ret = offsetof(VexGuestMIPS32State, guest_f17); break; 212 case 18: 213 ret = offsetof(VexGuestMIPS32State, guest_f18); break; 214 case 19: 215 ret = offsetof(VexGuestMIPS32State, guest_f19); break; 216 case 20: 217 ret = offsetof(VexGuestMIPS32State, guest_f20); break; 218 case 21: 219 ret = offsetof(VexGuestMIPS32State, guest_f21); break; 220 case 22: 221 ret = offsetof(VexGuestMIPS32State, guest_f22); break; 222 case 23: 223 ret = offsetof(VexGuestMIPS32State, guest_f23); break; 224 case 24: 225 ret = offsetof(VexGuestMIPS32State, guest_f24); break; 226 case 25: 227 ret = offsetof(VexGuestMIPS32State, guest_f25); break; 228 case 26: 229 ret = offsetof(VexGuestMIPS32State, guest_f26); break; 230 case 27: 231 ret = offsetof(VexGuestMIPS32State, guest_f27); break; 232 case 28: 233 ret = offsetof(VexGuestMIPS32State, guest_f28); break; 234 case 29: 235 ret = offsetof(VexGuestMIPS32State, guest_f29); break; 236 case 30: 237 ret = offsetof(VexGuestMIPS32State, guest_f30); break; 238 case 31: 239 ret = offsetof(VexGuestMIPS32State, guest_f31); break; 240 default: 241 vassert(0); 242 break; 243 } 244 return ret; 245 } 246 247 /* Do a endian load of a 32-bit word, regardless of the 248 endianness of the underlying host. */ 249 static inline UInt getUInt(UChar * p) 250 { 251 UInt w = 0; 252 #if defined (_MIPSEL) 253 w = (w << 8) | p[3]; 254 w = (w << 8) | p[2]; 255 w = (w << 8) | p[1]; 256 w = (w << 8) | p[0]; 257 #elif defined (_MIPSEB) 258 w = (w << 8) | p[0]; 259 w = (w << 8) | p[1]; 260 w = (w << 8) | p[2]; 261 w = (w << 8) | p[3]; 262 #endif 263 return w; 264 } 265 266 #define BITS2(_b1,_b0) \ 267 (((_b1) << 1) | (_b0)) 268 269 #define BITS3(_b2,_b1,_b0) \ 270 (((_b2) << 2) | ((_b1) << 1) | (_b0)) 271 272 #define BITS4(_b3,_b2,_b1,_b0) \ 273 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0)) 274 275 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 276 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0))) 277 278 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \ 279 ((BITS2((_b5),(_b4)) << 4) \ 280 | BITS4((_b3),(_b2),(_b1),(_b0))) 281 282 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \ 283 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \ 284 | BITS4((_b3),(_b2),(_b1),(_b0))) 285 286 #define LOAD_STORE_PATTERN \ 287 t1 = newTemp(Ity_I32); \ 288 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); \ 289 290 #define LWX_SWX_PATTERN \ 291 t2 = newTemp(Ity_I32); \ 292 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \ 293 t4 = newTemp(Ity_I32); \ 294 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003))) 295 296 #define SXXV_PATTERN(op) \ 297 putIReg(rd, binop(op, \ 298 getIReg(rt), \ 299 unop(Iop_32to8, \ 300 binop(Iop_And32, \ 301 getIReg(rs), \ 302 mkU32(0x0000001F) \ 303 ) \ 304 ) \ 305 ) \ 306 ) 307 308 #define SXX_PATTERN(op) \ 309 putIReg(rd, binop(op, getIReg(rt), mkU8(sa))); 310 311 #define ALU_PATTERN(op) \ 312 putIReg(rd, binop(op, getIReg(rs), getIReg(rt))); 313 314 #define ALUI_PATTERN(op) \ 315 putIReg(rt, binop(op, getIReg(rs), mkU32(imm))); 316 317 #define ALUI_PATTERN64(op) \ 318 putIReg(rt, binop(op, getIReg(rs), mkU64(imm))); 319 320 #define FP_CONDITIONAL_CODE \ 321 t3 = newTemp(Ity_I32); \ 322 assign(t3, binop(Iop_And32, IRExpr_Mux0X( unop(Iop_1Uto8, \ 323 binop(Iop_CmpEQ32, mkU32(cc), mkU32(0))), \ 324 binop(Iop_Shr32, getFCSR(), mkU8(24+cc)), \ 325 binop(Iop_Shr32, getFCSR(), mkU8(23))), mkU32(0x1))); 326 327 /*------------------------------------------------------------*/ 328 /*--- Field helpers ---*/ 329 /*------------------------------------------------------------*/ 330 331 static UInt get_opcode(UInt mipsins) 332 { 333 return (0xFC000000 & mipsins) >> 26; 334 } 335 336 static UInt get_rs(UInt mipsins) 337 { 338 return (0x03E00000 & mipsins) >> 21; 339 } 340 341 static UInt get_rt(UInt mipsins) 342 { 343 return (0x001F0000 & mipsins) >> 16; 344 } 345 346 static UInt get_imm(UInt mipsins) 347 { 348 return (0x0000FFFF & mipsins); 349 } 350 351 static UInt get_instr_index(UInt mipsins) 352 { 353 return (0x03FFFFFF & mipsins); 354 } 355 356 static UInt get_rd(UInt mipsins) 357 { 358 return (0x0000F800 & mipsins) >> 11; 359 } 360 361 static UInt get_sa(UInt mipsins) 362 { 363 return (0x000007C0 & mipsins) >> 6; 364 } 365 366 static UInt get_function(UInt mipsins) 367 { 368 return (0x0000003F & mipsins); 369 } 370 371 static UInt get_ft(UInt mipsins) 372 { 373 return (0x001F0000 & mipsins) >> 16; 374 } 375 376 static UInt get_fs(UInt mipsins) 377 { 378 return (0x0000F800 & mipsins) >> 11; 379 } 380 381 static UInt get_fd(UInt mipsins) 382 { 383 return (0x000007C0 & mipsins) >> 6; 384 } 385 386 static UInt get_mov_cc(UInt mipsins) 387 { 388 return (0x001C0000 & mipsins) >> 18; 389 } 390 391 static UInt get_bc1_cc(UInt mipsins) 392 { 393 return (0x001C0000 & mipsins) >> 18; 394 } 395 396 static UInt get_fpc_cc(UInt mipsins) 397 { 398 return (0x00000700 & mipsins) >> 8; 399 } 400 401 static UInt get_tf(UInt mipsins) 402 { 403 return (0x00010000 & mipsins) >> 16; 404 } 405 406 static UInt get_nd(UInt mipsins) 407 { 408 return (0x00020000 & mipsins) >> 17; 409 } 410 411 static UInt get_fmt(UInt mipsins) 412 { 413 return (0x03E00000 & mipsins) >> 21; 414 } 415 416 static UInt get_FC(UInt mipsins) 417 { 418 return (0x000000F0 & mipsins) >> 4; 419 } 420 421 static UInt get_cond(UInt mipsins) 422 { 423 return (0x0000000F & mipsins); 424 } 425 426 /* for break & syscall */ 427 static UInt get_code(UInt mipsins) 428 { 429 return (0xFFC0 & mipsins) >> 6; 430 } 431 432 static UInt get_lsb(UInt mipsins) 433 { 434 return (0x7C0 & mipsins) >> 6; 435 } 436 437 static UInt get_msb(UInt mipsins) 438 { 439 return (0x0000F800 & mipsins) >> 11; 440 } 441 442 static UInt get_rot(UInt mipsins) 443 { 444 return (0x00200000 & mipsins) >> 21; 445 } 446 447 static UInt get_rotv(UInt mipsins) 448 { 449 return (0x00000040 & mipsins) >> 6; 450 } 451 452 static UInt get_sel(UInt mipsins) 453 { 454 return (0x00000007 & mipsins); 455 } 456 457 static Bool branch_or_jump(UChar * addr) 458 { 459 UInt fmt; 460 UInt cins = getUInt(addr); 461 462 UInt opcode = get_opcode(cins); 463 UInt rt = get_rt(cins); 464 UInt function = get_function(cins); 465 466 /* bgtz, blez, bne, beq, jal */ 467 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04 468 || opcode == 0x03 || opcode == 0x02) { 469 return True; 470 } 471 472 /* bgez */ 473 if (opcode == 0x01 && rt == 0x01) { 474 return True; 475 } 476 477 /* bgezal */ 478 if (opcode == 0x01 && rt == 0x11) { 479 return True; 480 } 481 482 /* bltzal */ 483 if (opcode == 0x01 && rt == 0x10) { 484 return True; 485 } 486 487 /* bltz */ 488 if (opcode == 0x01 && rt == 0x00) { 489 return True; 490 } 491 492 /* jalr */ 493 if (opcode == 0x00 && function == 0x09) { 494 return True; 495 } 496 497 /* jr */ 498 if (opcode == 0x00 && function == 0x08) { 499 return True; 500 } 501 502 if (opcode == 0x11) { 503 /*bc1f & bc1t */ 504 fmt = get_fmt(cins); 505 if (fmt == 0x08) { 506 return True; 507 } 508 } 509 510 return False; 511 } 512 513 static Bool is_Branch_or_Jump_and_Link(UChar * addr) 514 { 515 UInt cins = getUInt(addr); 516 517 UInt opcode = get_opcode(cins); 518 UInt rt = get_rt(cins); 519 UInt function = get_function(cins); 520 521 /* jal */ 522 if (opcode == 0x02) { 523 return True; 524 } 525 526 /* bgezal */ 527 if (opcode == 0x01 && rt == 0x11) { 528 return True; 529 } 530 531 /* bltzal */ 532 if (opcode == 0x01 && rt == 0x10) { 533 return True; 534 } 535 536 /* jalr */ 537 if (opcode == 0x00 && function == 0x09) { 538 return True; 539 } 540 541 return False; 542 } 543 544 static Bool branch_or_link_likely(UChar * addr) 545 { 546 UInt cins = getUInt(addr); 547 UInt opcode = get_opcode(cins); 548 UInt rt = get_rt(cins); 549 550 /* bgtzl, blezl, bnel, beql */ 551 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14) 552 return True; 553 554 /* bgezl */ 555 if (opcode == 0x01 && rt == 0x03) 556 return True; 557 558 /* bgezall */ 559 if (opcode == 0x01 && rt == 0x13) 560 return True; 561 562 /* bltzall */ 563 if (opcode == 0x01 && rt == 0x12) 564 return True; 565 566 /* bltzl */ 567 if (opcode == 0x01 && rt == 0x02) 568 return True; 569 570 return False; 571 } 572 573 /*------------------------------------------------------------*/ 574 /*--- Helper bits and pieces for creating IR fragments. ---*/ 575 /*------------------------------------------------------------*/ 576 577 static IRExpr *mkU8(UInt i) 578 { 579 vassert(i < 256); 580 return IRExpr_Const(IRConst_U8((UChar) i)); 581 } 582 583 /* Create an expression node for a 32-bit integer constant */ 584 static IRExpr *mkU32(UInt i) 585 { 586 return IRExpr_Const(IRConst_U32(i)); 587 } 588 589 /* Create an expression node for a 64-bit integer constant */ 590 static IRExpr *mkU64(ULong i) 591 { 592 return IRExpr_Const(IRConst_U64(i)); 593 } 594 595 static IRExpr *mkexpr(IRTemp tmp) 596 { 597 return IRExpr_RdTmp(tmp); 598 } 599 600 static IRExpr *unop(IROp op, IRExpr * a) 601 { 602 return IRExpr_Unop(op, a); 603 } 604 605 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2) 606 { 607 return IRExpr_Binop(op, a1, a2); 608 } 609 610 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3) 611 { 612 return IRExpr_Triop(op, a1, a2, a3); 613 } 614 615 static IRExpr *load(IRType ty, IRExpr * addr) 616 { 617 IRExpr *load1 = NULL; 618 #if defined (_MIPSEL) 619 load1 = IRExpr_Load(Iend_LE, ty, addr); 620 #elif defined (_MIPSEB) 621 load1 = IRExpr_Load(Iend_BE, ty, addr); 622 #endif 623 return load1; 624 } 625 626 /* Add a statement to the list held by "irsb". */ 627 static void stmt(IRStmt * st) 628 { 629 addStmtToIRSB(irsb, st); 630 } 631 632 static void assign(IRTemp dst, IRExpr * e) 633 { 634 stmt(IRStmt_WrTmp(dst, e)); 635 } 636 637 static void store(IRExpr * addr, IRExpr * data) 638 { 639 #if defined (_MIPSEL) 640 stmt(IRStmt_Store(Iend_LE, addr, data)); 641 #elif defined (_MIPSEB) 642 stmt(IRStmt_Store(Iend_BE, addr, data)); 643 #endif 644 } 645 646 /* Generate a new temporary of the given type. */ 647 static IRTemp newTemp(IRType ty) 648 { 649 vassert(isPlausibleIRType(ty)); 650 return newIRTemp(irsb->tyenv, ty); 651 } 652 653 /* Generate an expression for SRC rotated right by ROT. */ 654 static IRExpr *genROR32(IRExpr * src, Int rot) 655 { 656 vassert(rot >= 0 && rot < 32); 657 if (rot == 0) 658 return src; 659 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)), 660 binop(Iop_Shr32, src, mkU8(rot))); 661 } 662 663 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs) 664 { 665 IRTemp t0 = newTemp(Ity_I8); 666 IRTemp t1 = newTemp(Ity_I8); 667 668 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F)))); 669 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0))); 670 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)), 671 binop(Iop_Shr32, src, mkexpr(t0))); 672 } 673 674 static UInt extend_s_16to32(UInt x) 675 { 676 return (UInt) ((((Int) x) << 16) >> 16); 677 } 678 679 static UInt extend_s_18to32(UInt x) 680 { 681 return (UInt) ((((Int) x) << 14) >> 14); 682 } 683 684 static void jmp_lit( /*MOD*/DisResult* dres, 685 IRJumpKind kind, Addr32 d32 ) 686 { 687 vassert(dres->whatNext == Dis_Continue); 688 vassert(dres->len == 0); 689 vassert(dres->continueAt == 0); 690 vassert(dres->jk_StopHere == Ijk_INVALID); 691 dres->whatNext = Dis_StopHere; 692 dres->jk_StopHere = kind; 693 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) ); 694 } 695 696 /* Fetch a byte from the guest insn stream. */ 697 static UChar getIByte(Int delta) 698 { 699 return guest_code[delta]; 700 } 701 702 static IRExpr *getIReg(UInt iregNo) 703 { 704 if (0 == iregNo) { 705 return mode64 ? mkU64(0x0) : mkU32(0x0); 706 } else { 707 IRType ty = mode64 ? Ity_I64 : Ity_I32; 708 vassert(iregNo < 32); 709 return IRExpr_Get(integerGuestRegOffset(iregNo), ty); 710 } 711 } 712 713 static IRExpr *getHI(void) 714 { 715 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32); 716 } 717 718 static IRExpr *getLO(void) 719 { 720 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32); 721 } 722 723 static IRExpr *getFCSR(void) 724 { 725 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32); 726 } 727 728 static void putFCSR(IRExpr * e) 729 { 730 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e)); 731 } 732 733 static IRExpr *getULR(void) 734 { 735 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32); 736 } 737 738 static void putIReg(UInt archreg, IRExpr * e) 739 { 740 IRType ty = mode64 ? Ity_I64 : Ity_I32; 741 vassert(archreg < 32); 742 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 743 if (archreg != 0) 744 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e)); 745 } 746 747 static void putLO(IRExpr * e) 748 { 749 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e)); 750 } 751 752 static void putHI(IRExpr * e) 753 { 754 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e)); 755 } 756 757 static void putPC(IRExpr * e) 758 { 759 stmt(IRStmt_Put(OFFB_PC, e)); 760 } 761 762 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined) 763 { 764 vassert(ty == Ity_I32 || ty == Ity_I64); 765 if (ty == Ity_I32) 766 return src; 767 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 768 } 769 770 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some 771 of these combinations make sense. */ 772 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e) 773 { 774 IRType src_ty = typeOfIRExpr(irsb->tyenv, e); 775 if (src_ty == dst_ty) 776 return e; 777 if (src_ty == Ity_I32 && dst_ty == Ity_I16) 778 return unop(Iop_32to16, e); 779 if (src_ty == Ity_I32 && dst_ty == Ity_I8) 780 return unop(Iop_32to8, e); 781 if (src_ty == Ity_I64 && dst_ty == Ity_I8) { 782 vassert(mode64); 783 return unop(Iop_64to8, e); 784 } 785 if (src_ty == Ity_I64 && dst_ty == Ity_I16) { 786 vassert(mode64); 787 return unop(Iop_64to16, e); 788 } 789 790 if (vex_traceflags & VEX_TRACE_FE) { 791 vex_printf("\nsrc, dst tys are: "); 792 ppIRType(src_ty); 793 vex_printf(", "); 794 ppIRType(dst_ty); 795 vex_printf("\n"); 796 } 797 798 vpanic("narrowTo(mips)"); 799 return 0; 800 } 801 802 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src) 803 { 804 vassert(ty == Ity_I32 || ty == Ity_I64); 805 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 806 } 807 808 static IRExpr *getLoFromF64(IRType ty, IRExpr * src) 809 { 810 vassert(ty == Ity_F32 || ty == Ity_F64); 811 if (ty == Ity_F64) { 812 IRTemp t0, t1; 813 t0 = newTemp(Ity_I64); 814 t1 = newTemp(Ity_I32); 815 assign(t0, unop(Iop_ReinterpF64asI64, src)); 816 assign(t1, unop(Iop_64to32, mkexpr(t0))); 817 return unop(Iop_ReinterpI32asF32, mkexpr(t1)); 818 } else 819 return src; 820 } 821 822 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src) 823 { 824 vassert(ty == Ity_F32 || ty == Ity_F64); 825 return ty == Ity_F64 ? unop(Iop_F32toF64, src) : src; 826 } 827 828 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm) 829 { 830 ULong branch_offset; 831 IRTemp t0; 832 833 /* PC = PC + (SignExtend(signed_immed_24) << 2) 834 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 835 is added to the address of the instruction following 836 the branch (not the branch itself), in the branch delay slot, to form 837 a PC-relative effective target address. */ 838 branch_offset = extend_s_18to32(imm << 2); 839 840 t0 = newTemp(Ity_I1); 841 assign(t0, guard); 842 843 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 844 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC)); 845 846 irsb->jumpkind = Ijk_Boring; 847 848 return mkU32(guest_PC_curr_instr + 4 + branch_offset); 849 } 850 851 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set) 852 { 853 ULong branch_offset; 854 IRTemp t0; 855 856 if (link) { // LR (GPR31) = addr of the 2nd instr after branch instr 857 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 858 } 859 860 /* PC = PC + (SignExtend(signed_immed_24) << 2) 861 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 862 is added to the address of the instruction following 863 the branch (not the branch itself), in the branch delay slot, to form 864 a PC-relative effective target address. */ 865 866 branch_offset = extend_s_18to32(imm << 2); 867 868 t0 = newTemp(Ity_I1); 869 assign(t0, guard); 870 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 871 IRConst_U32(guest_PC_curr_instr + 4 + (UInt) branch_offset), 872 OFFB_PC); 873 } 874 875 static IRExpr *getFReg(UInt dregNo) 876 { 877 vassert(dregNo < 32); 878 IRType ty = mode64 ? Ity_F64 : Ity_F32; 879 return IRExpr_Get(floatGuestRegOffset(dregNo), ty); 880 } 881 882 static IRExpr *getDReg(UInt dregNo) 883 { 884 vassert(dregNo < 32); 885 IRTemp t0 = newTemp(Ity_F32); 886 IRTemp t1 = newTemp(Ity_F32); 887 IRTemp t2 = newTemp(Ity_F64); 888 IRTemp t3 = newTemp(Ity_I32); 889 IRTemp t4 = newTemp(Ity_I32); 890 IRTemp t5 = newTemp(Ity_I64); 891 892 assign(t0, getFReg(dregNo)); 893 assign(t1, getFReg(dregNo + 1)); 894 895 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); 896 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); 897 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3))); 898 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5))); 899 900 return mkexpr(t2); 901 } 902 903 static void putFReg(UInt dregNo, IRExpr * e) 904 { 905 vassert(dregNo < 32); 906 IRType ty = mode64 ? Ity_F64 : Ity_F32; 907 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 908 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 909 } 910 911 static void putDReg(UInt dregNo, IRExpr * e) 912 { 913 vassert(dregNo < 32); 914 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 915 IRTemp t1 = newTemp(Ity_F64); 916 IRTemp t4 = newTemp(Ity_I32); 917 IRTemp t5 = newTemp(Ity_I32); 918 IRTemp t6 = newTemp(Ity_I64); 919 assign(t1, e); 920 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1))); 921 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); // hi 922 assign(t5, unop(Iop_64to32, mkexpr(t6))); //lo 923 putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5))); 924 putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); 925 } 926 927 static void setFPUCondCode(IRExpr * e, UInt cc) 928 { 929 if (cc == 0) { 930 DIP("setFpu: %d\n", cc); 931 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF))); 932 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23)))); 933 } else { 934 DIP("setFpu1: %d\n", cc); 935 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32, 936 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc))))); 937 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc)))); 938 } 939 } 940 941 static IRExpr */* :: Ity_I32 */get_IR_roundingmode(void) 942 { 943 /* 944 rounding mode | MIPS | IR 945 ------------------------ 946 to nearest | 00 | 00 947 to zero | 01 | 11 948 to +infinity | 10 | 10 949 to -infinity | 11 | 01 950 */ 951 IRTemp rm_MIPS = newTemp(Ity_I32); 952 /* Last two bits in FCSR are rounding mode. */ 953 954 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State, 955 guest_FCSR), Ity_I32), mkU32(3))); 956 957 // rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) 958 959 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32, 960 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2))); 961 } 962 963 /*********************************************************/ 964 /*--- Floating Point Compare ---*/ 965 /*********************************************************/ 966 static Bool dis_instr_CCondFmt(UInt cins) 967 { 968 IRTemp t0, t1, t2, t3; 969 IRTemp ccIR = newTemp(Ity_I32); 970 IRTemp ccMIPS = newTemp(Ity_I32); 971 UInt FC = get_FC(cins); 972 UInt fmt = get_fmt(cins); 973 UInt fs = get_fs(cins); 974 UInt ft = get_ft(cins); 975 UInt cond = get_cond(cins); 976 977 if (FC == 0x3) { // C.cond.fmt 978 UInt fpc_cc = get_fpc_cc(cins); 979 switch (fmt) { 980 case 0x10: { //C.cond.S 981 DIP("C.cond.S %d f%d, f%d\n", fpc_cc, fs, ft); 982 t0 = newTemp(Ity_I32); 983 t1 = newTemp(Ity_I32); 984 t2 = newTemp(Ity_I32); 985 t3 = newTemp(Ity_I32); 986 987 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)), 988 unop(Iop_F32toF64, getFReg(ft)))); 989 /* Map compare result from IR to MIPS */ 990 /* 991 FP cmp result | MIPS | IR 992 -------------------------- 993 UN | 0x1 | 0x45 994 EQ | 0x2 | 0x40 995 GT | 0x4 | 0x00 996 LT | 0x8 | 0x01 997 */ 998 999 // ccMIPS = Shl(1, (~(ccIR>>5) & 2) 1000 // | ((ccIR ^ (ccIR>>6)) & 1) 1001 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1002 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1003 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)), 1004 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1005 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1006 mkU32(1)))))); 1007 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); // UN 1008 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1009 mkU8(0x1)), mkU32(0x1))); // EQ 1010 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1011 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); // NGT 1012 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1013 mkU8(0x3)), mkU32(0x1))); // LT 1014 1015 switch (cond) { 1016 case 0x0: 1017 setFPUCondCode(mkU32(0), fpc_cc); 1018 break; 1019 case 0x1: 1020 DIP("unorderd: %d\n", fpc_cc); 1021 setFPUCondCode(mkexpr(t0), fpc_cc); 1022 break; 1023 case 0x2: 1024 setFPUCondCode(mkexpr(t1), fpc_cc); 1025 break; 1026 case 0x3: 1027 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1028 fpc_cc); 1029 break; 1030 case 0x4: 1031 setFPUCondCode(mkexpr(t3), fpc_cc); 1032 break; 1033 case 0x5: 1034 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1035 fpc_cc); 1036 break; 1037 case 0x6: 1038 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1039 fpc_cc); 1040 break; 1041 case 0x7: 1042 setFPUCondCode(mkexpr(t2), fpc_cc); 1043 break; 1044 case 0x8: 1045 setFPUCondCode(mkU32(0), fpc_cc); 1046 break; 1047 case 0x9: 1048 setFPUCondCode(mkexpr(t0), fpc_cc); 1049 break; 1050 case 0xA: 1051 setFPUCondCode(mkexpr(t1), fpc_cc); 1052 break; 1053 case 0xB: 1054 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1055 fpc_cc); 1056 break; 1057 case 0xC: 1058 setFPUCondCode(mkexpr(t3), fpc_cc); 1059 break; 1060 case 0xD: 1061 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1062 fpc_cc); 1063 break; 1064 case 0xE: 1065 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1066 fpc_cc); 1067 break; 1068 case 0xF: 1069 setFPUCondCode(mkexpr(t2), fpc_cc); 1070 break; 1071 1072 default: 1073 return False; 1074 } 1075 } 1076 break; 1077 1078 case 0x11: //C.cond.D 1079 DIP("C.%d.D %d f%d, f%d\n", cond, fpc_cc, fs, ft); 1080 t0 = newTemp(Ity_I32); 1081 t1 = newTemp(Ity_I32); 1082 t2 = newTemp(Ity_I32); 1083 t3 = newTemp(Ity_I32); 1084 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); 1085 /* Map compare result from IR to MIPS */ 1086 /* 1087 FP cmp result | MIPS | IR 1088 -------------------------- 1089 UN | 0x1 | 0x45 1090 EQ | 0x2 | 0x40 1091 GT | 0x4 | 0x00 1092 LT | 0x8 | 0x01 1093 */ 1094 1095 // ccMIPS = Shl(1, (~(ccIR>>5) & 2) 1096 // | ((ccIR ^ (ccIR>>6)) & 1) 1097 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1098 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1099 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)), 1100 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1101 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1102 mkU32(1)))))); 1103 1104 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); // UN 1105 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1106 mkU8(0x1)), mkU32(0x1))); // EQ 1107 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1108 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); // NGT 1109 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1110 mkU8(0x3)), mkU32(0x1))); // LT 1111 1112 switch (cond) { 1113 case 0x0: 1114 setFPUCondCode(mkU32(0), fpc_cc); 1115 break; 1116 case 0x1: 1117 DIP("unorderd: %d\n", fpc_cc); 1118 setFPUCondCode(mkexpr(t0), fpc_cc); 1119 break; 1120 case 0x2: 1121 setFPUCondCode(mkexpr(t1), fpc_cc); 1122 break; 1123 case 0x3: 1124 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1125 fpc_cc); 1126 break; 1127 case 0x4: 1128 setFPUCondCode(mkexpr(t3), fpc_cc); 1129 break; 1130 case 0x5: 1131 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1132 fpc_cc); 1133 break; 1134 case 0x6: 1135 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1136 fpc_cc); 1137 break; 1138 case 0x7: 1139 setFPUCondCode(mkexpr(t2), fpc_cc); 1140 break; 1141 case 0x8: 1142 setFPUCondCode(mkU32(0), fpc_cc); 1143 break; 1144 case 0x9: 1145 setFPUCondCode(mkexpr(t0), fpc_cc); 1146 break; 1147 case 0xA: 1148 setFPUCondCode(mkexpr(t1), fpc_cc); 1149 break; 1150 case 0xB: 1151 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1152 fpc_cc); 1153 break; 1154 case 0xC: 1155 setFPUCondCode(mkexpr(t3), fpc_cc); 1156 break; 1157 case 0xD: 1158 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1159 fpc_cc); 1160 break; 1161 case 0xE: 1162 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1163 fpc_cc); 1164 break; 1165 case 0xF: 1166 setFPUCondCode(mkexpr(t2), fpc_cc); 1167 break; 1168 default: 1169 return False; 1170 } 1171 break; 1172 1173 default: 1174 return False; 1175 } 1176 } else { 1177 return False; 1178 } 1179 1180 return True; 1181 } 1182 1183 /*------------------------------------------------------------*/ 1184 /*--- Disassemble a single instruction ---*/ 1185 /*------------------------------------------------------------*/ 1186 1187 /* Disassemble a single instruction into IR. The instruction is 1188 located in host memory at guest_instr, and has guest IP of 1189 guest_PC_curr_instr, which will have been set before the call 1190 here. */ 1191 1192 static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, 1193 Addr64), 1194 Bool resteerCisOk, 1195 void* callback_opaque, 1196 Long delta64, 1197 VexArchInfo* archinfo, 1198 VexAbiInfo* abiinfo ) 1199 { 1200 IRTemp t0, t1, t2, t3, t4, t5, t6, t7, t8; 1201 UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function, 1202 trap_code, imm, instr_index, p, msb, lsb, size, rot, sel; 1203 1204 DisResult dres; 1205 1206 static IRExpr *lastn = NULL; /* last jump addr */ 1207 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */ 1208 1209 /* The running delta */ 1210 Int delta = (Int) delta64; 1211 1212 /* Holds eip at the start of the insn, so that we can print 1213 consistent error messages for unimplemented insns. */ 1214 Int delta_start = delta; 1215 1216 /* Are we in a delay slot ? */ 1217 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump; 1218 1219 /* Set result defaults. */ 1220 dres.whatNext = Dis_Continue; 1221 dres.len = 0; 1222 dres.continueAt = 0; 1223 dres.jk_StopHere = Ijk_INVALID; 1224 1225 delay_slot_branch = likely_delay_slot = delay_slot_jump = False; 1226 1227 UChar *code = (UChar *) (guest_code + delta); 1228 cins = getUInt(code); 1229 1230 if (delta != 0) { 1231 if (branch_or_jump(guest_code + delta - 4)) { 1232 if (lastn == NULL && bstmt == NULL) { 1233 DIP("Info: jump to delay slot insn...\n"); 1234 } else { 1235 dres.whatNext = Dis_StopHere; 1236 1237 DIP("lastn = %p bstmt = %p\n", lastn, bstmt); 1238 if (lastn != NULL) { 1239 DIP("delay slot jump\n"); 1240 if (vex_traceflags & VEX_TRACE_FE) 1241 ppIRExpr(lastn); 1242 delay_slot_jump = True; 1243 } else if (bstmt != NULL) { 1244 DIP("\ndelay slot branch\n"); 1245 delay_slot_branch = True; 1246 } 1247 DIP("delay slot\n"); 1248 } 1249 } 1250 1251 if (branch_or_link_likely(guest_code + delta - 4)) { 1252 likely_delay_slot = True; 1253 } 1254 } 1255 1256 /* Spot "Special" instructions (see comment at top of file). */ 1257 { 1258 /* Spot the 16-byte preamble: 1259 ****mips32**** 1260 "srl $0, $0, 13 1261 "srl $0, $0, 29 1262 "srl $0, $0, 3 1263 "srl $0, $0, 19 */ 1264 UInt word1 = 0x00000342; 1265 UInt word2 = 0x00000742; 1266 UInt word3 = 0x000000C2; 1267 UInt word4 = 0x000004C2; 1268 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 && 1269 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) { 1270 /* Got a "Special" instruction preamble. Which one is it? */ 1271 if (getUInt(code + 16) == 0x01ad6825 /* or t5, t5, t5 */ ) { 1272 /* v0 = client_request ( t9 ) */ 1273 DIP("v0 = client_request ( t9 )\n"); 1274 putPC(mkU32(guest_PC_curr_instr + 20)); 1275 dres.jk_StopHere = Ijk_ClientReq; 1276 dres.whatNext = Dis_StopHere; 1277 1278 goto decode_success; 1279 } else if (getUInt(code + 16) == 0x01ce7025 /* or t6,t6,t6 */ ) { 1280 /* t9 = guest_NRADDR */ 1281 DIP("t9 = guest_NRADDR\n"); 1282 dres.len = 20; 1283 delta += 20; 1284 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, guest_NRADDR), 1285 Ity_I32)); 1286 goto decode_success; 1287 } else if (getUInt(code + 16) == 0x01ef7825/* or t7,t7,t7 */ ) { 1288 /* branch-and-link-to-noredir t9 */ 1289 DIP("branch-and-link-to-noredir t9\n"); 1290 putIReg(31, mkU32(guest_PC_curr_instr + 20)); 1291 putPC(getIReg(25)); 1292 dres.jk_StopHere = Ijk_NoRedir; 1293 dres.whatNext = Dis_StopHere; 1294 goto decode_success; 1295 } 1296 1297 /* We don't know what it is. Set opc1/opc2 so decode_failure 1298 can print the insn following the Special-insn preamble. */ 1299 delta += 16; 1300 goto decode_failure; 1301 /*NOTREACHED*/} 1302 } 1303 1304 opcode = get_opcode(cins); 1305 imm = get_imm(cins); 1306 rs = get_rs(cins); 1307 rt = get_rt(cins); 1308 rd = get_rd(cins); 1309 sa = get_sa(cins); 1310 fs = get_fs(cins); 1311 fd = get_fd(cins); 1312 ft = get_ft(cins); 1313 tf = get_tf(cins); 1314 nd = get_nd(cins); 1315 sel = get_sel(cins); 1316 fmt = get_fmt(cins); 1317 instr_index = get_instr_index(cins); 1318 trap_code = get_code(cins); 1319 function = get_function(cins); 1320 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1321 IRType tyF = mode64 ? Ity_F64 : Ity_F32; 1322 1323 DIP("[cins = 0x%08x] ", cins); 1324 1325 switch (opcode) { 1326 1327 case 0x03: /* JAL */ 1328 DIP("jal 0x%x", instr_index); 1329 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 1330 t0 = newTemp(ty); 1331 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 1332 (instr_index << 2))); 1333 lastn = mkexpr(t0); 1334 break; 1335 case 0x02: /* J */ 1336 DIP("j 0x%x", instr_index); 1337 t0 = newTemp(ty); 1338 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 1339 (instr_index << 2))); 1340 lastn = mkexpr(t0); 1341 break; 1342 1343 case 0x11: /* COP1 */ 1344 { 1345 UInt bc1_cc = get_bc1_cc(cins); 1346 if (0x08 == fmt) { 1347 switch (fmt) { 1348 case 0x08: //BC 1349 { 1350 DIP("tf: %d, nd: %d\n", tf, nd); 1351 //FcConditionalCode(bc1_cc) 1352 t1 = newTemp(Ity_I32); 1353 t2 = newTemp(Ity_I32); 1354 t3 = newTemp(Ity_I1); 1355 1356 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1357 mkU32(bc1_cc)))); 1358 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 1359 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1360 mkU8(24 + bc1_cc)), mkU32(0x1)), binop(Iop_And32, 1361 binop(Iop_Shr32, getFCSR(), mkU8(23)), 1362 mkU32(0x1)))); 1363 1364 if (tf == 1 && nd == 0) { 1365 //branch on true 1366 DIP("bc1t %d, %d", bc1_cc, imm); 1367 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 1368 dis_branch(False, mkexpr(t3), imm, &bstmt); 1369 break; 1370 } else if (tf == 0 && nd == 0) { 1371 //branch on false 1372 DIP("bc1f %d, %d", bc1_cc, imm); 1373 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 1374 dis_branch(False, mkexpr(t3), imm, &bstmt); 1375 break; 1376 } else if (nd == 1 && tf == 0) { 1377 DIP("bc1fl %d, %d", bc1_cc, imm); 1378 lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2), 1379 mode64 ? mkU64(0x0) : mkU32(0x0)), imm); 1380 break; 1381 } else if (nd == 1 && tf == 1) { 1382 DIP("bc1tl %d, %d", bc1_cc, imm); 1383 lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2), 1384 mkU32(0x0)), imm); 1385 break; 1386 } else 1387 goto decode_failure; 1388 } 1389 1390 default: 1391 goto decode_failure; 1392 } 1393 } else { 1394 switch (function) { 1395 1396 case 0x4: //SQRT.fmt 1397 { 1398 switch (fmt) { 1399 case 0x10: //S 1400 { 1401 IRExpr *rm = get_IR_roundingmode(); 1402 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm, 1403 getLoFromF64(tyF, getFReg(fs))))); 1404 } 1405 break; 1406 case 0x11: //D 1407 { 1408 IRExpr *rm = get_IR_roundingmode(); 1409 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs))); 1410 } 1411 break; 1412 } 1413 } 1414 break; 1415 case 0x5: //abs.fmt 1416 switch (fmt) { 1417 case 0x10: //S 1418 DIP("abs.s f%d, f%d\n", fd, fs); 1419 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32, 1420 getLoFromF64(tyF, getFReg(fs))))); 1421 break; 1422 case 0x11: //D 1423 DIP("abs.d f%d, f%d\n", fd, fs); 1424 putDReg(fd, unop(Iop_AbsF64, getDReg(fs))); 1425 break; 1426 default: 1427 goto decode_failure; 1428 } 1429 break; //case 0x5 1430 1431 case 0x02: // MUL.fmt 1432 switch (fmt) { 1433 case 0x11: // D 1434 { 1435 DIP("mul.d f%d, f%d, f%d", fd, fs, ft); 1436 IRExpr *rm = get_IR_roundingmode(); 1437 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs), 1438 getDReg(ft))); 1439 break; 1440 } 1441 case 0x10: // S 1442 { 1443 DIP("mul.s f%d, f%d, f%d", fd, fs, ft); 1444 IRExpr *rm = get_IR_roundingmode(); 1445 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm, 1446 getLoFromF64(tyF, getFReg(fs)), 1447 getLoFromF64(tyF, getFReg(ft))))); 1448 break; 1449 } 1450 default: 1451 goto decode_failure; 1452 } 1453 break; // MUL.fmt 1454 1455 case 0x03: // DIV.fmt 1456 switch (fmt) { 1457 case 0x11: // D 1458 { 1459 DIP("div.d f%d, f%d, f%d", fd, fs, ft); 1460 IRExpr *rm = get_IR_roundingmode(); 1461 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs), 1462 getDReg(ft))); 1463 break; 1464 } 1465 case 0x10: // S 1466 { 1467 DIP("div.s f%d, f%d, f%d", fd, fs, ft); 1468 IRExpr *rm = get_IR_roundingmode(); 1469 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 1470 getLoFromF64(tyF, getFReg(fs)), 1471 getLoFromF64(tyF, getFReg(ft))))); 1472 break; 1473 } 1474 default: 1475 goto decode_failure; 1476 } 1477 break; // DIV.fmt 1478 1479 case 0x01: // SUB.fmt 1480 switch (fmt) { 1481 case 0x11: // D 1482 { 1483 DIP("sub.d f%d, f%d, f%d", fd, fs, ft); 1484 IRExpr *rm = get_IR_roundingmode(); 1485 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), getDReg(ft))); 1486 break; 1487 } 1488 case 0x10: // S 1489 { 1490 DIP("sub.s f%d, f%d, f%d", fd, fs, ft); 1491 IRExpr *rm = get_IR_roundingmode(); 1492 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm, 1493 getLoFromF64(tyF, getFReg(fs)), 1494 getLoFromF64(tyF, getFReg(ft))))); 1495 break; 1496 } 1497 default: 1498 goto decode_failure; 1499 } 1500 break; // SUB.fmt 1501 1502 case 0x06: // MOV.fmt 1503 switch (fmt) { 1504 case 0x11: // D 1505 /* TODO: Check this for 64 bit FPU registers. */ 1506 DIP("mov.d f%d, f%d", fd, fs); 1507 putFReg(fd, getFReg(fs)); 1508 putFReg(fd + 1, getFReg(fs + 1)); 1509 break; 1510 case 0x10: // S 1511 DIP("mov.s f%d, f%d", fd, fs); 1512 putFReg(fd, getFReg(fs)); 1513 break; 1514 default: 1515 goto decode_failure; 1516 } 1517 break; // MOV.fmt 1518 1519 case 0x7: //neg.fmt 1520 switch (fmt) { 1521 case 0x10: //S 1522 DIP("neg.s f%d, f%d", fd, fs); 1523 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, 1524 getLoFromF64(tyF, getFReg(fs))))); 1525 break; 1526 case 0x11: //D 1527 DIP("neg.d f%d, f%d", fd, fs); 1528 putDReg(fd, unop(Iop_NegF64, getDReg(fs))); 1529 break; 1530 default: 1531 goto decode_failure; 1532 } 1533 break; //case 0x7 1534 1535 case 0x15: //RECIP.fmt 1536 switch (fmt) { 1537 case 0x10: 1538 { //S 1539 DIP("recip.s f%d, f%d\n", fd, fs); 1540 IRExpr *rm = get_IR_roundingmode(); 1541 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, 1542 rm, unop(Iop_ReinterpI32asF32, 1543 mkU32(0x3F800000)), getLoFromF64(tyF, 1544 getFReg(fs))))); 1545 break; 1546 } 1547 case 0x11: 1548 { //D 1549 DIP("recip.d f%d, f%d\n", fd, fs); 1550 IRExpr *rm = get_IR_roundingmode(); 1551 putDReg(fd, triop(Iop_DivF64, rm, 1552 unop(Iop_ReinterpI64asF64, 1553 mkU64(0x3FF0000000000000ULL)), getDReg(fs))); 1554 break; 1555 } 1556 default: 1557 goto decode_failure; 1558 1559 } 1560 break; //case 0x15 1561 1562 case 0x13: //MOVN.fmt 1563 switch (fmt) { 1564 case 0x10: // S 1565 DIP("movn.s f%d, f%d, r%d", fd, fs, rt); 1566 1567 t1 = newTemp(Ity_F64); 1568 t2 = newTemp(Ity_F64); 1569 t3 = newTemp(Ity_I32); 1570 t4 = newTemp(Ity_F64); 1571 1572 assign(t1, unop(Iop_F32toF64, getFReg(fs))); 1573 assign(t2, unop(Iop_F32toF64, getFReg(fd))); 1574 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0), 1575 getIReg(rt)))); 1576 1577 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1578 mkexpr(t2), mkexpr(t1))); 1579 1580 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 1581 mkexpr(t4))); 1582 break; 1583 case 0x11: // D 1584 DIP("movn.d f%d, f%d, r%d", fd, fs, rt); 1585 1586 t3 = newTemp(Ity_I32); 1587 t4 = newTemp(Ity_F64); 1588 1589 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpNE32, mkU32(0), 1590 getIReg(rt)))); 1591 putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1592 getDReg(fd), getDReg(fs))); 1593 break; 1594 default: 1595 goto decode_failure; 1596 } 1597 break; // MOVN.fmt 1598 1599 case 0x12: //MOVZ.fmt 1600 switch (fmt) { 1601 case 0x10: // S 1602 DIP("movz.s f%d, f%d, r%d", fd, fs, rt); 1603 1604 t1 = newTemp(Ity_F64); 1605 t2 = newTemp(Ity_F64); 1606 t3 = newTemp(Ity_I32); 1607 t4 = newTemp(Ity_F64); 1608 1609 assign(t1, unop(Iop_F32toF64, getFReg(fs))); 1610 assign(t2, unop(Iop_F32toF64, getFReg(fd))); 1611 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1612 getIReg(rt)))); 1613 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1614 mkexpr(t2), mkexpr(t1))); 1615 1616 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 1617 mkexpr(t4))); 1618 1619 break; 1620 case 0x11: // D 1621 DIP("movz.d f%d, f%d, r%d", fd, fs, rt); 1622 1623 t3 = newTemp(Ity_I32); 1624 t4 = newTemp(Ity_F64); 1625 1626 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1627 getIReg(rt)))); 1628 putDReg(fd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1629 getDReg(fd), getDReg(fs))); 1630 break; 1631 default: 1632 goto decode_failure; 1633 } 1634 break; // MOVZ.fmt 1635 1636 case 0x11: // MOVT.fmt 1637 if (tf == 1) { 1638 UInt mov_cc = get_mov_cc(cins); 1639 switch (fmt) // MOVCF = 010001 1640 { 1641 case 0x11: // D 1642 DIP("movt.d f%d, f%d, %d", fd, fs, mov_cc); 1643 t1 = newTemp(Ity_I32); 1644 t2 = newTemp(Ity_I32); 1645 t3 = newTemp(Ity_I32); 1646 t4 = newTemp(Ity_F64); 1647 1648 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1649 mkU32(mov_cc)))); 1650 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 1651 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1652 mkU8(24 + mov_cc)), mkU32(0x1)), 1653 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1654 mkU8(23)), mkU32(0x1)))); 1655 1656 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1), 1657 mkexpr(t2)))); 1658 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1659 getDReg(fs), getDReg(fd))); 1660 putDReg(fd, mkexpr(t4)); 1661 break; 1662 case 0x10: // S 1663 DIP("movt.s f%d, f%d, %d", fd, fs, mov_cc); 1664 t1 = newTemp(Ity_I32); 1665 t2 = newTemp(Ity_I32); 1666 t3 = newTemp(Ity_I32); 1667 t4 = newTemp(Ity_F64); 1668 t5 = newTemp(Ity_F64); 1669 t6 = newTemp(Ity_F64); 1670 t7 = newTemp(Ity_I64); 1671 1672 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 1673 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 1674 1675 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1676 mkU32(mov_cc)))); 1677 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 1678 binop(Iop_And32, binop(Iop_Shr32, 1679 getFCSR(), mkU8(24 + mov_cc)), 1680 mkU32(0x1)), binop(Iop_And32, 1681 binop(Iop_Shr32, getFCSR(), 1682 mkU8(23)), mkU32(0x1)))); 1683 1684 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1), 1685 mkexpr(t2)))); 1686 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1687 mkexpr(t5), mkexpr(t6))); 1688 1689 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 1690 mkexpr(t4))); 1691 break; 1692 default: 1693 goto decode_failure; 1694 } 1695 } else if (tf == 0) //movf.fmt 1696 { 1697 UInt mov_cc = get_mov_cc(cins); 1698 switch (fmt) // MOVCF = 010001 1699 { 1700 case 0x11: // D 1701 DIP("movf.d f%d, f%d, %d", fd, fs, mov_cc); 1702 t1 = newTemp(Ity_I32); 1703 t2 = newTemp(Ity_I32); 1704 t3 = newTemp(Ity_I32); 1705 t4 = newTemp(Ity_F64); 1706 1707 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, 1708 mkU32(0), mkU32(mov_cc)))); 1709 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 1710 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1711 mkU8(24 + mov_cc)), mkU32(0x1)), 1712 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1713 mkU8(23)), mkU32(0x1)))); 1714 1715 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1), 1716 mkexpr(t2)))); 1717 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1718 getDReg(fd), getDReg(fs))); 1719 putDReg(fd, mkexpr(t4)); 1720 break; 1721 case 0x10: // S 1722 DIP("movf.s f%d, f%d, %d", fd, fs, mov_cc); 1723 { 1724 t1 = newTemp(Ity_I32); 1725 t2 = newTemp(Ity_I32); 1726 t3 = newTemp(Ity_I32); 1727 t4 = newTemp(Ity_F64); 1728 t5 = newTemp(Ity_F64); 1729 t6 = newTemp(Ity_F64); 1730 1731 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 1732 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 1733 1734 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 1735 mkU32(mov_cc)))); 1736 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 1737 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1738 mkU8(24 + mov_cc)), mkU32(0x1)), 1739 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 1740 mkU8(23)), mkU32(0x1)))); 1741 1742 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1), 1743 mkexpr(t2)))); 1744 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 1745 mkexpr(t6), mkexpr(t5))); 1746 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 1747 mkexpr(t4))); 1748 } 1749 break; 1750 default: 1751 goto decode_failure; 1752 } 1753 } 1754 1755 break; // MOVT.fmt 1756 1757 case 0x0: //add.fmt 1758 switch (fmt) { 1759 case 0x10: //S 1760 { 1761 DIP("add.s f%d, f%d, f%d\n", fd, fs, ft); 1762 IRExpr *rm = get_IR_roundingmode(); 1763 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, 1764 getLoFromF64(tyF, getFReg(fs)), 1765 getLoFromF64(tyF, getFReg(ft))))); 1766 break; 1767 } 1768 case 0x11: //D 1769 { 1770 DIP("add.d f%d, f%d, f%d\n", fd, fs, ft); 1771 IRExpr *rm = get_IR_roundingmode(); 1772 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), 1773 getDReg(ft))); 1774 break; 1775 } 1776 1777 case 0x4: //MTC1 (Move Word to Floating Point) 1778 DIP("mtc1 r%d, f%d", rt, fs); 1779 putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt))); 1780 break; 1781 1782 case 0x0: //MFC1 1783 DIP("mfc1 r%d, f%d", rt, fs); 1784 putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs))); 1785 break; 1786 1787 case 0x6: //CTC1 1788 DIP("ctc1 r%d, f%d", rt, fs); 1789 t0 = newTemp(Ity_I32); 1790 t1 = newTemp(Ity_I32); 1791 t2 = newTemp(Ity_I32); 1792 t3 = newTemp(Ity_I32); 1793 t4 = newTemp(Ity_I32); 1794 t5 = newTemp(Ity_I32); 1795 t6 = newTemp(Ity_I32); 1796 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 1797 if (fs == 25) { //FCCR 1798 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 1799 mkU32(0x000000FE)), mkU8(24))); 1800 assign(t2, binop(Iop_And32, mkexpr(t0), 1801 mkU32(0x01000000))); 1802 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 1803 mkU32(0x00000001)), mkU8(23))); 1804 assign(t4, binop(Iop_And32, mkexpr(t0), 1805 mkU32(0x007FFFFF))); 1806 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1), 1807 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3), 1808 mkexpr(t4)))); 1809 } else if (fs == 26) { //FEXR 1810 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000))); 1811 assign(t2, binop(Iop_And32, mkexpr(t0), 1812 mkU32(0x0003F000))); 1813 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80))); 1814 assign(t4, binop(Iop_And32, mkexpr(t0), 1815 mkU32(0x0000007C))); 1816 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003))); 1817 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 1818 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 1819 mkexpr(t3), mkexpr(t4))), mkexpr(t5))); 1820 } else if (fs == 28) { 1821 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000))); 1822 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 1823 mkU32(0x00000002)), mkU8(22))); 1824 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000))); 1825 assign(t4, binop(Iop_And32, mkexpr(t0), 1826 mkU32(0x00000F80))); 1827 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C))); 1828 assign(t6, binop(Iop_And32, mkexpr(t0), 1829 mkU32(0x00000003))); 1830 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 1831 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 1832 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32, 1833 mkexpr(t5), mkexpr(t6)))); 1834 } else if (fs == 31) { 1835 putFCSR(mkexpr(t0)); 1836 } 1837 break; 1838 case 0x2: //CFC1 1839 DIP("cfc1 r%d, f%d", rt, fs); 1840 t0 = newTemp(Ity_I32); 1841 t1 = newTemp(Ity_I32); 1842 t2 = newTemp(Ity_I32); 1843 t3 = newTemp(Ity_I32); 1844 t4 = newTemp(Ity_I32); 1845 t5 = newTemp(Ity_I32); 1846 t6 = newTemp(Ity_I32); 1847 assign(t0, getFCSR()); 1848 if (fs == 0) { 1849 putIReg(rt, mkWidenFrom32(ty, 1850 IRExpr_Get(offsetof(VexGuestMIPS32State, 1851 guest_FIR), 1852 Ity_I32), 1853 False)); 1854 } else if (fs == 25) { 1855 assign(t1, mkU32(0x000000FF)); 1856 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 1857 mkU32(0xFE000000)), mkU8(25))); 1858 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 1859 mkU32(0x00800000)), mkU8(23))); 1860 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 1861 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 1862 mkexpr(t3)), False)); 1863 } else if (fs == 26) { 1864 assign(t1, mkU32(0xFFFFF07C)); 1865 assign(t2, binop(Iop_And32, mkexpr(t0), 1866 mkU32(0x0003F000))); 1867 assign(t3, binop(Iop_And32, mkexpr(t0), 1868 mkU32(0x0000007C))); 1869 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 1870 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 1871 mkexpr(t3)), False)); 1872 } else if (fs == 28) { 1873 assign(t1, mkU32(0x00000F87)); 1874 assign(t2, binop(Iop_And32, mkexpr(t0), 1875 mkU32(0x00000F83))); 1876 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 1877 mkU32(0x01000000)), mkU8(22))); 1878 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 1879 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 1880 mkexpr(t3)), False)); 1881 } else if (fs == 31) { 1882 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False)); 1883 } 1884 break; 1885 default: 1886 goto decode_failure; 1887 } 1888 break; //case 0x0: //add.fmt 1889 1890 case 0x21: //CVT.D 1891 switch (fmt) { 1892 case 0x10: //S 1893 DIP("cvt.d.s f%d, f%d", fd, fs); 1894 putDReg(fd, unop(Iop_F32toF64, getFReg(fs))); 1895 break; 1896 1897 case 0x14: 1898 { //W 1899 DIP("cvt.d.w %d, %d\n", fd, fs); 1900 t0 = newTemp(Ity_I32); 1901 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 1902 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0))); 1903 } 1904 break; 1905 1906 default: 1907 goto decode_failure; 1908 } 1909 break; //CVT.D 1910 1911 case 0x20: //cvt.s 1912 switch (fmt) { 1913 case 0x14: //W 1914 DIP("cvt.s.w %d, %d\n", fd, fs); 1915 t0 = newTemp(Ity_I32); 1916 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 1917 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(), 1918 mkexpr(t0))); 1919 break; 1920 1921 case 0x11: //D 1922 DIP("cvt.s.d %d, %d\n", fd, fs); 1923 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 1924 getDReg(fs))); 1925 break; 1926 1927 default: 1928 goto decode_failure; 1929 } 1930 break; //cvt.s 1931 1932 case 0x24: //cvt.w 1933 switch (fmt) { 1934 case 0x10: //S 1935 DIP("cvt.w.s %d, %d\n", fd, fs); 1936 putFReg(fd, binop(Iop_RoundF32toInt, get_IR_roundingmode(), 1937 getFReg(fs))); 1938 break; 1939 1940 case 0x11: 1941 { //D 1942 DIP("cvt.w.d %d, %d\n", fd, fs); 1943 t0 = newTemp(Ity_I32); 1944 1945 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(), 1946 getDReg(fs))); 1947 1948 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 1949 } 1950 break; 1951 1952 default: 1953 goto decode_failure; 1954 1955 } 1956 break; 1957 1958 case 0x09: //TRUNC.L 1959 switch (fmt) { 1960 case 0x10: //S 1961 DIP("trunc.l.s %d, %d\n", fd, fs); 1962 goto decode_failure; 1963 1964 case 0x11: //D 1965 DIP("trunc.l.d %d, %d\n", fd, fs); 1966 goto decode_failure; 1967 1968 default: 1969 goto decode_failure; 1970 1971 } 1972 break; //trunc.l 1973 1974 case 0x0C: //ROUND.W.fmt 1975 switch (fmt) { 1976 case 0x10: //S 1977 DIP("round.w.s f%d, f%d\n", fd, fs); 1978 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0), 1979 getFReg(fs))); 1980 break; 1981 1982 case 0x11: //D 1983 DIP("round.w.d f%d, f%d\n", fd, fs); 1984 t0 = newTemp(Ity_I32); 1985 1986 assign(t0, binop(Iop_F64toI32S, mkU32(0x0), getDReg(fs))); 1987 1988 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 1989 break; 1990 1991 default: 1992 goto decode_failure; 1993 1994 } 1995 break; //ROUND.W.fmt 1996 1997 case 0x0F: //FLOOR.W.fmt 1998 switch (fmt) { 1999 case 0x10: //S 2000 DIP("floor.w.s f%d, f%d\n", fd, fs); 2001 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1), 2002 getFReg(fs))); 2003 break; 2004 2005 case 0x11: //D 2006 DIP("floor.w.d f%d, f%d\n", fd, fs); 2007 t0 = newTemp(Ity_I32); 2008 2009 assign(t0, binop(Iop_F64toI32S, mkU32(0x1), getDReg(fs))); 2010 2011 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 2012 break; 2013 2014 default: 2015 goto decode_failure; 2016 2017 } 2018 break; //FLOOR.W.fmt 2019 2020 case 0x0D: //TRUNC.W 2021 switch (fmt) { 2022 case 0x10: //S 2023 DIP("trunc.w.s %d, %d\n", fd, fs); 2024 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3), 2025 getFReg(fs))); 2026 break; 2027 2028 case 0x11: //D 2029 DIP("trunc.w.d %d, %d\n", fd, fs); 2030 t0 = newTemp(Ity_I32); 2031 2032 assign(t0, binop(Iop_F64toI32S, mkU32(0x3), getDReg(fs))); 2033 2034 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 2035 break; 2036 2037 default: 2038 goto decode_failure; 2039 2040 } 2041 break; 2042 case 0x0E: //CEIL.W.fmt 2043 switch (fmt) { 2044 case 0x10: //S 2045 DIP("ceil.w.s %d, %d\n", fd, fs); 2046 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2), 2047 getFReg(fs))); 2048 break; 2049 2050 case 0x11: //D 2051 DIP("ceil.w.d %d, %d\n", fd, fs); 2052 t0 = newTemp(Ity_I32); 2053 2054 assign(t0, binop(Iop_F64toI32S, mkU32(0x2), getDReg(fs))); 2055 2056 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 2057 break; 2058 2059 default: 2060 goto decode_failure; 2061 2062 } 2063 break; 2064 case 0x0A: //CEIL.L.fmt 2065 switch (fmt) { 2066 case 0x10: //S 2067 DIP("ceil.l.s %d, %d\n", fd, fs); 2068 goto decode_failure; 2069 2070 case 0x11: //D 2071 DIP("ceil.l.d %d, %d\n", fd, fs); 2072 2073 goto decode_failure; 2074 2075 default: 2076 goto decode_failure; 2077 2078 } 2079 break; 2080 2081 case 0x16: //RSQRT.fmt 2082 switch (fmt) { 2083 case 0x10: 2084 { //S 2085 DIP("rsqrt.s %d, %d\n", fd, fs); 2086 IRExpr *rm = get_IR_roundingmode(); 2087 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 2088 unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)), 2089 binop(Iop_SqrtF32, rm, getLoFromF64(tyF, 2090 getFReg(fs)))))); 2091 break; 2092 } 2093 case 0x11: 2094 { //D 2095 DIP("rsqrt.d %d, %d\n", fd, fs); 2096 IRExpr *rm = get_IR_roundingmode(); 2097 putDReg(fd, triop(Iop_DivF64, rm, 2098 unop(Iop_ReinterpI64asF64, 2099 mkU64(0x3FF0000000000000ULL)), 2100 binop(Iop_SqrtF64, rm, getDReg(fs)))); 2101 break; 2102 } 2103 default: 2104 goto decode_failure; 2105 2106 } 2107 break; 2108 2109 default: 2110 if (dis_instr_CCondFmt(cins)) 2111 break; 2112 goto decode_failure; 2113 2114 } 2115 2116 } 2117 } 2118 break; /*COP1 */ 2119 case 0x10: /* COP0 */ 2120 if (rs == 0) { /* MFC0 */ 2121 DIP("mfc0 r%d, r%d, %d", rt, rd, sel); 2122 2123 IRTemp val = newTemp(Ity_I32); 2124 IRExpr** args = mkIRExprVec_2 (mkU32(rd), mkU32(sel)); 2125 IRDirty *d = unsafeIRDirty_1_N(val, 2126 0, 2127 "mips32_dirtyhelper_mfc0", 2128 &mips32_dirtyhelper_mfc0, 2129 args); 2130 2131 stmt(IRStmt_Dirty(d)); 2132 putIReg(rt, mkexpr(val)); 2133 } else 2134 goto decode_failure; 2135 break; 2136 case 0x31: /* LWC1 */ 2137 /* Load Word to Floating Point - LWC1 (MIPS32) */ 2138 LOAD_STORE_PATTERN; 2139 putFReg(ft, load(Ity_F32, mkexpr(t1))); 2140 2141 DIP("lwc1 f%d, %d(r%d)", ft, imm, rs); 2142 break; 2143 2144 case 0x39: /* SWC1 */ 2145 LOAD_STORE_PATTERN; 2146 store(mkexpr(t1), getFReg(ft)); 2147 DIP("swc1 f%d, %d(r%d)", ft, imm, rs); 2148 break; 2149 2150 case 0x33: /* PREF */ 2151 DIP("pref"); 2152 break; 2153 2154 case 0x35: 2155 /* Load Doubleword to Floating Point - LDC1 (MIPS32) */ 2156 LOAD_STORE_PATTERN; 2157 2158 t2 = newTemp(Ity_I32); 2159 assign(t2, binop(Iop_Add32, getIReg(rs), 2160 mkU32(extend_s_16to32(imm + 4)))); 2161 2162 #if defined (_MIPSEL) 2163 putFReg(ft, load(Ity_F32, mkexpr(t1))); 2164 putFReg(ft + 1, load(Ity_F32, mkexpr(t2))); 2165 #elif defined (_MIPSEB) 2166 putFReg(ft + 1, load(Ity_F32, mkexpr(t1))); 2167 putFReg(ft, load(Ity_F32, mkexpr(t2))); 2168 #endif 2169 DIP("ldc1 f%d, %d(%d) \n", rt, imm, rs); 2170 break; 2171 2172 case 0x3D: 2173 /* Store Doubleword from Floating Point - SDC1 */ 2174 LOAD_STORE_PATTERN; 2175 2176 t2 = newTemp(Ity_I32); 2177 assign(t2, binop(Iop_Add32, getIReg(rs), 2178 mkU32(extend_s_16to32(imm + 4)))); 2179 2180 #if defined (_MIPSEL) 2181 store(mkexpr(t1), getFReg(ft)); 2182 store(mkexpr(t2), getFReg(ft + 1)); 2183 #elif defined (_MIPSEB) 2184 store(mkexpr(t1), getFReg(ft + 1)); 2185 store(mkexpr(t2), getFReg(ft)); 2186 #endif 2187 DIP("sdc1 f%d, %d(%d)", ft, imm, rs); 2188 break; 2189 2190 case 0x23: /* LW */ 2191 DIP("lw r%d, %d(r%d)", rt, imm, rs); 2192 LOAD_STORE_PATTERN; 2193 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True)); 2194 break; 2195 2196 case 0x20: /* LB */ 2197 DIP("lb r%d, %d(r%d)", rt, imm, rs); 2198 LOAD_STORE_PATTERN; 2199 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 2200 break; 2201 2202 case 0x24: /* LBU */ 2203 DIP("lbu r%d, %d(r%d)", rt, imm, rs); 2204 LOAD_STORE_PATTERN; 2205 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1)))); 2206 break; 2207 2208 case 0x21: /* LH */ 2209 DIP("lh r%d, %d(r%d)", rt, imm, rs); 2210 LOAD_STORE_PATTERN; 2211 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1)))); 2212 break; 2213 2214 case 0x25: /* LHU */ 2215 DIP("lhu r%d, %d(r%d)", rt, imm, rs); 2216 LOAD_STORE_PATTERN; 2217 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 2218 break; 2219 2220 case 0x0F: /* LUI */ 2221 p = (imm << 16); 2222 DIP("lui rt: %d, imm: %d, imm << 16: %d", rt, imm, p); 2223 if ((vex_traceflags & VEX_TRACE_FE) && !mode64) 2224 ppIRExpr(mkU32(p)); 2225 putIReg(rt, mkU32(p)); 2226 break; 2227 2228 case 0x13: /* COP1X */ 2229 switch (function) { 2230 case 0x0: { /* LWXC1 */ 2231 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */ 2232 DIP("lwxc1 f%d, r%d(r%d) \n", fd, rt, rs); 2233 t0 = newTemp(Ity_I32); 2234 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 2235 putFReg(fd, load(Ity_F32, mkexpr(t0))); 2236 break; 2237 } 2238 2239 case 0x1: { /* LDXC1 */ 2240 /* Load Doubleword Indexed to Floating Point - LDXC1 (MIPS32r2) */ 2241 t0 = newTemp(Ity_I32); 2242 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 2243 2244 t1 = newTemp(Ity_I32); 2245 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); 2246 2247 #if defined (_MIPSEL) 2248 putFReg(fd, load(Ity_F32, mkexpr(t0))); 2249 putFReg(fd + 1, load(Ity_F32, mkexpr(t1))); 2250 #elif defined (_MIPSEB) 2251 putFReg(fd + 1, load(Ity_F32, mkexpr(t0))); 2252 putFReg(fd, load(Ity_F32, mkexpr(t1))); 2253 #endif 2254 DIP("ldxc1 f%d, r%d(r%d) \n", fd, rt, rs); 2255 break; 2256 } 2257 2258 case 0x5: // Load Doubleword Indexed Unaligned 2259 // to Floating Point - LUXC1; MIPS32r2 2260 DIP("luxc1 f%d, r%d(r%d) \n", fd, rt, rs); 2261 t0 = newTemp(Ity_I64); 2262 t1 = newTemp(Ity_I64); 2263 assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt))); 2264 assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL))); 2265 putFReg(fd, load(Ity_F64, mkexpr(t1))); 2266 break; 2267 2268 case 0x8: { /* SWXC1 */ 2269 /* Store Word Indexed from Floating Point - SWXC1 */ 2270 t0 = newTemp(Ity_I32); 2271 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 2272 2273 store(mkexpr(t0), getFReg(fs)); 2274 2275 DIP("swxc1 f%d, r%d(r%d)", ft, rt, rs); 2276 break; 2277 } 2278 case 0x9: { /* SDXC1 */ 2279 /* Store Doubleword Indexed from Floating Point - SDXC1 */ 2280 t0 = newTemp(Ity_I32); 2281 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 2282 2283 t1 = newTemp(Ity_I32); 2284 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); 2285 2286 #if defined (_MIPSEL) 2287 store(mkexpr(t0), getFReg(fs)); 2288 store(mkexpr(t1), getFReg(fs + 1)); 2289 #elif defined (_MIPSEB) 2290 store(mkexpr(t0), getFReg(fs + 1)); 2291 store(mkexpr(t1), getFReg(fs)); 2292 #endif 2293 2294 DIP("sdc1 f%d, %d(%d)", ft, imm, rs); 2295 break; 2296 } 2297 case 0x0F: { 2298 DIP("prefx"); 2299 break; 2300 } 2301 case 0x20: { /* MADD.S */ 2302 DIP("madd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2303 IRExpr *rm = get_IR_roundingmode(); 2304 t1 = newTemp(Ity_F32); 2305 assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)), 2306 getLoFromF64(tyF, getFReg(ft)))); 2307 2308 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, mkexpr(t1), 2309 getLoFromF64(tyF, getFReg(fmt))))); 2310 break; /* MADD.S */ 2311 } 2312 case 0x21: { /* MADD.D */ 2313 DIP("madd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2314 IRExpr *rm = get_IR_roundingmode(); 2315 t1 = newTemp(Ity_F64); 2316 assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft))); 2317 2318 putDReg(fd, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt))); 2319 break; /* MADD.D */ 2320 } 2321 case 0x28: { /* MSUB.S */ 2322 DIP("msub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2323 IRExpr *rm = get_IR_roundingmode(); 2324 t1 = newTemp(Ity_F32); 2325 assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)), 2326 getLoFromF64(tyF, getFReg(ft)))); 2327 2328 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm, 2329 mkexpr(t1), getLoFromF64(tyF, getFReg(fmt))))); 2330 break; /* MSUB.S */ 2331 } 2332 case 0x29: { /* MSUB.D */ 2333 DIP("msub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2334 IRExpr *rm = get_IR_roundingmode(); 2335 t1 = newTemp(Ity_F64); 2336 assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft))); 2337 2338 putDReg(fd, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt))); 2339 break; /* MSUB.D */ 2340 } 2341 case 0x30: { /* NMADD.S */ 2342 DIP("nmadd.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2343 IRExpr *rm = get_IR_roundingmode(); 2344 t1 = newTemp(Ity_F32); 2345 t2 = newTemp(Ity_F32); 2346 assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)), 2347 getLoFromF64(tyF, getFReg(ft)))); 2348 2349 assign(t2, triop(Iop_AddF32, rm, mkexpr(t1), 2350 getLoFromF64(tyF, getFReg(fmt)))); 2351 2352 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2)))); 2353 break; /* NMADD.S */ 2354 } 2355 case 0x31: { /* NMADD.D */ 2356 DIP("nmadd.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2357 IRExpr *rm = get_IR_roundingmode(); 2358 t1 = newTemp(Ity_F64); 2359 t2 = newTemp(Ity_F64); 2360 assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft))); 2361 2362 assign(t2, triop(Iop_AddF64, rm, mkexpr(t1), getDReg(fmt))); 2363 putDReg(fd, unop(Iop_NegF64, mkexpr(t2))); 2364 break; /* NMADD.D */ 2365 } 2366 case 0x38: { /* NMSUBB.S */ 2367 DIP("nmsub.s f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2368 IRExpr *rm = get_IR_roundingmode(); 2369 t1 = newTemp(Ity_F32); 2370 t2 = newTemp(Ity_F32); 2371 assign(t1, triop(Iop_MulF32, rm, getLoFromF64(tyF, getFReg(fs)), 2372 getLoFromF64(tyF, getFReg(ft)))); 2373 2374 assign(t2, triop(Iop_SubF32, rm, mkexpr(t1), getLoFromF64(tyF, 2375 getFReg(fmt)))); 2376 2377 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t2)))); 2378 break; /* NMSUBB.S */ 2379 } 2380 case 0x39: { /* NMSUBB.D */ 2381 DIP("nmsub.d f%d, f%d, f%d, f%d", fmt, ft, fs, fd); 2382 IRExpr *rm = get_IR_roundingmode(); 2383 t1 = newTemp(Ity_F64); 2384 t2 = newTemp(Ity_F64); 2385 assign(t1, triop(Iop_MulF64, rm, getDReg(fs), getDReg(ft))); 2386 2387 assign(t2, triop(Iop_SubF64, rm, mkexpr(t1), getDReg(fmt))); 2388 putDReg(fd, unop(Iop_NegF64, mkexpr(t2))); 2389 break; /* NMSUBB.D */ 2390 } 2391 2392 default: 2393 goto decode_failure; 2394 } 2395 break; 2396 2397 case 0x22: /* LWL */ 2398 2399 DIP("lwl r%d, %d(r%d)", rt, imm, rs); 2400 { 2401 /* t1 = addr */ 2402 t1 = newTemp(Ity_I32); 2403 #if defined (_MIPSEL) 2404 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 2405 #elif defined (_MIPSEB) 2406 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 2407 mkU32(extend_s_16to32(imm))))); 2408 #endif 2409 2410 /* t2 = word addr */ 2411 /* t4 = addr mod 4 */ 2412 LWX_SWX_PATTERN; 2413 2414 /* t3 = word content - shifted */ 2415 t3 = newTemp(Ity_I32); 2416 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8, 2417 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), 2418 mkU8(3))))); 2419 2420 /* rt content - adjusted */ 2421 t5 = newTemp(Ity_I32); 2422 assign(t5, binop(Iop_And32, getIReg(rt), binop(Iop_Shr32, 2423 mkU32(0xFFFFFFFF), narrowTo(Ity_I8, binop(Iop_Shl32, 2424 binop(Iop_Add32, mkexpr(t4), mkU32(0x1)), mkU8(0x3)))))); 2425 2426 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 2427 } 2428 break; 2429 2430 case 0x26: /* LWR */ 2431 2432 DIP("lwr r%d, %d(r%d)", rt, imm, rs); 2433 { 2434 /* t1 = addr */ 2435 t1 = newTemp(Ity_I32); 2436 #if defined (_MIPSEL) 2437 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 2438 #elif defined (_MIPSEB) 2439 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 2440 mkU32(extend_s_16to32(imm))))); 2441 #endif 2442 2443 /* t2 = word addr */ 2444 /* t4 = addr mod 4 */ 2445 LWX_SWX_PATTERN; 2446 2447 /* t3 = word content - shifted */ 2448 t3 = newTemp(Ity_I32); 2449 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)), 2450 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), 2451 mkU8(3))))); 2452 2453 /* rt content - adjusted */ 2454 t5 = newTemp(Ity_I32); 2455 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32, 2456 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, 2457 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 2458 2459 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 2460 } 2461 break; 2462 2463 case 0x2B: /* SW */ 2464 DIP("sw r%d, %d(r%d)", rt, imm, rs); 2465 LOAD_STORE_PATTERN; 2466 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))); 2467 break; 2468 2469 case 0x28: /* SB */ 2470 DIP("sb r%d, %d(r%d)", rt, imm, rs); 2471 LOAD_STORE_PATTERN; 2472 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt))); 2473 break; 2474 2475 case 0x29: /* SH */ 2476 DIP("sh r%d, %d(r%d)", rt, imm, rs); 2477 LOAD_STORE_PATTERN; 2478 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt))); 2479 break; 2480 2481 case 0x2A: /* SWL */ 2482 2483 DIP("swl r%d, %d(r%d)", rt, imm, rs); 2484 { 2485 /* t1 = addr */ 2486 t1 = newTemp(Ity_I32); 2487 #if defined (_MIPSEL) 2488 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 2489 #elif defined (_MIPSEB) 2490 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 2491 mkU32(extend_s_16to32(imm))))); 2492 #endif 2493 2494 /* t2 = word addr */ 2495 /* t4 = addr mod 4 */ 2496 LWX_SWX_PATTERN; 2497 2498 /* t3 = rt content - shifted */ 2499 t3 = newTemp(Ity_I32); 2500 assign(t3, binop(Iop_Shr32, getIReg(rt), narrowTo(Ity_I8, 2501 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), 2502 mkU8(3))))); 2503 2504 /* word content - adjusted */ 2505 t5 = newTemp(Ity_I32); 2506 t6 = newTemp(Ity_I32); 2507 t7 = newTemp(Ity_I32); 2508 t8 = newTemp(Ity_I32); 2509 2510 // neg(shr(0xFFFFFFFF, mul(sub(3,n), 8))) 2511 assign(t5, binop(Iop_Mul32, binop(Iop_Sub32, mkU32(0x3), mkexpr(t4)), 2512 mkU32(0x8))); 2513 2514 assign(t6, binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, 2515 mkexpr(t5)))); 2516 assign(t7, binop(Iop_Xor32, mkU32(0xFFFFFFFF), mkexpr(t6))); 2517 assign(t8, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), mkexpr(t7))); 2518 store(mkexpr(t2), binop(Iop_Or32, mkexpr(t8), mkexpr(t3))); 2519 } 2520 break; 2521 2522 case 0x2E: /* SWR */ 2523 2524 DIP("swr r%d, %d(r%d)", rt, imm, rs); 2525 { 2526 /* t1 = addr */ 2527 t1 = newTemp(Ity_I32); 2528 #if defined (_MIPSEL) 2529 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 2530 #elif defined (_MIPSEB) 2531 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 2532 mkU32(extend_s_16to32(imm))))); 2533 #endif 2534 2535 /* t2 = word addr */ 2536 /* t4 = addr mod 4 */ 2537 LWX_SWX_PATTERN; 2538 2539 /* t3 = rt content - shifted */ 2540 t3 = newTemp(Ity_I32); 2541 assign(t3, binop(Iop_Shl32, getIReg(rt), narrowTo(Ity_I8, 2542 binop(Iop_Shl32, mkexpr(t4), mkU8(3))))); 2543 2544 /* word content - adjusted */ 2545 t5 = newTemp(Ity_I32); 2546 assign(t5, binop(Iop_And32, load(Ity_I32, mkexpr(t2)), unop(Iop_Not32, 2547 binop(Iop_Shl32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, 2548 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 2549 2550 store(mkexpr(t2), binop(Iop_Xor32, mkexpr(t5), mkexpr(t3))); 2551 } 2552 break; 2553 2554 case 0x1C: /*Special2 */ 2555 switch (function) { 2556 case 0x02: { /* MUL */ 2557 DIP("mul r%d, r%d, r%d", rd, rs, rt); 2558 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt))); 2559 break; 2560 } 2561 2562 case 0x00: { /* MADD */ 2563 DIP("madd r%d, r%d", rs, rt); 2564 t1 = newTemp(Ity_I32); 2565 t2 = newTemp(Ity_I32); 2566 t3 = newTemp(Ity_I64); 2567 t4 = newTemp(Ity_I32); 2568 t5 = newTemp(Ity_I32); 2569 t6 = newTemp(Ity_I32); 2570 2571 assign(t1, getHI()); 2572 assign(t2, getLO()); 2573 2574 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2575 2576 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 2577 mkexpr(t3)))); 2578 2579 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 2580 unop(Iop_64to32, mkexpr(t3))))); 2581 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 2582 2583 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3)))); 2584 putLO(mkexpr(t4)); 2585 break; 2586 } 2587 2588 case 0x01: { /* MADDU */ 2589 DIP("maddu r%d, r%d", rs, rt); 2590 t1 = newTemp(Ity_I32); 2591 t2 = newTemp(Ity_I32); 2592 t3 = newTemp(Ity_I64); 2593 t4 = newTemp(Ity_I32); 2594 t5 = newTemp(Ity_I32); 2595 t6 = newTemp(Ity_I32); 2596 2597 assign(t1, getHI()); 2598 assign(t2, getLO()); 2599 2600 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2601 2602 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 2603 mkexpr(t3)))); 2604 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 2605 unop(Iop_64to32, mkexpr(t3))))); 2606 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 2607 2608 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3)))); 2609 putLO(mkexpr(t4)); 2610 break; 2611 } 2612 2613 case 0x04: { /* MSUB */ 2614 DIP("msub r%d, r%d", rs, rt); 2615 t1 = newTemp(Ity_I32); 2616 t2 = newTemp(Ity_I32); 2617 t3 = newTemp(Ity_I64); 2618 t4 = newTemp(Ity_I32); 2619 t5 = newTemp(Ity_I32); 2620 t6 = newTemp(Ity_I32); 2621 2622 assign(t1, getHI()); 2623 assign(t2, getLO()); 2624 2625 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2626 assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo 2627 2628 //if lo<lo(mul) hi = hi - 1 2629 assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2), 2630 mkexpr(t4)))); 2631 2632 assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)), mkexpr(t1), 2633 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)))); 2634 2635 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3)))); 2636 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 2637 break; 2638 } 2639 2640 case 0x05: { /* MSUBU */ 2641 DIP("msubu r%d, r%d", rs, rt); 2642 t1 = newTemp(Ity_I32); 2643 t2 = newTemp(Ity_I32); 2644 t3 = newTemp(Ity_I64); 2645 t4 = newTemp(Ity_I32); 2646 t5 = newTemp(Ity_I32); 2647 t6 = newTemp(Ity_I32); 2648 2649 assign(t1, getHI()); 2650 assign(t2, getLO()); 2651 2652 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2653 assign(t4, unop(Iop_64to32, mkexpr(t3))); //new lo 2654 2655 //if lo<lo(mul) hi = hi - 1 2656 assign(t5, unop(Iop_1Sto32, binop(Iop_CmpLT32U, mkexpr(t2), 2657 mkexpr(t4)))); 2658 2659 assign(t6, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t5)), 2660 mkexpr(t1), binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)))); 2661 2662 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, mkexpr(t3)))); 2663 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 2664 break; 2665 } 2666 2667 case 0x20: { /* CLZ */ 2668 DIP("clz r%d, r%d", rd, rs); 2669 t1 = newTemp(Ity_I32); 2670 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs), 2671 mkU32(0)))); 2672 putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 2673 unop(Iop_Clz32, getIReg(rs)), mkU32(0x00000020))); 2674 break; 2675 } 2676 2677 case 0x21: { /* CLO */ 2678 DIP("clo r%d, r%d", rd, rs); 2679 t1 = newTemp(Ity_I32); 2680 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rs), 2681 mkU32(0xffffffff)))); 2682 putIReg(rd, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 2683 unop(Iop_Clz32, unop(Iop_Not32, getIReg(rs))), 2684 mkU32(0x00000020))); 2685 break; 2686 } 2687 2688 default: 2689 goto decode_failure; 2690 } 2691 break; 2692 2693 case 0x1F: /*Special3 */ 2694 switch (function) { 2695 case 0x3B: 2696 /*RDHWR*/ { 2697 DIP("rdhwr r%d, r%d", rt, rd); 2698 if (rd == 29) { 2699 putIReg(rt, getULR()); 2700 } else 2701 goto decode_failure; 2702 break; 2703 } 2704 case 0x04: 2705 /*INS*/ msb = get_msb(cins); 2706 lsb = get_lsb(cins); 2707 2708 size = msb - lsb + 1; 2709 2710 vassert(lsb + size <= 32); 2711 vassert(lsb + size > 0); 2712 2713 DIP("ins size:%d msb:%d lsb:%d", size, msb, lsb); 2714 /*put size bits from rs at the pos in temporary */ 2715 t0 = newTemp(Ity_I32); 2716 t3 = newTemp(Ity_I32); 2717 /*shift left for 32 - size to clear leading bits and get zeros 2718 at the end */ 2719 assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - size))); 2720 /*now set it at pos */ 2721 t1 = newTemp(Ity_I32); 2722 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb))); 2723 2724 if (lsb > 0) { 2725 t2 = newTemp(Ity_I32); 2726 /*clear everything but lower pos bits from rt */ 2727 assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(32 - lsb))); 2728 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb))); 2729 } 2730 2731 if (msb < 31) { 2732 t4 = newTemp(Ity_I32); 2733 /*clear everything but upper msb + 1 bits from rt */ 2734 assign(t4, binop(Iop_Shr32, getIReg(rt), mkU8(msb + 1))); 2735 t5 = newTemp(Ity_I32); 2736 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1))); 2737 2738 /*now combine these registers */ 2739 if (lsb > 0) { 2740 t6 = newTemp(Ity_I32); 2741 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1))); 2742 putIReg(rt, binop(Iop_Or32, mkexpr(t6), mkexpr(t3))); 2743 } else { 2744 putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t5))); 2745 } 2746 } 2747 2748 else { 2749 putIReg(rt, binop(Iop_Or32, mkexpr(t1), mkexpr(t3))); 2750 2751 } 2752 break; 2753 2754 case 0x00: 2755 /*EXT*/ msb = get_msb(cins); 2756 lsb = get_lsb(cins); 2757 size = msb + 1; 2758 DIP("ext size:%d msb:%d lsb:%d", size, msb, lsb); 2759 vassert(lsb + size <= 32); 2760 vassert(lsb + size > 0); 2761 /*put size bits from rs at the top of in temporary */ 2762 if (lsb + size < 32) { 2763 t0 = newTemp(Ity_I32); 2764 assign(t0, binop(Iop_Shl32, getIReg(rs), mkU8(32 - lsb - size))); 2765 putIReg(rt, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size))); 2766 } else { 2767 putIReg(rt, binop(Iop_Shr32, getIReg(rs), mkU8(32 - size))); 2768 2769 } 2770 break; 2771 2772 case 0x20: 2773 /*BSHFL*/ switch (sa) { 2774 case 0x10: 2775 /*SEB*/ DIP("seb r%d, r%d", rd, rt); 2776 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt)))); 2777 break; 2778 2779 case 0x18: 2780 /*SEH*/ DIP("seh r%d, r%d", rd, rt); 2781 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 2782 break; 2783 2784 case 0x02: 2785 /*WSBH*/ DIP("wsbh r%d, r%d", rd, rt); 2786 t0 = newTemp(Ity_I32); 2787 t1 = newTemp(Ity_I32); 2788 t2 = newTemp(Ity_I32); 2789 t3 = newTemp(Ity_I32); 2790 assign(t0, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt), 2791 mkU32(0x00FF0000)), mkU8(0x8))); 2792 assign(t1, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt), 2793 mkU32(0xFF000000)), mkU8(0x8))); 2794 assign(t2, binop(Iop_Shl32, binop(Iop_And32, getIReg(rt), 2795 mkU32(0x000000FF)), mkU8(0x8))); 2796 assign(t3, binop(Iop_Shr32, binop(Iop_And32, getIReg(rt), 2797 mkU32(0x0000FF00)), mkU8(0x8))); 2798 putIReg(rd, binop(Iop_Or32, binop(Iop_Or32, mkexpr(t0), 2799 mkexpr(t1)), binop(Iop_Or32, mkexpr(t2), mkexpr(t3)))); 2800 break; 2801 2802 default: 2803 goto decode_failure; 2804 2805 } 2806 break; 2807 /*BSHFL*/ default: 2808 goto decode_failure; 2809 2810 } 2811 break; /*Special3 */ 2812 2813 case 0x3B: 2814 if (0x3B == function && (archinfo->hwcaps & VEX_PRID_COMP_BROADCOM)) { 2815 /*RDHWR*/ 2816 DIP("rdhwr r%d, r%d", rt, rd); 2817 if (rd == 29) { 2818 putIReg(rt, getULR()); 2819 } else 2820 goto decode_failure; 2821 break; 2822 } else { 2823 goto decode_failure; 2824 } 2825 2826 case 0x00: /*Special */ 2827 2828 switch (function) { 2829 case 0x1: { 2830 UInt mov_cc = get_mov_cc(cins); 2831 if (tf == 0) { /* MOVF */ 2832 DIP("movf r%d, r%d, %d", rd, rs, mov_cc); 2833 { 2834 t1 = newTemp(Ity_I32); 2835 t2 = newTemp(Ity_I32); 2836 t3 = newTemp(Ity_I32); 2837 t4 = newTemp(Ity_I32); 2838 2839 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 2840 mkU32(mov_cc)))); 2841 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 2842 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 2843 mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32, 2844 binop(Iop_Shr32, getFCSR(), mkU8(23)), 2845 mkU32(0x1)))); 2846 2847 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 2848 mkexpr(t2)))); 2849 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 2850 getIReg(rd), getIReg(rs))); 2851 putIReg(rd, mkexpr(t4)); 2852 } 2853 } else if (tf == 1) { /* MOVT */ 2854 DIP("movt r%d, r%d, %d", rd, rs, mov_cc); 2855 { 2856 t1 = newTemp(Ity_I32); 2857 t2 = newTemp(Ity_I32); 2858 t3 = newTemp(Ity_I32); 2859 t4 = newTemp(Ity_I32); 2860 2861 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(0), 2862 mkU32(mov_cc)))); 2863 assign(t2, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t1)), 2864 binop(Iop_And32, binop(Iop_Shr32, getFCSR(), 2865 mkU8(24 + mov_cc)), mkU32(0x1)), binop(Iop_And32, 2866 binop(Iop_Shr32, getFCSR(), mkU8(23)), 2867 mkU32(0x1)))); 2868 2869 assign(t3, unop(Iop_1Sto32, binop(Iop_CmpEQ32, mkU32(1), 2870 mkexpr(t2)))); 2871 assign(t4, IRExpr_Mux0X(unop(Iop_32to8, mkexpr(t3)), 2872 getIReg(rd), getIReg(rs))); 2873 putIReg(rd, mkexpr(t4)); 2874 } 2875 } 2876 break; 2877 } 2878 case 0x0A: { 2879 /* MOVZ */ 2880 DIP("movz r%d, r%d, r%d", rd, rs, rt); 2881 t1 = newTemp(ty); 2882 t2 = newTemp(ty); 2883 { 2884 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 2885 mkU32(0x0)))); 2886 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 2887 mkU32(0x0)))); 2888 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 2889 mkexpr(t1)), binop(Iop_And32, getIReg(rd), 2890 mkexpr(t2)))); 2891 } 2892 break; 2893 } 2894 2895 case 0x0B: { 2896 /* MOVN */ 2897 DIP("movn r%d, r%d, r%d", rd, rs, rt); 2898 t1 = newTemp(ty); 2899 t2 = newTemp(ty); 2900 { 2901 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 2902 mkU32(0x0)))); 2903 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 2904 mkU32(0x0)))); 2905 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 2906 mkexpr(t2)), binop(Iop_And32, getIReg(rd), 2907 mkexpr(t1)))); 2908 } 2909 break; 2910 } 2911 2912 case 0x18: /* MULT */ 2913 DIP("mult r%d, r%d", rs, rt); 2914 t2 = newTemp(Ity_I64); 2915 2916 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 2917 mkNarrowTo32(ty, getIReg(rt)))); 2918 2919 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 2920 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 2921 break; 2922 2923 case 0x19: /* MULTU */ 2924 DIP("multu r%d, r%d", rs, rt); 2925 t2 = newTemp(Ity_I64); 2926 2927 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 2928 mkNarrowTo32(ty, getIReg(rt)))); 2929 2930 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 2931 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 2932 break; 2933 2934 case 0x20: /* ADD */ 2935 DIP("add r%d, r%d, r%d", rd, rs, rt); 2936 { 2937 t2 = newTemp(Ity_I32); 2938 2939 assign(t2, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 2940 putIReg(rd, mkexpr(t2)); 2941 } 2942 break; 2943 2944 case 0x1A: /* DIV */ 2945 DIP("div r%d, r%d", rs, rt); 2946 { 2947 t1 = newTemp(Ity_I64); 2948 t2 = newTemp(Ity_I64); 2949 2950 assign(t1, unop(Iop_32Sto64, getIReg(rs))); 2951 assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt))); 2952 2953 putHI(unop(Iop_64HIto32, mkexpr(t2))); 2954 putLO(unop(Iop_64to32, mkexpr(t2))); 2955 } 2956 break; 2957 2958 case 0x1B: /* DIVU */ 2959 DIP("divu r%d, r%d", rs, rt); 2960 { 2961 t1 = newTemp(Ity_I64); 2962 t2 = newTemp(Ity_I64); 2963 assign(t1, unop(Iop_32Uto64, getIReg(rs))); 2964 assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt))); 2965 putHI(unop(Iop_64HIto32, mkexpr(t2))); 2966 putLO(unop(Iop_64to32, mkexpr(t2))); 2967 } 2968 break; 2969 2970 case 0x10: /* MFHI */ 2971 DIP("mfhi r%d", rd); 2972 putIReg(rd, getHI()); 2973 break; 2974 2975 case 0x11: /* MTHI */ 2976 DIP("mthi r%d", rs); 2977 putHI(getIReg(rs)); 2978 break; 2979 2980 case 0x12: /* MFLO */ 2981 DIP("mflo r%d", rd); 2982 putIReg(rd, getLO()); 2983 break; 2984 2985 case 0x13: /* MTLO */ 2986 DIP("mtlo r%d", rs); 2987 putLO(getIReg(rs)); 2988 break; 2989 2990 case 0x21: /* ADDU */ 2991 DIP("addu r%d, r%d, r%d", rd, rs, rt); 2992 ALU_PATTERN(Iop_Add32); 2993 break; 2994 2995 case 0x22: /* SUB */ 2996 DIP("sub r%d, r%d, r%d", rd, rs, rt); 2997 ALU_PATTERN(Iop_Sub32); 2998 break; 2999 3000 case 0x23: /* SUBU */ 3001 DIP("subu r%d, r%d, r%d", rd, rs, rt); 3002 ALU_PATTERN(Iop_Sub32); 3003 break; 3004 3005 case 0x24: /* AND */ 3006 DIP("and r%d, r%d, r%d", rd, rs, rt); 3007 ALU_PATTERN(Iop_And32); 3008 break; 3009 3010 case 0x25: /* OR */ 3011 DIP("or r%d, r%d, r%d", rd, rs, rt); 3012 ALU_PATTERN(Iop_Or32); 3013 break; 3014 3015 case 0x26: /* XOR */ 3016 DIP("xor r%d, r%d, r%d", rd, rs, rt); 3017 ALU_PATTERN(Iop_Xor32); 3018 break; 3019 3020 case 0x27: /* NOR */ 3021 DIP("nor r%d, r%d, r%d", rd, rs, rt); 3022 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs),getIReg(rt)))); 3023 break; 3024 3025 case 0x08: /* JR */ 3026 DIP("jr r%d", rs); 3027 t0 = newTemp(ty); 3028 assign(t0, getIReg(rs)); 3029 lastn = mkexpr(t0); 3030 break; 3031 3032 case 0x09: /* JALR */ 3033 DIP("jalr r%d r%d", rd, rs); 3034 putIReg(rd, mkU32(guest_PC_curr_instr + 8)); 3035 t0 = newTemp(Ity_I32); 3036 assign(t0, getIReg(rs)); 3037 lastn = mkexpr(t0); 3038 break; 3039 3040 case 0x0C: /* SYSCALL */ 3041 DIP("syscall"); 3042 putPC(mkU32(guest_PC_curr_instr + 4)); 3043 dres.jk_StopHere = Ijk_Sys_syscall; 3044 dres.whatNext = Dis_StopHere; 3045 break; 3046 3047 case 0x2A: /* SLT */ 3048 DIP("slt r%d, r%d, r%d", rd, rs, rt); 3049 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 3050 getIReg(rt)))); 3051 break; 3052 3053 case 0x2B: /* SLTU */ 3054 DIP("sltu r%d, r%d, r%d", rd, rs, rt); 3055 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 3056 getIReg(rt)))); 3057 break; 3058 3059 case 0x00: 3060 /* SLL */ 3061 DIP("sll r%d, r%d, %d", rd, rt, sa); 3062 SXX_PATTERN(Iop_Shl32); 3063 break; 3064 3065 case 0x04: /* SLLV */ 3066 DIP("sllv r%d, r%d, r%d", rd, rt, rs); 3067 SXXV_PATTERN(Iop_Shl32); 3068 break; 3069 3070 case 0x03: /* SRA */ 3071 DIP("sra r%d, r%d, %d", rd, rt, sa); 3072 SXX_PATTERN(Iop_Sar32); 3073 break; 3074 3075 case 0x07: /* SRAV */ 3076 DIP("srav r%d, r%d, r%d", rd, rt, rs); 3077 SXXV_PATTERN(Iop_Sar32); 3078 break; 3079 3080 case 0x02: { /* SRL */ 3081 rot = get_rot(cins); 3082 if (rot) { 3083 DIP("rotr r%d, r%d, %d", rd, rt, sa); 3084 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty, 3085 getIReg(rt)), sa), False)); 3086 } else { 3087 DIP("srl r%d, r%d, %d", rd, rt, sa); 3088 SXX_PATTERN(Iop_Shr32); 3089 } 3090 break; 3091 } 3092 3093 case 0x06: { 3094 rot = get_rotv(cins); 3095 if (rot) { 3096 DIP("rotrv r%d, r%d, r%d", rd, rt, rs); 3097 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty, 3098 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))),False)); 3099 break; 3100 } else { 3101 /* SRLV */ 3102 DIP("srlv r%d, r%d, r%d", rd, rt, rs); 3103 SXXV_PATTERN(Iop_Shr32); 3104 break; 3105 } 3106 } 3107 3108 case 0x0D: /* BREAK */ 3109 DIP("Info: Breakpoint...code = %d", trap_code); 3110 jmp_lit(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4)); 3111 vassert(dres.whatNext == Dis_StopHere); 3112 break; 3113 3114 case 0x30: { /* TGE */ 3115 /*tge */ DIP("tge r%d, r%d %d", rs, rt, trap_code); 3116 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rt), getIReg (rs)), 3117 Ijk_SigTRAP, 3118 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3119 break; 3120 } 3121 case 0x31: { /* TGEU */ 3122 /*tgeu */ DIP("tgeu r%d, r%d %d", rs, rt, trap_code); 3123 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rt), getIReg (rs)), 3124 Ijk_SigTRAP, 3125 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3126 break; 3127 } 3128 case 0x32: { /* TLT */ 3129 /*tlt */ DIP("tlt r%d, r%d %d", rs, rt, trap_code); 3130 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), getIReg (rt)), 3131 Ijk_SigTRAP, 3132 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3133 break; 3134 } 3135 case 0x33: { /* TLTU */ 3136 /*tltu */ DIP("tltu r%d, r%d %d", rs, rt, trap_code); 3137 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), getIReg (rt)), 3138 Ijk_SigTRAP, 3139 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3140 break; 3141 } 3142 case 0x34: { /* TEQ */ 3143 /*teq */ DIP("teq r%d, r%d %d", rs, rt, trap_code); 3144 stmt (IRStmt_Exit(binop (Iop_CmpEQ32, getIReg (rs), getIReg (rt)), 3145 Ijk_SigTRAP, IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3146 break; 3147 } 3148 case 0x36: { /* TNE */ 3149 /*tne */ DIP("tne r%d, r%d %d", rs, rt, trap_code); 3150 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), getIReg (rt)), 3151 Ijk_SigTRAP, 3152 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3153 break; 3154 } 3155 case 0x0F: { 3156 /*SYNC*/ DIP("sync r%d, r%d, %d", rt, rd, sel); 3157 lsb = get_lsb(cins); 3158 IRDirty *d = unsafeIRDirty_0_N(0, 3159 "mips32_dirtyhelper_sync", 3160 &mips32_dirtyhelper_sync, 3161 mkIRExprVec_1 3162 (mkU32(lsb))); 3163 3164 d->needsBBP = False; 3165 d->nFxState = 0; 3166 3167 stmt(IRStmt_Dirty(d)); 3168 break; 3169 } 3170 3171 default: 3172 goto decode_failure; 3173 } 3174 break; 3175 3176 case 0x01: /* Regimm */ 3177 3178 switch (rt) { 3179 case 0x01: /* BGEZ */ 3180 DIP("bgez r%d, %d", rs, imm); 3181 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 3182 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 3183 break; 3184 3185 case 0x03: /* BGEZL */ 3186 DIP("bgezl r%d, %d", rs, imm); 3187 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 3188 getIReg(rs), mode64 ? 3189 mkU64(0x8000000000000000ULL) 3190 :mkU32(0x80000000)), 3191 mkU32(0x0)), imm); 3192 break; 3193 3194 case 0x00: /* BLTZ */ 3195 DIP("bltz r%d, %d", rs, imm); 3196 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 3197 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 3198 break; 3199 3200 case 0x02: /* BLTZL */ 3201 DIP("bltzl r%d, %d", rs, imm); 3202 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 3203 getIReg(rs), mkU32(0x80000000)), 3204 mkU32(0x80000000)), imm); 3205 break; 3206 3207 case 0x10: /* BLTZAL */ 3208 DIP("bltzal r%d, %d", rs, imm); 3209 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 3210 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 3211 break; 3212 3213 case 0x12: /* BLTZALL */ 3214 DIP("bltzall r%d, %d", rs, imm); 3215 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 3216 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 3217 getIReg(rs), mkU32(0x80000000)), 3218 mkU32(0x80000000)), imm); 3219 break; 3220 3221 case 0x11: /* BGEZAL */ 3222 DIP("bgezal r%d, %d", rs, imm); 3223 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 3224 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 3225 break; 3226 3227 case 0x13: /* BGEZALL */ 3228 DIP("bgezall r%d, %d", rs, imm); 3229 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 3230 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 3231 getIReg(rs), mkU32(0x80000000)), 3232 mkU32(0x0)), imm); 3233 break; 3234 3235 case 0x08: { /* TGEI */ 3236 /*tgei */ DIP("tgei r%d, %d %d", rs, imm, trap_code); 3237 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, mkU32 (imm), getIReg (rs)), 3238 Ijk_SigTRAP, 3239 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3240 break; 3241 } 3242 case 0x09: { /* TGEIU */ 3243 /*tqeiu */ DIP("tgeiu r%d, %d %d", rs, imm, trap_code); 3244 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, mkU32 (imm), getIReg (rs)), 3245 Ijk_SigTRAP, 3246 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3247 break; 3248 } 3249 case 0x0A: { /* TLTI */ 3250 /*tlti */ DIP("tlti r%d, %d %d", rs, imm, trap_code); 3251 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), mkU32 (imm)), 3252 Ijk_SigTRAP, 3253 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3254 break; 3255 } 3256 case 0x0B: { /* TLTIU */ 3257 /*tltiu */ DIP("tltiu r%d, %d %d", rs, imm, trap_code); 3258 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), mkU32 (imm)), 3259 Ijk_SigTRAP, 3260 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3261 break; 3262 } 3263 case 0x0C: { /* TEQI */ 3264 /*teqi */ DIP("teqi r%d, %d %d", rs, imm, trap_code); 3265 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), mkU32 (imm)), 3266 Ijk_SigTRAP, 3267 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3268 break; 3269 } 3270 case 0x0E: { /* TNEI */ 3271 /*tnei */ DIP("tnei r%d, %d %d", rs, imm, trap_code); 3272 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), mkU32 (imm)), 3273 Ijk_SigTRAP, 3274 IRConst_U32 (guest_PC_curr_instr + 4), OFFB_PC)); 3275 break; 3276 } 3277 case 0x1F: 3278 /*SYNCI*/ 3279 //Just ignore it 3280 break; 3281 3282 default: 3283 goto decode_failure; 3284 } 3285 break; 3286 3287 case 0x04: 3288 DIP("beq r%d, r%d, %d", rs, rt, imm); 3289 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), 3290 imm, &bstmt); 3291 break; 3292 3293 case 0x14: 3294 DIP("beql r%d, r%d, %d", rs, rt, imm); 3295 lastn = dis_branch_likely(binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)), 3296 imm); 3297 break; 3298 3299 case 0x05: 3300 DIP("bne r%d, r%d, %d", rs, rt, imm); 3301 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)), 3302 imm, &bstmt); 3303 break; 3304 3305 case 0x15: 3306 DIP("bnel r%d, r%d, %d", rs, rt, imm); 3307 lastn = 3308 dis_branch_likely(binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), imm); 3309 break; 3310 3311 case 0x07: /* BGTZ */ 3312 DIP("bgtz r%d, %d", rs, imm); 3313 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs), 3314 mkU32(0x00))), imm, &bstmt); 3315 break; 3316 3317 case 0x17: /* BGTZL */ 3318 DIP("bgtzl r%d, %d", rs, imm); 3319 lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x00)), 3320 imm); 3321 break; 3322 3323 case 0x06: /* BLEZ */ 3324 DIP("blez r%d, %d", rs, imm); 3325 dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm, 3326 &bstmt); 3327 break; 3328 3329 case 0x16: /* BLEZL */ 3330 DIP("blezl r%d, %d", rs, imm); 3331 lastn = dis_branch_likely(unop(Iop_Not1, (binop(Iop_CmpLE32S, 3332 getIReg(rs), mkU32(0x0)))), imm); 3333 break; 3334 3335 case 0x08: /* ADDI TODO: Check this */ 3336 DIP("addi r%d, r%d, %d", rt, rs, imm); 3337 putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 3338 break; 3339 3340 case 0x09: /* ADDIU */ 3341 DIP("addiu r%d, r%d, %d", rt, rs, imm); 3342 putIReg(rt, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 3343 break; 3344 3345 case 0x0C: /* ANDI */ 3346 DIP("andi r%d, r%d, %d", rt, rs, imm); 3347 ALUI_PATTERN(Iop_And32); 3348 break; 3349 3350 case 0x0E: /* XORI */ 3351 DIP("xori r%d, r%d, %d", rt, rs, imm); 3352 ALUI_PATTERN(Iop_Xor32); 3353 break; 3354 3355 case 0x0D: /* ORI */ 3356 DIP("ori r%d, r%d, %d", rt, rs, imm); 3357 ALUI_PATTERN(Iop_Or32); 3358 break; 3359 3360 case 0x0A: /* SLTI */ 3361 DIP("slti r%d, r%d, %d", rt, rs, imm); 3362 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 3363 mkU32(extend_s_16to32(imm))))); 3364 break; 3365 3366 case 0x0B: /* SLTIU */ 3367 DIP("sltiu r%d, r%d, %d", rt, rs, imm); 3368 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 3369 mkU32(extend_s_16to32(imm))))); 3370 break; 3371 3372 case 0x30: /* LL / LWC0 */ 3373 DIP("ll r%d, %d(r%d)", rt, imm, rs); 3374 LOAD_STORE_PATTERN; 3375 3376 t2 = newTemp(Ity_I32); 3377 #if defined (_MIPSEL) 3378 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /*this is a load */ )); 3379 #elif defined (_MIPSEB) 3380 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /*this is a load */ )); 3381 #endif 3382 3383 putIReg(rt, mkexpr(t2)); 3384 break; 3385 3386 case 0x38: /* SC / SWC0 */ 3387 DIP("sc r%d, %d(r%d)", rt, imm, rs); 3388 LOAD_STORE_PATTERN; 3389 3390 t2 = newTemp(Ity_I1); 3391 #if defined (_MIPSEL) 3392 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)))); 3393 #elif defined (_MIPSEB) 3394 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)))); 3395 #endif 3396 3397 putIReg(rt, unop(Iop_1Uto32, mkexpr(t2))); 3398 break; 3399 3400 decode_failure: 3401 /* All decode failures end up here. */ 3402 DIP("vex mips->IR: unhandled instruction bytes: " 3403 "0x%x 0x%x 0x%x 0x%x\n", 3404 (Int) getIByte(delta_start + 0), 3405 (Int) getIByte(delta_start + 1), 3406 (Int) getIByte(delta_start + 2), 3407 (Int) getIByte(delta_start + 3)); 3408 3409 /* Tell the dispatcher that this insn cannot be decoded, and so has 3410 not been executed, and (is currently) the next to be executed. 3411 EIP should be up-to-date since it made so at the start bnezof each 3412 insn, but nevertheless be paranoid and update it again right 3413 now. */ 3414 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC), 3415 mkU32(guest_PC_curr_instr))); 3416 jmp_lit(&dres, Ijk_NoDecode, guest_PC_curr_instr); 3417 dres.whatNext = Dis_StopHere; 3418 dres.len = 0; 3419 return dres; 3420 } /* switch (opc) for the main (primary) opcode switch. */ 3421 3422 /* All MIPS insn have 4 bytes */ 3423 3424 if (delay_slot_branch) { 3425 delay_slot_branch = False; 3426 stmt(bstmt); 3427 bstmt = NULL; 3428 putPC(mkU32(guest_PC_curr_instr + 4)); 3429 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 3430 Ijk_Call : Ijk_Boring; 3431 } 3432 3433 if (likely_delay_slot) { 3434 dres.jk_StopHere = Ijk_Boring; 3435 dres.whatNext = Dis_StopHere; 3436 putPC(lastn); 3437 lastn = NULL; 3438 } 3439 if (delay_slot_jump) { 3440 putPC(lastn); 3441 lastn = NULL; 3442 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 3443 Ijk_Call : Ijk_Boring; 3444 } 3445 3446 decode_success: 3447 /* All decode successes end up here. */ 3448 switch (dres.whatNext) { 3449 case Dis_Continue: 3450 putPC(mkU32(guest_PC_curr_instr + 4)); 3451 break; 3452 case Dis_ResteerU: 3453 case Dis_ResteerC: 3454 putPC(mkU32(dres.continueAt)); 3455 break; 3456 case Dis_StopHere: 3457 break; 3458 default: 3459 vassert(0); 3460 break; 3461 } 3462 3463 // On MIPS we need to check if the last instruction 3464 // in block is branch or jump 3465 if ((vex_control.guest_max_insns - 1) == (delta+4)/4) 3466 if (branch_or_jump(guest_code + delta + 4)) { 3467 dres.whatNext = Dis_StopHere; 3468 dres.jk_StopHere = Ijk_Boring; 3469 putPC(mkU32(guest_PC_curr_instr + 4)); 3470 } 3471 dres.len = 4; 3472 3473 DIP("\n"); 3474 3475 return dres; 3476 3477 } 3478 3479 /*------------------------------------------------------------*/ 3480 /*--- Top-level fn ---*/ 3481 /*------------------------------------------------------------*/ 3482 3483 /* Disassemble a single instruction into IR. The instruction 3484 is located in host memory at &guest_code[delta]. */ 3485 3486 DisResult 3487 disInstr_MIPS(IRSB* irsb_IN, 3488 Bool (*resteerOkFn) (void *, Addr64), 3489 Bool resteerCisOk, 3490 void* callback_opaque, 3491 UChar* guest_code_IN, 3492 Long delta, 3493 Addr64 guest_IP, 3494 VexArch guest_arch, 3495 VexArchInfo* archinfo, 3496 VexAbiInfo* abiinfo, 3497 Bool host_bigendian_IN) 3498 { 3499 DisResult dres; 3500 3501 /* Set globals (see top of this file) */ 3502 vassert(guest_arch == VexArchMIPS32); 3503 3504 mode64 = guest_arch != VexArchMIPS32; 3505 3506 guest_code = guest_code_IN; 3507 irsb = irsb_IN; 3508 host_is_bigendian = host_bigendian_IN; 3509 guest_PC_curr_instr = (Addr32) guest_IP; 3510 guest_PC_bbstart = (Addr32) toUInt(guest_IP - delta); 3511 3512 dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque, 3513 delta, archinfo, abiinfo); 3514 3515 return dres; 3516 } 3517 3518 /*--------------------------------------------------------------------*/ 3519 /*--- end guest_mips_toIR.c ---*/ 3520 /*--------------------------------------------------------------------*/ 3521