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-2015 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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, %lld", regRd, regRt, 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 %u, f%u, f%u", 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 %u, f%u, f%u", 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%u, r%u, r%u", 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%u, r%u, r%u", 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%u, r%u", 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%u, r%u", 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, %u, %u\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%u, r%u, r%u", 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%u, r%u, %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%u, r%u, %u", 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%u, r%u, %u", 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%u, r%u(r%u)", regRd, regRt, regRs); 2636 LOADX_STORE_PATTERN; 2637 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2638 True)); 2639 break; 2640 } 2641 case 0x04: // LHX rd, index(base) 2642 DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs); 2643 LOADX_STORE_PATTERN; 2644 if (mode64) 2645 putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16, 2646 mkexpr(t1)))); 2647 else 2648 putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16, 2649 mkexpr(t1)))); 2650 break; 2651 case 0x08: { // LDX rd, index(base) 2652 DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs); 2653 vassert(mode64); /* Currently Implemented only for n64 */ 2654 LOADX_STORE_PATTERN; 2655 putIReg(regRd, load(Ity_I64, mkexpr(t1))); 2656 break; 2657 } 2658 case 0x06: { // LBUX rd, index(base) 2659 DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs); 2660 LOADX_STORE_PATTERN; 2661 if (mode64) 2662 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8, 2663 mkexpr(t1)))); 2664 else 2665 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8, 2666 mkexpr(t1)))); 2667 break; 2668 } 2669 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON) 2670 DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs); 2671 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/ 2672 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2673 False)); 2674 break; 2675 } 2676 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON) 2677 DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs); 2678 LOADX_STORE_PATTERN; 2679 if (mode64) 2680 putIReg(regRd, 2681 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 2682 else 2683 putIReg(regRd, 2684 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 2685 break; 2686 } 2687 case 0x16: { // LBX rd, index(base) (Cavium OCTEON) 2688 DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt); 2689 LOADX_STORE_PATTERN; 2690 if (mode64) 2691 putIReg(regRd, 2692 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 2693 else 2694 putIReg(regRd, 2695 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 2696 break; 2697 } 2698 default: 2699 vex_printf("\nUnhandled LX instruction opc3 = %x\n", 2700 get_sa(theInstr)); 2701 return False; 2702 } 2703 break; 2704 } 2705 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/ 2706 break; 2707 } /* opc1 = 0x1F ends here*/ 2708 default: 2709 return False; 2710 } /* main opc1 switch ends here */ 2711 return True; 2712 } 2713 2714 /*------------------------------------------------------------*/ 2715 /*--- Disassemble a single DSP ASE instruction ---*/ 2716 /*------------------------------------------------------------*/ 2717 2718 static UInt disDSPInstr_MIPS_WRK ( UInt cins ) 2719 { 2720 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, 2721 t15, t16, t17; 2722 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask, 2723 wrdsp_mask, dsp_imm, shift; 2724 2725 opcode = get_opcode(cins); 2726 rs = get_rs(cins); 2727 rt = get_rt(cins); 2728 rd = get_rd(cins); 2729 sa = get_sa(cins); 2730 function = get_function(cins); 2731 ac = get_acNo(cins); 2732 ac_mfhilo = get_acNo_mfhilo(cins); 2733 rddsp_mask = get_rddspMask(cins); 2734 wrdsp_mask = get_wrdspMask(cins); 2735 dsp_imm = get_dspImm(cins); 2736 shift = get_shift(cins); 2737 2738 switch (opcode) { 2739 case 0x00: { /* Special */ 2740 switch (function) { 2741 case 0x10: { /* MFHI */ 2742 DIP("mfhi ac%u r%u", ac_mfhilo, rd); 2743 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo))); 2744 break; 2745 } 2746 2747 case 0x11: { /* MTHI */ 2748 DIP("mthi ac%u r%u", ac, rs); 2749 t1 = newTemp(Ity_I32); 2750 assign(t1, unop(Iop_64to32, getAcc(ac))); 2751 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1))); 2752 break; 2753 } 2754 2755 case 0x12: { /* MFLO */ 2756 DIP("mflo ac%u r%u", ac_mfhilo, rd); 2757 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo))); 2758 break; 2759 } 2760 2761 case 0x13: { /* MTLO */ 2762 DIP("mtlo ac%u r%u", ac, rs); 2763 t1 = newTemp(Ity_I32); 2764 assign(t1, unop(Iop_64HIto32, getAcc(ac))); 2765 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs))); 2766 break; 2767 } 2768 2769 case 0x18: { /* MULT */ 2770 DIP("mult ac%u r%u, r%u", ac, rs, rt); 2771 t1 = newTemp(Ity_I64); 2772 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2773 mkNarrowTo32(Ity_I32, getIReg(rt)))); 2774 putAcc(ac, mkexpr(t1)); 2775 break; 2776 } 2777 2778 case 0x19: { /* MULTU */ 2779 DIP("multu ac%u r%u, r%u", ac, rs, rt); 2780 t1 = newTemp(Ity_I64); 2781 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2782 mkNarrowTo32(Ity_I32, 2783 getIReg(rt)))); 2784 putAcc(ac, mkexpr(t1)); 2785 break; 2786 } 2787 } 2788 break; 2789 } 2790 case 0x1C: { /* Special2 */ 2791 switch (function) { 2792 case 0x00: { /* MADD */ 2793 DIP("madd ac%u, r%u, r%u", ac, rs, rt); 2794 t1 = newTemp(Ity_I64); 2795 t2 = newTemp(Ity_I64); 2796 t3 = newTemp(Ity_I64); 2797 2798 assign(t1, getAcc(ac)); 2799 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2800 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2))); 2801 2802 putAcc(ac, mkexpr(t3)); 2803 break; 2804 } 2805 case 0x01: { /* MADDU */ 2806 DIP("maddu ac%u r%u, r%u", ac, rs, rt); 2807 t1 = newTemp(Ity_I64); 2808 t2 = newTemp(Ity_I64); 2809 t3 = newTemp(Ity_I64); 2810 2811 assign(t1, getAcc(ac)); 2812 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2813 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1))); 2814 2815 putAcc(ac, mkexpr(t3)); 2816 break; 2817 } 2818 case 0x04: { /* MSUB */ 2819 DIP("msub ac%u r%u, r%u", ac, rs, rt); 2820 t1 = newTemp(Ity_I64); 2821 t2 = newTemp(Ity_I64); 2822 t3 = newTemp(Ity_I64); 2823 2824 assign(t1, getAcc(ac)); 2825 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2826 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2827 2828 putAcc(ac, mkexpr(t3)); 2829 break; 2830 } 2831 case 0x05: { /* MSUBU */ 2832 DIP("msubu ac%u r%u, r%u", ac, rs, rt); 2833 t1 = newTemp(Ity_I64); 2834 t2 = newTemp(Ity_I64); 2835 t3 = newTemp(Ity_I64); 2836 2837 assign(t1, getAcc(ac)); 2838 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2839 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2840 2841 putAcc(ac, mkexpr(t3)); 2842 break; 2843 } 2844 } 2845 break; 2846 } 2847 case 0x1F: { /* Special3 */ 2848 switch (function) { 2849 case 0x12: { /* ABSQ_S.PH */ 2850 switch (sa) { 2851 case 0x1: { /* ABSQ_S.QB */ 2852 DIP("absq_s.qb r%u, r%u", rd, rt); 2853 vassert(!mode64); 2854 t0 = newTemp(Ity_I8); 2855 t1 = newTemp(Ity_I1); 2856 t2 = newTemp(Ity_I1); 2857 t3 = newTemp(Ity_I8); 2858 t4 = newTemp(Ity_I8); 2859 t5 = newTemp(Ity_I1); 2860 t6 = newTemp(Ity_I1); 2861 t7 = newTemp(Ity_I8); 2862 t8 = newTemp(Ity_I8); 2863 t9 = newTemp(Ity_I1); 2864 t10 = newTemp(Ity_I1); 2865 t11 = newTemp(Ity_I8); 2866 t12 = newTemp(Ity_I8); 2867 t13 = newTemp(Ity_I1); 2868 t14 = newTemp(Ity_I1); 2869 t15 = newTemp(Ity_I8); 2870 t16 = newTemp(Ity_I32); 2871 t17 = newTemp(Ity_I32); 2872 2873 /* Absolute value of the rightmost byte (bits 7-0). */ 2874 /* t0 - rightmost byte. */ 2875 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt)))); 2876 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */ 2877 assign(t1, binop(Iop_CmpEQ32, 2878 unop(Iop_8Uto32, mkexpr(t0)), 2879 mkU32(0x00000080))); 2880 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 2881 assign(t2, unop(Iop_32to1, 2882 binop(Iop_Shr32, 2883 binop(Iop_And32, 2884 getIReg(rt), 2885 mkU32(0x00000080)), 2886 mkU8(0x7)))); 2887 /* t3 holds abs(t0). */ 2888 assign(t3, IRExpr_ITE(mkexpr(t1), 2889 mkU8(0x7F), 2890 IRExpr_ITE(mkexpr(t2), 2891 binop(Iop_Add8, 2892 unop(Iop_Not8, 2893 mkexpr(t0)), 2894 mkU8(0x1)), 2895 mkexpr(t0)))); 2896 2897 /* Absolute value of bits 15-8. */ 2898 /* t4 - input byte. */ 2899 assign(t4, 2900 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt)))); 2901 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */ 2902 assign(t5, binop(Iop_CmpEQ32, 2903 unop(Iop_8Uto32, mkexpr(t4)), 2904 mkU32(0x00000080))); 2905 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 2906 assign(t6, unop(Iop_32to1, 2907 binop(Iop_Shr32, 2908 binop(Iop_And32, 2909 getIReg(rt), 2910 mkU32(0x00008000)), 2911 mkU8(15)))); 2912 /* t3 holds abs(t4). */ 2913 assign(t7, IRExpr_ITE(mkexpr(t5), 2914 mkU8(0x7F), 2915 IRExpr_ITE(mkexpr(t6), 2916 binop(Iop_Add8, 2917 unop(Iop_Not8, 2918 mkexpr(t4)), 2919 mkU8(0x1)), 2920 mkexpr(t4)))); 2921 2922 /* Absolute value of bits 23-15. */ 2923 /* t8 - input byte. */ 2924 assign(t8, 2925 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt)))); 2926 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */ 2927 assign(t9, binop(Iop_CmpEQ32, 2928 unop(Iop_8Uto32, mkexpr(t8)), 2929 mkU32(0x00000080))); 2930 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */ 2931 assign(t10, unop(Iop_32to1, 2932 binop(Iop_Shr32, 2933 binop(Iop_And32, 2934 getIReg(rt), 2935 mkU32(0x00800000)), 2936 mkU8(23)))); 2937 /* t3 holds abs(t8). */ 2938 assign(t11, IRExpr_ITE(mkexpr(t9), 2939 mkU8(0x7F), 2940 IRExpr_ITE(mkexpr(t10), 2941 binop(Iop_Add8, 2942 unop(Iop_Not8, 2943 mkexpr(t8)), 2944 mkU8(0x1)), 2945 mkexpr(t8)))); 2946 2947 /* Absolute value of bits 31-24. */ 2948 /* t12 - input byte. */ 2949 assign(t12, 2950 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt)))); 2951 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */ 2952 assign(t13, binop(Iop_CmpEQ32, 2953 unop(Iop_8Uto32, mkexpr(t12)), 2954 mkU32(0x00000080))); 2955 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */ 2956 assign(t14, unop(Iop_32to1, 2957 binop(Iop_Shr32, 2958 binop(Iop_And32, 2959 getIReg(rt), 2960 mkU32(0x80000000)), 2961 mkU8(31)))); 2962 /* t15 holds abs(t12). */ 2963 assign(t15, IRExpr_ITE(mkexpr(t13), 2964 mkU8(0x7F), 2965 IRExpr_ITE(mkexpr(t14), 2966 binop(Iop_Add8, 2967 unop(Iop_Not8, 2968 mkexpr(t12)), 2969 mkU8(0x1)), 2970 mkexpr(t12)))); 2971 2972 /* t16 holds !0 if any of input bytes is 0x80 or 0 2973 otherwise. */ 2974 assign(t16, 2975 binop(Iop_Or32, 2976 binop(Iop_Or32, 2977 binop(Iop_Or32, 2978 unop(Iop_1Sto32, mkexpr(t13)), 2979 unop(Iop_1Sto32, mkexpr(t9))), 2980 unop(Iop_1Sto32, mkexpr(t5))), 2981 unop(Iop_1Sto32, mkexpr(t1)))); 2982 2983 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 2984 mkexpr(t16), 2985 mkU32(0x0)), 2986 getDSPControl(), 2987 binop(Iop_Or32, 2988 getDSPControl(), 2989 mkU32(0x00100000)))); 2990 2991 /* t17 = t15|t11|t7|t3 */ 2992 assign(t17, 2993 binop(Iop_16HLto32, 2994 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)), 2995 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3)))); 2996 2997 putIReg(rd, mkexpr(t17)); 2998 break; 2999 } 3000 case 0x2: { /* REPL.QB */ 3001 DIP("repl.qb r%u, %u", rd, dsp_imm); 3002 vassert(!mode64); 3003 3004 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) | 3005 (dsp_imm << 8) | (dsp_imm))); 3006 break; 3007 } 3008 case 0x3: { /* REPLV.QB */ 3009 DIP("replv.qb r%u, r%u", rd, rt); 3010 vassert(!mode64); 3011 t0 = newTemp(Ity_I8); 3012 3013 assign(t0, unop(Iop_32to8, 3014 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 3015 putIReg(rd, 3016 binop(Iop_16HLto32, 3017 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)), 3018 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)))); 3019 break; 3020 } 3021 case 0x4: { /* PRECEQU.PH.QBL */ 3022 DIP("precequ.ph.qbl r%u, r%u", rd, rt); 3023 vassert(!mode64); 3024 3025 putIReg(rd, binop(Iop_Or32, 3026 binop(Iop_Shr32, 3027 binop(Iop_And32, 3028 getIReg(rt), 3029 mkU32(0xff000000)), 3030 mkU8(1)), 3031 binop(Iop_Shr32, 3032 binop(Iop_And32, 3033 getIReg(rt), 3034 mkU32(0x00ff0000)), 3035 mkU8(9)))); 3036 break; 3037 } 3038 case 0x5: { /* PRECEQU.PH.QBR */ 3039 DIP("precequ.ph.qbr r%u, r%u", rd, rt); 3040 vassert(!mode64); 3041 3042 putIReg(rd, binop(Iop_Or32, 3043 binop(Iop_Shl32, 3044 binop(Iop_And32, 3045 getIReg(rt), 3046 mkU32(0x0000ff00)), 3047 mkU8(15)), 3048 binop(Iop_Shl32, 3049 binop(Iop_And32, 3050 getIReg(rt), 3051 mkU32(0x000000ff)), 3052 mkU8(7)))); 3053 break; 3054 } 3055 case 0x6: { /* PRECEQU.PH.QBLA */ 3056 DIP("precequ.ph.qbla r%u, r%u", rd, rt); 3057 vassert(!mode64); 3058 3059 putIReg(rd, binop(Iop_Or32, 3060 binop(Iop_Shr32, 3061 binop(Iop_And32, 3062 getIReg(rt), 3063 mkU32(0xff000000)), 3064 mkU8(1)), 3065 binop(Iop_Shr32, 3066 binop(Iop_And32, 3067 getIReg(rt), 3068 mkU32(0x0000ff00)), 3069 mkU8(1)))); 3070 break; 3071 } 3072 case 0x7: { /* PRECEQU.PH.QBRA */ 3073 DIP("precequ.ph.qbra r%u, r%u", rd, rt); 3074 vassert(!mode64); 3075 3076 putIReg(rd, binop(Iop_Or32, 3077 binop(Iop_Shl32, 3078 binop(Iop_And32, 3079 getIReg(rt), 3080 mkU32(0x00ff0000)), 3081 mkU8(7)), 3082 binop(Iop_Shl32, 3083 binop(Iop_And32, 3084 getIReg(rt), 3085 mkU32(0x000000ff)), 3086 mkU8(7)))); 3087 break; 3088 } 3089 case 0x9: { /* ABSQ_S.PH */ 3090 DIP("absq_s.ph r%u, r%u", rd, rt); 3091 vassert(!mode64); 3092 t0 = newTemp(Ity_I16); 3093 t1 = newTemp(Ity_I1); 3094 t2 = newTemp(Ity_I1); 3095 t3 = newTemp(Ity_I16); 3096 t4 = newTemp(Ity_I16); 3097 t5 = newTemp(Ity_I1); 3098 t6 = newTemp(Ity_I1); 3099 t7 = newTemp(Ity_I16); 3100 t8 = newTemp(Ity_I32); 3101 t9 = newTemp(Ity_I32); 3102 3103 /* t0 holds lower 16 bits of value in rt. */ 3104 assign(t0, unop(Iop_32to16, getIReg(rt))); 3105 /* t1 holds 1 if t0 is equal to 0x8000. */ 3106 assign(t1, binop(Iop_CmpEQ32, 3107 unop(Iop_16Uto32, mkexpr(t0)), 3108 mkU32(0x00008000))); 3109 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 3110 assign(t2, unop(Iop_32to1, 3111 binop(Iop_Shr32, 3112 binop(Iop_And32, 3113 getIReg(rt), 3114 mkU32(0x00008000)), 3115 mkU8(15)))); 3116 /* t3 holds abs(t0). */ 3117 assign(t3, IRExpr_ITE(mkexpr(t1), 3118 mkU16(0x7FFF), 3119 IRExpr_ITE(mkexpr(t2), 3120 binop(Iop_Add16, 3121 unop(Iop_Not16, 3122 mkexpr(t0)), 3123 mkU16(0x1)), 3124 mkexpr(t0)))); 3125 3126 /* t4 holds lower 16 bits of value in rt. */ 3127 assign(t4, unop(Iop_32HIto16, getIReg(rt))); 3128 /* t5 holds 1 if t4 is equal to 0x8000. */ 3129 assign(t5, binop(Iop_CmpEQ32, 3130 unop(Iop_16Uto32, mkexpr(t4)), 3131 mkU32(0x00008000))); 3132 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 3133 assign(t6, unop(Iop_32to1, 3134 binop(Iop_Shr32, 3135 binop(Iop_And32, 3136 getIReg(rt), 3137 mkU32(0x80000000)), 3138 mkU8(31)))); 3139 /* t7 holds abs(t4). */ 3140 assign(t7, IRExpr_ITE(mkexpr(t5), 3141 mkU16(0x7FFF), 3142 IRExpr_ITE(mkexpr(t6), 3143 binop(Iop_Add16, 3144 unop(Iop_Not16, 3145 mkexpr(t4)), 3146 mkU16(0x1)), 3147 mkexpr(t4)))); 3148 /* If any of the two input halfwords is equal 0x8000, 3149 set bit 20 in DSPControl register. */ 3150 assign(t8, binop(Iop_Or32, 3151 unop(Iop_1Sto32, mkexpr(t5)), 3152 unop(Iop_1Sto32, mkexpr(t1)))); 3153 3154 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 3155 mkexpr(t8), 3156 mkU32(0x0)), 3157 getDSPControl(), 3158 binop(Iop_Or32, 3159 getDSPControl(), 3160 mkU32(0x00100000)))); 3161 3162 /* t9 = t7|t3 */ 3163 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 3164 3165 putIReg(rd, mkexpr(t9)); 3166 break; 3167 } 3168 case 0xA: { /* REPL.PH */ 3169 DIP("repl.ph r%u, %u", rd, dsp_imm); 3170 vassert(!mode64); 3171 UShort immediate = extend_s_10to16(dsp_imm); 3172 3173 putIReg(rd, mkU32(immediate << 16 | immediate)); 3174 break; 3175 } 3176 case 0xB: { /* REPLV.PH */ 3177 DIP("replv.ph r%u, r%u", rd, rt); 3178 vassert(!mode64); 3179 3180 putIReg(rd, binop(Iop_16HLto32, 3181 unop(Iop_32to16, getIReg(rt)), 3182 unop(Iop_32to16, getIReg(rt)))); 3183 break; 3184 } 3185 case 0xC: { /* PRECEQ.W.PHL */ 3186 DIP("preceq.w.phl r%u, r%u", rd, rt); 3187 vassert(!mode64); 3188 putIReg(rd, binop(Iop_And32, 3189 getIReg(rt), 3190 mkU32(0xffff0000))); 3191 break; 3192 } 3193 case 0xD: { /* PRECEQ.W.PHR */ 3194 DIP("preceq.w.phr r%u, r%u", rd, rt); 3195 vassert(!mode64); 3196 putIReg(rd, binop(Iop_16HLto32, 3197 unop(Iop_32to16, getIReg(rt)), 3198 mkU16(0x0))); 3199 break; 3200 } 3201 case 0x11: { /* ABSQ_S.W */ 3202 DIP("absq_s.w r%u, r%u", rd, rt); 3203 vassert(!mode64); 3204 t0 = newTemp(Ity_I1); 3205 t1 = newTemp(Ity_I1); 3206 t2 = newTemp(Ity_I32); 3207 3208 assign(t0, 3209 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 3210 3211 putDSPControl(IRExpr_ITE(mkexpr(t0), 3212 binop(Iop_Or32, 3213 getDSPControl(), 3214 mkU32(0x00100000)), 3215 getDSPControl())); 3216 3217 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0))); 3218 3219 assign(t2, IRExpr_ITE(mkexpr(t0), 3220 mkU32(0x7FFFFFFF), 3221 IRExpr_ITE(mkexpr(t1), 3222 binop(Iop_Add32, 3223 unop(Iop_Not32, 3224 getIReg(rt)), 3225 mkU32(0x1)), 3226 getIReg(rt)))); 3227 putIReg(rd, mkexpr(t2)); 3228 break; 3229 } 3230 case 0x1B: { /* BITREV */ 3231 DIP("bitrev r%u, r%u", rd, rt); 3232 vassert(!mode64); 3233 /* 32bit reversal as seen on Bit Twiddling Hacks site 3234 http://graphics.stanford.edu/~seander/bithacks.html 3235 section ReverseParallel */ 3236 t1 = newTemp(Ity_I32); 3237 t2 = newTemp(Ity_I32); 3238 t3 = newTemp(Ity_I32); 3239 t4 = newTemp(Ity_I32); 3240 t5 = newTemp(Ity_I32); 3241 3242 assign(t1, binop(Iop_Or32, 3243 binop(Iop_Shr32, 3244 binop(Iop_And32, 3245 getIReg(rt), 3246 mkU32(0xaaaaaaaa)), 3247 mkU8(0x1)), 3248 binop(Iop_Shl32, 3249 binop(Iop_And32, 3250 getIReg(rt), 3251 mkU32(0x55555555)), 3252 mkU8(0x1)))); 3253 assign(t2, binop(Iop_Or32, 3254 binop(Iop_Shr32, 3255 binop(Iop_And32, 3256 mkexpr(t1), 3257 mkU32(0xcccccccc)), 3258 mkU8(0x2)), 3259 binop(Iop_Shl32, 3260 binop(Iop_And32, 3261 mkexpr(t1), 3262 mkU32(0x33333333)), 3263 mkU8(0x2)))); 3264 assign(t3, binop(Iop_Or32, 3265 binop(Iop_Shr32, 3266 binop(Iop_And32, 3267 mkexpr(t2), 3268 mkU32(0xf0f0f0f0)), 3269 mkU8(0x4)), 3270 binop(Iop_Shl32, 3271 binop(Iop_And32, 3272 mkexpr(t2), 3273 mkU32(0x0f0f0f0f)), 3274 mkU8(0x4)))); 3275 assign(t4, binop(Iop_Or32, 3276 binop(Iop_Shr32, 3277 binop(Iop_And32, 3278 mkexpr(t3), 3279 mkU32(0xff00ff00)), 3280 mkU8(0x8)), 3281 binop(Iop_Shl32, 3282 binop(Iop_And32, 3283 mkexpr(t3), 3284 mkU32(0x00ff00ff)), 3285 mkU8(0x8)))); 3286 assign(t5, binop(Iop_Or32, 3287 binop(Iop_Shr32, 3288 mkexpr(t4), 3289 mkU8(0x10)), 3290 binop(Iop_Shl32, 3291 mkexpr(t4), 3292 mkU8(0x10)))); 3293 putIReg(rd, binop(Iop_Shr32, 3294 mkexpr(t5), 3295 mkU8(16))); 3296 break; 3297 } 3298 case 0x1C: { /* PRECEU.PH.QBL */ 3299 DIP("preceu.ph.qbl r%u, r%u", rd, rt); 3300 vassert(!mode64); 3301 3302 putIReg(rd, binop(Iop_Or32, 3303 binop(Iop_Shr32, 3304 binop(Iop_And32, 3305 getIReg(rt), 3306 mkU32(0xff000000)), 3307 mkU8(8)), 3308 binop(Iop_Shr32, 3309 binop(Iop_And32, 3310 getIReg(rt), 3311 mkU32(0x00ff0000)), 3312 mkU8(16)))); 3313 break; 3314 } 3315 case 0x1E: { /* PRECEU.PH.QBLA */ 3316 DIP("preceu.ph.qbla r%u, r%u", rd, rt); 3317 vassert(!mode64); 3318 3319 putIReg(rd, binop(Iop_Or32, 3320 binop(Iop_Shr32, 3321 binop(Iop_And32, 3322 getIReg(rt), 3323 mkU32(0xff000000)), 3324 mkU8(8)), 3325 binop(Iop_Shr32, 3326 binop(Iop_And32, 3327 getIReg(rt), 3328 mkU32(0x0000ff00)), 3329 mkU8(8)))); 3330 break; 3331 } 3332 case 0x1D: { /* PRECEU.PH.QBR */ 3333 DIP("preceu.ph.qbr r%u, r%u", rd, rt); 3334 vassert(!mode64); 3335 3336 putIReg(rd, binop(Iop_Or32, 3337 binop(Iop_Shl32, 3338 binop(Iop_And32, 3339 getIReg(rt), 3340 mkU32(0x0000ff00)), 3341 mkU8(8)), 3342 binop(Iop_And32, 3343 getIReg(rt), 3344 mkU32(0x000000ff)))); 3345 break; 3346 } 3347 case 0x1F: { /* PRECEU.PH.QBRA */ 3348 DIP("preceu.ph.qbra r%u, r%u", rd, rt); 3349 vassert(!mode64); 3350 3351 putIReg(rd, binop(Iop_Or32, 3352 binop(Iop_And32, 3353 getIReg(rt), 3354 mkU32(0x00ff0000)), 3355 binop(Iop_And32, 3356 getIReg(rt), 3357 mkU32(0x000000ff)))); 3358 break; 3359 } 3360 default: 3361 return -1; 3362 } 3363 break; /* end of ABSQ_S.PH */ 3364 } 3365 case 0x38: { /* EXTR.W */ 3366 switch(sa) { 3367 case 0x0: { /* EXTR.W */ 3368 DIP("extr.w r%u, ac%u, %u", rt, ac, rs); 3369 vassert(!mode64); 3370 t0 = newTemp(Ity_I64); 3371 t1 = newTemp(Ity_I64); 3372 t2 = newTemp(Ity_I32); 3373 t3 = newTemp(Ity_I1); 3374 t4 = newTemp(Ity_I1); 3375 t5 = newTemp(Ity_I1); 3376 t6 = newTemp(Ity_I1); 3377 t7 = newTemp(Ity_I32); 3378 t8 = newTemp(Ity_I64); 3379 t9 = newTemp(Ity_I64); 3380 t10 = newTemp(Ity_I1); 3381 t11 = newTemp(Ity_I1); 3382 t12 = newTemp(Ity_I1); 3383 t13 = newTemp(Ity_I1); 3384 t14 = newTemp(Ity_I32); 3385 3386 assign(t0, getAcc(ac)); 3387 if (0 == rs) { 3388 assign(t1, mkexpr(t0)); 3389 } else { 3390 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 3391 } 3392 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3393 assign(t3, binop(Iop_CmpNE32, 3394 unop(Iop_64HIto32, 3395 mkexpr(t1)), 3396 mkU32(0))); 3397 assign(t4, binop(Iop_CmpNE32, 3398 binop(Iop_And32, 3399 unop(Iop_64to32, 3400 mkexpr(t1)), 3401 mkU32(0x80000000)), 3402 mkU32(0))); 3403 /* Check if bits 63..31 of the result in t1 aren't 3404 0x1ffffffff. */ 3405 assign(t5, binop(Iop_CmpNE32, 3406 unop(Iop_64HIto32, 3407 mkexpr(t1)), 3408 mkU32(0xffffffff))); 3409 assign(t6, binop(Iop_CmpNE32, 3410 binop(Iop_And32, 3411 unop(Iop_64to32, 3412 mkexpr(t1)), 3413 mkU32(0x80000000)), 3414 mkU32(0x80000000))); 3415 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3416 control register. */ 3417 assign(t7, binop(Iop_And32, 3418 binop(Iop_Or32, 3419 unop(Iop_1Sto32, mkexpr(t3)), 3420 unop(Iop_1Sto32, mkexpr(t4))), 3421 binop(Iop_Or32, 3422 unop(Iop_1Sto32, mkexpr(t5)), 3423 unop(Iop_1Sto32, mkexpr(t6))))); 3424 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3425 mkexpr(t7), 3426 mkU32(0)), 3427 binop(Iop_Or32, 3428 getDSPControl(), 3429 mkU32(0x00800000)), 3430 getDSPControl())); 3431 3432 /* If the last discarded bit is 1, there would be carry 3433 when rounding, otherwise there wouldn't. We use that 3434 fact and just add the value of the last discarded bit 3435 to the least sifgnificant bit of the shifted value 3436 from acc. */ 3437 if (0 == rs) { 3438 assign(t8, mkU64(0x0ULL)); 3439 } else { 3440 assign(t8, binop(Iop_And64, 3441 binop(Iop_Shr64, 3442 mkexpr(t0), 3443 mkU8(rs-1)), 3444 mkU64(0x1ULL))); 3445 } 3446 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3447 3448 /* Repeat previous steps for the rounded value. */ 3449 assign(t10, binop(Iop_CmpNE32, 3450 unop(Iop_64HIto32, 3451 mkexpr(t9)), 3452 mkU32(0))); 3453 assign(t11, binop(Iop_CmpNE32, 3454 binop(Iop_And32, 3455 unop(Iop_64to32, 3456 mkexpr(t9)), 3457 mkU32(0x80000000)), 3458 mkU32(0))); 3459 3460 assign(t12, binop(Iop_CmpNE32, 3461 unop(Iop_64HIto32, 3462 mkexpr(t9)), 3463 mkU32(0xffffffff))); 3464 assign(t13, binop(Iop_CmpNE32, 3465 binop(Iop_And32, 3466 unop(Iop_64to32, 3467 mkexpr(t9)), 3468 mkU32(0x80000000)), 3469 mkU32(0x80000000))); 3470 3471 assign(t14, binop(Iop_And32, 3472 binop(Iop_Or32, 3473 unop(Iop_1Sto32, mkexpr(t10)), 3474 unop(Iop_1Sto32, mkexpr(t11))), 3475 binop(Iop_Or32, 3476 unop(Iop_1Sto32, mkexpr(t12)), 3477 unop(Iop_1Sto32, mkexpr(t13))))); 3478 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3479 mkexpr(t14), 3480 mkU32(0)), 3481 binop(Iop_Or32, 3482 getDSPControl(), 3483 mkU32(0x00800000)), 3484 getDSPControl())); 3485 if (0 == rs) { 3486 putIReg(rt, unop(Iop_64to32, mkexpr(t0))); 3487 } else { 3488 putIReg(rt, unop(Iop_64to32, mkexpr(t1))); 3489 } 3490 break; 3491 } 3492 case 0x1: { /* EXTRV.W */ 3493 DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs); 3494 vassert(!mode64); 3495 t0 = newTemp(Ity_I64); 3496 t1 = newTemp(Ity_I64); 3497 t2 = newTemp(Ity_I32); 3498 t3 = newTemp(Ity_I1); 3499 t4 = newTemp(Ity_I1); 3500 t5 = newTemp(Ity_I1); 3501 t6 = newTemp(Ity_I1); 3502 t7 = newTemp(Ity_I32); 3503 t8 = newTemp(Ity_I64); 3504 t9 = newTemp(Ity_I64); 3505 t10 = newTemp(Ity_I1); 3506 t11 = newTemp(Ity_I1); 3507 t12 = newTemp(Ity_I1); 3508 t13 = newTemp(Ity_I1); 3509 t14 = newTemp(Ity_I32); 3510 t15 = newTemp(Ity_I8); 3511 3512 assign(t15, unop(Iop_32to8, 3513 binop(Iop_And32, 3514 getIReg(rs), 3515 mkU32(0x1f)))); 3516 assign(t0, getAcc(ac)); 3517 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3518 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 3519 unop(Iop_8Uto32, 3520 mkexpr(t15)), 3521 mkU32(0)), 3522 unop(Iop_64to32, mkexpr(t0)), 3523 unop(Iop_64to32, mkexpr(t1)))); 3524 3525 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3526 assign(t3, binop(Iop_CmpNE32, 3527 unop(Iop_64HIto32, 3528 mkexpr(t1)), 3529 mkU32(0))); 3530 assign(t4, binop(Iop_CmpNE32, 3531 binop(Iop_And32, 3532 unop(Iop_64to32, 3533 mkexpr(t1)), 3534 mkU32(0x80000000)), 3535 mkU32(0))); 3536 /* Check if bits 63..31 of the result in t1 aren't 3537 0x1ffffffff. */ 3538 assign(t5, binop(Iop_CmpNE32, 3539 unop(Iop_64HIto32, 3540 mkexpr(t1)), 3541 mkU32(0xffffffff))); 3542 assign(t6, binop(Iop_CmpNE32, 3543 binop(Iop_And32, 3544 unop(Iop_64to32, 3545 mkexpr(t1)), 3546 mkU32(0x80000000)), 3547 mkU32(0x80000000))); 3548 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3549 control register. */ 3550 assign(t7, binop(Iop_And32, 3551 binop(Iop_Or32, 3552 unop(Iop_1Sto32, mkexpr(t3)), 3553 unop(Iop_1Sto32, mkexpr(t4))), 3554 binop(Iop_Or32, 3555 unop(Iop_1Sto32, mkexpr(t5)), 3556 unop(Iop_1Sto32, mkexpr(t6))))); 3557 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3558 mkexpr(t7), 3559 mkU32(0)), 3560 binop(Iop_Or32, 3561 getDSPControl(), 3562 mkU32(0x00800000)), 3563 getDSPControl())); 3564 3565 /* If the last discarded bit is 1, there would be carry 3566 when rounding, otherwise there wouldn't. We use that 3567 fact and just add the value of the last discarded bit 3568 to the least sifgnificant bit of the shifted value 3569 from acc. */ 3570 assign(t8, 3571 IRExpr_ITE(binop(Iop_CmpEQ32, 3572 unop(Iop_8Uto32, 3573 mkexpr(t15)), 3574 mkU32(0)), 3575 mkU64(0x0ULL), 3576 binop(Iop_And64, 3577 binop(Iop_Shr64, 3578 mkexpr(t0), 3579 unop(Iop_32to8, 3580 binop(Iop_Sub32, 3581 unop(Iop_8Uto32, 3582 mkexpr(t15)), 3583 mkU32(1)))), 3584 mkU64(0x1ULL)))); 3585 3586 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3587 3588 /* Repeat previous steps for the rounded value. */ 3589 assign(t10, binop(Iop_CmpNE32, 3590 unop(Iop_64HIto32, 3591 mkexpr(t9)), 3592 mkU32(0))); 3593 assign(t11, binop(Iop_CmpNE32, 3594 binop(Iop_And32, 3595 unop(Iop_64to32, 3596 mkexpr(t9)), 3597 mkU32(0x80000000)), 3598 mkU32(0))); 3599 3600 assign(t12, binop(Iop_CmpNE32, 3601 unop(Iop_64HIto32, 3602 mkexpr(t9)), 3603 mkU32(0xffffffff))); 3604 assign(t13, binop(Iop_CmpNE32, 3605 binop(Iop_And32, 3606 unop(Iop_64to32, 3607 mkexpr(t9)), 3608 mkU32(0x80000000)), 3609 mkU32(0x80000000))); 3610 3611 assign(t14, binop(Iop_And32, 3612 binop(Iop_Or32, 3613 unop(Iop_1Sto32, mkexpr(t10)), 3614 unop(Iop_1Sto32, mkexpr(t11))), 3615 binop(Iop_Or32, 3616 unop(Iop_1Sto32, mkexpr(t12)), 3617 unop(Iop_1Sto32, mkexpr(t13))))); 3618 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3619 mkexpr(t14), 3620 mkU32(0)), 3621 binop(Iop_Or32, 3622 getDSPControl(), 3623 mkU32(0x00800000)), 3624 getDSPControl())); 3625 break; 3626 } 3627 case 0x2: { /* EXTP */ 3628 DIP("extp r%u, ac%u, %u", rt, ac, rs); 3629 vassert(!mode64); 3630 t0 = newTemp(Ity_I64); 3631 t1 = newTemp(Ity_I32); 3632 t2 = newTemp(Ity_I1); 3633 t3 = newTemp(Ity_I1); 3634 t4 = newTemp(Ity_I8); 3635 t5 = newTemp(Ity_I64); 3636 t6 = newTemp(Ity_I64); 3637 t7 = newTemp(Ity_I32); 3638 3639 assign(t0, getAcc(ac)); 3640 /* Extract pos field of DSPControl register. */ 3641 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3642 3643 /* Check if (pos - size) >= 0 [size <= pos] 3644 if (pos < size) 3645 put 1 to EFI field of DSPControl register 3646 else 3647 extract bits from acc and put 0 to EFI field of 3648 DSPCtrl */ 3649 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 3650 3651 putDSPControl(IRExpr_ITE(mkexpr(t2), 3652 binop(Iop_Or32, 3653 binop(Iop_And32, 3654 getDSPControl(), 3655 mkU32(0xffffbfff)), 3656 mkU32(0x4000)), 3657 binop(Iop_And32, 3658 getDSPControl(), 3659 mkU32(0xffffbfff)))); 3660 3661 /* If pos <= 31, shift right the value from the acc 3662 (pos-size) times and take (size+1) bits from the least 3663 significant positions. Otherwise, shift left the value 3664 (63-pos) times, take (size+1) bits from the most 3665 significant positions and shift right (31-size) times.*/ 3666 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3667 3668 assign(t4, 3669 IRExpr_ITE(mkexpr(t3), 3670 unop(Iop_32to8, 3671 binop(Iop_Sub32, 3672 mkexpr(t1), mkU32(rs))), 3673 unop(Iop_32to8, 3674 binop(Iop_Sub32, 3675 mkU32(63), mkexpr(t1))))); 3676 3677 assign(t5, IRExpr_ITE(mkexpr(t3), 3678 binop(Iop_Shr64, 3679 mkexpr(t0), mkexpr(t4)), 3680 binop(Iop_Shl64, 3681 mkexpr(t0), mkexpr(t4)))); 3682 3683 /* t6 holds a mask for bit extraction */ 3684 assign(t6, 3685 IRExpr_ITE(mkexpr(t3), 3686 unop(Iop_Not64, 3687 binop(Iop_Shl64, 3688 mkU64(0xffffffffffffffffULL), 3689 mkU8(rs+1))), 3690 unop(Iop_Not64, 3691 binop(Iop_Shr64, 3692 mkU64(0xffffffffffffffffULL), 3693 mkU8(rs+1))))); 3694 3695 assign(t7, IRExpr_ITE(mkexpr(t3), 3696 unop(Iop_64to32, 3697 binop(Iop_And64, 3698 mkexpr(t5), 3699 mkexpr(t6))), 3700 binop(Iop_Shr32, 3701 unop(Iop_64HIto32, 3702 binop(Iop_And64, 3703 mkexpr(t5), 3704 mkexpr(t6))), 3705 mkU8(31-rs)))); 3706 3707 putIReg(rt, mkexpr(t7)); 3708 break; 3709 } 3710 case 0x3: { /* EXTPV */ 3711 DIP("extpv r%u, ac%u, r%u", rt, ac, rs); 3712 vassert(!mode64); 3713 t0 = newTemp(Ity_I64); 3714 t1 = newTemp(Ity_I32); 3715 t2 = newTemp(Ity_I1); 3716 t3 = newTemp(Ity_I1); 3717 t4 = newTemp(Ity_I8); 3718 t5 = newTemp(Ity_I64); 3719 t6 = newTemp(Ity_I64); 3720 t7 = newTemp(Ity_I32); 3721 t8 = newTemp(Ity_I32); 3722 3723 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 3724 assign(t0, getAcc(ac)); 3725 /* Extract pos field of DSPControl register. */ 3726 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3727 3728 /* Check if (pos - size) >= 0 [size <= pos] 3729 if (pos < size) 3730 put 1 to EFI field of DSPControl register 3731 else 3732 extract bits from acc and put 0 to EFI field of 3733 DSPCtrl */ 3734 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 3735 3736 putDSPControl(IRExpr_ITE(mkexpr(t2), 3737 binop(Iop_Or32, 3738 binop(Iop_And32, 3739 getDSPControl(), 3740 mkU32(0xffffbfff)), 3741 mkU32(0x4000)), 3742 binop(Iop_And32, 3743 getDSPControl(), 3744 mkU32(0xffffbfff)))); 3745 3746 /* If pos <= 31, shift right the value from the acc 3747 (pos-size) times and take (size+1) bits from the least 3748 significant positions. Otherwise, shift left the value 3749 (63-pos) times, take (size+1) bits from the most 3750 significant positions and shift right (31-size) 3751 times. */ 3752 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3753 3754 assign(t4, 3755 IRExpr_ITE(mkexpr(t3), 3756 unop(Iop_32to8, 3757 binop(Iop_Sub32, 3758 mkexpr(t1), mkexpr(t8))), 3759 unop(Iop_32to8, 3760 binop(Iop_Sub32, 3761 mkU32(63), mkexpr(t1))))); 3762 3763 assign(t5, IRExpr_ITE(mkexpr(t3), 3764 binop(Iop_Shr64, 3765 mkexpr(t0), mkexpr(t4)), 3766 binop(Iop_Shl64, 3767 mkexpr(t0), mkexpr(t4)))); 3768 3769 /* t6 holds a mask for bit extraction. */ 3770 assign(t6, 3771 IRExpr_ITE(mkexpr(t3), 3772 unop(Iop_Not64, 3773 binop(Iop_Shl64, 3774 mkU64(0xffffffffffffffffULL), 3775 unop(Iop_32to8, 3776 binop(Iop_Add32, 3777 mkexpr(t8), 3778 mkU32(1))))), 3779 unop(Iop_Not64, 3780 binop(Iop_Shr64, 3781 mkU64(0xffffffffffffffffULL), 3782 unop(Iop_32to8, 3783 binop(Iop_Add32, 3784 mkexpr(t8), 3785 mkU32(1))))))); 3786 3787 assign(t7, IRExpr_ITE(mkexpr(t3), 3788 unop(Iop_64to32, 3789 binop(Iop_And64, 3790 mkexpr(t5), 3791 mkexpr(t6))), 3792 binop(Iop_Shr32, 3793 unop(Iop_64HIto32, 3794 binop(Iop_And64, 3795 mkexpr(t5), 3796 mkexpr(t6))), 3797 unop(Iop_32to8, 3798 binop(Iop_Sub32, 3799 mkU32(31), 3800 mkexpr(t8)))))); 3801 3802 putIReg(rt, mkexpr(t7)); 3803 break; 3804 } 3805 case 0x4: { /* EXTR_R.W */ 3806 DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs); 3807 vassert(!mode64); 3808 t0 = newTemp(Ity_I64); 3809 t1 = newTemp(Ity_I64); 3810 t2 = newTemp(Ity_I32); 3811 t3 = newTemp(Ity_I1); 3812 t4 = newTemp(Ity_I1); 3813 t5 = newTemp(Ity_I1); 3814 t6 = newTemp(Ity_I1); 3815 t7 = newTemp(Ity_I32); 3816 t8 = newTemp(Ity_I64); 3817 t9 = newTemp(Ity_I64); 3818 t10 = newTemp(Ity_I1); 3819 t11 = newTemp(Ity_I1); 3820 t12 = newTemp(Ity_I1); 3821 t13 = newTemp(Ity_I1); 3822 t14 = newTemp(Ity_I32); 3823 t15 = newTemp(Ity_I64); 3824 t16 = newTemp(Ity_I1); 3825 3826 assign(t0, getAcc(ac)); 3827 assign(t16, binop(Iop_CmpEQ32, 3828 mkU32(rs), 3829 mkU32(0))); 3830 assign(t1, IRExpr_ITE(mkexpr(t16), 3831 mkexpr(t0), 3832 binop(Iop_Sar64, 3833 mkexpr(t0), 3834 mkU8(rs)))); 3835 /* If the last discarded bit is 1, there would be carry 3836 when rounding, otherwise there wouldn't. We use that 3837 fact and just add the value of the last discarded bit 3838 to the least significant bit of the shifted value 3839 from acc. */ 3840 assign(t15, binop(Iop_Shr64, 3841 mkexpr(t0), 3842 unop(Iop_32to8, 3843 binop(Iop_Sub32, 3844 binop(Iop_And32, 3845 mkU32(rs), 3846 mkU32(0x1f)), 3847 mkU32(1))))); 3848 3849 assign(t8, 3850 IRExpr_ITE(mkexpr(t16), 3851 mkU64(0x0ULL), 3852 binop(Iop_And64, 3853 mkexpr(t15), 3854 mkU64(0x0000000000000001ULL)))); 3855 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3856 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 3857 3858 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3859 assign(t3, binop(Iop_CmpNE32, 3860 unop(Iop_64HIto32, 3861 mkexpr(t1)), 3862 mkU32(0))); 3863 assign(t4, binop(Iop_CmpNE32, 3864 binop(Iop_And32, 3865 unop(Iop_64to32, 3866 mkexpr(t1)), 3867 mkU32(0x80000000)), 3868 mkU32(0))); 3869 3870 /* Check if bits 63..31 of the result in t1 aren't 3871 0x1ffffffff. */ 3872 assign(t5, binop(Iop_CmpNE32, 3873 unop(Iop_64HIto32, 3874 mkexpr(t1)), 3875 mkU32(0xffffffff))); 3876 assign(t6, binop(Iop_CmpNE32, 3877 binop(Iop_And32, 3878 unop(Iop_64to32, 3879 mkexpr(t1)), 3880 mkU32(0x80000000)), 3881 mkU32(0x80000000))); 3882 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3883 control register. */ 3884 assign(t7, binop(Iop_And32, 3885 binop(Iop_Or32, 3886 unop(Iop_1Sto32, mkexpr(t3)), 3887 unop(Iop_1Sto32, mkexpr(t4))), 3888 binop(Iop_Or32, 3889 unop(Iop_1Sto32, mkexpr(t5)), 3890 unop(Iop_1Sto32, mkexpr(t6))))); 3891 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3892 mkexpr(t7), 3893 mkU32(0)), 3894 binop(Iop_Or32, 3895 getDSPControl(), 3896 mkU32(0x00800000)), 3897 getDSPControl())); 3898 3899 /* Repeat previous steps for the rounded value. */ 3900 assign(t10, binop(Iop_CmpNE32, 3901 unop(Iop_64HIto32, 3902 mkexpr(t9)), 3903 mkU32(0))); 3904 assign(t11, binop(Iop_CmpNE32, 3905 binop(Iop_And32, 3906 unop(Iop_64to32, 3907 mkexpr(t9)), 3908 mkU32(0x80000000)), 3909 mkU32(0))); 3910 3911 assign(t12, binop(Iop_CmpNE32, 3912 unop(Iop_64HIto32, 3913 mkexpr(t9)), 3914 mkU32(0xffffffff))); 3915 assign(t13, binop(Iop_CmpNE32, 3916 binop(Iop_And32, 3917 unop(Iop_64to32, 3918 mkexpr(t9)), 3919 mkU32(0x80000000)), 3920 mkU32(0x80000000))); 3921 3922 assign(t14, binop(Iop_And32, 3923 binop(Iop_Or32, 3924 unop(Iop_1Sto32, mkexpr(t10)), 3925 unop(Iop_1Sto32, mkexpr(t11))), 3926 binop(Iop_Or32, 3927 unop(Iop_1Sto32, mkexpr(t12)), 3928 unop(Iop_1Sto32, mkexpr(t13))))); 3929 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3930 mkexpr(t14), 3931 mkU32(0)), 3932 binop(Iop_Or32, 3933 getDSPControl(), 3934 mkU32(0x00800000)), 3935 getDSPControl())); 3936 break; 3937 } 3938 case 0x5: { /* EXTRV_R.W */ 3939 DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs); 3940 vassert(!mode64); 3941 t0 = newTemp(Ity_I64); 3942 t1 = newTemp(Ity_I64); 3943 t2 = newTemp(Ity_I32); 3944 t3 = newTemp(Ity_I1); 3945 t4 = newTemp(Ity_I1); 3946 t5 = newTemp(Ity_I1); 3947 t6 = newTemp(Ity_I1); 3948 t7 = newTemp(Ity_I32); 3949 t8 = newTemp(Ity_I64); 3950 t9 = newTemp(Ity_I64); 3951 t10 = newTemp(Ity_I1); 3952 t11 = newTemp(Ity_I1); 3953 t12 = newTemp(Ity_I1); 3954 t13 = newTemp(Ity_I1); 3955 t14 = newTemp(Ity_I32); 3956 t15 = newTemp(Ity_I8); 3957 3958 assign(t15, unop(Iop_32to8, 3959 binop(Iop_And32, 3960 getIReg(rs), 3961 mkU32(0x1f)))); 3962 assign(t0, getAcc(ac)); 3963 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3964 3965 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3966 assign(t3, binop(Iop_CmpNE32, 3967 unop(Iop_64HIto32, 3968 mkexpr(t1)), 3969 mkU32(0))); 3970 assign(t4, binop(Iop_CmpNE32, 3971 binop(Iop_And32, 3972 unop(Iop_64to32, 3973 mkexpr(t1)), 3974 mkU32(0x80000000)), 3975 mkU32(0))); 3976 /* Check if bits 63..31 of the result in t1 aren't 3977 0x1ffffffff. */ 3978 assign(t5, binop(Iop_CmpNE32, 3979 unop(Iop_64HIto32, 3980 mkexpr(t1)), 3981 mkU32(0xffffffff))); 3982 assign(t6, binop(Iop_CmpNE32, 3983 binop(Iop_And32, 3984 unop(Iop_64to32, 3985 mkexpr(t1)), 3986 mkU32(0x80000000)), 3987 mkU32(0x80000000))); 3988 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3989 control register. */ 3990 assign(t7, binop(Iop_And32, 3991 binop(Iop_Or32, 3992 unop(Iop_1Sto32, mkexpr(t3)), 3993 unop(Iop_1Sto32, mkexpr(t4))), 3994 binop(Iop_Or32, 3995 unop(Iop_1Sto32, mkexpr(t5)), 3996 unop(Iop_1Sto32, mkexpr(t6))))); 3997 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3998 mkexpr(t7), 3999 mkU32(0)), 4000 binop(Iop_Or32, 4001 getDSPControl(), 4002 mkU32(0x00800000)), 4003 getDSPControl())); 4004 4005 /* If the last discarded bit is 1, there would be carry 4006 when rounding, otherwise there wouldn't. We use that 4007 fact and just add the value of the last discarded bit 4008 to the least sifgnificant bit of the shifted value 4009 from acc. */ 4010 assign(t8, 4011 IRExpr_ITE(binop(Iop_CmpEQ32, 4012 unop(Iop_8Uto32, 4013 mkexpr(t15)), 4014 mkU32(0)), 4015 mkU64(0x0ULL), 4016 binop(Iop_And64, 4017 binop(Iop_Shr64, 4018 mkexpr(t0), 4019 unop(Iop_32to8, 4020 binop(Iop_Sub32, 4021 unop(Iop_8Uto32, 4022 mkexpr(t15)), 4023 mkU32(1)))), 4024 mkU64(0x1ULL)))); 4025 4026 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4027 /* Put rounded value in destination register. */ 4028 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 4029 4030 /* Repeat previous steps for the rounded value. */ 4031 assign(t10, binop(Iop_CmpNE32, 4032 unop(Iop_64HIto32, 4033 mkexpr(t9)), 4034 mkU32(0))); 4035 assign(t11, binop(Iop_CmpNE32, 4036 binop(Iop_And32, 4037 unop(Iop_64to32, 4038 mkexpr(t9)), 4039 mkU32(0x80000000)), 4040 mkU32(0))); 4041 4042 assign(t12, binop(Iop_CmpNE32, 4043 unop(Iop_64HIto32, 4044 mkexpr(t9)), 4045 mkU32(0xffffffff))); 4046 assign(t13, binop(Iop_CmpNE32, 4047 binop(Iop_And32, 4048 unop(Iop_64to32, 4049 mkexpr(t9)), 4050 mkU32(0x80000000)), 4051 mkU32(0x80000000))); 4052 4053 assign(t14, binop(Iop_And32, 4054 binop(Iop_Or32, 4055 unop(Iop_1Sto32, mkexpr(t10)), 4056 unop(Iop_1Sto32, mkexpr(t11))), 4057 binop(Iop_Or32, 4058 unop(Iop_1Sto32, mkexpr(t12)), 4059 unop(Iop_1Sto32, mkexpr(t13))))); 4060 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4061 mkexpr(t14), 4062 mkU32(0)), 4063 binop(Iop_Or32, 4064 getDSPControl(), 4065 mkU32(0x00800000)), 4066 getDSPControl())); 4067 break; 4068 } 4069 case 0x6: { /* EXTR_RS.W */ 4070 DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs); 4071 vassert(!mode64); 4072 t0 = newTemp(Ity_I64); 4073 t1 = newTemp(Ity_I64); 4074 t2 = newTemp(Ity_I32); 4075 t3 = newTemp(Ity_I1); 4076 t4 = newTemp(Ity_I1); 4077 t5 = newTemp(Ity_I1); 4078 t6 = newTemp(Ity_I1); 4079 t7 = newTemp(Ity_I32); 4080 t8 = newTemp(Ity_I64); 4081 t9 = newTemp(Ity_I64); 4082 t10 = newTemp(Ity_I1); 4083 t11 = newTemp(Ity_I1); 4084 t12 = newTemp(Ity_I1); 4085 t13 = newTemp(Ity_I1); 4086 t14 = newTemp(Ity_I32); 4087 t16 = newTemp(Ity_I32); 4088 4089 assign(t0, getAcc(ac)); 4090 if (0 == rs) { 4091 assign(t1, mkexpr(t0)); 4092 } else { 4093 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4094 } 4095 4096 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4097 assign(t3, binop(Iop_CmpNE32, 4098 unop(Iop_64HIto32, 4099 mkexpr(t1)), 4100 mkU32(0))); 4101 assign(t4, binop(Iop_CmpNE32, 4102 binop(Iop_And32, 4103 unop(Iop_64to32, 4104 mkexpr(t1)), 4105 mkU32(0x80000000)), 4106 mkU32(0))); 4107 /* Check if bits 63..31 of the result in t1 aren't 4108 0x1ffffffff. */ 4109 assign(t5, binop(Iop_CmpNE32, 4110 unop(Iop_64HIto32, 4111 mkexpr(t1)), 4112 mkU32(0xffffffff))); 4113 assign(t6, binop(Iop_CmpNE32, 4114 binop(Iop_And32, 4115 unop(Iop_64to32, 4116 mkexpr(t1)), 4117 mkU32(0x80000000)), 4118 mkU32(0x80000000))); 4119 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4120 control register. */ 4121 assign(t7, binop(Iop_And32, 4122 binop(Iop_Or32, 4123 unop(Iop_1Sto32, mkexpr(t3)), 4124 unop(Iop_1Sto32, mkexpr(t4))), 4125 binop(Iop_Or32, 4126 unop(Iop_1Sto32, mkexpr(t5)), 4127 unop(Iop_1Sto32, mkexpr(t6))))); 4128 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4129 mkexpr(t7), 4130 mkU32(0)), 4131 binop(Iop_Or32, 4132 getDSPControl(), 4133 mkU32(0x00800000)), 4134 getDSPControl())); 4135 4136 /* If the last discarded bit is 1, there would be carry 4137 when rounding, otherwise there wouldn't. We use that 4138 fact and just add the value of the last discarded bit 4139 to the least sifgnificant bit of the shifted value 4140 from acc. */ 4141 if (0 == rs) { 4142 assign(t8, mkU64(0x0ULL)); 4143 } else { 4144 assign(t8, binop(Iop_And64, 4145 binop(Iop_Shr64, 4146 mkexpr(t0), 4147 mkU8(rs-1)), 4148 mkU64(0x1ULL))); 4149 } 4150 4151 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4152 4153 /* Repeat previous steps for the rounded value. */ 4154 assign(t10, binop(Iop_CmpNE32, 4155 unop(Iop_64HIto32, 4156 mkexpr(t9)), 4157 mkU32(0))); 4158 assign(t11, binop(Iop_CmpNE32, 4159 binop(Iop_And32, 4160 unop(Iop_64to32, 4161 mkexpr(t9)), 4162 mkU32(0x80000000)), 4163 mkU32(0))); 4164 4165 assign(t12, binop(Iop_CmpNE32, 4166 unop(Iop_64HIto32, 4167 mkexpr(t9)), 4168 mkU32(0xffffffff))); 4169 assign(t13, binop(Iop_CmpNE32, 4170 binop(Iop_And32, 4171 unop(Iop_64to32, 4172 mkexpr(t9)), 4173 mkU32(0x80000000)), 4174 mkU32(0x80000000))); 4175 4176 assign(t14, binop(Iop_And32, 4177 binop(Iop_Or32, 4178 unop(Iop_1Sto32, mkexpr(t10)), 4179 unop(Iop_1Sto32, mkexpr(t11))), 4180 binop(Iop_Or32, 4181 unop(Iop_1Sto32, mkexpr(t12)), 4182 unop(Iop_1Sto32, mkexpr(t13))))); 4183 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4184 mkexpr(t14), 4185 mkU32(0)), 4186 binop(Iop_Or32, 4187 getDSPControl(), 4188 mkU32(0x00800000)), 4189 getDSPControl())); 4190 4191 assign(t16, binop(Iop_And32, 4192 unop(Iop_64HIto32, 4193 mkexpr(t9)), 4194 mkU32(0x80000000))); 4195 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4196 mkexpr(t14), 4197 mkU32(0)), 4198 IRExpr_ITE(binop(Iop_CmpEQ32, 4199 mkexpr(t16), 4200 mkU32(0)), 4201 mkU32(0x7fffffff), 4202 mkU32(0x80000000)), 4203 unop(Iop_64to32, mkexpr(t9)))); 4204 break; 4205 } 4206 case 0x7: { /* EXTRV_RS.W */ 4207 DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs); 4208 vassert(!mode64); 4209 t0 = newTemp(Ity_I64); 4210 t1 = newTemp(Ity_I64); 4211 t2 = newTemp(Ity_I32); 4212 t3 = newTemp(Ity_I1); 4213 t4 = newTemp(Ity_I1); 4214 t5 = newTemp(Ity_I1); 4215 t6 = newTemp(Ity_I1); 4216 t7 = newTemp(Ity_I32); 4217 t8 = newTemp(Ity_I64); 4218 t9 = newTemp(Ity_I64); 4219 t10 = newTemp(Ity_I1); 4220 t11 = newTemp(Ity_I1); 4221 t12 = newTemp(Ity_I1); 4222 t13 = newTemp(Ity_I1); 4223 t14 = newTemp(Ity_I32); 4224 t15 = newTemp(Ity_I32); 4225 t16 = newTemp(Ity_I32); 4226 t17 = newTemp(Ity_I1); 4227 4228 assign(t15, binop(Iop_And32, 4229 getIReg(rs), 4230 mkU32(0x1f))); 4231 assign(t17, binop(Iop_CmpEQ32, 4232 mkexpr(t15), 4233 mkU32(0))); 4234 assign(t0, getAcc(ac)); 4235 assign(t1, IRExpr_ITE(mkexpr(t17), 4236 mkexpr(t0), 4237 binop(Iop_Sar64, 4238 mkexpr(t0), 4239 unop(Iop_32to8, 4240 mkexpr(t15))))); 4241 4242 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4243 assign(t3, binop(Iop_CmpNE32, 4244 unop(Iop_64HIto32, 4245 mkexpr(t1)), 4246 mkU32(0))); 4247 assign(t4, binop(Iop_CmpNE32, 4248 binop(Iop_And32, 4249 unop(Iop_64to32, 4250 mkexpr(t1)), 4251 mkU32(0x80000000)), 4252 mkU32(0))); 4253 /* Check if bits 63..31 of the result in t1 aren't 4254 0x1ffffffff. */ 4255 assign(t5, binop(Iop_CmpNE32, 4256 unop(Iop_64HIto32, 4257 mkexpr(t1)), 4258 mkU32(0xffffffff))); 4259 assign(t6, binop(Iop_CmpNE32, 4260 binop(Iop_And32, 4261 unop(Iop_64to32, 4262 mkexpr(t1)), 4263 mkU32(0x80000000)), 4264 mkU32(0x80000000))); 4265 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4266 control register. */ 4267 assign(t7, binop(Iop_And32, 4268 binop(Iop_Or32, 4269 unop(Iop_1Sto32, mkexpr(t3)), 4270 unop(Iop_1Sto32, mkexpr(t4))), 4271 binop(Iop_Or32, 4272 unop(Iop_1Sto32, mkexpr(t5)), 4273 unop(Iop_1Sto32, mkexpr(t6))))); 4274 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4275 mkexpr(t7), 4276 mkU32(0)), 4277 binop(Iop_Or32, 4278 getDSPControl(), 4279 mkU32(0x00800000)), 4280 getDSPControl())); 4281 4282 /* If the last discarded bit is 1, there would be carry 4283 when rounding, otherwise there wouldn't. We use that 4284 fact and just add the value of the last discarded bit 4285 to the least sifgnificant bit of the shifted value 4286 from acc. */ 4287 assign(t8, 4288 IRExpr_ITE(mkexpr(t17), 4289 mkU64(0x0ULL), 4290 binop(Iop_And64, 4291 binop(Iop_Shr64, 4292 mkexpr(t0), 4293 unop(Iop_32to8, 4294 binop(Iop_Sub32, 4295 mkexpr(t15), 4296 mkU32(1)))), 4297 mkU64(0x1ULL)))); 4298 4299 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4300 4301 /* Repeat previous steps for the rounded value. */ 4302 assign(t10, binop(Iop_CmpNE32, 4303 unop(Iop_64HIto32, 4304 mkexpr(t9)), 4305 mkU32(0))); 4306 assign(t11, binop(Iop_CmpNE32, 4307 binop(Iop_And32, 4308 unop(Iop_64to32, 4309 mkexpr(t9)), 4310 mkU32(0x80000000)), 4311 mkU32(0))); 4312 4313 assign(t12, binop(Iop_CmpNE32, 4314 unop(Iop_64HIto32, 4315 mkexpr(t9)), 4316 mkU32(0xffffffff))); 4317 assign(t13, binop(Iop_CmpNE32, 4318 binop(Iop_And32, 4319 unop(Iop_64to32, 4320 mkexpr(t9)), 4321 mkU32(0x80000000)), 4322 mkU32(0x80000000))); 4323 4324 assign(t14, binop(Iop_And32, 4325 binop(Iop_Or32, 4326 unop(Iop_1Sto32, mkexpr(t10)), 4327 unop(Iop_1Sto32, mkexpr(t11))), 4328 binop(Iop_Or32, 4329 unop(Iop_1Sto32, mkexpr(t12)), 4330 unop(Iop_1Sto32, mkexpr(t13))))); 4331 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4332 mkexpr(t14), 4333 mkU32(0)), 4334 binop(Iop_Or32, 4335 getDSPControl(), 4336 mkU32(0x00800000)), 4337 getDSPControl())); 4338 4339 assign(t16, binop(Iop_And32, 4340 unop(Iop_64HIto32, 4341 mkexpr(t9)), 4342 mkU32(0x80000000))); 4343 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4344 mkexpr(t14), 4345 mkU32(0)), 4346 IRExpr_ITE(binop(Iop_CmpEQ32, 4347 mkexpr(t16), 4348 mkU32(0)), 4349 mkU32(0x7fffffff), 4350 mkU32(0x80000000)), 4351 unop(Iop_64to32, mkexpr(t9)))); 4352 break; 4353 } 4354 case 0xA: { /* EXTPDP */ 4355 DIP("extpdp r%u, ac%u, %u", rt, ac, rs); 4356 vassert(!mode64); 4357 t0 = newTemp(Ity_I64); 4358 t1 = newTemp(Ity_I32); 4359 t2 = newTemp(Ity_I1); 4360 t3 = newTemp(Ity_I1); 4361 t4 = newTemp(Ity_I8); 4362 t5 = newTemp(Ity_I64); 4363 t6 = newTemp(Ity_I64); 4364 t7 = newTemp(Ity_I32); 4365 t8 = newTemp(Ity_I32); 4366 4367 assign(t0, getAcc(ac)); 4368 /* Extract pos field of DSPControl register. */ 4369 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4370 4371 /* Check if (pos - size) >= 0 [size <= pos] 4372 if (pos < size) 4373 put 1 to EFI field of DSPControl register 4374 else 4375 extract bits from acc and put 0 to EFI field of 4376 DSPCtrl */ 4377 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 4378 4379 assign(t8, binop(Iop_Or32, 4380 binop(Iop_And32, 4381 getDSPControl(), 4382 mkU32(0xffffbfc0)), 4383 binop(Iop_And32, 4384 binop(Iop_Sub32, 4385 binop(Iop_And32, 4386 getDSPControl(), 4387 mkU32(0x3f)), 4388 mkU32(rs+1)), 4389 mkU32(0x3f)))); 4390 putDSPControl(IRExpr_ITE(mkexpr(t2), 4391 binop(Iop_Or32, 4392 binop(Iop_And32, 4393 getDSPControl(), 4394 mkU32(0xffffbfff)), 4395 mkU32(0x4000)), 4396 mkexpr(t8))); 4397 4398 /* If pos <= 31, shift right the value from the acc 4399 (pos-size) times and take (size+1) bits from the least 4400 significant positions. Otherwise, shift left the value 4401 (63-pos) times, take (size+1) bits from the most 4402 significant positions and shift right (31-size) times. 4403 */ 4404 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4405 4406 assign(t4, 4407 IRExpr_ITE(mkexpr(t3), 4408 unop(Iop_32to8, 4409 binop(Iop_Sub32, 4410 mkexpr(t1), mkU32(rs))), 4411 unop(Iop_32to8, 4412 binop(Iop_Sub32, 4413 mkU32(63), mkexpr(t1))))); 4414 4415 assign(t5, IRExpr_ITE(mkexpr(t3), 4416 binop(Iop_Shr64, 4417 mkexpr(t0), mkexpr(t4)), 4418 binop(Iop_Shl64, 4419 mkexpr(t0), mkexpr(t4)))); 4420 4421 /* t6 holds a mask for bit extraction. */ 4422 assign(t6, 4423 IRExpr_ITE(mkexpr(t3), 4424 unop(Iop_Not64, 4425 binop(Iop_Shl64, 4426 mkU64(0xffffffffffffffffULL), 4427 mkU8(rs+1))), 4428 unop(Iop_Not64, 4429 binop(Iop_Shr64, 4430 mkU64(0xffffffffffffffffULL), 4431 mkU8(rs+1))))); 4432 4433 assign(t7, IRExpr_ITE(mkexpr(t3), 4434 unop(Iop_64to32, 4435 binop(Iop_And64, 4436 mkexpr(t5), 4437 mkexpr(t6))), 4438 binop(Iop_Shr32, 4439 unop(Iop_64HIto32, 4440 binop(Iop_And64, 4441 mkexpr(t5), 4442 mkexpr(t6))), 4443 mkU8(31-rs)))); 4444 4445 putIReg(rt, mkexpr(t7)); 4446 break; 4447 } 4448 case 0xB: { /* EXTPDPV */ 4449 DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs); 4450 vassert(!mode64); 4451 t0 = newTemp(Ity_I64); 4452 t1 = newTemp(Ity_I32); 4453 t2 = newTemp(Ity_I1); 4454 t3 = newTemp(Ity_I1); 4455 t4 = newTemp(Ity_I8); 4456 t5 = newTemp(Ity_I64); 4457 t6 = newTemp(Ity_I64); 4458 t7 = newTemp(Ity_I32); 4459 t8 = newTemp(Ity_I32); 4460 t9 = newTemp(Ity_I32); 4461 4462 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 4463 assign(t0, getAcc(ac)); 4464 /* Extract pos field of DSPControl register. */ 4465 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4466 4467 /* Check if (pos - size) >= 0 [size <= pos] 4468 if (pos < size) 4469 put 1 to EFI field of DSPControl register 4470 else 4471 extract bits from acc and put 0 to EFI field of 4472 DSPCtrl */ 4473 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 4474 4475 assign(t9, binop(Iop_Or32, 4476 binop(Iop_And32, 4477 getDSPControl(), 4478 mkU32(0xffffbfc0)), 4479 binop(Iop_And32, 4480 binop(Iop_Sub32, 4481 binop(Iop_And32, 4482 getDSPControl(), 4483 mkU32(0x3f)), 4484 binop(Iop_Add32, 4485 mkexpr(t8), 4486 mkU32(0x1))), 4487 mkU32(0x3f)))); 4488 putDSPControl(IRExpr_ITE(mkexpr(t2), 4489 binop(Iop_Or32, 4490 binop(Iop_And32, 4491 getDSPControl(), 4492 mkU32(0xffffbfff)), 4493 mkU32(0x4000)), 4494 mkexpr(t9))); 4495 4496 /* If pos <= 31, shift right the value from the acc 4497 (pos-size) times and take (size+1) bits from the least 4498 significant positions. Otherwise, shift left the value 4499 (63-pos) times, take (size+1) bits from the most 4500 significant positions and shift right (31-size) times. 4501 */ 4502 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4503 4504 assign(t4, 4505 IRExpr_ITE(mkexpr(t3), 4506 unop(Iop_32to8, 4507 binop(Iop_Sub32, 4508 mkexpr(t1), mkexpr(t8))), 4509 unop(Iop_32to8, 4510 binop(Iop_Sub32, 4511 mkU32(63), mkexpr(t1))))); 4512 4513 assign(t5, IRExpr_ITE(mkexpr(t3), 4514 binop(Iop_Shr64, 4515 mkexpr(t0), mkexpr(t4)), 4516 binop(Iop_Shl64, 4517 mkexpr(t0), mkexpr(t4)))); 4518 4519 /* t6 holds a mask for bit extraction. */ 4520 assign(t6, 4521 IRExpr_ITE(mkexpr(t3), 4522 unop(Iop_Not64, 4523 binop(Iop_Shl64, 4524 mkU64(0xffffffffffffffffULL), 4525 unop(Iop_32to8, 4526 binop(Iop_Add32, 4527 mkexpr(t8), 4528 mkU32(1))))), 4529 unop(Iop_Not64, 4530 binop(Iop_Shr64, 4531 mkU64(0xffffffffffffffffULL), 4532 unop(Iop_32to8, 4533 binop(Iop_Add32, 4534 mkexpr(t8), 4535 mkU32(1))))))); 4536 4537 assign(t7, IRExpr_ITE(mkexpr(t3), 4538 unop(Iop_64to32, 4539 binop(Iop_And64, 4540 mkexpr(t5), 4541 mkexpr(t6))), 4542 binop(Iop_Shr32, 4543 unop(Iop_64HIto32, 4544 binop(Iop_And64, 4545 mkexpr(t5), 4546 mkexpr(t6))), 4547 unop(Iop_32to8, 4548 binop(Iop_Sub32, 4549 mkU32(31), 4550 mkexpr(t8)))))); 4551 4552 putIReg(rt, mkexpr(t7)); 4553 break; 4554 } 4555 case 0xE: { /* EXTR_S.H */ 4556 DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs); 4557 vassert(!mode64); 4558 t0 = newTemp(Ity_I64); 4559 t1 = newTemp(Ity_I64); 4560 t2 = newTemp(Ity_I32); 4561 t3 = newTemp(Ity_I64); 4562 t4 = newTemp(Ity_I32); 4563 t5 = newTemp(Ity_I32); 4564 t6 = newTemp(Ity_I64); 4565 t7 = newTemp(Ity_I32); 4566 t9 = newTemp(Ity_I32); 4567 4568 assign(t0, getAcc(ac)); 4569 4570 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4571 4572 assign(t2, binop(Iop_Or32, 4573 getDSPControl(), mkU32(0x00800000))); 4574 4575 assign(t9, binop(Iop_And32, 4576 unop(Iop_64to32, 4577 mkexpr(t1)), 4578 mkU32(0x80000000))); 4579 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4580 mkexpr(t9), 4581 binop(Iop_And32, 4582 unop(Iop_64HIto32, 4583 mkexpr(t0)), 4584 mkU32(0x80000000))), 4585 mkexpr(t2), 4586 getDSPControl())); 4587 4588 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4589 1. subtract 0x7fff from t1 4590 2. if the resulting number is positive (sign bit = 0) 4591 and any of the other bits is 1, the value is > 0. */ 4592 assign(t3, binop(Iop_Sub64, 4593 mkexpr(t1), 4594 mkU64(0x0000000000007fffULL))); 4595 assign(t4, binop(Iop_And32, 4596 binop(Iop_Or32, 4597 unop(Iop_1Sto32, 4598 binop(Iop_CmpNE32, 4599 mkU32(0), 4600 binop(Iop_And32, 4601 unop(Iop_64HIto32, 4602 mkexpr(t3)), 4603 mkU32(0x7fffffff)))), 4604 unop(Iop_1Sto32, 4605 binop(Iop_CmpNE32, 4606 mkU32(0), 4607 unop(Iop_64to32, 4608 mkexpr(t3))))), 4609 unop(Iop_1Sto32, 4610 binop(Iop_CmpEQ32, 4611 binop(Iop_And32, 4612 unop(Iop_64HIto32, 4613 mkexpr(t3)), 4614 mkU32(0x80000000)), 4615 mkU32(0))))); 4616 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4617 mkU32(0), 4618 mkexpr(t4)), 4619 binop(Iop_Or32, 4620 getDSPControl(), 4621 mkU32(0x00800000)), 4622 getDSPControl())); 4623 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4624 1. subtract t1 from 0xffffffffffff8000 4625 2. if the resulting number is positive (sign bit = 0) 4626 and any of the other bits is 1, the value is > 0 */ 4627 assign(t6, binop(Iop_Sub64, 4628 mkU64(0xffffffffffff8000ULL), 4629 mkexpr(t1))); 4630 assign(t7, binop(Iop_And32, 4631 binop(Iop_Or32, 4632 unop(Iop_1Sto32, 4633 binop(Iop_CmpNE32, 4634 mkU32(0), 4635 binop(Iop_And32, 4636 unop(Iop_64HIto32, 4637 mkexpr(t6)), 4638 mkU32(0x7fffffff)))), 4639 unop(Iop_1Sto32, 4640 binop(Iop_CmpNE32, 4641 mkU32(0), 4642 unop(Iop_64to32, 4643 mkexpr(t6))))), 4644 unop(Iop_1Sto32, 4645 binop(Iop_CmpEQ32, 4646 binop(Iop_And32, 4647 unop(Iop_64HIto32, 4648 mkexpr(t6)), 4649 mkU32(0x80000000)), 4650 mkU32(0))))); 4651 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4652 mkU32(0), 4653 mkexpr(t7)), 4654 binop(Iop_Or32, 4655 getDSPControl(), 4656 mkU32(0x00800000)), 4657 getDSPControl())); 4658 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4659 mkU32(0), 4660 mkexpr(t4)), 4661 mkU32(0x00007fff), 4662 IRExpr_ITE(binop(Iop_CmpNE32, 4663 mkU32(0), 4664 mkexpr(t7)), 4665 mkU32(0xffff8000), 4666 unop(Iop_64to32, 4667 mkexpr(t1))))); 4668 break; 4669 } 4670 case 0xF: { /* EXTRV_S.H */ 4671 DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs); 4672 vassert(!mode64); 4673 t0 = newTemp(Ity_I64); 4674 t1 = newTemp(Ity_I64); 4675 t2 = newTemp(Ity_I32); 4676 t3 = newTemp(Ity_I64); 4677 t4 = newTemp(Ity_I32); 4678 t5 = newTemp(Ity_I32); 4679 t6 = newTemp(Ity_I64); 4680 t7 = newTemp(Ity_I32); 4681 t9 = newTemp(Ity_I32); 4682 4683 assign(t0, getAcc(ac)); 4684 4685 assign(t1, binop(Iop_Sar64, 4686 mkexpr(t0), 4687 unop(Iop_32to8, 4688 binop(Iop_And32, 4689 getIReg(rs), 4690 mkU32(0x1f))))); 4691 4692 assign(t2, binop(Iop_Or32, 4693 getDSPControl(), mkU32(0x00800000))); 4694 4695 assign(t9, binop(Iop_And32, 4696 unop(Iop_64to32, 4697 mkexpr(t1)), 4698 mkU32(0x80000000))); 4699 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4700 mkexpr(t9), 4701 binop(Iop_And32, 4702 unop(Iop_64HIto32, 4703 mkexpr(t0)), 4704 mkU32(0x80000000))), 4705 mkexpr(t2), 4706 getDSPControl())); 4707 4708 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4709 1. subtract 0x7fff from t1 4710 2. if the resulting number is positive (sign bit = 0) 4711 and any of the other bits is 1, the value is > 0. */ 4712 assign(t3, binop(Iop_Sub64, 4713 mkexpr(t1), 4714 mkU64(0x0000000000007fffULL))); 4715 assign(t4, binop(Iop_And32, 4716 binop(Iop_Or32, 4717 unop(Iop_1Sto32, 4718 binop(Iop_CmpNE32, 4719 mkU32(0), 4720 binop(Iop_And32, 4721 unop(Iop_64HIto32, 4722 mkexpr(t3)), 4723 mkU32(0x7fffffff)))), 4724 unop(Iop_1Sto32, 4725 binop(Iop_CmpNE32, 4726 mkU32(0), 4727 unop(Iop_64to32, 4728 mkexpr(t3))))), 4729 unop(Iop_1Sto32, 4730 binop(Iop_CmpEQ32, 4731 binop(Iop_And32, 4732 unop(Iop_64HIto32, 4733 mkexpr(t3)), 4734 mkU32(0x80000000)), 4735 mkU32(0))))); 4736 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4737 mkU32(0), 4738 mkexpr(t4)), 4739 binop(Iop_Or32, 4740 getDSPControl(), 4741 mkU32(0x00800000)), 4742 getDSPControl())); 4743 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4744 1. subtract t1 from 0xffffffffffff8000 4745 2. if the resulting number is positive (sign bit = 0) 4746 and any of the other bits is 1, the value is > 0 */ 4747 assign(t6, binop(Iop_Sub64, 4748 mkU64(0xffffffffffff8000ULL), 4749 mkexpr(t1))); 4750 assign(t7, binop(Iop_And32, 4751 binop(Iop_Or32, 4752 unop(Iop_1Sto32, 4753 binop(Iop_CmpNE32, 4754 mkU32(0), 4755 binop(Iop_And32, 4756 unop(Iop_64HIto32, 4757 mkexpr(t6)), 4758 mkU32(0x7fffffff)))), 4759 unop(Iop_1Sto32, 4760 binop(Iop_CmpNE32, 4761 mkU32(0), 4762 unop(Iop_64to32, 4763 mkexpr(t6))))), 4764 unop(Iop_1Sto32, 4765 binop(Iop_CmpEQ32, 4766 binop(Iop_And32, 4767 unop(Iop_64HIto32, 4768 mkexpr(t6)), 4769 mkU32(0x80000000)), 4770 mkU32(0))))); 4771 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4772 mkU32(0), 4773 mkexpr(t7)), 4774 binop(Iop_Or32, 4775 getDSPControl(), 4776 mkU32(0x00800000)), 4777 getDSPControl())); 4778 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4779 mkU32(0), 4780 mkexpr(t4)), 4781 mkU32(0x00007fff), 4782 IRExpr_ITE(binop(Iop_CmpNE32, 4783 mkU32(0), 4784 mkexpr(t7)), 4785 mkU32(0xffff8000), 4786 unop(Iop_64to32, 4787 mkexpr(t1))))); 4788 break; 4789 } 4790 case 0x12: { /* RDDSP*/ 4791 DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask); 4792 vassert(!mode64); 4793 4794 putIReg(rd, mkU32(0x0)); 4795 4796 if ((rddsp_mask & 0x1) == 0x1) { 4797 /* Read pos field (bits 5-0) of DSPControl register. */ 4798 putIReg(rd, binop(Iop_Or32, 4799 getIReg(rd), 4800 binop(Iop_And32, 4801 getDSPControl(), 4802 mkU32(0x0000003F)))); 4803 } 4804 4805 if ((rddsp_mask & 0x2) == 0x2) { 4806 /* Read scount field (bits 12-7) of DSPControl 4807 register. */ 4808 putIReg(rd, binop(Iop_Or32, 4809 getIReg(rd), 4810 binop(Iop_And32, 4811 getDSPControl(), 4812 mkU32(0x00001F80)))); 4813 } 4814 4815 if ((rddsp_mask & 0x4) == 0x4) { 4816 /* Read C field (bit 13) of DSPControl register. */ 4817 putIReg(rd, binop(Iop_Or32, 4818 getIReg(rd), 4819 binop(Iop_And32, 4820 getDSPControl(), 4821 mkU32(0x00002000)))); 4822 } 4823 4824 if ((rddsp_mask & 0x8) == 0x8) { 4825 /* Read outflag field (bit s 23-16) of DSPControl 4826 register. */ 4827 putIReg(rd, binop(Iop_Or32, 4828 getIReg(rd), 4829 binop(Iop_And32, 4830 getDSPControl(), 4831 mkU32(0x00FF0000)))); 4832 } 4833 4834 if ((rddsp_mask & 0x10) == 0x10) { 4835 /* Read ccond field (bits 31-24) of DSPControl 4836 register. */ 4837 putIReg(rd, binop(Iop_Or32, 4838 getIReg(rd), 4839 binop(Iop_And32, 4840 getDSPControl(), 4841 mkU32(0xFF000000)))); 4842 } 4843 4844 if ((rddsp_mask & 0x20) == 0x20) { 4845 /* Read EFI field (bit 14) of DSPControl register. */ 4846 putIReg(rd, binop(Iop_Or32, 4847 getIReg(rd), 4848 binop(Iop_And32, 4849 getDSPControl(), 4850 mkU32(0x00004000)))); 4851 } 4852 4853 if ((rddsp_mask & 0x3f) == 0x3f) { 4854 /* Read all fields of DSPControl register. */ 4855 putIReg(rd, getDSPControl()); 4856 } 4857 break; 4858 } 4859 case 0x13: { /* WRDSP */ 4860 DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask); 4861 vassert(!mode64); 4862 4863 if ((wrdsp_mask & 0x3f) == 0x3f) { 4864 /* If mips64 put all fields of rs, except bit 15 and bit 4865 6, to DSPControl register, otherwise put all except 4866 bits 15, 6 and bits 31..28. */ 4867 putDSPControl(mode64 ? 4868 binop(Iop_And32, 4869 getIReg(rs), 4870 mkU32(0xffff7fbf)) : 4871 binop(Iop_And32, 4872 getIReg(rs), 4873 mkU32(0x0fff7fbf))); 4874 } else { 4875 if ((wrdsp_mask & 0x1) == 0x1) { 4876 /* Put bits 5-0 of rs to DSPControl register pos 4877 field. */ 4878 putDSPControl(binop(Iop_Or32, 4879 binop(Iop_And32, 4880 getDSPControl(), 4881 mkU32(0xFFFF7F40)), 4882 binop(Iop_And32, 4883 getIReg(rs), 4884 mkU32(0x0000003F)))); 4885 } 4886 4887 if ((wrdsp_mask & 0x2) == 0x2) { 4888 /* Put bits 12-7 of rs to DSPControl scount field. */ 4889 putDSPControl(binop(Iop_Or32, 4890 binop(Iop_And32, 4891 getDSPControl(), 4892 mkU32(0xFFFFE03F)), 4893 binop(Iop_And32, 4894 getIReg(rs), 4895 mkU32(0x00001F80)))); 4896 } 4897 4898 if ((wrdsp_mask & 0x4) == 0x4) { 4899 /* Put bit 13 of rs to DSPControl register C 4900 field. */ 4901 putDSPControl(binop(Iop_Or32, 4902 binop(Iop_And32, 4903 getDSPControl(), 4904 mkU32(0xFFFF5FBF)), 4905 binop(Iop_And32, 4906 getIReg(rs), 4907 mkU32(0x00002000)))); 4908 } 4909 4910 if ((wrdsp_mask & 0x8) == 0x8) { 4911 /* Put bits 23-16 of rs to DSPControl reg outflag 4912 field. */ 4913 putDSPControl(binop(Iop_Or32, 4914 binop(Iop_And32, 4915 getDSPControl(), 4916 mkU32(0xFF007FBF)), 4917 binop(Iop_And32, 4918 getIReg(rs), 4919 mkU32(0x00FF0000)))); 4920 } 4921 4922 if ((wrdsp_mask & 0x10) == 0x10) { 4923 /* Put bits 31-24 of rs to DSPControl reg ccond 4924 field. */ 4925 putDSPControl(binop(Iop_Or32, 4926 binop(Iop_And32, 4927 getDSPControl(), 4928 mkU32(0x00FF7FBF)), 4929 binop(Iop_And32, 4930 getIReg(rs), 4931 mode64 ? mkU32(0xFF000000) 4932 : mkU32(0x0F000000)) 4933 ) 4934 ); 4935 } 4936 4937 if ((wrdsp_mask & 0x20) == 0x20) { 4938 /* Put bit 14 of rs to DSPControl register EFI 4939 field. */ 4940 putDSPControl(binop(Iop_Or32, 4941 binop(Iop_And32, 4942 getDSPControl(), 4943 mkU32(0xFFFF3FBF)), 4944 binop(Iop_And32, 4945 getIReg(rs), 4946 mkU32(0x00004000)))); 4947 } 4948 } 4949 break; 4950 } 4951 case 0x1A: { /* SHILO */ 4952 DIP("shilo ac%u, %u", ac, shift); 4953 vassert(!mode64); 4954 t0 = newTemp(Ity_I64); 4955 t1 = newTemp(Ity_I64); 4956 4957 assign(t0, getAcc(ac)); 4958 4959 putAcc(ac, mkexpr(t0)); 4960 4961 if (0x20 == (shift & 0x3f)) { 4962 putAcc(ac, binop(Iop_32HLto64, 4963 unop(Iop_64to32, mkexpr(t0)), 4964 mkU32(0x0))); 4965 } else if (0x20 == (shift & 0x20)) { 4966 assign(t1, binop(Iop_Shl64, 4967 mkexpr(t0), 4968 unop(Iop_32to8, 4969 binop(Iop_Add32, 4970 unop(Iop_Not32, 4971 mkU32(shift)), 4972 mkU32(0x1))))); 4973 4974 putAcc(ac, mkexpr(t1)); 4975 } else { 4976 assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift))); 4977 4978 putAcc(ac, mkexpr(t1)); 4979 } 4980 break; 4981 } 4982 case 0x1B: { /* SHILOV */ 4983 DIP("shilov ac%u, r%u", ac, rs); 4984 vassert(!mode64); 4985 t0 = newTemp(Ity_I64); 4986 t1 = newTemp(Ity_I32); 4987 t2 = newTemp(Ity_I1); 4988 t3 = newTemp(Ity_I64); 4989 t4 = newTemp(Ity_I64); 4990 4991 assign(t0, getAcc(ac)); 4992 assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f))); 4993 assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20))); 4994 assign(t3, binop(Iop_Shl64, 4995 mkexpr(t0), 4996 unop(Iop_32to8, 4997 binop(Iop_Add32, 4998 unop(Iop_Not32, 4999 mkexpr(t1)), 5000 mkU32(0x1))))); 5001 assign(t4, binop(Iop_Shr64, 5002 mkexpr(t0), 5003 unop(Iop_32to8, 5004 mkexpr(t1)))); 5005 5006 putAcc(ac, 5007 IRExpr_ITE(mkexpr(t2), 5008 binop(Iop_32HLto64, 5009 unop(Iop_64to32, mkexpr(t0)), 5010 mkU32(0x0)), 5011 IRExpr_ITE(binop(Iop_CmpEQ32, 5012 binop(Iop_And32, 5013 mkexpr(t1), 5014 mkU32(0x20)), 5015 mkU32(0x20)), 5016 mkexpr(t3), 5017 mkexpr(t4)))); 5018 break; 5019 } 5020 case 0x1F: { /* MTHLIP */ 5021 DIP("mthlip r%u, ac%u", rs, ac); 5022 vassert(!mode64); 5023 t0 = newTemp(Ity_I64); 5024 t1 = newTemp(Ity_I32); 5025 t2 = newTemp(Ity_I32); 5026 t3 = newTemp(Ity_I1); 5027 5028 assign(t0, getAcc(ac)); 5029 putAcc(ac, binop(Iop_32HLto64, 5030 unop(Iop_64to32, mkexpr(t0)), 5031 getIReg(rs))); 5032 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5033 putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U, 5034 mkU32(32), 5035 mkexpr(t1)), 5036 binop(Iop_Or32, 5037 binop(Iop_Sub32, 5038 mkexpr(t1), 5039 mkU32(32)), 5040 binop(Iop_And32, 5041 getDSPControl(), 5042 mkU32(0xffffffc0))), 5043 binop(Iop_Or32, 5044 binop(Iop_Add32, 5045 mkexpr(t1), 5046 mkU32(32)), 5047 binop(Iop_And32, 5048 getDSPControl(), 5049 mkU32(0xffffffc0))))); 5050 break; 5051 } 5052 default: 5053 return -1; 5054 } 5055 break; /* end of EXTR.W */ 5056 } 5057 case 0xA: { /* LX */ 5058 switch(sa) { 5059 case 0x0: { /* LWX */ 5060 DIP("lwx r%u, r%u(r%u)", 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, load(Ity_I32, mkexpr(t0))); 5067 break; 5068 } 5069 case 0x4: { /* LHX */ 5070 DIP("lhx r%u, r%u(r%u)", 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_16Sto32, load(Ity_I16, mkexpr(t0)))); 5077 break; 5078 } 5079 case 0x6: { /* LBUX */ 5080 DIP("lbux r%u, r%u(r%u)", rd, rt, rs); 5081 vassert(!mode64); 5082 t0 = newTemp(Ity_I32); 5083 5084 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5085 5086 putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0)))); 5087 break; 5088 } 5089 default: 5090 return -1; 5091 } 5092 break; /* end of LX */ 5093 } 5094 case 0xC: { /* INSV */ 5095 switch(sa) { 5096 case 0x0: { /* INSV */ 5097 DIP("insv r%u, r%u", rt, rs); 5098 vassert(!mode64); 5099 5100 t0 = newTemp(Ity_I32); 5101 t1 = newTemp(Ity_I32); 5102 t2 = newTemp(Ity_I8); 5103 t3 = newTemp(Ity_I8); 5104 t4 = newTemp(Ity_I32); 5105 t5 = newTemp(Ity_I1); 5106 t6 = newTemp(Ity_I32); 5107 t7 = newTemp(Ity_I32); 5108 t8 = newTemp(Ity_I32); 5109 t9 = newTemp(Ity_I32); 5110 5111 /* t0 <- pos field of DSPControl register. */ 5112 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5113 /* t1 <- scount field of DSPControl register. */ 5114 assign(t1, binop(Iop_Shr32, 5115 binop(Iop_And32, 5116 getDSPControl(), 5117 mkU32(0x1f80)), 5118 mkU8(7))); 5119 5120 assign(t2, unop(Iop_32to8, 5121 binop(Iop_Add32, 5122 mkexpr(t1), 5123 mkexpr(t0)))); 5124 5125 /* 32-(pos+size) most significant bits of rt. */ 5126 assign(t6, binop(Iop_Shl32, 5127 binop(Iop_Shr32, 5128 getIReg(rt), 5129 mkexpr(t2)), 5130 mkexpr(t2))); 5131 5132 assign(t3, unop(Iop_32to8, 5133 binop(Iop_Sub32, 5134 mkU32(32), 5135 mkexpr(t0)))); 5136 /* Pos least significant bits of rt. */ 5137 assign(t7, binop(Iop_Shr32, 5138 binop(Iop_Shl32, 5139 getIReg(rt), 5140 mkexpr(t3)), 5141 mkexpr(t3))); 5142 5143 /* Size least significant bits of rs, 5144 shifted to appropriate position. */ 5145 assign(t8, binop(Iop_Shl32, 5146 binop(Iop_And32, 5147 getIReg(rs), 5148 unop(Iop_Not32, 5149 binop(Iop_Shl32, 5150 mkU32(0xffffffff), 5151 unop(Iop_32to8, 5152 mkexpr(t1))))), 5153 unop(Iop_32to8, 5154 mkexpr(t0)))); 5155 5156 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 5157 mkexpr(t0), 5158 mkU32(0)), 5159 IRExpr_ITE(binop(Iop_CmpEQ32, 5160 mkexpr(t1), 5161 mkU32(32)), 5162 getIReg(rs), 5163 binop(Iop_Or32, 5164 mkexpr(t6), 5165 mkexpr(t8))), 5166 IRExpr_ITE(binop(Iop_CmpEQ32, 5167 unop(Iop_8Uto32, 5168 mkexpr(t2)), 5169 mkU32(32)), 5170 binop(Iop_Or32, 5171 mkexpr(t7), 5172 mkexpr(t8)), 5173 binop(Iop_Or32, 5174 binop(Iop_Or32, 5175 mkexpr(t6), 5176 mkexpr(t7)), 5177 mkexpr(t8))))); 5178 break; 5179 } 5180 default: 5181 return -1; 5182 } 5183 break; /* enf of INSV */ 5184 } 5185 case 0x10: { /* ADDU.QB */ 5186 switch(sa) { 5187 case 0x00: { /* ADDU.QB */ 5188 DIP("addu.qb r%u, r%u, r%u", rd, rs, rt); 5189 vassert(!mode64); 5190 t0 = newTemp(Ity_I32); 5191 t1 = newTemp(Ity_I1); 5192 t2 = newTemp(Ity_I32); 5193 t3 = newTemp(Ity_I1); 5194 t4 = newTemp(Ity_I32); 5195 t5 = newTemp(Ity_I1); 5196 t6 = newTemp(Ity_I32); 5197 t7 = newTemp(Ity_I1); 5198 t8 = newTemp(Ity_I32); 5199 5200 /* Add rightmost bytes of rs and rt. */ 5201 assign(t0, 5202 binop(Iop_Add32, 5203 unop(Iop_8Uto32, 5204 unop(Iop_16to8, 5205 unop(Iop_32to16, getIReg(rs)))), 5206 unop(Iop_8Uto32, 5207 unop(Iop_16to8, 5208 unop(Iop_32to16, getIReg(rt)))))); 5209 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5210 assign(t1, binop(Iop_CmpEQ32, 5211 binop(Iop_And32, 5212 mkexpr(t0), 5213 mkU32(0x00000100)), 5214 mkU32(0x00000100))); 5215 5216 /* Add bits 15-8 of rs and rt. */ 5217 assign(t2, 5218 binop(Iop_Add32, 5219 unop(Iop_8Uto32, 5220 unop(Iop_16HIto8, 5221 unop(Iop_32to16, getIReg(rs)))), 5222 unop(Iop_8Uto32, 5223 unop(Iop_16HIto8, 5224 unop(Iop_32to16, getIReg(rt)))))); 5225 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5226 assign(t3, binop(Iop_CmpEQ32, 5227 binop(Iop_And32, 5228 mkexpr(t2), 5229 mkU32(0x00000100)), 5230 mkU32(0x00000100))); 5231 5232 /* Add bits 15-8 of rs and rt. */ 5233 assign(t4, 5234 binop(Iop_Add32, 5235 unop(Iop_8Uto32, 5236 unop(Iop_16to8, 5237 unop(Iop_32HIto16, getIReg(rs)))), 5238 unop(Iop_8Uto32, 5239 unop(Iop_16to8, 5240 unop(Iop_32HIto16, getIReg(rt)))))); 5241 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5242 assign(t5, binop(Iop_CmpEQ32, 5243 binop(Iop_And32, 5244 mkexpr(t4), 5245 mkU32(0x00000100)), 5246 mkU32(0x00000100))); 5247 5248 /* Add bits 15-8 of rs and rt. */ 5249 assign(t6, 5250 binop(Iop_Add32, 5251 unop(Iop_8Uto32, 5252 unop(Iop_16HIto8, 5253 unop(Iop_32HIto16, getIReg(rs)))), 5254 unop(Iop_8Uto32, 5255 unop(Iop_16HIto8, 5256 unop(Iop_32HIto16, getIReg(rt)))))); 5257 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5258 assign(t7, binop(Iop_CmpEQ32, 5259 binop(Iop_And32, 5260 mkexpr(t6), 5261 mkU32(0x00000100)), 5262 mkU32(0x00000100))); 5263 5264 assign(t8, 5265 binop(Iop_Or32, 5266 binop(Iop_Or32, 5267 binop(Iop_Or32, 5268 unop(Iop_1Sto32, mkexpr(t7)), 5269 unop(Iop_1Sto32, mkexpr(t5))), 5270 unop(Iop_1Sto32, mkexpr(t3))), 5271 unop(Iop_1Sto32, mkexpr(t1)))); 5272 5273 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5274 mkexpr(t8), 5275 mkU32(0x0)), 5276 getDSPControl(), 5277 binop(Iop_Or32, 5278 getDSPControl(), 5279 mkU32(0x00100000)))); 5280 5281 putIReg(rd, binop(Iop_16HLto32, 5282 binop(Iop_8HLto16, 5283 unop(Iop_32to8, mkexpr(t6)), 5284 unop(Iop_32to8, mkexpr(t4))), 5285 binop(Iop_8HLto16, 5286 unop(Iop_32to8, mkexpr(t2)), 5287 unop(Iop_32to8, mkexpr(t0))))); 5288 break; 5289 } 5290 case 0x1: { /* SUBU.QB */ 5291 DIP("subu.qb r%u, r%u, r%u", rd, rs, rt); 5292 vassert(!mode64); 5293 t0 = newTemp(Ity_I32); 5294 t1 = newTemp(Ity_I1); 5295 t2 = newTemp(Ity_I32); 5296 t3 = newTemp(Ity_I1); 5297 t4 = newTemp(Ity_I32); 5298 t5 = newTemp(Ity_I1); 5299 t6 = newTemp(Ity_I32); 5300 t7 = newTemp(Ity_I1); 5301 t8 = newTemp(Ity_I32); 5302 5303 /* Subtract rightmost bytes of rs and rt. */ 5304 assign(t0, 5305 binop(Iop_Sub32, 5306 unop(Iop_8Uto32, 5307 unop(Iop_16to8, 5308 unop(Iop_32to16, getIReg(rs)))), 5309 unop(Iop_8Uto32, 5310 unop(Iop_16to8, 5311 unop(Iop_32to16, getIReg(rt)))))); 5312 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5313 assign(t1, binop(Iop_CmpEQ32, 5314 binop(Iop_And32, 5315 mkexpr(t0), 5316 mkU32(0x00000100)), 5317 mkU32(0x00000100))); 5318 5319 /* Subtract bits 15-8 of rs and rt. */ 5320 assign(t2, 5321 binop(Iop_Sub32, 5322 unop(Iop_8Uto32, 5323 unop(Iop_16HIto8, 5324 unop(Iop_32to16, getIReg(rs)))), 5325 unop(Iop_8Uto32, 5326 unop(Iop_16HIto8, 5327 unop(Iop_32to16, getIReg(rt)))))); 5328 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5329 assign(t3, binop(Iop_CmpEQ32, 5330 binop(Iop_And32, 5331 mkexpr(t2), 5332 mkU32(0x00000100)), 5333 mkU32(0x00000100))); 5334 5335 /* Subtract bits 15-8 of rs and rt. */ 5336 assign(t4, 5337 binop(Iop_Sub32, 5338 unop(Iop_8Uto32, 5339 unop(Iop_16to8, 5340 unop(Iop_32HIto16, getIReg(rs)))), 5341 unop(Iop_8Uto32, 5342 unop(Iop_16to8, 5343 unop(Iop_32HIto16, getIReg(rt)))))); 5344 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5345 assign(t5, binop(Iop_CmpEQ32, 5346 binop(Iop_And32, 5347 mkexpr(t4), 5348 mkU32(0x00000100)), 5349 mkU32(0x00000100))); 5350 5351 /* Subtract bits 15-8 of rs and rt. */ 5352 assign(t6, 5353 binop(Iop_Sub32, 5354 unop(Iop_8Uto32, 5355 unop(Iop_16HIto8, 5356 unop(Iop_32HIto16, getIReg(rs)))), 5357 unop(Iop_8Uto32, 5358 unop(Iop_16HIto8, 5359 unop(Iop_32HIto16, getIReg(rt)))))); 5360 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5361 assign(t7, binop(Iop_CmpEQ32, 5362 binop(Iop_And32, 5363 mkexpr(t6), 5364 mkU32(0x00000100)), 5365 mkU32(0x00000100))); 5366 5367 assign(t8, binop(Iop_Or32, 5368 binop(Iop_Or32, 5369 binop(Iop_Or32, 5370 unop(Iop_1Sto32, mkexpr(t7)), 5371 unop(Iop_1Sto32, mkexpr(t5))), 5372 unop(Iop_1Sto32, mkexpr(t3))), 5373 unop(Iop_1Sto32, mkexpr(t1)))); 5374 5375 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5376 mkexpr(t8), 5377 mkU32(0x0)), 5378 getDSPControl(), 5379 binop(Iop_Or32, 5380 getDSPControl(), 5381 mkU32(0x00100000)))); 5382 5383 putIReg(rd, binop(Iop_16HLto32, 5384 binop(Iop_8HLto16, 5385 unop(Iop_32to8, mkexpr(t6)), 5386 unop(Iop_32to8, mkexpr(t4))), 5387 binop(Iop_8HLto16, 5388 unop(Iop_32to8, mkexpr(t2)), 5389 unop(Iop_32to8, mkexpr(t0))))); 5390 break; 5391 } 5392 case 0x04: { /* ADDU_S.QB */ 5393 DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt); 5394 vassert(!mode64); 5395 t0 = newTemp(Ity_I32); 5396 t1 = newTemp(Ity_I1); 5397 t2 = newTemp(Ity_I8); 5398 t3 = newTemp(Ity_I32); 5399 t4 = newTemp(Ity_I1); 5400 t5 = newTemp(Ity_I8); 5401 t6 = newTemp(Ity_I32); 5402 t7 = newTemp(Ity_I1); 5403 t8 = newTemp(Ity_I8); 5404 t9 = newTemp(Ity_I32); 5405 t10 = newTemp(Ity_I1); 5406 t11 = newTemp(Ity_I8); 5407 t12 = newTemp(Ity_I32); 5408 5409 /* Add rightmost bytes of rs and rt. */ 5410 assign(t0, 5411 binop(Iop_Add32, 5412 unop(Iop_8Uto32, 5413 unop(Iop_16to8, 5414 unop(Iop_32to16, getIReg(rs)))), 5415 unop(Iop_8Uto32, 5416 unop(Iop_16to8, 5417 unop(Iop_32to16, getIReg(rt)))))); 5418 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5419 assign(t1, binop(Iop_CmpEQ32, 5420 binop(Iop_And32, 5421 mkexpr(t0), 5422 mkU32(0x00000100)), 5423 mkU32(0x00000100))); 5424 /* Saturate if necessary. */ 5425 assign(t2, IRExpr_ITE(mkexpr(t1), 5426 mkU8(0xff), 5427 unop(Iop_32to8, mkexpr(t0)))); 5428 5429 /* Add bits 15-8 of rs and rt. */ 5430 assign(t3, 5431 binop(Iop_Add32, 5432 unop(Iop_8Uto32, 5433 unop(Iop_16HIto8, 5434 unop(Iop_32to16, getIReg(rs)))), 5435 unop(Iop_8Uto32, 5436 unop(Iop_16HIto8, 5437 unop(Iop_32to16, getIReg(rt)))))); 5438 /* t4 will be 1 if there is overflow, 0 otherwise. */ 5439 assign(t4, binop(Iop_CmpEQ32, 5440 binop(Iop_And32, 5441 mkexpr(t3), 5442 mkU32(0x00000100)), 5443 mkU32(0x00000100))); 5444 /* Saturate if necessary. */ 5445 assign(t5, IRExpr_ITE(mkexpr(t4), 5446 mkU8(0xff), 5447 unop(Iop_32to8, mkexpr(t3)))); 5448 5449 /* Add bits 15-8 of rs and rt. */ 5450 assign(t6, 5451 binop(Iop_Add32, 5452 unop(Iop_8Uto32, 5453 unop(Iop_16to8, 5454 unop(Iop_32HIto16, getIReg(rs)))), 5455 unop(Iop_8Uto32, 5456 unop(Iop_16to8, 5457 unop(Iop_32HIto16, getIReg(rt)))))); 5458 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5459 assign(t7, binop(Iop_CmpEQ32, 5460 binop(Iop_And32, 5461 mkexpr(t6), 5462 mkU32(0x00000100)), 5463 mkU32(0x00000100))); 5464 /* Saturate if necessary. */ 5465 assign(t8, IRExpr_ITE(mkexpr(t7), 5466 mkU8(0xff), 5467 unop(Iop_32to8, mkexpr(t6)))); 5468 5469 /* Add bits 15-8 of rs and rt. */ 5470 assign(t9, 5471 binop(Iop_Add32, 5472 unop(Iop_8Uto32, 5473 unop(Iop_16HIto8, 5474 unop(Iop_32HIto16, getIReg(rs)))), 5475 unop(Iop_8Uto32, 5476 unop(Iop_16HIto8, 5477 unop(Iop_32HIto16, getIReg(rt)))))); 5478 /* t10 will be 1 if there is overflow, 0 otherwise. */ 5479 assign(t10, binop(Iop_CmpEQ32, 5480 binop(Iop_And32, 5481 mkexpr(t9), 5482 mkU32(0x00000100)), 5483 mkU32(0x00000100))); 5484 /* Saturate if necessary. */ 5485 assign(t11, IRExpr_ITE(mkexpr(t10), 5486 mkU8(0xff), 5487 unop(Iop_32to8, mkexpr(t9)))); 5488 5489 assign(t12, 5490 binop(Iop_Or32, 5491 binop(Iop_Or32, 5492 binop(Iop_Or32, 5493 unop(Iop_1Sto32, mkexpr(t10)), 5494 unop(Iop_1Sto32, mkexpr(t7))), 5495 unop(Iop_1Sto32, mkexpr(t4))), 5496 unop(Iop_1Sto32, mkexpr(t1)))); 5497 5498 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5499 mkexpr(t12), 5500 mkU32(0x0)), 5501 getDSPControl(), 5502 binop(Iop_Or32, 5503 getDSPControl(), 5504 mkU32(0x00100000)))); 5505 5506 putIReg(rd, 5507 binop(Iop_16HLto32, 5508 binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)), 5509 binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2)))); 5510 break; 5511 } 5512 case 0x05: { /* SUBU_S.QB */ 5513 DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt); 5514 vassert(!mode64); 5515 t1 = newTemp(Ity_I32); 5516 t2 = newTemp(Ity_I1); 5517 t3 = newTemp(Ity_I1); 5518 t4 = newTemp(Ity_I1); 5519 t5 = newTemp(Ity_I1); 5520 t6 = newTemp(Ity_I32); 5521 t7 = newTemp(Ity_I32); 5522 t8 = newTemp(Ity_I32); 5523 t9 = newTemp(Ity_I32); 5524 5525 /* Use C function to easily calculate the result 5526 and write it in the register more conveniently 5527 Underflow is checked using step by step subtraction. */ 5528 assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt))); 5529 5530 /* Subtract each byte of rs and rt. */ 5531 assign(t6, 5532 binop(Iop_Sub32, 5533 unop(Iop_8Uto32, 5534 unop(Iop_16to8, 5535 unop(Iop_32to16, getIReg(rs)))), 5536 unop(Iop_8Uto32, 5537 unop(Iop_16to8, 5538 unop(Iop_32to16, getIReg(rt)))))); 5539 assign(t7, 5540 binop(Iop_Sub32, 5541 unop(Iop_8Uto32, 5542 unop(Iop_16HIto8, 5543 unop(Iop_32to16, getIReg(rs)))), 5544 unop(Iop_8Uto32, 5545 unop(Iop_16HIto8, 5546 unop(Iop_32to16, getIReg(rt)))))); 5547 assign(t8, 5548 binop(Iop_Sub32, 5549 unop(Iop_8Uto32, 5550 unop(Iop_16to8, 5551 unop(Iop_32HIto16, getIReg(rs)))), 5552 unop(Iop_8Uto32, 5553 unop(Iop_16to8, 5554 unop(Iop_32HIto16, getIReg(rt)))))); 5555 assign(t9, 5556 binop(Iop_Sub32, 5557 unop(Iop_8Uto32, 5558 unop(Iop_16HIto8, 5559 unop(Iop_32HIto16, getIReg(rs)))), 5560 unop(Iop_8Uto32, 5561 unop(Iop_16HIto8, 5562 unop(Iop_32HIto16, getIReg(rt)))))); 5563 5564 /* Put 1 to bit 20 in DSPControl if there is underflow 5565 in either byte. */ 5566 assign(t2, binop(Iop_CmpEQ32, 5567 binop(Iop_And32, 5568 mkexpr(t6), 5569 mkU32(0x00000100)), 5570 mkU32(0x00000100))); 5571 putDSPControl(IRExpr_ITE(mkexpr(t2), 5572 binop(Iop_Or32, 5573 getDSPControl(), 5574 mkU32(0x00100000)), 5575 getDSPControl())); 5576 assign(t3, binop(Iop_CmpEQ32, 5577 binop(Iop_And32, 5578 mkexpr(t7), 5579 mkU32(0x00000100)), 5580 mkU32(0x00000100))); 5581 putDSPControl(IRExpr_ITE(mkexpr(t3), 5582 binop(Iop_Or32, 5583 getDSPControl(), 5584 mkU32(0x00100000)), 5585 getDSPControl())); 5586 assign(t4, binop(Iop_CmpEQ32, 5587 binop(Iop_And32, 5588 mkexpr(t8), 5589 mkU32(0x00000100)), 5590 mkU32(0x00000100))); 5591 putDSPControl(IRExpr_ITE(mkexpr(t4), 5592 binop(Iop_Or32, 5593 getDSPControl(), 5594 mkU32(0x00100000)), 5595 getDSPControl())); 5596 assign(t5, binop(Iop_CmpEQ32, 5597 binop(Iop_And32, 5598 mkexpr(t9), 5599 mkU32(0x00000100)), 5600 mkU32(0x00000100))); 5601 putDSPControl(IRExpr_ITE(mkexpr(t5), 5602 binop(Iop_Or32, 5603 getDSPControl(), 5604 mkU32(0x00100000)), 5605 getDSPControl())); 5606 putIReg(rd, mkexpr(t1)); 5607 break; 5608 } 5609 case 0x6: { /* MULEU_S.PH.QBL */ 5610 DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt); 5611 vassert(!mode64); 5612 t0 = newTemp(Ity_I32); 5613 t1 = newTemp(Ity_I32); 5614 t2 = newTemp(Ity_I1); 5615 t3 = newTemp(Ity_I1); 5616 5617 assign(t0, 5618 unop(Iop_64to32, 5619 binop(Iop_MullU32, 5620 unop(Iop_8Uto32, 5621 unop(Iop_16HIto8, 5622 unop(Iop_32HIto16, 5623 getIReg(rs)))), 5624 unop(Iop_16Uto32, 5625 unop(Iop_32HIto16, getIReg(rt)))))); 5626 assign(t1, 5627 unop(Iop_64to32, 5628 binop(Iop_MullU32, 5629 unop(Iop_8Uto32, 5630 unop(Iop_16to8, 5631 unop(Iop_32HIto16, 5632 getIReg(rs)))), 5633 unop(Iop_16Uto32, 5634 unop(Iop_32to16, getIReg(rt)))))); 5635 5636 assign(t2, binop(Iop_CmpNE32, 5637 mkU32(0x0), 5638 binop(Iop_And32, 5639 mkexpr(t0), 5640 mkU32(0x03ff0000)))); 5641 assign(t3, binop(Iop_CmpNE32, 5642 mkU32(0x0), 5643 binop(Iop_And32, 5644 mkexpr(t1), 5645 mkU32(0x03ff0000)))); 5646 putDSPControl(IRExpr_ITE(mkexpr(t2), 5647 binop(Iop_Or32, 5648 getDSPControl(), 5649 mkU32(0x200000)), 5650 IRExpr_ITE(mkexpr(t3), 5651 binop(Iop_Or32, 5652 getDSPControl(), 5653 mkU32(0x200000)), 5654 getDSPControl()))); 5655 putIReg(rd, 5656 binop(Iop_16HLto32, 5657 IRExpr_ITE(mkexpr(t2), 5658 mkU16(0xffff), 5659 unop(Iop_32to16, mkexpr(t0))), 5660 IRExpr_ITE(mkexpr(t3), 5661 mkU16(0xffff), 5662 unop(Iop_32to16, mkexpr(t1))))); 5663 break; 5664 } 5665 case 0x7: { /* MULEU_S.PH.QBR */ 5666 DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt); 5667 vassert(!mode64); 5668 t0 = newTemp(Ity_I32); 5669 t1 = newTemp(Ity_I32); 5670 t2 = newTemp(Ity_I1); 5671 t3 = newTemp(Ity_I1); 5672 5673 assign(t0, unop(Iop_64to32, 5674 binop(Iop_MullU32, 5675 unop(Iop_8Uto32, 5676 unop(Iop_16HIto8, 5677 unop(Iop_32to16, 5678 getIReg(rs)))), 5679 unop(Iop_16Uto32, 5680 unop(Iop_32HIto16, 5681 getIReg(rt)))))); 5682 assign(t1, unop(Iop_64to32, 5683 binop(Iop_MullU32, 5684 unop(Iop_8Uto32, 5685 unop(Iop_16to8, 5686 unop(Iop_32to16, 5687 getIReg(rs)))), 5688 unop(Iop_16Uto32, 5689 unop(Iop_32to16, 5690 getIReg(rt)))))); 5691 5692 assign(t2, binop(Iop_CmpNE32, 5693 mkU32(0x0), 5694 binop(Iop_And32, 5695 mkexpr(t0), 5696 mkU32(0x03ff0000)))); 5697 assign(t3, binop(Iop_CmpNE32, 5698 mkU32(0x0), 5699 binop(Iop_And32, 5700 mkexpr(t1), 5701 mkU32(0x03ff0000)))); 5702 putDSPControl(IRExpr_ITE(mkexpr(t2), 5703 binop(Iop_Or32, 5704 getDSPControl(), 5705 mkU32(0x200000)), 5706 IRExpr_ITE(mkexpr(t3), 5707 binop(Iop_Or32, 5708 getDSPControl(), 5709 mkU32(0x200000)), 5710 getDSPControl()))); 5711 putIReg(rd, binop(Iop_16HLto32, 5712 IRExpr_ITE(mkexpr(t2), 5713 mkU16(0xffff), 5714 unop(Iop_32to16, 5715 mkexpr(t0))), 5716 IRExpr_ITE(mkexpr(t3), 5717 mkU16(0xffff), 5718 unop(Iop_32to16, 5719 mkexpr(t1))))); 5720 break; 5721 } 5722 case 0x08: { /* ADDU.PH */ 5723 DIP("addu.ph r%u, r%u, r%u", rd, rs, rt); 5724 vassert(!mode64); 5725 t0 = newTemp(Ity_I32); 5726 t1 = newTemp(Ity_I1); 5727 t2 = newTemp(Ity_I32); 5728 t3 = newTemp(Ity_I1); 5729 5730 /* Add lower halves. */ 5731 assign(t0, binop(Iop_Add32, 5732 unop(Iop_16Uto32, 5733 unop(Iop_32to16, getIReg(rs))), 5734 unop(Iop_16Uto32, 5735 unop(Iop_32to16, getIReg(rt))))); 5736 5737 /* Detect overflow. */ 5738 assign(t1, binop(Iop_CmpLT32U, 5739 unop(Iop_16Uto32, 5740 unop(Iop_32to16, mkexpr(t0))), 5741 unop(Iop_16Uto32, 5742 unop(Iop_32to16, getIReg(rs))))); 5743 5744 putDSPControl(IRExpr_ITE(mkexpr(t1), 5745 binop(Iop_Or32, 5746 getDSPControl(), 5747 mkU32(0x00100000)), 5748 getDSPControl())); 5749 5750 /* Add higher halves. */ 5751 assign(t2, binop(Iop_Add32, 5752 unop(Iop_16Uto32, 5753 unop(Iop_32HIto16, getIReg(rs))), 5754 unop(Iop_16Uto32, 5755 unop(Iop_32HIto16, getIReg(rt))))); 5756 5757 /* Detect overflow. */ 5758 assign(t3, binop(Iop_CmpLT32U, 5759 unop(Iop_16Uto32, 5760 unop(Iop_32to16, mkexpr(t2))), 5761 unop(Iop_16Uto32, 5762 unop(Iop_32HIto16, 5763 getIReg(rs))))); 5764 5765 putDSPControl(IRExpr_ITE(mkexpr(t3), 5766 binop(Iop_Or32, 5767 getDSPControl(), 5768 mkU32(0x00100000)), 5769 getDSPControl())); 5770 5771 putIReg(rd, binop(Iop_16HLto32, 5772 unop(Iop_32to16, mkexpr(t2)), 5773 unop(Iop_32to16, mkexpr(t0)))); 5774 break; 5775 } 5776 case 0x9: { /* SUBU.PH */ 5777 DIP("subu.ph r%u, r%u, r%u", rd, rs, rt); 5778 vassert(!mode64); 5779 t0 = newTemp(Ity_I32); 5780 t1 = newTemp(Ity_I1); 5781 t2 = newTemp(Ity_I32); 5782 t3 = newTemp(Ity_I1); 5783 5784 /* Substract lower halves. */ 5785 assign(t0, binop(Iop_Sub32, 5786 unop(Iop_16Uto32, 5787 unop(Iop_32to16, getIReg(rs))), 5788 unop(Iop_16Uto32, 5789 unop(Iop_32to16, getIReg(rt))))); 5790 5791 /* Detect underflow. */ 5792 assign(t1, binop(Iop_CmpNE32, 5793 binop(Iop_And32, 5794 mkexpr(t0), 5795 mkU32(0x00010000)), 5796 mkU32(0x0))); 5797 5798 putDSPControl(IRExpr_ITE(mkexpr(t1), 5799 binop(Iop_Or32, 5800 getDSPControl(), 5801 mkU32(0x00100000)), 5802 getDSPControl())); 5803 5804 /* Subtract higher halves. */ 5805 assign(t2, binop(Iop_Sub32, 5806 unop(Iop_16Uto32, 5807 unop(Iop_32HIto16, getIReg(rs))), 5808 unop(Iop_16Uto32, 5809 unop(Iop_32HIto16, getIReg(rt))))); 5810 5811 /* Detect underflow. */ 5812 assign(t3, binop(Iop_CmpNE32, 5813 binop(Iop_And32, 5814 mkexpr(t2), 5815 mkU32(0x00010000)), 5816 mkU32(0x0))); 5817 5818 putDSPControl(IRExpr_ITE(mkexpr(t3), 5819 binop(Iop_Or32, 5820 getDSPControl(), 5821 mkU32(0x00100000)), 5822 getDSPControl())); 5823 5824 putIReg(rd, binop(Iop_16HLto32, 5825 unop(Iop_32to16, mkexpr(t2)), 5826 unop(Iop_32to16, mkexpr(t0)))); 5827 break; 5828 } 5829 case 0xA: { /* ADDQ.PH */ 5830 DIP("addq.ph r%u, r%u, r%u", rd, rs, rt); 5831 vassert(!mode64); 5832 t0 = newTemp(Ity_I32); 5833 t1 = newTemp(Ity_I1); 5834 t2 = newTemp(Ity_I32); 5835 t3 = newTemp(Ity_I1); 5836 t6 = newTemp(Ity_I32); 5837 t7 = newTemp(Ity_I32); 5838 5839 /* Add lower halves. */ 5840 assign(t0, binop(Iop_Add32, 5841 unop(Iop_16Sto32, 5842 unop(Iop_32to16, getIReg(rs))), 5843 unop(Iop_16Sto32, 5844 unop(Iop_32to16, getIReg(rt))))); 5845 5846 /* Bit 16 of the result. */ 5847 assign(t6, binop(Iop_And32, 5848 unop(Iop_16Uto32, 5849 unop(Iop_32HIto16, mkexpr(t0))), 5850 mkU32(0x1))); 5851 /* Detect overflow. */ 5852 assign(t1, binop(Iop_CmpNE32, 5853 binop(Iop_Shr32, 5854 binop(Iop_And32, 5855 mkexpr(t0), 5856 mkU32(0x8000)), 5857 mkU8(15)), 5858 mkexpr(t6))); 5859 5860 putDSPControl(IRExpr_ITE(mkexpr(t1), 5861 binop(Iop_Or32, 5862 getDSPControl(), 5863 mkU32(0x00100000)), 5864 getDSPControl())); 5865 5866 /* Add higher halves. */ 5867 assign(t2, binop(Iop_Add32, 5868 unop(Iop_16Sto32, 5869 unop(Iop_32HIto16, getIReg(rs))), 5870 unop(Iop_16Sto32, 5871 unop(Iop_32HIto16, getIReg(rt))))); 5872 5873 /* Bit 16 of the result. */ 5874 assign(t7, binop(Iop_And32, 5875 unop(Iop_16Uto32, 5876 unop(Iop_32HIto16, mkexpr(t2))), 5877 mkU32(0x1))); 5878 /* Detect overflow. */ 5879 assign(t3, binop(Iop_CmpNE32, 5880 binop(Iop_Shr32, 5881 binop(Iop_And32, 5882 mkexpr(t2), 5883 mkU32(0x00008000)), 5884 mkU8(15)), 5885 mkexpr(t7))); 5886 5887 putDSPControl(IRExpr_ITE(mkexpr(t3), 5888 binop(Iop_Or32, 5889 getDSPControl(), 5890 mkU32(0x00100000)), 5891 getDSPControl())); 5892 5893 putIReg(rd, binop(Iop_16HLto32, 5894 unop(Iop_32to16, mkexpr(t2)), 5895 unop(Iop_32to16, mkexpr(t0)))); 5896 break; 5897 } 5898 case 0xB: { /* SUBQ.PH */ 5899 DIP("subq.ph r%u, r%u, r%u", rd, rs, rt); 5900 vassert(!mode64); 5901 t0 = newTemp(Ity_I32); 5902 t1 = newTemp(Ity_I1); 5903 t2 = newTemp(Ity_I32); 5904 t3 = newTemp(Ity_I1); 5905 t6 = newTemp(Ity_I32); 5906 t7 = newTemp(Ity_I32); 5907 5908 /* Subtract lower halves. */ 5909 assign(t0, binop(Iop_Sub32, 5910 unop(Iop_16Sto32, 5911 unop(Iop_32to16, getIReg(rs))), 5912 unop(Iop_16Sto32, 5913 unop(Iop_32to16, getIReg(rt))))); 5914 5915 /* Bit 16 of the result. */ 5916 assign(t6, binop(Iop_And32, 5917 unop(Iop_16Uto32, 5918 unop(Iop_32HIto16, mkexpr(t0))), 5919 mkU32(0x1))); 5920 /* Compare the signs of input value and the result. */ 5921 assign(t1, binop(Iop_CmpNE32, 5922 binop(Iop_Shr32, 5923 binop(Iop_And32, 5924 mkexpr(t0), 5925 mkU32(0x8000)), 5926 mkU8(15)), 5927 mkexpr(t6))); 5928 5929 putDSPControl(IRExpr_ITE(mkexpr(t1), 5930 binop(Iop_Or32, 5931 getDSPControl(), 5932 mkU32(0x00100000)), 5933 getDSPControl())); 5934 5935 /* Subtract higher halves. */ 5936 assign(t2, binop(Iop_Sub32, 5937 unop(Iop_16Sto32, 5938 unop(Iop_32HIto16, getIReg(rs))), 5939 unop(Iop_16Sto32, 5940 unop(Iop_32HIto16, getIReg(rt))))); 5941 5942 /* Bit 16 of the result. */ 5943 assign(t7, binop(Iop_And32, 5944 unop(Iop_16Uto32, 5945 unop(Iop_32HIto16, mkexpr(t2))), 5946 mkU32(0x1))); 5947 /* Compare the signs of input value and the result. */ 5948 assign(t3, binop(Iop_CmpNE32, 5949 binop(Iop_Shr32, 5950 binop(Iop_And32, 5951 mkexpr(t2), 5952 mkU32(0x00008000)), 5953 mkU8(15)), 5954 mkexpr(t7))); 5955 5956 putDSPControl(IRExpr_ITE(mkexpr(t3), 5957 binop(Iop_Or32, 5958 getDSPControl(), 5959 mkU32(0x00100000)), 5960 getDSPControl())); 5961 5962 putIReg(rd, binop(Iop_16HLto32, 5963 unop(Iop_32to16, mkexpr(t2)), 5964 unop(Iop_32to16, mkexpr(t0)))); 5965 break; 5966 } 5967 case 0xC: { /* ADDU_S.PH */ 5968 DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt); 5969 vassert(!mode64); 5970 t0 = newTemp(Ity_I32); 5971 t1 = newTemp(Ity_I1); 5972 t2 = newTemp(Ity_I32); 5973 t3 = newTemp(Ity_I1); 5974 5975 /* Add lower halves. */ 5976 assign(t0, binop(Iop_Add32, 5977 unop(Iop_16Uto32, 5978 unop(Iop_32to16, getIReg(rs))), 5979 unop(Iop_16Uto32, 5980 unop(Iop_32to16, getIReg(rt))))); 5981 5982 /* Detect overflow. */ 5983 assign(t1, binop(Iop_CmpLT32U, 5984 unop(Iop_16Uto32, 5985 unop(Iop_32to16, mkexpr(t0))), 5986 unop(Iop_16Uto32, 5987 unop(Iop_32to16, getIReg(rs))))); 5988 5989 putDSPControl(IRExpr_ITE(mkexpr(t1), 5990 binop(Iop_Or32, 5991 getDSPControl(), 5992 mkU32(0x00100000)), 5993 getDSPControl())); 5994 5995 /* Add higher halves. */ 5996 assign(t2, binop(Iop_Add32, 5997 unop(Iop_16Uto32, 5998 unop(Iop_32HIto16, getIReg(rs))), 5999 unop(Iop_16Uto32, 6000 unop(Iop_32HIto16, getIReg(rt))))); 6001 6002 /* Detect overflow. */ 6003 assign(t3, binop(Iop_CmpLT32U, 6004 unop(Iop_16Uto32, 6005 unop(Iop_32to16, mkexpr(t2))), 6006 unop(Iop_16Uto32, 6007 unop(Iop_32HIto16, getIReg(rs))))); 6008 6009 putDSPControl(IRExpr_ITE(mkexpr(t3), 6010 binop(Iop_Or32, 6011 getDSPControl(), 6012 mkU32(0x00100000)), 6013 getDSPControl())); 6014 6015 putIReg(rd, binop(Iop_16HLto32, 6016 IRExpr_ITE(mkexpr(t3), 6017 mkU16(0xffff), 6018 unop(Iop_32to16, 6019 mkexpr(t2))), 6020 IRExpr_ITE(mkexpr(t1), 6021 mkU16(0xffff), 6022 unop(Iop_32to16, 6023 mkexpr(t0))))); 6024 break; 6025 } 6026 case 0xD: { /* SUBU_S.PH */ 6027 DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt); 6028 vassert(!mode64); 6029 t0 = newTemp(Ity_I32); 6030 t1 = newTemp(Ity_I1); 6031 t2 = newTemp(Ity_I32); 6032 t3 = newTemp(Ity_I1); 6033 6034 /* Subtract lower halves. */ 6035 assign(t0, binop(Iop_Sub32, 6036 unop(Iop_16Uto32, 6037 unop(Iop_32to16, getIReg(rs))), 6038 unop(Iop_16Uto32, 6039 unop(Iop_32to16, getIReg(rt))))); 6040 6041 /* Detect underflow. */ 6042 assign(t1, binop(Iop_CmpNE32, 6043 binop(Iop_And32, 6044 mkexpr(t0), mkU32(0x00010000)), 6045 mkU32(0x0))); 6046 6047 putDSPControl(IRExpr_ITE(mkexpr(t1), 6048 binop(Iop_Or32, 6049 getDSPControl(), 6050 mkU32(0x00100000)), 6051 getDSPControl())); 6052 6053 /* Subtract higher halves. */ 6054 assign(t2, binop(Iop_Sub32, 6055 unop(Iop_16Uto32, 6056 unop(Iop_32HIto16, getIReg(rs))), 6057 unop(Iop_16Uto32, 6058 unop(Iop_32HIto16, getIReg(rt))))); 6059 6060 /* Detect underflow. */ 6061 assign(t3, binop(Iop_CmpNE32, 6062 binop(Iop_And32, 6063 mkexpr(t2), mkU32(0x00010000)), 6064 mkU32(0x0))); 6065 6066 putDSPControl(IRExpr_ITE(mkexpr(t3), 6067 binop(Iop_Or32, 6068 getDSPControl(), 6069 mkU32(0x00100000)), 6070 getDSPControl())); 6071 6072 putIReg(rd, 6073 binop(Iop_16HLto32, 6074 IRExpr_ITE(mkexpr(t3), 6075 mkU16(0x0000), 6076 unop(Iop_32to16, mkexpr(t2))), 6077 IRExpr_ITE(mkexpr(t1), 6078 mkU16(0x0000), 6079 unop(Iop_32to16, mkexpr(t0))))); 6080 break; 6081 } 6082 case 0xE: { /* ADDQ_S.PH */ 6083 DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt); 6084 vassert(!mode64); 6085 t0 = newTemp(Ity_I32); 6086 t1 = newTemp(Ity_I1); 6087 t2 = newTemp(Ity_I32); 6088 t3 = newTemp(Ity_I1); 6089 t4 = newTemp(Ity_I16); 6090 t5 = newTemp(Ity_I16); 6091 t6 = newTemp(Ity_I32); 6092 t7 = newTemp(Ity_I32); 6093 6094 /* Add lower halves. */ 6095 assign(t0, binop(Iop_Add32, 6096 unop(Iop_16Sto32, 6097 unop(Iop_32to16, getIReg(rs))), 6098 unop(Iop_16Sto32, 6099 unop(Iop_32to16, getIReg(rt))))); 6100 6101 /* Bit 16 of the result. */ 6102 assign(t6, binop(Iop_And32, 6103 unop(Iop_16Uto32, 6104 unop(Iop_32HIto16, mkexpr(t0))), 6105 mkU32(0x1))); 6106 /* Detect overflow. */ 6107 assign(t1, binop(Iop_CmpNE32, 6108 binop(Iop_Shr32, 6109 binop(Iop_And32, 6110 mkexpr(t0), 6111 mkU32(0x8000)), 6112 mkU8(15)), 6113 mkexpr(t6))); 6114 6115 putDSPControl(IRExpr_ITE(mkexpr(t1), 6116 binop(Iop_Or32, 6117 getDSPControl(), 6118 mkU32(0x00100000)), 6119 getDSPControl())); 6120 /* Saturate if needed. */ 6121 assign(t4, IRExpr_ITE(mkexpr(t1), 6122 IRExpr_ITE(binop(Iop_CmpEQ32, 6123 mkexpr(t6), 6124 mkU32(0x0)), 6125 mkU16(0x7fff), 6126 mkU16(0x8000)), 6127 unop(Iop_32to16, mkexpr(t0)))); 6128 6129 /* Add higher halves. */ 6130 assign(t2, binop(Iop_Add32, 6131 unop(Iop_16Sto32, 6132 unop(Iop_32HIto16, getIReg(rs))), 6133 unop(Iop_16Sto32, 6134 unop(Iop_32HIto16, getIReg(rt))))); 6135 6136 /* Bit 16 of the result. */ 6137 assign(t7, binop(Iop_And32, 6138 unop(Iop_16Uto32, 6139 unop(Iop_32HIto16, mkexpr(t2))), 6140 mkU32(0x1))); 6141 /* Detect overflow. */ 6142 assign(t3, binop(Iop_CmpNE32, 6143 binop(Iop_Shr32, 6144 binop(Iop_And32, 6145 mkexpr(t2), 6146 mkU32(0x00008000)), 6147 mkU8(15)), 6148 mkexpr(t7))); 6149 6150 putDSPControl(IRExpr_ITE(mkexpr(t3), 6151 binop(Iop_Or32, 6152 getDSPControl(), 6153 mkU32(0x00100000)), 6154 getDSPControl())); 6155 /* Saturate if needed. */ 6156 assign(t5, IRExpr_ITE(mkexpr(t3), 6157 IRExpr_ITE(binop(Iop_CmpEQ32, 6158 mkexpr(t7), 6159 mkU32(0x0)), 6160 mkU16(0x7fff), 6161 mkU16(0x8000)), 6162 unop(Iop_32to16, mkexpr(t2)))); 6163 6164 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6165 break; 6166 } 6167 case 0xF: { /* SUBQ_S.PH */ 6168 DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt); 6169 vassert(!mode64); 6170 t0 = newTemp(Ity_I32); 6171 t1 = newTemp(Ity_I1); 6172 t2 = newTemp(Ity_I32); 6173 t3 = newTemp(Ity_I1); 6174 t4 = newTemp(Ity_I16); 6175 t5 = newTemp(Ity_I16); 6176 t6 = newTemp(Ity_I32); 6177 t7 = newTemp(Ity_I32); 6178 6179 /* Subtract lower halves. */ 6180 assign(t0, binop(Iop_Sub32, 6181 unop(Iop_16Sto32, 6182 unop(Iop_32to16, getIReg(rs))), 6183 unop(Iop_16Sto32, 6184 unop(Iop_32to16, getIReg(rt))))); 6185 6186 /* Bit 16 of the result. */ 6187 assign(t6, binop(Iop_And32, 6188 unop(Iop_16Uto32, 6189 unop(Iop_32HIto16, mkexpr(t0))), 6190 mkU32(0x1))); 6191 /* Detect overflow or underflow. */ 6192 assign(t1, binop(Iop_CmpNE32, 6193 binop(Iop_Shr32, 6194 binop(Iop_And32, 6195 mkexpr(t0), 6196 mkU32(0x8000)), 6197 mkU8(15)), 6198 mkexpr(t6))); 6199 6200 putDSPControl(IRExpr_ITE(mkexpr(t1), 6201 binop(Iop_Or32, 6202 getDSPControl(), 6203 mkU32(0x00100000)), 6204 getDSPControl())); 6205 /* Saturate if needed. */ 6206 assign(t4, IRExpr_ITE(mkexpr(t1), 6207 IRExpr_ITE(binop(Iop_CmpEQ32, 6208 mkexpr(t6), 6209 mkU32(0x0)), 6210 mkU16(0x7fff), 6211 mkU16(0x8000)), 6212 unop(Iop_32to16, mkexpr(t0)))); 6213 6214 /* Subtract higher halves. */ 6215 assign(t2, binop(Iop_Sub32, 6216 unop(Iop_16Sto32, 6217 unop(Iop_32HIto16, getIReg(rs))), 6218 unop(Iop_16Sto32, 6219 unop(Iop_32HIto16, getIReg(rt))))); 6220 6221 /* Bit 16 of the result. */ 6222 assign(t7, binop(Iop_And32, 6223 unop(Iop_16Uto32, 6224 unop(Iop_32HIto16, mkexpr(t2))), 6225 mkU32(0x1))); 6226 /* Detect overflow or underflow. */ 6227 assign(t3, binop(Iop_CmpNE32, 6228 binop(Iop_Shr32, 6229 binop(Iop_And32, 6230 mkexpr(t2), 6231 mkU32(0x00008000)), 6232 mkU8(15)), 6233 mkexpr(t7))); 6234 6235 putDSPControl(IRExpr_ITE(mkexpr(t3), 6236 binop(Iop_Or32, 6237 getDSPControl(), 6238 mkU32(0x00100000)), 6239 getDSPControl())); 6240 /* Saturate if needed. */ 6241 assign(t5, IRExpr_ITE(mkexpr(t3), 6242 IRExpr_ITE(binop(Iop_CmpEQ32, 6243 mkexpr(t7), 6244 mkU32(0x0)), 6245 mkU16(0x7fff), 6246 mkU16(0x8000)), 6247 unop(Iop_32to16, mkexpr(t2)))); 6248 6249 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6250 break; 6251 } 6252 case 0x10: { /* ADDSC */ 6253 DIP("addsc r%u, r%u, r%u", rd, rs, rt); 6254 vassert(!mode64); 6255 t0 = newTemp(Ity_I64); 6256 t1 = newTemp(Ity_I1); 6257 6258 /* The carry bit result out of the addition operation is 6259 written to bit 13(the c field) of the DSPControl reg. */ 6260 assign(t0, binop(Iop_Add64, 6261 unop(Iop_32Uto64, getIReg(rs)), 6262 unop(Iop_32Uto64, getIReg(rt)))); 6263 6264 assign(t1, binop(Iop_CmpEQ32, 6265 binop(Iop_And32, 6266 unop(Iop_64HIto32, mkexpr(t0)), 6267 mkU32(0x1)), 6268 mkU32(0x1))); 6269 putDSPControl(IRExpr_ITE(mkexpr(t1), 6270 binop(Iop_Or32, 6271 getDSPControl(), 6272 mkU32(0x2000)), 6273 binop(Iop_And32, 6274 getDSPControl(), 6275 mkU32(0xffffdfff)))); 6276 6277 putIReg(rd, unop(Iop_64to32, mkexpr(t0))); 6278 break; 6279 } 6280 case 0x11: { /* ADDWC */ 6281 DIP("addwc r%u, r%u, r%u", rd, rs, rt); 6282 vassert(!mode64); 6283 t0 = newTemp(Ity_I32); 6284 t1 = newTemp(Ity_I64); 6285 t2 = newTemp(Ity_I32); 6286 t3 = newTemp(Ity_I32); 6287 t4 = newTemp(Ity_I1); 6288 6289 /* Get carry bit from DSPControl register. */ 6290 assign(t0, binop(Iop_Shr32, 6291 binop(Iop_And32, 6292 getDSPControl(), 6293 mkU32(0x2000)), 6294 mkU8(0xd))); 6295 assign(t1, binop(Iop_Add64, 6296 unop(Iop_32Sto64, getIReg(rs)), 6297 unop(Iop_32Sto64, 6298 binop(Iop_Add32, 6299 getIReg(rt), 6300 mkexpr(t0))))); 6301 6302 /* Extract bits 32 and 31. */ 6303 assign(t2, binop(Iop_And32, 6304 unop(Iop_64HIto32, mkexpr(t1)), 6305 mkU32(0x1))); 6306 assign(t3, binop(Iop_Shr32, 6307 binop(Iop_And32, 6308 unop(Iop_64to32, mkexpr(t1)), 6309 mkU32(0x80000000)), 6310 mkU8(31))); 6311 assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3))); 6312 6313 putDSPControl(IRExpr_ITE(mkexpr(t4), 6314 binop(Iop_Or32, 6315 getDSPControl(), 6316 mkU32(0x00100000)), 6317 getDSPControl())); 6318 putIReg(rd, unop(Iop_64to32, mkexpr(t1))); 6319 break; 6320 } 6321 case 0x12: { /* MODSUB */ 6322 DIP("modsub r%u, r%u, r%u", rd, rs, rt); 6323 vassert(!mode64); 6324 t0 = newTemp(Ity_I32); 6325 t1 = newTemp(Ity_I32); 6326 t2 = newTemp(Ity_I32); 6327 6328 /* decr_7..0 */ 6329 assign(t0, 6330 unop(Iop_8Uto32, 6331 unop(Iop_16to8, 6332 unop(Iop_32to16, getIReg(rt))))); 6333 6334 /* lastindex_15..0 */ 6335 assign(t1, 6336 unop(Iop_16Uto32, 6337 binop(Iop_8HLto16, 6338 unop(Iop_16to8, 6339 unop(Iop_32HIto16, getIReg(rt))), 6340 unop(Iop_16HIto8, 6341 unop(Iop_32to16, getIReg(rt)))))); 6342 /* temp_15..0 */ 6343 assign(t2, 6344 IRExpr_ITE(binop(Iop_CmpEQ32, 6345 getIReg(rs), 6346 mkU32(0x00000000)), 6347 mkexpr(t1), 6348 binop(Iop_Sub32, 6349 getIReg(rs), mkexpr(t0)))); 6350 putIReg(rd, mkexpr(t2)); 6351 break; 6352 } 6353 case 0x14: { /* RADDU.W.QB */ 6354 DIP("raddu.w.qb r%u, r%u", rd, rs); 6355 vassert(!mode64); 6356 putIReg(rd, binop(Iop_Add32, 6357 binop(Iop_Add32, 6358 unop(Iop_8Uto32, 6359 unop(Iop_16to8, 6360 unop(Iop_32to16, 6361 getIReg(rs)))), 6362 unop(Iop_8Uto32, 6363 unop(Iop_16HIto8, 6364 unop(Iop_32to16, 6365 getIReg(rs))))), 6366 binop(Iop_Add32, 6367 unop(Iop_8Uto32, 6368 unop(Iop_16to8, 6369 unop(Iop_32HIto16, 6370 getIReg(rs)))), 6371 unop(Iop_8Uto32, 6372 unop(Iop_16HIto8, 6373 unop(Iop_32HIto16, 6374 getIReg(rs))))))); 6375 break; 6376 } 6377 case 0x16: { /* ADDQ_S.W */ 6378 DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt); 6379 vassert(!mode64); 6380 t0 = newTemp(Ity_I64); 6381 t1 = newTemp(Ity_I1); 6382 t2 = newTemp(Ity_I32); 6383 t3 = newTemp(Ity_I32); 6384 6385 assign(t0, binop(Iop_Add64, 6386 unop(Iop_32Sto64, getIReg(rs)), 6387 unop(Iop_32Sto64, getIReg(rt)))); 6388 6389 assign(t3, binop(Iop_And32, 6390 unop(Iop_64HIto32, mkexpr(t0)), 6391 mkU32(0x1))); 6392 assign(t1, binop(Iop_CmpNE32, 6393 binop(Iop_Shr32, 6394 binop(Iop_And32, 6395 unop(Iop_64to32, mkexpr(t0)), 6396 mkU32(0x80000000)), 6397 mkU8(31)), 6398 mkexpr(t3))); 6399 6400 putDSPControl(IRExpr_ITE(mkexpr(t1), 6401 binop(Iop_Or32, 6402 getDSPControl(), 6403 mkU32(0x00100000)), 6404 getDSPControl())); 6405 6406 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6407 IRExpr_ITE(binop(Iop_CmpEQ32, 6408 mkexpr(t3), 6409 mkU32(0x0)), 6410 mkU32(0x7fffffff), 6411 mkU32(0x80000000)), 6412 unop(Iop_64to32, mkexpr(t0)))); 6413 break; 6414 } 6415 case 0x17: { /* SUBQ_S.W */ 6416 DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt); 6417 vassert(!mode64); 6418 t0 = newTemp(Ity_I64); 6419 t1 = newTemp(Ity_I1); 6420 t2 = newTemp(Ity_I32); 6421 t3 = newTemp(Ity_I32); 6422 6423 assign(t0, binop(Iop_Sub64, 6424 unop(Iop_32Sto64, getIReg(rs)), 6425 unop(Iop_32Sto64, getIReg(rt)))); 6426 6427 assign(t3, binop(Iop_And32, 6428 unop(Iop_64HIto32, mkexpr(t0)), 6429 mkU32(0x1))); 6430 assign(t1, binop(Iop_CmpNE32, 6431 binop(Iop_Shr32, 6432 binop(Iop_And32, 6433 unop(Iop_64to32, mkexpr(t0)), 6434 mkU32(0x80000000)), 6435 mkU8(31)), 6436 mkexpr(t3))); 6437 6438 putDSPControl(IRExpr_ITE(mkexpr(t1), 6439 binop(Iop_Or32, 6440 getDSPControl(), 6441 mkU32(0x00100000)), 6442 getDSPControl())); 6443 6444 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6445 IRExpr_ITE(binop(Iop_CmpEQ32, 6446 mkexpr(t3), 6447 mkU32(0x0)), 6448 mkU32(0x7fffffff), 6449 mkU32(0x80000000)), 6450 unop(Iop_64to32, mkexpr(t0)))); 6451 break; 6452 } 6453 case 0x1C: { /* MULEQ_S.W.PHL */ 6454 DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt); 6455 vassert(!mode64); 6456 t0 = newTemp(Ity_I32); 6457 t1 = newTemp(Ity_I1); 6458 t2 = newTemp(Ity_I1); 6459 t3 = newTemp(Ity_I32); 6460 6461 assign(t0, 6462 binop(Iop_Shl32, 6463 binop(Iop_Mul32, 6464 unop(Iop_16Sto32, 6465 unop(Iop_32HIto16, getIReg(rt))), 6466 unop(Iop_16Sto32, 6467 unop(Iop_32HIto16, getIReg(rs)))), 6468 mkU8(0x1))); 6469 assign(t1, binop(Iop_CmpEQ32, 6470 binop(Iop_And32, 6471 getIReg(rt), 6472 mkU32(0xffff0000)), 6473 mkU32(0x80000000))); 6474 assign(t2, binop(Iop_CmpEQ32, 6475 binop(Iop_And32, 6476 getIReg(rs), 6477 mkU32(0xffff0000)), 6478 mkU32(0x80000000))); 6479 assign(t3, IRExpr_ITE(mkexpr(t1), 6480 IRExpr_ITE(mkexpr(t2), 6481 binop(Iop_Or32, 6482 getDSPControl(), 6483 mkU32(0x00200000)), 6484 getDSPControl()), 6485 getDSPControl())); 6486 putDSPControl(mkexpr(t3)); 6487 6488 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6489 IRExpr_ITE(mkexpr(t2), 6490 mkU32(0x7fffffff), 6491 mkexpr(t0)), 6492 mkexpr(t0))); 6493 break; 6494 } 6495 case 0x1D: { /* MULEQ_S.W.PHR */ 6496 DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt); 6497 vassert(!mode64); 6498 t0 = newTemp(Ity_I32); 6499 t1 = newTemp(Ity_I1); 6500 t2 = newTemp(Ity_I1); 6501 6502 assign(t0, 6503 binop(Iop_Shl32, 6504 binop(Iop_Mul32, 6505 unop(Iop_16Sto32, 6506 unop(Iop_32to16, getIReg(rt))), 6507 unop(Iop_16Sto32, 6508 unop(Iop_32to16, getIReg(rs)))), 6509 mkU8(0x1))); 6510 assign(t1, binop(Iop_CmpEQ32, 6511 binop(Iop_And32, 6512 getIReg(rt), 6513 mkU32(0xffff)), 6514 mkU32(0x8000))); 6515 assign(t2, binop(Iop_CmpEQ32, 6516 binop(Iop_And32, 6517 getIReg(rs), 6518 mkU32(0xffff)), 6519 mkU32(0x8000))); 6520 putDSPControl(IRExpr_ITE(mkexpr(t1), 6521 IRExpr_ITE(mkexpr(t2), 6522 binop(Iop_Or32, 6523 getDSPControl(), 6524 mkU32(0x00200000) 6525 ), 6526 getDSPControl()), 6527 getDSPControl())); 6528 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6529 IRExpr_ITE(mkexpr(t2), 6530 mkU32(0x7fffffff), 6531 mkexpr(t0)), 6532 mkexpr(t0))); 6533 break; 6534 } 6535 case 0x1E: { /* MULQ_S.PH */ 6536 DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt); 6537 vassert(!mode64); 6538 t0 = newTemp(Ity_I32); 6539 t1 = newTemp(Ity_I32); 6540 t2 = newTemp(Ity_I16); 6541 t3 = newTemp(Ity_I16); 6542 t5 = newTemp(Ity_I32); 6543 t6 = newTemp(Ity_I32); 6544 t7 = newTemp(Ity_I32); 6545 t8 = newTemp(Ity_I32); 6546 6547 assign(t5, 6548 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs)))); 6549 assign(t6, 6550 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 6551 6552 assign(t7, 6553 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs)))); 6554 assign(t8, 6555 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt)))); 6556 6557 assign(t0, binop(Iop_And32, 6558 unop(Iop_1Sto32, 6559 binop(Iop_CmpEQ32, 6560 binop(Iop_And32, 6561 mkexpr(t5), 6562 mkU32(0xffff)), 6563 mkU32(0x8000))), 6564 unop(Iop_1Sto32, 6565 binop(Iop_CmpEQ32, 6566 binop(Iop_And32, 6567 mkexpr(t6), 6568 mkU32(0xffff)), 6569 mkU32(0x8000))))); 6570 assign(t1, binop(Iop_And32, 6571 unop(Iop_1Sto32, 6572 binop(Iop_CmpEQ32, 6573 binop(Iop_And32, 6574 mkexpr(t7), 6575 mkU32(0xffff)), 6576 mkU32(0x8000))), 6577 unop(Iop_1Sto32, 6578 binop(Iop_CmpEQ32, 6579 binop(Iop_And32, 6580 mkexpr(t8), 6581 mkU32(0xffff)), 6582 mkU32(0x8000))))); 6583 6584 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 6585 binop(Iop_Or32, 6586 mkexpr(t0), 6587 mkexpr(t1)), 6588 mkU32(0x0)), 6589 getDSPControl(), 6590 binop(Iop_Or32, 6591 getDSPControl(), 6592 mkU32(0x200000)))); 6593 6594 assign(t2, unop(Iop_32HIto16, 6595 binop(Iop_Shl32, 6596 unop(Iop_64to32, 6597 binop(Iop_MullS32, 6598 mkexpr(t7), 6599 mkexpr(t8))), 6600 mkU8(0x1)))); 6601 assign(t3, unop(Iop_32HIto16, 6602 binop(Iop_Shl32, 6603 unop(Iop_64to32, 6604 binop(Iop_MullS32, 6605 mkexpr(t5), 6606 mkexpr(t6))), 6607 mkU8(0x1)))); 6608 putIReg(rd, binop(Iop_16HLto32, 6609 IRExpr_ITE(binop(Iop_CmpEQ32, 6610 mkexpr(t1), 6611 mkU32(0x0)), 6612 mkexpr(t2), 6613 mkU16(0x7fff)), 6614 IRExpr_ITE(binop(Iop_CmpEQ32, 6615 mkexpr(t0), 6616 mkU32(0x0)), 6617 mkexpr(t3), 6618 mkU16(0x7fff)))); 6619 break; 6620 } 6621 case 0x1F: { /* MULQ_RS.PH */ 6622 DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt); 6623 vassert(!mode64); 6624 t0 = newTemp(Ity_I32); 6625 t1 = newTemp(Ity_I1); 6626 t2 = newTemp(Ity_I1); 6627 t3 = newTemp(Ity_I16); 6628 t4 = newTemp(Ity_I32); 6629 t5 = newTemp(Ity_I1); 6630 t6 = newTemp(Ity_I1); 6631 t7 = newTemp(Ity_I16); 6632 6633 /* Multiply and round lower halfwords. */ 6634 assign(t0, binop(Iop_Add32, 6635 binop(Iop_Shl32, 6636 binop(Iop_Mul32, 6637 unop(Iop_16Sto32, 6638 unop(Iop_32to16, 6639 getIReg(rt))), 6640 unop(Iop_16Sto32, 6641 unop(Iop_32to16, 6642 getIReg(rs)))), 6643 mkU8(0x1)), 6644 mkU32(0x00008000))); 6645 assign(t1, binop(Iop_CmpEQ32, 6646 binop(Iop_And32, 6647 getIReg(rt), mkU32(0xffff)), 6648 mkU32(0x8000))); 6649 assign(t2, binop(Iop_CmpEQ32, 6650 binop(Iop_And32, 6651 getIReg(rs), mkU32(0xffff)), 6652 mkU32(0x8000))); 6653 putDSPControl(IRExpr_ITE(mkexpr(t1), 6654 IRExpr_ITE(mkexpr(t2), 6655 binop(Iop_Or32, 6656 getDSPControl(), 6657 mkU32(0x00200000) 6658 ), 6659 getDSPControl()), 6660 getDSPControl())); 6661 assign(t3, IRExpr_ITE(mkexpr(t1), 6662 IRExpr_ITE(mkexpr(t2), 6663 mkU16(0x7fff), 6664 unop(Iop_32HIto16, 6665 mkexpr(t0))), 6666 unop(Iop_32HIto16, mkexpr(t0)))); 6667 6668 /* Multiply and round higher halfwords. */ 6669 assign(t4, binop(Iop_Add32, 6670 binop(Iop_Shl32, 6671 binop(Iop_Mul32, 6672 unop(Iop_16Sto32, 6673 unop(Iop_32HIto16, 6674 getIReg(rt))), 6675 unop(Iop_16Sto32, 6676 unop(Iop_32HIto16, 6677 getIReg(rs)))), 6678 mkU8(0x1)), 6679 mkU32(0x00008000))); 6680 assign(t5, binop(Iop_CmpEQ32, 6681 binop(Iop_And32, 6682 getIReg(rt), 6683 mkU32(0xffff0000)), 6684 mkU32(0x80000000))); 6685 assign(t6, binop(Iop_CmpEQ32, 6686 binop(Iop_And32, 6687 getIReg(rs), 6688 mkU32(0xffff0000)), 6689 mkU32(0x80000000))); 6690 putDSPControl(IRExpr_ITE(mkexpr(t5), 6691 IRExpr_ITE(mkexpr(t6), 6692 binop(Iop_Or32, 6693 getDSPControl(), 6694 mkU32(0x00200000)), 6695 getDSPControl()), 6696 getDSPControl())); 6697 assign(t7, IRExpr_ITE(mkexpr(t5), 6698 IRExpr_ITE(mkexpr(t6), 6699 mkU16(0x7fff), 6700 unop(Iop_32HIto16, 6701 mkexpr(t4))), 6702 unop(Iop_32HIto16, mkexpr(t4)))); 6703 6704 putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 6705 break; 6706 } 6707 default: 6708 return -1; 6709 } 6710 break; /* end of ADDU.QB */ 6711 } 6712 case 0x11: { /* CMPU.EQ.QB */ 6713 switch(sa) { 6714 case 0x0: { /* CMPU.EQ.QB */ 6715 DIP("cmpu.eq.qb r%u, r%u", rs, rt); 6716 vassert(!mode64); 6717 t1 = newTemp(Ity_I1); 6718 t2 = newTemp(Ity_I1); 6719 t3 = newTemp(Ity_I1); 6720 t4 = newTemp(Ity_I1); 6721 6722 assign(t1, 6723 binop(Iop_CmpEQ32, 6724 binop(Iop_And32, getIReg(rs), mkU32(0xff)), 6725 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 6726 putDSPControl(IRExpr_ITE(mkexpr(t1), 6727 binop(Iop_Or32, 6728 getDSPControl(), 6729 mkU32(0x01000000)), 6730 binop(Iop_And32, 6731 getDSPControl(), 6732 mkU32(0xfeffffff)))); 6733 6734 assign(t2, binop(Iop_CmpEQ32, 6735 unop(Iop_8Uto32, 6736 unop(Iop_16HIto8, 6737 unop(Iop_32to16, 6738 getIReg(rs)))), 6739 unop(Iop_8Uto32, 6740 unop(Iop_16HIto8, 6741 unop(Iop_32to16, 6742 getIReg(rt)))))); 6743 putDSPControl(IRExpr_ITE(mkexpr(t2), 6744 binop(Iop_Or32, 6745 getDSPControl(), 6746 mkU32(0x02000000)), 6747 binop(Iop_And32, 6748 getDSPControl(), 6749 mkU32(0xfdffffff)))); 6750 6751 assign(t3, binop(Iop_CmpEQ32, 6752 unop(Iop_8Uto32, 6753 unop(Iop_16to8, 6754 unop(Iop_32HIto16, 6755 getIReg(rs)))), 6756 unop(Iop_8Uto32, 6757 unop(Iop_16to8, 6758 unop(Iop_32HIto16, 6759 getIReg(rt)))))); 6760 putDSPControl(IRExpr_ITE(mkexpr(t3), 6761 binop(Iop_Or32, 6762 getDSPControl(), 6763 mkU32(0x04000000)), 6764 binop(Iop_And32, 6765 getDSPControl(), 6766 mkU32(0xfbffffff)))); 6767 6768 assign(t4, binop(Iop_CmpEQ32, 6769 unop(Iop_8Uto32, 6770 unop(Iop_16HIto8, 6771 unop(Iop_32HIto16, 6772 getIReg(rs)))), 6773 unop(Iop_8Uto32, 6774 unop(Iop_16HIto8, 6775 unop(Iop_32HIto16, 6776 getIReg(rt)))))); 6777 putDSPControl(IRExpr_ITE(mkexpr(t4), 6778 binop(Iop_Or32, 6779 getDSPControl(), 6780 mkU32(0x08000000)), 6781 binop(Iop_And32, 6782 getDSPControl(), 6783 mkU32(0xf7ffffff)))); 6784 break; 6785 } 6786 case 0x1: { /* CMPU.LT.QB */ 6787 DIP("cmpu.lt.qb r%u, r%u", rs, rt); 6788 vassert(!mode64); 6789 t1 = newTemp(Ity_I1); 6790 t2 = newTemp(Ity_I1); 6791 t3 = newTemp(Ity_I1); 6792 t4 = newTemp(Ity_I1); 6793 6794 assign(t1, binop(Iop_CmpLT32U, 6795 unop(Iop_8Uto32, 6796 unop(Iop_16to8, 6797 unop(Iop_32to16, 6798 getIReg(rs)))), 6799 unop(Iop_8Uto32, 6800 unop(Iop_16to8, 6801 unop(Iop_32to16, 6802 getIReg(rt)))))); 6803 putDSPControl(IRExpr_ITE(mkexpr(t1), 6804 binop(Iop_Or32, 6805 getDSPControl(), 6806 mkU32(0x01000000)), 6807 binop(Iop_And32, 6808 getDSPControl(), 6809 mkU32(0xfeffffff)))); 6810 6811 assign(t2, binop(Iop_CmpLT32U, 6812 unop(Iop_8Uto32, 6813 unop(Iop_16HIto8, 6814 unop(Iop_32to16, 6815 getIReg(rs)))), 6816 unop(Iop_8Uto32, 6817 unop(Iop_16HIto8, 6818 unop(Iop_32to16, 6819 getIReg(rt)))))); 6820 putDSPControl(IRExpr_ITE(mkexpr(t2), 6821 binop(Iop_Or32, 6822 getDSPControl(), 6823 mkU32(0x02000000)), 6824 binop(Iop_And32, 6825 getDSPControl(), 6826 mkU32(0xfdffffff)))); 6827 6828 assign(t3, binop(Iop_CmpLT32U, 6829 unop(Iop_8Uto32, 6830 unop(Iop_16to8, 6831 unop(Iop_32HIto16, 6832 getIReg(rs)))), 6833 unop(Iop_8Uto32, 6834 unop(Iop_16to8, 6835 unop(Iop_32HIto16, 6836 getIReg(rt)))))); 6837 putDSPControl(IRExpr_ITE(mkexpr(t3), 6838 binop(Iop_Or32, 6839 getDSPControl(), 6840 mkU32(0x04000000)), 6841 binop(Iop_And32, 6842 getDSPControl(), 6843 mkU32(0xfbffffff)))); 6844 6845 assign(t4, binop(Iop_CmpLT32U, 6846 unop(Iop_8Uto32, 6847 unop(Iop_16HIto8, 6848 unop(Iop_32HIto16, 6849 getIReg(rs)))), 6850 unop(Iop_8Uto32, 6851 unop(Iop_16HIto8, 6852 unop(Iop_32HIto16, 6853 getIReg(rt)))))); 6854 putDSPControl(IRExpr_ITE(mkexpr(t4), 6855 binop(Iop_Or32, 6856 getDSPControl(), 6857 mkU32(0x08000000)), 6858 binop(Iop_And32, 6859 getDSPControl(), 6860 mkU32(0xf7ffffff)))); 6861 break; 6862 } 6863 case 0x2: { /* CMPU.LE.QB */ 6864 DIP("cmpu.le.qb r%u, r%u", rs, rt); 6865 vassert(!mode64); 6866 t1 = newTemp(Ity_I1); 6867 t2 = newTemp(Ity_I1); 6868 t3 = newTemp(Ity_I1); 6869 t4 = newTemp(Ity_I1); 6870 6871 assign(t1, binop(Iop_CmpLE32U, 6872 unop(Iop_8Uto32, 6873 unop(Iop_16to8, 6874 unop(Iop_32to16, 6875 getIReg(rs)))), 6876 unop(Iop_8Uto32, 6877 unop(Iop_16to8, 6878 unop(Iop_32to16, 6879 getIReg(rt)))))); 6880 putDSPControl(IRExpr_ITE(mkexpr(t1), 6881 binop(Iop_Or32, 6882 getDSPControl(), 6883 mkU32(0x01000000)), 6884 binop(Iop_And32, 6885 getDSPControl(), 6886 mkU32(0xfeffffff)))); 6887 6888 assign(t2, binop(Iop_CmpLE32U, 6889 unop(Iop_8Uto32, 6890 unop(Iop_16HIto8, 6891 unop(Iop_32to16, 6892 getIReg(rs)))), 6893 unop(Iop_8Uto32, 6894 unop(Iop_16HIto8, 6895 unop(Iop_32to16, 6896 getIReg(rt)))))); 6897 putDSPControl(IRExpr_ITE(mkexpr(t2), 6898 binop(Iop_Or32, 6899 getDSPControl(), 6900 mkU32(0x02000000)), 6901 binop(Iop_And32, 6902 getDSPControl(), 6903 mkU32(0xfdffffff)))); 6904 6905 assign(t3, binop(Iop_CmpLE32U, 6906 unop(Iop_8Uto32, 6907 unop(Iop_16to8, 6908 unop(Iop_32HIto16, 6909 getIReg(rs)))), 6910 unop(Iop_8Uto32, 6911 unop(Iop_16to8, 6912 unop(Iop_32HIto16, 6913 getIReg(rt)))))); 6914 putDSPControl(IRExpr_ITE(mkexpr(t3), 6915 binop(Iop_Or32, 6916 getDSPControl(), 6917 mkU32(0x04000000)), 6918 binop(Iop_And32, 6919 getDSPControl(), 6920 mkU32(0xfbffffff)))); 6921 6922 assign(t4, binop(Iop_CmpLE32U, 6923 unop(Iop_8Uto32, 6924 unop(Iop_16HIto8, 6925 unop(Iop_32HIto16, 6926 getIReg(rs)))), 6927 unop(Iop_8Uto32, 6928 unop(Iop_16HIto8, 6929 unop(Iop_32HIto16, 6930 getIReg(rt)))))); 6931 putDSPControl(IRExpr_ITE(mkexpr(t4), 6932 binop(Iop_Or32, 6933 getDSPControl(), 6934 mkU32(0x08000000)), 6935 binop(Iop_And32, 6936 getDSPControl(), 6937 mkU32(0xf7ffffff)))); 6938 break; 6939 } 6940 case 0x3: { /* PICK.QB */ 6941 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt); 6942 vassert(!mode64); 6943 t0 = newTemp(Ity_I32); 6944 t1 = newTemp(Ity_I8); 6945 t2 = newTemp(Ity_I8); 6946 t3 = newTemp(Ity_I8); 6947 t4 = newTemp(Ity_I8); 6948 6949 assign(t0, getDSPControl()); 6950 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32, 6951 binop(Iop_And32, 6952 mkexpr(t0), 6953 mkU32(0x01000000)), 6954 mkU32(0x0)), 6955 unop(Iop_16to8, 6956 unop(Iop_32to16, 6957 getIReg(rs))), 6958 unop(Iop_16to8, 6959 unop(Iop_32to16, 6960 getIReg(rt))))); 6961 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32, 6962 binop(Iop_And32, 6963 mkexpr(t0), 6964 mkU32(0x02000000)), 6965 mkU32(0x0)), 6966 unop(Iop_16HIto8, 6967 unop(Iop_32to16, getIReg(rs))), 6968 unop(Iop_16HIto8, 6969 unop(Iop_32to16, 6970 getIReg(rt))))); 6971 assign(t3, IRExpr_ITE(binop(Iop_CmpNE32, 6972 binop(Iop_And32, 6973 mkexpr(t0), 6974 mkU32(0x04000000)), 6975 mkU32(0x0)), 6976 unop(Iop_16to8, 6977 unop(Iop_32HIto16, 6978 getIReg(rs))), 6979 unop(Iop_16to8, 6980 unop(Iop_32HIto16, 6981 getIReg(rt))))); 6982 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 6983 binop(Iop_And32, 6984 mkexpr(t0), 6985 mkU32(0x08000000)), 6986 mkU32(0x0)), 6987 unop(Iop_16HIto8, 6988 unop(Iop_32HIto16, 6989 getIReg(rs))), 6990 unop(Iop_16HIto8, 6991 unop(Iop_32HIto16, 6992 getIReg(rt))))); 6993 putIReg(rd, 6994 binop(Iop_16HLto32, 6995 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)), 6996 binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1)))); 6997 break; 6998 } 6999 case 0x4: { /* CMPGU.EQ.QB */ 7000 DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt); 7001 vassert(!mode64); 7002 t1 = newTemp(Ity_I1); 7003 t2 = newTemp(Ity_I1); 7004 t3 = newTemp(Ity_I1); 7005 t4 = newTemp(Ity_I1); 7006 t5 = newTemp(Ity_I32); 7007 t6 = newTemp(Ity_I32); 7008 t7 = newTemp(Ity_I32); 7009 t8 = newTemp(Ity_I32); 7010 7011 assign(t1, binop(Iop_CmpEQ32, 7012 unop(Iop_8Uto32, 7013 unop(Iop_16to8, 7014 unop(Iop_32to16, getIReg(rs)))), 7015 unop(Iop_8Uto32, 7016 unop(Iop_16to8, 7017 unop(Iop_32to16, 7018 getIReg(rt)))))); 7019 assign(t5, IRExpr_ITE(mkexpr(t1), 7020 mkU32(0x00000001), mkU32(0))); 7021 7022 assign(t2, binop(Iop_CmpEQ32, 7023 unop(Iop_8Uto32, 7024 unop(Iop_16HIto8, 7025 unop(Iop_32to16, getIReg(rs)))), 7026 unop(Iop_8Uto32, 7027 unop(Iop_16HIto8, 7028 unop(Iop_32to16, 7029 getIReg(rt)))))); 7030 assign(t6, IRExpr_ITE(mkexpr(t2), 7031 mkU32(0x00000002), mkU32(0))); 7032 7033 assign(t3, binop(Iop_CmpEQ32, 7034 unop(Iop_8Uto32, 7035 unop(Iop_16to8, 7036 unop(Iop_32HIto16, 7037 getIReg(rs)))), 7038 unop(Iop_8Uto32, 7039 unop(Iop_16to8, 7040 unop(Iop_32HIto16, 7041 getIReg(rt)))))); 7042 assign(t7, IRExpr_ITE(mkexpr(t3), 7043 mkU32(0x00000004), mkU32(0))); 7044 7045 assign(t4, binop(Iop_CmpEQ32, 7046 unop(Iop_8Uto32, 7047 unop(Iop_16HIto8, 7048 unop(Iop_32HIto16, 7049 getIReg(rs)))), 7050 unop(Iop_8Uto32, 7051 unop(Iop_16HIto8, 7052 unop(Iop_32HIto16, 7053 getIReg(rt)))))); 7054 assign(t8, IRExpr_ITE(mkexpr(t4), 7055 mkU32(0x00000008), mkU32(0))); 7056 7057 putIReg(rd, binop(Iop_Or32, 7058 binop(Iop_Or32, 7059 binop(Iop_Or32, 7060 mkexpr(t5), mkexpr(t6)), 7061 mkexpr(t7)), 7062 mkexpr(t8))); 7063 break; 7064 } 7065 case 0x5: { /* CMPGU.LT.QB */ 7066 DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt); 7067 vassert(!mode64); 7068 t1 = newTemp(Ity_I1); 7069 t2 = newTemp(Ity_I1); 7070 t3 = newTemp(Ity_I1); 7071 t4 = newTemp(Ity_I1); 7072 t5 = newTemp(Ity_I32); 7073 t6 = newTemp(Ity_I32); 7074 t7 = newTemp(Ity_I32); 7075 t8 = newTemp(Ity_I32); 7076 7077 assign(t1, binop(Iop_CmpLT32U, 7078 unop(Iop_8Uto32, 7079 unop(Iop_16to8, 7080 unop(Iop_32to16, getIReg(rs)))), 7081 unop(Iop_8Uto32, 7082 unop(Iop_16to8, 7083 unop(Iop_32to16, 7084 getIReg(rt)))))); 7085 assign(t5, IRExpr_ITE(mkexpr(t1), 7086 mkU32(0x00000001), mkU32(0))); 7087 7088 assign(t2, binop(Iop_CmpLT32U, 7089 unop(Iop_8Uto32, 7090 unop(Iop_16HIto8, 7091 unop(Iop_32to16, getIReg(rs)))), 7092 unop(Iop_8Uto32, 7093 unop(Iop_16HIto8, 7094 unop(Iop_32to16, 7095 getIReg(rt)))))); 7096 assign(t6, IRExpr_ITE(mkexpr(t2), 7097 mkU32(0x00000002), mkU32(0))); 7098 7099 assign(t3, binop(Iop_CmpLT32U, 7100 unop(Iop_8Uto32, 7101 unop(Iop_16to8, 7102 unop(Iop_32HIto16, 7103 getIReg(rs)))), 7104 unop(Iop_8Uto32, 7105 unop(Iop_16to8, 7106 unop(Iop_32HIto16, 7107 getIReg(rt)))))); 7108 assign(t7, IRExpr_ITE(mkexpr(t3), 7109 mkU32(0x00000004), mkU32(0))); 7110 7111 assign(t4, binop(Iop_CmpLT32U, 7112 unop(Iop_8Uto32, 7113 unop(Iop_16HIto8, 7114 unop(Iop_32HIto16, 7115 getIReg(rs)))), 7116 unop(Iop_8Uto32, 7117 unop(Iop_16HIto8, 7118 unop(Iop_32HIto16, 7119 getIReg(rt)))))); 7120 assign(t8, IRExpr_ITE(mkexpr(t4), 7121 mkU32(0x00000008), mkU32(0))); 7122 putIReg(rd, binop(Iop_Or32, 7123 binop(Iop_Or32, 7124 binop(Iop_Or32, 7125 mkexpr(t5), mkexpr(t6)), 7126 mkexpr(t7)), 7127 mkexpr(t8))); 7128 break; 7129 } 7130 case 0x6: { /* CMPGU.LE.QB */ 7131 DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt); 7132 vassert(!mode64); 7133 t1 = newTemp(Ity_I1); 7134 t2 = newTemp(Ity_I1); 7135 t3 = newTemp(Ity_I1); 7136 t4 = newTemp(Ity_I1); 7137 t5 = newTemp(Ity_I32); 7138 t6 = newTemp(Ity_I32); 7139 t7 = newTemp(Ity_I32); 7140 t8 = newTemp(Ity_I32); 7141 7142 assign(t1, binop(Iop_CmpLE32U, 7143 unop(Iop_8Uto32, 7144 unop(Iop_16to8, 7145 unop(Iop_32to16, getIReg(rs)))), 7146 unop(Iop_8Uto32, 7147 unop(Iop_16to8, 7148 unop(Iop_32to16, 7149 getIReg(rt)))))); 7150 assign(t5, IRExpr_ITE(mkexpr(t1), 7151 mkU32(0x00000001), mkU32(0))); 7152 7153 assign(t2, binop(Iop_CmpLE32U, 7154 unop(Iop_8Uto32, 7155 unop(Iop_16HIto8, 7156 unop(Iop_32to16, getIReg(rs)))), 7157 unop(Iop_8Uto32, 7158 unop(Iop_16HIto8, 7159 unop(Iop_32to16, 7160 getIReg(rt)))))); 7161 assign(t6, IRExpr_ITE(mkexpr(t2), 7162 mkU32(0x00000002), mkU32(0))); 7163 7164 assign(t3, binop(Iop_CmpLE32U, 7165 unop(Iop_8Uto32, 7166 unop(Iop_16to8, 7167 unop(Iop_32HIto16, 7168 getIReg(rs)))), 7169 unop(Iop_8Uto32, 7170 unop(Iop_16to8, 7171 unop(Iop_32HIto16, 7172 getIReg(rt)))))); 7173 assign(t7, IRExpr_ITE(mkexpr(t3), 7174 mkU32(0x00000004), mkU32(0))); 7175 7176 assign(t4, binop(Iop_CmpLE32U, 7177 unop(Iop_8Uto32, 7178 unop(Iop_16HIto8, 7179 unop(Iop_32HIto16, 7180 getIReg(rs)))), 7181 unop(Iop_8Uto32, 7182 unop(Iop_16HIto8, 7183 unop(Iop_32HIto16, 7184 getIReg(rt)))))); 7185 assign(t8, IRExpr_ITE(mkexpr(t4), 7186 mkU32(0x00000008), mkU32(0))); 7187 putIReg(rd, binop(Iop_Or32, 7188 binop(Iop_Or32, 7189 binop(Iop_Or32, 7190 mkexpr(t5), mkexpr(t6)), 7191 mkexpr(t7)), 7192 mkexpr(t8))); 7193 break; 7194 } 7195 case 0x8: { /* CMP.EQ.PH */ 7196 DIP("cmp.eq.ph r%u, r%u", rs, rt); 7197 vassert(!mode64); 7198 t1 = newTemp(Ity_I1); 7199 t2 = newTemp(Ity_I1); 7200 7201 assign(t1, binop(Iop_CmpEQ16, 7202 unop(Iop_32to16, getIReg(rs)), 7203 unop(Iop_32to16, getIReg(rt)))); 7204 putDSPControl(IRExpr_ITE(mkexpr(t1), 7205 binop(Iop_Or32, 7206 getDSPControl(), 7207 mkU32(0x01000000)), 7208 binop(Iop_And32, 7209 getDSPControl(), 7210 mkU32(0xfeffffff)))); 7211 assign(t2, binop(Iop_CmpEQ16, 7212 unop(Iop_32HIto16, getIReg(rs)), 7213 unop(Iop_32HIto16, getIReg(rt)))); 7214 putDSPControl(IRExpr_ITE(mkexpr(t2), 7215 binop(Iop_Or32, 7216 getDSPControl(), 7217 mkU32(0x02000000)), 7218 binop(Iop_And32, 7219 getDSPControl(), 7220 mkU32(0xfdffffff)))); 7221 break; 7222 } 7223 case 0x9: { /* CMP.LT.PH */ 7224 DIP("cmp.lt.ph r%u, r%u", rs, rt); 7225 vassert(!mode64); 7226 t1 = newTemp(Ity_I1); 7227 t2 = newTemp(Ity_I1); 7228 7229 assign(t1, binop(Iop_CmpLT32S, 7230 unop(Iop_16Sto32, 7231 unop(Iop_32to16, getIReg(rs))), 7232 unop(Iop_16Sto32, 7233 unop(Iop_32to16, getIReg(rt))))); 7234 putDSPControl(IRExpr_ITE(mkexpr(t1), 7235 binop(Iop_Or32, 7236 getDSPControl(), 7237 mkU32(0x01000000)), 7238 binop(Iop_And32, 7239 getDSPControl(), 7240 mkU32(0xfeffffff)))); 7241 7242 assign(t2, binop(Iop_CmpLT32S, 7243 unop(Iop_16Sto32, 7244 unop(Iop_32HIto16, getIReg(rs))), 7245 unop(Iop_16Sto32, 7246 unop(Iop_32HIto16, getIReg(rt))))); 7247 putDSPControl(IRExpr_ITE(mkexpr(t2), 7248 binop(Iop_Or32, 7249 getDSPControl(), 7250 mkU32(0x02000000)), 7251 binop(Iop_And32, 7252 getDSPControl(), 7253 mkU32(0xfdffffff)))); 7254 break; 7255 } 7256 case 0xA: { /* CMP.LE.PH */ 7257 DIP("cmp.le.ph r%u, r%u", rs, rt); 7258 vassert(!mode64); 7259 t1 = newTemp(Ity_I1); 7260 t2 = newTemp(Ity_I1); 7261 7262 assign(t1, binop(Iop_CmpLE32S, 7263 unop(Iop_16Sto32, 7264 unop(Iop_32to16, getIReg(rs))), 7265 unop(Iop_16Sto32, 7266 unop(Iop_32to16, getIReg(rt))))); 7267 putDSPControl(IRExpr_ITE(mkexpr(t1), 7268 binop(Iop_Or32, 7269 getDSPControl(), 7270 mkU32(0x01000000)), 7271 binop(Iop_And32, 7272 getDSPControl(), 7273 mkU32(0xfeffffff)))); 7274 7275 assign(t2, binop(Iop_CmpLE32S, 7276 unop(Iop_16Sto32, 7277 unop(Iop_32HIto16, getIReg(rs))), 7278 unop(Iop_16Sto32, 7279 unop(Iop_32HIto16, getIReg(rt))))); 7280 putDSPControl(IRExpr_ITE(mkexpr(t2), 7281 binop(Iop_Or32, 7282 getDSPControl(), 7283 mkU32(0x02000000)), 7284 binop(Iop_And32, 7285 getDSPControl(), 7286 mkU32(0xfdffffff)))); 7287 break; 7288 } 7289 case 0xB: { /* PICK.PH */ 7290 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt); 7291 vassert(!mode64); 7292 t0 = newTemp(Ity_I32); 7293 t1 = newTemp(Ity_I16); 7294 t2 = newTemp(Ity_I16); 7295 7296 assign(t0, getDSPControl()); 7297 7298 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32, 7299 binop(Iop_And32, 7300 mkexpr(t0), 7301 mkU32(0x01000000)), 7302 mkU32(0x0)), 7303 unop(Iop_32to16, getIReg(rs)), 7304 unop(Iop_32to16, getIReg(rt)))); 7305 7306 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32, 7307 binop(Iop_And32, 7308 mkexpr(t0), 7309 mkU32(0x02000000)), 7310 mkU32(0x0)), 7311 unop(Iop_32HIto16, getIReg(rs)), 7312 unop(Iop_32HIto16, getIReg(rt)))); 7313 7314 putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1))); 7315 break; 7316 } 7317 case 0xC: { /* PRECRQ.QB.PH */ 7318 DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt); 7319 vassert(!mode64); 7320 putIReg(rd, 7321 binop(Iop_16HLto32, 7322 binop(Iop_8HLto16, 7323 unop(Iop_16HIto8, 7324 unop(Iop_32HIto16, getIReg(rs))), 7325 unop(Iop_16HIto8, 7326 unop(Iop_32to16, getIReg(rs)))), 7327 binop(Iop_8HLto16, 7328 unop(Iop_16HIto8, 7329 unop(Iop_32HIto16, getIReg(rt))), 7330 unop(Iop_16HIto8, 7331 unop(Iop_32to16, getIReg(rt)))))); 7332 break; 7333 } 7334 case 0xD: { /* PRECR.QB.PH */ 7335 DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt); 7336 vassert(!mode64); 7337 7338 putIReg(rd, 7339 binop(Iop_16HLto32, 7340 binop(Iop_8HLto16, 7341 unop(Iop_16to8, 7342 unop(Iop_32HIto16, getIReg(rs))), 7343 unop(Iop_16to8, 7344 unop(Iop_32to16, getIReg(rs)))), 7345 binop(Iop_8HLto16, 7346 unop(Iop_16to8, 7347 unop(Iop_32HIto16, getIReg(rt))), 7348 unop(Iop_16to8, 7349 unop(Iop_32to16, getIReg(rt)))))); 7350 break; 7351 } 7352 case 0xF: { /* PRECRQU_S.QB.PH */ 7353 DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt); 7354 vassert(!mode64); 7355 t0 = newTemp(Ity_I8); 7356 t1 = newTemp(Ity_I8); 7357 t2 = newTemp(Ity_I8); 7358 t3 = newTemp(Ity_I8); 7359 t4 = newTemp(Ity_I8); 7360 t5 = newTemp(Ity_I32); 7361 t6 = newTemp(Ity_I1); 7362 t7 = newTemp(Ity_I8); 7363 t8 = newTemp(Ity_I1); 7364 t9 = newTemp(Ity_I32); 7365 t10 = newTemp(Ity_I8); 7366 t11 = newTemp(Ity_I1); 7367 t12 = newTemp(Ity_I32); 7368 t13 = newTemp(Ity_I8); 7369 t14 = newTemp(Ity_I1); 7370 t15 = newTemp(Ity_I32); 7371 7372 assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U, 7373 mkU32(0x7f80), 7374 binop(Iop_And32, 7375 unop(Iop_16Uto32, 7376 unop(Iop_32to16, 7377 getIReg(rs))), 7378 mkU32(0x7fff))), 7379 mkU8(0xff), 7380 unop(Iop_16HIto8, 7381 unop(Iop_32to16, 7382 binop(Iop_Shl32, 7383 getIReg(rs), 7384 mkU8(1)))))); 7385 assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32, 7386 binop(Iop_And32, 7387 unop(Iop_16Uto32, 7388 unop(Iop_32to16, 7389 getIReg(rs))), 7390 mkU32(0x00008000)), 7391 mkU32(0x0)), 7392 mkexpr(t4), 7393 mkU8(0x0))); 7394 assign(t5, binop(Iop_And32, 7395 unop(Iop_16Uto32, 7396 unop(Iop_32to16, 7397 getIReg(rs))), 7398 mkU32(0x00008000))); 7399 assign(t6, binop(Iop_CmpLT32U, 7400 mkU32(0x7f80), 7401 binop(Iop_And32, 7402 unop(Iop_16Uto32, 7403 unop(Iop_32to16, 7404 getIReg(rs))), 7405 mkU32(0x7fff)))); 7406 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 7407 mkexpr(t5), 7408 mkU32(0x0)), 7409 IRExpr_ITE(mkexpr(t6), 7410 binop(Iop_Or32, 7411 getDSPControl(), 7412 mkU32(0x00400000) 7413 ), 7414 getDSPControl()), 7415 binop(Iop_Or32, 7416 getDSPControl(), 7417 mkU32(0x00400000)))); 7418 7419 assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U, 7420 mkU32(0x7f80), 7421 binop(Iop_And32, 7422 unop(Iop_16Uto32, 7423 unop(Iop_32HIto16, 7424 getIReg(rs))), 7425 mkU32(0x7fff))), 7426 mkU8(0xff), 7427 unop(Iop_16HIto8, 7428 unop(Iop_32HIto16, 7429 binop(Iop_Shl32, 7430 getIReg(rs), 7431 mkU8(1)))))); 7432 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32, 7433 binop(Iop_And32, 7434 unop(Iop_16Uto32, 7435 unop(Iop_32HIto16, 7436 getIReg(rs))), 7437 mkU32(0x00008000)), 7438 mkU32(0x0)), 7439 mkexpr(t7), 7440 mkU8(0x0))); 7441 assign(t8, binop(Iop_CmpEQ32, 7442 binop(Iop_And32, 7443 unop(Iop_16Uto32, 7444 unop(Iop_32HIto16, 7445 getIReg(rs))), 7446 mkU32(0x00008000)), 7447 mkU32(0x0))); 7448 assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U, 7449 mkU32(0x7f80), 7450 binop(Iop_And32, 7451 unop(Iop_16Uto32, 7452 unop(Iop_32HIto16, 7453 getIReg(rs))), 7454 mkU32(0x7fff))), 7455 binop(Iop_Or32, 7456 getDSPControl(), 7457 mkU32(0x00400000)), 7458 getDSPControl())); 7459 putDSPControl(IRExpr_ITE(mkexpr(t8), 7460 mkexpr(t9), 7461 binop(Iop_Or32, 7462 getDSPControl(), 7463 mkU32(0x00400000)))); 7464 7465 assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U, 7466 mkU32(0x7f80), 7467 binop(Iop_And32, 7468 unop(Iop_16Uto32, 7469 unop(Iop_32to16, 7470 getIReg(rt))), 7471 mkU32(0x7fff))), 7472 mkU8(0xff), 7473 unop(Iop_16HIto8, 7474 unop(Iop_32to16, 7475 binop(Iop_Shl32, 7476 getIReg(rt), 7477 mkU8(1)))))); 7478 assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32, 7479 binop(Iop_And32, 7480 unop(Iop_16Uto32, 7481 unop(Iop_32to16, 7482 getIReg(rt))), 7483 mkU32(0x00008000)), 7484 mkU32(0x0)), 7485 mkexpr(t10), 7486 mkU8(0x0))); 7487 assign(t11, binop(Iop_CmpEQ32, 7488 binop(Iop_And32, 7489 unop(Iop_16Uto32, 7490 unop(Iop_32to16, 7491 getIReg(rt))), 7492 mkU32(0x00008000)), 7493 mkU32(0x0))); 7494 assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U, 7495 mkU32(0x7f80), 7496 binop(Iop_And32, 7497 unop(Iop_16Uto32, 7498 unop(Iop_32to16, 7499 getIReg(rt))), 7500 mkU32(0x7fff))), 7501 binop(Iop_Or32, 7502 getDSPControl(), 7503 mkU32(0x00400000)), 7504 getDSPControl())); 7505 putDSPControl(IRExpr_ITE(mkexpr(t11), 7506 mkexpr(t12), 7507 binop(Iop_Or32, 7508 getDSPControl(), 7509 mkU32(0x00400000)))); 7510 7511 assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U, 7512 mkU32(0x7f80), 7513 binop(Iop_And32, 7514 unop(Iop_16Uto32, 7515 unop(Iop_32HIto16, 7516 getIReg(rt))), 7517 mkU32(0x7fff))), 7518 mkU8(0xff), 7519 unop(Iop_16HIto8, 7520 unop(Iop_32HIto16, 7521 binop(Iop_Shl32, 7522 getIReg(rt), 7523 mkU8(1)))))); 7524 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32, 7525 binop(Iop_And32, 7526 unop(Iop_16Uto32, 7527 unop(Iop_32HIto16, 7528 getIReg(rt))), 7529 mkU32(0x00008000)), 7530 mkU32(0x0)), 7531 mkexpr(t13), 7532 mkU8(0x0))); 7533 assign(t14, binop(Iop_CmpEQ32, 7534 binop(Iop_And32, 7535 unop(Iop_16Uto32, 7536 unop(Iop_32HIto16, 7537 getIReg(rt))), 7538 mkU32(0x00008000)), 7539 mkU32(0x0))); 7540 assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U, 7541 mkU32(0x7f80), 7542 binop(Iop_And32, 7543 unop(Iop_16Uto32, 7544 unop(Iop_32HIto16, 7545 getIReg(rt))), 7546 mkU32(0x7fff))), 7547 binop(Iop_Or32, 7548 getDSPControl(), 7549 mkU32(0x00400000)), 7550 getDSPControl())); 7551 putDSPControl(IRExpr_ITE(mkexpr(t14), 7552 mkexpr(t15), 7553 binop(Iop_Or32, 7554 getDSPControl(), 7555 mkU32(0x00400000)))); 7556 7557 putIReg(rd, binop(Iop_16HLto32, 7558 binop(Iop_8HLto16, 7559 mkexpr(t1), mkexpr(t0)), 7560 binop(Iop_8HLto16, 7561 mkexpr(t3), mkexpr(t2)))); 7562 break; 7563 } 7564 case 0x14: { /* PRECRQ.PH.W */ 7565 DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt); 7566 vassert(!mode64); 7567 putIReg(rd, binop(Iop_16HLto32, 7568 unop(Iop_32HIto16, getIReg(rs)), 7569 unop(Iop_32HIto16, getIReg(rt)))); 7570 break; 7571 } 7572 case 0x15: { /* PRECRQ_RS.PH.W */ 7573 DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt); 7574 vassert(!mode64); 7575 t0 = newTemp(Ity_I64); 7576 t1 = newTemp(Ity_I1); 7577 t2 = newTemp(Ity_I32); 7578 t3 = newTemp(Ity_I64); 7579 t4 = newTemp(Ity_I1); 7580 t5 = newTemp(Ity_I32); 7581 7582 assign(t0, binop(Iop_Add64, 7583 binop(Iop_32HLto64, 7584 binop(Iop_Shr32, 7585 binop(Iop_And32, 7586 getIReg(rs), 7587 mkU32(0x80000000)), 7588 mkU8(31)), 7589 getIReg(rs)), 7590 mkU64(0x0000000000008000ULL))); 7591 assign(t1, binop(Iop_CmpNE32, 7592 binop(Iop_And32, 7593 unop(Iop_64HIto32, mkexpr(t0)), 7594 mkU32(0x1)), 7595 binop(Iop_And32, 7596 binop(Iop_Shr32, 7597 unop(Iop_64to32, mkexpr(t0)), 7598 mkU8(31)), 7599 mkU32(0x1)))); 7600 assign(t2, IRExpr_ITE(mkexpr(t1), 7601 mkU32(0x7fffffff), 7602 unop(Iop_64to32, mkexpr(t0)))); 7603 putDSPControl(IRExpr_ITE(mkexpr(t1), 7604 binop(Iop_Or32, 7605 getDSPControl(), 7606 mkU32(0x400000)), 7607 getDSPControl())); 7608 assign(t3, binop(Iop_Add64, 7609 binop(Iop_32HLto64, 7610 binop(Iop_Shr32, 7611 binop(Iop_And32, 7612 getIReg(rt), 7613 mkU32(0x80000000)), 7614 mkU8(31)), 7615 getIReg(rt)), 7616 mkU64(0x0000000000008000ULL))); 7617 assign(t4, binop(Iop_CmpNE32, 7618 binop(Iop_And32, 7619 unop(Iop_64HIto32, mkexpr(t3)), 7620 mkU32(0x1)), 7621 binop(Iop_And32, 7622 binop(Iop_Shr32, 7623 unop(Iop_64to32, mkexpr(t3)), 7624 mkU8(31)), 7625 mkU32(0x1)))); 7626 assign(t5, IRExpr_ITE(mkexpr(t4), 7627 mkU32(0x7fffffff), 7628 unop(Iop_64to32, mkexpr(t3)))); 7629 putDSPControl(IRExpr_ITE(mkexpr(t4), 7630 binop(Iop_Or32, 7631 getDSPControl(), 7632 mkU32(0x400000)), 7633 getDSPControl())); 7634 putIReg(rd, binop(Iop_16HLto32, 7635 unop(Iop_32HIto16, mkexpr(t2)), 7636 unop(Iop_32HIto16, mkexpr(t5)))); 7637 break; 7638 } 7639 case 0x1E: { /* PRECR_SRA.PH.W */ 7640 DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd); 7641 vassert(!mode64); 7642 7643 if (0 == rd) { 7644 putIReg(rt, binop(Iop_16HLto32, 7645 unop(Iop_32to16, getIReg(rt)), 7646 unop(Iop_32to16, getIReg(rs)))); 7647 } else { 7648 putIReg(rt, binop(Iop_16HLto32, 7649 unop(Iop_32to16, binop(Iop_Sar32, 7650 getIReg(rt), 7651 mkU8(rd))), 7652 unop(Iop_32to16, binop(Iop_Sar32, 7653 getIReg(rs), 7654 mkU8(rd))))); 7655 } 7656 break; 7657 } 7658 case 0x1F: { /* PRECR_SRA_R.PH.W */ 7659 DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd); 7660 vassert(!mode64); 7661 7662 t0 = newTemp(Ity_I32); 7663 t1 = newTemp(Ity_I32); 7664 7665 if (0 == rd) { 7666 putIReg(rt, binop(Iop_16HLto32, 7667 unop(Iop_32to16, getIReg(rt)), 7668 unop(Iop_32to16, getIReg(rs)))); 7669 } else { 7670 assign(t0, binop(Iop_Shr32, 7671 binop(Iop_Add32, 7672 binop(Iop_Sar32, 7673 getIReg(rt), 7674 mkU8(rd-1)), 7675 mkU32(0x1)), 7676 mkU8(0x1))); 7677 assign(t1, binop(Iop_Shr32, 7678 binop(Iop_Add32, 7679 binop(Iop_Sar32, 7680 getIReg(rs), 7681 mkU8(rd-1)), 7682 mkU32(0x1)), 7683 mkU8(0x1))); 7684 putIReg(rt, binop(Iop_16HLto32, 7685 unop(Iop_32to16, mkexpr(t0)), 7686 unop(Iop_32to16, mkexpr(t1)))); 7687 }; 7688 break; 7689 } 7690 case 0xE: { /* PACKRL.PH */ 7691 DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt); 7692 vassert(!mode64); 7693 7694 putIReg(rd, binop(Iop_16HLto32, 7695 unop(Iop_32to16, getIReg(rs)), 7696 unop(Iop_32HIto16, getIReg(rt)))); 7697 break; 7698 } 7699 case 0x18: { /* CMPGDU.EQ.QB */ 7700 DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt); 7701 vassert(!mode64); 7702 t1 = newTemp(Ity_I1); 7703 t2 = newTemp(Ity_I1); 7704 t3 = newTemp(Ity_I1); 7705 t4 = newTemp(Ity_I1); 7706 t5 = newTemp(Ity_I32); 7707 t6 = newTemp(Ity_I32); 7708 t7 = newTemp(Ity_I32); 7709 t8 = newTemp(Ity_I32); 7710 7711 assign(t1, 7712 binop(Iop_CmpEQ32, 7713 unop(Iop_8Uto32, 7714 unop(Iop_16to8, 7715 unop(Iop_32to16, getIReg(rs)))), 7716 unop(Iop_8Uto32, 7717 unop(Iop_16to8, 7718 unop(Iop_32to16, getIReg(rt)))))); 7719 assign(t5, IRExpr_ITE(mkexpr(t1), 7720 mkU32(0x00000001), mkU32(0))); 7721 putDSPControl(IRExpr_ITE(mkexpr(t1), 7722 binop(Iop_Or32, 7723 getDSPControl(), 7724 mkU32(0x01000000)), 7725 binop(Iop_And32, 7726 getDSPControl(), 7727 mkU32(0xfeffffff)))); 7728 7729 assign(t2, binop(Iop_CmpEQ32, 7730 unop(Iop_8Uto32, 7731 unop(Iop_16HIto8, 7732 unop(Iop_32to16, getIReg(rs)))), 7733 unop(Iop_8Uto32, 7734 unop(Iop_16HIto8, 7735 unop(Iop_32to16, 7736 getIReg(rt)))))); 7737 assign(t6, IRExpr_ITE(mkexpr(t2), 7738 mkU32(0x00000002), mkU32(0))); 7739 putDSPControl(IRExpr_ITE(mkexpr(t2), 7740 binop(Iop_Or32, 7741 getDSPControl(), 7742 mkU32(0x02000000)), 7743 binop(Iop_And32, 7744 getDSPControl(), 7745 mkU32(0xfdffffff)))); 7746 7747 assign(t3, binop(Iop_CmpEQ32, 7748 unop(Iop_8Uto32, 7749 unop(Iop_16to8, 7750 unop(Iop_32HIto16, 7751 getIReg(rs)))), 7752 unop(Iop_8Uto32, 7753 unop(Iop_16to8, 7754 unop(Iop_32HIto16, 7755 getIReg(rt)))))); 7756 assign(t7, IRExpr_ITE(mkexpr(t3), 7757 mkU32(0x00000004), mkU32(0))); 7758 putDSPControl(IRExpr_ITE(mkexpr(t3), 7759 binop(Iop_Or32, 7760 getDSPControl(), 7761 mkU32(0x04000000)), 7762 binop(Iop_And32, 7763 getDSPControl(), 7764 mkU32(0xfbffffff)))); 7765 7766 assign(t4, binop(Iop_CmpEQ32, 7767 unop(Iop_8Uto32, 7768 unop(Iop_16HIto8, 7769 unop(Iop_32HIto16, 7770 getIReg(rs)))), 7771 unop(Iop_8Uto32, 7772 unop(Iop_16HIto8, 7773 unop(Iop_32HIto16, 7774 getIReg(rt)))))); 7775 assign(t8, IRExpr_ITE(mkexpr(t4), 7776 mkU32(0x00000008), mkU32(0))); 7777 putDSPControl(IRExpr_ITE(mkexpr(t4), 7778 binop(Iop_Or32, 7779 getDSPControl(), 7780 mkU32(0x08000000)), 7781 binop(Iop_And32, 7782 getDSPControl(), 7783 mkU32(0xf7ffffff)))); 7784 7785 putIReg(rd, binop(Iop_Or32, 7786 binop(Iop_Or32, 7787 binop(Iop_Or32, 7788 mkexpr(t5), mkexpr(t6)), 7789 mkexpr(t7)), 7790 mkexpr(t8))); 7791 break; 7792 } 7793 case 0x19: { /* CMPGDU.LT.QB */ 7794 DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt); 7795 vassert(!mode64); 7796 t1 = newTemp(Ity_I1); 7797 t2 = newTemp(Ity_I1); 7798 t3 = newTemp(Ity_I1); 7799 t4 = newTemp(Ity_I1); 7800 t5 = newTemp(Ity_I32); 7801 t6 = newTemp(Ity_I32); 7802 t7 = newTemp(Ity_I32); 7803 t8 = newTemp(Ity_I32); 7804 7805 assign(t1, binop(Iop_CmpLT32U, 7806 unop(Iop_8Uto32, 7807 unop(Iop_16to8, 7808 unop(Iop_32to16, getIReg(rs)))), 7809 unop(Iop_8Uto32, 7810 unop(Iop_16to8, 7811 unop(Iop_32to16, 7812 getIReg(rt)))))); 7813 assign(t5, IRExpr_ITE(mkexpr(t1), 7814 mkU32(0x00000001), mkU32(0))); 7815 putDSPControl(IRExpr_ITE(mkexpr(t1), 7816 binop(Iop_Or32, 7817 getDSPControl(), 7818 mkU32(0x01000000)), 7819 binop(Iop_And32, 7820 getDSPControl(), 7821 mkU32(0xfeffffff)))); 7822 7823 assign(t2, binop(Iop_CmpLT32U, 7824 unop(Iop_8Uto32, 7825 unop(Iop_16HIto8, 7826 unop(Iop_32to16, getIReg(rs)))), 7827 unop(Iop_8Uto32, 7828 unop(Iop_16HIto8, 7829 unop(Iop_32to16, 7830 getIReg(rt)))))); 7831 assign(t6, IRExpr_ITE(mkexpr(t2), 7832 mkU32(0x00000002), mkU32(0))); 7833 putDSPControl(IRExpr_ITE(mkexpr(t2), 7834 binop(Iop_Or32, 7835 getDSPControl(), 7836 mkU32(0x02000000)), 7837 binop(Iop_And32, 7838 getDSPControl(), 7839 mkU32(0xfdffffff)))); 7840 7841 assign(t3, binop(Iop_CmpLT32U, 7842 unop(Iop_8Uto32, 7843 unop(Iop_16to8, 7844 unop(Iop_32HIto16, 7845 getIReg(rs)))), 7846 unop(Iop_8Uto32, 7847 unop(Iop_16to8, 7848 unop(Iop_32HIto16, 7849 getIReg(rt)))))); 7850 assign(t7, IRExpr_ITE(mkexpr(t3), 7851 mkU32(0x00000004), mkU32(0))); 7852 putDSPControl(IRExpr_ITE(mkexpr(t3), 7853 binop(Iop_Or32, 7854 getDSPControl(), 7855 mkU32(0x04000000)), 7856 binop(Iop_And32, 7857 getDSPControl(), 7858 mkU32(0xfbffffff)))); 7859 7860 assign(t4, binop(Iop_CmpLT32U, 7861 unop(Iop_8Uto32, 7862 unop(Iop_16HIto8, 7863 unop(Iop_32HIto16, 7864 getIReg(rs)))), 7865 unop(Iop_8Uto32, 7866 unop(Iop_16HIto8, 7867 unop(Iop_32HIto16, 7868 getIReg(rt)))))); 7869 assign(t8, IRExpr_ITE(mkexpr(t4), 7870 mkU32(0x00000008), mkU32(0))); 7871 putDSPControl(IRExpr_ITE(mkexpr(t4), 7872 binop(Iop_Or32, 7873 getDSPControl(), 7874 mkU32(0x08000000)), 7875 binop(Iop_And32, 7876 getDSPControl(), 7877 mkU32(0xf7ffffff)))); 7878 7879 putIReg(rd, binop(Iop_Or32, 7880 binop(Iop_Or32, 7881 binop(Iop_Or32, 7882 mkexpr(t5), mkexpr(t6)), 7883 mkexpr(t7)), 7884 mkexpr(t8))); 7885 break; 7886 } 7887 case 0x1A: { /* CMPGDU.LE.QB */ 7888 DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt); 7889 vassert(!mode64); 7890 t1 = newTemp(Ity_I1); 7891 t2 = newTemp(Ity_I1); 7892 t3 = newTemp(Ity_I1); 7893 t4 = newTemp(Ity_I1); 7894 t5 = newTemp(Ity_I32); 7895 t6 = newTemp(Ity_I32); 7896 t7 = newTemp(Ity_I32); 7897 t8 = newTemp(Ity_I32); 7898 7899 assign(t1, binop(Iop_CmpLE32U, 7900 unop(Iop_8Uto32, 7901 unop(Iop_16to8, 7902 unop(Iop_32to16, getIReg(rs)))), 7903 unop(Iop_8Uto32, 7904 unop(Iop_16to8, 7905 unop(Iop_32to16, 7906 getIReg(rt)))))); 7907 assign(t5, IRExpr_ITE(mkexpr(t1), 7908 mkU32(0x00000001), 7909 mkU32(0))); 7910 putDSPControl(IRExpr_ITE(mkexpr(t1), 7911 binop(Iop_Or32, 7912 getDSPControl(), 7913 mkU32(0x01000000)), 7914 binop(Iop_And32, 7915 getDSPControl(), 7916 mkU32(0xfeffffff)))); 7917 7918 assign(t2, binop(Iop_CmpLE32U, 7919 unop(Iop_8Uto32, 7920 unop(Iop_16HIto8, 7921 unop(Iop_32to16, getIReg(rs)))), 7922 unop(Iop_8Uto32, 7923 unop(Iop_16HIto8, 7924 unop(Iop_32to16, 7925 getIReg(rt)))))); 7926 assign(t6, IRExpr_ITE(mkexpr(t2), 7927 mkU32(0x00000002), mkU32(0))); 7928 putDSPControl(IRExpr_ITE(mkexpr(t2), 7929 binop(Iop_Or32, 7930 getDSPControl(), 7931 mkU32(0x02000000)), 7932 binop(Iop_And32, 7933 getDSPControl(), 7934 mkU32(0xfdffffff)))); 7935 7936 assign(t3, binop(Iop_CmpLE32U, 7937 unop(Iop_8Uto32, 7938 unop(Iop_16to8, 7939 unop(Iop_32HIto16, 7940 getIReg(rs)))), 7941 unop(Iop_8Uto32, 7942 unop(Iop_16to8, 7943 unop(Iop_32HIto16, 7944 getIReg(rt)))))); 7945 assign(t7, IRExpr_ITE(mkexpr(t3), 7946 mkU32(0x00000004), mkU32(0))); 7947 putDSPControl(IRExpr_ITE(mkexpr(t3), 7948 binop(Iop_Or32, 7949 getDSPControl(), 7950 mkU32(0x04000000)), 7951 binop(Iop_And32, 7952 getDSPControl(), 7953 mkU32(0xfbffffff)))); 7954 7955 assign(t4, binop(Iop_CmpLE32U, 7956 unop(Iop_8Uto32, 7957 unop(Iop_16HIto8, 7958 unop(Iop_32HIto16, 7959 getIReg(rs)))), 7960 unop(Iop_8Uto32, 7961 unop(Iop_16HIto8, 7962 unop(Iop_32HIto16, 7963 getIReg(rt)))))); 7964 assign(t8, IRExpr_ITE(mkexpr(t4), 7965 mkU32(0x00000008), mkU32(0))); 7966 putDSPControl(IRExpr_ITE(mkexpr(t4), 7967 binop(Iop_Or32, 7968 getDSPControl(), 7969 mkU32(0x08000000)), 7970 binop(Iop_And32, 7971 getDSPControl(), 7972 mkU32(0xf7ffffff)))); 7973 7974 putIReg(rd, binop(Iop_Or32, 7975 binop(Iop_Or32, 7976 binop(Iop_Or32, 7977 mkexpr(t5), mkexpr(t6)), 7978 mkexpr(t7)), 7979 mkexpr(t8))); 7980 break; 7981 } 7982 default: 7983 return -1; 7984 } 7985 break; /* end of CMPU.EQ.QB */ 7986 } 7987 case 0x13: { /* SHLL.QB */ 7988 switch(sa) { 7989 case 0x0: { /* SHLL.QB */ 7990 DIP("shll.qb r%u, r%u, %u", rd, rt, rs); 7991 vassert(!mode64); 7992 t0 = newTemp(Ity_I32); 7993 t1 = newTemp(Ity_I1); 7994 t2 = newTemp(Ity_I1); 7995 t3 = newTemp(Ity_I32); 7996 t4 = newTemp(Ity_I1); 7997 t5 = newTemp(Ity_I1); 7998 t6 = newTemp(Ity_I32); 7999 t7 = newTemp(Ity_I1); 8000 t8 = newTemp(Ity_I1); 8001 t9 = newTemp(Ity_I1); 8002 t10 = newTemp(Ity_I1); 8003 8004 if (0 == rs) { 8005 putIReg(rd, getIReg(rt)); 8006 } else { 8007 /* Shift bits 7..0 and 23..16. */ 8008 assign(t0, binop(Iop_Shl32, 8009 binop(Iop_And32, 8010 getIReg(rt), 8011 mkU32(0x00ff00ff)), 8012 mkU8(rs))); 8013 assign(t1, binop(Iop_CmpNE32, 8014 binop(Iop_And32, 8015 mkexpr(t0), 8016 mkU32(0xff000000)), 8017 mkU32(0x00000000))); 8018 assign(t2, binop(Iop_CmpNE32, 8019 binop(Iop_And32, 8020 mkexpr(t0), 8021 mkU32(0xff000000)), 8022 mkU32(0xff000000))); 8023 assign(t7, binop(Iop_CmpNE32, 8024 binop(Iop_And32, 8025 mkexpr(t0), 8026 mkU32(0x0000ff00)), 8027 mkU32(0x00000000))); 8028 assign(t8, binop(Iop_CmpNE32, 8029 binop(Iop_And32, 8030 mkexpr(t0), 8031 mkU32(0x0000ff00)), 8032 mkU32(0x000ff00))); 8033 /* Shift bits 15..8 and 31..24. */ 8034 assign(t3, binop(Iop_Shl32, 8035 binop(Iop_Shr32, 8036 binop(Iop_And32, 8037 getIReg(rt), 8038 mkU32(0xff00ff00)), 8039 mkU8(8)), 8040 mkU8(rs))); 8041 assign(t4, binop(Iop_CmpNE32, 8042 binop(Iop_And32, 8043 mkexpr(t3), 8044 mkU32(0xff000000)), 8045 mkU32(0x00000000))); 8046 assign(t5, binop(Iop_CmpNE32, 8047 binop(Iop_And32, 8048 mkexpr(t3), 8049 mkU32(0xff000000)), 8050 mkU32(0xff000000))); 8051 assign(t9, binop(Iop_CmpNE32, 8052 binop(Iop_And32, 8053 mkexpr(t3), 8054 mkU32(0x0000ff00)), 8055 mkU32(0x00000000))); 8056 assign(t10, binop(Iop_CmpNE32, 8057 binop(Iop_And32, 8058 mkexpr(t3), 8059 mkU32(0x0000ff00)), 8060 mkU32(0x0000ff00))); 8061 8062 assign(t6, binop(Iop_Or32, 8063 binop(Iop_Or32, 8064 binop(Iop_And32, 8065 unop(Iop_1Uto32, 8066 mkexpr(t1)), 8067 unop(Iop_1Uto32, 8068 mkexpr(t2))), 8069 binop(Iop_And32, 8070 unop(Iop_1Uto32, 8071 mkexpr(t7)), 8072 unop(Iop_1Uto32, 8073 mkexpr(t8)))), 8074 binop(Iop_Or32, 8075 binop(Iop_And32, 8076 unop(Iop_1Uto32, 8077 mkexpr(t4)), 8078 unop(Iop_1Uto32, 8079 mkexpr(t5))), 8080 binop(Iop_And32, 8081 unop(Iop_1Uto32, 8082 mkexpr(t9)), 8083 unop(Iop_1Uto32, 8084 mkexpr(t10)))))); 8085 8086 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8087 mkexpr(t6), 8088 mkU32(0x0)), 8089 binop(Iop_Or32, 8090 getDSPControl(), 8091 mkU32(0x400000)), 8092 getDSPControl())); 8093 putIReg(rd, binop(Iop_Or32, 8094 binop(Iop_Shl32, 8095 binop(Iop_And32, 8096 mkexpr(t3), 8097 mkU32(0x00ff00ff)), 8098 mkU8(8)), 8099 binop(Iop_And32, 8100 mkexpr(t0), 8101 mkU32(0x00ff00ff)))); 8102 } 8103 break; 8104 } 8105 case 0x3: { /* SHRL.QB */ 8106 DIP("shrl.qb r%u, r%u, %u", rd, rt, rs); 8107 vassert(!mode64); 8108 t0 = newTemp(Ity_I32); 8109 t1 = newTemp(Ity_I8); 8110 t2 = newTemp(Ity_I32); 8111 t3 = newTemp(Ity_I8); 8112 t4 = newTemp(Ity_I32); 8113 t5 = newTemp(Ity_I8); 8114 t6 = newTemp(Ity_I32); 8115 t7 = newTemp(Ity_I8); 8116 t9 = newTemp(Ity_I32); 8117 8118 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7))); 8119 assign(t0, unop(Iop_8Uto32, 8120 unop(Iop_16to8, 8121 unop(Iop_32to16, getIReg(rt))))); 8122 assign(t1, unop(Iop_32to8, 8123 binop(Iop_Shr32, 8124 mkexpr(t0), 8125 unop(Iop_32to8, mkexpr(t9))))); 8126 8127 assign(t2, unop(Iop_8Uto32, 8128 unop(Iop_16HIto8, 8129 unop(Iop_32to16, getIReg(rt))))); 8130 assign(t3, unop(Iop_32to8, 8131 binop(Iop_Shr32, 8132 mkexpr(t2), 8133 unop(Iop_32to8, mkexpr(t9))))); 8134 8135 assign(t4, unop(Iop_8Uto32, 8136 unop(Iop_16to8, 8137 unop(Iop_32HIto16, getIReg(rt))))); 8138 assign(t5, unop(Iop_32to8, 8139 binop(Iop_Shr32, 8140 mkexpr(t4), 8141 unop(Iop_32to8, mkexpr(t9))))); 8142 8143 assign(t6, unop(Iop_8Uto32, 8144 unop(Iop_16HIto8, 8145 unop(Iop_32HIto16, getIReg(rt))))); 8146 assign(t7, unop(Iop_32to8, 8147 binop(Iop_Shr32, 8148 mkexpr(t6), 8149 unop(Iop_32to8, mkexpr(t9))))); 8150 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8151 mkexpr(t9), 8152 mkU32(0x0)), 8153 getIReg(rt), 8154 binop(Iop_16HLto32, 8155 binop(Iop_8HLto16, 8156 mkexpr(t7), 8157 mkexpr(t5)), 8158 binop(Iop_8HLto16, 8159 mkexpr(t3), 8160 mkexpr(t1))))); 8161 break; 8162 } 8163 case 0x2: { /* SHLLV.QB */ 8164 DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs); 8165 vassert(!mode64); 8166 t0 = newTemp(Ity_I32); 8167 t1 = newTemp(Ity_I1); 8168 t2 = newTemp(Ity_I1); 8169 t3 = newTemp(Ity_I32); 8170 t4 = newTemp(Ity_I1); 8171 t5 = newTemp(Ity_I1); 8172 t6 = newTemp(Ity_I32); 8173 t7 = newTemp(Ity_I1); 8174 t8 = newTemp(Ity_I1); 8175 t9 = newTemp(Ity_I1); 8176 t10 = newTemp(Ity_I1); 8177 t11 = newTemp(Ity_I8); 8178 8179 assign(t11, unop(Iop_32to8, 8180 binop(Iop_And32, 8181 getIReg(rs), 8182 mkU32(0x7)))); 8183 /* Shift bits 7..0 and 23..16. */ 8184 assign(t0, binop(Iop_Shl32, 8185 binop(Iop_And32, 8186 getIReg(rt), 8187 mkU32(0x00ff00ff)), 8188 mkexpr(t11))); 8189 assign(t1, binop(Iop_CmpNE32, 8190 binop(Iop_And32, 8191 mkexpr(t0), 8192 mkU32(0xff000000)), 8193 mkU32(0x00000000))); 8194 assign(t2, binop(Iop_CmpNE32, 8195 binop(Iop_And32, 8196 mkexpr(t0), 8197 mkU32(0xff000000)), 8198 mkU32(0xff000000))); 8199 assign(t7, binop(Iop_CmpNE32, 8200 binop(Iop_And32, 8201 mkexpr(t0), 8202 mkU32(0x0000ff00)), 8203 mkU32(0x00000000))); 8204 assign(t8, binop(Iop_CmpNE32, 8205 binop(Iop_And32, 8206 mkexpr(t0), 8207 mkU32(0x0000ff00)), 8208 mkU32(0x000ff00))); 8209 /* Shift bits 15..8 and 31..24. */ 8210 assign(t3, binop(Iop_Shl32, 8211 binop(Iop_Shr32, 8212 binop(Iop_And32, 8213 getIReg(rt), 8214 mkU32(0xff00ff00)), 8215 mkU8(8)), 8216 mkexpr(t11))); 8217 assign(t4, binop(Iop_CmpNE32, 8218 binop(Iop_And32, 8219 mkexpr(t3), 8220 mkU32(0xff000000)), 8221 mkU32(0x00000000))); 8222 assign(t5, binop(Iop_CmpNE32, 8223 binop(Iop_And32, 8224 mkexpr(t3), 8225 mkU32(0xff000000)), 8226 mkU32(0xff000000))); 8227 assign(t9, binop(Iop_CmpNE32, 8228 binop(Iop_And32, 8229 mkexpr(t3), 8230 mkU32(0x0000ff00)), 8231 mkU32(0x00000000))); 8232 assign(t10, binop(Iop_CmpNE32, 8233 binop(Iop_And32, 8234 mkexpr(t3), 8235 mkU32(0x0000ff00)), 8236 mkU32(0x0000ff00))); 8237 8238 assign(t6, binop(Iop_Or32, 8239 binop(Iop_Or32, 8240 binop(Iop_And32, 8241 unop(Iop_1Uto32, 8242 mkexpr(t1)), 8243 unop(Iop_1Uto32, 8244 mkexpr(t2))), 8245 binop(Iop_And32, 8246 unop(Iop_1Uto32, 8247 mkexpr(t7)), 8248 unop(Iop_1Uto32, 8249 mkexpr(t8)))), 8250 binop(Iop_Or32, 8251 binop(Iop_And32, 8252 unop(Iop_1Uto32, 8253 mkexpr(t4)), 8254 unop(Iop_1Uto32, 8255 mkexpr(t5))), 8256 binop(Iop_And32, 8257 unop(Iop_1Uto32, 8258 mkexpr(t9)), 8259 unop(Iop_1Uto32, 8260 mkexpr(t10)))))); 8261 8262 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8263 mkexpr(t6), 8264 mkU32(0x0)), 8265 binop(Iop_Or32, 8266 getDSPControl(), 8267 mkU32(0x400000)), 8268 getDSPControl())); 8269 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8270 unop(Iop_8Uto32, mkexpr(t11)), 8271 mkU32(0)), 8272 getIReg(rt), 8273 binop(Iop_Or32, 8274 binop(Iop_Shl32, 8275 binop(Iop_And32, 8276 mkexpr(t3), 8277 mkU32(0xff00ff)), 8278 mkU8(8)), 8279 binop(Iop_And32, 8280 mkexpr(t0), 8281 mkU32(0x00ff00ff))))); 8282 break; 8283 } 8284 case 0x1: { /* SHRLV.QB */ 8285 DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs); 8286 vassert(!mode64); 8287 t0 = newTemp(Ity_I8); 8288 t1 = newTemp(Ity_I8); 8289 t2 = newTemp(Ity_I8); 8290 t3 = newTemp(Ity_I8); 8291 8292 assign(t0, unop(Iop_32to8, 8293 binop(Iop_Shr32, 8294 unop(Iop_8Uto32, 8295 unop(Iop_32to8, getIReg(rt))), 8296 mkU8(rs)))); 8297 assign(t1, unop(Iop_32to8, 8298 binop(Iop_Shr32, 8299 unop(Iop_8Uto32, 8300 unop(Iop_16HIto8, 8301 unop(Iop_32to16, 8302 getIReg(rt)))), 8303 mkU8(rs)))); 8304 assign(t2, unop(Iop_32to8, 8305 binop(Iop_Shr32, 8306 unop(Iop_8Uto32, 8307 unop(Iop_16to8, 8308 unop(Iop_32HIto16, 8309 getIReg(rt)))), 8310 mkU8(rs)))); 8311 assign(t3, unop(Iop_32to8, 8312 binop(Iop_Shr32, 8313 unop(Iop_8Uto32, 8314 unop(Iop_16HIto8, 8315 unop(Iop_32HIto16, 8316 getIReg(rt)))), 8317 mkU8(rs)))); 8318 putIReg(rd, 8319 binop(Iop_16HLto32, 8320 binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)), 8321 binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0)))); 8322 break; 8323 } 8324 case 0x4: { /* SHRA.QB */ 8325 DIP("shra.qb r%u, r%u, %u", rd, rt, rs); 8326 vassert(!mode64); 8327 t0 = newTemp(Ity_I32); 8328 t1 = newTemp(Ity_I32); 8329 t2 = newTemp(Ity_I32); 8330 t3 = newTemp(Ity_I32); 8331 t4 = newTemp(Ity_I32); 8332 t5 = newTemp(Ity_I32); 8333 t6 = newTemp(Ity_I32); 8334 t7 = newTemp(Ity_I32); 8335 t8 = newTemp(Ity_I32); 8336 t9 = newTemp(Ity_I32); 8337 t10 = newTemp(Ity_I32); 8338 t11 = newTemp(Ity_I32); 8339 8340 /* ========== GPR[rt]_31..24 ========== */ 8341 assign(t1, 8342 unop(Iop_8Uto32, 8343 unop(Iop_16HIto8, 8344 unop(Iop_32HIto16, getIReg(rt))))); 8345 assign(t2, 8346 binop(Iop_Shr32, mkexpr(t1), mkU8(rs))); 8347 /* tempD_7..0 */ 8348 assign(t0, 8349 binop(Iop_Or32, 8350 mkexpr(t2), 8351 binop(Iop_Shl32, 8352 IRExpr_ITE(binop(Iop_CmpEQ32, 8353 binop(Iop_And32, 8354 mkexpr(t1), 8355 mkU32(0x00000080) 8356 ), 8357 mkU32(0x00000080)), 8358 mkU32(0xFFFFFFFF), 8359 mkU32(0x00000000)), 8360 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8361 8362 /* ========== GPR[rt]_23..16 ========== */ 8363 assign(t4, 8364 unop(Iop_8Uto32, 8365 unop(Iop_16to8, 8366 unop(Iop_32HIto16, getIReg(rt))))); 8367 assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs))); 8368 /* tempC_7..0 */ 8369 assign(t3, 8370 binop(Iop_Or32, 8371 mkexpr(t5), 8372 binop(Iop_Shl32, 8373 IRExpr_ITE(binop(Iop_CmpEQ32, 8374 binop(Iop_And32, 8375 mkexpr(t4), 8376 mkU32(0x00000080) 8377 ), 8378 mkU32(0x00000080)), 8379 mkU32(0xFFFFFFFF), 8380 mkU32(0x00000000)), 8381 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8382 8383 /* ========== GPR[rt]_15..8 ========== */ 8384 assign(t7, 8385 unop(Iop_8Uto32, 8386 unop(Iop_16HIto8, 8387 unop(Iop_32to16, getIReg(rt))))); 8388 assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs))); 8389 /* tempB_7..0 */ 8390 assign(t6, 8391 binop(Iop_Or32, 8392 mkexpr(t8), 8393 binop(Iop_Shl32, 8394 IRExpr_ITE(binop(Iop_CmpEQ32, 8395 binop(Iop_And32, 8396 mkexpr(t7), 8397 mkU32(0x00000080) 8398 ), 8399 mkU32(0x00000080)), 8400 mkU32(0xFFFFFFFF), 8401 mkU32(0x00000000)), 8402 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8403 8404 /* ========== GPR[rt]_7..0 ========== */ 8405 assign(t10, 8406 unop(Iop_8Uto32, 8407 unop(Iop_16to8, 8408 unop(Iop_32to16, getIReg(rt))))); 8409 assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs))); 8410 /* tempB_7..0 */ 8411 assign(t9, 8412 binop(Iop_Or32, 8413 mkexpr(t11), 8414 binop(Iop_Shl32, 8415 IRExpr_ITE(binop(Iop_CmpEQ32, 8416 binop(Iop_And32, 8417 mkexpr(t10), 8418 mkU32(0x00000080) 8419 ), 8420 mkU32(0x00000080)), 8421 mkU32(0xFFFFFFFF), 8422 mkU32(0x00000000)), 8423 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8424 8425 putIReg(rd, 8426 binop(Iop_16HLto32, 8427 binop(Iop_8HLto16, 8428 unop(Iop_32to8, mkexpr(t0)), 8429 unop(Iop_32to8, mkexpr(t3))), 8430 binop(Iop_8HLto16, 8431 unop(Iop_32to8, mkexpr(t6)), 8432 unop(Iop_32to8, mkexpr(t9))))); 8433 break; 8434 } 8435 case 0x5: { /* SHRA_R.QB */ 8436 DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs); 8437 vassert(!mode64); 8438 t0 = newTemp(Ity_I32); 8439 t1 = newTemp(Ity_I8); 8440 t2 = newTemp(Ity_I32); 8441 t3 = newTemp(Ity_I8); 8442 t4 = newTemp(Ity_I32); 8443 t5 = newTemp(Ity_I8); 8444 t6 = newTemp(Ity_I32); 8445 t7 = newTemp(Ity_I8); 8446 8447 if (0 == rs) { 8448 putIReg(rd, getIReg(rt)); 8449 } else { 8450 assign(t0, unop(Iop_8Sto32, 8451 unop(Iop_16to8, 8452 unop(Iop_32to16, getIReg(rt))))); 8453 assign(t1, unop(Iop_32to8, 8454 binop(Iop_Sar32, 8455 binop(Iop_Add32, 8456 mkexpr(t0), 8457 binop(Iop_Shl32, 8458 mkU32(0x1), 8459 mkU8(rs-1))), 8460 mkU8(rs)))); 8461 8462 assign(t2, unop(Iop_8Sto32, 8463 unop(Iop_16HIto8, 8464 unop(Iop_32to16, getIReg(rt))))); 8465 assign(t3, unop(Iop_32to8, 8466 binop(Iop_Sar32, 8467 binop(Iop_Add32, 8468 mkexpr(t2), 8469 binop(Iop_Shl32, 8470 mkU32(0x1), 8471 mkU8(rs-1))), 8472 mkU8(rs)))); 8473 8474 assign(t4, unop(Iop_8Sto32, 8475 unop(Iop_16to8, 8476 unop(Iop_32HIto16, getIReg(rt))))); 8477 assign(t5, unop(Iop_32to8, 8478 binop(Iop_Sar32, 8479 binop(Iop_Add32, 8480 mkexpr(t4), 8481 binop(Iop_Shl32, 8482 mkU32(0x1), 8483 mkU8(rs-1))), 8484 mkU8(rs)))); 8485 8486 assign(t6, unop(Iop_8Sto32, 8487 unop(Iop_16HIto8, 8488 unop(Iop_32HIto16, getIReg(rt))))); 8489 assign(t7, unop(Iop_32to8, 8490 binop(Iop_Sar32, 8491 binop(Iop_Add32, 8492 mkexpr(t6), 8493 binop(Iop_Shl32, 8494 mkU32(0x1), 8495 mkU8(rs-1))), 8496 mkU8(rs)))); 8497 putIReg(rd, binop(Iop_16HLto32, 8498 binop(Iop_8HLto16, 8499 mkexpr(t7), mkexpr(t5)), 8500 binop(Iop_8HLto16, 8501 mkexpr(t3), mkexpr(t1)))); 8502 } 8503 break; 8504 } 8505 case 0x6: { /* SHRAV.QB */ 8506 DIP("shrav.qb r%u, r%u, %u", rd, rt, rs); 8507 vassert(!mode64); 8508 8509 t0 = newTemp(Ity_I32); 8510 t1 = newTemp(Ity_I32); 8511 t2 = newTemp(Ity_I32); 8512 8513 t3 = newTemp(Ity_I32); 8514 t4 = newTemp(Ity_I32); 8515 t5 = newTemp(Ity_I32); 8516 8517 t6 = newTemp(Ity_I32); 8518 t7 = newTemp(Ity_I32); 8519 t8 = newTemp(Ity_I32); 8520 8521 t9 = newTemp(Ity_I32); 8522 t10 = newTemp(Ity_I32); 8523 t11 = newTemp(Ity_I32); 8524 8525 /* ========== GPR[rt]_31..24 ========== */ 8526 assign(t1, 8527 unop(Iop_8Uto32, 8528 unop(Iop_16HIto8, 8529 unop(Iop_32HIto16, getIReg(rt))))); 8530 assign(t2, 8531 binop(Iop_Shr32, 8532 mkexpr(t1), 8533 unop(Iop_32to8, binop(Iop_And32, 8534 getIReg(rs), 8535 mkU32(0x7))))); 8536 /* tempD_7..0 */ 8537 assign(t0, 8538 binop(Iop_Or32, 8539 mkexpr(t2), 8540 binop(Iop_Shl32, 8541 IRExpr_ITE(binop(Iop_CmpEQ32, 8542 binop(Iop_And32, 8543 mkexpr(t1), 8544 mkU32(0x00000080) 8545 ), 8546 mkU32(0x00000080)), 8547 mkU32(0xFFFFFFFF), 8548 mkU32(0x00000000)), 8549 binop(Iop_Sub8, 8550 mkU8(0x8), 8551 unop(Iop_32to8, binop(Iop_And32, 8552 getIReg(rs), 8553 mkU32(0x7))) 8554 )))); 8555 8556 /* ========== GPR[rt]_23..16 ========== */ 8557 assign(t4, 8558 unop(Iop_8Uto32, 8559 unop(Iop_16to8, 8560 unop(Iop_32HIto16, getIReg(rt))))); 8561 assign(t5, 8562 binop(Iop_Shr32, 8563 mkexpr(t4), 8564 unop(Iop_32to8, binop(Iop_And32, 8565 getIReg(rs), 8566 mkU32(0x7))))); 8567 /* tempC_7..0 */ 8568 assign(t3, 8569 binop(Iop_Or32, 8570 mkexpr(t5), 8571 binop(Iop_Shl32, 8572 IRExpr_ITE(binop(Iop_CmpEQ32, 8573 binop(Iop_And32, 8574 mkexpr(t4), 8575 mkU32(0x00000080) 8576 ), 8577 mkU32(0x00000080)), 8578 mkU32(0xFFFFFFFF), 8579 mkU32(0x00000000)), 8580 binop(Iop_Sub8, 8581 mkU8(0x8), 8582 unop(Iop_32to8, binop(Iop_And32, 8583 getIReg(rs), 8584 mkU32(0x7))) 8585 )))); 8586 8587 /* ========== GPR[rt]_15..8 ========== */ 8588 assign(t7, 8589 unop(Iop_8Uto32, 8590 unop(Iop_16HIto8, 8591 unop(Iop_32to16, getIReg(rt))))); 8592 assign(t8, 8593 binop(Iop_Shr32, 8594 mkexpr(t7), 8595 unop(Iop_32to8, binop(Iop_And32, 8596 getIReg(rs), 8597 mkU32(0x7))))); 8598 /* tempB_7..0 */ 8599 assign(t6, 8600 binop(Iop_Or32, 8601 mkexpr(t8), 8602 binop(Iop_Shl32, 8603 IRExpr_ITE(binop(Iop_CmpEQ32, 8604 binop(Iop_And32, 8605 mkexpr(t7), 8606 mkU32(0x00000080) 8607 ), 8608 mkU32(0x00000080)), 8609 mkU32(0xFFFFFFFF), 8610 mkU32(0x00000000)), 8611 binop(Iop_Sub8, 8612 mkU8(0x8), 8613 unop(Iop_32to8, binop(Iop_And32, 8614 getIReg(rs), 8615 mkU32(0x7))) 8616 )))); 8617 8618 /* ========== GPR[rt]_7..0 ========== */ 8619 assign(t10, 8620 unop(Iop_8Uto32, 8621 unop(Iop_16to8, 8622 unop(Iop_32to16, getIReg(rt))))); 8623 assign(t11, 8624 binop(Iop_Shr32, 8625 mkexpr(t10), 8626 unop(Iop_32to8, binop(Iop_And32, 8627 getIReg(rs), 8628 mkU32(0x7))))); 8629 /* tempB_7..0 */ 8630 assign(t9, 8631 binop(Iop_Or32, 8632 mkexpr(t11), 8633 binop(Iop_Shl32, 8634 IRExpr_ITE(binop(Iop_CmpEQ32, 8635 binop(Iop_And32, 8636 mkexpr(t10), 8637 mkU32(0x00000080) 8638 ), 8639 mkU32(0x00000080)), 8640 mkU32(0xFFFFFFFF), 8641 mkU32(0x00000000)), 8642 binop(Iop_Sub8, 8643 mkU8(0x8), 8644 unop(Iop_32to8, binop(Iop_And32, 8645 getIReg(rs), 8646 mkU32(0x7))) 8647 )))); 8648 8649 putIReg(rd, 8650 binop(Iop_16HLto32, 8651 binop(Iop_8HLto16, 8652 unop(Iop_32to8, 8653 IRExpr_ITE(binop(Iop_CmpEQ32, 8654 binop(Iop_And32, 8655 mkU32(rs), 8656 mkU32(0x7) 8657 ), 8658 mkU32(0x0)), 8659 mkexpr(t1), 8660 mkexpr(t0))), 8661 unop(Iop_32to8, 8662 IRExpr_ITE(binop(Iop_CmpEQ32, 8663 binop(Iop_And32, 8664 mkU32(rs), 8665 mkU32(0x7) 8666 ), 8667 mkU32(0x0)), 8668 mkexpr(t2), 8669 mkexpr(t3)))), 8670 binop(Iop_8HLto16, 8671 unop(Iop_32to8, 8672 IRExpr_ITE(binop(Iop_CmpEQ32, 8673 binop(Iop_And32, 8674 mkU32(rs), 8675 mkU32(0x7) 8676 ), 8677 mkU32(0x0)), 8678 mkexpr(t5), 8679 mkexpr(t6))), 8680 unop(Iop_32to8, 8681 IRExpr_ITE(binop(Iop_CmpEQ32, 8682 binop(Iop_And32, 8683 mkU32(rs), 8684 mkU32(0x7) 8685 ), 8686 mkU32(0x0)), 8687 mkexpr(t8), 8688 mkexpr(t9)))))); 8689 break; 8690 } 8691 case 0x7: { /* SHRAV_R.QB */ 8692 DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs); 8693 vassert(!mode64); 8694 t0 = newTemp(Ity_I32); 8695 t1 = newTemp(Ity_I8); 8696 t2 = newTemp(Ity_I32); 8697 t3 = newTemp(Ity_I8); 8698 t4 = newTemp(Ity_I32); 8699 t5 = newTemp(Ity_I8); 8700 t6 = newTemp(Ity_I32); 8701 t7 = newTemp(Ity_I8); 8702 t8 = newTemp(Ity_I8); 8703 t9 = newTemp(Ity_I32); 8704 8705 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7))); 8706 assign(t8, unop(Iop_32to8, 8707 binop(Iop_Sub32, mkexpr(t9), mkU32(0x1)))); 8708 assign(t0, unop(Iop_8Sto32, 8709 unop(Iop_16to8, 8710 unop(Iop_32to16, getIReg(rt))))); 8711 assign(t1, unop(Iop_32to8, 8712 binop(Iop_Sar32, 8713 binop(Iop_Add32, 8714 mkexpr(t0), 8715 binop(Iop_Shl32, 8716 mkU32(0x1), 8717 mkexpr(t8))), 8718 unop(Iop_32to8, 8719 mkexpr(t9))))); 8720 8721 assign(t2, unop(Iop_8Sto32, 8722 unop(Iop_16HIto8, 8723 unop(Iop_32to16, getIReg(rt))))); 8724 assign(t3, unop(Iop_32to8, 8725 binop(Iop_Sar32, 8726 binop(Iop_Add32, 8727 mkexpr(t2), 8728 binop(Iop_Shl32, 8729 mkU32(0x1), 8730 mkexpr(t8))), 8731 unop(Iop_32to8, mkexpr(t9))))); 8732 8733 assign(t4, unop(Iop_8Sto32, 8734 unop(Iop_16to8, 8735 unop(Iop_32HIto16, getIReg(rt))))); 8736 assign(t5, unop(Iop_32to8, 8737 binop(Iop_Sar32, 8738 binop(Iop_Add32, 8739 mkexpr(t4), 8740 binop(Iop_Shl32, 8741 mkU32(0x1), 8742 mkexpr(t8))), 8743 unop(Iop_32to8, mkexpr(t9))))); 8744 8745 assign(t6, unop(Iop_8Sto32, 8746 unop(Iop_16HIto8, 8747 unop(Iop_32HIto16, getIReg(rt))))); 8748 assign(t7, unop(Iop_32to8, 8749 binop(Iop_Sar32, 8750 binop(Iop_Add32, 8751 mkexpr(t6), 8752 binop(Iop_Shl32, 8753 mkU32(0x1), 8754 mkexpr(t8))), 8755 unop(Iop_32to8, mkexpr(t9))))); 8756 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8757 mkexpr(t9), 8758 mkU32(0x0)), 8759 getIReg(rt), 8760 binop(Iop_16HLto32, 8761 binop(Iop_8HLto16, 8762 mkexpr(t7), 8763 mkexpr(t5)), 8764 binop(Iop_8HLto16, 8765 mkexpr(t3), 8766 mkexpr(t1))))); 8767 break; 8768 } 8769 case 0x8: { /* SHLL.PH */ 8770 DIP("shll.ph r%u, r%u, %u", rd, rt, rs); 8771 vassert(!mode64); 8772 t0 = newTemp(Ity_I32); 8773 t1 = newTemp(Ity_I32); 8774 t2 = newTemp(Ity_I32); 8775 t3 = newTemp(Ity_I32); 8776 t4 = newTemp(Ity_I32); 8777 t5 = newTemp(Ity_I32); 8778 t6 = newTemp(Ity_I32); 8779 t7 = newTemp(Ity_I32); 8780 8781 if (0 == rs) { 8782 putIReg(rd, getIReg(rt)); 8783 } else { 8784 /* Shift lower 16 bits. */ 8785 assign(t0, binop(Iop_Shl32, 8786 unop(Iop_16Sto32, 8787 unop(Iop_32to16, getIReg(rt))), 8788 mkU8(rs))); 8789 8790 assign(t1, unop(Iop_1Uto32, 8791 binop(Iop_CmpNE32, 8792 binop(Iop_Sar32, 8793 mkexpr(t0), 8794 mkU8(16)), 8795 mkU32(0)))); 8796 assign(t2, unop(Iop_1Uto32, 8797 binop(Iop_CmpNE32, 8798 binop(Iop_Sar32, 8799 mkexpr(t0), 8800 mkU8(16)), 8801 mkU32(0xffffffff)))); 8802 assign(t3, binop(Iop_And32, 8803 mkexpr(t1), 8804 mkexpr(t2))); 8805 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8806 mkexpr(t3), 8807 mkU32(0x1)), 8808 binop(Iop_Or32, 8809 getDSPControl(), 8810 mkU32(0x400000)), 8811 getDSPControl())); 8812 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8813 binop(Iop_And32, 8814 getIReg(rt), 8815 mkU32(0x00008000)), 8816 binop(Iop_And32, 8817 mkexpr(t0), 8818 mkU32(0x00008000)) 8819 ), 8820 getDSPControl(), 8821 binop(Iop_Or32, 8822 getDSPControl(), 8823 mkU32(0x400000)))); 8824 /* Shift higher 16 bits. */ 8825 assign(t4, binop(Iop_Shl32, 8826 unop(Iop_16Sto32, 8827 unop(Iop_32HIto16, getIReg(rt))), 8828 mkU8(rs))); 8829 8830 assign(t5, unop(Iop_1Uto32, 8831 binop(Iop_CmpNE32, 8832 binop(Iop_Sar32, 8833 mkexpr(t4), 8834 mkU8(16)), 8835 mkU32(0)))); 8836 assign(t6, unop(Iop_1Uto32, 8837 binop(Iop_CmpNE32, 8838 binop(Iop_Sar32, 8839 mkexpr(t4), 8840 mkU8(16)), 8841 mkU32(0xffffffff)))); 8842 assign(t7, binop(Iop_And32, 8843 mkexpr(t5), 8844 mkexpr(t6))); 8845 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8846 mkexpr(t7), 8847 mkU32(0x1)), 8848 binop(Iop_Or32, 8849 getDSPControl(), 8850 mkU32(0x400000)), 8851 getDSPControl())); 8852 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8853 mkexpr(t7), 8854 mkU32(0x1)), 8855 binop(Iop_Or32, 8856 getDSPControl(), 8857 mkU32(0x400000)), 8858 getDSPControl())); 8859 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8860 binop(Iop_And32, 8861 getIReg(rt), 8862 mkU32(0x80000000)), 8863 binop(Iop_Shl32, 8864 binop(Iop_And32, 8865 mkexpr(t4), 8866 mkU32(0x00008000)), 8867 mkU8(16)) 8868 ), 8869 getDSPControl(), 8870 binop(Iop_Or32, 8871 getDSPControl(), 8872 mkU32(0x400000)))); 8873 putIReg(rd, binop(Iop_16HLto32, 8874 unop(Iop_32to16, mkexpr(t4)), 8875 unop(Iop_32to16, mkexpr(t0)))); 8876 } 8877 break; 8878 } 8879 case 0x9: { /* SHRA.PH */ 8880 DIP("shra.ph r%u, r%u, %u", rd, rt, rs); 8881 vassert(!mode64); 8882 t0 = newTemp(Ity_I32); 8883 t1 = newTemp(Ity_I32); 8884 if (0 == rs) { 8885 putIReg(rd, getIReg(rt)); 8886 } else { 8887 assign(t0, binop(Iop_Sar32, 8888 unop(Iop_16Sto32, 8889 unop(Iop_32to16, getIReg(rt))), 8890 mkU8(rs))); 8891 assign(t1, binop(Iop_Sar32, 8892 unop(Iop_16Sto32, 8893 unop(Iop_32HIto16, getIReg(rt))), 8894 mkU8(rs))); 8895 putIReg(rd, binop(Iop_16HLto32, 8896 unop(Iop_32to16, mkexpr(t1)), 8897 unop(Iop_32to16, mkexpr(t0)))); 8898 } 8899 break; 8900 } 8901 case 0xA: { /* SHLLV.PH */ 8902 DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs); 8903 vassert(!mode64); 8904 t0 = newTemp(Ity_I32); 8905 t2 = newTemp(Ity_I32); 8906 t3 = newTemp(Ity_I1); 8907 t4 = newTemp(Ity_I1); 8908 t5 = newTemp(Ity_I32); 8909 t6 = newTemp(Ity_I32); 8910 t7 = newTemp(Ity_I1); 8911 t8 = newTemp(Ity_I1); 8912 t9 = newTemp(Ity_I32); 8913