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-2013 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 #include "libvex_guest_mips64.h" 38 39 #include "main_util.h" 40 #include "main_globals.h" 41 #include "guest_generic_bb_to_IR.h" 42 #include "guest_mips_defs.h" 43 44 /*------------------------------------------------------------*/ 45 /*--- Globals ---*/ 46 /*------------------------------------------------------------*/ 47 48 /* These are set at the start of the translation of a instruction, so 49 that we don't have to pass them around endlessly. CONST means does 50 not change during translation of the instruction. */ 51 52 /* CONST: what is the host's endianness? This has to do with float vs 53 double register accesses on VFP, but it's complex and not properly 54 thought out. */ 55 static VexEndness host_endness; 56 57 /* Pointer to the guest code area. */ 58 static const UChar *guest_code; 59 60 /* CONST: The guest address for the instruction currently being 61 translated. */ 62 #if defined(VGP_mips32_linux) 63 static Addr32 guest_PC_curr_instr; 64 #else 65 static Addr64 guest_PC_curr_instr; 66 #endif 67 68 /* MOD: The IRSB* into which we're generating code. */ 69 static IRSB *irsb; 70 71 /* Is our guest binary 32 or 64bit? Set at each call to 72 disInstr_MIPS below. */ 73 static Bool mode64 = False; 74 75 /* CPU has FPU and 32 dbl. prec. FP registers. */ 76 static Bool fp_mode64 = False; 77 78 /* Define 1.0 in single and double precision. */ 79 #define ONE_SINGLE 0x3F800000 80 #define ONE_DOUBLE 0x3FF0000000000000ULL 81 82 /*------------------------------------------------------------*/ 83 /*--- Debugging output ---*/ 84 /*------------------------------------------------------------*/ 85 86 #define DIP(format, args...) \ 87 if (vex_traceflags & VEX_TRACE_FE) \ 88 vex_printf(format, ## args) 89 90 /*------------------------------------------------------------*/ 91 /*--- Helper bits and pieces for deconstructing the ---*/ 92 /*--- mips insn stream. ---*/ 93 /*------------------------------------------------------------*/ 94 95 /* ---------------- Integer registers ---------------- */ 96 97 static UInt integerGuestRegOffset(UInt iregNo) 98 { 99 /* Do we care about endianness here? We do if sub-parts of integer 100 registers are accessed, but I don't think that ever happens on 101 MIPS. */ 102 UInt ret; 103 if (!mode64) 104 switch (iregNo) { 105 case 0: 106 ret = offsetof(VexGuestMIPS32State, guest_r0); break; 107 case 1: 108 ret = offsetof(VexGuestMIPS32State, guest_r1); break; 109 case 2: 110 ret = offsetof(VexGuestMIPS32State, guest_r2); break; 111 case 3: 112 ret = offsetof(VexGuestMIPS32State, guest_r3); break; 113 case 4: 114 ret = offsetof(VexGuestMIPS32State, guest_r4); break; 115 case 5: 116 ret = offsetof(VexGuestMIPS32State, guest_r5); break; 117 case 6: 118 ret = offsetof(VexGuestMIPS32State, guest_r6); break; 119 case 7: 120 ret = offsetof(VexGuestMIPS32State, guest_r7); break; 121 case 8: 122 ret = offsetof(VexGuestMIPS32State, guest_r8); break; 123 case 9: 124 ret = offsetof(VexGuestMIPS32State, guest_r9); break; 125 case 10: 126 ret = offsetof(VexGuestMIPS32State, guest_r10); break; 127 case 11: 128 ret = offsetof(VexGuestMIPS32State, guest_r11); break; 129 case 12: 130 ret = offsetof(VexGuestMIPS32State, guest_r12); break; 131 case 13: 132 ret = offsetof(VexGuestMIPS32State, guest_r13); break; 133 case 14: 134 ret = offsetof(VexGuestMIPS32State, guest_r14); break; 135 case 15: 136 ret = offsetof(VexGuestMIPS32State, guest_r15); break; 137 case 16: 138 ret = offsetof(VexGuestMIPS32State, guest_r16); break; 139 case 17: 140 ret = offsetof(VexGuestMIPS32State, guest_r17); break; 141 case 18: 142 ret = offsetof(VexGuestMIPS32State, guest_r18); break; 143 case 19: 144 ret = offsetof(VexGuestMIPS32State, guest_r19); break; 145 case 20: 146 ret = offsetof(VexGuestMIPS32State, guest_r20); break; 147 case 21: 148 ret = offsetof(VexGuestMIPS32State, guest_r21); break; 149 case 22: 150 ret = offsetof(VexGuestMIPS32State, guest_r22); break; 151 case 23: 152 ret = offsetof(VexGuestMIPS32State, guest_r23); break; 153 case 24: 154 ret = offsetof(VexGuestMIPS32State, guest_r24); break; 155 case 25: 156 ret = offsetof(VexGuestMIPS32State, guest_r25); break; 157 case 26: 158 ret = offsetof(VexGuestMIPS32State, guest_r26); break; 159 case 27: 160 ret = offsetof(VexGuestMIPS32State, guest_r27); break; 161 case 28: 162 ret = offsetof(VexGuestMIPS32State, guest_r28); break; 163 case 29: 164 ret = offsetof(VexGuestMIPS32State, guest_r29); break; 165 case 30: 166 ret = offsetof(VexGuestMIPS32State, guest_r30); break; 167 case 31: 168 ret = offsetof(VexGuestMIPS32State, guest_r31); break; 169 default: 170 vassert(0); 171 break; 172 } 173 else 174 switch (iregNo) { 175 case 0: 176 ret = offsetof(VexGuestMIPS64State, guest_r0); break; 177 case 1: 178 ret = offsetof(VexGuestMIPS64State, guest_r1); break; 179 case 2: 180 ret = offsetof(VexGuestMIPS64State, guest_r2); break; 181 case 3: 182 ret = offsetof(VexGuestMIPS64State, guest_r3); break; 183 case 4: 184 ret = offsetof(VexGuestMIPS64State, guest_r4); break; 185 case 5: 186 ret = offsetof(VexGuestMIPS64State, guest_r5); break; 187 case 6: 188 ret = offsetof(VexGuestMIPS64State, guest_r6); break; 189 case 7: 190 ret = offsetof(VexGuestMIPS64State, guest_r7); break; 191 case 8: 192 ret = offsetof(VexGuestMIPS64State, guest_r8); break; 193 case 9: 194 ret = offsetof(VexGuestMIPS64State, guest_r9); break; 195 case 10: 196 ret = offsetof(VexGuestMIPS64State, guest_r10); break; 197 case 11: 198 ret = offsetof(VexGuestMIPS64State, guest_r11); break; 199 case 12: 200 ret = offsetof(VexGuestMIPS64State, guest_r12); break; 201 case 13: 202 ret = offsetof(VexGuestMIPS64State, guest_r13); break; 203 case 14: 204 ret = offsetof(VexGuestMIPS64State, guest_r14); break; 205 case 15: 206 ret = offsetof(VexGuestMIPS64State, guest_r15); break; 207 case 16: 208 ret = offsetof(VexGuestMIPS64State, guest_r16); break; 209 case 17: 210 ret = offsetof(VexGuestMIPS64State, guest_r17); break; 211 case 18: 212 ret = offsetof(VexGuestMIPS64State, guest_r18); break; 213 case 19: 214 ret = offsetof(VexGuestMIPS64State, guest_r19); break; 215 case 20: 216 ret = offsetof(VexGuestMIPS64State, guest_r20); break; 217 case 21: 218 ret = offsetof(VexGuestMIPS64State, guest_r21); break; 219 case 22: 220 ret = offsetof(VexGuestMIPS64State, guest_r22); break; 221 case 23: 222 ret = offsetof(VexGuestMIPS64State, guest_r23); break; 223 case 24: 224 ret = offsetof(VexGuestMIPS64State, guest_r24); break; 225 case 25: 226 ret = offsetof(VexGuestMIPS64State, guest_r25); break; 227 case 26: 228 ret = offsetof(VexGuestMIPS64State, guest_r26); break; 229 case 27: 230 ret = offsetof(VexGuestMIPS64State, guest_r27); break; 231 case 28: 232 ret = offsetof(VexGuestMIPS64State, guest_r28); break; 233 case 29: 234 ret = offsetof(VexGuestMIPS64State, guest_r29); break; 235 case 30: 236 ret = offsetof(VexGuestMIPS64State, guest_r30); break; 237 case 31: 238 ret = offsetof(VexGuestMIPS64State, guest_r31); break; 239 default: 240 vassert(0); 241 break; 242 } 243 return ret; 244 } 245 246 #if defined(VGP_mips32_linux) 247 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC) 248 #else 249 #define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC) 250 #endif 251 252 /* ---------------- Floating point registers ---------------- */ 253 254 static UInt floatGuestRegOffset(UInt fregNo) 255 { 256 vassert(fregNo < 32); 257 UInt ret; 258 if (!mode64) 259 switch (fregNo) { 260 case 0: 261 ret = offsetof(VexGuestMIPS32State, guest_f0); break; 262 case 1: 263 ret = offsetof(VexGuestMIPS32State, guest_f1); break; 264 case 2: 265 ret = offsetof(VexGuestMIPS32State, guest_f2); break; 266 case 3: 267 ret = offsetof(VexGuestMIPS32State, guest_f3); break; 268 case 4: 269 ret = offsetof(VexGuestMIPS32State, guest_f4); break; 270 case 5: 271 ret = offsetof(VexGuestMIPS32State, guest_f5); break; 272 case 6: 273 ret = offsetof(VexGuestMIPS32State, guest_f6); break; 274 case 7: 275 ret = offsetof(VexGuestMIPS32State, guest_f7); break; 276 case 8: 277 ret = offsetof(VexGuestMIPS32State, guest_f8); break; 278 case 9: 279 ret = offsetof(VexGuestMIPS32State, guest_f9); break; 280 case 10: 281 ret = offsetof(VexGuestMIPS32State, guest_f10); break; 282 case 11: 283 ret = offsetof(VexGuestMIPS32State, guest_f11); break; 284 case 12: 285 ret = offsetof(VexGuestMIPS32State, guest_f12); break; 286 case 13: 287 ret = offsetof(VexGuestMIPS32State, guest_f13); break; 288 case 14: 289 ret = offsetof(VexGuestMIPS32State, guest_f14); break; 290 case 15: 291 ret = offsetof(VexGuestMIPS32State, guest_f15); break; 292 case 16: 293 ret = offsetof(VexGuestMIPS32State, guest_f16); break; 294 case 17: 295 ret = offsetof(VexGuestMIPS32State, guest_f17); break; 296 case 18: 297 ret = offsetof(VexGuestMIPS32State, guest_f18); break; 298 case 19: 299 ret = offsetof(VexGuestMIPS32State, guest_f19); break; 300 case 20: 301 ret = offsetof(VexGuestMIPS32State, guest_f20); break; 302 case 21: 303 ret = offsetof(VexGuestMIPS32State, guest_f21); break; 304 case 22: 305 ret = offsetof(VexGuestMIPS32State, guest_f22); break; 306 case 23: 307 ret = offsetof(VexGuestMIPS32State, guest_f23); break; 308 case 24: 309 ret = offsetof(VexGuestMIPS32State, guest_f24); break; 310 case 25: 311 ret = offsetof(VexGuestMIPS32State, guest_f25); break; 312 case 26: 313 ret = offsetof(VexGuestMIPS32State, guest_f26); break; 314 case 27: 315 ret = offsetof(VexGuestMIPS32State, guest_f27); break; 316 case 28: 317 ret = offsetof(VexGuestMIPS32State, guest_f28); break; 318 case 29: 319 ret = offsetof(VexGuestMIPS32State, guest_f29); break; 320 case 30: 321 ret = offsetof(VexGuestMIPS32State, guest_f30); break; 322 case 31: 323 ret = offsetof(VexGuestMIPS32State, guest_f31); break; 324 default: 325 vassert(0); 326 break; 327 } 328 else 329 switch (fregNo) { 330 case 0: 331 ret = offsetof(VexGuestMIPS64State, guest_f0); break; 332 case 1: 333 ret = offsetof(VexGuestMIPS64State, guest_f1); break; 334 case 2: 335 ret = offsetof(VexGuestMIPS64State, guest_f2); break; 336 case 3: 337 ret = offsetof(VexGuestMIPS64State, guest_f3); break; 338 case 4: 339 ret = offsetof(VexGuestMIPS64State, guest_f4); break; 340 case 5: 341 ret = offsetof(VexGuestMIPS64State, guest_f5); break; 342 case 6: 343 ret = offsetof(VexGuestMIPS64State, guest_f6); break; 344 case 7: 345 ret = offsetof(VexGuestMIPS64State, guest_f7); break; 346 case 8: 347 ret = offsetof(VexGuestMIPS64State, guest_f8); break; 348 case 9: 349 ret = offsetof(VexGuestMIPS64State, guest_f9); break; 350 case 10: 351 ret = offsetof(VexGuestMIPS64State, guest_f10); break; 352 case 11: 353 ret = offsetof(VexGuestMIPS64State, guest_f11); break; 354 case 12: 355 ret = offsetof(VexGuestMIPS64State, guest_f12); break; 356 case 13: 357 ret = offsetof(VexGuestMIPS64State, guest_f13); break; 358 case 14: 359 ret = offsetof(VexGuestMIPS64State, guest_f14); break; 360 case 15: 361 ret = offsetof(VexGuestMIPS64State, guest_f15); break; 362 case 16: 363 ret = offsetof(VexGuestMIPS64State, guest_f16); break; 364 case 17: 365 ret = offsetof(VexGuestMIPS64State, guest_f17); break; 366 case 18: 367 ret = offsetof(VexGuestMIPS64State, guest_f18); break; 368 case 19: 369 ret = offsetof(VexGuestMIPS64State, guest_f19); break; 370 case 20: 371 ret = offsetof(VexGuestMIPS64State, guest_f20); break; 372 case 21: 373 ret = offsetof(VexGuestMIPS64State, guest_f21); break; 374 case 22: 375 ret = offsetof(VexGuestMIPS64State, guest_f22); break; 376 case 23: 377 ret = offsetof(VexGuestMIPS64State, guest_f23); break; 378 case 24: 379 ret = offsetof(VexGuestMIPS64State, guest_f24); break; 380 case 25: 381 ret = offsetof(VexGuestMIPS64State, guest_f25); break; 382 case 26: 383 ret = offsetof(VexGuestMIPS64State, guest_f26); break; 384 case 27: 385 ret = offsetof(VexGuestMIPS64State, guest_f27); break; 386 case 28: 387 ret = offsetof(VexGuestMIPS64State, guest_f28); break; 388 case 29: 389 ret = offsetof(VexGuestMIPS64State, guest_f29); break; 390 case 30: 391 ret = offsetof(VexGuestMIPS64State, guest_f30); break; 392 case 31: 393 ret = offsetof(VexGuestMIPS64State, guest_f31); break; 394 default: 395 vassert(0); 396 break; 397 } 398 return ret; 399 } 400 401 /* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */ 402 403 static UInt accumulatorGuestRegOffset(UInt acNo) 404 { 405 vassert(!mode64); 406 vassert(acNo <= 3); 407 UInt ret; 408 switch (acNo) { 409 case 0: 410 ret = offsetof(VexGuestMIPS32State, guest_ac0); break; 411 case 1: 412 ret = offsetof(VexGuestMIPS32State, guest_ac1); break; 413 case 2: 414 ret = offsetof(VexGuestMIPS32State, guest_ac2); break; 415 case 3: 416 ret = offsetof(VexGuestMIPS32State, guest_ac3); break; 417 default: 418 vassert(0); 419 break; 420 } 421 return ret; 422 } 423 424 /* Do a endian load of a 32-bit word, regardless of the endianness of the 425 underlying host. */ 426 static inline UInt getUInt(const UChar * p) 427 { 428 UInt w = 0; 429 #if defined (_MIPSEL) 430 w = (w << 8) | p[3]; 431 w = (w << 8) | p[2]; 432 w = (w << 8) | p[1]; 433 w = (w << 8) | p[0]; 434 #elif defined (_MIPSEB) 435 w = (w << 8) | p[0]; 436 w = (w << 8) | p[1]; 437 w = (w << 8) | p[2]; 438 w = (w << 8) | p[3]; 439 #endif 440 return w; 441 } 442 443 #define BITS2(_b1,_b0) \ 444 (((_b1) << 1) | (_b0)) 445 446 #define BITS3(_b2,_b1,_b0) \ 447 (((_b2) << 2) | ((_b1) << 1) | (_b0)) 448 449 #define BITS4(_b3,_b2,_b1,_b0) \ 450 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0)) 451 452 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 453 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0))) 454 455 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \ 456 ((BITS2((_b5),(_b4)) << 4) \ 457 | BITS4((_b3),(_b2),(_b1),(_b0))) 458 459 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \ 460 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \ 461 | BITS4((_b3),(_b2),(_b1),(_b0))) 462 463 #define LOAD_STORE_PATTERN \ 464 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \ 465 if(!mode64) \ 466 assign(t1, binop(Iop_Add32, getIReg(rs), \ 467 mkU32(extend_s_16to32(imm)))); \ 468 else \ 469 assign(t1, binop(Iop_Add64, getIReg(rs), \ 470 mkU64(extend_s_16to64(imm)))); \ 471 472 #define LOADX_STORE_PATTERN \ 473 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \ 474 if(!mode64) \ 475 assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \ 476 else \ 477 assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt))); 478 479 #define LWX_SWX_PATTERN64 \ 480 t2 = newTemp(Ity_I64); \ 481 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \ 482 t4 = newTemp(Ity_I32); \ 483 assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \ 484 mkexpr(t1), mkU64(0x3)))); 485 486 #define LWX_SWX_PATTERN64_1 \ 487 t2 = newTemp(Ity_I64); \ 488 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \ 489 t4 = newTemp(Ity_I64); \ 490 assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 491 492 #define LWX_SWX_PATTERN \ 493 t2 = newTemp(Ity_I32); \ 494 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \ 495 t4 = newTemp(Ity_I32); \ 496 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003))) 497 498 #define SXXV_PATTERN(op) \ 499 putIReg(rd, binop(op, \ 500 getIReg(rt), \ 501 unop(Iop_32to8, \ 502 binop(Iop_And32, \ 503 getIReg(rs), \ 504 mkU32(0x0000001F) \ 505 ) \ 506 ) \ 507 ) \ 508 ) 509 510 #define SXXV_PATTERN64(op) \ 511 putIReg(rd, mkWidenFrom32(ty, binop(op, \ 512 mkNarrowTo32(ty, getIReg(rt)), \ 513 unop(Iop_32to8, \ 514 binop(Iop_And32, \ 515 mkNarrowTo32(ty, getIReg(rs)), \ 516 mkU32(0x0000001F) \ 517 ) \ 518 ) \ 519 ), True \ 520 )) 521 522 #define SXX_PATTERN(op) \ 523 putIReg(rd, binop(op, getIReg(rt), mkU8(sa))); 524 525 #define ALU_PATTERN(op) \ 526 putIReg(rd, binop(op, getIReg(rs), getIReg(rt))); 527 528 #define ALUI_PATTERN(op) \ 529 putIReg(rt, binop(op, getIReg(rs), mkU32(imm))); 530 531 #define ALUI_PATTERN64(op) \ 532 putIReg(rt, binop(op, getIReg(rs), mkU64(imm))); 533 534 #define ALU_PATTERN64(op) \ 535 putIReg(rd, mkWidenFrom32(ty, binop(op, \ 536 mkNarrowTo32(ty, getIReg(rs)), \ 537 mkNarrowTo32(ty, getIReg(rt))), True)); 538 539 #define FP_CONDITIONAL_CODE \ 540 t3 = newTemp(Ity_I32); \ 541 assign(t3, binop(Iop_And32, \ 542 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \ 543 binop(Iop_Shr32, getFCSR(), mkU8(23)), \ 544 binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \ 545 mkU32(0x1))); 546 547 #define ILLEGAL_INSTRUCTON \ 548 putPC(mkU32(guest_PC_curr_instr + 4)); \ 549 dres.jk_StopHere = Ijk_SigILL; \ 550 dres.whatNext = Dis_StopHere; 551 552 /*------------------------------------------------------------*/ 553 /*--- Field helpers ---*/ 554 /*------------------------------------------------------------*/ 555 556 static UInt get_opcode(UInt mipsins) 557 { 558 return (0xFC000000 & mipsins) >> 26; 559 } 560 561 static UInt get_rs(UInt mipsins) 562 { 563 return (0x03E00000 & mipsins) >> 21; 564 } 565 566 static UInt get_rt(UInt mipsins) 567 { 568 return (0x001F0000 & mipsins) >> 16; 569 } 570 571 static UInt get_imm(UInt mipsins) 572 { 573 return (0x0000FFFF & mipsins); 574 } 575 576 static UInt get_instr_index(UInt mipsins) 577 { 578 return (0x03FFFFFF & mipsins); 579 } 580 581 static UInt get_rd(UInt mipsins) 582 { 583 return (0x0000F800 & mipsins) >> 11; 584 } 585 586 static UInt get_sa(UInt mipsins) 587 { 588 return (0x000007C0 & mipsins) >> 6; 589 } 590 591 static UInt get_function(UInt mipsins) 592 { 593 return (0x0000003F & mipsins); 594 } 595 596 static UInt get_ft(UInt mipsins) 597 { 598 return (0x001F0000 & mipsins) >> 16; 599 } 600 601 static UInt get_fs(UInt mipsins) 602 { 603 return (0x0000F800 & mipsins) >> 11; 604 } 605 606 static UInt get_fd(UInt mipsins) 607 { 608 return (0x000007C0 & mipsins) >> 6; 609 } 610 611 static UInt get_mov_cc(UInt mipsins) 612 { 613 return (0x001C0000 & mipsins) >> 18; 614 } 615 616 static UInt get_bc1_cc(UInt mipsins) 617 { 618 return (0x001C0000 & mipsins) >> 18; 619 } 620 621 static UInt get_fpc_cc(UInt mipsins) 622 { 623 return (0x00000700 & mipsins) >> 8; 624 } 625 626 static UInt get_tf(UInt mipsins) 627 { 628 return (0x00010000 & mipsins) >> 16; 629 } 630 631 static UInt get_nd(UInt mipsins) 632 { 633 return (0x00020000 & mipsins) >> 17; 634 } 635 636 static UInt get_fmt(UInt mipsins) 637 { 638 return (0x03E00000 & mipsins) >> 21; 639 } 640 641 static UInt get_FC(UInt mipsins) 642 { 643 return (0x000000F0 & mipsins) >> 4; 644 } 645 646 static UInt get_cond(UInt mipsins) 647 { 648 return (0x0000000F & mipsins); 649 } 650 651 /* for break & syscall */ 652 static UInt get_code(UInt mipsins) 653 { 654 return (0xFFC0 & mipsins) >> 6; 655 } 656 657 static UInt get_lsb(UInt mipsins) 658 { 659 return (0x7C0 & mipsins) >> 6; 660 } 661 662 static UInt get_msb(UInt mipsins) 663 { 664 return (0x0000F800 & mipsins) >> 11; 665 } 666 667 static UInt get_rot(UInt mipsins) 668 { 669 return (0x00200000 & mipsins) >> 21; 670 } 671 672 static UInt get_rotv(UInt mipsins) 673 { 674 return (0x00000040 & mipsins) >> 6; 675 } 676 677 static UInt get_sel(UInt mipsins) 678 { 679 return (0x00000007 & mipsins); 680 } 681 682 /* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them, 683 except for MFHI and MFLO. */ 684 static UInt get_acNo(UInt mipsins) 685 { 686 return (0x00001800 & mipsins) >> 11; 687 } 688 689 /* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */ 690 static UInt get_acNo_mfhilo(UInt mipsins) 691 { 692 return (0x00600000 & mipsins) >> 21; 693 } 694 695 /* Get mask field (helper function for wrdsp instruction). */ 696 static UInt get_wrdspMask(UInt mipsins) 697 { 698 return (0x001ff800 & mipsins) >> 11; 699 } 700 701 /* Get mask field (helper function for rddsp instruction). */ 702 static UInt get_rddspMask(UInt mipsins) 703 { 704 return (0x03ff0000 & mipsins) >> 16; 705 } 706 707 /* Get shift field (helper function for DSP ASE instructions). */ 708 static UInt get_shift(UInt mipsins) 709 { 710 return (0x03f00000 & mipsins) >> 20; 711 } 712 713 /* Get immediate field for DSP ASE instructions. */ 714 static UInt get_dspImm(UInt mipsins) 715 { 716 return (0x03ff0000 & mipsins) >> 16; 717 } 718 719 static Bool branch_or_jump(const UChar * addr) 720 { 721 UInt fmt; 722 UInt cins = getUInt(addr); 723 724 UInt opcode = get_opcode(cins); 725 UInt rt = get_rt(cins); 726 UInt function = get_function(cins); 727 728 /* bgtz, blez, bne, beq, jal */ 729 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04 730 || opcode == 0x03 || opcode == 0x02) { 731 return True; 732 } 733 734 /* bgez */ 735 if (opcode == 0x01 && rt == 0x01) { 736 return True; 737 } 738 739 /* bgezal */ 740 if (opcode == 0x01 && rt == 0x11) { 741 return True; 742 } 743 744 /* bltzal */ 745 if (opcode == 0x01 && rt == 0x10) { 746 return True; 747 } 748 749 /* bltz */ 750 if (opcode == 0x01 && rt == 0x00) { 751 return True; 752 } 753 754 /* jalr */ 755 if (opcode == 0x00 && function == 0x09) { 756 return True; 757 } 758 759 /* jr */ 760 if (opcode == 0x00 && function == 0x08) { 761 return True; 762 } 763 764 if (opcode == 0x11) { 765 /*bc1f & bc1t */ 766 fmt = get_fmt(cins); 767 if (fmt == 0x08) { 768 return True; 769 } 770 } 771 772 /* bposge32 */ 773 if (opcode == 0x01 && rt == 0x1c) { 774 return True; 775 } 776 777 /* Cavium Specific instructions. */ 778 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) { 779 /* BBIT0, BBIT1, BBIT032, BBIT132 */ 780 return True; 781 } 782 783 return False; 784 } 785 786 static Bool is_Branch_or_Jump_and_Link(const UChar * addr) 787 { 788 UInt cins = getUInt(addr); 789 790 UInt opcode = get_opcode(cins); 791 UInt rt = get_rt(cins); 792 UInt function = get_function(cins); 793 794 /* jal */ 795 if (opcode == 0x02) { 796 return True; 797 } 798 799 /* bgezal */ 800 if (opcode == 0x01 && rt == 0x11) { 801 return True; 802 } 803 804 /* bltzal */ 805 if (opcode == 0x01 && rt == 0x10) { 806 return True; 807 } 808 809 /* jalr */ 810 if (opcode == 0x00 && function == 0x09) { 811 return True; 812 } 813 814 return False; 815 } 816 817 static Bool branch_or_link_likely(const UChar * addr) 818 { 819 UInt cins = getUInt(addr); 820 UInt opcode = get_opcode(cins); 821 UInt rt = get_rt(cins); 822 823 /* bgtzl, blezl, bnel, beql */ 824 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14) 825 return True; 826 827 /* bgezl */ 828 if (opcode == 0x01 && rt == 0x03) 829 return True; 830 831 /* bgezall */ 832 if (opcode == 0x01 && rt == 0x13) 833 return True; 834 835 /* bltzall */ 836 if (opcode == 0x01 && rt == 0x12) 837 return True; 838 839 /* bltzl */ 840 if (opcode == 0x01 && rt == 0x02) 841 return True; 842 843 return False; 844 } 845 846 /*------------------------------------------------------------*/ 847 /*--- Helper bits and pieces for creating IR fragments. ---*/ 848 /*------------------------------------------------------------*/ 849 850 static IRExpr *mkU8(UInt i) 851 { 852 vassert(i < 256); 853 return IRExpr_Const(IRConst_U8((UChar) i)); 854 } 855 856 /* Create an expression node for a 16-bit integer constant. */ 857 static IRExpr *mkU16(UInt i) 858 { 859 return IRExpr_Const(IRConst_U16(i)); 860 } 861 862 /* Create an expression node for a 32-bit integer constant. */ 863 static IRExpr *mkU32(UInt i) 864 { 865 return IRExpr_Const(IRConst_U32(i)); 866 } 867 868 /* Create an expression node for a 64-bit integer constant. */ 869 static IRExpr *mkU64(ULong i) 870 { 871 return IRExpr_Const(IRConst_U64(i)); 872 } 873 874 static IRExpr *mkexpr(IRTemp tmp) 875 { 876 return IRExpr_RdTmp(tmp); 877 } 878 879 static IRExpr *unop(IROp op, IRExpr * a) 880 { 881 return IRExpr_Unop(op, a); 882 } 883 884 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2) 885 { 886 return IRExpr_Binop(op, a1, a2); 887 } 888 889 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3) 890 { 891 return IRExpr_Triop(op, a1, a2, a3); 892 } 893 894 static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3, 895 IRExpr * a4 ) 896 { 897 return IRExpr_Qop(op, a1, a2, a3, a4); 898 } 899 900 static IRExpr *load(IRType ty, IRExpr * addr) 901 { 902 IRExpr *load1 = NULL; 903 #if defined (_MIPSEL) 904 load1 = IRExpr_Load(Iend_LE, ty, addr); 905 #elif defined (_MIPSEB) 906 load1 = IRExpr_Load(Iend_BE, ty, addr); 907 #endif 908 return load1; 909 } 910 911 /* Add a statement to the list held by "irsb". */ 912 static void stmt(IRStmt * st) 913 { 914 addStmtToIRSB(irsb, st); 915 } 916 917 static void assign(IRTemp dst, IRExpr * e) 918 { 919 stmt(IRStmt_WrTmp(dst, e)); 920 } 921 922 static void store(IRExpr * addr, IRExpr * data) 923 { 924 #if defined (_MIPSEL) 925 stmt(IRStmt_Store(Iend_LE, addr, data)); 926 #elif defined (_MIPSEB) 927 stmt(IRStmt_Store(Iend_BE, addr, data)); 928 #endif 929 } 930 931 /* Generate a new temporary of the given type. */ 932 static IRTemp newTemp(IRType ty) 933 { 934 vassert(isPlausibleIRType(ty)); 935 return newIRTemp(irsb->tyenv, ty); 936 } 937 938 /* Generate an expression for SRC rotated right by ROT. */ 939 static IRExpr *genROR32(IRExpr * src, Int rot) 940 { 941 vassert(rot >= 0 && rot < 32); 942 if (rot == 0) 943 return src; 944 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)), 945 binop(Iop_Shr32, src, mkU8(rot))); 946 } 947 948 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs) 949 { 950 IRTemp t0 = newTemp(Ity_I8); 951 IRTemp t1 = newTemp(Ity_I8); 952 953 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F)))); 954 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0))); 955 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)), 956 binop(Iop_Shr32, src, mkexpr(t0))); 957 } 958 959 static UShort extend_s_10to16(UInt x) 960 { 961 return (UShort) ((((Int) x) << 22) >> 22); 962 } 963 964 static ULong extend_s_10to32(UInt x) 965 { 966 return (ULong)((((Long) x) << 22) >> 22); 967 } 968 969 static ULong extend_s_10to64(UInt x) 970 { 971 return (ULong)((((Long) x) << 54) >> 54); 972 } 973 974 static UInt extend_s_16to32(UInt x) 975 { 976 return (UInt) ((((Int) x) << 16) >> 16); 977 } 978 979 static UInt extend_s_18to32(UInt x) 980 { 981 return (UInt) ((((Int) x) << 14) >> 14); 982 } 983 984 static ULong extend_s_16to64 ( UInt x ) 985 { 986 return (ULong) ((((Long) x) << 48) >> 48); 987 } 988 989 static ULong extend_s_18to64 ( UInt x ) 990 { 991 return (ULong) ((((Long) x) << 46) >> 46); 992 } 993 994 static ULong extend_s_32to64 ( UInt x ) 995 { 996 return (ULong) ((((Long) x) << 32) >> 32); 997 } 998 999 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 ) 1000 { 1001 vassert(dres->whatNext == Dis_Continue); 1002 vassert(dres->len == 0); 1003 vassert(dres->continueAt == 0); 1004 vassert(dres->jk_StopHere == Ijk_INVALID); 1005 dres->whatNext = Dis_StopHere; 1006 dres->jk_StopHere = kind; 1007 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) ); 1008 } 1009 1010 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 ) 1011 { 1012 vassert(dres->whatNext == Dis_Continue); 1013 vassert(dres->len == 0); 1014 vassert(dres->continueAt == 0); 1015 vassert(dres->jk_StopHere == Ijk_INVALID); 1016 dres->whatNext = Dis_StopHere; 1017 dres->jk_StopHere = kind; 1018 stmt(IRStmt_Put(OFFB_PC, mkU64(d64))); 1019 } 1020 1021 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions). 1022 This function should be called before any other operation if widening 1023 multiplications are used. */ 1024 static IRExpr *getAcc(UInt acNo) 1025 { 1026 vassert(!mode64); 1027 vassert(acNo <= 3); 1028 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64); 1029 } 1030 1031 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE 1032 instructions). */ 1033 static IRExpr *getDSPControl(void) 1034 { 1035 vassert(!mode64); 1036 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32); 1037 } 1038 1039 /* Put value to DSPControl register. Expression e is written to DSPControl as 1040 is. If only certain bits of DSPControl need to be changed, it should be done 1041 before calling putDSPControl(). It could be done by reading DSPControl and 1042 ORing it with appropriate mask. */ 1043 static void putDSPControl(IRExpr * e) 1044 { 1045 vassert(!mode64); 1046 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e)); 1047 } 1048 1049 /* Fetch a byte from the guest insn stream. */ 1050 static UChar getIByte(Int delta) 1051 { 1052 return guest_code[delta]; 1053 } 1054 1055 static IRExpr *getIReg(UInt iregNo) 1056 { 1057 if (0 == iregNo) { 1058 return mode64 ? mkU64(0x0) : mkU32(0x0); 1059 } else { 1060 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1061 vassert(iregNo < 32); 1062 return IRExpr_Get(integerGuestRegOffset(iregNo), ty); 1063 } 1064 } 1065 1066 static IRExpr *getHI(void) 1067 { 1068 if (mode64) 1069 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64); 1070 else 1071 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32); 1072 } 1073 1074 static IRExpr *getLO(void) 1075 { 1076 if (mode64) 1077 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64); 1078 else 1079 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32); 1080 } 1081 1082 static IRExpr *getFCSR(void) 1083 { 1084 if (mode64) 1085 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32); 1086 else 1087 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32); 1088 } 1089 1090 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */ 1091 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos) 1092 { 1093 UInt pos = byte_pos * 8; 1094 if (mode64) 1095 return unop(Iop_64to8, binop(Iop_And64, 1096 binop(Iop_Shr64, getIReg(reg), mkU8(pos)), 1097 mkU64(0xFF))); 1098 else 1099 return unop(Iop_32to8, binop(Iop_And32, 1100 binop(Iop_Shr32, getIReg(reg), mkU8(pos)), 1101 mkU32(0xFF))); 1102 } 1103 1104 static void putFCSR(IRExpr * e) 1105 { 1106 if (mode64) 1107 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e)); 1108 else 1109 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e)); 1110 } 1111 1112 /* fs - fpu source register number. 1113 inst - fpu instruction that needs to be executed. 1114 sz32 - size of source register. 1115 opN - number of operads: 1116 1 - unary operation. 1117 2 - binary operation. */ 1118 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN) 1119 { 1120 IRDirty *d; 1121 IRTemp fcsr = newTemp(Ity_I32); 1122 /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */ 1123 if (fp_mode64) 1124 d = unsafeIRDirty_1_N(fcsr, 0, 1125 "mips_dirtyhelper_calculate_FCSR_fp64", 1126 &mips_dirtyhelper_calculate_FCSR_fp64, 1127 mkIRExprVec_4(IRExpr_BBPTR(), 1128 mkU32(fs), 1129 mkU32(ft), 1130 mkU32(inst))); 1131 else 1132 d = unsafeIRDirty_1_N(fcsr, 0, 1133 "mips_dirtyhelper_calculate_FCSR_fp32", 1134 &mips_dirtyhelper_calculate_FCSR_fp32, 1135 mkIRExprVec_4(IRExpr_BBPTR(), 1136 mkU32(fs), 1137 mkU32(ft), 1138 mkU32(inst))); 1139 1140 if (opN == 1) { /* Unary operation. */ 1141 /* Declare we're reading guest state. */ 1142 if (sz32 || fp_mode64) 1143 d->nFxState = 2; 1144 else 1145 d->nFxState = 3; 1146 vex_bzero(&d->fxState, sizeof(d->fxState)); 1147 1148 d->fxState[0].fx = Ifx_Read; /* read */ 1149 if (mode64) 1150 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1151 else 1152 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1153 d->fxState[0].size = sizeof(UInt); 1154 d->fxState[1].fx = Ifx_Read; /* read */ 1155 d->fxState[1].offset = floatGuestRegOffset(fs); 1156 d->fxState[1].size = sizeof(ULong); 1157 1158 if (!(sz32 || fp_mode64)) { 1159 d->fxState[2].fx = Ifx_Read; /* read */ 1160 d->fxState[2].offset = floatGuestRegOffset(fs+1); 1161 d->fxState[2].size = sizeof(ULong); 1162 } 1163 } else if (opN == 2) { /* Binary operation. */ 1164 /* Declare we're reading guest state. */ 1165 if (sz32 || fp_mode64) 1166 d->nFxState = 3; 1167 else 1168 d->nFxState = 5; 1169 vex_bzero(&d->fxState, sizeof(d->fxState)); 1170 1171 d->fxState[0].fx = Ifx_Read; /* read */ 1172 if (mode64) 1173 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1174 else 1175 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1176 d->fxState[0].size = sizeof(UInt); 1177 d->fxState[1].fx = Ifx_Read; /* read */ 1178 d->fxState[1].offset = floatGuestRegOffset(fs); 1179 d->fxState[1].size = sizeof(ULong); 1180 d->fxState[2].fx = Ifx_Read; /* read */ 1181 d->fxState[2].offset = floatGuestRegOffset(ft); 1182 d->fxState[2].size = sizeof(ULong); 1183 1184 if (!(sz32 || fp_mode64)) { 1185 d->fxState[3].fx = Ifx_Read; /* read */ 1186 d->fxState[3].offset = floatGuestRegOffset(fs+1); 1187 d->fxState[3].size = sizeof(ULong); 1188 d->fxState[4].fx = Ifx_Read; /* read */ 1189 d->fxState[4].offset = floatGuestRegOffset(ft+1); 1190 d->fxState[4].size = sizeof(ULong); 1191 } 1192 } 1193 1194 stmt(IRStmt_Dirty(d)); 1195 1196 putFCSR(mkexpr(fcsr)); 1197 } 1198 1199 static IRExpr *getULR(void) 1200 { 1201 if (mode64) 1202 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64); 1203 else 1204 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32); 1205 } 1206 1207 static void putIReg(UInt archreg, IRExpr * e) 1208 { 1209 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1210 vassert(archreg < 32); 1211 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1212 if (archreg != 0) 1213 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e)); 1214 } 1215 1216 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src) 1217 { 1218 vassert(ty == Ity_I32 || ty == Ity_I64); 1219 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1220 } 1221 1222 static void putLO(IRExpr * e) 1223 { 1224 if (mode64) { 1225 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e)); 1226 } else { 1227 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e)); 1228 /* Add value to lower 32 bits of ac0 to maintain compatibility between 1229 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits 1230 unchanged. */ 1231 IRTemp t_lo = newTemp(Ity_I32); 1232 IRTemp t_hi = newTemp(Ity_I32); 1233 assign(t_lo, e); 1234 assign(t_hi, unop(Iop_64HIto32, getAcc(0))); 1235 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1236 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1237 } 1238 } 1239 1240 static void putHI(IRExpr * e) 1241 { 1242 if (mode64) { 1243 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e)); 1244 } else { 1245 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e)); 1246 /* Add value to higher 32 bits of ac0 to maintain compatibility between 1247 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits 1248 unchanged. */ 1249 IRTemp t_lo = newTemp(Ity_I32); 1250 IRTemp t_hi = newTemp(Ity_I32); 1251 assign(t_hi, e); 1252 assign(t_lo, unop(Iop_64to32, getAcc(0))); 1253 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1254 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1255 } 1256 } 1257 1258 /* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */ 1259 static void putAcc(UInt acNo, IRExpr * e) 1260 { 1261 vassert(!mode64); 1262 vassert(acNo <= 3); 1263 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64); 1264 stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e)); 1265 /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility 1266 between MIPS32 and MIPS DSP ASE insn sets. */ 1267 if (0 == acNo) { 1268 putLO(unop(Iop_64to32, e)); 1269 putHI(unop(Iop_64HIto32, e)); 1270 } 1271 } 1272 1273 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src ) 1274 { 1275 vassert(ty == Ity_I32 || ty == Ity_I64); 1276 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1277 } 1278 1279 static void putPC(IRExpr * e) 1280 { 1281 stmt(IRStmt_Put(OFFB_PC, e)); 1282 } 1283 1284 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined) 1285 { 1286 vassert(ty == Ity_I32 || ty == Ity_I64); 1287 if (ty == Ity_I32) 1288 return src; 1289 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1290 } 1291 1292 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some 1293 of these combinations make sense. */ 1294 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e) 1295 { 1296 IRType src_ty = typeOfIRExpr(irsb->tyenv, e); 1297 if (src_ty == dst_ty) 1298 return e; 1299 if (src_ty == Ity_I32 && dst_ty == Ity_I16) 1300 return unop(Iop_32to16, e); 1301 if (src_ty == Ity_I32 && dst_ty == Ity_I8) 1302 return unop(Iop_32to8, e); 1303 if (src_ty == Ity_I64 && dst_ty == Ity_I8) { 1304 vassert(mode64); 1305 return unop(Iop_64to8, e); 1306 } 1307 if (src_ty == Ity_I64 && dst_ty == Ity_I16) { 1308 vassert(mode64); 1309 return unop(Iop_64to16, e); 1310 } 1311 vpanic("narrowTo(mips)"); 1312 return 0; 1313 } 1314 1315 static IRExpr *getLoFromF64(IRType ty, IRExpr * src) 1316 { 1317 vassert(ty == Ity_F32 || ty == Ity_F64); 1318 if (ty == Ity_F64) { 1319 IRTemp t0, t1; 1320 t0 = newTemp(Ity_I64); 1321 t1 = newTemp(Ity_I32); 1322 assign(t0, unop(Iop_ReinterpF64asI64, src)); 1323 assign(t1, unop(Iop_64to32, mkexpr(t0))); 1324 return unop(Iop_ReinterpI32asF32, mkexpr(t1)); 1325 } else 1326 return src; 1327 } 1328 1329 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src) 1330 { 1331 vassert(ty == Ity_F32 || ty == Ity_F64); 1332 if (ty == Ity_F64) { 1333 IRTemp t0 = newTemp(Ity_I32); 1334 IRTemp t1 = newTemp(Ity_I64); 1335 assign(t0, unop(Iop_ReinterpF32asI32, src)); 1336 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0))); 1337 return unop(Iop_ReinterpI64asF64, mkexpr(t1)); 1338 } else 1339 return src; 1340 } 1341 1342 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm) 1343 { 1344 ULong branch_offset; 1345 IRTemp t0; 1346 1347 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1348 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1349 is added to the address of the instruction following 1350 the branch (not the branch itself), in the branch delay slot, to form 1351 a PC-relative effective target address. */ 1352 if (mode64) 1353 branch_offset = extend_s_18to64(imm << 2); 1354 else 1355 branch_offset = extend_s_18to32(imm << 2); 1356 1357 t0 = newTemp(Ity_I1); 1358 assign(t0, guard); 1359 1360 if (mode64) 1361 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1362 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC)); 1363 else 1364 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1365 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC)); 1366 1367 irsb->jumpkind = Ijk_Boring; 1368 1369 if (mode64) 1370 return mkU64(guest_PC_curr_instr + 4 + branch_offset); 1371 else 1372 return mkU32(guest_PC_curr_instr + 4 + branch_offset); 1373 } 1374 1375 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set) 1376 { 1377 ULong branch_offset; 1378 IRTemp t0; 1379 1380 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */ 1381 if (mode64) 1382 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 1383 else 1384 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 1385 } 1386 1387 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1388 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1389 is added to the address of the instruction following 1390 the branch (not the branch itself), in the branch delay slot, to form 1391 a PC-relative effective target address. */ 1392 1393 if (mode64) 1394 branch_offset = extend_s_18to64(imm << 2); 1395 else 1396 branch_offset = extend_s_18to32(imm << 2); 1397 1398 t0 = newTemp(Ity_I1); 1399 assign(t0, guard); 1400 if (mode64) 1401 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1402 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset), 1403 OFFB_PC); 1404 else 1405 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1406 IRConst_U32(guest_PC_curr_instr + 4 + 1407 (UInt) branch_offset), OFFB_PC); 1408 } 1409 1410 static IRExpr *getFReg(UInt fregNo) 1411 { 1412 vassert(fregNo < 32); 1413 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1414 return IRExpr_Get(floatGuestRegOffset(fregNo), ty); 1415 } 1416 1417 static IRExpr *getDReg(UInt dregNo) 1418 { 1419 vassert(dregNo < 32); 1420 if (fp_mode64) { 1421 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64); 1422 } else { 1423 /* Read a floating point register pair and combine their contents into a 1424 64-bit value */ 1425 IRTemp t0 = newTemp(Ity_F32); 1426 IRTemp t1 = newTemp(Ity_F32); 1427 IRTemp t2 = newTemp(Ity_F64); 1428 IRTemp t3 = newTemp(Ity_I32); 1429 IRTemp t4 = newTemp(Ity_I32); 1430 IRTemp t5 = newTemp(Ity_I64); 1431 1432 assign(t0, getFReg(dregNo)); 1433 assign(t1, getFReg(dregNo + 1)); 1434 1435 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); 1436 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); 1437 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3))); 1438 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5))); 1439 1440 return mkexpr(t2); 1441 } 1442 } 1443 1444 static void putFReg(UInt dregNo, IRExpr * e) 1445 { 1446 vassert(dregNo < 32); 1447 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1448 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1449 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1450 } 1451 1452 static void putDReg(UInt dregNo, IRExpr * e) 1453 { 1454 if (fp_mode64) { 1455 vassert(dregNo < 32); 1456 IRType ty = Ity_F64; 1457 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1458 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1459 } else { 1460 vassert(dregNo < 32); 1461 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1462 IRTemp t1 = newTemp(Ity_F64); 1463 IRTemp t4 = newTemp(Ity_I32); 1464 IRTemp t5 = newTemp(Ity_I32); 1465 IRTemp t6 = newTemp(Ity_I64); 1466 assign(t1, e); 1467 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1))); 1468 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */ 1469 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */ 1470 putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5))); 1471 putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); 1472 } 1473 } 1474 1475 static void setFPUCondCode(IRExpr * e, UInt cc) 1476 { 1477 if (cc == 0) { 1478 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF))); 1479 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23)))); 1480 } else { 1481 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32, 1482 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc))))); 1483 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc)))); 1484 } 1485 } 1486 1487 static IRExpr* get_IR_roundingmode ( void ) 1488 { 1489 /* 1490 rounding mode | MIPS | IR 1491 ------------------------ 1492 to nearest | 00 | 00 1493 to zero | 01 | 11 1494 to +infinity | 10 | 10 1495 to -infinity | 11 | 01 1496 */ 1497 IRTemp rm_MIPS = newTemp(Ity_I32); 1498 /* Last two bits in FCSR are rounding mode. */ 1499 1500 if (mode64) 1501 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State, 1502 guest_FCSR), Ity_I32), mkU32(3))); 1503 else 1504 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State, 1505 guest_FCSR), Ity_I32), mkU32(3))); 1506 1507 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */ 1508 1509 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32, 1510 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2))); 1511 } 1512 1513 /* sz, ULong -> IRExpr */ 1514 static IRExpr *mkSzImm ( IRType ty, ULong imm64 ) 1515 { 1516 vassert(ty == Ity_I32 || ty == Ity_I64); 1517 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64); 1518 } 1519 1520 static IRConst *mkSzConst ( IRType ty, ULong imm64 ) 1521 { 1522 vassert(ty == Ity_I32 || ty == Ity_I64); 1523 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64)); 1524 } 1525 1526 /* Make sure we get valid 32 and 64bit addresses */ 1527 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1528 { 1529 vassert(ty == Ity_I32 || ty == Ity_I64); 1530 return (ty == Ity_I64 ? (Addr64) addr : 1531 (Addr64) extend_s_32to64(toUInt(addr))); 1532 } 1533 1534 /* Shift and Rotate instructions for MIPS64 */ 1535 static Bool dis_instr_shrt ( UInt theInstr ) 1536 { 1537 UInt opc2 = get_function(theInstr); 1538 UChar regRs = get_rs(theInstr); 1539 UChar regRt = get_rt(theInstr); 1540 UChar regRd = get_rd(theInstr); 1541 UChar uImmsa = get_sa(theInstr); 1542 Long sImmsa = extend_s_16to64(uImmsa); 1543 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1544 IRTemp tmp = newTemp(ty); 1545 IRTemp tmpOr = newTemp(ty); 1546 IRTemp tmpRt = newTemp(ty); 1547 IRTemp tmpRs = newTemp(ty); 1548 IRTemp tmpRd = newTemp(ty); 1549 1550 assign(tmpRs, getIReg(regRs)); 1551 assign(tmpRt, getIReg(regRt)); 1552 1553 switch (opc2) { 1554 case 0x3A: 1555 if ((regRs & 0x01) == 0) { 1556 /* Doubleword Shift Right Logical - DSRL; MIPS64 */ 1557 DIP("dsrl r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1558 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1559 putIReg(regRd, mkexpr(tmpRd)); 1560 } else if ((regRs & 0x01) == 1) { 1561 /* Doubleword Rotate Right - DROTR; MIPS64r2 */ 1562 vassert(mode64); 1563 DIP("drotr r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1564 IRTemp tmpL = newTemp(ty); 1565 IRTemp tmpR = newTemp(ty); 1566 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1567 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa))); 1568 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1569 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1570 putIReg(regRd, mkexpr(tmpRd)); 1571 } else 1572 return False; 1573 break; 1574 1575 case 0x3E: 1576 if ((regRs & 0x01) == 0) { 1577 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */ 1578 DIP("dsrl32 r%u, r%u, %d", regRd, regRt, (Int)(sImmsa + 32)); 1579 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1580 putIReg(regRd, mkexpr(tmpRd)); 1581 } else if ((regRs & 0x01) == 1) { 1582 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */ 1583 DIP("drotr32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1584 vassert(mode64); 1585 IRTemp tmpL = newTemp(ty); 1586 IRTemp tmpR = newTemp(ty); 1587 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */ 1588 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1589 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), 1590 mkU8(63 - (uImmsa + 32)))); 1591 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1592 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1593 putIReg(regRd, mkexpr(tmpRd)); 1594 } else 1595 return False; 1596 break; 1597 1598 case 0x16: 1599 if ((uImmsa & 0x01) == 0) { 1600 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */ 1601 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs); 1602 IRTemp tmpRs8 = newTemp(Ity_I8); 1603 /* s = tmpRs[5..0] */ 1604 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63))); 1605 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1606 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1607 putIReg(regRd, mkexpr(tmpRd)); 1608 } else if ((uImmsa & 0x01) == 1) { 1609 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */ 1610 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs); 1611 IRTemp tmpL = newTemp(ty); 1612 IRTemp tmpR = newTemp(ty); 1613 IRTemp tmpRs8 = newTemp(Ity_I8); 1614 IRTemp tmpLs8 = newTemp(Ity_I8); 1615 IRTemp tmp64 = newTemp(ty); 1616 /* s = tmpRs[5...0] 1617 m = 64 - s 1618 (tmpRt << s) | (tmpRt >> m) */ 1619 1620 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1621 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64))); 1622 1623 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp))); 1624 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64))); 1625 1626 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1627 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8))); 1628 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1))); 1629 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR))); 1630 1631 putIReg(regRd, mkexpr(tmpOr)); 1632 } else 1633 return False; 1634 break; 1635 1636 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */ 1637 DIP("dsll r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1638 vassert(mode64); 1639 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa))); 1640 putIReg(regRd, mkexpr(tmpRd)); 1641 break; 1642 1643 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */ 1644 DIP("dsll32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1645 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1646 putIReg(regRd, mkexpr(tmpRd)); 1647 break; 1648 1649 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */ 1650 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs); 1651 IRTemp tmpRs8 = newTemp(Ity_I8); 1652 1653 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1654 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1655 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1656 putIReg(regRd, mkexpr(tmpRd)); 1657 break; 1658 } 1659 1660 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */ 1661 DIP("dsra r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1662 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa))); 1663 putIReg(regRd, mkexpr(tmpRd)); 1664 break; 1665 1666 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32; 1667 MIPS64 */ 1668 DIP("dsra32 r%u, r%u, %d", regRd, regRt, (Int)sImmsa); 1669 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1670 putIReg(regRd, mkexpr(tmpRd)); 1671 break; 1672 1673 case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV; 1674 MIPS64 */ 1675 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs); 1676 IRTemp tmpRs8 = newTemp(Ity_I8); 1677 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1678 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1679 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1680 putIReg(regRd, mkexpr(tmpRd)); 1681 break; 1682 1683 } 1684 1685 default: 1686 return False; 1687 1688 } 1689 return True; 1690 } 1691 1692 static IROp mkSzOp ( IRType ty, IROp op8 ) 1693 { 1694 Int adj; 1695 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64); 1696 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 1697 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 1698 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 1699 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8); 1700 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3)); 1701 return adj + op8; 1702 } 1703 1704 /*********************************************************/ 1705 /*--- Floating Point Compare ---*/ 1706 /*********************************************************/ 1707 /* Function that returns a string that represent mips cond 1708 mnemonic for the input code. */ 1709 static const HChar* showCondCode(UInt code) { 1710 const HChar* ret; 1711 switch (code) { 1712 case 0: ret = "f"; break; 1713 case 1: ret = "un"; break; 1714 case 2: ret = "eq"; break; 1715 case 3: ret = "ueq"; break; 1716 case 4: ret = "olt"; break; 1717 case 5: ret = "ult"; break; 1718 case 6: ret = "ole"; break; 1719 case 7: ret = "ule"; break; 1720 case 8: ret = "sf"; break; 1721 case 9: ret = "ngle"; break; 1722 case 10: ret = "seq"; break; 1723 case 11: ret = "ngl"; break; 1724 case 12: ret = "lt"; break; 1725 case 13: ret = "nge"; break; 1726 case 14: ret = "le"; break; 1727 case 15: ret = "ngt"; break; 1728 default: vpanic("showCondCode"); break; 1729 } 1730 return ret; 1731 } 1732 1733 static Bool dis_instr_CCondFmt ( UInt cins ) 1734 { 1735 IRTemp t0, t1, t2, t3, tmp5, tmp6; 1736 IRTemp ccIR = newTemp(Ity_I32); 1737 IRTemp ccMIPS = newTemp(Ity_I32); 1738 UInt FC = get_FC(cins); 1739 UInt fmt = get_fmt(cins); 1740 UInt fs = get_fs(cins); 1741 UInt ft = get_ft(cins); 1742 UInt cond = get_cond(cins); 1743 1744 if (FC == 0x3) { /* C.cond.fmt */ 1745 UInt fpc_cc = get_fpc_cc(cins); 1746 switch (fmt) { 1747 case 0x10: { /* C.cond.S */ 1748 DIP("c.%s.s %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft); 1749 if (fp_mode64) { 1750 t0 = newTemp(Ity_I32); 1751 t1 = newTemp(Ity_I32); 1752 t2 = newTemp(Ity_I32); 1753 t3 = newTemp(Ity_I32); 1754 1755 tmp5 = newTemp(Ity_F64); 1756 tmp6 = newTemp(Ity_F64); 1757 1758 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1759 getFReg(fs)))); 1760 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1761 getFReg(ft)))); 1762 1763 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6))); 1764 putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1765 mkexpr(ccIR), True)); 1766 /* Map compare result from IR to MIPS 1767 FP cmp result | MIPS | IR 1768 -------------------------- 1769 UN | 0x1 | 0x45 1770 EQ | 0x2 | 0x40 1771 GT | 0x4 | 0x00 1772 LT | 0x8 | 0x01 1773 */ 1774 1775 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1776 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1777 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1778 binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)), 1779 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1780 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1781 mkU32(1)))))); 1782 putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1783 mkexpr(ccMIPS), True)); 1784 1785 /* UN */ 1786 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1787 /* EQ */ 1788 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1789 mkU8(0x1)), mkU32(0x1))); 1790 /* NGT */ 1791 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1792 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1))); 1793 /* LT */ 1794 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1795 mkU8(0x3)), mkU32(0x1))); 1796 switch (cond) { 1797 case 0x0: 1798 setFPUCondCode(mkU32(0), fpc_cc); 1799 break; 1800 case 0x1: 1801 setFPUCondCode(mkexpr(t0), fpc_cc); 1802 break; 1803 case 0x2: 1804 setFPUCondCode(mkexpr(t1), fpc_cc); 1805 break; 1806 case 0x3: 1807 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1808 fpc_cc); 1809 break; 1810 case 0x4: 1811 setFPUCondCode(mkexpr(t3), fpc_cc); 1812 break; 1813 case 0x5: 1814 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1815 fpc_cc); 1816 break; 1817 case 0x6: 1818 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1819 fpc_cc); 1820 break; 1821 case 0x7: 1822 setFPUCondCode(mkexpr(t2), fpc_cc); 1823 break; 1824 case 0x8: 1825 setFPUCondCode(mkU32(0), fpc_cc); 1826 break; 1827 case 0x9: 1828 setFPUCondCode(mkexpr(t0), fpc_cc); 1829 break; 1830 case 0xA: 1831 setFPUCondCode(mkexpr(t1), fpc_cc); 1832 break; 1833 case 0xB: 1834 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1835 fpc_cc); 1836 break; 1837 case 0xC: 1838 setFPUCondCode(mkexpr(t3), fpc_cc); 1839 break; 1840 case 0xD: 1841 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1842 fpc_cc); 1843 break; 1844 case 0xE: 1845 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1846 fpc_cc); 1847 break; 1848 case 0xF: 1849 setFPUCondCode(mkexpr(t2), fpc_cc); 1850 break; 1851 1852 default: 1853 return False; 1854 } 1855 1856 } else { 1857 t0 = newTemp(Ity_I32); 1858 t1 = newTemp(Ity_I32); 1859 t2 = newTemp(Ity_I32); 1860 t3 = newTemp(Ity_I32); 1861 1862 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)), 1863 unop(Iop_F32toF64, getFReg(ft)))); 1864 /* Map compare result from IR to MIPS 1865 FP cmp result | MIPS | IR 1866 -------------------------- 1867 UN | 0x1 | 0x45 1868 EQ | 0x2 | 0x40 1869 GT | 0x4 | 0x00 1870 LT | 0x8 | 0x01 1871 */ 1872 1873 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1874 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1875 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1876 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), 1877 mkU32(2)), binop(Iop_And32, 1878 binop(Iop_Xor32, mkexpr(ccIR), 1879 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1880 mkU32(1)))))); 1881 /* UN */ 1882 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1883 /* EQ */ 1884 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1885 mkU8(0x1)), mkU32(0x1))); 1886 /* NGT */ 1887 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1888 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 1889 /* LT */ 1890 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1891 mkU8(0x3)), mkU32(0x1))); 1892 1893 switch (cond) { 1894 case 0x0: 1895 setFPUCondCode(mkU32(0), fpc_cc); 1896 break; 1897 case 0x1: 1898 setFPUCondCode(mkexpr(t0), fpc_cc); 1899 break; 1900 case 0x2: 1901 setFPUCondCode(mkexpr(t1), fpc_cc); 1902 break; 1903 case 0x3: 1904 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1905 fpc_cc); 1906 break; 1907 case 0x4: 1908 setFPUCondCode(mkexpr(t3), fpc_cc); 1909 break; 1910 case 0x5: 1911 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1912 fpc_cc); 1913 break; 1914 case 0x6: 1915 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1916 fpc_cc); 1917 break; 1918 case 0x7: 1919 setFPUCondCode(mkexpr(t2), fpc_cc); 1920 break; 1921 case 0x8: 1922 setFPUCondCode(mkU32(0), fpc_cc); 1923 break; 1924 case 0x9: 1925 setFPUCondCode(mkexpr(t0), fpc_cc); 1926 break; 1927 case 0xA: 1928 setFPUCondCode(mkexpr(t1), fpc_cc); 1929 break; 1930 case 0xB: 1931 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1932 fpc_cc); 1933 break; 1934 case 0xC: 1935 setFPUCondCode(mkexpr(t3), fpc_cc); 1936 break; 1937 case 0xD: 1938 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1939 fpc_cc); 1940 break; 1941 case 0xE: 1942 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1943 fpc_cc); 1944 break; 1945 case 0xF: 1946 setFPUCondCode(mkexpr(t2), fpc_cc); 1947 break; 1948 1949 default: 1950 return False; 1951 } 1952 } 1953 } 1954 break; 1955 1956 case 0x11: { /* C.cond.D */ 1957 DIP("c.%s.d %d, f%d, f%d", showCondCode(cond), fpc_cc, fs, ft); 1958 t0 = newTemp(Ity_I32); 1959 t1 = newTemp(Ity_I32); 1960 t2 = newTemp(Ity_I32); 1961 t3 = newTemp(Ity_I32); 1962 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); 1963 /* Map compare result from IR to MIPS 1964 FP cmp result | MIPS | IR 1965 -------------------------- 1966 UN | 0x1 | 0x45 1967 EQ | 0x2 | 0x40 1968 GT | 0x4 | 0x00 1969 LT | 0x8 | 0x01 1970 */ 1971 1972 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1973 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1974 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1975 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)), 1976 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1977 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1978 mkU32(1)))))); 1979 1980 /* UN */ 1981 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1982 /* EQ */ 1983 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1984 mkU8(0x1)), mkU32(0x1))); 1985 /* NGT */ 1986 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1987 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 1988 /* LT */ 1989 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1990 mkU8(0x3)), mkU32(0x1))); 1991 1992 switch (cond) { 1993 case 0x0: 1994 setFPUCondCode(mkU32(0), fpc_cc); 1995 break; 1996 case 0x1: 1997 setFPUCondCode(mkexpr(t0), fpc_cc); 1998 break; 1999 case 0x2: 2000 setFPUCondCode(mkexpr(t1), fpc_cc); 2001 break; 2002 case 0x3: 2003 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2004 fpc_cc); 2005 break; 2006 case 0x4: 2007 setFPUCondCode(mkexpr(t3), fpc_cc); 2008 break; 2009 case 0x5: 2010 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2011 fpc_cc); 2012 break; 2013 case 0x6: 2014 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2015 fpc_cc); 2016 break; 2017 case 0x7: 2018 setFPUCondCode(mkexpr(t2), fpc_cc); 2019 break; 2020 case 0x8: 2021 setFPUCondCode(mkU32(0), fpc_cc); 2022 break; 2023 case 0x9: 2024 setFPUCondCode(mkexpr(t0), fpc_cc); 2025 break; 2026 case 0xA: 2027 setFPUCondCode(mkexpr(t1), fpc_cc); 2028 break; 2029 case 0xB: 2030 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2031 fpc_cc); 2032 break; 2033 case 0xC: 2034 setFPUCondCode(mkexpr(t3), fpc_cc); 2035 break; 2036 case 0xD: 2037 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2038 fpc_cc); 2039 break; 2040 case 0xE: 2041 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2042 fpc_cc); 2043 break; 2044 case 0xF: 2045 setFPUCondCode(mkexpr(t2), fpc_cc); 2046 break; 2047 default: 2048 return False; 2049 } 2050 } 2051 break; 2052 2053 default: 2054 return False; 2055 } 2056 } else { 2057 return False; 2058 } 2059 2060 return True; 2061 } 2062 2063 /*********************************************************/ 2064 /*--- Branch Instructions for mips64 ---*/ 2065 /*********************************************************/ 2066 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres, 2067 Bool(*resteerOkFn) (void *, Addr), 2068 void *callback_opaque, IRStmt ** set ) 2069 { 2070 UInt jmpKind = 0; 2071 UChar opc1 = get_opcode(theInstr); 2072 UChar regRs = get_rs(theInstr); 2073 UChar regRt = get_rt(theInstr); 2074 UInt offset = get_imm(theInstr); 2075 Long sOffset = extend_s_16to64(offset); 2076 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2077 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S; 2078 2079 IRTemp tmp = newTemp(ty); 2080 IRTemp tmpRs = newTemp(ty); 2081 IRTemp tmpRt = newTemp(ty); 2082 IRTemp tmpLt = newTemp(ty); 2083 IRTemp tmpReg0 = newTemp(ty); 2084 2085 UChar regLnk = 31; /* reg 31 is link reg in MIPS */ 2086 Addr64 addrTgt = 0; 2087 Addr64 cia = guest_PC_curr_instr; 2088 2089 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0); 2090 IRExpr *eNia = mkSzImm(ty, cia + 8); 2091 IRExpr *eCond = NULL; 2092 2093 assign(tmpRs, getIReg(regRs)); 2094 assign(tmpRt, getIReg(regRt)); 2095 assign(tmpReg0, getIReg(0)); 2096 2097 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0)); 2098 2099 switch (opc1) { 2100 case 0x01: 2101 switch (regRt) { 2102 case 0x00: { /* BLTZ rs, offset */ 2103 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2104 IRTemp tmpLtRes = newTemp(Ity_I1); 2105 2106 assign(tmp, eConst0); 2107 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2108 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2109 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2110 2111 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt), 2112 mkexpr(tmpReg0)); 2113 2114 jmpKind = Ijk_Boring; 2115 break; 2116 } 2117 2118 case 0x01: { /* BGEZ rs, offset */ 2119 IRTemp tmpLtRes = newTemp(Ity_I1); 2120 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2121 2122 assign(tmp, eConst0); 2123 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2124 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2125 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2126 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2127 mkexpr(tmpReg0)); 2128 2129 jmpKind = Ijk_Boring; 2130 break; 2131 } 2132 2133 case 0x11: { /* BGEZAL rs, offset */ 2134 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2135 putIReg(regLnk, eNia); 2136 IRTemp tmpLtRes = newTemp(Ity_I1); 2137 2138 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0)); 2139 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2140 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2141 2142 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2143 mkexpr(tmpReg0)); 2144 2145 jmpKind = Ijk_Call; 2146 break; 2147 } 2148 2149 case 0x10: { /* BLTZAL rs, offset */ 2150 IRTemp tmpLtRes = newTemp(Ity_I1); 2151 IRTemp tmpRes = newTemp(ty); 2152 2153 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2154 putIReg(regLnk, eNia); 2155 2156 assign(tmp, eConst0); 2157 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2158 assign(tmpRes, mode64 ? unop(Iop_1Uto64, 2159 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2160 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes), 2161 mkexpr(tmpReg0)); 2162 2163 jmpKind = Ijk_Call; 2164 break; 2165 } 2166 2167 } 2168 break; 2169 default: 2170 return False; 2171 } 2172 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC); 2173 return True; 2174 } 2175 2176 /*********************************************************/ 2177 /*--- Cavium Specific Instructions ---*/ 2178 /*********************************************************/ 2179 2180 /* Convenience function to yield to thread scheduler */ 2181 static void jump_back(IRExpr *condition) 2182 { 2183 stmt( IRStmt_Exit(condition, 2184 Ijk_Yield, 2185 IRConst_U64( guest_PC_curr_instr ), 2186 OFFB_PC) ); 2187 } 2188 2189 /* Based on s390_irgen_load_and_add32. */ 2190 static void mips_irgen_load_and_add32(IRTemp op1addr, IRTemp new_val, 2191 UChar rd, Bool putIntoRd) 2192 { 2193 IRCAS *cas; 2194 IRTemp old_mem = newTemp(Ity_I32); 2195 IRTemp expd = newTemp(Ity_I32); 2196 2197 assign(expd, load(Ity_I32, mkexpr(op1addr))); 2198 2199 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2200 Iend_LE, mkexpr(op1addr), 2201 NULL, mkexpr(expd), /* expected value */ 2202 NULL, mkexpr(new_val) /* new value */); 2203 stmt(IRStmt_CAS(cas)); 2204 2205 /* If old_mem contains the expected value, then the CAS succeeded. 2206 Otherwise, it did not */ 2207 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd))); 2208 if (putIntoRd) 2209 putIReg(rd, mkWidenFrom32(Ity_I64, mkexpr(old_mem), True)); 2210 } 2211 2212 /* Based on s390_irgen_load_and_add64. */ 2213 static void mips_irgen_load_and_add64(IRTemp op1addr, IRTemp new_val, 2214 UChar rd, Bool putIntoRd) 2215 { 2216 IRCAS *cas; 2217 IRTemp old_mem = newTemp(Ity_I64); 2218 IRTemp expd = newTemp(Ity_I64); 2219 2220 assign(expd, load(Ity_I64, mkexpr(op1addr))); 2221 2222 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2223 Iend_LE, mkexpr(op1addr), 2224 NULL, mkexpr(expd), /* expected value */ 2225 NULL, mkexpr(new_val) /* new value */); 2226 stmt(IRStmt_CAS(cas)); 2227 2228 /* If old_mem contains the expected value, then the CAS succeeded. 2229 Otherwise, it did not */ 2230 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd))); 2231 if (putIntoRd) 2232 putIReg(rd, mkexpr(old_mem)); 2233 } 2234 2235 static Bool dis_instr_CVM ( UInt theInstr ) 2236 { 2237 UChar opc2 = get_function(theInstr); 2238 UChar opc1 = get_opcode(theInstr); 2239 UChar regRs = get_rs(theInstr); 2240 UChar regRt = get_rt(theInstr); 2241 UChar regRd = get_rd(theInstr); 2242 /* MIPS trap instructions extract code from theInstr[15:6]. 2243 Cavium OCTEON instructions SNEI, SEQI extract immediate operands 2244 from the same bit field [15:6]. */ 2245 UInt imm = get_code(theInstr); 2246 UChar lenM1 = get_msb(theInstr); 2247 UChar p = get_lsb(theInstr); 2248 IRType ty = mode64? Ity_I64 : Ity_I32; 2249 IRTemp tmp = newTemp(ty); 2250 IRTemp tmpRs = newTemp(ty); 2251 IRTemp tmpRt = newTemp(ty); 2252 IRTemp t1 = newTemp(ty); 2253 UInt size; 2254 assign(tmpRs, getIReg(regRs)); 2255 2256 switch(opc1) { 2257 case 0x1C: { 2258 switch(opc2) { 2259 case 0x03: { /* DMUL rd, rs, rt */ 2260 DIP("dmul r%d, r%d, r%d", regRd, regRs, regRt); 2261 IRTemp t0 = newTemp(Ity_I128); 2262 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt))); 2263 putIReg(regRd, unop(Iop_128to64, mkexpr(t0))); 2264 break; 2265 } 2266 2267 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */ 2268 DIP("saa r%u, (r%u)", regRt, regRs); 2269 IRTemp addr = newTemp(Ity_I64); 2270 IRTemp new = newTemp(Ity_I32); 2271 assign (addr, getIReg(regRs)); 2272 assign(new, binop(Iop_Add32, 2273 load(Ity_I32, mkexpr(addr)), 2274 mkNarrowTo32(ty, getIReg(regRt)))); 2275 mips_irgen_load_and_add32(addr, new, 0, False); 2276 break; 2277 } 2278 2279 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */ 2280 case 0x19: { 2281 DIP( "saad r%u, (r%u)", regRt, regRs); 2282 IRTemp addr = newTemp(Ity_I64); 2283 IRTemp new = newTemp(Ity_I64); 2284 assign (addr, getIReg(regRs)); 2285 assign(new, binop(Iop_Add64, 2286 load(Ity_I64, mkexpr(addr)), 2287 getIReg(regRt))); 2288 mips_irgen_load_and_add64(addr, new, 0, False); 2289 break; 2290 } 2291 2292 /* LAI, LAID, LAD, LADD, LAS, LASD, 2293 LAC, LACD, LAA, LAAD, LAW, LAWD */ 2294 case 0x1f: { 2295 UInt opc3 = get_sa(theInstr); 2296 IRTemp addr = newTemp(Ity_I64); 2297 switch (opc3) { 2298 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */ 2299 case 0x02: { 2300 DIP("lai r%u,(r%u)\n", regRd, regRs); 2301 IRTemp new = newTemp(Ity_I32); 2302 assign(addr, getIReg(regRs)); 2303 assign(new, binop(Iop_Add32, 2304 load(Ity_I32, mkexpr(addr)), 2305 mkU32(1))); 2306 mips_irgen_load_and_add32(addr, new, regRd, True); 2307 break; 2308 } 2309 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */ 2310 case 0x03: { 2311 DIP("laid r%u,(r%u)\n", regRd, regRs); 2312 IRTemp new = newTemp(Ity_I64); 2313 assign(addr, getIReg(regRs)); 2314 assign(new, binop(Iop_Add64, 2315 load(Ity_I64, mkexpr(addr)), 2316 mkU64(1))); 2317 mips_irgen_load_and_add64(addr, new, regRd, True); 2318 break; 2319 } 2320 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */ 2321 case 0x06: { 2322 DIP("lad r%u,(r%u)\n", regRd, regRs); 2323 IRTemp new = newTemp(Ity_I32); 2324 assign(addr, getIReg(regRs)); 2325 assign(new, binop(Iop_Sub32, 2326 load(Ity_I32, mkexpr(addr)), 2327 mkU32(1))); 2328 mips_irgen_load_and_add32(addr, new, regRd, True); 2329 break; 2330 } 2331 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */ 2332 case 0x07: { 2333 DIP("ladd r%u,(r%u)\n", regRd, regRs); 2334 IRTemp new = newTemp(Ity_I64); 2335 assign (addr, getIReg(regRs)); 2336 assign(new, binop(Iop_Sub64, 2337 load(Ity_I64, mkexpr(addr)), 2338 mkU64(1))); 2339 mips_irgen_load_and_add64(addr, new, regRd, True); 2340 break; 2341 } 2342 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */ 2343 case 0x0a: { 2344 DIP("las r%u,(r%u)\n", regRd, regRs); 2345 IRTemp new = newTemp(Ity_I32); 2346 assign(addr, getIReg(regRs)); 2347 assign(new, mkU32(0xffffffff)); 2348 mips_irgen_load_and_add32(addr, new, regRd, True); 2349 break; 2350 } 2351 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */ 2352 case 0x0b: { 2353 DIP("lasd r%u,(r%u)\n", regRd, regRs); 2354 IRTemp new = newTemp(Ity_I64); 2355 assign (addr, getIReg(regRs)); 2356 assign(new, mkU64(0xffffffffffffffffULL)); 2357 mips_irgen_load_and_add64(addr, new, regRd, True); 2358 break; 2359 } 2360 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */ 2361 case 0x0e: { 2362 DIP("lac r%u,(r%u)\n", regRd, regRs); 2363 IRTemp new = newTemp(Ity_I32); 2364 assign (addr, getIReg(regRs)); 2365 assign(new, mkU32(0)); 2366 mips_irgen_load_and_add32(addr, new, regRd, True); 2367 break; 2368 } 2369 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */ 2370 case 0x0f: { 2371 DIP("lacd r%u,(r%u)\n", regRd, regRs); 2372 IRTemp new = newTemp(Ity_I64); 2373 assign(addr, getIReg(regRs)); 2374 assign(new, mkU64(0)); 2375 mips_irgen_load_and_add64(addr, new, regRd, True); 2376 break; 2377 } 2378 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */ 2379 case 0x12: { 2380 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt); 2381 IRTemp new = newTemp(Ity_I32); 2382 assign(addr, getIReg(regRs)); 2383 assign(new, binop(Iop_Add32, 2384 load(Ity_I32, mkexpr(addr)), 2385 mkNarrowTo32(ty, getIReg(regRt)))); 2386 mips_irgen_load_and_add32(addr, new, regRd, True); 2387 break; 2388 } 2389 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */ 2390 case 0x13: { 2391 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt); 2392 IRTemp new = newTemp(Ity_I64); 2393 assign (addr, getIReg(regRs)); 2394 assign(new, binop(Iop_Add64, 2395 load(Ity_I64, mkexpr(addr)), 2396 getIReg(regRt))); 2397 mips_irgen_load_and_add64(addr, new, regRd, True); 2398 break; 2399 } 2400 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */ 2401 case 0x16: { 2402 DIP("law r%u,(r%u)\n", regRd, regRs); 2403 IRTemp new = newTemp(Ity_I32); 2404 assign(addr, getIReg(regRs)); 2405 assign(new, mkNarrowTo32(ty, getIReg(regRt))); 2406 mips_irgen_load_and_add32(addr, new, regRd, True); 2407 break; 2408 } 2409 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */ 2410 case 0x17: { 2411 DIP("lawd r%u,(r%u)\n", regRd, regRs); 2412 IRTemp new = newTemp(Ity_I64); 2413 assign(addr, getIReg(regRs)); 2414 assign(new, getIReg(regRt)); 2415 mips_irgen_load_and_add64(addr, new, regRd, True); 2416 break; 2417 } 2418 default: 2419 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3); 2420 vex_printf("Instruction=0x%08x\n", theInstr); 2421 return False; 2422 } 2423 break; 2424 } 2425 2426 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */ 2427 case 0x28: { 2428 DIP("BADDU r%d, r%d, r%d", regRs, regRt, regRd); 2429 IRTemp t0 = newTemp(Ity_I8); 2430 2431 assign(t0, binop(Iop_Add8, 2432 mkNarrowTo8(ty, getIReg(regRs)), 2433 mkNarrowTo8(ty, getIReg(regRt)))); 2434 2435 if (mode64) 2436 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2437 unop(Iop_8Uto64, mkexpr(t0)), 2438 mkSzImm(ty, 0xFF))); 2439 else 2440 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2441 unop(Iop_8Uto32, mkexpr(t0)), 2442 mkSzImm(ty, 0xFF))); 2443 break; 2444 } 2445 2446 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */ 2447 int i, shift[5]; 2448 IRTemp mask[5]; 2449 IRTemp old = newTemp(ty); 2450 IRTemp nyu = IRTemp_INVALID; 2451 assign(old, getIReg(regRs)); 2452 DIP("pop r%d, r%d", regRd, regRs); 2453 2454 for (i = 0; i < 5; i++) { 2455 mask[i] = newTemp(ty); 2456 shift[i] = 1 << i; 2457 } 2458 if(mode64) { 2459 assign(mask[0], mkU64(0x0000000055555555)); 2460 assign(mask[1], mkU64(0x0000000033333333)); 2461 assign(mask[2], mkU64(0x000000000F0F0F0F)); 2462 assign(mask[3], mkU64(0x0000000000FF00FF)); 2463 assign(mask[4], mkU64(0x000000000000FFFF)); 2464 2465 for (i = 0; i < 5; i++) { 2466 nyu = newTemp(ty); 2467 assign(nyu, 2468 binop(Iop_Add64, 2469 binop(Iop_And64, 2470 mkexpr(old), mkexpr(mask[i])), 2471 binop(Iop_And64, 2472 binop(Iop_Shr64, 2473 mkexpr(old), mkU8(shift[i])), 2474 mkexpr(mask[i])))); 2475 old = nyu; 2476 } 2477 } else { 2478 assign(mask[0], mkU32(0x55555555)); 2479 assign(mask[1], mkU32(0x33333333)); 2480 assign(mask[2], mkU32(0x0F0F0F0F)); 2481 assign(mask[3], mkU32(0x00FF00FF)); 2482 assign(mask[4], mkU32(0x0000FFFF)); 2483 assign(old, getIReg(regRs)); 2484 2485 for (i = 0; i < 5; i++) { 2486 nyu = newTemp(ty); 2487 assign(nyu, 2488 binop(Iop_Add32, 2489 binop(Iop_And32, 2490 mkexpr(old), mkexpr(mask[i])), 2491 binop(Iop_And32, 2492 binop(Iop_Shr32, 2493 mkexpr(old), mkU8(shift[i])), 2494 mkexpr(mask[i])))); 2495 old = nyu; 2496 } 2497 } 2498 putIReg(regRd, mkexpr(nyu)); 2499 break; 2500 } 2501 2502 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */ 2503 case 0x2d: { 2504 int i, shift[6]; 2505 IRTemp mask[6]; 2506 IRTemp old = newTemp(ty); 2507 IRTemp nyu = IRTemp_INVALID; 2508 DIP("dpop r%d, r%d", regRd, regRs); 2509 2510 for (i = 0; i < 6; i++) { 2511 mask[i] = newTemp(ty); 2512 shift[i] = 1 << i; 2513 } 2514 vassert(mode64); /*Caution! Only for Mode 64*/ 2515 assign(mask[0], mkU64(0x5555555555555555ULL)); 2516 assign(mask[1], mkU64(0x3333333333333333ULL)); 2517 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL)); 2518 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL)); 2519 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL)); 2520 assign(mask[5], mkU64(0x00000000FFFFFFFFULL)); 2521 assign(old, getIReg(regRs)); 2522 for (i = 0; i < 6; i++) { 2523 nyu = newTemp(Ity_I64); 2524 assign(nyu, 2525 binop(Iop_Add64, 2526 binop(Iop_And64, 2527 mkexpr(old), mkexpr(mask[i])), 2528 binop(Iop_And64, 2529 binop(Iop_Shr64, 2530 mkexpr(old), mkU8(shift[i])), 2531 mkexpr(mask[i])))); 2532 old = nyu; 2533 } 2534 putIReg(regRd, mkexpr(nyu)); 2535 break; 2536 } 2537 2538 case 0x32: /* 5. CINS rd, rs, p, lenm1 */ 2539 DIP("cins r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2540 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2541 mkU8(64-( lenM1+1 )))); 2542 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2543 mkU8(64-(p+lenM1+1)))); 2544 putIReg( regRt, mkexpr(tmpRt)); 2545 break; 2546 2547 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */ 2548 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1); 2549 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2550 mkU8(64-( lenM1+1 )))); 2551 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2552 mkU8(32-(p+lenM1+1)))); 2553 putIReg( regRt, mkexpr(tmpRt)); 2554 break; 2555 2556 case 0x3A: /* 3. EXTS rt, rs, p len */ 2557 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2558 size = lenM1 + 1; /* lenm1+1 */ 2559 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */ 2560 UChar rsAmt = 64 - size; /* lenm1+1 */ 2561 tmp = newTemp(Ity_I64); 2562 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 2563 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt))); 2564 break; 2565 2566 case 0x3B: /* 4. EXTS32 rt, rs, p len */ 2567 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2568 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2569 mkU8(32-(p+lenM1+1)))); 2570 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp), 2571 mkU8(64-(lenM1+1))) ); 2572 putIReg( regRt, mkexpr(tmpRt)); 2573 break; 2574 2575 case 0x2B: /* 20. SNE rd, rs, rt */ 2576 DIP("sne r%d, r%d, r%d", regRd,regRs, regRt); 2577 if (mode64) 2578 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64, 2579 getIReg(regRs), 2580 getIReg(regRt)))); 2581 else 2582 putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32, 2583 getIReg(regRs), 2584 getIReg(regRt)))); 2585 break; 2586 2587 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */ 2588 DIP("seq r%d, r%d, %d", regRd, regRs, regRt); 2589 if (mode64) 2590 putIReg(regRd, unop(Iop_1Uto64, 2591 binop(Iop_CmpEQ64, getIReg(regRs), 2592 getIReg(regRt)))); 2593 else 2594 putIReg(regRd, unop(Iop_1Uto32, 2595 binop(Iop_CmpEQ32, getIReg(regRs), 2596 getIReg(regRt)))); 2597 break; 2598 2599 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */ 2600 DIP("seqi r%d, r%d, %d", regRt, regRs, imm); 2601 if (mode64) 2602 putIReg(regRt, unop(Iop_1Uto64, 2603 binop(Iop_CmpEQ64, getIReg(regRs), 2604 mkU64(extend_s_10to64(imm))))); 2605 else 2606 putIReg(regRt, unop(Iop_1Uto32, 2607 binop(Iop_CmpEQ32, getIReg(regRs), 2608 mkU32(extend_s_10to32(imm))))); 2609 break; 2610 2611 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */ 2612 DIP("snei r%d, r%d, %d", regRt, regRs, imm); 2613 if (mode64) 2614 putIReg(regRt, unop(Iop_1Uto64, 2615 binop(Iop_CmpNE64, 2616 getIReg(regRs), 2617 mkU64(extend_s_10to64(imm))))); 2618 else 2619 putIReg(regRt, unop(Iop_1Uto32, 2620 binop(Iop_CmpNE32, 2621 getIReg(regRs), 2622 mkU32(extend_s_10to32(imm))))); 2623 break; 2624 2625 default: 2626 return False; 2627 } 2628 break; 2629 } /* opc1 0x1C ends here*/ 2630 case 0x1F: { 2631 switch(opc2) { 2632 case 0x0A: { // lx - Load indexed instructions 2633 switch (get_sa(theInstr)) { 2634 case 0x00: { // LWX rd, index(base) 2635 DIP("lwx r%d, r%d(r%d)", regRd, regRt, regRs); 2636 LOADX_STORE_PATTERN; 2637 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2638 True)); 2639 break; 2640 } 2641 case 0x08: { // LDX rd, index(base) 2642 DIP("ldx r%d, r%d(r%d)", regRd, regRt, regRs); 2643 vassert(mode64); /* Currently Implemented only for n64 */ 2644 LOADX_STORE_PATTERN; 2645 putIReg(regRd, load(Ity_I64, mkexpr(t1))); 2646 break; 2647 } 2648 case 0x06: { // LBUX rd, index(base) 2649 DIP("lbux r%d, r%d(r%d)", regRd, regRt, regRs); 2650 LOADX_STORE_PATTERN; 2651 if (mode64) 2652 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8, 2653 mkexpr(t1)))); 2654 else 2655 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8, 2656 mkexpr(t1)))); 2657 break; 2658 } 2659 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON) 2660 DIP("lwux r%d, r%d(r%d)", regRd, regRt, regRs); 2661 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/ 2662 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2663 False)); 2664 break; 2665 } 2666 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON) 2667 DIP("lhux r%d, r%d(r%d)", regRd, regRt, regRs); 2668 LOADX_STORE_PATTERN; 2669 if (mode64) 2670 putIReg(regRd, 2671 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 2672 else 2673 putIReg(regRd, 2674 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 2675 break; 2676 } 2677 case 0x16: { // LBX rd, index(base) (Cavium OCTEON) 2678 DIP("lbx r%d, r%d(r%d)", regRd, regRs, regRt); 2679 LOADX_STORE_PATTERN; 2680 if (mode64) 2681 putIReg(regRd, 2682 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 2683 else 2684 putIReg(regRd, 2685 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 2686 break; 2687 } 2688 default: 2689 vex_printf("\nUnhandled LX instruction opc3 = %x\n", 2690 get_sa(theInstr)); 2691 return False; 2692 } 2693 break; 2694 } 2695 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/ 2696 break; 2697 } /* opc1 = 0x1F ends here*/ 2698 default: 2699 return False; 2700 } /* main opc1 switch ends here */ 2701 return True; 2702 } 2703 2704 /*------------------------------------------------------------*/ 2705 /*--- Disassemble a single DSP ASE instruction ---*/ 2706 /*------------------------------------------------------------*/ 2707 2708 static UInt disDSPInstr_MIPS_WRK ( UInt cins ) 2709 { 2710 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, 2711 t15, t16, t17; 2712 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask, 2713 wrdsp_mask, dsp_imm, shift; 2714 2715 opcode = get_opcode(cins); 2716 rs = get_rs(cins); 2717 rt = get_rt(cins); 2718 rd = get_rd(cins); 2719 sa = get_sa(cins); 2720 function = get_function(cins); 2721 ac = get_acNo(cins); 2722 ac_mfhilo = get_acNo_mfhilo(cins); 2723 rddsp_mask = get_rddspMask(cins); 2724 wrdsp_mask = get_wrdspMask(cins); 2725 dsp_imm = get_dspImm(cins); 2726 shift = get_shift(cins); 2727 2728 switch (opcode) { 2729 case 0x00: { /* Special */ 2730 switch (function) { 2731 case 0x10: { /* MFHI */ 2732 DIP("mfhi ac%d r%d", ac_mfhilo, rd); 2733 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo))); 2734 break; 2735 } 2736 2737 case 0x11: { /* MTHI */ 2738 DIP("mthi ac%d r%d", ac, rs); 2739 t1 = newTemp(Ity_I32); 2740 assign(t1, unop(Iop_64to32, getAcc(ac))); 2741 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1))); 2742 break; 2743 } 2744 2745 case 0x12: { /* MFLO */ 2746 DIP("mflo ac%d r%d", ac_mfhilo, rd); 2747 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo))); 2748 break; 2749 } 2750 2751 case 0x13: { /* MTLO */ 2752 DIP("mtlo ac%d r%d", ac, rs); 2753 t1 = newTemp(Ity_I32); 2754 assign(t1, unop(Iop_64HIto32, getAcc(ac))); 2755 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs))); 2756 break; 2757 } 2758 2759 case 0x18: { /* MULT */ 2760 DIP("mult ac%d r%d, r%d", ac, rs, rt); 2761 t1 = newTemp(Ity_I64); 2762 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2763 mkNarrowTo32(Ity_I32, getIReg(rt)))); 2764 putAcc(ac, mkexpr(t1)); 2765 break; 2766 } 2767 2768 case 0x19: { /* MULTU */ 2769 DIP("multu ac%d r%d, r%d", ac, rs, rt); 2770 t1 = newTemp(Ity_I64); 2771 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2772 mkNarrowTo32(Ity_I32, 2773 getIReg(rt)))); 2774 putAcc(ac, mkexpr(t1)); 2775 break; 2776 } 2777 } 2778 break; 2779 } 2780 case 0x1C: { /* Special2 */ 2781 switch (function) { 2782 case 0x00: { /* MADD */ 2783 DIP("madd ac%d, r%d, r%d", ac, rs, rt); 2784 t1 = newTemp(Ity_I64); 2785 t2 = newTemp(Ity_I64); 2786 t3 = newTemp(Ity_I64); 2787 2788 assign(t1, getAcc(ac)); 2789 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2790 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2))); 2791 2792 putAcc(ac, mkexpr(t3)); 2793 break; 2794 } 2795 case 0x01: { /* MADDU */ 2796 DIP("maddu ac%d r%d, r%d", ac, rs, rt); 2797 t1 = newTemp(Ity_I64); 2798 t2 = newTemp(Ity_I64); 2799 t3 = newTemp(Ity_I64); 2800 2801 assign(t1, getAcc(ac)); 2802 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2803 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1))); 2804 2805 putAcc(ac, mkexpr(t3)); 2806 break; 2807 } 2808 case 0x04: { /* MSUB */ 2809 DIP("msub ac%d r%d, r%d", ac, rs, rt); 2810 t1 = newTemp(Ity_I64); 2811 t2 = newTemp(Ity_I64); 2812 t3 = newTemp(Ity_I64); 2813 2814 assign(t1, getAcc(ac)); 2815 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2816 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2817 2818 putAcc(ac, mkexpr(t3)); 2819 break; 2820 } 2821 case 0x05: { /* MSUBU */ 2822 DIP("msubu ac%d r%d, r%d", ac, rs, rt); 2823 t1 = newTemp(Ity_I64); 2824 t2 = newTemp(Ity_I64); 2825 t3 = newTemp(Ity_I64); 2826 2827 assign(t1, getAcc(ac)); 2828 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2829 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2830 2831 putAcc(ac, mkexpr(t3)); 2832 break; 2833 } 2834 } 2835 break; 2836 } 2837 case 0x1F: { /* Special3 */ 2838 switch (function) { 2839 case 0x12: { /* ABSQ_S.PH */ 2840 switch (sa) { 2841 case 0x1: { /* ABSQ_S.QB */ 2842 DIP("absq_s.qb r%d, r%d", rd, rt); 2843 vassert(!mode64); 2844 t0 = newTemp(Ity_I8); 2845 t1 = newTemp(Ity_I1); 2846 t2 = newTemp(Ity_I1); 2847 t3 = newTemp(Ity_I8); 2848 t4 = newTemp(Ity_I8); 2849 t5 = newTemp(Ity_I1); 2850 t6 = newTemp(Ity_I1); 2851 t7 = newTemp(Ity_I8); 2852 t8 = newTemp(Ity_I8); 2853 t9 = newTemp(Ity_I1); 2854 t10 = newTemp(Ity_I1); 2855 t11 = newTemp(Ity_I8); 2856 t12 = newTemp(Ity_I8); 2857 t13 = newTemp(Ity_I1); 2858 t14 = newTemp(Ity_I1); 2859 t15 = newTemp(Ity_I8); 2860 t16 = newTemp(Ity_I32); 2861 t17 = newTemp(Ity_I32); 2862 2863 /* Absolute value of the rightmost byte (bits 7-0). */ 2864 /* t0 - rightmost byte. */ 2865 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt)))); 2866 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */ 2867 assign(t1, binop(Iop_CmpEQ32, 2868 unop(Iop_8Uto32, mkexpr(t0)), 2869 mkU32(0x00000080))); 2870 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 2871 assign(t2, unop(Iop_32to1, 2872 binop(Iop_Shr32, 2873 binop(Iop_And32, 2874 getIReg(rt), 2875 mkU32(0x00000080)), 2876 mkU8(0x7)))); 2877 /* t3 holds abs(t0). */ 2878 assign(t3, IRExpr_ITE(mkexpr(t1), 2879 mkU8(0x7F), 2880 IRExpr_ITE(mkexpr(t2), 2881 binop(Iop_Add8, 2882 unop(Iop_Not8, 2883 mkexpr(t0)), 2884 mkU8(0x1)), 2885 mkexpr(t0)))); 2886 2887 /* Absolute value of bits 15-8. */ 2888 /* t4 - input byte. */ 2889 assign(t4, 2890 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt)))); 2891 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */ 2892 assign(t5, binop(Iop_CmpEQ32, 2893 unop(Iop_8Uto32, mkexpr(t4)), 2894 mkU32(0x00000080))); 2895 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 2896 assign(t6, unop(Iop_32to1, 2897 binop(Iop_Shr32, 2898 binop(Iop_And32, 2899 getIReg(rt), 2900 mkU32(0x00008000)), 2901 mkU8(15)))); 2902 /* t3 holds abs(t4). */ 2903 assign(t7, IRExpr_ITE(mkexpr(t5), 2904 mkU8(0x7F), 2905 IRExpr_ITE(mkexpr(t6), 2906 binop(Iop_Add8, 2907 unop(Iop_Not8, 2908 mkexpr(t4)), 2909 mkU8(0x1)), 2910 mkexpr(t4)))); 2911 2912 /* Absolute value of bits 23-15. */ 2913 /* t8 - input byte. */ 2914 assign(t8, 2915 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt)))); 2916 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */ 2917 assign(t9, binop(Iop_CmpEQ32, 2918 unop(Iop_8Uto32, mkexpr(t8)), 2919 mkU32(0x00000080))); 2920 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */ 2921 assign(t10, unop(Iop_32to1, 2922 binop(Iop_Shr32, 2923 binop(Iop_And32, 2924 getIReg(rt), 2925 mkU32(0x00800000)), 2926 mkU8(23)))); 2927 /* t3 holds abs(t8). */ 2928 assign(t11, IRExpr_ITE(mkexpr(t9), 2929 mkU8(0x7F), 2930 IRExpr_ITE(mkexpr(t10), 2931 binop(Iop_Add8, 2932 unop(Iop_Not8, 2933 mkexpr(t8)), 2934 mkU8(0x1)), 2935 mkexpr(t8)))); 2936 2937 /* Absolute value of bits 31-24. */ 2938 /* t12 - input byte. */ 2939 assign(t12, 2940 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt)))); 2941 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */ 2942 assign(t13, binop(Iop_CmpEQ32, 2943 unop(Iop_8Uto32, mkexpr(t12)), 2944 mkU32(0x00000080))); 2945 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */ 2946 assign(t14, unop(Iop_32to1, 2947 binop(Iop_Shr32, 2948 binop(Iop_And32, 2949 getIReg(rt), 2950 mkU32(0x80000000)), 2951 mkU8(31)))); 2952 /* t15 holds abs(t12). */ 2953 assign(t15, IRExpr_ITE(mkexpr(t13), 2954 mkU8(0x7F), 2955 IRExpr_ITE(mkexpr(t14), 2956 binop(Iop_Add8, 2957 unop(Iop_Not8, 2958 mkexpr(t12)), 2959 mkU8(0x1)), 2960 mkexpr(t12)))); 2961 2962 /* t16 holds !0 if any of input bytes is 0x80 or 0 2963 otherwise. */ 2964 assign(t16, 2965 binop(Iop_Or32, 2966 binop(Iop_Or32, 2967 binop(Iop_Or32, 2968 unop(Iop_1Sto32, mkexpr(t13)), 2969 unop(Iop_1Sto32, mkexpr(t9))), 2970 unop(Iop_1Sto32, mkexpr(t5))), 2971 unop(Iop_1Sto32, mkexpr(t1)))); 2972 2973 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 2974 mkexpr(t16), 2975 mkU32(0x0)), 2976 getDSPControl(), 2977 binop(Iop_Or32, 2978 getDSPControl(), 2979 mkU32(0x00100000)))); 2980 2981 /* t17 = t15|t11|t7|t3 */ 2982 assign(t17, 2983 binop(Iop_16HLto32, 2984 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)), 2985 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3)))); 2986 2987 putIReg(rd, mkexpr(t17)); 2988 break; 2989 } 2990 case 0x2: { /* REPL.QB */ 2991 DIP("repl.qb r%d, %d", rd, dsp_imm); 2992 vassert(!mode64); 2993 2994 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) | 2995 (dsp_imm << 8) | (dsp_imm))); 2996 break; 2997 } 2998 case 0x3: { /* REPLV.QB */ 2999 DIP("replv.qb r%d, r%d", rd, rt); 3000 vassert(!mode64); 3001 t0 = newTemp(Ity_I8); 3002 3003 assign(t0, unop(Iop_32to8, 3004 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 3005 putIReg(rd, 3006 binop(Iop_16HLto32, 3007 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)), 3008 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)))); 3009 break; 3010 } 3011 case 0x4: { /* PRECEQU.PH.QBL */ 3012 DIP("precequ.ph.qbl r%d, r%d", rd, rt); 3013 vassert(!mode64); 3014 3015 putIReg(rd, binop(Iop_Or32, 3016 binop(Iop_Shr32, 3017 binop(Iop_And32, 3018 getIReg(rt), 3019 mkU32(0xff000000)), 3020 mkU8(1)), 3021 binop(Iop_Shr32, 3022 binop(Iop_And32, 3023 getIReg(rt), 3024 mkU32(0x00ff0000)), 3025 mkU8(9)))); 3026 break; 3027 } 3028 case 0x5: { /* PRECEQU.PH.QBR */ 3029 DIP("precequ.ph.qbr r%d, r%d", rd, rt); 3030 vassert(!mode64); 3031 3032 putIReg(rd, binop(Iop_Or32, 3033 binop(Iop_Shl32, 3034 binop(Iop_And32, 3035 getIReg(rt), 3036 mkU32(0x0000ff00)), 3037 mkU8(15)), 3038 binop(Iop_Shl32, 3039 binop(Iop_And32, 3040 getIReg(rt), 3041 mkU32(0x000000ff)), 3042 mkU8(7)))); 3043 break; 3044 } 3045 case 0x6: { /* PRECEQU.PH.QBLA */ 3046 DIP("precequ.ph.qbla r%d, r%d", rd, rt); 3047 vassert(!mode64); 3048 3049 putIReg(rd, binop(Iop_Or32, 3050 binop(Iop_Shr32, 3051 binop(Iop_And32, 3052 getIReg(rt), 3053 mkU32(0xff000000)), 3054 mkU8(1)), 3055 binop(Iop_Shr32, 3056 binop(Iop_And32, 3057 getIReg(rt), 3058 mkU32(0x0000ff00)), 3059 mkU8(1)))); 3060 break; 3061 } 3062 case 0x7: { /* PRECEQU.PH.QBRA */ 3063 DIP("precequ.ph.qbra r%d, r%d", rd, rt); 3064 vassert(!mode64); 3065 3066 putIReg(rd, binop(Iop_Or32, 3067 binop(Iop_Shl32, 3068 binop(Iop_And32, 3069 getIReg(rt), 3070 mkU32(0x00ff0000)), 3071 mkU8(7)), 3072 binop(Iop_Shl32, 3073 binop(Iop_And32, 3074 getIReg(rt), 3075 mkU32(0x000000ff)), 3076 mkU8(7)))); 3077 break; 3078 } 3079 case 0x9: { /* ABSQ_S.PH */ 3080 DIP("absq_s.ph r%d, r%d", rd, rt); 3081 vassert(!mode64); 3082 t0 = newTemp(Ity_I16); 3083 t1 = newTemp(Ity_I1); 3084 t2 = newTemp(Ity_I1); 3085 t3 = newTemp(Ity_I16); 3086 t4 = newTemp(Ity_I16); 3087 t5 = newTemp(Ity_I1); 3088 t6 = newTemp(Ity_I1); 3089 t7 = newTemp(Ity_I16); 3090 t8 = newTemp(Ity_I32); 3091 t9 = newTemp(Ity_I32); 3092 3093 /* t0 holds lower 16 bits of value in rt. */ 3094 assign(t0, unop(Iop_32to16, getIReg(rt))); 3095 /* t1 holds 1 if t0 is equal to 0x8000. */ 3096 assign(t1, binop(Iop_CmpEQ32, 3097 unop(Iop_16Uto32, mkexpr(t0)), 3098 mkU32(0x00008000))); 3099 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 3100 assign(t2, unop(Iop_32to1, 3101 binop(Iop_Shr32, 3102 binop(Iop_And32, 3103 getIReg(rt), 3104 mkU32(0x00008000)), 3105 mkU8(15)))); 3106 /* t3 holds abs(t0). */ 3107 assign(t3, IRExpr_ITE(mkexpr(t1), 3108 mkU16(0x7FFF), 3109 IRExpr_ITE(mkexpr(t2), 3110 binop(Iop_Add16, 3111 unop(Iop_Not16, 3112 mkexpr(t0)), 3113 mkU16(0x1)), 3114 mkexpr(t0)))); 3115 3116 /* t4 holds lower 16 bits of value in rt. */ 3117 assign(t4, unop(Iop_32HIto16, getIReg(rt))); 3118 /* t5 holds 1 if t4 is equal to 0x8000. */ 3119 assign(t5, binop(Iop_CmpEQ32, 3120 unop(Iop_16Uto32, mkexpr(t4)), 3121 mkU32(0x00008000))); 3122 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 3123 assign(t6, unop(Iop_32to1, 3124 binop(Iop_Shr32, 3125 binop(Iop_And32, 3126 getIReg(rt), 3127 mkU32(0x80000000)), 3128 mkU8(31)))); 3129 /* t7 holds abs(t4). */ 3130 assign(t7, IRExpr_ITE(mkexpr(t5), 3131 mkU16(0x7FFF), 3132 IRExpr_ITE(mkexpr(t6), 3133 binop(Iop_Add16, 3134 unop(Iop_Not16, 3135 mkexpr(t4)), 3136 mkU16(0x1)), 3137 mkexpr(t4)))); 3138 /* If any of the two input halfwords is equal 0x8000, 3139 set bit 20 in DSPControl register. */ 3140 assign(t8, binop(Iop_Or32, 3141 unop(Iop_1Sto32, mkexpr(t5)), 3142 unop(Iop_1Sto32, mkexpr(t1)))); 3143 3144 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 3145 mkexpr(t8), 3146 mkU32(0x0)), 3147 getDSPControl(), 3148 binop(Iop_Or32, 3149 getDSPControl(), 3150 mkU32(0x00100000)))); 3151 3152 /* t9 = t7|t3 */ 3153 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 3154 3155 putIReg(rd, mkexpr(t9)); 3156 break; 3157 } 3158 case 0xA: { /* REPL.PH */ 3159 DIP("repl.ph r%d, %d", rd, dsp_imm); 3160 vassert(!mode64); 3161 UShort immediate = extend_s_10to16(dsp_imm); 3162 3163 putIReg(rd, mkU32(immediate << 16 | immediate)); 3164 break; 3165 } 3166 case 0xB: { /* REPLV.PH */ 3167 DIP("replv.ph r%d, r%d", rd, rt); 3168 vassert(!mode64); 3169 3170 putIReg(rd, binop(Iop_16HLto32, 3171 unop(Iop_32to16, getIReg(rt)), 3172 unop(Iop_32to16, getIReg(rt)))); 3173 break; 3174 } 3175 case 0xC: { /* PRECEQ.W.PHL */ 3176 DIP("preceq.w.phl r%d, r%d", rd, rt); 3177 vassert(!mode64); 3178 putIReg(rd, binop(Iop_And32, 3179 getIReg(rt), 3180 mkU32(0xffff0000))); 3181 break; 3182 } 3183 case 0xD: { /* PRECEQ.W.PHR */ 3184 DIP("preceq.w.phr r%d, r%d", rd, rt); 3185 vassert(!mode64); 3186 putIReg(rd, binop(Iop_16HLto32, 3187 unop(Iop_32to16, getIReg(rt)), 3188 mkU16(0x0))); 3189 break; 3190 } 3191 case 0x11: { /* ABSQ_S.W */ 3192 DIP("absq_s.w r%d, r%d", rd, rt); 3193 vassert(!mode64); 3194 t0 = newTemp(Ity_I1); 3195 t1 = newTemp(Ity_I1); 3196 t2 = newTemp(Ity_I32); 3197 3198 assign(t0, 3199 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 3200 3201 putDSPControl(IRExpr_ITE(mkexpr(t0), 3202 binop(Iop_Or32, 3203 getDSPControl(), 3204 mkU32(0x00100000)), 3205 getDSPControl())); 3206 3207 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0))); 3208 3209 assign(t2, IRExpr_ITE(mkexpr(t0), 3210 mkU32(0x7FFFFFFF), 3211 IRExpr_ITE(mkexpr(t1), 3212 binop(Iop_Add32, 3213 unop(Iop_Not32, 3214 getIReg(rt)), 3215 mkU32(0x1)), 3216 getIReg(rt)))); 3217 putIReg(rd, mkexpr(t2)); 3218 break; 3219 } 3220 case 0x1B: { /* BITREV */ 3221 DIP("bitrev r%d, r%d", rd, rt); 3222 vassert(!mode64); 3223 /* 32bit reversal as seen on Bit Twiddling Hacks site 3224 http://graphics.stanford.edu/~seander/bithacks.html 3225 section ReverseParallel */ 3226 t1 = newTemp(Ity_I32); 3227 t2 = newTemp(Ity_I32); 3228 t3 = newTemp(Ity_I32); 3229 t4 = newTemp(Ity_I32); 3230 t5 = newTemp(Ity_I32); 3231 3232 assign(t1, binop(Iop_Or32, 3233 binop(Iop_Shr32, 3234 binop(Iop_And32, 3235 getIReg(rt), 3236 mkU32(0xaaaaaaaa)), 3237 mkU8(0x1)), 3238 binop(Iop_Shl32, 3239 binop(Iop_And32, 3240 getIReg(rt), 3241 mkU32(0x55555555)), 3242 mkU8(0x1)))); 3243 assign(t2, binop(Iop_Or32, 3244 binop(Iop_Shr32, 3245 binop(Iop_And32, 3246 mkexpr(t1), 3247 mkU32(0xcccccccc)), 3248 mkU8(0x2)), 3249 binop(Iop_Shl32, 3250 binop(Iop_And32, 3251 mkexpr(t1), 3252 mkU32(0x33333333)), 3253 mkU8(0x2)))); 3254 assign(t3, binop(Iop_Or32, 3255 binop(Iop_Shr32, 3256 binop(Iop_And32, 3257 mkexpr(t2), 3258 mkU32(0xf0f0f0f0)), 3259 mkU8(0x4)), 3260 binop(Iop_Shl32, 3261 binop(Iop_And32, 3262 mkexpr(t2), 3263 mkU32(0x0f0f0f0f)), 3264 mkU8(0x4)))); 3265 assign(t4, binop(Iop_Or32, 3266 binop(Iop_Shr32, 3267 binop(Iop_And32, 3268 mkexpr(t3), 3269 mkU32(0xff00ff00)), 3270 mkU8(0x8)), 3271 binop(Iop_Shl32, 3272 binop(Iop_And32, 3273 mkexpr(t3), 3274 mkU32(0x00ff00ff)), 3275 mkU8(0x8)))); 3276 assign(t5, binop(Iop_Or32, 3277 binop(Iop_Shr32, 3278 mkexpr(t4), 3279 mkU8(0x10)), 3280 binop(Iop_Shl32, 3281 mkexpr(t4), 3282 mkU8(0x10)))); 3283 putIReg(rd, binop(Iop_Shr32, 3284 mkexpr(t5), 3285 mkU8(16))); 3286 break; 3287 } 3288 case 0x1C: { /* PRECEU.PH.QBL */ 3289 DIP("preceu.ph.qbl r%d, r%d", rd, rt); 3290 vassert(!mode64); 3291 3292 putIReg(rd, binop(Iop_Or32, 3293 binop(Iop_Shr32, 3294 binop(Iop_And32, 3295 getIReg(rt), 3296 mkU32(0xff000000)), 3297 mkU8(8)), 3298 binop(Iop_Shr32, 3299 binop(Iop_And32, 3300 getIReg(rt), 3301 mkU32(0x00ff0000)), 3302 mkU8(16)))); 3303 break; 3304 } 3305 case 0x1E: { /* PRECEU.PH.QBLA */ 3306 DIP("preceu.ph.qbla r%d, r%d", rd, rt); 3307 vassert(!mode64); 3308 3309 putIReg(rd, binop(Iop_Or32, 3310 binop(Iop_Shr32, 3311 binop(Iop_And32, 3312 getIReg(rt), 3313 mkU32(0xff000000)), 3314 mkU8(8)), 3315 binop(Iop_Shr32, 3316 binop(Iop_And32, 3317 getIReg(rt), 3318 mkU32(0x0000ff00)), 3319 mkU8(8)))); 3320 break; 3321 } 3322 case 0x1D: { /* PRECEU.PH.QBR */ 3323 DIP("preceu.ph.qbr r%d, r%d", rd, rt); 3324 vassert(!mode64); 3325 3326 putIReg(rd, binop(Iop_Or32, 3327 binop(Iop_Shl32, 3328 binop(Iop_And32, 3329 getIReg(rt), 3330 mkU32(0x0000ff00)), 3331 mkU8(8)), 3332 binop(Iop_And32, 3333 getIReg(rt), 3334 mkU32(0x000000ff)))); 3335 break; 3336 } 3337 case 0x1F: { /* PRECEU.PH.QBRA */ 3338 DIP("preceu.ph.qbra r%d, r%d", rd, rt); 3339 vassert(!mode64); 3340 3341 putIReg(rd, binop(Iop_Or32, 3342 binop(Iop_And32, 3343 getIReg(rt), 3344 mkU32(0x00ff0000)), 3345 binop(Iop_And32, 3346 getIReg(rt), 3347 mkU32(0x000000ff)))); 3348 break; 3349 } 3350 default: 3351 return -1; 3352 } 3353 break; /* end of ABSQ_S.PH */ 3354 } 3355 case 0x38: { /* EXTR.W */ 3356 switch(sa) { 3357 case 0x0: { /* EXTR.W */ 3358 DIP("extr.w r%d, ac%d, %d", rt, ac, rs); 3359 vassert(!mode64); 3360 t0 = newTemp(Ity_I64); 3361 t1 = newTemp(Ity_I64); 3362 t2 = newTemp(Ity_I32); 3363 t3 = newTemp(Ity_I1); 3364 t4 = newTemp(Ity_I1); 3365 t5 = newTemp(Ity_I1); 3366 t6 = newTemp(Ity_I1); 3367 t7 = newTemp(Ity_I32); 3368 t8 = newTemp(Ity_I64); 3369 t9 = newTemp(Ity_I64); 3370 t10 = newTemp(Ity_I1); 3371 t11 = newTemp(Ity_I1); 3372 t12 = newTemp(Ity_I1); 3373 t13 = newTemp(Ity_I1); 3374 t14 = newTemp(Ity_I32); 3375 3376 assign(t0, getAcc(ac)); 3377 if (0 == rs) { 3378 assign(t1, mkexpr(t0)); 3379 } else { 3380 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 3381 } 3382 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3383 assign(t3, binop(Iop_CmpNE32, 3384 unop(Iop_64HIto32, 3385 mkexpr(t1)), 3386 mkU32(0))); 3387 assign(t4, binop(Iop_CmpNE32, 3388 binop(Iop_And32, 3389 unop(Iop_64to32, 3390 mkexpr(t1)), 3391 mkU32(0x80000000)), 3392 mkU32(0))); 3393 /* Check if bits 63..31 of the result in t1 aren't 3394 0x1ffffffff. */ 3395 assign(t5, binop(Iop_CmpNE32, 3396 unop(Iop_64HIto32, 3397 mkexpr(t1)), 3398 mkU32(0xffffffff))); 3399 assign(t6, binop(Iop_CmpNE32, 3400 binop(Iop_And32, 3401 unop(Iop_64to32, 3402 mkexpr(t1)), 3403 mkU32(0x80000000)), 3404 mkU32(0x80000000))); 3405 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3406 control register. */ 3407 assign(t7, binop(Iop_And32, 3408 binop(Iop_Or32, 3409 unop(Iop_1Sto32, mkexpr(t3)), 3410 unop(Iop_1Sto32, mkexpr(t4))), 3411 binop(Iop_Or32, 3412 unop(Iop_1Sto32, mkexpr(t5)), 3413 unop(Iop_1Sto32, mkexpr(t6))))); 3414 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3415 mkexpr(t7), 3416 mkU32(0)), 3417 binop(Iop_Or32, 3418 getDSPControl(), 3419 mkU32(0x00800000)), 3420 getDSPControl())); 3421 3422 /* If the last discarded bit is 1, there would be carry 3423 when rounding, otherwise there wouldn't. We use that 3424 fact and just add the value of the last discarded bit 3425 to the least sifgnificant bit of the shifted value 3426 from acc. */ 3427 if (0 == rs) { 3428 assign(t8, mkU64(0x0ULL)); 3429 } else { 3430 assign(t8, binop(Iop_And64, 3431 binop(Iop_Shr64, 3432 mkexpr(t0), 3433 mkU8(rs-1)), 3434 mkU64(0x1ULL))); 3435 } 3436 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3437 3438 /* Repeat previous steps for the rounded value. */ 3439 assign(t10, binop(Iop_CmpNE32, 3440 unop(Iop_64HIto32, 3441 mkexpr(t9)), 3442 mkU32(0))); 3443 assign(t11, binop(Iop_CmpNE32, 3444 binop(Iop_And32, 3445 unop(Iop_64to32, 3446 mkexpr(t9)), 3447 mkU32(0x80000000)), 3448 mkU32(0))); 3449 3450 assign(t12, binop(Iop_CmpNE32, 3451 unop(Iop_64HIto32, 3452 mkexpr(t9)), 3453 mkU32(0xffffffff))); 3454 assign(t13, binop(Iop_CmpNE32, 3455 binop(Iop_And32, 3456 unop(Iop_64to32, 3457 mkexpr(t9)), 3458 mkU32(0x80000000)), 3459 mkU32(0x80000000))); 3460 3461 assign(t14, binop(Iop_And32, 3462 binop(Iop_Or32, 3463 unop(Iop_1Sto32, mkexpr(t10)), 3464 unop(Iop_1Sto32, mkexpr(t11))), 3465 binop(Iop_Or32, 3466 unop(Iop_1Sto32, mkexpr(t12)), 3467 unop(Iop_1Sto32, mkexpr(t13))))); 3468 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3469 mkexpr(t14), 3470 mkU32(0)), 3471 binop(Iop_Or32, 3472 getDSPControl(), 3473 mkU32(0x00800000)), 3474 getDSPControl())); 3475 if (0 == rs) { 3476 putIReg(rt, unop(Iop_64to32, mkexpr(t0))); 3477 } else { 3478 putIReg(rt, unop(Iop_64to32, mkexpr(t1))); 3479 } 3480 break; 3481 } 3482 case 0x1: { /* EXTRV.W */ 3483 DIP("extrv.w r%d, ac%d, r%d", rt, ac, rs); 3484 vassert(!mode64); 3485 t0 = newTemp(Ity_I64); 3486 t1 = newTemp(Ity_I64); 3487 t2 = newTemp(Ity_I32); 3488 t3 = newTemp(Ity_I1); 3489 t4 = newTemp(Ity_I1); 3490 t5 = newTemp(Ity_I1); 3491 t6 = newTemp(Ity_I1); 3492 t7 = newTemp(Ity_I32); 3493 t8 = newTemp(Ity_I64); 3494 t9 = newTemp(Ity_I64); 3495 t10 = newTemp(Ity_I1); 3496 t11 = newTemp(Ity_I1); 3497 t12 = newTemp(Ity_I1); 3498 t13 = newTemp(Ity_I1); 3499 t14 = newTemp(Ity_I32); 3500 t15 = newTemp(Ity_I8); 3501 3502 assign(t15, unop(Iop_32to8, 3503 binop(Iop_And32, 3504 getIReg(rs), 3505 mkU32(0x1f)))); 3506 assign(t0, getAcc(ac)); 3507 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3508 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 3509 unop(Iop_8Uto32, 3510 mkexpr(t15)), 3511 mkU32(0)), 3512 unop(Iop_64to32, mkexpr(t0)), 3513 unop(Iop_64to32, mkexpr(t1)))); 3514 3515 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3516 assign(t3, binop(Iop_CmpNE32, 3517 unop(Iop_64HIto32, 3518 mkexpr(t1)), 3519 mkU32(0))); 3520 assign(t4, binop(Iop_CmpNE32, 3521 binop(Iop_And32, 3522 unop(Iop_64to32, 3523 mkexpr(t1)), 3524 mkU32(0x80000000)), 3525 mkU32(0))); 3526 /* Check if bits 63..31 of the result in t1 aren't 3527 0x1ffffffff. */ 3528 assign(t5, binop(Iop_CmpNE32, 3529 unop(Iop_64HIto32, 3530 mkexpr(t1)), 3531 mkU32(0xffffffff))); 3532 assign(t6, binop(Iop_CmpNE32, 3533 binop(Iop_And32, 3534 unop(Iop_64to32, 3535 mkexpr(t1)), 3536 mkU32(0x80000000)), 3537 mkU32(0x80000000))); 3538 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3539 control register. */ 3540 assign(t7, binop(Iop_And32, 3541 binop(Iop_Or32, 3542 unop(Iop_1Sto32, mkexpr(t3)), 3543 unop(Iop_1Sto32, mkexpr(t4))), 3544 binop(Iop_Or32, 3545 unop(Iop_1Sto32, mkexpr(t5)), 3546 unop(Iop_1Sto32, mkexpr(t6))))); 3547 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3548 mkexpr(t7), 3549 mkU32(0)), 3550 binop(Iop_Or32, 3551 getDSPControl(), 3552 mkU32(0x00800000)), 3553 getDSPControl())); 3554 3555 /* If the last discarded bit is 1, there would be carry 3556 when rounding, otherwise there wouldn't. We use that 3557 fact and just add the value of the last discarded bit 3558 to the least sifgnificant bit of the shifted value 3559 from acc. */ 3560 assign(t8, 3561 IRExpr_ITE(binop(Iop_CmpEQ32, 3562 unop(Iop_8Uto32, 3563 mkexpr(t15)), 3564 mkU32(0)), 3565 mkU64(0x0ULL), 3566 binop(Iop_And64, 3567 binop(Iop_Shr64, 3568 mkexpr(t0), 3569 unop(Iop_32to8, 3570 binop(Iop_Sub32, 3571 unop(Iop_8Uto32, 3572 mkexpr(t15)), 3573 mkU32(1)))), 3574 mkU64(0x1ULL)))); 3575 3576 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3577 3578 /* Repeat previous steps for the rounded value. */ 3579 assign(t10, binop(Iop_CmpNE32, 3580 unop(Iop_64HIto32, 3581 mkexpr(t9)), 3582 mkU32(0))); 3583 assign(t11, binop(Iop_CmpNE32, 3584 binop(Iop_And32, 3585 unop(Iop_64to32, 3586 mkexpr(t9)), 3587 mkU32(0x80000000)), 3588 mkU32(0))); 3589 3590 assign(t12, binop(Iop_CmpNE32, 3591 unop(Iop_64HIto32, 3592 mkexpr(t9)), 3593 mkU32(0xffffffff))); 3594 assign(t13, binop(Iop_CmpNE32, 3595 binop(Iop_And32, 3596 unop(Iop_64to32, 3597 mkexpr(t9)), 3598 mkU32(0x80000000)), 3599 mkU32(0x80000000))); 3600 3601 assign(t14, binop(Iop_And32, 3602 binop(Iop_Or32, 3603 unop(Iop_1Sto32, mkexpr(t10)), 3604 unop(Iop_1Sto32, mkexpr(t11))), 3605 binop(Iop_Or32, 3606 unop(Iop_1Sto32, mkexpr(t12)), 3607 unop(Iop_1Sto32, mkexpr(t13))))); 3608 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3609 mkexpr(t14), 3610 mkU32(0)), 3611 binop(Iop_Or32, 3612 getDSPControl(), 3613 mkU32(0x00800000)), 3614 getDSPControl())); 3615 break; 3616 } 3617 case 0x2: { /* EXTP */ 3618 DIP("extp r%d, ac%d, %d", rt, ac, rs); 3619 vassert(!mode64); 3620 t0 = newTemp(Ity_I64); 3621 t1 = newTemp(Ity_I32); 3622 t2 = newTemp(Ity_I1); 3623 t3 = newTemp(Ity_I1); 3624 t4 = newTemp(Ity_I8); 3625 t5 = newTemp(Ity_I64); 3626 t6 = newTemp(Ity_I64); 3627 t7 = newTemp(Ity_I32); 3628 3629 assign(t0, getAcc(ac)); 3630 /* Extract pos field of DSPControl register. */ 3631 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3632 3633 /* Check if (pos - size) >= 0 [size <= pos] 3634 if (pos < size) 3635 put 1 to EFI field of DSPControl register 3636 else 3637 extract bits from acc and put 0 to EFI field of 3638 DSPCtrl */ 3639 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 3640 3641 putDSPControl(IRExpr_ITE(mkexpr(t2), 3642 binop(Iop_Or32, 3643 binop(Iop_And32, 3644 getDSPControl(), 3645 mkU32(0xffffbfff)), 3646 mkU32(0x4000)), 3647 binop(Iop_And32, 3648 getDSPControl(), 3649 mkU32(0xffffbfff)))); 3650 3651 /* If pos <= 31, shift right the value from the acc 3652 (pos-size) times and take (size+1) bits from the least 3653 significant positions. Otherwise, shift left the value 3654 (63-pos) times, take (size+1) bits from the most 3655 significant positions and shift right (31-size) times.*/ 3656 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3657 3658 assign(t4, 3659 IRExpr_ITE(mkexpr(t3), 3660 unop(Iop_32to8, 3661 binop(Iop_Sub32, 3662 mkexpr(t1), mkU32(rs))), 3663 unop(Iop_32to8, 3664 binop(Iop_Sub32, 3665 mkU32(63), mkexpr(t1))))); 3666 3667 assign(t5, IRExpr_ITE(mkexpr(t3), 3668 binop(Iop_Shr64, 3669 mkexpr(t0), mkexpr(t4)), 3670 binop(Iop_Shl64, 3671 mkexpr(t0), mkexpr(t4)))); 3672 3673 /* t6 holds a mask for bit extraction */ 3674 assign(t6, 3675 IRExpr_ITE(mkexpr(t3), 3676 unop(Iop_Not64, 3677 binop(Iop_Shl64, 3678 mkU64(0xffffffffffffffffULL), 3679 mkU8(rs+1))), 3680 unop(Iop_Not64, 3681 binop(Iop_Shr64, 3682 mkU64(0xffffffffffffffffULL), 3683 mkU8(rs+1))))); 3684 3685 assign(t7, IRExpr_ITE(mkexpr(t3), 3686 unop(Iop_64to32, 3687 binop(Iop_And64, 3688 mkexpr(t5), 3689 mkexpr(t6))), 3690 binop(Iop_Shr32, 3691 unop(Iop_64HIto32, 3692 binop(Iop_And64, 3693 mkexpr(t5), 3694 mkexpr(t6))), 3695 mkU8(31-rs)))); 3696 3697 putIReg(rt, mkexpr(t7)); 3698 break; 3699 } 3700 case 0x3: { /* EXTPV */ 3701 DIP("extpv r%d, ac%d, r%d", rt, ac, rs); 3702 vassert(!mode64); 3703 t0 = newTemp(Ity_I64); 3704 t1 = newTemp(Ity_I32); 3705 t2 = newTemp(Ity_I1); 3706 t3 = newTemp(Ity_I1); 3707 t4 = newTemp(Ity_I8); 3708 t5 = newTemp(Ity_I64); 3709 t6 = newTemp(Ity_I64); 3710 t7 = newTemp(Ity_I32); 3711 t8 = newTemp(Ity_I32); 3712 3713 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 3714 assign(t0, getAcc(ac)); 3715 /* Extract pos field of DSPControl register. */ 3716 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3717 3718 /* Check if (pos - size) >= 0 [size <= pos] 3719 if (pos < size) 3720 put 1 to EFI field of DSPControl register 3721 else 3722 extract bits from acc and put 0 to EFI field of 3723 DSPCtrl */ 3724 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 3725 3726 putDSPControl(IRExpr_ITE(mkexpr(t2), 3727 binop(Iop_Or32, 3728 binop(Iop_And32, 3729 getDSPControl(), 3730 mkU32(0xffffbfff)), 3731 mkU32(0x4000)), 3732 binop(Iop_And32, 3733 getDSPControl(), 3734 mkU32(0xffffbfff)))); 3735 3736 /* If pos <= 31, shift right the value from the acc 3737 (pos-size) times and take (size+1) bits from the least 3738 significant positions. Otherwise, shift left the value 3739 (63-pos) times, take (size+1) bits from the most 3740 significant positions and shift right (31-size) 3741 times. */ 3742 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3743 3744 assign(t4, 3745 IRExpr_ITE(mkexpr(t3), 3746 unop(Iop_32to8, 3747 binop(Iop_Sub32, 3748 mkexpr(t1), mkexpr(t8))), 3749 unop(Iop_32to8, 3750 binop(Iop_Sub32, 3751 mkU32(63), mkexpr(t1))))); 3752 3753 assign(t5, IRExpr_ITE(mkexpr(t3), 3754 binop(Iop_Shr64, 3755 mkexpr(t0), mkexpr(t4)), 3756 binop(Iop_Shl64, 3757 mkexpr(t0), mkexpr(t4)))); 3758 3759 /* t6 holds a mask for bit extraction. */ 3760 assign(t6, 3761 IRExpr_ITE(mkexpr(t3), 3762 unop(Iop_Not64, 3763 binop(Iop_Shl64, 3764 mkU64(0xffffffffffffffffULL), 3765 unop(Iop_32to8, 3766 binop(Iop_Add32, 3767 mkexpr(t8), 3768 mkU32(1))))), 3769 unop(Iop_Not64, 3770 binop(Iop_Shr64, 3771 mkU64(0xffffffffffffffffULL), 3772 unop(Iop_32to8, 3773 binop(Iop_Add32, 3774 mkexpr(t8), 3775 mkU32(1))))))); 3776 3777 assign(t7, IRExpr_ITE(mkexpr(t3), 3778 unop(Iop_64to32, 3779 binop(Iop_And64, 3780 mkexpr(t5), 3781 mkexpr(t6))), 3782 binop(Iop_Shr32, 3783 unop(Iop_64HIto32, 3784 binop(Iop_And64, 3785 mkexpr(t5), 3786 mkexpr(t6))), 3787 unop(Iop_32to8, 3788 binop(Iop_Sub32, 3789 mkU32(31), 3790 mkexpr(t8)))))); 3791 3792 putIReg(rt, mkexpr(t7)); 3793 break; 3794 } 3795 case 0x4: { /* EXTR_R.W */ 3796 DIP("extr_r.w r%d, ac%d, %d", rt, ac, rs); 3797 vassert(!mode64); 3798 t0 = newTemp(Ity_I64); 3799 t1 = newTemp(Ity_I64); 3800 t2 = newTemp(Ity_I32); 3801 t3 = newTemp(Ity_I1); 3802 t4 = newTemp(Ity_I1); 3803 t5 = newTemp(Ity_I1); 3804 t6 = newTemp(Ity_I1); 3805 t7 = newTemp(Ity_I32); 3806 t8 = newTemp(Ity_I64); 3807 t9 = newTemp(Ity_I64); 3808 t10 = newTemp(Ity_I1); 3809 t11 = newTemp(Ity_I1); 3810 t12 = newTemp(Ity_I1); 3811 t13 = newTemp(Ity_I1); 3812 t14 = newTemp(Ity_I32); 3813 t15 = newTemp(Ity_I64); 3814 t16 = newTemp(Ity_I1); 3815 3816 assign(t0, getAcc(ac)); 3817 assign(t16, binop(Iop_CmpEQ32, 3818 mkU32(rs), 3819 mkU32(0))); 3820 assign(t1, IRExpr_ITE(mkexpr(t16), 3821 mkexpr(t0), 3822 binop(Iop_Sar64, 3823 mkexpr(t0), 3824 mkU8(rs)))); 3825 /* If the last discarded bit is 1, there would be carry 3826 when rounding, otherwise there wouldn't. We use that 3827 fact and just add the value of the last discarded bit 3828 to the least significant bit of the shifted value 3829 from acc. */ 3830 assign(t15, binop(Iop_Shr64, 3831 mkexpr(t0), 3832 unop(Iop_32to8, 3833 binop(Iop_Sub32, 3834 binop(Iop_And32, 3835 mkU32(rs), 3836 mkU32(0x1f)), 3837 mkU32(1))))); 3838 3839 assign(t8, 3840 IRExpr_ITE(mkexpr(t16), 3841 mkU64(0x0ULL), 3842 binop(Iop_And64, 3843 mkexpr(t15), 3844 mkU64(0x0000000000000001ULL)))); 3845 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3846 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 3847 3848 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3849 assign(t3, binop(Iop_CmpNE32, 3850 unop(Iop_64HIto32, 3851 mkexpr(t1)), 3852 mkU32(0))); 3853 assign(t4, binop(Iop_CmpNE32, 3854 binop(Iop_And32, 3855 unop(Iop_64to32, 3856 mkexpr(t1)), 3857 mkU32(0x80000000)), 3858 mkU32(0))); 3859 3860 /* Check if bits 63..31 of the result in t1 aren't 3861 0x1ffffffff. */ 3862 assign(t5, binop(Iop_CmpNE32, 3863 unop(Iop_64HIto32, 3864 mkexpr(t1)), 3865 mkU32(0xffffffff))); 3866 assign(t6, binop(Iop_CmpNE32, 3867 binop(Iop_And32, 3868 unop(Iop_64to32, 3869 mkexpr(t1)), 3870 mkU32(0x80000000)), 3871 mkU32(0x80000000))); 3872 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3873 control register. */ 3874 assign(t7, binop(Iop_And32, 3875 binop(Iop_Or32, 3876 unop(Iop_1Sto32, mkexpr(t3)), 3877 unop(Iop_1Sto32, mkexpr(t4))), 3878 binop(Iop_Or32, 3879 unop(Iop_1Sto32, mkexpr(t5)), 3880 unop(Iop_1Sto32, mkexpr(t6))))); 3881 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3882 mkexpr(t7), 3883 mkU32(0)), 3884 binop(Iop_Or32, 3885 getDSPControl(), 3886 mkU32(0x00800000)), 3887 getDSPControl())); 3888 3889 /* Repeat previous steps for the rounded value. */ 3890 assign(t10, binop(Iop_CmpNE32, 3891 unop(Iop_64HIto32, 3892 mkexpr(t9)), 3893 mkU32(0))); 3894 assign(t11, binop(Iop_CmpNE32, 3895 binop(Iop_And32, 3896 unop(Iop_64to32, 3897 mkexpr(t9)), 3898 mkU32(0x80000000)), 3899 mkU32(0))); 3900 3901 assign(t12, binop(Iop_CmpNE32, 3902 unop(Iop_64HIto32, 3903 mkexpr(t9)), 3904 mkU32(0xffffffff))); 3905 assign(t13, binop(Iop_CmpNE32, 3906 binop(Iop_And32, 3907 unop(Iop_64to32, 3908 mkexpr(t9)), 3909 mkU32(0x80000000)), 3910 mkU32(0x80000000))); 3911 3912 assign(t14, binop(Iop_And32, 3913 binop(Iop_Or32, 3914 unop(Iop_1Sto32, mkexpr(t10)), 3915 unop(Iop_1Sto32, mkexpr(t11))), 3916 binop(Iop_Or32, 3917 unop(Iop_1Sto32, mkexpr(t12)), 3918 unop(Iop_1Sto32, mkexpr(t13))))); 3919 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3920 mkexpr(t14), 3921 mkU32(0)), 3922 binop(Iop_Or32, 3923 getDSPControl(), 3924 mkU32(0x00800000)), 3925 getDSPControl())); 3926 break; 3927 } 3928 case 0x5: { /* EXTRV_R.W */ 3929 DIP("extrv_r.w r%d, ac%d, r%d", rt, ac, rs); 3930 vassert(!mode64); 3931 t0 = newTemp(Ity_I64); 3932 t1 = newTemp(Ity_I64); 3933 t2 = newTemp(Ity_I32); 3934 t3 = newTemp(Ity_I1); 3935 t4 = newTemp(Ity_I1); 3936 t5 = newTemp(Ity_I1); 3937 t6 = newTemp(Ity_I1); 3938 t7 = newTemp(Ity_I32); 3939 t8 = newTemp(Ity_I64); 3940 t9 = newTemp(Ity_I64); 3941 t10 = newTemp(Ity_I1); 3942 t11 = newTemp(Ity_I1); 3943 t12 = newTemp(Ity_I1); 3944 t13 = newTemp(Ity_I1); 3945 t14 = newTemp(Ity_I32); 3946 t15 = newTemp(Ity_I8); 3947 3948 assign(t15, unop(Iop_32to8, 3949 binop(Iop_And32, 3950 getIReg(rs), 3951 mkU32(0x1f)))); 3952 assign(t0, getAcc(ac)); 3953 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3954 3955 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3956 assign(t3, binop(Iop_CmpNE32, 3957 unop(Iop_64HIto32, 3958 mkexpr(t1)), 3959 mkU32(0))); 3960 assign(t4, binop(Iop_CmpNE32, 3961 binop(Iop_And32, 3962 unop(Iop_64to32, 3963 mkexpr(t1)), 3964 mkU32(0x80000000)), 3965 mkU32(0))); 3966 /* Check if bits 63..31 of the result in t1 aren't 3967 0x1ffffffff. */ 3968 assign(t5, binop(Iop_CmpNE32, 3969 unop(Iop_64HIto32, 3970 mkexpr(t1)), 3971 mkU32(0xffffffff))); 3972 assign(t6, binop(Iop_CmpNE32, 3973 binop(Iop_And32, 3974 unop(Iop_64to32, 3975 mkexpr(t1)), 3976 mkU32(0x80000000)), 3977 mkU32(0x80000000))); 3978 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3979 control register. */ 3980 assign(t7, binop(Iop_And32, 3981 binop(Iop_Or32, 3982 unop(Iop_1Sto32, mkexpr(t3)), 3983 unop(Iop_1Sto32, mkexpr(t4))), 3984 binop(Iop_Or32, 3985 unop(Iop_1Sto32, mkexpr(t5)), 3986 unop(Iop_1Sto32, mkexpr(t6))))); 3987 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3988 mkexpr(t7), 3989 mkU32(0)), 3990 binop(Iop_Or32, 3991 getDSPControl(), 3992 mkU32(0x00800000)), 3993 getDSPControl())); 3994 3995 /* If the last discarded bit is 1, there would be carry 3996 when rounding, otherwise there wouldn't. We use that 3997 fact and just add the value of the last discarded bit 3998 to the least sifgnificant bit of the shifted value 3999 from acc. */ 4000 assign(t8, 4001 IRExpr_ITE(binop(Iop_CmpEQ32, 4002 unop(Iop_8Uto32, 4003 mkexpr(t15)), 4004 mkU32(0)), 4005 mkU64(0x0ULL), 4006 binop(Iop_And64, 4007 binop(Iop_Shr64, 4008 mkexpr(t0), 4009 unop(Iop_32to8, 4010 binop(Iop_Sub32, 4011 unop(Iop_8Uto32, 4012 mkexpr(t15)), 4013 mkU32(1)))), 4014 mkU64(0x1ULL)))); 4015 4016 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4017 /* Put rounded value in destination register. */ 4018 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 4019 4020 /* Repeat previous steps for the rounded value. */ 4021 assign(t10, binop(Iop_CmpNE32, 4022 unop(Iop_64HIto32, 4023 mkexpr(t9)), 4024 mkU32(0))); 4025 assign(t11, binop(Iop_CmpNE32, 4026 binop(Iop_And32, 4027 unop(Iop_64to32, 4028 mkexpr(t9)), 4029 mkU32(0x80000000)), 4030 mkU32(0))); 4031 4032 assign(t12, binop(Iop_CmpNE32, 4033 unop(Iop_64HIto32, 4034 mkexpr(t9)), 4035 mkU32(0xffffffff))); 4036 assign(t13, binop(Iop_CmpNE32, 4037 binop(Iop_And32, 4038 unop(Iop_64to32, 4039 mkexpr(t9)), 4040 mkU32(0x80000000)), 4041 mkU32(0x80000000))); 4042 4043 assign(t14, binop(Iop_And32, 4044 binop(Iop_Or32, 4045 unop(Iop_1Sto32, mkexpr(t10)), 4046 unop(Iop_1Sto32, mkexpr(t11))), 4047 binop(Iop_Or32, 4048 unop(Iop_1Sto32, mkexpr(t12)), 4049 unop(Iop_1Sto32, mkexpr(t13))))); 4050 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4051 mkexpr(t14), 4052 mkU32(0)), 4053 binop(Iop_Or32, 4054 getDSPControl(), 4055 mkU32(0x00800000)), 4056 getDSPControl())); 4057 break; 4058 } 4059 case 0x6: { /* EXTR_RS.W */ 4060 DIP("extr_rs.w r%d, ac%d, %d", rt, ac, rs); 4061 vassert(!mode64); 4062 t0 = newTemp(Ity_I64); 4063 t1 = newTemp(Ity_I64); 4064 t2 = newTemp(Ity_I32); 4065 t3 = newTemp(Ity_I1); 4066 t4 = newTemp(Ity_I1); 4067 t5 = newTemp(Ity_I1); 4068 t6 = newTemp(Ity_I1); 4069 t7 = newTemp(Ity_I32); 4070 t8 = newTemp(Ity_I64); 4071 t9 = newTemp(Ity_I64); 4072 t10 = newTemp(Ity_I1); 4073 t11 = newTemp(Ity_I1); 4074 t12 = newTemp(Ity_I1); 4075 t13 = newTemp(Ity_I1); 4076 t14 = newTemp(Ity_I32); 4077 t16 = newTemp(Ity_I32); 4078 4079 assign(t0, getAcc(ac)); 4080 if (0 == rs) { 4081 assign(t1, mkexpr(t0)); 4082 } else { 4083 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4084 } 4085 4086 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4087 assign(t3, binop(Iop_CmpNE32, 4088 unop(Iop_64HIto32, 4089 mkexpr(t1)), 4090 mkU32(0))); 4091 assign(t4, binop(Iop_CmpNE32, 4092 binop(Iop_And32, 4093 unop(Iop_64to32, 4094 mkexpr(t1)), 4095 mkU32(0x80000000)), 4096 mkU32(0))); 4097 /* Check if bits 63..31 of the result in t1 aren't 4098 0x1ffffffff. */ 4099 assign(t5, binop(Iop_CmpNE32, 4100 unop(Iop_64HIto32, 4101 mkexpr(t1)), 4102 mkU32(0xffffffff))); 4103 assign(t6, binop(Iop_CmpNE32, 4104 binop(Iop_And32, 4105 unop(Iop_64to32, 4106 mkexpr(t1)), 4107 mkU32(0x80000000)), 4108 mkU32(0x80000000))); 4109 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4110 control register. */ 4111 assign(t7, binop(Iop_And32, 4112 binop(Iop_Or32, 4113 unop(Iop_1Sto32, mkexpr(t3)), 4114 unop(Iop_1Sto32, mkexpr(t4))), 4115 binop(Iop_Or32, 4116 unop(Iop_1Sto32, mkexpr(t5)), 4117 unop(Iop_1Sto32, mkexpr(t6))))); 4118 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4119 mkexpr(t7), 4120 mkU32(0)), 4121 binop(Iop_Or32, 4122 getDSPControl(), 4123 mkU32(0x00800000)), 4124 getDSPControl())); 4125 4126 /* If the last discarded bit is 1, there would be carry 4127 when rounding, otherwise there wouldn't. We use that 4128 fact and just add the value of the last discarded bit 4129 to the least sifgnificant bit of the shifted value 4130 from acc. */ 4131 if (0 == rs) { 4132 assign(t8, mkU64(0x0ULL)); 4133 } else { 4134 assign(t8, binop(Iop_And64, 4135 binop(Iop_Shr64, 4136 mkexpr(t0), 4137 mkU8(rs-1)), 4138 mkU64(0x1ULL))); 4139 } 4140 4141 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4142 4143 /* Repeat previous steps for the rounded value. */ 4144 assign(t10, binop(Iop_CmpNE32, 4145 unop(Iop_64HIto32, 4146 mkexpr(t9)), 4147 mkU32(0))); 4148 assign(t11, binop(Iop_CmpNE32, 4149 binop(Iop_And32, 4150 unop(Iop_64to32, 4151 mkexpr(t9)), 4152 mkU32(0x80000000)), 4153 mkU32(0))); 4154 4155 assign(t12, binop(Iop_CmpNE32, 4156 unop(Iop_64HIto32, 4157 mkexpr(t9)), 4158 mkU32(0xffffffff))); 4159 assign(t13, binop(Iop_CmpNE32, 4160 binop(Iop_And32, 4161 unop(Iop_64to32, 4162 mkexpr(t9)), 4163 mkU32(0x80000000)), 4164 mkU32(0x80000000))); 4165 4166 assign(t14, binop(Iop_And32, 4167 binop(Iop_Or32, 4168 unop(Iop_1Sto32, mkexpr(t10)), 4169 unop(Iop_1Sto32, mkexpr(t11))), 4170 binop(Iop_Or32, 4171 unop(Iop_1Sto32, mkexpr(t12)), 4172 unop(Iop_1Sto32, mkexpr(t13))))); 4173 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4174 mkexpr(t14), 4175 mkU32(0)), 4176 binop(Iop_Or32, 4177 getDSPControl(), 4178 mkU32(0x00800000)), 4179 getDSPControl())); 4180 4181 assign(t16, binop(Iop_And32, 4182 unop(Iop_64HIto32, 4183 mkexpr(t9)), 4184 mkU32(0x80000000))); 4185 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4186 mkexpr(t14), 4187 mkU32(0)), 4188 IRExpr_ITE(binop(Iop_CmpEQ32, 4189 mkexpr(t16), 4190 mkU32(0)), 4191 mkU32(0x7fffffff), 4192 mkU32(0x80000000)), 4193 unop(Iop_64to32, mkexpr(t9)))); 4194 break; 4195 } 4196 case 0x7: { /* EXTRV_RS.W */ 4197 DIP("extrv_rs.w r%d, ac%d, r%d", rt, ac, rs); 4198 vassert(!mode64); 4199 t0 = newTemp(Ity_I64); 4200 t1 = newTemp(Ity_I64); 4201 t2 = newTemp(Ity_I32); 4202 t3 = newTemp(Ity_I1); 4203 t4 = newTemp(Ity_I1); 4204 t5 = newTemp(Ity_I1); 4205 t6 = newTemp(Ity_I1); 4206 t7 = newTemp(Ity_I32); 4207 t8 = newTemp(Ity_I64); 4208 t9 = newTemp(Ity_I64); 4209 t10 = newTemp(Ity_I1); 4210 t11 = newTemp(Ity_I1); 4211 t12 = newTemp(Ity_I1); 4212 t13 = newTemp(Ity_I1); 4213 t14 = newTemp(Ity_I32); 4214 t15 = newTemp(Ity_I32); 4215 t16 = newTemp(Ity_I32); 4216 t17 = newTemp(Ity_I1); 4217 4218 assign(t15, binop(Iop_And32, 4219 getIReg(rs), 4220 mkU32(0x1f))); 4221 assign(t17, binop(Iop_CmpEQ32, 4222 mkexpr(t15), 4223 mkU32(0))); 4224 assign(t0, getAcc(ac)); 4225 assign(t1, IRExpr_ITE(mkexpr(t17), 4226 mkexpr(t0), 4227 binop(Iop_Sar64, 4228 mkexpr(t0), 4229 unop(Iop_32to8, 4230 mkexpr(t15))))); 4231 4232 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4233 assign(t3, binop(Iop_CmpNE32, 4234 unop(Iop_64HIto32, 4235 mkexpr(t1)), 4236 mkU32(0))); 4237 assign(t4, binop(Iop_CmpNE32, 4238 binop(Iop_And32, 4239 unop(Iop_64to32, 4240 mkexpr(t1)), 4241 mkU32(0x80000000)), 4242 mkU32(0))); 4243 /* Check if bits 63..31 of the result in t1 aren't 4244 0x1ffffffff. */ 4245 assign(t5, binop(Iop_CmpNE32, 4246 unop(Iop_64HIto32, 4247 mkexpr(t1)), 4248 mkU32(0xffffffff))); 4249 assign(t6, binop(Iop_CmpNE32, 4250 binop(Iop_And32, 4251 unop(Iop_64to32, 4252 mkexpr(t1)), 4253 mkU32(0x80000000)), 4254 mkU32(0x80000000))); 4255 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4256 control register. */ 4257 assign(t7, binop(Iop_And32, 4258 binop(Iop_Or32, 4259 unop(Iop_1Sto32, mkexpr(t3)), 4260 unop(Iop_1Sto32, mkexpr(t4))), 4261 binop(Iop_Or32, 4262 unop(Iop_1Sto32, mkexpr(t5)), 4263 unop(Iop_1Sto32, mkexpr(t6))))); 4264 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4265 mkexpr(t7), 4266 mkU32(0)), 4267 binop(Iop_Or32, 4268 getDSPControl(), 4269 mkU32(0x00800000)), 4270 getDSPControl())); 4271 4272 /* If the last discarded bit is 1, there would be carry 4273 when rounding, otherwise there wouldn't. We use that 4274 fact and just add the value of the last discarded bit 4275 to the least sifgnificant bit of the shifted value 4276 from acc. */ 4277 assign(t8, 4278 IRExpr_ITE(mkexpr(t17), 4279 mkU64(0x0ULL), 4280 binop(Iop_And64, 4281 binop(Iop_Shr64, 4282 mkexpr(t0), 4283 unop(Iop_32to8, 4284 binop(Iop_Sub32, 4285 mkexpr(t15), 4286 mkU32(1)))), 4287 mkU64(0x1ULL)))); 4288 4289 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4290 4291 /* Repeat previous steps for the rounded value. */ 4292 assign(t10, binop(Iop_CmpNE32, 4293 unop(Iop_64HIto32, 4294 mkexpr(t9)), 4295 mkU32(0))); 4296 assign(t11, binop(Iop_CmpNE32, 4297 binop(Iop_And32, 4298 unop(Iop_64to32, 4299 mkexpr(t9)), 4300 mkU32(0x80000000)), 4301 mkU32(0))); 4302 4303 assign(t12, binop(Iop_CmpNE32, 4304 unop(Iop_64HIto32, 4305 mkexpr(t9)), 4306 mkU32(0xffffffff))); 4307 assign(t13, binop(Iop_CmpNE32, 4308 binop(Iop_And32, 4309 unop(Iop_64to32, 4310 mkexpr(t9)), 4311 mkU32(0x80000000)), 4312 mkU32(0x80000000))); 4313 4314 assign(t14, binop(Iop_And32, 4315 binop(Iop_Or32, 4316 unop(Iop_1Sto32, mkexpr(t10)), 4317 unop(Iop_1Sto32, mkexpr(t11))), 4318 binop(Iop_Or32, 4319 unop(Iop_1Sto32, mkexpr(t12)), 4320 unop(Iop_1Sto32, mkexpr(t13))))); 4321 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4322 mkexpr(t14), 4323 mkU32(0)), 4324 binop(Iop_Or32, 4325 getDSPControl(), 4326 mkU32(0x00800000)), 4327 getDSPControl())); 4328 4329 assign(t16, binop(Iop_And32, 4330 unop(Iop_64HIto32, 4331 mkexpr(t9)), 4332 mkU32(0x80000000))); 4333 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4334 mkexpr(t14), 4335 mkU32(0)), 4336 IRExpr_ITE(binop(Iop_CmpEQ32, 4337 mkexpr(t16), 4338 mkU32(0)), 4339 mkU32(0x7fffffff), 4340 mkU32(0x80000000)), 4341 unop(Iop_64to32, mkexpr(t9)))); 4342 break; 4343 } 4344 case 0xA: { /* EXTPDP */ 4345 DIP("extpdp r%d, ac%d, %d", rt, ac, rs); 4346 vassert(!mode64); 4347 t0 = newTemp(Ity_I64); 4348 t1 = newTemp(Ity_I32); 4349 t2 = newTemp(Ity_I1); 4350 t3 = newTemp(Ity_I1); 4351 t4 = newTemp(Ity_I8); 4352 t5 = newTemp(Ity_I64); 4353 t6 = newTemp(Ity_I64); 4354 t7 = newTemp(Ity_I32); 4355 t8 = newTemp(Ity_I32); 4356 4357 assign(t0, getAcc(ac)); 4358 /* Extract pos field of DSPControl register. */ 4359 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4360 4361 /* Check if (pos - size) >= 0 [size <= pos] 4362 if (pos < size) 4363 put 1 to EFI field of DSPControl register 4364 else 4365 extract bits from acc and put 0 to EFI field of 4366 DSPCtrl */ 4367 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 4368 4369 assign(t8, binop(Iop_Or32, 4370 binop(Iop_And32, 4371 getDSPControl(), 4372 mkU32(0xffffbfc0)), 4373 binop(Iop_And32, 4374 binop(Iop_Sub32, 4375 binop(Iop_And32, 4376 getDSPControl(), 4377 mkU32(0x3f)), 4378 mkU32(rs+1)), 4379 mkU32(0x3f)))); 4380 putDSPControl(IRExpr_ITE(mkexpr(t2), 4381 binop(Iop_Or32, 4382 binop(Iop_And32, 4383 getDSPControl(), 4384 mkU32(0xffffbfff)), 4385 mkU32(0x4000)), 4386 mkexpr(t8))); 4387 4388 /* If pos <= 31, shift right the value from the acc 4389 (pos-size) times and take (size+1) bits from the least 4390 significant positions. Otherwise, shift left the value 4391 (63-pos) times, take (size+1) bits from the most 4392 significant positions and shift right (31-size) times. 4393 */ 4394 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4395 4396 assign(t4, 4397 IRExpr_ITE(mkexpr(t3), 4398 unop(Iop_32to8, 4399 binop(Iop_Sub32, 4400 mkexpr(t1), mkU32(rs))), 4401 unop(Iop_32to8, 4402 binop(Iop_Sub32, 4403 mkU32(63), mkexpr(t1))))); 4404 4405 assign(t5, IRExpr_ITE(mkexpr(t3), 4406 binop(Iop_Shr64, 4407 mkexpr(t0), mkexpr(t4)), 4408 binop(Iop_Shl64, 4409 mkexpr(t0), mkexpr(t4)))); 4410 4411 /* t6 holds a mask for bit extraction. */ 4412 assign(t6, 4413 IRExpr_ITE(mkexpr(t3), 4414 unop(Iop_Not64, 4415 binop(Iop_Shl64, 4416 mkU64(0xffffffffffffffffULL), 4417 mkU8(rs+1))), 4418 unop(Iop_Not64, 4419 binop(Iop_Shr64, 4420 mkU64(0xffffffffffffffffULL), 4421 mkU8(rs+1))))); 4422 4423 assign(t7, IRExpr_ITE(mkexpr(t3), 4424 unop(Iop_64to32, 4425 binop(Iop_And64, 4426 mkexpr(t5), 4427 mkexpr(t6))), 4428 binop(Iop_Shr32, 4429 unop(Iop_64HIto32, 4430 binop(Iop_And64, 4431 mkexpr(t5), 4432 mkexpr(t6))), 4433 mkU8(31-rs)))); 4434 4435 putIReg(rt, mkexpr(t7)); 4436 break; 4437 } 4438 case 0xB: { /* EXTPDPV */ 4439 DIP("extpdpv r%d, ac%d, r%d", rt, ac, rs); 4440 vassert(!mode64); 4441 t0 = newTemp(Ity_I64); 4442 t1 = newTemp(Ity_I32); 4443 t2 = newTemp(Ity_I1); 4444 t3 = newTemp(Ity_I1); 4445 t4 = newTemp(Ity_I8); 4446 t5 = newTemp(Ity_I64); 4447 t6 = newTemp(Ity_I64); 4448 t7 = newTemp(Ity_I32); 4449 t8 = newTemp(Ity_I32); 4450 t9 = newTemp(Ity_I32); 4451 4452 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 4453 assign(t0, getAcc(ac)); 4454 /* Extract pos field of DSPControl register. */ 4455 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4456 4457 /* Check if (pos - size) >= 0 [size <= pos] 4458 if (pos < size) 4459 put 1 to EFI field of DSPControl register 4460 else 4461 extract bits from acc and put 0 to EFI field of 4462 DSPCtrl */ 4463 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 4464 4465 assign(t9, binop(Iop_Or32, 4466 binop(Iop_And32, 4467 getDSPControl(), 4468 mkU32(0xffffbfc0)), 4469 binop(Iop_And32, 4470 binop(Iop_Sub32, 4471 binop(Iop_And32, 4472 getDSPControl(), 4473 mkU32(0x3f)), 4474 binop(Iop_Add32, 4475 mkexpr(t8), 4476 mkU32(0x1))), 4477 mkU32(0x3f)))); 4478 putDSPControl(IRExpr_ITE(mkexpr(t2), 4479 binop(Iop_Or32, 4480 binop(Iop_And32, 4481 getDSPControl(), 4482 mkU32(0xffffbfff)), 4483 mkU32(0x4000)), 4484 mkexpr(t9))); 4485 4486 /* If pos <= 31, shift right the value from the acc 4487 (pos-size) times and take (size+1) bits from the least 4488 significant positions. Otherwise, shift left the value 4489 (63-pos) times, take (size+1) bits from the most 4490 significant positions and shift right (31-size) times. 4491 */ 4492 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4493 4494 assign(t4, 4495 IRExpr_ITE(mkexpr(t3), 4496 unop(Iop_32to8, 4497 binop(Iop_Sub32, 4498 mkexpr(t1), mkexpr(t8))), 4499 unop(Iop_32to8, 4500 binop(Iop_Sub32, 4501 mkU32(63), mkexpr(t1))))); 4502 4503 assign(t5, IRExpr_ITE(mkexpr(t3), 4504 binop(Iop_Shr64, 4505 mkexpr(t0), mkexpr(t4)), 4506 binop(Iop_Shl64, 4507 mkexpr(t0), mkexpr(t4)))); 4508 4509 /* t6 holds a mask for bit extraction. */ 4510 assign(t6, 4511 IRExpr_ITE(mkexpr(t3), 4512 unop(Iop_Not64, 4513 binop(Iop_Shl64, 4514 mkU64(0xffffffffffffffffULL), 4515 unop(Iop_32to8, 4516 binop(Iop_Add32, 4517 mkexpr(t8), 4518 mkU32(1))))), 4519 unop(Iop_Not64, 4520 binop(Iop_Shr64, 4521 mkU64(0xffffffffffffffffULL), 4522 unop(Iop_32to8, 4523 binop(Iop_Add32, 4524 mkexpr(t8), 4525 mkU32(1))))))); 4526 4527 assign(t7, IRExpr_ITE(mkexpr(t3), 4528 unop(Iop_64to32, 4529 binop(Iop_And64, 4530 mkexpr(t5), 4531 mkexpr(t6))), 4532 binop(Iop_Shr32, 4533 unop(Iop_64HIto32, 4534 binop(Iop_And64, 4535 mkexpr(t5), 4536 mkexpr(t6))), 4537 unop(Iop_32to8, 4538 binop(Iop_Sub32, 4539 mkU32(31), 4540 mkexpr(t8)))))); 4541 4542 putIReg(rt, mkexpr(t7)); 4543 break; 4544 } 4545 case 0xE: { /* EXTR_S.H */ 4546 DIP("extr_s.h r%d, ac%d, %d", rt, ac, rs); 4547 vassert(!mode64); 4548 t0 = newTemp(Ity_I64); 4549 t1 = newTemp(Ity_I64); 4550 t2 = newTemp(Ity_I32); 4551 t3 = newTemp(Ity_I64); 4552 t4 = newTemp(Ity_I32); 4553 t5 = newTemp(Ity_I32); 4554 t6 = newTemp(Ity_I64); 4555 t7 = newTemp(Ity_I32); 4556 t9 = newTemp(Ity_I32); 4557 4558 assign(t0, getAcc(ac)); 4559 4560 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4561 4562 assign(t2, binop(Iop_Or32, 4563 getDSPControl(), mkU32(0x00800000))); 4564 4565 assign(t9, binop(Iop_And32, 4566 unop(Iop_64to32, 4567 mkexpr(t1)), 4568 mkU32(0x80000000))); 4569 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4570 mkexpr(t9), 4571 binop(Iop_And32, 4572 unop(Iop_64HIto32, 4573 mkexpr(t0)), 4574 mkU32(0x80000000))), 4575 mkexpr(t2), 4576 getDSPControl())); 4577 4578 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4579 1. subtract 0x7fff from t1 4580 2. if the resulting number is positive (sign bit = 0) 4581 and any of the other bits is 1, the value is > 0. */ 4582 assign(t3, binop(Iop_Sub64, 4583 mkexpr(t1), 4584 mkU64(0x0000000000007fffULL))); 4585 assign(t4, binop(Iop_And32, 4586 binop(Iop_Or32, 4587 unop(Iop_1Sto32, 4588 binop(Iop_CmpNE32, 4589 mkU32(0), 4590 binop(Iop_And32, 4591 unop(Iop_64HIto32, 4592 mkexpr(t3)), 4593 mkU32(0x7fffffff)))), 4594 unop(Iop_1Sto32, 4595 binop(Iop_CmpNE32, 4596 mkU32(0), 4597 unop(Iop_64to32, 4598 mkexpr(t3))))), 4599 unop(Iop_1Sto32, 4600 binop(Iop_CmpEQ32, 4601 binop(Iop_And32, 4602 unop(Iop_64HIto32, 4603 mkexpr(t3)), 4604 mkU32(0x80000000)), 4605 mkU32(0))))); 4606 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4607 mkU32(0), 4608 mkexpr(t4)), 4609 binop(Iop_Or32, 4610 getDSPControl(), 4611 mkU32(0x00800000)), 4612 getDSPControl())); 4613 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4614 1. subtract t1 from 0xffffffffffff8000 4615 2. if the resulting number is positive (sign bit = 0) 4616 and any of the other bits is 1, the value is > 0 */ 4617 assign(t6, binop(Iop_Sub64, 4618 mkU64(0xffffffffffff8000ULL), 4619 mkexpr(t1))); 4620 assign(t7, binop(Iop_And32, 4621 binop(Iop_Or32, 4622 unop(Iop_1Sto32, 4623 binop(Iop_CmpNE32, 4624 mkU32(0), 4625 binop(Iop_And32, 4626 unop(Iop_64HIto32, 4627 mkexpr(t6)), 4628 mkU32(0x7fffffff)))), 4629 unop(Iop_1Sto32, 4630 binop(Iop_CmpNE32, 4631 mkU32(0), 4632 unop(Iop_64to32, 4633 mkexpr(t6))))), 4634 unop(Iop_1Sto32, 4635 binop(Iop_CmpEQ32, 4636 binop(Iop_And32, 4637 unop(Iop_64HIto32, 4638 mkexpr(t6)), 4639 mkU32(0x80000000)), 4640 mkU32(0))))); 4641 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4642 mkU32(0), 4643 mkexpr(t7)), 4644 binop(Iop_Or32, 4645 getDSPControl(), 4646 mkU32(0x00800000)), 4647 getDSPControl())); 4648 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4649 mkU32(0), 4650 mkexpr(t4)), 4651 mkU32(0x00007fff), 4652 IRExpr_ITE(binop(Iop_CmpNE32, 4653 mkU32(0), 4654 mkexpr(t7)), 4655 mkU32(0xffff8000), 4656 unop(Iop_64to32, 4657 mkexpr(t1))))); 4658 break; 4659 } 4660 case 0xF: { /* EXTRV_S.H */ 4661 DIP("extrv_s.h r%d, ac%d, %d", rt, ac, rs); 4662 vassert(!mode64); 4663 t0 = newTemp(Ity_I64); 4664 t1 = newTemp(Ity_I64); 4665 t2 = newTemp(Ity_I32); 4666 t3 = newTemp(Ity_I64); 4667 t4 = newTemp(Ity_I32); 4668 t5 = newTemp(Ity_I32); 4669 t6 = newTemp(Ity_I64); 4670 t7 = newTemp(Ity_I32); 4671 t9 = newTemp(Ity_I32); 4672 4673 assign(t0, getAcc(ac)); 4674 4675 assign(t1, binop(Iop_Sar64, 4676 mkexpr(t0), 4677 unop(Iop_32to8, 4678 binop(Iop_And32, 4679 getIReg(rs), 4680 mkU32(0x1f))))); 4681 4682 assign(t2, binop(Iop_Or32, 4683 getDSPControl(), mkU32(0x00800000))); 4684 4685 assign(t9, binop(Iop_And32, 4686 unop(Iop_64to32, 4687 mkexpr(t1)), 4688 mkU32(0x80000000))); 4689 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4690 mkexpr(t9), 4691 binop(Iop_And32, 4692 unop(Iop_64HIto32, 4693 mkexpr(t0)), 4694 mkU32(0x80000000))), 4695 mkexpr(t2), 4696 getDSPControl())); 4697 4698 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4699 1. subtract 0x7fff from t1 4700 2. if the resulting number is positive (sign bit = 0) 4701 and any of the other bits is 1, the value is > 0. */ 4702 assign(t3, binop(Iop_Sub64, 4703 mkexpr(t1), 4704 mkU64(0x0000000000007fffULL))); 4705 assign(t4, binop(Iop_And32, 4706 binop(Iop_Or32, 4707 unop(Iop_1Sto32, 4708 binop(Iop_CmpNE32, 4709 mkU32(0), 4710 binop(Iop_And32, 4711 unop(Iop_64HIto32, 4712 mkexpr(t3)), 4713 mkU32(0x7fffffff)))), 4714 unop(Iop_1Sto32, 4715 binop(Iop_CmpNE32, 4716 mkU32(0), 4717 unop(Iop_64to32, 4718 mkexpr(t3))))), 4719 unop(Iop_1Sto32, 4720 binop(Iop_CmpEQ32, 4721 binop(Iop_And32, 4722 unop(Iop_64HIto32, 4723 mkexpr(t3)), 4724 mkU32(0x80000000)), 4725 mkU32(0))))); 4726 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4727 mkU32(0), 4728 mkexpr(t4)), 4729 binop(Iop_Or32, 4730 getDSPControl(), 4731 mkU32(0x00800000)), 4732 getDSPControl())); 4733 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4734 1. subtract t1 from 0xffffffffffff8000 4735 2. if the resulting number is positive (sign bit = 0) 4736 and any of the other bits is 1, the value is > 0 */ 4737 assign(t6, binop(Iop_Sub64, 4738 mkU64(0xffffffffffff8000ULL), 4739 mkexpr(t1))); 4740 assign(t7, binop(Iop_And32, 4741 binop(Iop_Or32, 4742 unop(Iop_1Sto32, 4743 binop(Iop_CmpNE32, 4744 mkU32(0), 4745 binop(Iop_And32, 4746 unop(Iop_64HIto32, 4747 mkexpr(t6)), 4748 mkU32(0x7fffffff)))), 4749 unop(Iop_1Sto32, 4750 binop(Iop_CmpNE32, 4751 mkU32(0), 4752 unop(Iop_64to32, 4753 mkexpr(t6))))), 4754 unop(Iop_1Sto32, 4755 binop(Iop_CmpEQ32, 4756 binop(Iop_And32, 4757 unop(Iop_64HIto32, 4758 mkexpr(t6)), 4759 mkU32(0x80000000)), 4760 mkU32(0))))); 4761 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4762 mkU32(0), 4763 mkexpr(t7)), 4764 binop(Iop_Or32, 4765 getDSPControl(), 4766 mkU32(0x00800000)), 4767 getDSPControl())); 4768 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4769 mkU32(0), 4770 mkexpr(t4)), 4771 mkU32(0x00007fff), 4772 IRExpr_ITE(binop(Iop_CmpNE32, 4773 mkU32(0), 4774 mkexpr(t7)), 4775 mkU32(0xffff8000), 4776 unop(Iop_64to32, 4777 mkexpr(t1))))); 4778 break; 4779 } 4780 case 0x12: { /* RDDSP*/ 4781 DIP("rddsp r%d, mask 0x%x", rd, rddsp_mask); 4782 vassert(!mode64); 4783 4784 putIReg(rd, mkU32(0x0)); 4785 4786 if ((rddsp_mask & 0x1) == 0x1) { 4787 /* Read pos field (bits 5-0) of DSPControl register. */ 4788 putIReg(rd, binop(Iop_Or32, 4789 getIReg(rd), 4790 binop(Iop_And32, 4791 getDSPControl(), 4792 mkU32(0x0000003F)))); 4793 } 4794 4795 if ((rddsp_mask & 0x2) == 0x2) { 4796 /* Read scount field (bits 12-7) of DSPControl 4797 register. */ 4798 putIReg(rd, binop(Iop_Or32, 4799 getIReg(rd), 4800 binop(Iop_And32, 4801 getDSPControl(), 4802 mkU32(0x00001F80)))); 4803 } 4804 4805 if ((rddsp_mask & 0x4) == 0x4) { 4806 /* Read C field (bit 13) of DSPControl register. */ 4807 putIReg(rd, binop(Iop_Or32, 4808 getIReg(rd), 4809 binop(Iop_And32, 4810 getDSPControl(), 4811 mkU32(0x00002000)))); 4812 } 4813 4814 if ((rddsp_mask & 0x8) == 0x8) { 4815 /* Read outflag field (bit s 23-16) of DSPControl 4816 register. */ 4817 putIReg(rd, binop(Iop_Or32, 4818 getIReg(rd), 4819 binop(Iop_And32, 4820 getDSPControl(), 4821 mkU32(0x00FF0000)))); 4822 } 4823 4824 if ((rddsp_mask & 0x10) == 0x10) { 4825 /* Read ccond field (bits 31-24) of DSPControl 4826 register. */ 4827 putIReg(rd, binop(Iop_Or32, 4828 getIReg(rd), 4829 binop(Iop_And32, 4830 getDSPControl(), 4831 mkU32(0xFF000000)))); 4832 } 4833 4834 if ((rddsp_mask & 0x20) == 0x20) { 4835 /* Read EFI field (bit 14) of DSPControl register. */ 4836 putIReg(rd, binop(Iop_Or32, 4837 getIReg(rd), 4838 binop(Iop_And32, 4839 getDSPControl(), 4840 mkU32(0x00004000)))); 4841 } 4842 4843 if ((rddsp_mask & 0x3f) == 0x3f) { 4844 /* Read all fields of DSPControl register. */ 4845 putIReg(rd, getDSPControl()); 4846 } 4847 break; 4848 } 4849 case 0x13: { /* WRDSP */ 4850 DIP("wrdsp r%d, mask 0x%x", rs, wrdsp_mask); 4851 vassert(!mode64); 4852 4853 if ((wrdsp_mask & 0x3f) == 0x3f) { 4854 /* If mips64 put all fields of rs, except bit 15 and bit 4855 6, to DSPControl register, otherwise put all except 4856 bits 15, 6 and bits 31..28. */ 4857 putDSPControl(mode64 ? 4858 binop(Iop_And32, 4859 getIReg(rs), 4860 mkU32(0xffff7fbf)) : 4861 binop(Iop_And32, 4862 getIReg(rs), 4863 mkU32(0x0fff7fbf))); 4864 } else { 4865 if ((wrdsp_mask & 0x1) == 0x1) { 4866 /* Put bits 5-0 of rs to DSPControl register pos 4867 field. */ 4868 putDSPControl(binop(Iop_Or32, 4869 binop(Iop_And32, 4870 getDSPControl(), 4871 mkU32(0xFFFF7F40)), 4872 binop(Iop_And32, 4873 getIReg(rs), 4874 mkU32(0x0000003F)))); 4875 } 4876 4877 if ((wrdsp_mask & 0x2) == 0x2) { 4878 /* Put bits 12-7 of rs to DSPControl scount field. */ 4879 putDSPControl(binop(Iop_Or32, 4880 binop(Iop_And32, 4881 getDSPControl(), 4882 mkU32(0xFFFFE03F)), 4883 binop(Iop_And32, 4884 getIReg(rs), 4885 mkU32(0x00001F80)))); 4886 } 4887 4888 if ((wrdsp_mask & 0x4) == 0x4) { 4889 /* Put bit 13 of rs to DSPControl register C 4890 field. */ 4891 putDSPControl(binop(Iop_Or32, 4892 binop(Iop_And32, 4893 getDSPControl(), 4894 mkU32(0xFFFF5FBF)), 4895 binop(Iop_And32, 4896 getIReg(rs), 4897 mkU32(0x00002000)))); 4898 } 4899 4900 if ((wrdsp_mask & 0x8) == 0x8) { 4901 /* Put bits 23-16 of rs to DSPControl reg outflag 4902 field. */ 4903 putDSPControl(binop(Iop_Or32, 4904 binop(Iop_And32, 4905 getDSPControl(), 4906 mkU32(0xFF007FBF)), 4907 binop(Iop_And32, 4908 getIReg(rs), 4909 mkU32(0x00FF0000)))); 4910 } 4911 4912 if ((wrdsp_mask & 0x10) == 0x10) { 4913 /* Put bits 31-24 of rs to DSPControl reg ccond 4914 field. */ 4915 putDSPControl(binop(Iop_Or32, 4916 binop(Iop_And32, 4917 getDSPControl(), 4918 mkU32(0x00FF7FBF)), 4919 binop(Iop_And32, 4920 getIReg(rs), 4921 mode64 ? mkU32(0xFF000000) 4922 : mkU32(0x0F000000)) 4923 ) 4924 ); 4925 } 4926 4927 if ((wrdsp_mask & 0x20) == 0x20) { 4928 /* Put bit 14 of rs to DSPControl register EFI 4929 field. */ 4930 putDSPControl(binop(Iop_Or32, 4931 binop(Iop_And32, 4932 getDSPControl(), 4933 mkU32(0xFFFF3FBF)), 4934 binop(Iop_And32, 4935 getIReg(rs), 4936 mkU32(0x00004000)))); 4937 } 4938 } 4939 break; 4940 } 4941 case 0x1A: { /* SHILO */ 4942 DIP("shilo ac%d, %d", ac, shift); 4943 vassert(!mode64); 4944 t0 = newTemp(Ity_I64); 4945 t1 = newTemp(Ity_I64); 4946 4947 assign(t0, getAcc(ac)); 4948 4949 putAcc(ac, mkexpr(t0)); 4950 4951 if (0x20 == (shift & 0x3f)) { 4952 putAcc(ac, binop(Iop_32HLto64, 4953 unop(Iop_64to32, mkexpr(t0)), 4954 mkU32(0x0))); 4955 } else if (0x20 == (shift & 0x20)) { 4956 assign(t1, binop(Iop_Shl64, 4957 mkexpr(t0), 4958 unop(Iop_32to8, 4959 binop(Iop_Add32, 4960 unop(Iop_Not32, 4961 mkU32(shift)), 4962 mkU32(0x1))))); 4963 4964 putAcc(ac, mkexpr(t1)); 4965 } else { 4966 assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift))); 4967 4968 putAcc(ac, mkexpr(t1)); 4969 } 4970 break; 4971 } 4972 case 0x1B: { /* SHILOV */ 4973 DIP("shilov ac%d, r%d", ac, rs); 4974 vassert(!mode64); 4975 t0 = newTemp(Ity_I64); 4976 t1 = newTemp(Ity_I32); 4977 t2 = newTemp(Ity_I1); 4978 t3 = newTemp(Ity_I64); 4979 t4 = newTemp(Ity_I64); 4980 4981 assign(t0, getAcc(ac)); 4982 assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f))); 4983 assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20))); 4984 assign(t3, binop(Iop_Shl64, 4985 mkexpr(t0), 4986 unop(Iop_32to8, 4987 binop(Iop_Add32, 4988 unop(Iop_Not32, 4989 mkexpr(t1)), 4990 mkU32(0x1))))); 4991 assign(t4, binop(Iop_Shr64, 4992 mkexpr(t0), 4993 unop(Iop_32to8, 4994 mkexpr(t1)))); 4995 4996 putAcc(ac, 4997 IRExpr_ITE(mkexpr(t2), 4998 binop(Iop_32HLto64, 4999 unop(Iop_64to32, mkexpr(t0)), 5000 mkU32(0x0)), 5001 IRExpr_ITE(binop(Iop_CmpEQ32, 5002 binop(Iop_And32, 5003 mkexpr(t1), 5004 mkU32(0x20)), 5005 mkU32(0x20)), 5006 mkexpr(t3), 5007 mkexpr(t4)))); 5008 break; 5009 } 5010 case 0x1F: { /* MTHLIP */ 5011 DIP("mthlip r%d, ac%d", rs, ac); 5012 vassert(!mode64); 5013 t0 = newTemp(Ity_I64); 5014 t1 = newTemp(Ity_I32); 5015 t2 = newTemp(Ity_I32); 5016 t3 = newTemp(Ity_I1); 5017 5018 assign(t0, getAcc(ac)); 5019 putAcc(ac, binop(Iop_32HLto64, 5020 unop(Iop_64to32, mkexpr(t0)), 5021 getIReg(rs))); 5022 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5023 putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U, 5024 mkU32(32), 5025 mkexpr(t1)), 5026 binop(Iop_Or32, 5027 binop(Iop_Sub32, 5028 mkexpr(t1), 5029 mkU32(32)), 5030 binop(Iop_And32, 5031 getDSPControl(), 5032 mkU32(0xffffffc0))), 5033 binop(Iop_Or32, 5034 binop(Iop_Add32, 5035 mkexpr(t1), 5036 mkU32(32)), 5037 binop(Iop_And32, 5038 getDSPControl(), 5039 mkU32(0xffffffc0))))); 5040 break; 5041 } 5042 default: 5043 return -1; 5044 } 5045 break; /* end of EXTR.W */ 5046 } 5047 case 0xA: { /* LX */ 5048 switch(sa) { 5049 case 0x0: { /* LWX */ 5050 DIP("lwx r%d, r%d(r%d)", rd, rt, rs); 5051 vassert(!mode64); 5052 t0 = newTemp(Ity_I32); 5053 5054 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5055 5056 putIReg(rd, load(Ity_I32, mkexpr(t0))); 5057 break; 5058 } 5059 case 0x4: { /* LHX */ 5060 DIP("lhx r%d, r%d(r%d)", rd, rt, rs); 5061 vassert(!mode64); 5062 t0 = newTemp(Ity_I32); 5063 5064 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5065 5066 putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0)))); 5067 break; 5068 } 5069 case 0x6: { /* LBUX */ 5070 DIP("lbux r%d, r%d(r%d)", rd, rt, rs); 5071 vassert(!mode64); 5072 t0 = newTemp(Ity_I32); 5073 5074 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5075 5076 putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0)))); 5077 break; 5078 } 5079 default: 5080 return -1; 5081 } 5082 break; /* end of LX */ 5083 } 5084 case 0xC: { /* INSV */ 5085 switch(sa) { 5086 case 0x0: { /* INSV */ 5087 DIP("insv r%d, r%d", rt, rs); 5088 vassert(!mode64); 5089 5090 t0 = newTemp(Ity_I32); 5091 t1 = newTemp(Ity_I32); 5092 t2 = newTemp(Ity_I8); 5093 t3 = newTemp(Ity_I8); 5094 t4 = newTemp(Ity_I32); 5095 t5 = newTemp(Ity_I1); 5096 t6 = newTemp(Ity_I32); 5097 t7 = newTemp(Ity_I32); 5098 t8 = newTemp(Ity_I32); 5099 t9 = newTemp(Ity_I32); 5100 5101 /* t0 <- pos field of DSPControl register. */ 5102 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5103 /* t1 <- scount field of DSPControl register. */ 5104 assign(t1, binop(Iop_Shr32, 5105 binop(Iop_And32, 5106 getDSPControl(), 5107 mkU32(0x1f80)), 5108 mkU8(7))); 5109 5110 assign(t2, unop(Iop_32to8, 5111 binop(Iop_Add32, 5112 mkexpr(t1), 5113 mkexpr(t0)))); 5114 5115 /* 32-(pos+size) most significant bits of rt. */ 5116 assign(t6, binop(Iop_Shl32, 5117 binop(Iop_Shr32, 5118 getIReg(rt), 5119 mkexpr(t2)), 5120 mkexpr(t2))); 5121 5122 assign(t3, unop(Iop_32to8, 5123 binop(Iop_Sub32, 5124 mkU32(32), 5125 mkexpr(t0)))); 5126 /* Pos least significant bits of rt. */ 5127 assign(t7, binop(Iop_Shr32, 5128 binop(Iop_Shl32, 5129 getIReg(rt), 5130 mkexpr(t3)), 5131 mkexpr(t3))); 5132 5133 /* Size least significant bits of rs, 5134 shifted to appropriate position. */ 5135 assign(t8, binop(Iop_Shl32, 5136 binop(Iop_And32, 5137 getIReg(rs), 5138 unop(Iop_Not32, 5139 binop(Iop_Shl32, 5140 mkU32(0xffffffff), 5141 unop(Iop_32to8, 5142 mkexpr(t1))))), 5143 unop(Iop_32to8, 5144 mkexpr(t0)))); 5145 5146 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 5147 mkexpr(t0), 5148 mkU32(0)), 5149 IRExpr_ITE(binop(Iop_CmpEQ32, 5150 mkexpr(t1), 5151 mkU32(32)), 5152 getIReg(rs), 5153 binop(Iop_Or32, 5154 mkexpr(t6), 5155 mkexpr(t8))), 5156 IRExpr_ITE(binop(Iop_CmpEQ32, 5157 unop(Iop_8Uto32, 5158 mkexpr(t2)), 5159 mkU32(32)), 5160 binop(Iop_Or32, 5161 mkexpr(t7), 5162 mkexpr(t8)), 5163 binop(Iop_Or32, 5164 binop(Iop_Or32, 5165 mkexpr(t6), 5166 mkexpr(t7)), 5167 mkexpr(t8))))); 5168 break; 5169 } 5170 default: 5171 return -1; 5172 } 5173 break; /* enf of INSV */ 5174 } 5175 case 0x10: { /* ADDU.QB */ 5176 switch(sa) { 5177 case 0x00: { /* ADDU.QB */ 5178 DIP("addu.qb r%d, r%d, r%d", rd, rs, rt); 5179 vassert(!mode64); 5180 t0 = newTemp(Ity_I32); 5181 t1 = newTemp(Ity_I1); 5182 t2 = newTemp(Ity_I32); 5183 t3 = newTemp(Ity_I1); 5184 t4 = newTemp(Ity_I32); 5185 t5 = newTemp(Ity_I1); 5186 t6 = newTemp(Ity_I32); 5187 t7 = newTemp(Ity_I1); 5188 t8 = newTemp(Ity_I32); 5189 5190 /* Add rightmost bytes of rs and rt. */ 5191 assign(t0, 5192 binop(Iop_Add32, 5193 unop(Iop_8Uto32, 5194 unop(Iop_16to8, 5195 unop(Iop_32to16, getIReg(rs)))), 5196 unop(Iop_8Uto32, 5197 unop(Iop_16to8, 5198 unop(Iop_32to16, getIReg(rt)))))); 5199 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5200 assign(t1, binop(Iop_CmpEQ32, 5201 binop(Iop_And32, 5202 mkexpr(t0), 5203 mkU32(0x00000100)), 5204 mkU32(0x00000100))); 5205 5206 /* Add bits 15-8 of rs and rt. */ 5207 assign(t2, 5208 binop(Iop_Add32, 5209 unop(Iop_8Uto32, 5210 unop(Iop_16HIto8, 5211 unop(Iop_32to16, getIReg(rs)))), 5212 unop(Iop_8Uto32, 5213 unop(Iop_16HIto8, 5214 unop(Iop_32to16, getIReg(rt)))))); 5215 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5216 assign(t3, binop(Iop_CmpEQ32, 5217 binop(Iop_And32, 5218 mkexpr(t2), 5219 mkU32(0x00000100)), 5220 mkU32(0x00000100))); 5221 5222 /* Add bits 15-8 of rs and rt. */ 5223 assign(t4, 5224 binop(Iop_Add32, 5225 unop(Iop_8Uto32, 5226 unop(Iop_16to8, 5227 unop(Iop_32HIto16, getIReg(rs)))), 5228 unop(Iop_8Uto32, 5229 unop(Iop_16to8, 5230 unop(Iop_32HIto16, getIReg(rt)))))); 5231 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5232 assign(t5, binop(Iop_CmpEQ32, 5233 binop(Iop_And32, 5234 mkexpr(t4), 5235 mkU32(0x00000100)), 5236 mkU32(0x00000100))); 5237 5238 /* Add bits 15-8 of rs and rt. */ 5239 assign(t6, 5240 binop(Iop_Add32, 5241 unop(Iop_8Uto32, 5242 unop(Iop_16HIto8, 5243 unop(Iop_32HIto16, getIReg(rs)))), 5244 unop(Iop_8Uto32, 5245 unop(Iop_16HIto8, 5246 unop(Iop_32HIto16, getIReg(rt)))))); 5247 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5248 assign(t7, binop(Iop_CmpEQ32, 5249 binop(Iop_And32, 5250 mkexpr(t6), 5251 mkU32(0x00000100)), 5252 mkU32(0x00000100))); 5253 5254 assign(t8, 5255 binop(Iop_Or32, 5256 binop(Iop_Or32, 5257 binop(Iop_Or32, 5258 unop(Iop_1Sto32, mkexpr(t7)), 5259 unop(Iop_1Sto32, mkexpr(t5))), 5260 unop(Iop_1Sto32, mkexpr(t3))), 5261 unop(Iop_1Sto32, mkexpr(t1)))); 5262 5263 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5264 mkexpr(t8), 5265 mkU32(0x0)), 5266 getDSPControl(), 5267 binop(Iop_Or32, 5268 getDSPControl(), 5269 mkU32(0x00100000)))); 5270 5271 putIReg(rd, binop(Iop_16HLto32, 5272 binop(Iop_8HLto16, 5273 unop(Iop_32to8, mkexpr(t6)), 5274 unop(Iop_32to8, mkexpr(t4))), 5275 binop(Iop_8HLto16, 5276 unop(Iop_32to8, mkexpr(t2)), 5277 unop(Iop_32to8, mkexpr(t0))))); 5278 break; 5279 } 5280 case 0x1: { /* SUBU.QB */ 5281 DIP("subu.qb r%d, r%d, r%d", rd, rs, rt); 5282 vassert(!mode64); 5283 t0 = newTemp(Ity_I32); 5284 t1 = newTemp(Ity_I1); 5285 t2 = newTemp(Ity_I32); 5286 t3 = newTemp(Ity_I1); 5287 t4 = newTemp(Ity_I32); 5288 t5 = newTemp(Ity_I1); 5289 t6 = newTemp(Ity_I32); 5290 t7 = newTemp(Ity_I1); 5291 t8 = newTemp(Ity_I32); 5292 5293 /* Subtract rightmost bytes of rs and rt. */ 5294 assign(t0, 5295 binop(Iop_Sub32, 5296 unop(Iop_8Uto32, 5297 unop(Iop_16to8, 5298 unop(Iop_32to16, getIReg(rs)))), 5299 unop(Iop_8Uto32, 5300 unop(Iop_16to8, 5301 unop(Iop_32to16, getIReg(rt)))))); 5302 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5303 assign(t1, binop(Iop_CmpEQ32, 5304 binop(Iop_And32, 5305 mkexpr(t0), 5306 mkU32(0x00000100)), 5307 mkU32(0x00000100))); 5308 5309 /* Subtract bits 15-8 of rs and rt. */ 5310 assign(t2, 5311 binop(Iop_Sub32, 5312 unop(Iop_8Uto32, 5313 unop(Iop_16HIto8, 5314 unop(Iop_32to16, getIReg(rs)))), 5315 unop(Iop_8Uto32, 5316 unop(Iop_16HIto8, 5317 unop(Iop_32to16, getIReg(rt)))))); 5318 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5319 assign(t3, binop(Iop_CmpEQ32, 5320 binop(Iop_And32, 5321 mkexpr(t2), 5322 mkU32(0x00000100)), 5323 mkU32(0x00000100))); 5324 5325 /* Subtract bits 15-8 of rs and rt. */ 5326 assign(t4, 5327 binop(Iop_Sub32, 5328 unop(Iop_8Uto32, 5329 unop(Iop_16to8, 5330 unop(Iop_32HIto16, getIReg(rs)))), 5331 unop(Iop_8Uto32, 5332 unop(Iop_16to8, 5333 unop(Iop_32HIto16, getIReg(rt)))))); 5334 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5335 assign(t5, binop(Iop_CmpEQ32, 5336 binop(Iop_And32, 5337 mkexpr(t4), 5338 mkU32(0x00000100)), 5339 mkU32(0x00000100))); 5340 5341 /* Subtract bits 15-8 of rs and rt. */ 5342 assign(t6, 5343 binop(Iop_Sub32, 5344 unop(Iop_8Uto32, 5345 unop(Iop_16HIto8, 5346 unop(Iop_32HIto16, getIReg(rs)))), 5347 unop(Iop_8Uto32, 5348 unop(Iop_16HIto8, 5349 unop(Iop_32HIto16, getIReg(rt)))))); 5350 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5351 assign(t7, binop(Iop_CmpEQ32, 5352 binop(Iop_And32, 5353 mkexpr(t6), 5354 mkU32(0x00000100)), 5355 mkU32(0x00000100))); 5356 5357 assign(t8, binop(Iop_Or32, 5358 binop(Iop_Or32, 5359 binop(Iop_Or32, 5360 unop(Iop_1Sto32, mkexpr(t7)), 5361 unop(Iop_1Sto32, mkexpr(t5))), 5362 unop(Iop_1Sto32, mkexpr(t3))), 5363 unop(Iop_1Sto32, mkexpr(t1)))); 5364 5365 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5366 mkexpr(t8), 5367 mkU32(0x0)), 5368 getDSPControl(), 5369 binop(Iop_Or32, 5370 getDSPControl(), 5371 mkU32(0x00100000)))); 5372 5373 putIReg(rd, binop(Iop_16HLto32, 5374 binop(Iop_8HLto16, 5375 unop(Iop_32to8, mkexpr(t6)), 5376 unop(Iop_32to8, mkexpr(t4))), 5377 binop(Iop_8HLto16, 5378 unop(Iop_32to8, mkexpr(t2)), 5379 unop(Iop_32to8, mkexpr(t0))))); 5380 break; 5381 } 5382 case 0x04: { /* ADDU_S.QB */ 5383 DIP("addu_s.qb r%d, r%d, r%d", rd, rs, rt); 5384 vassert(!mode64); 5385 t0 = newTemp(Ity_I32); 5386 t1 = newTemp(Ity_I1); 5387 t2 = newTemp(Ity_I8); 5388 t3 = newTemp(Ity_I32); 5389 t4 = newTemp(Ity_I1); 5390 t5 = newTemp(Ity_I8); 5391 t6 = newTemp(Ity_I32); 5392 t7 = newTemp(Ity_I1); 5393 t8 = newTemp(Ity_I8); 5394 t9 = newTemp(Ity_I32); 5395 t10 = newTemp(Ity_I1); 5396 t11 = newTemp(Ity_I8); 5397 t12 = newTemp(Ity_I32); 5398 5399 /* Add rightmost bytes of rs and rt. */ 5400 assign(t0, 5401 binop(Iop_Add32, 5402 unop(Iop_8Uto32, 5403 unop(Iop_16to8, 5404 unop(Iop_32to16, getIReg(rs)))), 5405 unop(Iop_8Uto32, 5406 unop(Iop_16to8, 5407 unop(Iop_32to16, getIReg(rt)))))); 5408 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5409 assign(t1, binop(Iop_CmpEQ32, 5410 binop(Iop_And32, 5411 mkexpr(t0), 5412 mkU32(0x00000100)), 5413 mkU32(0x00000100))); 5414 /* Saturate if necessary. */ 5415 assign(t2, IRExpr_ITE(mkexpr(t1), 5416 mkU8(0xff), 5417 unop(Iop_32to8, mkexpr(t0)))); 5418 5419 /* Add bits 15-8 of rs and rt. */ 5420 assign(t3, 5421 binop(Iop_Add32, 5422 unop(Iop_8Uto32, 5423 unop(Iop_16HIto8, 5424 unop(Iop_32to16, getIReg(rs)))), 5425 unop(Iop_8Uto32, 5426 unop(Iop_16HIto8, 5427 unop(Iop_32to16, getIReg(rt)))))); 5428 /* t4 will be 1 if there is overflow, 0 otherwise. */ 5429 assign(t4, binop(Iop_CmpEQ32, 5430 binop(Iop_And32, 5431 mkexpr(t3), 5432 mkU32(0x00000100)), 5433 mkU32(0x00000100))); 5434 /* Saturate if necessary. */ 5435 assign(t5, IRExpr_ITE(mkexpr(t4), 5436 mkU8(0xff), 5437 unop(Iop_32to8, mkexpr(t3)))); 5438 5439 /* Add bits 15-8 of rs and rt. */ 5440 assign(t6, 5441 binop(Iop_Add32, 5442 unop(Iop_8Uto32, 5443 unop(Iop_16to8, 5444 unop(Iop_32HIto16, getIReg(rs)))), 5445 unop(Iop_8Uto32, 5446 unop(Iop_16to8, 5447 unop(Iop_32HIto16, getIReg(rt)))))); 5448 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5449 assign(t7, binop(Iop_CmpEQ32, 5450 binop(Iop_And32, 5451 mkexpr(t6), 5452 mkU32(0x00000100)), 5453 mkU32(0x00000100))); 5454 /* Saturate if necessary. */ 5455 assign(t8, IRExpr_ITE(mkexpr(t7), 5456 mkU8(0xff), 5457 unop(Iop_32to8, mkexpr(t6)))); 5458 5459 /* Add bits 15-8 of rs and rt. */ 5460 assign(t9, 5461 binop(Iop_Add32, 5462 unop(Iop_8Uto32, 5463 unop(Iop_16HIto8, 5464 unop(Iop_32HIto16, getIReg(rs)))), 5465 unop(Iop_8Uto32, 5466 unop(Iop_16HIto8, 5467 unop(Iop_32HIto16, getIReg(rt)))))); 5468 /* t10 will be 1 if there is overflow, 0 otherwise. */ 5469 assign(t10, binop(Iop_CmpEQ32, 5470 binop(Iop_And32, 5471 mkexpr(t9), 5472 mkU32(0x00000100)), 5473 mkU32(0x00000100))); 5474 /* Saturate if necessary. */ 5475 assign(t11, IRExpr_ITE(mkexpr(t10), 5476 mkU8(0xff), 5477 unop(Iop_32to8, mkexpr(t9)))); 5478 5479 assign(t12, 5480 binop(Iop_Or32, 5481 binop(Iop_Or32, 5482 binop(Iop_Or32, 5483 unop(Iop_1Sto32, mkexpr(t10)), 5484 unop(Iop_1Sto32, mkexpr(t7))), 5485 unop(Iop_1Sto32, mkexpr(t4))), 5486 unop(Iop_1Sto32, mkexpr(t1)))); 5487 5488 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5489 mkexpr(t12), 5490 mkU32(0x0)), 5491 getDSPControl(), 5492 binop(Iop_Or32, 5493 getDSPControl(), 5494 mkU32(0x00100000)))); 5495 5496 putIReg(rd, 5497 binop(Iop_16HLto32, 5498 binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)), 5499 binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2)))); 5500 break; 5501 } 5502 case 0x05: { /* SUBU_S.QB */ 5503 DIP("subu_s.qb r%d, r%d, r%d", rd, rs, rt); 5504 vassert(!mode64); 5505 t1 = newTemp(Ity_I32); 5506 t2 = newTemp(Ity_I1); 5507 t3 = newTemp(Ity_I1); 5508 t4 = newTemp(Ity_I1); 5509 t5 = newTemp(Ity_I1); 5510 t6 = newTemp(Ity_I32); 5511 t7 = newTemp(Ity_I32); 5512 t8 = newTemp(Ity_I32); 5513 t9 = newTemp(Ity_I32); 5514 5515 /* Use C function to easily calculate the result 5516 and write it in the register more conveniently 5517 Underflow is checked using step by step subtraction. */ 5518 assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt))); 5519 5520 /* Subtract each byte of rs and rt. */ 5521 assign(t6, 5522 binop(Iop_Sub32, 5523 unop(Iop_8Uto32, 5524 unop(Iop_16to8, 5525 unop(Iop_32to16, getIReg(rs)))), 5526 unop(Iop_8Uto32, 5527 unop(Iop_16to8, 5528 unop(Iop_32to16, getIReg(rt)))))); 5529 assign(t7, 5530 binop(Iop_Sub32, 5531 unop(Iop_8Uto32, 5532 unop(Iop_16HIto8, 5533 unop(Iop_32to16, getIReg(rs)))), 5534 unop(Iop_8Uto32, 5535 unop(Iop_16HIto8, 5536 unop(Iop_32to16, getIReg(rt)))))); 5537 assign(t8, 5538 binop(Iop_Sub32, 5539 unop(Iop_8Uto32, 5540 unop(Iop_16to8, 5541 unop(Iop_32HIto16, getIReg(rs)))), 5542 unop(Iop_8Uto32, 5543 unop(Iop_16to8, 5544 unop(Iop_32HIto16, getIReg(rt)))))); 5545 assign(t9, 5546 binop(Iop_Sub32, 5547 unop(Iop_8Uto32, 5548 unop(Iop_16HIto8, 5549 unop(Iop_32HIto16, getIReg(rs)))), 5550 unop(Iop_8Uto32, 5551 unop(Iop_16HIto8, 5552 unop(Iop_32HIto16, getIReg(rt)))))); 5553 5554 /* Put 1 to bit 20 in DSPControl if there is underflow 5555 in either byte. */ 5556 assign(t2, binop(Iop_CmpEQ32, 5557 binop(Iop_And32, 5558 mkexpr(t6), 5559 mkU32(0x00000100)), 5560 mkU32(0x00000100))); 5561 putDSPControl(IRExpr_ITE(mkexpr(t2), 5562 binop(Iop_Or32, 5563 getDSPControl(), 5564 mkU32(0x00100000)), 5565 getDSPControl())); 5566 assign(t3, binop(Iop_CmpEQ32, 5567 binop(Iop_And32, 5568 mkexpr(t7), 5569 mkU32(0x00000100)), 5570 mkU32(0x00000100))); 5571 putDSPControl(IRExpr_ITE(mkexpr(t3), 5572 binop(Iop_Or32, 5573 getDSPControl(), 5574 mkU32(0x00100000)), 5575 getDSPControl())); 5576 assign(t4, binop(Iop_CmpEQ32, 5577 binop(Iop_And32, 5578 mkexpr(t8), 5579 mkU32(0x00000100)), 5580 mkU32(0x00000100))); 5581 putDSPControl(IRExpr_ITE(mkexpr(t4), 5582 binop(Iop_Or32, 5583 getDSPControl(), 5584 mkU32(0x00100000)), 5585 getDSPControl())); 5586 assign(t5, binop(Iop_CmpEQ32, 5587 binop(Iop_And32, 5588 mkexpr(t9), 5589 mkU32(0x00000100)), 5590 mkU32(0x00000100))); 5591 putDSPControl(IRExpr_ITE(mkexpr(t5), 5592 binop(Iop_Or32, 5593 getDSPControl(), 5594 mkU32(0x00100000)), 5595 getDSPControl())); 5596 putIReg(rd, mkexpr(t1)); 5597 break; 5598 } 5599 case 0x6: { /* MULEU_S.PH.QBL */ 5600 DIP("muleu_s.ph.qbl r%d, r%d, r%d", rd, rs, rt); 5601 vassert(!mode64); 5602 t0 = newTemp(Ity_I32); 5603 t1 = newTemp(Ity_I32); 5604 t2 = newTemp(Ity_I1); 5605 t3 = newTemp(Ity_I1); 5606 5607 assign(t0, 5608 unop(Iop_64to32, 5609 binop(Iop_MullU32, 5610 unop(Iop_8Uto32, 5611 unop(Iop_16HIto8, 5612 unop(Iop_32HIto16, 5613 getIReg(rs)))), 5614 unop(Iop_16Uto32, 5615 unop(Iop_32HIto16, getIReg(rt)))))); 5616 assign(t1, 5617 unop(Iop_64to32, 5618 binop(Iop_MullU32, 5619 unop(Iop_8Uto32, 5620 unop(Iop_16to8, 5621 unop(Iop_32HIto16, 5622 getIReg(rs)))), 5623 unop(Iop_16Uto32, 5624 unop(Iop_32to16, getIReg(rt)))))); 5625 5626 assign(t2, binop(Iop_CmpNE32, 5627 mkU32(0x0), 5628 binop(Iop_And32, 5629 mkexpr(t0), 5630 mkU32(0x03ff0000)))); 5631 assign(t3, binop(Iop_CmpNE32, 5632 mkU32(0x0), 5633 binop(Iop_And32, 5634 mkexpr(t1), 5635 mkU32(0x03ff0000)))); 5636 putDSPControl(IRExpr_ITE(mkexpr(t2), 5637 binop(Iop_Or32, 5638 getDSPControl(), 5639 mkU32(0x200000)), 5640 IRExpr_ITE(mkexpr(t3), 5641 binop(Iop_Or32, 5642 getDSPControl(), 5643 mkU32(0x200000)), 5644 getDSPControl()))); 5645 putIReg(rd, 5646 binop(Iop_16HLto32, 5647 IRExpr_ITE(mkexpr(t2), 5648 mkU16(0xffff), 5649 unop(Iop_32to16, mkexpr(t0))), 5650 IRExpr_ITE(mkexpr(t3), 5651 mkU16(0xffff), 5652 unop(Iop_32to16, mkexpr(t1))))); 5653 break; 5654 } 5655 case 0x7: { /* MULEU_S.PH.QBR */ 5656 DIP("muleu_s.ph.qbr r%d, r%d, r%d", rd, rs, rt); 5657 vassert(!mode64); 5658 t0 = newTemp(Ity_I32); 5659 t1 = newTemp(Ity_I32); 5660 t2 = newTemp(Ity_I1); 5661 t3 = newTemp(Ity_I1); 5662 5663 assign(t0, unop(Iop_64to32, 5664 binop(Iop_MullU32, 5665 unop(Iop_8Uto32, 5666 unop(Iop_16HIto8, 5667 unop(Iop_32to16, 5668 getIReg(rs)))), 5669 unop(Iop_16Uto32, 5670 unop(Iop_32HIto16, 5671 getIReg(rt)))))); 5672 assign(t1, unop(Iop_64to32, 5673 binop(Iop_MullU32, 5674 unop(Iop_8Uto32, 5675 unop(Iop_16to8, 5676 unop(Iop_32to16, 5677 getIReg(rs)))), 5678 unop(Iop_16Uto32, 5679 unop(Iop_32to16, 5680 getIReg(rt)))))); 5681 5682 assign(t2, binop(Iop_CmpNE32, 5683 mkU32(0x0), 5684 binop(Iop_And32, 5685 mkexpr(t0), 5686 mkU32(0x03ff0000)))); 5687 assign(t3, binop(Iop_CmpNE32, 5688 mkU32(0x0), 5689 binop(Iop_And32, 5690 mkexpr(t1), 5691 mkU32(0x03ff0000)))); 5692 putDSPControl(IRExpr_ITE(mkexpr(t2), 5693 binop(Iop_Or32, 5694 getDSPControl(), 5695 mkU32(0x200000)), 5696 IRExpr_ITE(mkexpr(t3), 5697 binop(Iop_Or32, 5698 getDSPControl(), 5699 mkU32(0x200000)), 5700 getDSPControl()))); 5701 putIReg(rd, binop(Iop_16HLto32, 5702 IRExpr_ITE(mkexpr(t2), 5703 mkU16(0xffff), 5704 unop(Iop_32to16, 5705 mkexpr(t0))), 5706 IRExpr_ITE(mkexpr(t3), 5707 mkU16(0xffff), 5708 unop(Iop_32to16, 5709 mkexpr(t1))))); 5710 break; 5711 } 5712 case 0x08: { /* ADDU.PH */ 5713 DIP("addu.ph r%d, r%d, r%d", rd, rs, rt); 5714 vassert(!mode64); 5715 t0 = newTemp(Ity_I32); 5716 t1 = newTemp(Ity_I1); 5717 t2 = newTemp(Ity_I32); 5718 t3 = newTemp(Ity_I1); 5719 5720 /* Add lower halves. */ 5721 assign(t0, binop(Iop_Add32, 5722 unop(Iop_16Uto32, 5723 unop(Iop_32to16, getIReg(rs))), 5724 unop(Iop_16Uto32, 5725 unop(Iop_32to16, getIReg(rt))))); 5726 5727 /* Detect overflow. */ 5728 assign(t1, binop(Iop_CmpLT32U, 5729 unop(Iop_16Uto32, 5730 unop(Iop_32to16, mkexpr(t0))), 5731 unop(Iop_16Uto32, 5732 unop(Iop_32to16, getIReg(rs))))); 5733 5734 putDSPControl(IRExpr_ITE(mkexpr(t1), 5735 binop(Iop_Or32, 5736 getDSPControl(), 5737 mkU32(0x00100000)), 5738 getDSPControl())); 5739 5740 /* Add higher halves. */ 5741 assign(t2, binop(Iop_Add32, 5742 unop(Iop_16Uto32, 5743 unop(Iop_32HIto16, getIReg(rs))), 5744 unop(Iop_16Uto32, 5745 unop(Iop_32HIto16, getIReg(rt))))); 5746 5747 /* Detect overflow. */ 5748 assign(t3, binop(Iop_CmpLT32U, 5749 unop(Iop_16Uto32, 5750 unop(Iop_32to16, mkexpr(t2))), 5751 unop(Iop_16Uto32, 5752 unop(Iop_32HIto16, 5753 getIReg(rs))))); 5754 5755 putDSPControl(IRExpr_ITE(mkexpr(t3), 5756 binop(Iop_Or32, 5757 getDSPControl(), 5758 mkU32(0x00100000)), 5759 getDSPControl())); 5760 5761 putIReg(rd, binop(Iop_16HLto32, 5762 unop(Iop_32to16, mkexpr(t2)), 5763 unop(Iop_32to16, mkexpr(t0)))); 5764 break; 5765 } 5766 case 0x9: { /* SUBU.PH */ 5767 DIP("subu.ph r%d, r%d, r%d", rd, rs, rt); 5768 vassert(!mode64); 5769 t0 = newTemp(Ity_I32); 5770 t1 = newTemp(Ity_I1); 5771 t2 = newTemp(Ity_I32); 5772 t3 = newTemp(Ity_I1); 5773 5774 /* Substract lower halves. */ 5775 assign(t0, binop(Iop_Sub32, 5776 unop(Iop_16Uto32, 5777 unop(Iop_32to16, getIReg(rs))), 5778 unop(Iop_16Uto32, 5779 unop(Iop_32to16, getIReg(rt))))); 5780 5781 /* Detect underflow. */ 5782 assign(t1, binop(Iop_CmpNE32, 5783 binop(Iop_And32, 5784 mkexpr(t0), 5785 mkU32(0x00010000)), 5786 mkU32(0x0))); 5787 5788 putDSPControl(IRExpr_ITE(mkexpr(t1), 5789 binop(Iop_Or32, 5790 getDSPControl(), 5791 mkU32(0x00100000)), 5792 getDSPControl())); 5793 5794 /* Subtract higher halves. */ 5795 assign(t2, binop(Iop_Sub32, 5796 unop(Iop_16Uto32, 5797 unop(Iop_32HIto16, getIReg(rs))), 5798 unop(Iop_16Uto32, 5799 unop(Iop_32HIto16, getIReg(rt))))); 5800 5801 /* Detect underflow. */ 5802 assign(t3, binop(Iop_CmpNE32, 5803 binop(Iop_And32, 5804 mkexpr(t2), 5805 mkU32(0x00010000)), 5806 mkU32(0x0))); 5807 5808 putDSPControl(IRExpr_ITE(mkexpr(t3), 5809 binop(Iop_Or32, 5810 getDSPControl(), 5811 mkU32(0x00100000)), 5812 getDSPControl())); 5813 5814 putIReg(rd, binop(Iop_16HLto32, 5815 unop(Iop_32to16, mkexpr(t2)), 5816 unop(Iop_32to16, mkexpr(t0)))); 5817 break; 5818 } 5819 case 0xA: { /* ADDQ.PH */ 5820 DIP("addq.ph r%d, r%d, r%d", rd, rs, rt); 5821 vassert(!mode64); 5822 t0 = newTemp(Ity_I32); 5823 t1 = newTemp(Ity_I1); 5824 t2 = newTemp(Ity_I32); 5825 t3 = newTemp(Ity_I1); 5826 t6 = newTemp(Ity_I32); 5827 t7 = newTemp(Ity_I32); 5828 5829 /* Add lower halves. */ 5830 assign(t0, binop(Iop_Add32, 5831 unop(Iop_16Sto32, 5832 unop(Iop_32to16, getIReg(rs))), 5833 unop(Iop_16Sto32, 5834 unop(Iop_32to16, getIReg(rt))))); 5835 5836 /* Bit 16 of the result. */ 5837 assign(t6, binop(Iop_And32, 5838 unop(Iop_16Uto32, 5839 unop(Iop_32HIto16, mkexpr(t0))), 5840 mkU32(0x1))); 5841 /* Detect overflow. */ 5842 assign(t1, binop(Iop_CmpNE32, 5843 binop(Iop_Shr32, 5844 binop(Iop_And32, 5845 mkexpr(t0), 5846 mkU32(0x8000)), 5847 mkU8(15)), 5848 mkexpr(t6))); 5849 5850 putDSPControl(IRExpr_ITE(mkexpr(t1), 5851 binop(Iop_Or32, 5852 getDSPControl(), 5853 mkU32(0x00100000)), 5854 getDSPControl())); 5855 5856 /* Add higher halves. */ 5857 assign(t2, binop(Iop_Add32, 5858 unop(Iop_16Sto32, 5859 unop(Iop_32HIto16, getIReg(rs))), 5860 unop(Iop_16Sto32, 5861 unop(Iop_32HIto16, getIReg(rt))))); 5862 5863 /* Bit 16 of the result. */ 5864 assign(t7, binop(Iop_And32, 5865 unop(Iop_16Uto32, 5866 unop(Iop_32HIto16, mkexpr(t2))), 5867 mkU32(0x1))); 5868 /* Detect overflow. */ 5869 assign(t3, binop(Iop_CmpNE32, 5870 binop(Iop_Shr32, 5871 binop(Iop_And32, 5872 mkexpr(t2), 5873 mkU32(0x00008000)), 5874 mkU8(15)), 5875 mkexpr(t7))); 5876 5877 putDSPControl(IRExpr_ITE(mkexpr(t3), 5878 binop(Iop_Or32, 5879 getDSPControl(), 5880 mkU32(0x00100000)), 5881 getDSPControl())); 5882 5883 putIReg(rd, binop(Iop_16HLto32, 5884 unop(Iop_32to16, mkexpr(t2)), 5885 unop(Iop_32to16, mkexpr(t0)))); 5886 break; 5887 } 5888 case 0xB: { /* SUBQ.PH */ 5889 DIP("subq.ph r%d, r%d, r%d", rd, rs, rt); 5890 vassert(!mode64); 5891 t0 = newTemp(Ity_I32); 5892 t1 = newTemp(Ity_I1); 5893 t2 = newTemp(Ity_I32); 5894 t3 = newTemp(Ity_I1); 5895 t6 = newTemp(Ity_I32); 5896 t7 = newTemp(Ity_I32); 5897 5898 /* Subtract lower halves. */ 5899 assign(t0, binop(Iop_Sub32, 5900 unop(Iop_16Sto32, 5901 unop(Iop_32to16, getIReg(rs))), 5902 unop(Iop_16Sto32, 5903 unop(Iop_32to16, getIReg(rt))))); 5904 5905 /* Bit 16 of the result. */ 5906 assign(t6, binop(Iop_And32, 5907 unop(Iop_16Uto32, 5908 unop(Iop_32HIto16, mkexpr(t0))), 5909 mkU32(0x1))); 5910 /* Compare the signs of input value and the result. */ 5911 assign(t1, binop(Iop_CmpNE32, 5912 binop(Iop_Shr32, 5913 binop(Iop_And32, 5914 mkexpr(t0), 5915 mkU32(0x8000)), 5916 mkU8(15)), 5917 mkexpr(t6))); 5918 5919 putDSPControl(IRExpr_ITE(mkexpr(t1), 5920 binop(Iop_Or32, 5921 getDSPControl(), 5922 mkU32(0x00100000)), 5923 getDSPControl())); 5924 5925 /* Subtract higher halves. */ 5926 assign(t2, binop(Iop_Sub32, 5927 unop(Iop_16Sto32, 5928 unop(Iop_32HIto16, getIReg(rs))), 5929 unop(Iop_16Sto32, 5930 unop(Iop_32HIto16, getIReg(rt))))); 5931 5932 /* Bit 16 of the result. */ 5933 assign(t7, binop(Iop_And32, 5934 unop(Iop_16Uto32, 5935 unop(Iop_32HIto16, mkexpr(t2))), 5936 mkU32(0x1))); 5937 /* Compare the signs of input value and the result. */ 5938 assign(t3, binop(Iop_CmpNE32, 5939 binop(Iop_Shr32, 5940 binop(Iop_And32, 5941 mkexpr(t2), 5942 mkU32(0x00008000)), 5943 mkU8(15)), 5944 mkexpr(t7))); 5945 5946 putDSPControl(IRExpr_ITE(mkexpr(t3), 5947 binop(Iop_Or32, 5948 getDSPControl(), 5949 mkU32(0x00100000)), 5950 getDSPControl())); 5951 5952 putIReg(rd, binop(Iop_16HLto32, 5953 unop(Iop_32to16, mkexpr(t2)), 5954 unop(Iop_32to16, mkexpr(t0)))); 5955 break; 5956 } 5957 case 0xC: { /* ADDU_S.PH */ 5958 DIP("addu_s.ph r%d, r%d, r%d", rd, rs, rt); 5959 vassert(!mode64); 5960 t0 = newTemp(Ity_I32); 5961 t1 = newTemp(Ity_I1); 5962 t2 = newTemp(Ity_I32); 5963 t3 = newTemp(Ity_I1); 5964 5965 /* Add lower halves. */ 5966 assign(t0, binop(Iop_Add32, 5967 unop(Iop_16Uto32, 5968 unop(Iop_32to16, getIReg(rs))), 5969 unop(Iop_16Uto32, 5970 unop(Iop_32to16, getIReg(rt))))); 5971 5972 /* Detect overflow. */ 5973 assign(t1, binop(Iop_CmpLT32U, 5974 unop(Iop_16Uto32, 5975 unop(Iop_32to16, mkexpr(t0))), 5976 unop(Iop_16Uto32, 5977 unop(Iop_32to16, getIReg(rs))))); 5978 5979 putDSPControl(IRExpr_ITE(mkexpr(t1), 5980 binop(Iop_Or32, 5981 getDSPControl(), 5982 mkU32(0x00100000)), 5983 getDSPControl())); 5984 5985 /* Add higher halves. */ 5986 assign(t2, binop(Iop_Add32, 5987 unop(Iop_16Uto32, 5988 unop(Iop_32HIto16, getIReg(rs))), 5989 unop(Iop_16Uto32, 5990 unop(Iop_32HIto16, getIReg(rt))))); 5991 5992 /* Detect overflow. */ 5993 assign(t3, binop(Iop_CmpLT32U, 5994 unop(Iop_16Uto32, 5995 unop(Iop_32to16, mkexpr(t2))), 5996 unop(Iop_16Uto32, 5997 unop(Iop_32HIto16, getIReg(rs))))); 5998 5999 putDSPControl(IRExpr_ITE(mkexpr(t3), 6000 binop(Iop_Or32, 6001 getDSPControl(), 6002 mkU32(0x00100000)), 6003 getDSPControl())); 6004 6005 putIReg(rd, binop(Iop_16HLto32, 6006 IRExpr_ITE(mkexpr(t3), 6007 mkU16(0xffff), 6008 unop(Iop_32to16, 6009 mkexpr(t2))), 6010 IRExpr_ITE(mkexpr(t1), 6011 mkU16(0xffff), 6012 unop(Iop_32to16, 6013 mkexpr(t0))))); 6014 break; 6015 } 6016 case 0xD: { /* SUBU_S.PH */ 6017 DIP("subu_s.ph r%d, r%d, r%d", rd, rs, rt); 6018 vassert(!mode64); 6019 t0 = newTemp(Ity_I32); 6020 t1 = newTemp(Ity_I1); 6021 t2 = newTemp(Ity_I32); 6022 t3 = newTemp(Ity_I1); 6023 6024 /* Subtract lower halves. */ 6025 assign(t0, binop(Iop_Sub32, 6026 unop(Iop_16Uto32, 6027 unop(Iop_32to16, getIReg(rs))), 6028 unop(Iop_16Uto32, 6029 unop(Iop_32to16, getIReg(rt))))); 6030 6031 /* Detect underflow. */ 6032 assign(t1, binop(Iop_CmpNE32, 6033 binop(Iop_And32, 6034 mkexpr(t0), mkU32(0x00010000)), 6035 mkU32(0x0))); 6036 6037 putDSPControl(IRExpr_ITE(mkexpr(t1), 6038 binop(Iop_Or32, 6039 getDSPControl(), 6040 mkU32(0x00100000)), 6041 getDSPControl())); 6042 6043 /* Subtract higher halves. */ 6044 assign(t2, binop(Iop_Sub32, 6045 unop(Iop_16Uto32, 6046 unop(Iop_32HIto16, getIReg(rs))), 6047 unop(Iop_16Uto32, 6048 unop(Iop_32HIto16, getIReg(rt))))); 6049 6050 /* Detect underflow. */ 6051 assign(t3, binop(Iop_CmpNE32, 6052 binop(Iop_And32, 6053 mkexpr(t2), mkU32(0x00010000)), 6054 mkU32(0x0))); 6055 6056 putDSPControl(IRExpr_ITE(mkexpr(t3), 6057 binop(Iop_Or32, 6058 getDSPControl(), 6059 mkU32(0x00100000)), 6060 getDSPControl())); 6061 6062 putIReg(rd, 6063 binop(Iop_16HLto32, 6064 IRExpr_ITE(mkexpr(t3), 6065 mkU16(0x0000), 6066 unop(Iop_32to16, mkexpr(t2))), 6067 IRExpr_ITE(mkexpr(t1), 6068 mkU16(0x0000), 6069 unop(Iop_32to16, mkexpr(t0))))); 6070 break; 6071 } 6072 case 0xE: { /* ADDQ_S.PH */ 6073 DIP("addq_s.ph r%d r%d, r%d", rd, rs, rt); 6074 vassert(!mode64); 6075 t0 = newTemp(Ity_I32); 6076 t1 = newTemp(Ity_I1); 6077 t2 = newTemp(Ity_I32); 6078 t3 = newTemp(Ity_I1); 6079 t4 = newTemp(Ity_I16); 6080 t5 = newTemp(Ity_I16); 6081 t6 = newTemp(Ity_I32); 6082 t7 = newTemp(Ity_I32); 6083 6084 /* Add lower halves. */ 6085 assign(t0, binop(Iop_Add32, 6086 unop(Iop_16Sto32, 6087 unop(Iop_32to16, getIReg(rs))), 6088 unop(Iop_16Sto32, 6089 unop(Iop_32to16, getIReg(rt))))); 6090 6091 /* Bit 16 of the result. */ 6092 assign(t6, binop(Iop_And32, 6093 unop(Iop_16Uto32, 6094 unop(Iop_32HIto16, mkexpr(t0))), 6095 mkU32(0x1))); 6096 /* Detect overflow. */ 6097 assign(t1, binop(Iop_CmpNE32, 6098 binop(Iop_Shr32, 6099 binop(Iop_And32, 6100 mkexpr(t0), 6101 mkU32(0x8000)), 6102 mkU8(15)), 6103 mkexpr(t6))); 6104 6105 putDSPControl(IRExpr_ITE(mkexpr(t1), 6106 binop(Iop_Or32, 6107 getDSPControl(), 6108 mkU32(0x00100000)), 6109 getDSPControl())); 6110 /* Saturate if needed. */ 6111 assign(t4, IRExpr_ITE(mkexpr(t1), 6112 IRExpr_ITE(binop(Iop_CmpEQ32, 6113 mkexpr(t6), 6114 mkU32(0x0)), 6115 mkU16(0x7fff), 6116 mkU16(0x8000)), 6117 unop(Iop_32to16, mkexpr(t0)))); 6118 6119 /* Add higher halves. */ 6120 assign(t2, binop(Iop_Add32, 6121 unop(Iop_16Sto32, 6122 unop(Iop_32HIto16, getIReg(rs))), 6123 unop(Iop_16Sto32, 6124 unop(Iop_32HIto16, getIReg(rt))))); 6125 6126 /* Bit 16 of the result. */ 6127 assign(t7, binop(Iop_And32, 6128 unop(Iop_16Uto32, 6129 unop(Iop_32HIto16, mkexpr(t2))), 6130 mkU32(0x1))); 6131 /* Detect overflow. */ 6132 assign(t3, binop(Iop_CmpNE32, 6133 binop(Iop_Shr32, 6134 binop(Iop_And32, 6135 mkexpr(t2), 6136 mkU32(0x00008000)), 6137 mkU8(15)), 6138 mkexpr(t7))); 6139 6140 putDSPControl(IRExpr_ITE(mkexpr(t3), 6141 binop(Iop_Or32, 6142 getDSPControl(), 6143 mkU32(0x00100000)), 6144 getDSPControl())); 6145 /* Saturate if needed. */ 6146 assign(t5, IRExpr_ITE(mkexpr(t3), 6147 IRExpr_ITE(binop(Iop_CmpEQ32, 6148 mkexpr(t7), 6149 mkU32(0x0)), 6150 mkU16(0x7fff), 6151 mkU16(0x8000)), 6152 unop(Iop_32to16, mkexpr(t2)))); 6153 6154 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6155 break; 6156 } 6157 case 0xF: { /* SUBQ_S.PH */ 6158 DIP("subq_s.ph r%d r%d, r%d", rd, rs, rt); 6159 vassert(!mode64); 6160 t0 = newTemp(Ity_I32); 6161 t1 = newTemp(Ity_I1); 6162 t2 = newTemp(Ity_I32); 6163 t3 = newTemp(Ity_I1); 6164 t4 = newTemp(Ity_I16); 6165 t5 = newTemp(Ity_I16); 6166 t6 = newTemp(Ity_I32); 6167 t7 = newTemp(Ity_I32); 6168 6169 /* Subtract lower halves. */ 6170 assign(t0, binop(Iop_Sub32, 6171 unop(Iop_16Sto32, 6172 unop(Iop_32to16, getIReg(rs))), 6173 unop(Iop_16Sto32, 6174 unop(Iop_32to16, getIReg(rt))))); 6175 6176 /* Bit 16 of the result. */ 6177 assign(t6, binop(Iop_And32, 6178 unop(Iop_16Uto32, 6179 unop(Iop_32HIto16, mkexpr(t0))), 6180 mkU32(0x1))); 6181 /* Detect overflow or underflow. */ 6182 assign(t1, binop(Iop_CmpNE32, 6183 binop(Iop_Shr32, 6184 binop(Iop_And32, 6185 mkexpr(t0), 6186 mkU32(0x8000)), 6187 mkU8(15)), 6188 mkexpr(t6))); 6189 6190 putDSPControl(IRExpr_ITE(mkexpr(t1), 6191 binop(Iop_Or32, 6192 getDSPControl(), 6193 mkU32(0x00100000)), 6194 getDSPControl())); 6195 /* Saturate if needed. */ 6196 assign(t4, IRExpr_ITE(mkexpr(t1), 6197 IRExpr_ITE(binop(Iop_CmpEQ32, 6198 mkexpr(t6), 6199 mkU32(0x0)), 6200 mkU16(0x7fff), 6201 mkU16(0x8000)), 6202 unop(Iop_32to16, mkexpr(t0)))); 6203 6204 /* Subtract higher halves. */ 6205 assign(t2, binop(Iop_Sub32, 6206 unop(Iop_16Sto32, 6207 unop(Iop_32HIto16, getIReg(rs))), 6208 unop(Iop_16Sto32, 6209 unop(Iop_32HIto16, getIReg(rt))))); 6210 6211 /* Bit 16 of the result. */ 6212 assign(t7, binop(Iop_And32, 6213 unop(Iop_16Uto32, 6214 unop(Iop_32HIto16, mkexpr(t2))), 6215 mkU32(0x1))); 6216 /* Detect overflow or underflow. */ 6217 assign(t3, binop(Iop_CmpNE32, 6218 binop(Iop_Shr32, 6219 binop(Iop_And32, 6220 mkexpr(t2), 6221 mkU32(0x00008000)), 6222 mkU8(15)), 6223 mkexpr(t7))); 6224 6225 putDSPControl(IRExpr_ITE(mkexpr(t3), 6226 binop(Iop_Or32, 6227 getDSPControl(), 6228 mkU32(0x00100000)), 6229 getDSPControl())); 6230 /* Saturate if needed. */ 6231 assign(t5, IRExpr_ITE(mkexpr(t3), 6232 IRExpr_ITE(binop(Iop_CmpEQ32, 6233 mkexpr(t7), 6234 mkU32(0x0)), 6235 mkU16(0x7fff), 6236 mkU16(0x8000)), 6237 unop(Iop_32to16, mkexpr(t2)))); 6238 6239 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6240 break; 6241 } 6242 case 0x10: { /* ADDSC */ 6243 DIP("addsc r%d, r%d, r%d", rd, rs, rt); 6244 vassert(!mode64); 6245 t0 = newTemp(Ity_I64); 6246 t1 = newTemp(Ity_I1); 6247 6248 /* The carry bit result out of the addition operation is 6249 written to bit 13(the c field) of the DSPControl reg. */ 6250 assign(t0, binop(Iop_Add64, 6251 unop(Iop_32Uto64, getIReg(rs)), 6252 unop(Iop_32Uto64, getIReg(rt)))); 6253 6254 assign(t1, binop(Iop_CmpEQ32, 6255 binop(Iop_And32, 6256 unop(Iop_64HIto32, mkexpr(t0)), 6257 mkU32(0x1)), 6258 mkU32(0x1))); 6259 putDSPControl(IRExpr_ITE(mkexpr(t1), 6260 binop(Iop_Or32, 6261 getDSPControl(), 6262 mkU32(0x2000)), 6263 binop(Iop_And32, 6264 getDSPControl(), 6265 mkU32(0xffffdfff)))); 6266 6267 putIReg(rd, unop(Iop_64to32, mkexpr(t0))); 6268 break; 6269 } 6270 case 0x11: { /* ADDWC */ 6271 DIP("addwc r%d, r%d, r%d", rd, rs, rt); 6272 vassert(!mode64); 6273 t0 = newTemp(Ity_I32); 6274 t1 = newTemp(Ity_I64); 6275 t2 = newTemp(Ity_I32); 6276 t3 = newTemp(Ity_I32); 6277 t4 = newTemp(Ity_I1); 6278 6279 /* Get carry bit from DSPControl register. */ 6280 assign(t0, binop(Iop_Shr32, 6281 binop(Iop_And32, 6282 getDSPControl(), 6283 mkU32(0x2000)), 6284 mkU8(0xd))); 6285 assign(t1, binop(Iop_Add64, 6286 unop(Iop_32Sto64, getIReg(rs)), 6287 unop(Iop_32Sto64, 6288 binop(Iop_Add32, 6289 getIReg(rt), 6290 mkexpr(t0))))); 6291 6292 /* Extract bits 32 and 31. */ 6293 assign(t2, binop(Iop_And32, 6294 unop(Iop_64HIto32, mkexpr(t1)), 6295 mkU32(0x1))); 6296 assign(t3, binop(Iop_Shr32, 6297 binop(Iop_And32, 6298 unop(Iop_64to32, mkexpr(t1)), 6299 mkU32(0x80000000)), 6300 mkU8(31))); 6301 assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3))); 6302 6303 putDSPControl(IRExpr_ITE(mkexpr(t4), 6304 binop(Iop_Or32, 6305 getDSPControl(), 6306 mkU32(0x00100000)), 6307 getDSPControl())); 6308 putIReg(rd, unop(Iop_64to32, mkexpr(t1))); 6309 break; 6310 } 6311 case 0x12: { /* MODSUB */ 6312 DIP("modsub r%d, r%d, r%d", rd, rs, rt); 6313 vassert(!mode64); 6314 t0 = newTemp(Ity_I32); 6315 t1 = newTemp(Ity_I32); 6316 t2 = newTemp(Ity_I32); 6317 6318 /* decr_7..0 */ 6319 assign(t0, 6320 unop(Iop_8Uto32, 6321 unop(Iop_16to8, 6322 unop(Iop_32to16, getIReg(rt))))); 6323 6324 /* lastindex_15..0 */ 6325 assign(t1, 6326 unop(Iop_16Uto32, 6327 binop(Iop_8HLto16, 6328 unop(Iop_16to8, 6329 unop(Iop_32HIto16, getIReg(rt))), 6330 unop(Iop_16HIto8, 6331 unop(Iop_32to16, getIReg(rt)))))); 6332 /* temp_15..0 */ 6333 assign(t2, 6334 IRExpr_ITE(binop(Iop_CmpEQ32, 6335 getIReg(rs), 6336 mkU32(0x00000000)), 6337 mkexpr(t1), 6338 binop(Iop_Sub32, 6339 getIReg(rs), mkexpr(t0)))); 6340 putIReg(rd, mkexpr(t2)); 6341 break; 6342 } 6343 case 0x14: { /* RADDU.W.QB */ 6344 DIP("raddu.w.qb r%d, r%d", rd, rs); 6345 vassert(!mode64); 6346 putIReg(rd, binop(Iop_Add32, 6347 binop(Iop_Add32, 6348 unop(Iop_8Uto32, 6349 unop(Iop_16to8, 6350 unop(Iop_32to16, 6351 getIReg(rs)))), 6352 unop(Iop_8Uto32, 6353 unop(Iop_16HIto8, 6354 unop(Iop_32to16, 6355 getIReg(rs))))), 6356 binop(Iop_Add32, 6357 unop(Iop_8Uto32, 6358 unop(Iop_16to8, 6359 unop(Iop_32HIto16, 6360 getIReg(rs)))), 6361 unop(Iop_8Uto32, 6362 unop(Iop_16HIto8, 6363 unop(Iop_32HIto16, 6364 getIReg(rs))))))); 6365 break; 6366 } 6367 case 0x16: { /* ADDQ_S.W */ 6368 DIP("addq_s.w r%d, r%d, r%d", rd, rs, rt); 6369 vassert(!mode64); 6370 t0 = newTemp(Ity_I64); 6371 t1 = newTemp(Ity_I1); 6372 t2 = newTemp(Ity_I32); 6373 t3 = newTemp(Ity_I32); 6374 6375 assign(t0, binop(Iop_Add64, 6376 unop(Iop_32Sto64, getIReg(rs)), 6377 unop(Iop_32Sto64, getIReg(rt)))); 6378 6379 assign(t3, binop(Iop_And32, 6380 unop(Iop_64HIto32, mkexpr(t0)), 6381 mkU32(0x1))); 6382 assign(t1, binop(Iop_CmpNE32, 6383 binop(Iop_Shr32, 6384 binop(Iop_And32, 6385 unop(Iop_64to32, mkexpr(t0)), 6386 mkU32(0x80000000)), 6387 mkU8(31)), 6388 mkexpr(t3))); 6389 6390 putDSPControl(IRExpr_ITE(mkexpr(t1), 6391 binop(Iop_Or32, 6392 getDSPControl(), 6393 mkU32(0x00100000)), 6394 getDSPControl())); 6395 6396 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6397 IRExpr_ITE(binop(Iop_CmpEQ32, 6398 mkexpr(t3), 6399 mkU32(0x0)), 6400 mkU32(0x7fffffff), 6401 mkU32(0x80000000)), 6402 unop(Iop_64to32, mkexpr(t0)))); 6403 break; 6404 } 6405 case 0x17: { /* SUBQ_S.W */ 6406 DIP("subq_s.w r%d, r%d, r%d", rd, rs, rt); 6407 vassert(!mode64); 6408 t0 = newTemp(Ity_I64); 6409 t1 = newTemp(Ity_I1); 6410 t2 = newTemp(Ity_I32); 6411 t3 = newTemp(Ity_I32); 6412 6413 assign(t0, binop(Iop_Sub64, 6414 unop(Iop_32Sto64, getIReg(rs)), 6415 unop(Iop_32Sto64, getIReg(rt)))); 6416 6417 assign(t3, binop(Iop_And32, 6418 unop(Iop_64HIto32, mkexpr(t0)), 6419 mkU32(0x1))); 6420 assign(t1, binop(Iop_CmpNE32, 6421 binop(Iop_Shr32, 6422 binop(Iop_And32, 6423 unop(Iop_64to32, mkexpr(t0)), 6424 mkU32(0x80000000)), 6425 mkU8(31)), 6426 mkexpr(t3))); 6427 6428 putDSPControl(IRExpr_ITE(mkexpr(t1), 6429 binop(Iop_Or32, 6430 getDSPControl(), 6431 mkU32(0x00100000)), 6432 getDSPControl())); 6433 6434 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6435 IRExpr_ITE(binop(Iop_CmpEQ32, 6436 mkexpr(t3), 6437 mkU32(0x0)), 6438 mkU32(0x7fffffff), 6439 mkU32(0x80000000)), 6440 unop(Iop_64to32, mkexpr(t0)))); 6441 break; 6442 } 6443 case 0x1C: { /* MULEQ_S.W.PHL */ 6444 DIP("muleq_s.w.phl r%d, r%d, r%d", rd, rs, rt); 6445 vassert(!mode64); 6446 t0 = newTemp(Ity_I32); 6447 t1 = newTemp(Ity_I1); 6448 t2 = newTemp(Ity_I1); 6449 t3 = newTemp(Ity_I32); 6450 6451 assign(t0, 6452 binop(Iop_Shl32, 6453 binop(Iop_Mul32, 6454 unop(Iop_16Sto32, 6455 unop(Iop_32HIto16, getIReg(rt))), 6456 unop(Iop_16Sto32, 6457 unop(Iop_32HIto16, getIReg(rs)))), 6458 mkU8(0x1))); 6459 assign(t1, binop(Iop_CmpEQ32, 6460 binop(Iop_And32, 6461 getIReg(rt), 6462 mkU32(0xffff0000)), 6463 mkU32(0x80000000))); 6464 assign(t2, binop(Iop_CmpEQ32, 6465 binop(Iop_And32, 6466 getIReg(rs), 6467 mkU32(0xffff0000)), 6468 mkU32(0x80000000))); 6469 assign(t3, IRExpr_ITE(mkexpr(t1), 6470 IRExpr_ITE(mkexpr(t2), 6471 binop(Iop_Or32, 6472 getDSPControl(), 6473 mkU32(0x00200000)), 6474 getDSPControl()), 6475 getDSPControl())); 6476 putDSPControl(mkexpr(t3)); 6477 6478 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6479 IRExpr_ITE(mkexpr(t2), 6480 mkU32(0x7fffffff), 6481 mkexpr(t0)), 6482 mkexpr(t0))); 6483 break; 6484 } 6485 case 0x1D: { /* MULEQ_S.W.PHR */ 6486 DIP("muleq_s.w.phr r%d, r%d, r%d", rd, rs, rt); 6487 vassert(!mode64); 6488 t0 = newTemp(Ity_I32); 6489 t1 = newTemp(Ity_I1); 6490 t2 = newTemp(Ity_I1); 6491 6492 assign(t0, 6493 binop(Iop_Shl32, 6494 binop(Iop_Mul32, 6495 unop(Iop_16Sto32, 6496 unop(Iop_32to16, getIReg(rt))), 6497 unop(Iop_16Sto32, 6498 unop(Iop_32to16, getIReg(rs)))), 6499 mkU8(0x1))); 6500 assign(t1, binop(Iop_CmpEQ32, 6501 binop(Iop_And32, 6502 getIReg(rt), 6503 mkU32(0xffff)), 6504 mkU32(0x8000))); 6505 assign(t2, binop(Iop_CmpEQ32, 6506 binop(Iop_And32, 6507 getIReg(rs), 6508 mkU32(0xffff)), 6509 mkU32(0x8000))); 6510 putDSPControl(IRExpr_ITE(mkexpr(t1), 6511 IRExpr_ITE(mkexpr(t2), 6512 binop(Iop_Or32, 6513 getDSPControl(), 6514 mkU32(0x00200000) 6515 ), 6516 getDSPControl()), 6517 getDSPControl())); 6518 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6519 IRExpr_ITE(mkexpr(t2), 6520 mkU32(0x7fffffff), 6521 mkexpr(t0)), 6522 mkexpr(t0))); 6523 break; 6524 } 6525 case 0x1E: { /* MULQ_S.PH */ 6526 DIP("mulq_s.ph r%d, r%d, r%d", rd, rs, rt); 6527 vassert(!mode64); 6528 t0 = newTemp(Ity_I32); 6529 t1 = newTemp(Ity_I32); 6530 t2 = newTemp(Ity_I16); 6531 t3 = newTemp(Ity_I16); 6532 t5 = newTemp(Ity_I32); 6533 t6 = newTemp(Ity_I32); 6534 t7 = newTemp(Ity_I32); 6535 t8 = newTemp(Ity_I32); 6536 6537 assign(t5, 6538 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs)))); 6539 assign(t6, 6540 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 6541 6542 assign(t7, 6543 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs)))); 6544 assign(t8, 6545 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt)))); 6546 6547 assign(t0, binop(Iop_And32, 6548 unop(Iop_1Sto32, 6549 binop(Iop_CmpEQ32, 6550 binop(Iop_And32, 6551 mkexpr(t5), 6552 mkU32(0xffff)), 6553 mkU32(0x8000))), 6554 unop(Iop_1Sto32, 6555 binop(Iop_CmpEQ32, 6556 binop(Iop_And32, 6557 mkexpr(t6), 6558 mkU32(0xffff)), 6559 mkU32(0x8000))))); 6560 assign(t1, binop(Iop_And32, 6561 unop(Iop_1Sto32, 6562 binop(Iop_CmpEQ32, 6563 binop(Iop_And32, 6564 mkexpr(t7), 6565 mkU32(0xffff)), 6566 mkU32(0x8000))), 6567 unop(Iop_1Sto32, 6568 binop(Iop_CmpEQ32, 6569 binop(Iop_And32, 6570 mkexpr(t8), 6571 mkU32(0xffff)), 6572 mkU32(0x8000))))); 6573 6574 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 6575 binop(Iop_Or32, 6576 mkexpr(t0), 6577 mkexpr(t1)), 6578 mkU32(0x0)), 6579 getDSPControl(), 6580 binop(Iop_Or32, 6581 getDSPControl(), 6582 mkU32(0x200000)))); 6583 6584 assign(t2, unop(Iop_32HIto16, 6585 binop(Iop_Shl32, 6586 unop(Iop_64to32, 6587 binop(Iop_MullS32, 6588 mkexpr(t7), 6589 mkexpr(t8))), 6590 mkU8(0x1)))); 6591 assign(t3, unop(Iop_32HIto16, 6592 binop(