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 t10 = newTemp(Ity_I32); 8914 t11 = newTemp(Ity_I32); 8915 t12 = newTemp(Ity_I1); 8916 t13 = newTemp(Ity_I1); 8917 8918 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 8919 8920 /* Shift lower 16 bits. */ 8921 assign(t2, binop(Iop_Shl32, 8922 unop(Iop_16Sto32, 8923 unop(Iop_32to16, getIReg(rt))), 8924 unop(Iop_32to8, mkexpr(t0)))); 8925 8926 assign(t3, binop(Iop_CmpNE32, 8927 unop(Iop_16Sto32, 8928 unop(Iop_32HIto16, mkexpr(t2))), 8929 mkU32(0x00000000))); 8930 assign(t4, binop(Iop_CmpNE32, 8931 unop(Iop_16Sto32, 8932 unop(Iop_32HIto16, mkexpr(t2))), 8933 mkU32(0xffffffff))); 8934 assign(t10, binop(Iop_And32, 8935 unop(Iop_1Sto32, mkexpr(t3)), 8936 unop(Iop_1Sto32, mkexpr(t4)))); 8937 assign(t5, binop(Iop_Shr32, 8938 binop(Iop_And32, 8939 getIReg(rt), 8940 mkU32(0x00008000)), 8941 mkU8(15))); 8942 assign(t12, binop(Iop_CmpEQ32, 8943 mkexpr(t5), 8944 binop(Iop_Shr32, 8945 binop(Iop_And32, 8946 mkexpr(t2), 8947 mkU32(0x00008000)), 8948 mkU8(15)))); 8949 8950 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8951 mkexpr(t10), 8952 mkU32(0x0)), 8953 binop(Iop_Or32, 8954 getDSPControl(), 8955 mkU32(0x400000)), 8956 IRExpr_ITE(mkexpr(t12), 8957 getDSPControl(), 8958 binop(Iop_Or32, 8959 getDSPControl(), 8960 mkU32(0x400000))) 8961 )); 8962 /* Shift higher 16 bits. */ 8963 assign(t6, binop(Iop_Shl32, 8964 unop(Iop_16Sto32, 8965 unop(Iop_32HIto16, getIReg(rt))), 8966 unop(Iop_32to8, mkexpr(t0)))); 8967 8968 assign(t7, binop(Iop_CmpNE32, 8969 unop(Iop_16Sto32, 8970 unop(Iop_32HIto16, mkexpr(t6))), 8971 mkU32(0x00000000))); 8972 assign(t8, binop(Iop_CmpNE32, 8973 unop(Iop_16Sto32, 8974 unop(Iop_32HIto16, mkexpr(t6))), 8975 mkU32(0xffffffff))); 8976 assign(t11, binop(Iop_And32, 8977 unop(Iop_1Sto32, mkexpr(t7)), 8978 unop(Iop_1Sto32, mkexpr(t8)))); 8979 8980 assign(t9, binop(Iop_Shr32, 8981 binop(Iop_And32, 8982 getIReg(rt), 8983 mkU32(0x80000000)), 8984 mkU8(31))); 8985 assign(t13, binop(Iop_CmpEQ32, 8986 mkexpr(t9), 8987 binop(Iop_Shr32, 8988 binop(Iop_And32, 8989 mkexpr(t6), 8990 mkU32(0x00008000)), 8991 mkU8(15)))); 8992 8993 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8994 mkexpr(t11), 8995 mkU32(0x0)), 8996 binop(Iop_Or32, 8997 getDSPControl(), 8998 mkU32(0x400000)), 8999 IRExpr_ITE(mkexpr(t13), 9000 getDSPControl(), 9001 binop(Iop_Or32, 9002 getDSPControl(), 9003 mkU32(0x400000))) 9004 )); 9005 9006 putIReg(rd, binop(Iop_16HLto32, 9007 unop(Iop_32to16, mkexpr(t6)), 9008 unop(Iop_32to16, mkexpr(t2)))); 9009 break; 9010 } 9011 case 0xB: { /* SHRAV.PH */ 9012 DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs); 9013 vassert(!mode64); 9014 t0 = newTemp(Ity_I32); 9015 t1 = newTemp(Ity_I1); 9016 t2 = newTemp(Ity_I32); 9017 t3 = newTemp(Ity_I32); 9018 9019 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9020 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9021 assign(t2, binop(Iop_Sar32, 9022 unop(Iop_16Sto32, 9023 unop(Iop_32to16, getIReg(rt))), 9024 unop(Iop_32to8, mkexpr(t0)))); 9025 assign(t3, binop(Iop_Sar32, 9026 unop(Iop_16Sto32, 9027 unop(Iop_32HIto16, getIReg(rt))), 9028 unop(Iop_32to8, mkexpr(t0)))); 9029 putIReg(rd, 9030 binop(Iop_16HLto32, 9031 IRExpr_ITE(mkexpr(t1), 9032 unop(Iop_32HIto16, getIReg(rt)), 9033 unop(Iop_32to16, mkexpr(t3))), 9034 IRExpr_ITE(mkexpr(t1), 9035 unop(Iop_32to16, getIReg(rt)), 9036 unop(Iop_32to16, mkexpr(t2))))); 9037 break; 9038 } 9039 case 0xC: { /* SHLL_S.PH */ 9040 DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs); 9041 vassert(!mode64); 9042 t0 = newTemp(Ity_I32); 9043 t1 = newTemp(Ity_I32); 9044 t2 = newTemp(Ity_I32); 9045 t3 = newTemp(Ity_I32); 9046 t4 = newTemp(Ity_I32); 9047 t5 = newTemp(Ity_I32); 9048 t6 = newTemp(Ity_I32); 9049 t7 = newTemp(Ity_I32); 9050 t8 = newTemp(Ity_I32); 9051 t9 = newTemp(Ity_I32); 9052 t10 = newTemp(Ity_I32); 9053 t11 = newTemp(Ity_I32); 9054 t12 = newTemp(Ity_I32); 9055 t13 = newTemp(Ity_I32); 9056 t14 = newTemp(Ity_I32); 9057 9058 if (0 == rs) { 9059 putIReg(rd, getIReg(rt)); 9060 } else { 9061 /* Shift lower 16 bits. */ 9062 assign(t0, binop(Iop_Shl32, 9063 unop(Iop_16Sto32, 9064 unop(Iop_32to16, getIReg(rt))), 9065 mkU8(rs))); 9066 9067 assign(t1, unop(Iop_1Uto32, 9068 binop(Iop_CmpNE32, 9069 binop(Iop_Sar32, 9070 mkexpr(t0), 9071 mkU8(16)), 9072 mkU32(0)))); 9073 assign(t2, unop(Iop_1Uto32, 9074 binop(Iop_CmpNE32, 9075 binop(Iop_Sar32, 9076 mkexpr(t0), 9077 mkU8(16)), 9078 mkU32(0xffffffff)))); 9079 assign(t3, binop(Iop_And32, 9080 mkexpr(t1), 9081 mkexpr(t2))); 9082 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9083 mkexpr(t3), 9084 mkU32(0x1)), 9085 binop(Iop_Or32, 9086 getDSPControl(), 9087 mkU32(0x400000)), 9088 getDSPControl())); 9089 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9090 binop(Iop_And32, 9091 getIReg(rt), 9092 mkU32(0x00008000)), 9093 binop(Iop_And32, 9094 mkexpr(t0), 9095 mkU32(0x00008000)) 9096 ), 9097 getDSPControl(), 9098 binop(Iop_Or32, 9099 getDSPControl(), 9100 mkU32(0x400000)))); 9101 assign(t8, 9102 IRExpr_ITE(binop(Iop_CmpEQ32, 9103 mkexpr(t3), 9104 mkU32(0x1)), 9105 IRExpr_ITE(binop(Iop_CmpEQ32, 9106 binop(Iop_And32, 9107 getIReg(rt), 9108 mkU32(0x8000)), 9109 mkU32(0)), 9110 mkU32(0x00007fff), 9111 mkU32(0x00008000)), 9112 binop(Iop_And32, 9113 mkexpr(t0), 9114 mkU32(0x0000ffff)))); 9115 assign(t10, 9116 IRExpr_ITE(binop(Iop_CmpEQ32, 9117 binop(Iop_And32, 9118 getIReg(rt), 9119 mkU32(0x00008000)), 9120 binop(Iop_And32, 9121 mkexpr(t0), 9122 mkU32(0x00008000))), 9123 mkexpr(t8), 9124 IRExpr_ITE(binop(Iop_CmpEQ32, 9125 binop(Iop_And32, 9126 getIReg(rt), 9127 mkU32(0x8000)), 9128 mkU32(0)), 9129 mkU32(0x00007fff), 9130 mkU32(0x00008000)))); 9131 /* Shift higher 16 bits. */ 9132 assign(t4, binop(Iop_Shl32, 9133 unop(Iop_16Sto32, 9134 unop(Iop_32HIto16, getIReg(rt))), 9135 mkU8(rs))); 9136 9137 assign(t5, unop(Iop_1Uto32, 9138 binop(Iop_CmpNE32, 9139 binop(Iop_Sar32, 9140 mkexpr(t4), 9141 mkU8(16)), 9142 mkU32(0)))); 9143 assign(t6, unop(Iop_1Uto32, 9144 binop(Iop_CmpNE32, 9145 binop(Iop_Sar32, 9146 mkexpr(t4), 9147 mkU8(16)), 9148 mkU32(0xffffffff)))); 9149 assign(t7, binop(Iop_And32, 9150 mkexpr(t5), 9151 mkexpr(t6))); 9152 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9153 mkexpr(t7), 9154 mkU32(0x1)), 9155 binop(Iop_Or32, 9156 getDSPControl(), 9157 mkU32(0x400000)), 9158 getDSPControl())); 9159 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9160 mkexpr(t7), 9161 mkU32(0x1)), 9162 binop(Iop_Or32, 9163 getDSPControl(), 9164 mkU32(0x400000)), 9165 getDSPControl())); 9166 assign(t12, binop(Iop_Shl32, 9167 binop(Iop_And32, 9168 mkexpr(t4), 9169 mkU32(0x8000)), 9170 mkU8(16))); 9171 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9172 binop(Iop_And32, 9173 getIReg(rt), 9174 mkU32(0x80000000)), 9175 mkexpr(t12)), 9176 getDSPControl(), 9177 binop(Iop_Or32, 9178 getDSPControl(), 9179 mkU32(0x400000)))); 9180 assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32, 9181 binop(Iop_And32, 9182 getIReg(rt), 9183 mkU32(0x80000000)), 9184 mkU32(0)), 9185 mkU32(0x7fff0000), 9186 mkU32(0x80000000))); 9187 assign(t9, 9188 IRExpr_ITE(binop(Iop_CmpEQ32, 9189 mkexpr(t7), 9190 mkU32(0x1)), 9191 mkexpr(t13), 9192 binop(Iop_Shl32, 9193 binop(Iop_And32, 9194 mkexpr(t4), 9195 mkU32(0x0000ffff)), 9196 mkU8(16)))); 9197 assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32, 9198 binop(Iop_And32, 9199 getIReg(rt), 9200 mkU32(0x80000000)), 9201 mkU32(0)), 9202 mkU32(0x7fff0000), 9203 mkU32(0x80000000))); 9204 assign(t11, 9205 IRExpr_ITE(binop(Iop_CmpEQ32, 9206 binop(Iop_And32, 9207 getIReg(rt), 9208 mkU32(0x80000000)), 9209 binop(Iop_Shl32, 9210 binop(Iop_And32, 9211 mkexpr(t4), 9212 mkU32(0x00008000)), 9213 mkU8(16))), 9214 mkexpr(t9), 9215 mkexpr(t14))); 9216 putIReg(rd, binop(Iop_Or32, 9217 mkexpr(t10), 9218 mkexpr(t11))); 9219 } 9220 break; 9221 } 9222 case 0xD: { /* SHRA_R.PH */ 9223 DIP("shra.ph r%u, r%u, %u", rd, rt, rs); 9224 vassert(!mode64); 9225 t0 = newTemp(Ity_I32); 9226 t1 = newTemp(Ity_I32); 9227 if (0 == rs) { 9228 putIReg(rd, getIReg(rt)); 9229 } else { 9230 assign(t0, binop(Iop_Sar32, 9231 binop(Iop_Add32, 9232 unop(Iop_16Sto32, 9233 unop(Iop_32to16, 9234 getIReg(rt))), 9235 binop(Iop_Shl32, 9236 mkU32(0x1), 9237 mkU8(rs-1))), 9238 mkU8(rs))); 9239 assign(t1, binop(Iop_Sar32, 9240 binop(Iop_Add32, 9241 unop(Iop_16Sto32, 9242 unop(Iop_32HIto16, 9243 getIReg(rt))), 9244 binop(Iop_Shl32, 9245 mkU32(0x1), 9246 mkU8(rs-1))), 9247 mkU8(rs))); 9248 putIReg(rd, binop(Iop_16HLto32, 9249 unop(Iop_32to16, mkexpr(t1)), 9250 unop(Iop_32to16, mkexpr(t0)))); 9251 } 9252 break; 9253 } 9254 case 0xE: { /* SHLLV_S.PH */ 9255 DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs); 9256 vassert(!mode64); 9257 t0 = newTemp(Ity_I32); 9258 t2 = newTemp(Ity_I32); 9259 t3 = newTemp(Ity_I1); 9260 t4 = newTemp(Ity_I1); 9261 t5 = newTemp(Ity_I32); 9262 t6 = newTemp(Ity_I32); 9263 t7 = newTemp(Ity_I1); 9264 t8 = newTemp(Ity_I1); 9265 t9 = newTemp(Ity_I32); 9266 t10 = newTemp(Ity_I32); 9267 t11 = newTemp(Ity_I32); 9268 t12 = newTemp(Ity_I1); 9269 t13 = newTemp(Ity_I1); 9270 t14 = newTemp(Ity_I16); 9271 t15 = newTemp(Ity_I16); 9272 t16 = newTemp(Ity_I16); 9273 t17 = newTemp(Ity_I16); 9274 9275 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9276 9277 /* Shift lower 16 bits. */ 9278 assign(t2, binop(Iop_Shl32, 9279 unop(Iop_16Sto32, 9280 unop(Iop_32to16, getIReg(rt))), 9281 unop(Iop_32to8, mkexpr(t0)))); 9282 9283 assign(t3, binop(Iop_CmpNE32, 9284 unop(Iop_16Sto32, 9285 unop(Iop_32HIto16, mkexpr(t2))), 9286 mkU32(0x00000000))); 9287 assign(t4, binop(Iop_CmpNE32, 9288 unop(Iop_16Sto32, 9289 unop(Iop_32HIto16, mkexpr(t2))), 9290 mkU32(0xffffffff))); 9291 assign(t10, binop(Iop_And32, 9292 unop(Iop_1Sto32, mkexpr(t3)), 9293 unop(Iop_1Sto32, mkexpr(t4)))); 9294 assign(t5, binop(Iop_Shr32, 9295 binop(Iop_And32, 9296 getIReg(rt), 9297 mkU32(0x00008000)), 9298 mkU8(15))); 9299 assign(t12, binop(Iop_CmpEQ32, 9300 mkexpr(t5), 9301 binop(Iop_Shr32, 9302 binop(Iop_And32, 9303 mkexpr(t2), 9304 mkU32(0x00008000)), 9305 mkU8(15)))); 9306 9307 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9308 mkexpr(t10), 9309 mkU32(0x0)), 9310 binop(Iop_Or32, 9311 getDSPControl(), 9312 mkU32(0x400000)), 9313 IRExpr_ITE(mkexpr(t12), 9314 getDSPControl(), 9315 binop(Iop_Or32, 9316 getDSPControl(), 9317 mkU32(0x400000))) 9318 )); 9319 assign(t14, IRExpr_ITE(binop(Iop_CmpNE32, 9320 mkexpr(t5), 9321 mkU32(0x0)), 9322 mkU16(0x8000), 9323 mkU16(0x7fff))); 9324 assign(t15, IRExpr_ITE(binop(Iop_CmpNE32, 9325 mkexpr(t10), 9326 mkU32(0x0)), 9327 mkexpr(t14), 9328 IRExpr_ITE(mkexpr(t12), 9329 unop(Iop_32to16, 9330 mkexpr(t2)), 9331 mkexpr(t14)))); 9332 /* Shift higher 16 bits. */ 9333 assign(t6, binop(Iop_Shl32, 9334 unop(Iop_16Sto32, 9335 unop(Iop_32HIto16, getIReg(rt))), 9336 unop(Iop_32to8, mkexpr(t0)))); 9337 9338 assign(t7, binop(Iop_CmpNE32, 9339 unop(Iop_16Sto32, 9340 unop(Iop_32HIto16, mkexpr(t6))), 9341 mkU32(0x00000000))); 9342 assign(t8, binop(Iop_CmpNE32, 9343 unop(Iop_16Sto32, 9344 unop(Iop_32HIto16, mkexpr(t6))), 9345 mkU32(0xffffffff))); 9346 assign(t11, binop(Iop_And32, 9347 unop(Iop_1Sto32, mkexpr(t7)), 9348 unop(Iop_1Sto32, mkexpr(t8)))); 9349 9350 assign(t9, binop(Iop_Shr32, 9351 binop(Iop_And32, 9352 getIReg(rt), 9353 mkU32(0x80000000)), 9354 mkU8(31))); 9355 assign(t13, binop(Iop_CmpEQ32, 9356 mkexpr(t9), 9357 binop(Iop_Shr32, 9358 binop(Iop_And32, 9359 mkexpr(t6), 9360 mkU32(0x00008000)), 9361 mkU8(15)))); 9362 9363 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9364 mkexpr(t11), 9365 mkU32(0x0)), 9366 binop(Iop_Or32, 9367 getDSPControl(), 9368 mkU32(0x400000)), 9369 IRExpr_ITE(mkexpr(t13), 9370 getDSPControl(), 9371 binop(Iop_Or32, 9372 getDSPControl(), 9373 mkU32(0x400000))) 9374 )); 9375 9376 assign(t16, IRExpr_ITE(binop(Iop_CmpNE32, 9377 mkexpr(t9), 9378 mkU32(0x0)), 9379 mkU16(0x8000), 9380 mkU16(0x7fff))); 9381 assign(t17, IRExpr_ITE(binop(Iop_CmpNE32, 9382 mkexpr(t11), 9383 mkU32(0x0)), 9384 mkexpr(t16), 9385 IRExpr_ITE(mkexpr(t13), 9386 unop(Iop_32to16, 9387 mkexpr(t6)), 9388 mkexpr(t16)))); 9389 9390 putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15))); 9391 break; 9392 } 9393 case 0xF: { /* SHRAV_R.PH */ 9394 DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs); 9395 vassert(!mode64); 9396 t0 = newTemp(Ity_I32); 9397 t1 = newTemp(Ity_I1); 9398 t2 = newTemp(Ity_I8); 9399 t3 = newTemp(Ity_I32); 9400 t4 = newTemp(Ity_I32); 9401 9402 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9403 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9404 assign(t2, unop(Iop_32to8, 9405 binop(Iop_Sub32, mkexpr(t0), mkU32(1)))); 9406 9407 assign(t3, binop(Iop_Sar32, 9408 binop(Iop_Add32, 9409 unop(Iop_16Sto32, 9410 unop(Iop_32to16, getIReg(rt))), 9411 binop(Iop_Shl32, 9412 mkU32(0x1), 9413 mkexpr(t2))), 9414 unop(Iop_32to8, mkexpr(t0)))); 9415 assign(t4, binop(Iop_Sar32, 9416 binop(Iop_Add32, 9417 unop(Iop_16Sto32, 9418 unop(Iop_32HIto16, 9419 getIReg(rt))), 9420 binop(Iop_Shl32, 9421 mkU32(0x1), 9422 mkexpr(t2))), 9423 unop(Iop_32to8, mkexpr(t0)))); 9424 9425 putIReg(rd, binop(Iop_16HLto32, 9426 IRExpr_ITE(mkexpr(t1), 9427 unop(Iop_32HIto16, 9428 getIReg(rt)), 9429 unop(Iop_32to16, 9430 mkexpr(t4))), 9431 IRExpr_ITE(mkexpr(t1), 9432 unop(Iop_32to16, getIReg(rt)), 9433 unop(Iop_32to16, 9434 mkexpr(t3))))); 9435 break; 9436 } 9437 case 0x14: { /* SHLL_S.W */ 9438 DIP("shll_s.w r%u, r%u, %u", rd, rt, rs); 9439 vassert(!mode64); 9440 t0 = newTemp(Ity_I32); 9441 t1 = newTemp(Ity_I32); 9442 t2 = newTemp(Ity_I32); 9443 t3 = newTemp(Ity_I32); 9444 t4 = newTemp(Ity_I32); 9445 t5 = newTemp(Ity_I32); 9446 9447 if (0 == rs) { 9448 putIReg(rd, getIReg(rt)); 9449 } else { 9450 /* t0-bits that will be discarded, sign extended to 9451 32bits. */ 9452 assign(t0, binop(Iop_Sar32, 9453 binop(Iop_And32, 9454 getIReg(rt), 9455 binop(Iop_Sar32, 9456 mkU32(0x80000000), 9457 mkU8(rs-1))), 9458 mkU8(32-rs))); 9459 9460 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32, 9461 binop(Iop_And32, 9462 getIReg(rt), 9463 mkU32(0x80000000)), 9464 mkU32(0x0)), 9465 mkU32(0x7fffffff), 9466 mkU32(0x80000000))); 9467 9468 assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs))); 9469 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32, 9470 binop(Iop_And32, 9471 getIReg(rt), 9472 mkU32(0x80000000)), 9473 binop(Iop_And32, 9474 mkexpr(t2), 9475 mkU32(0x80000000))), 9476 mkexpr(t2), 9477 mkexpr(t1))); 9478 9479 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 9480 mkexpr(t0), 9481 mkU32(0x0)), 9482 IRExpr_ITE(binop(Iop_CmpNE32, 9483 mkexpr(t0), 9484 mkU32(0xffffffff) 9485 ), 9486 mkexpr(t1), 9487 mkexpr(t3)), 9488 mkexpr(t3))); 9489 assign(t5, IRExpr_ITE(binop(Iop_CmpNE32, 9490 mkexpr(t0), 9491 mkU32(0xffffffff)), 9492 binop(Iop_Or32, 9493 getDSPControl(), 9494 mkU32(0x400000)), 9495 getDSPControl())); 9496 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9497 mkexpr(t0), 9498 mkU32(0x0)), 9499 mkexpr(t5), 9500 getDSPControl())); 9501 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9502 binop(Iop_And32, 9503 getIReg(rt), 9504 mkU32(0x80000000)), 9505 binop(Iop_And32, 9506 mkexpr(t2), 9507 mkU32(0x80000000)) 9508 ), 9509 getDSPControl(), 9510 binop(Iop_Or32, 9511 getDSPControl(), 9512 mkU32(0x400000)))); 9513 putIReg(rd, mkexpr(t4)); 9514 } 9515 break; 9516 } 9517 case 0x15: { /* SHRA_R.W */ 9518 DIP("shra_r.w r%u, r%u, %u", rd, rt, rs); 9519 vassert(!mode64); 9520 if (0 == rs) { 9521 putIReg(rd, getIReg(rt)); 9522 } else { 9523 putIReg(rd, binop(Iop_Add32, 9524 binop(Iop_Sar32, 9525 getIReg(rt), mkU8(rs)), 9526 binop(Iop_Shr32, 9527 binop(Iop_And32, 9528 getIReg(rt), 9529 binop(Iop_Shl32, 9530 mkU32(0x1), 9531 mkU8(rs-1))), 9532 mkU8(rs-1)))); 9533 } 9534 break; 9535 } 9536 case 0x16: { /* SHLLV_S.W */ 9537 DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs); 9538 vassert(!mode64); 9539 t0 = newTemp(Ity_I32); 9540 t1 = newTemp(Ity_I1); 9541 t2 = newTemp(Ity_I32); 9542 t3 = newTemp(Ity_I64); 9543 t4 = newTemp(Ity_I1); 9544 t5 = newTemp(Ity_I1); 9545 t6 = newTemp(Ity_I32); 9546 t7 = newTemp(Ity_I1); 9547 t8 = newTemp(Ity_I32); 9548 9549 /* Check if shift amount is zero. */ 9550 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 9551 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9552 9553 /* t2 = sign of the input value. */ 9554 assign(t2, binop(Iop_Shr32, 9555 binop(Iop_And32, 9556 getIReg(rt), 9557 mkU32(0x80000000)), 9558 mkU8(31))); 9559 /* Shift left input value and check for overflow. */ 9560 assign(t3, binop(Iop_Shl64, 9561 unop(Iop_32Sto64, getIReg(rt)), 9562 unop(Iop_32to8, mkexpr(t0)))); 9563 assign(t4, binop(Iop_CmpNE32, 9564 unop(Iop_64HIto32, mkexpr(t3)), 9565 mkU32(0x00000000))); 9566 assign(t5, binop(Iop_CmpNE32, 9567 unop(Iop_64HIto32, mkexpr(t3)), 9568 mkU32(0xffffffff))); 9569 assign(t6, binop(Iop_And32, 9570 unop(Iop_1Uto32, mkexpr(t4)), 9571 unop(Iop_1Uto32, mkexpr(t5)))); 9572 assign(t7, binop(Iop_CmpEQ32, 9573 binop(Iop_Shr32, 9574 binop(Iop_And32, 9575 getIReg(rt), 9576 mkU32(0x80000000)), 9577 mkU8(31)), 9578 binop(Iop_Shr32, 9579 binop(Iop_And32, 9580 unop(Iop_64to32, mkexpr(t3)), 9581 mkU32(0x80000000)), 9582 mkU8(31)))); 9583 9584 putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)), 9585 binop(Iop_Or32, 9586 getDSPControl(), 9587 mkU32(0x400000)), 9588 IRExpr_ITE(mkexpr(t7), 9589 getDSPControl(), 9590 binop(Iop_Or32, 9591 getDSPControl(), 9592 mkU32(0x400000))) 9593 )); 9594 9595 assign(t8, IRExpr_ITE(unop(Iop_32to1, 9596 mkexpr(t2)), 9597 mkU32(0x80000000), 9598 mkU32(0x7fffffff))); 9599 putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)), 9600 IRExpr_ITE(unop(Iop_32to1, 9601 mkexpr(t2)), 9602 mkU32(0x80000000), 9603 mkU32(0x7fffffff)), 9604 IRExpr_ITE(mkexpr(t7), 9605 unop(Iop_64to32, 9606 mkexpr(t3)), 9607 mkexpr(t8)))); 9608 break; 9609 } 9610 case 0x17: { /* SHRAV_R.W */ 9611 DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs); 9612 vassert(!mode64); 9613 t0 = newTemp(Ity_I32); 9614 t1 = newTemp(Ity_I1); 9615 t2 = newTemp(Ity_I8); 9616 t3 = newTemp(Ity_I32); 9617 9618 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 9619 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9620 assign(t2, unop(Iop_32to8, 9621 binop(Iop_Sub32, mkexpr(t0), mkU32(1)))); 9622 9623 putIReg(rd, IRExpr_ITE(mkexpr(t1), 9624 getIReg(rt), 9625 binop(Iop_Sar32, 9626 binop(Iop_Add32, 9627 binop(Iop_Sar32, 9628 getIReg(rt), 9629 mkexpr(t2)), 9630 mkU32(0x1)), 9631 mkU8(1)))); 9632 break; 9633 } 9634 case 0x19: { /* SHRL.PH */ 9635 DIP("shrl.ph r%u, r%u, %u", rd, rt, rs); 9636 vassert(!mode64); 9637 t0 = newTemp(Ity_I32); 9638 t1 = newTemp(Ity_I32); 9639 assign(t0, binop(Iop_Shr32, 9640 unop(Iop_16Uto32, 9641 unop(Iop_32to16, getIReg(rt))), 9642 mkU8(rs))); 9643 assign(t1, binop(Iop_Shr32, 9644 unop(Iop_16Uto32, 9645 unop(Iop_32HIto16, getIReg(rt))), 9646 mkU8(rs))); 9647 putIReg(rd, binop(Iop_16HLto32, 9648 unop(Iop_32to16, mkexpr(t1)), 9649 unop(Iop_32to16, mkexpr(t0)))); 9650 break; 9651 } 9652 case 0x1B: { /* SHRLV.PH */ 9653 DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs); 9654 vassert(!mode64); 9655 t0 = newTemp(Ity_I32); 9656 t1 = newTemp(Ity_I1); 9657 t2 = newTemp(Ity_I32); 9658 t3 = newTemp(Ity_I32); 9659 t4 = newTemp(Ity_I16); 9660 t5 = newTemp(Ity_I16); 9661 9662 /* Get shift amount from lower 5 bits of rs 9663 and check if it is zero. */ 9664 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9665 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9666 9667 assign(t2, binop(Iop_Shr32, 9668 unop(Iop_16Uto32, 9669 unop(Iop_32to16, getIReg(rt))), 9670 unop(Iop_32to8, mkexpr(t0)))); 9671 assign(t3, binop(Iop_Shr32, 9672 unop(Iop_16Uto32, 9673 unop(Iop_32HIto16, getIReg(rt))), 9674 unop(Iop_32to8, mkexpr(t0)))); 9675 9676 assign(t4, IRExpr_ITE(mkexpr(t1), 9677 unop(Iop_32HIto16, getIReg(rt)), 9678 unop(Iop_32to16, mkexpr(t3)))); 9679 assign(t5, IRExpr_ITE(mkexpr(t1), 9680 unop(Iop_32to16, getIReg(rt)), 9681 unop(Iop_32to16, mkexpr(t2)))); 9682 putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5))); 9683 break; 9684 } 9685 default: 9686 return -1; 9687 } 9688 break; /* end of SHLL.QB */ 9689 } 9690 case 0x18: { /* ADDUH.QB/MUL.PH */ 9691 switch(sa) { 9692 case 0x00: { /* ADDUH.QB */ 9693 DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt); 9694 vassert(!mode64); 9695 t0 = newTemp(Ity_I32); 9696 9697 assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt))); 9698 9699 putIReg(rd, mkexpr(t0)); 9700 break; 9701 } 9702 case 0x1: { /* SUBUH.QB */ 9703 DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt); 9704 vassert(!mode64); 9705 t0 = newTemp(Ity_I32); 9706 9707 assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt))); 9708 9709 putIReg(rd, mkexpr(t0)); 9710 break; 9711 } 9712 case 0x02: { /* ADDUH_R.QB */ 9713 DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt); 9714 vassert(!mode64); 9715 t0 = newTemp(Ity_I32); 9716 t1 = newTemp(Ity_I32); 9717 t2 = newTemp(Ity_I8); 9718 t3 = newTemp(Ity_I32); 9719 t4 = newTemp(Ity_I32); 9720 t5 = newTemp(Ity_I8); 9721 t6 = newTemp(Ity_I32); 9722 t7 = newTemp(Ity_I32); 9723 t8 = newTemp(Ity_I8); 9724 t9 = newTemp(Ity_I32); 9725 t10 = newTemp(Ity_I32); 9726 t11 = newTemp(Ity_I8); 9727 9728 /* Extract input bytes, add values, add 1 and half the 9729 result. */ 9730 assign(t0, unop(Iop_8Uto32, 9731 unop(Iop_16to8, 9732 unop(Iop_32to16, getIReg(rs))))); 9733 assign(t1, unop(Iop_8Uto32, 9734 unop(Iop_16to8, 9735 unop(Iop_32to16, getIReg(rt))))); 9736 assign(t2, unop(Iop_16to8, 9737 unop(Iop_32to16, 9738 binop(Iop_Shr32, 9739 binop(Iop_Add32, 9740 binop(Iop_Add32, 9741 mkexpr(t0), 9742 mkexpr(t1)), 9743 mkU32(0x00000001)), 9744 mkU8(0x01))))); 9745 9746 assign(t3, unop(Iop_8Uto32, 9747 unop(Iop_16HIto8, 9748 unop(Iop_32to16, getIReg(rs))))); 9749 assign(t4, unop(Iop_8Uto32, 9750 unop(Iop_16HIto8, 9751 unop(Iop_32to16, getIReg(rt))))); 9752 assign(t5, unop(Iop_16to8, 9753 unop(Iop_32to16, 9754 binop(Iop_Shr32, 9755 binop(Iop_Add32, 9756 binop(Iop_Add32, 9757 mkexpr(t3), 9758 mkexpr(t4)), 9759 mkU32(0x00000001)), 9760 mkU8(0x01))))); 9761 9762 assign(t6, unop(Iop_8Uto32, 9763 unop(Iop_16to8, 9764 unop(Iop_32HIto16, getIReg(rs))))); 9765 assign(t7, unop(Iop_8Uto32, 9766 unop(Iop_16to8, 9767 unop(Iop_32HIto16, getIReg(rt))))); 9768 assign(t8, unop(Iop_16to8, 9769 unop(Iop_32to16, 9770 binop(Iop_Shr32, 9771 binop(Iop_Add32, 9772 binop(Iop_Add32, 9773 mkexpr(t7), 9774 mkexpr(t6)), 9775 mkU32(0x00000001)), 9776 mkU8(0x01))))); 9777 9778 assign(t9, unop(Iop_8Uto32, 9779 unop(Iop_16HIto8, 9780 unop(Iop_32HIto16, getIReg(rs))))); 9781 assign(t10, unop(Iop_8Uto32, 9782 unop(Iop_16HIto8, 9783 unop(Iop_32HIto16, getIReg(rt))))); 9784 assign(t11, unop(Iop_16to8, 9785 unop(Iop_32to16, 9786 binop(Iop_Shr32, 9787 binop(Iop_Add32, 9788 binop(Iop_Add32, 9789 mkexpr(t9), 9790 mkexpr(t10)), 9791 mkU32(0x00000001)), 9792 mkU8(0x01))))); 9793 9794 putIReg(rd, binop(Iop_16HLto32, 9795 binop(Iop_8HLto16, 9796 mkexpr(t11), mkexpr(t8)), 9797 binop(Iop_8HLto16, 9798 mkexpr(t5), mkexpr(t2)))); 9799 break; 9800 } 9801 case 0x3: { /* SUBUH_R.QB */ 9802 DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt); 9803 vassert(!mode64); 9804 t1 = newTemp(Ity_I32); 9805 t2 = newTemp(Ity_I32); 9806 t3 = newTemp(Ity_I32); 9807 t4 = newTemp(Ity_I32); 9808 t5 = newTemp(Ity_I32); 9809 t6 = newTemp(Ity_I32); 9810 t7 = newTemp(Ity_I32); 9811 t8 = newTemp(Ity_I32); 9812 t9 = newTemp(Ity_I8); 9813 t10 = newTemp(Ity_I8); 9814 t11 = newTemp(Ity_I8); 9815 t12 = newTemp(Ity_I8); 9816 9817 /* Extract each byte of rs and rt. */ 9818 assign(t1, unop(Iop_8Uto32, 9819 unop(Iop_16to8, 9820 unop(Iop_32to16, getIReg(rs))))); 9821 assign(t2, unop(Iop_8Uto32, 9822 unop(Iop_16HIto8, 9823 unop(Iop_32to16, getIReg(rs))))); 9824 assign(t3, unop(Iop_8Uto32, 9825 unop(Iop_16to8, 9826 unop(Iop_32HIto16, getIReg(rs))))); 9827 assign(t4, unop(Iop_8Uto32, 9828 unop(Iop_16HIto8, 9829 unop(Iop_32HIto16, getIReg(rs))))); 9830 9831 assign(t5, unop(Iop_8Uto32, 9832 unop(Iop_16to8, 9833 unop(Iop_32to16, getIReg(rt))))); 9834 assign(t6, unop(Iop_8Uto32, 9835 unop(Iop_16HIto8, 9836 unop(Iop_32to16, getIReg(rt))))); 9837 assign(t7, unop(Iop_8Uto32, 9838 unop(Iop_16to8, 9839 unop(Iop_32HIto16, getIReg(rt))))); 9840 assign(t8, unop(Iop_8Uto32, 9841 unop(Iop_16HIto8, 9842 unop(Iop_32HIto16, getIReg(rt))))); 9843 9844 /* Add 1 to each resulting byte and half the results. */ 9845 assign(t9, unop(Iop_16to8, 9846 unop(Iop_32to16, 9847 binop(Iop_Shr32, 9848 binop(Iop_Add32, 9849 binop(Iop_Sub32, 9850 mkexpr(t1), 9851 mkexpr(t5)), 9852 mkU32(0x00000001)), 9853 mkU8(0x01))))); 9854 assign(t10, unop(Iop_16to8, 9855 unop(Iop_32to16, 9856 binop(Iop_Shr32, 9857 binop(Iop_Add32, 9858 binop(Iop_Sub32, 9859 mkexpr(t2), 9860 mkexpr(t6)), 9861 mkU32(0x00000001)), 9862 mkU8(0x01))))); 9863 assign(t11, unop(Iop_16to8, 9864 unop(Iop_32to16, 9865 binop(Iop_Shr32, 9866 binop(Iop_Add32, 9867 binop(Iop_Sub32, 9868 mkexpr(t3), 9869 mkexpr(t7)), 9870 mkU32(0x00000001)), 9871 mkU8(0x01))))); 9872 assign(t12, unop(Iop_16to8, 9873 unop(Iop_32to16, 9874 binop(Iop_Shr32, 9875 binop(Iop_Add32, 9876 binop(Iop_Sub32, 9877 mkexpr(t4), 9878 mkexpr(t8)), 9879 mkU32(0x00000001)), 9880 mkU8(0x01))))); 9881 9882 putIReg(rd, binop(Iop_16HLto32, 9883 binop(Iop_8HLto16, 9884 mkexpr(t12), mkexpr(t11)), 9885 binop(Iop_8HLto16, 9886 mkexpr(t10), mkexpr(t9)))); 9887 break; 9888 } 9889 case 0x8: { /* ADDQH.PH */ 9890 DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt); 9891 vassert(!mode64); 9892 t0 = newTemp(Ity_I32); 9893 t1 = newTemp(Ity_I16); 9894 t2 = newTemp(Ity_I32); 9895 t3 = newTemp(Ity_I16); 9896 9897 /* Add lower halfs of rs and rt 9898 and right shift the result by 1. */ 9899 assign(t0, binop(Iop_Add32, 9900 unop(Iop_16Sto32, 9901 unop(Iop_32to16, getIReg(rs))), 9902 unop(Iop_16Sto32, 9903 unop(Iop_32to16, getIReg(rt))))); 9904 assign(t1, unop(Iop_32to16, 9905 binop(Iop_Shr32, 9906 binop(Iop_And32, 9907 mkexpr(t0), 9908 mkU32(0x0001fffe)), 9909 mkU8(0x1)))); 9910 /* Add higher halfs of rs and rt 9911 and right shift the result by 1. */ 9912 assign(t2, binop(Iop_Add32, 9913 unop(Iop_16Sto32, 9914 unop(Iop_32HIto16, getIReg(rs))), 9915 unop(Iop_16Sto32, 9916 unop(Iop_32HIto16, getIReg(rt))))); 9917 assign(t3, unop(Iop_32to16, 9918 binop(Iop_Shr32, 9919 binop(Iop_And32, 9920 mkexpr(t2), 9921 mkU32(0x0001fffe)), 9922 mkU8(0x1)))); 9923 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 9924 break; 9925 } 9926 case 0x9: { /* SUBQH.PH */ 9927 DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt); 9928 vassert(!mode64); 9929 9930 putIReg(rd, binop(Iop_HSub16Sx2, 9931 getIReg(rs), getIReg(rt))); 9932 break; 9933 } 9934 case 0xA: {/* ADDQH_R.PH */ 9935 DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt); 9936 vassert(!mode64); 9937 t0 = newTemp(Ity_I32); 9938 t1 = newTemp(Ity_I16); 9939 t2 = newTemp(Ity_I32); 9940 t3 = newTemp(Ity_I16); 9941 9942 /* Add lower halfs of rs and rt, add 1 9943 and right shift the result by 1. */ 9944 assign(t0, binop(Iop_Add32, 9945 unop(Iop_16Sto32, 9946 unop(Iop_32to16, getIReg(rs))), 9947 unop(Iop_16Sto32, 9948 unop(Iop_32to16, getIReg(rt))))); 9949 assign(t1, unop(Iop_32to16, 9950 binop(Iop_Shr32, 9951 binop(Iop_And32, 9952 binop(Iop_Add32, 9953 mkexpr(t0), 9954 mkU32(0x1)), 9955 mkU32(0x0001fffe)), 9956 mkU8(0x1)))); 9957 /* Add higher halfs of rs and rt, add 1 9958 and right shift the result by 1. */ 9959 assign(t2, binop(Iop_Add32, 9960 unop(Iop_16Sto32, 9961 unop(Iop_32HIto16, getIReg(rs))), 9962 unop(Iop_16Sto32, 9963 unop(Iop_32HIto16, getIReg(rt))))); 9964 assign(t3, unop(Iop_32to16, 9965 binop(Iop_Shr32, 9966 binop(Iop_And32, 9967 binop(Iop_Add32, 9968 mkexpr(t2), 9969 mkU32(0x1)), 9970 mkU32(0x0001fffe)), 9971 mkU8(0x1)))); 9972 9973 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 9974 break; 9975 } 9976 case 0xB: { /* SUBQH_R.PH */ 9977 DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt); 9978 vassert(!mode64); 9979 t0 = newTemp(Ity_I32); 9980 t1 = newTemp(Ity_I16); 9981 t2 = newTemp(Ity_I32); 9982 t3 = newTemp(Ity_I16); 9983 9984 /* Sub lower halfs of rs and rt, add 1 9985 and right shift the result by 1. */ 9986 assign(t0, binop(Iop_Sub32, 9987 unop(Iop_16Sto32, 9988 unop(Iop_32to16, getIReg(rs))), 9989 unop(Iop_16Sto32, 9990 unop(Iop_32to16, getIReg(rt))))); 9991 assign(t1, unop(Iop_32to16, 9992 binop(Iop_Shr32, 9993 binop(Iop_And32, 9994 binop(Iop_Add32, 9995 mkexpr(t0), 9996 mkU32(0x1)), 9997 mkU32(0x0001fffe)), 9998 mkU8(0x1)))); 9999 /* Sub higher halfs of rs and rt, add 1 10000 and right shift the result by 1. */ 10001 assign(t2, binop(Iop_Sub32, 10002 unop(Iop_16Sto32, 10003 unop(Iop_32HIto16, getIReg(rs))), 10004 unop(Iop_16Sto32, 10005 unop(Iop_32HIto16, getIReg(rt))))); 10006 assign(t3, unop(Iop_32to16, 10007 binop(Iop_Shr32, 10008 binop(Iop_And32, 10009 binop(Iop_Add32, 10010 mkexpr(t2), 10011 mkU32(0x1)), 10012 mkU32(0x0001fffe)), 10013 mkU8(0x1)))); 10014 10015 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 10016 break; 10017 } 10018 case 0xC: { /* MUL.PH */ 10019 DIP("mul.ph r%u, r%u, r%u", rd, rs, rt); 10020 vassert(!mode64); 10021 t0 = newTemp(Ity_I32); 10022 t1 = newTemp(Ity_I32); 10023 t2 = newTemp(Ity_I32); 10024 10025 assign(t0, 10026 binop(Iop_Mul32, 10027 unop(Iop_16Sto32, 10028 unop(Iop_32HIto16, getIReg(rs))), 10029 unop(Iop_16Sto32, 10030 unop(Iop_32HIto16, getIReg(rt))))); 10031 /* DSP Control flag. */ 10032 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10033 binop(Iop_CmpLE32S, 10034 mkexpr(t0), 10035 mkU32(0x7FFF))), 10036 binop(Iop_Or32, 10037 getDSPControl(), 10038 mkU32(0x00200000)), 10039 IRExpr_ITE(binop(Iop_CmpLT32S, 10040 mkexpr(t0), 10041 mkU32(0xFFFF8000) 10042 ), 10043 binop(Iop_Or32, 10044 getDSPControl(), 10045 mkU32(0x00200000) 10046 ), 10047 getDSPControl()))); 10048 10049 assign(t1, 10050 binop(Iop_Mul32, 10051 unop(Iop_16Sto32, 10052 unop(Iop_32to16, getIReg(rs))), 10053 unop(Iop_16Sto32, 10054 unop(Iop_32to16, getIReg(rt))))); 10055 /* DSP Control flag. */ 10056 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10057 binop(Iop_CmpLE32S, 10058 mkexpr(t1), 10059 mkU32(0x7FFF))), 10060 binop(Iop_Or32, 10061 getDSPControl(), 10062 mkU32(0x00200000)), 10063 IRExpr_ITE(binop(Iop_CmpLT32S, 10064 mkexpr(t1), 10065 mkU32(0xFFFF8000) 10066 ), 10067 binop(Iop_Or32, 10068 getDSPControl(), 10069 mkU32(0x00200000) 10070 ), 10071 getDSPControl()))); 10072 10073 assign(t2, binop(Iop_16HLto32, 10074 unop(Iop_32to16, mkexpr(t0)), 10075 unop(Iop_32to16, mkexpr(t1)))); 10076 putIReg(rd, mkexpr(t2)); 10077 break; 10078 } 10079 case 0xE: { /* MUL_S.PH */ 10080 DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt); 10081 vassert(!mode64); 10082 10083 t0 = newTemp(Ity_I32); 10084 t1 = newTemp(Ity_I32); 10085 t2 = newTemp(Ity_I32); 10086 t3 = newTemp(Ity_I32); 10087 t4 = newTemp(Ity_I32); 10088 10089 /* t0 - signed intermediate result. */ 10090 assign(t0, 10091 binop(Iop_Mul32, 10092 unop(Iop_16Sto32, 10093 unop(Iop_32HIto16, getIReg(rs))), 10094 unop(Iop_16Sto32, 10095 unop(Iop_32HIto16, getIReg(rt))))); 10096 10097 assign(t1, 10098 IRExpr_ITE(unop(Iop_Not1, 10099 binop(Iop_CmpLE32S, 10100 mkexpr(t0), 10101 mkU32(0x7FFF))), 10102 mkU32(0x00007FFF), 10103 IRExpr_ITE(binop(Iop_CmpLT32S, 10104 mkexpr(t0), 10105 mkU32(0xFFFF8000)), 10106 mkU32(0xFFFF8000), 10107 mkexpr(t0)))); 10108 10109 /* DSP Control flag. */ 10110 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10111 binop(Iop_CmpLE32S, 10112 mkexpr(t0), 10113 mkU32(0x7FFF))), 10114 binop(Iop_Or32, 10115 getDSPControl(), 10116 mkU32(0x00200000)), 10117 IRExpr_ITE(binop(Iop_CmpLT32S, 10118 mkexpr(t0), 10119 mkU32(0xFFFF8000) 10120 ), 10121 binop(Iop_Or32, 10122 getDSPControl(), 10123 mkU32(0x00200000) 10124 ), 10125 getDSPControl()))); 10126 10127 /* t2 - signed intermediate result. */ 10128 assign(t2, binop(Iop_Mul32, 10129 unop(Iop_16Sto32, 10130 unop(Iop_32to16, getIReg(rs))), 10131 unop(Iop_16Sto32, 10132 unop(Iop_32to16, getIReg(rt))))); 10133 10134 assign(t3, IRExpr_ITE(unop(Iop_Not1, 10135 binop(Iop_CmpLE32S, 10136 mkexpr(t2), 10137 mkU32(0x7FFF))), 10138 mkU32(0x00007FFF), 10139 IRExpr_ITE(binop(Iop_CmpLT32S, 10140 mkexpr(t2), 10141 mkU32(0xFFFF8000)), 10142 mkU32(0xFFFF8000), 10143 mkexpr(t2)))); 10144 10145 /* DSP Control flag. */ 10146 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10147 binop(Iop_CmpLE32S, 10148 mkexpr(t2), 10149 mkU32(0x7FFF))), 10150 binop(Iop_Or32, 10151 getDSPControl(), 10152 mkU32(0x00200000)), 10153 IRExpr_ITE(binop(Iop_CmpLT32S, 10154 mkexpr(t2), 10155 mkU32(0xFFFF8000) 10156 ), 10157 binop(Iop_Or32, 10158 getDSPControl(), 10159 mkU32(0x00200000) 10160 ), 10161 getDSPControl()))); 10162 10163 assign(t4, binop(Iop_16HLto32, 10164 unop(Iop_32to16, mkexpr(t1)), 10165 unop(Iop_32to16, mkexpr(t3)))); 10166 putIReg(rd, mkexpr(t4)); 10167 break; 10168 } 10169 case 0x10: { /* ADDQH.W */ 10170 DIP("addqh.w r%u, r%u, r%u", rd, rs, rt); 10171 vassert(!mode64); 10172 t0 = newTemp(Ity_I64); 10173 t1 = newTemp(Ity_I64); 10174 10175 assign(t0, binop(Iop_Add64, 10176 unop(Iop_32Sto64, getIReg(rs)), 10177 unop(Iop_32Sto64, getIReg(rt)))); 10178 assign(t1, binop(Iop_And64, 10179 mkexpr(t0), 10180 mkU64(0x00000001fffffffeULL))); 10181 putIReg(rd, unop(Iop_64to32, 10182 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1)))); 10183 break; 10184 } 10185 case 0x11: { /* SUBQH.W */ 10186 DIP("subqh.w r%u, r%u, r%u", rd, rs, rt); 10187 vassert(!mode64); 10188 t0 = newTemp(Ity_I64); 10189 t1 = newTemp(Ity_I64); 10190 10191 assign(t0, binop(Iop_Sub64, 10192 unop(Iop_32Sto64, getIReg(rs)), 10193 unop(Iop_32Sto64, getIReg(rt)))); 10194 assign(t1, binop(Iop_And64, 10195 mkexpr(t0), 10196 mkU64(0x00000001fffffffeULL))); 10197 putIReg(rd, unop(Iop_64to32, 10198 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1)))); 10199 break; 10200 } 10201 case 0x12: { /* ADDQH_R.W */ 10202 DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt); 10203 vassert(!mode64); 10204 t0 = newTemp(Ity_I64); 10205 t1 = newTemp(Ity_I64); 10206 t2 = newTemp(Ity_I64); 10207 10208 assign(t0, binop(Iop_Add64, 10209 unop(Iop_32Sto64, getIReg(rs)), 10210 unop(Iop_32Sto64, getIReg(rt)))); 10211 assign(t1, binop(Iop_Add64, 10212 mkexpr(t0), 10213 mkU64(0x0000000000000001ULL))); 10214 assign(t2, binop(Iop_And64, 10215 mkexpr(t1), 10216 mkU64(0x00000001fffffffeULL))); 10217 putIReg(rd, unop(Iop_64to32, 10218 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1)))); 10219 break; 10220 } 10221 case 0x13: { /* SUBQH_R.W */ 10222 DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt); 10223 vassert(!mode64); 10224 t0 = newTemp(Ity_I64); 10225 t1 = newTemp(Ity_I64); 10226 t2 = newTemp(Ity_I64); 10227 10228 assign(t0, binop(Iop_Sub64, 10229 unop(Iop_32Sto64, getIReg(rs)), 10230 unop(Iop_32Sto64, getIReg(rt)))); 10231 assign(t1, binop(Iop_Add64, 10232 mkexpr(t0), 10233 mkU64(0x0000000000000001ULL))); 10234 assign(t2, binop(Iop_And64, 10235 mkexpr(t1), 10236 mkU64(0x00000001fffffffeULL))); 10237 putIReg(rd, unop(Iop_64to32, 10238 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1)))); 10239 break; 10240 } 10241 case 0x16: { /* MULQ_S.W */ 10242 DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt); 10243 vassert(!mode64); 10244 t0 = newTemp(Ity_I64); 10245 t1 = newTemp(Ity_I1); 10246 t2 = newTemp(Ity_I1); 10247 10248 assign(t0, binop(Iop_Shl64, 10249 binop(Iop_MullS32, 10250 getIReg(rt), getIReg(rs)), 10251 mkU8(0x1))); 10252 assign(t1, binop(Iop_CmpEQ32, 10253 getIReg(rt), mkU32(0x80000000))); 10254 assign(t2, binop(Iop_CmpEQ32, 10255 getIReg(rs), mkU32(0x80000000))); 10256 10257 putDSPControl(IRExpr_ITE(mkexpr(t1), 10258 IRExpr_ITE(mkexpr(t2), 10259 binop(Iop_Or32, 10260 getDSPControl(), 10261 mkU32(0x00200000) 10262 ), 10263 getDSPControl()), 10264 getDSPControl())); 10265 putIReg(rd, IRExpr_ITE(mkexpr(t1), 10266 IRExpr_ITE(mkexpr(t2), 10267 mkU32(0x7fffffff), 10268 unop(Iop_64HIto32, 10269 mkexpr(t0))), 10270 unop(Iop_64HIto32, mkexpr(t0)))); 10271 break; 10272 } 10273 case 0x17: { /* MULQ_RS.W */ 10274 DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt); 10275 vassert(!mode64); 10276 t0 = newTemp(Ity_I64); 10277 t1 = newTemp(Ity_I1); 10278 t2 = newTemp(Ity_I1); 10279 10280 assign(t0, binop(Iop_Add64, 10281 binop(Iop_Shl64, 10282 binop(Iop_MullS32, 10283 getIReg(rt), 10284 getIReg(rs)), 10285 mkU8(0x1)), 10286 mkU64(0x0000000080000000ULL))); 10287 assign(t1, 10288 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 10289 assign(t2, 10290 binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000))); 10291 putDSPControl(IRExpr_ITE(mkexpr(t1), 10292 IRExpr_ITE(mkexpr(t2), 10293 binop(Iop_Or32, 10294 getDSPControl(), 10295 mkU32(0x00200000) 10296 ), 10297 getDSPControl()), 10298 getDSPControl())); 10299 putIReg(rd, IRExpr_ITE(mkexpr(t1), 10300 IRExpr_ITE(mkexpr(t2), 10301 mkU32(0x7fffffff), 10302 unop(Iop_64HIto32, 10303 mkexpr(t0))), 10304 unop(Iop_64HIto32, mkexpr(t0)))); 10305 break; 10306 } 10307 default: 10308 return -1; 10309 } 10310 break; /* end of ADDUH.QB/MUL.PH */ 10311 } 10312 case 0x30: { /* DPAQ.W.PH */ 10313 switch(sa) { 10314 case 0x0: { /* DPA.W.PH */ 10315 DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt); 10316 vassert(!mode64); 10317 10318 t0 = newTemp(Ity_I64); 10319 t1 = newTemp(Ity_I64); 10320 t2 = newTemp(Ity_I64); 10321 10322 assign(t0, 10323 unop(Iop_32Sto64, 10324 binop(Iop_Mul32, 10325 unop(Iop_16Sto32, 10326 unop(Iop_32HIto16, getIReg(rs))), 10327 unop(Iop_16Sto32, 10328 unop(Iop_32HIto16, getIReg(rt)))))); 10329 assign(t1, 10330 unop(Iop_32Sto64, 10331 binop(Iop_Mul32, 10332 unop(Iop_16Sto32, 10333 unop(Iop_32to16, getIReg(rs))), 10334 unop(Iop_16Sto32, 10335 unop(Iop_32to16, getIReg(rt)))))); 10336 assign(t2, 10337 binop(Iop_Add64, 10338 getAcc(ac), 10339 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10340 putAcc(ac, mkexpr(t2)); 10341 break; 10342 } 10343 case 0x1: { /* DPS.W.PH */ 10344 DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt); 10345 vassert(!mode64); 10346 10347 t0 = newTemp(Ity_I64); 10348 t1 = newTemp(Ity_I64); 10349 t2 = newTemp(Ity_I64); 10350 10351 assign(t0, 10352 unop(Iop_32Sto64, 10353 binop(Iop_Mul32, 10354 unop(Iop_16Sto32, 10355 unop(Iop_32HIto16, getIReg(rs))), 10356 unop(Iop_16Sto32, 10357 unop(Iop_32HIto16, getIReg(rt)))))); 10358 assign(t1, 10359 unop(Iop_32Sto64, 10360 binop(Iop_Mul32, 10361 unop(Iop_16Sto32, 10362 unop(Iop_32to16, getIReg(rs))), 10363 unop(Iop_16Sto32, 10364 unop(Iop_32to16, getIReg(rt)))))); 10365 assign(t2, 10366 binop(Iop_Sub64, 10367 getAcc(ac), 10368 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10369 putAcc(ac, mkexpr(t2)); 10370 break; 10371 } 10372 case 0x2: { /* MULSA.W.PH */ 10373 DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt); 10374 vassert(!mode64); 10375 t0 = newTemp(Ity_I32); 10376 t1 = newTemp(Ity_I32); 10377 t2 = newTemp(Ity_I32); 10378 t3 = newTemp(Ity_I1); 10379 t4 = newTemp(Ity_I64); 10380 10381 assign(t4, getAcc(ac)); 10382 assign(t0, binop(Iop_Mul32, 10383 unop(Iop_16Sto32, 10384 unop(Iop_32to16, getIReg(rt))), 10385 unop(Iop_16Sto32, 10386 unop(Iop_32to16, getIReg(rs))))); 10387 assign(t1, binop(Iop_Mul32, 10388 unop(Iop_16Sto32, 10389 unop(Iop_32HIto16, getIReg(rt))), 10390 unop(Iop_16Sto32, 10391 unop(Iop_32HIto16, getIReg(rs))))); 10392 assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0))); 10393 putAcc(ac, binop(Iop_Add64, 10394 mkexpr(t4), 10395 unop(Iop_32Sto64, mkexpr(t2)))); 10396 break; 10397 } 10398 case 0x3: { /* DPAU.H.QBL */ 10399 DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt); 10400 vassert(!mode64); 10401 t0 = newTemp(Ity_I32); 10402 t1 = newTemp(Ity_I32); 10403 t2 = newTemp(Ity_I64); 10404 t3 = newTemp(Ity_I64); 10405 10406 assign(t0, 10407 binop(Iop_Mul32, 10408 unop(Iop_8Uto32, 10409 unop(Iop_16HIto8, 10410 unop(Iop_32HIto16, getIReg(rs)))), 10411 unop(Iop_8Uto32, 10412 unop(Iop_16HIto8, 10413 unop(Iop_32HIto16, getIReg(rt)))))); 10414 assign(t1, 10415 binop(Iop_Mul32, 10416 unop(Iop_8Uto32, 10417 unop(Iop_16to8, 10418 unop(Iop_32HIto16, getIReg(rs)))), 10419 unop(Iop_8Uto32, 10420 unop(Iop_16to8, 10421 unop(Iop_32HIto16, getIReg(rt)))))); 10422 assign(t2, 10423 unop(Iop_32Uto64, 10424 binop(Iop_Add32, 10425 mkexpr(t0), 10426 mkexpr(t1)))); 10427 assign(t3, 10428 binop(Iop_Add64, getAcc(ac), mkexpr(t2))); 10429 putAcc(ac, mkexpr(t3)); 10430 break; 10431 } 10432 case 0x4: { /* DPAQ_S.W.PH */ 10433 DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 10434 vassert(!mode64); 10435 t0 = newTemp(Ity_I64); 10436 t1 = newTemp(Ity_I64); 10437 t2 = newTemp(Ity_I1); 10438 t3 = newTemp(Ity_I1); 10439 t4 = newTemp(Ity_I64); 10440 t5 = newTemp(Ity_I64); 10441 t6 = newTemp(Ity_I1); 10442 t7 = newTemp(Ity_I1); 10443 t8 = newTemp(Ity_I64); 10444 t9 = newTemp(Ity_I64); 10445 10446 assign(t0, getAcc(ac)); 10447 10448 assign(t1, binop(Iop_Shl64, 10449 binop(Iop_MullS32, 10450 unop(Iop_16Sto32, 10451 unop(Iop_32HIto16, 10452 getIReg(rs))), 10453 unop(Iop_16Sto32, 10454 unop(Iop_32HIto16, 10455 getIReg(rt)))), 10456 mkU8(0x1))); 10457 assign(t2, binop(Iop_CmpEQ32, 10458 unop(Iop_16Uto32, 10459 unop(Iop_32HIto16, getIReg(rs))), 10460 mkU32(0x00008000))); 10461 assign(t3, binop(Iop_CmpEQ32, 10462 unop(Iop_16Uto32, 10463 unop(Iop_32HIto16, getIReg(rt))), 10464 mkU32(0x00008000))); 10465 assign(t4, 10466 IRExpr_ITE(mkexpr(t2), 10467 IRExpr_ITE(mkexpr(t3), 10468 mkU64(0x000000007fffffffULL), 10469 mkexpr(t1)), 10470 mkexpr(t1))); 10471 10472 putDSPControl(IRExpr_ITE(mkexpr(t2), 10473 IRExpr_ITE(mkexpr(t3), 10474 binop(Iop_Or32, 10475 getDSPControl(), 10476 binop(Iop_Shl32, 10477 mkU32(0x1), 10478 mkU8(ac+16) 10479 ) 10480 ), 10481 getDSPControl()), 10482 getDSPControl())); 10483 10484 assign(t5, binop(Iop_Shl64, 10485 binop(Iop_MullS32, 10486 unop(Iop_16Sto32, 10487 unop(Iop_32to16, getIReg(rs))), 10488 unop(Iop_16Sto32, 10489 unop(Iop_32to16, getIReg(rt))) 10490 ), 10491 mkU8(0x1))); 10492 assign(t6, binop(Iop_CmpEQ32, 10493 unop(Iop_16Uto32, 10494 unop(Iop_32to16, getIReg(rs))), 10495 mkU32(0x00008000))); 10496 assign(t7, binop(Iop_CmpEQ32, 10497 unop(Iop_16Uto32, 10498 unop(Iop_32to16, getIReg(rt))), 10499 mkU32(0x00008000))); 10500 assign(t8, 10501 IRExpr_ITE(mkexpr(t6), 10502 IRExpr_ITE(mkexpr(t7), 10503 mkU64(0x000000007fffffffULL), 10504 mkexpr(t5)), 10505 mkexpr(t5))); 10506 10507 putDSPControl(IRExpr_ITE(mkexpr(t6), 10508 IRExpr_ITE(mkexpr(t7), 10509 binop(Iop_Or32, 10510 getDSPControl(), 10511 binop(Iop_Shl32, 10512 mkU32(0x1), 10513 mkU8(ac+16) 10514 ) 10515 ), 10516 getDSPControl()), 10517 getDSPControl())); 10518 10519 assign(t9, binop(Iop_Add64, 10520 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)), 10521 mkexpr(t0))); 10522 putAcc(ac, mkexpr(t9)); 10523 break; 10524 } 10525 case 0x5: { /* DPSQ_S.W.PH */ 10526 DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt); 10527 vassert(!mode64); 10528 t0 = newTemp(Ity_I64); 10529 t1 = newTemp(Ity_I64); 10530 t2 = newTemp(Ity_I1); 10531 t3 = newTemp(Ity_I1); 10532 t4 = newTemp(Ity_I64); 10533 t5 = newTemp(Ity_I64); 10534 t6 = newTemp(Ity_I1); 10535 t7 = newTemp(Ity_I1); 10536 t8 = newTemp(Ity_I64); 10537 t9 = newTemp(Ity_I64); 10538 10539 assign(t0, getAcc(ac)); 10540 10541 assign(t1, binop(Iop_Shl64, 10542 binop(Iop_MullS32, 10543 unop(Iop_16Sto32, 10544 unop(Iop_32HIto16, 10545 getIReg(rs))), 10546 unop(Iop_16Sto32, 10547 unop(Iop_32HIto16, 10548 getIReg(rt)))), 10549 mkU8(0x1))); 10550 assign(t2, binop(Iop_CmpEQ32, 10551 unop(Iop_16Uto32, 10552 unop(Iop_32HIto16, getIReg(rs))), 10553 mkU32(0x00008000))); 10554 assign(t3, binop(Iop_CmpEQ32, 10555 unop(Iop_16Uto32, 10556 unop(Iop_32HIto16, getIReg(rt))), 10557 mkU32(0x00008000))); 10558 assign(t4, 10559 IRExpr_ITE(mkexpr(t2), 10560 IRExpr_ITE(mkexpr(t3), 10561 mkU64(0x000000007fffffffULL), 10562 mkexpr(t1)), 10563 mkexpr(t1))); 10564 10565 putDSPControl(IRExpr_ITE(mkexpr(t2), 10566 IRExpr_ITE(mkexpr(t3), 10567 binop(Iop_Or32, 10568 getDSPControl(), 10569 binop(Iop_Shl32, 10570 mkU32(0x1), 10571 mkU8(ac+16) 10572 ) 10573 ), 10574 getDSPControl()), 10575 getDSPControl())); 10576 10577 assign(t5, 10578 binop(Iop_Shl64, 10579 binop(Iop_MullS32, 10580 unop(Iop_16Sto32, 10581 unop(Iop_32to16, getIReg(rs))), 10582 unop(Iop_16Sto32, 10583 unop(Iop_32to16, getIReg(rt)))), 10584 mkU8(0x1))); 10585 assign(t6, binop(Iop_CmpEQ32, 10586 unop(Iop_16Uto32, 10587 unop(Iop_32to16, getIReg(rs))), 10588 mkU32(0x00008000))); 10589 assign(t7, binop(Iop_CmpEQ32, 10590 unop(Iop_16Uto32, 10591 unop(Iop_32to16, getIReg(rt))), 10592 mkU32(0x00008000))); 10593 assign(t8, 10594 IRExpr_ITE(mkexpr(t6), 10595 IRExpr_ITE(mkexpr(t7), 10596 mkU64(0x000000007fffffffULL), 10597 mkexpr(t5)), 10598 mkexpr(t5))); 10599 10600 putDSPControl(IRExpr_ITE(mkexpr(t6), 10601 IRExpr_ITE(mkexpr(t7), 10602 binop(Iop_Or32, 10603 getDSPControl(), 10604 binop(Iop_Shl32, 10605 mkU32(0x1), 10606 mkU8(ac+16) 10607 ) 10608 ), 10609 getDSPControl()), 10610 getDSPControl())); 10611 10612 assign(t9, 10613 binop(Iop_Sub64, 10614 mkexpr(t0), 10615 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)))); 10616 putAcc(ac, mkexpr(t9)); 10617 break; 10618 } 10619 case 0x6: { /* MULSAQ_S.W.PH */ 10620 DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt); 10621 vassert(!mode64); 10622 10623 t0 = newTemp(Ity_I32); 10624 t1 = newTemp(Ity_I32); 10625 t2 = newTemp(Ity_I32); 10626 t3 = newTemp(Ity_I32); 10627 t4 = newTemp(Ity_I32); 10628 t5 = newTemp(Ity_I32); 10629 t6 = newTemp(Ity_I64); 10630 t7 = newTemp(Ity_I64); 10631 t8 = newTemp(Ity_I32); 10632 t9 = newTemp(Ity_I32); 10633 10634 assign(t0, unop(Iop_16Sto32, 10635 unop(Iop_32HIto16, getIReg(rs)))); 10636 assign(t1, unop(Iop_16Sto32, 10637 unop(Iop_32HIto16, getIReg(rt)))); 10638 10639 assign(t8, binop(Iop_And32, 10640 unop(Iop_1Sto32, 10641 binop(Iop_CmpEQ32, 10642 unop(Iop_16Uto32, 10643 unop(Iop_32HIto16, 10644 getIReg(rs))), 10645 mkU32(0x8000))), 10646 unop(Iop_1Sto32, 10647 binop(Iop_CmpEQ32, 10648 unop(Iop_16Uto32, 10649 unop(Iop_32HIto16, 10650 getIReg(rt))), 10651 mkU32(0x8000))))); 10652 /* DSPControl_outflag:16+acc <- 1 */ 10653 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 10654 mkexpr(t8), 10655 mkU32(0x0)), 10656 binop(Iop_Or32, 10657 getDSPControl(), 10658 binop(Iop_Shl32, 10659 mkU32(0x00010000), 10660 mkU8(ac))), 10661 getDSPControl())); 10662 10663 /* tempB_31..0 */ 10664 assign(t2, 10665 IRExpr_ITE(binop(Iop_CmpNE32, 10666 mkexpr(t8), mkU32(0x0)), 10667 mkU32(0x7FFFFFFF), 10668 binop(Iop_Shl32, 10669 binop(Iop_Mul32, 10670 mkexpr(t0), mkexpr(t1)), 10671 mkU8(1)))); 10672 10673 assign(t3, unop(Iop_16Sto32, 10674 unop(Iop_32to16, getIReg(rs)))); 10675 assign(t4, unop(Iop_16Sto32, 10676 unop(Iop_32to16, getIReg(rt)))); 10677 10678 assign(t9, binop(Iop_And32, 10679 unop(Iop_1Sto32, 10680 binop(Iop_CmpEQ32, 10681 unop(Iop_16Uto32, 10682 unop(Iop_32to16, 10683 getIReg(rs))), 10684 mkU32(0x8000))), 10685 unop(Iop_1Sto32, 10686 binop(Iop_CmpEQ32, 10687 unop(Iop_16Uto32, 10688 unop(Iop_32to16, 10689 getIReg(rt))), 10690 mkU32(0x8000))))); 10691 /* DSPControl_outflag:16+acc <- 1 */ 10692 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 10693 mkexpr(t9), 10694 mkU32(0x0)), 10695 binop(Iop_Or32, 10696 getDSPControl(), 10697 binop(Iop_Shl32, 10698 mkU32(0x00010000), 10699 mkU8(ac))), 10700 getDSPControl())); 10701 /* tempA_31..0 */ 10702 assign(t5, 10703 IRExpr_ITE(binop(Iop_CmpNE32, 10704 mkexpr(t9), 10705 mkU32(0x0)), 10706 mkU32(0x7FFFFFFF), 10707 binop(Iop_Shl32, 10708 binop(Iop_Mul32, 10709 mkexpr(t3), 10710 mkexpr(t4)), 10711 mkU8(1)))); 10712 /* dotp_63..0 */ 10713 assign(t6, 10714 binop(Iop_Sub64, 10715 unop(Iop_32Sto64, mkexpr(t2)), 10716 unop(Iop_32Sto64, mkexpr(t5)))); 10717 /* tempC_63..0 */ 10718 assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6))); 10719 10720 putAcc(ac, mkexpr(t7)); 10721 break; 10722 } 10723 case 0x7: { /* DPAU.H.QBR */ 10724 DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt); 10725 vassert(!mode64); 10726 t0 = newTemp(Ity_I32); 10727 t1 = newTemp(Ity_I32); 10728 t2 = newTemp(Ity_I64); 10729 t3 = newTemp(Ity_I64); 10730 10731 assign(t0, 10732 binop(Iop_Mul32, 10733 unop(Iop_8Uto32, 10734 unop(Iop_16HIto8, 10735 unop(Iop_32to16, getIReg(rs)))), 10736 unop(Iop_8Uto32, 10737 unop(Iop_16HIto8, 10738 unop(Iop_32to16, getIReg(rt)))))); 10739 assign(t1, 10740 binop(Iop_Mul32, 10741 unop(Iop_8Uto32, 10742 unop(Iop_16to8, 10743 unop(Iop_32to16, getIReg(rs)))), 10744 unop(Iop_8Uto32, 10745 unop(Iop_16to8, 10746 unop(Iop_32to16, getIReg(rt)))))); 10747 assign(t2, unop(Iop_32Uto64, 10748 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 10749 assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2))); 10750 putAcc(ac, mkexpr(t3)); 10751 break; 10752 } 10753 case 0x8: { /* DPAX.W.PH */ 10754 DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt); 10755 vassert(!mode64); 10756 t0 = newTemp(Ity_I64); 10757 t1 = newTemp(Ity_I64); 10758 t2 = newTemp(Ity_I64); 10759 10760 assign(t0, 10761 unop(Iop_32Sto64, 10762 binop(Iop_Mul32, 10763 unop(Iop_16Sto32, 10764 unop(Iop_32HIto16, getIReg(rs))), 10765 unop(Iop_16Sto32, 10766 unop(Iop_32to16, getIReg(rt)))))); 10767 assign(t1, 10768 unop(Iop_32Sto64, 10769 binop(Iop_Mul32, 10770 unop(Iop_16Sto32, 10771 unop(Iop_32to16, getIReg(rs))), 10772 unop(Iop_16Sto32, 10773 unop(Iop_32HIto16, getIReg(rt)))))); 10774 assign(t2, 10775 binop(Iop_Add64, 10776 getAcc(ac), 10777 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10778 putAcc(ac, mkexpr(t2)); 10779 break; 10780 } 10781 case 0x9: { /* DPSX.W.PH */ 10782 DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt); 10783 vassert(!mode64); 10784 10785 t0 = newTemp(Ity_I64); 10786 t1 = newTemp(Ity_I64); 10787 t2 = newTemp(Ity_I64); 10788 10789 assign(t0, 10790 unop(Iop_32Sto64, 10791 binop(Iop_Mul32, 10792 unop(Iop_16Sto32, 10793 unop(Iop_32HIto16, getIReg(rs))), 10794 unop(Iop_16Sto32, 10795 unop(Iop_32to16, getIReg(rt)))))); 10796 assign(t1, 10797 unop(Iop_32Sto64, 10798 binop(Iop_Mul32, 10799 unop(Iop_16Sto32, 10800 unop(Iop_32to16, getIReg(rs))), 10801 unop(Iop_16Sto32, 10802 unop(Iop_32HIto16, getIReg(rt)))))); 10803 assign(t2, 10804 binop(Iop_Sub64, 10805 getAcc(ac), 10806 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10807 putAcc(ac, mkexpr(t2)); 10808 break; 10809 } 10810 case 0xB: { /* DPSU.H.QBL */ 10811 DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt); 10812 vassert(!mode64); 10813 10814 t0 = newTemp(Ity_I32); 10815 t1 = newTemp(Ity_I32); 10816 t2 = newTemp(Ity_I64); 10817 t3 = newTemp(Ity_I64); 10818 10819 assign(t0, 10820 binop(Iop_Mul32, 10821 unop(Iop_8Uto32, 10822 unop(Iop_16HIto8, 10823 unop(Iop_32HIto16, getIReg(rs)))), 10824 unop(Iop_8Uto32, 10825 unop(Iop_16HIto8, 10826 unop(Iop_32HIto16, getIReg(rt)))))); 10827 assign(t1, 10828 binop(Iop_Mul32, 10829 unop(Iop_8Uto32, 10830 unop(Iop_16to8, 10831 unop(Iop_32HIto16, getIReg(rs)))), 10832 unop(Iop_8Uto32, 10833 unop(Iop_16to8, 10834 unop(Iop_32HIto16, getIReg(rt)))))); 10835 assign(t2, 10836 unop(Iop_32Uto64, 10837 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 10838 assign(t3, 10839 binop(Iop_Sub64, getAcc(ac), mkexpr(t2))); 10840 putAcc(ac, mkexpr(t3)); 10841 break; 10842 } 10843 case 0xC: { /* DPAQ_SA.L.W */ 10844 DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt); 10845 vassert(!mode64); 10846 t0 = newTemp(Ity_I64); 10847 t1 = newTemp(Ity_I64); 10848 t2 = newTemp(Ity_I1); 10849 t3 = newTemp(Ity_I1); 10850 t4 = newTemp(Ity_I64); 10851 t5 = newTemp(Ity_I64); 10852 t6 = newTemp(Ity_I64); 10853 t7 = newTemp(Ity_I64); 10854 t8 = newTemp(Ity_I1); 10855 t9 = newTemp(Ity_I1); 10856 10857 assign(t0, getAcc(ac)); 10858 10859 assign(t1, binop(Iop_Shl64, 10860 binop(Iop_MullS32, 10861 getIReg(rs), getIReg(rt)), 10862 mkU8(0x1))); 10863 10864 assign(t2, binop(Iop_CmpEQ32, 10865 getIReg(rs), 10866 mkU32(0x80000000))); 10867 assign(t3, binop(Iop_CmpEQ32, 10868 getIReg(rt), 10869 mkU32(0x80000000))); 10870 10871 assign(t4, 10872 IRExpr_ITE(mkexpr(t2), 10873 IRExpr_ITE(mkexpr(t3), 10874 mkU64(0x7fffffffffffffffULL), 10875 mkexpr(t1)), 10876 mkexpr(t1))); 10877 10878 putDSPControl(IRExpr_ITE(mkexpr(t2), 10879 IRExpr_ITE(mkexpr(t3), 10880 binop(Iop_Or32, 10881 getDSPControl(), 10882 binop(Iop_Shl32, 10883 mkU32(0x1), 10884 mkU8(ac+16) 10885 ) 10886 ), 10887 getDSPControl()), 10888 getDSPControl())); 10889 10890 assign(t5, binop(Iop_Add64, 10891 unop(Iop_32Uto64, 10892 unop(Iop_64to32, mkexpr(t0))), 10893 unop(Iop_32Uto64, 10894 unop(Iop_64to32, mkexpr(t4))))); 10895 assign(t6, 10896 binop(Iop_Add64, 10897 binop(Iop_Add64, 10898 unop(Iop_32Sto64, 10899 unop(Iop_64HIto32, mkexpr(t0))), 10900 unop(Iop_32Sto64, 10901 unop(Iop_64HIto32, mkexpr(t4)))), 10902 unop(Iop_32Uto64, 10903 binop(Iop_And32, 10904 unop(Iop_64HIto32, mkexpr(t5)), 10905 mkU32(0x1))))); 10906 assign(t7, binop(Iop_32HLto64, 10907 unop(Iop_64to32, mkexpr(t6)), 10908 unop(Iop_64to32, mkexpr(t5)))); 10909 assign(t8, binop(Iop_CmpEQ32, 10910 binop(Iop_Shr32, 10911 binop(Iop_And32, 10912 unop(Iop_64to32, mkexpr(t6)), 10913 mkU32(0x80000000)), 10914 mkU8(31)), 10915 binop(Iop_And32, 10916 unop(Iop_64HIto32, mkexpr(t6)), 10917 mkU32(0x00000001)))); 10918 assign(t9, binop(Iop_CmpEQ32, 10919 binop(Iop_And32, 10920 unop(Iop_64HIto32, 10921 mkexpr(t6)), 10922 mkU32(0x00000001)), 10923 mkU32(0x1))); 10924 putDSPControl(IRExpr_ITE(mkexpr(t8), 10925 getDSPControl(), 10926 binop(Iop_Or32, 10927 getDSPControl(), 10928 binop(Iop_Shl32, 10929 mkU32(0x1), 10930 mkU8(ac+16))))); 10931 putAcc(ac, 10932 IRExpr_ITE(mkexpr(t8), 10933 mkexpr(t7), 10934 IRExpr_ITE(mkexpr(t9), 10935 mkU64(0x8000000000000000ULL), 10936 mkU64(0x7fffffffffffffffULL))) 10937 ); 10938 break; 10939 } 10940 case 0xD: { /* DPSQ_SA.L.W */ 10941 DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt); 10942 vassert(!mode64); 10943 t0 = newTemp(Ity_I64); 10944 t1 = newTemp(Ity_I64); 10945 t2 = newTemp(Ity_I1); 10946 t3 = newTemp(Ity_I1); 10947 t4 = newTemp(Ity_I64); 10948 t5 = newTemp(Ity_I64); 10949 t6 = newTemp(Ity_I64); 10950 t7 = newTemp(Ity_I64); 10951 t8 = newTemp(Ity_I1); 10952 t9 = newTemp(Ity_I1); 10953 10954 assign(t0, getAcc(ac)); 10955 10956 assign(t1, binop(Iop_Shl64, 10957 binop(Iop_MullS32, 10958 getIReg(rs), getIReg(rt)), 10959 mkU8(0x1))); 10960 10961 assign(t2, binop(Iop_CmpEQ32, 10962 getIReg(rs), 10963 mkU32(0x80000000))); 10964 assign(t3, binop(Iop_CmpEQ32, 10965 getIReg(rt), 10966 mkU32(0x80000000))); 10967 10968 assign(t4, 10969 IRExpr_ITE(mkexpr(t2), 10970 IRExpr_ITE(mkexpr(t3), 10971 mkU64(0x7fffffffffffffffULL), 10972 mkexpr(t1)), 10973 mkexpr(t1))); 10974 10975 putDSPControl(IRExpr_ITE(mkexpr(t2), 10976 IRExpr_ITE(mkexpr(t3), 10977 binop(Iop_Or32, 10978 getDSPControl(), 10979 binop(Iop_Shl32, 10980 mkU32(0x1), 10981 mkU8(ac+16) 10982 ) 10983 ), 10984 getDSPControl()), 10985 getDSPControl())); 10986 10987 assign(t5, binop(Iop_Sub64, 10988 unop(Iop_32Uto64, 10989 unop(Iop_64to32, mkexpr(t0))), 10990 unop(Iop_32Uto64, 10991 unop(Iop_64to32, mkexpr(t4))))); 10992 assign(t6, binop(Iop_Sub64, 10993 binop(Iop_Add64, 10994 unop(Iop_32Sto64, 10995 unop(Iop_64HIto32, mkexpr(t0)) 10996 ), 10997 unop(Iop_32Sto64, 10998 unop(Iop_1Sto32, 10999 binop(Iop_CmpLT32U, 11000 unop(Iop_64to32, 11001 mkexpr(t0)), 11002 unop(Iop_64to32, 11003 mkexpr(t4)))))), 11004 unop(Iop_32Sto64, 11005 unop(Iop_64HIto32, mkexpr(t4))))); 11006 assign(t7, binop(Iop_32HLto64, 11007 unop(Iop_64to32, mkexpr(t6)), 11008 unop(Iop_64to32, mkexpr(t5)))); 11009 assign(t8, binop(Iop_CmpEQ32, 11010 binop(Iop_Shr32, 11011 binop(Iop_And32, 11012 unop(Iop_64to32, mkexpr(t6)), 11013 mkU32(0x80000000)), 11014 mkU8(31)), 11015 binop(Iop_And32, 11016 unop(Iop_64HIto32, mkexpr(t6)), 11017 mkU32(0x00000001)))); 11018 assign(t9, binop(Iop_CmpEQ32, 11019 binop(Iop_And32, 11020 unop(Iop_64HIto32, mkexpr(t6)), 11021 mkU32(0x00000001)), 11022 mkU32(0x1))); 11023 putDSPControl(IRExpr_ITE(mkexpr(t8), 11024 getDSPControl(), 11025 binop(Iop_Or32, 11026 getDSPControl(), 11027 binop(Iop_Shl32, 11028 mkU32(0x1), 11029 mkU8(ac+16))))); 11030 putAcc(ac, 11031 IRExpr_ITE(mkexpr(t8), 11032 mkexpr(t7), 11033 IRExpr_ITE(mkexpr(t9), 11034 mkU64(0x8000000000000000ULL), 11035 mkU64(0x7fffffffffffffffULL))) 11036 ); 11037 break; 11038 } 11039 case 0xF: { /* DPSU.H.QBR */ 11040 DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt); 11041 vassert(!mode64); 11042 11043 t0 = newTemp(Ity_I32); 11044 t1 = newTemp(Ity_I32); 11045 t2 = newTemp(Ity_I64); 11046 t3 = newTemp(Ity_I64); 11047 11048 assign(t0, 11049 binop(Iop_Mul32, 11050 unop(Iop_8Uto32, 11051 unop(Iop_16HIto8, 11052 unop(Iop_32to16, getIReg(rs)))), 11053 unop(Iop_8Uto32, 11054 unop(Iop_16HIto8, 11055 unop(Iop_32to16, getIReg(rt)))))); 11056 assign(t1, 11057 binop(Iop_Mul32, 11058 unop(Iop_8Uto32, 11059 unop(Iop_16to8, 11060 unop(Iop_32to16, getIReg(rs)))), 11061 unop(Iop_8Uto32, 11062 unop(Iop_16to8, 11063 unop(Iop_32to16, getIReg(rt)))))); 11064 assign(t2, unop(Iop_32Uto64, 11065 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 11066 assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2))); 11067 putAcc(ac, mkexpr(t3)); 11068 11069 break; 11070 } 11071 case 0x10: { /* MAQ_SA.W.PHL */ 11072 DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt); 11073 vassert(!mode64); 11074 t0 = newTemp(Ity_I64); 11075 t1 = newTemp(Ity_I64); 11076 t2 = newTemp(Ity_I1); 11077 t3 = newTemp(Ity_I1); 11078 t4 = newTemp(Ity_I64); 11079 t5 = newTemp(Ity_I64); 11080 t6 = newTemp(Ity_I1); 11081 t7 = newTemp(Ity_I64); 11082 11083 assign(t0, getAcc(ac)); 11084 assign(t1, unop(Iop_32Sto64, 11085 binop(Iop_Shl32, 11086 binop(Iop_Mul32, 11087 unop(Iop_16Sto32, 11088 unop(Iop_32HIto16, 11089 getIReg(rs))), 11090 unop(Iop_16Sto32, 11091 unop(Iop_32HIto16, 11092 getIReg(rt)))), 11093 mkU8(0x1)))); 11094 11095 /* If both input arguments are equal 0x8000, saturate 11096 intermediate product and write to DSPControl register. 11097 */ 11098 assign(t2, binop(Iop_CmpEQ32, 11099 unop(Iop_16Uto32, 11100 unop(Iop_32HIto16, getIReg(rs))), 11101 mkU32(0x00008000))); 11102 assign(t3, binop(Iop_CmpEQ32, 11103 unop(Iop_16Uto32, 11104 unop(Iop_32HIto16, getIReg(rt))), 11105 mkU32(0x00008000))); 11106 11107 assign(t4, 11108 IRExpr_ITE(mkexpr(t2), 11109 IRExpr_ITE(mkexpr(t3), 11110 mkU64(0x000000007fffffffULL), 11111 mkexpr(t1)), 11112 mkexpr(t1))); 11113 11114 putDSPControl(IRExpr_ITE(mkexpr(t2), 11115 IRExpr_ITE(mkexpr(t3), 11116 binop(Iop_Or32, 11117 getDSPControl(), 11118 binop(Iop_Shl32, 11119 mkU32(0x1), 11120 mkU8(ac+16) 11121 ) 11122 ), 11123 getDSPControl()), 11124 getDSPControl())); 11125 /* Add intermediate product and value in the 11126 accumulator. */ 11127 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4))); 11128 11129 /* Compare bits 31 and 32 of the value in t5. */ 11130 assign(t6, binop(Iop_CmpEQ32, 11131 binop(Iop_Shr32, 11132 binop(Iop_And32, 11133 unop(Iop_64to32, mkexpr(t5)), 11134 mkU32(0x80000000)), 11135 mkU8(31)), 11136 binop(Iop_And32, 11137 unop(Iop_64HIto32, mkexpr(t5)), 11138 mkU32(1)))); 11139 putDSPControl(IRExpr_ITE(mkexpr(t6), 11140 getDSPControl(), 11141 binop(Iop_Or32, 11142 getDSPControl(), 11143 binop(Iop_Shl32, 11144 mkU32(0x1), 11145 mkU8(ac+16))))); 11146 assign(t7, 11147 IRExpr_ITE(mkexpr(t6), 11148 mkexpr(t5), 11149 IRExpr_ITE(binop(Iop_CmpEQ32, 11150 binop(Iop_And32, 11151 unop(Iop_64HIto32, 11152 mkexpr(t5)), 11153 mkU32(1)), 11154 mkU32(0x0)), 11155 mkU64(0x000000007fffffffULL), 11156 mkU64(0xffffffff80000000ULL))) 11157 ); 11158 putAcc(ac, mkexpr(t7)); 11159 break; 11160 } 11161 case 0x12: { /* MAQ_SA.W.PHR */ 11162 DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt); 11163 vassert(!mode64); 11164 t0 = newTemp(Ity_I64); 11165 t1 = newTemp(Ity_I64); 11166 t2 = newTemp(Ity_I1); 11167 t3 = newTemp(Ity_I1); 11168 t4 = newTemp(Ity_I64); 11169 t5 = newTemp(Ity_I64); 11170 t6 = newTemp(Ity_I1); 11171 t7 = newTemp(Ity_I64); 11172 11173 assign(t0, getAcc(ac)); 11174 assign(t1, unop(Iop_32Sto64, 11175 binop(Iop_Shl32, 11176 binop(Iop_Mul32, 11177 unop(Iop_16Sto32, 11178 unop(Iop_32to16, 11179 getIReg(rs))), 11180 unop(Iop_16Sto32, 11181 unop(Iop_32to16, 11182 getIReg(rt)))), 11183 mkU8(0x1)))); 11184 11185 /* If both input arguments are equal 0x8000, saturate 11186 intermediate product and write to DSPControl 11187 register. */ 11188 assign(t2, binop(Iop_CmpEQ32, 11189 unop(Iop_16Uto32, 11190 unop(Iop_32to16, getIReg(rs))), 11191 mkU32(0x00008000))); 11192 assign(t3, binop(Iop_CmpEQ32, 11193 unop(Iop_16Uto32, 11194 unop(Iop_32to16, getIReg(rt))), 11195 mkU32(0x00008000))); 11196 11197 assign(t4, 11198 IRExpr_ITE(mkexpr(t2), 11199 IRExpr_ITE(mkexpr(t3), 11200 mkU64(0x000000007fffffffULL), 11201 mkexpr(t1)), 11202 mkexpr(t1))); 11203 11204 putDSPControl(IRExpr_ITE(mkexpr(t2), 11205 IRExpr_ITE(mkexpr(t3), 11206 binop(Iop_Or32, 11207 getDSPControl(), 11208 binop(Iop_Shl32, 11209 mkU32(0x1), 11210 mkU8(ac+16) 11211 ) 11212 ), 11213 getDSPControl()), 11214 getDSPControl())); 11215 /* Add intermediate product and value in the 11216 accumulator. */ 11217 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4))); 11218 11219 /* Compare bits 31 and 32 of the value in t5. */ 11220 assign(t6, binop(Iop_CmpEQ32, 11221 binop(Iop_Shr32, 11222 binop(Iop_And32, 11223 unop(Iop_64to32, mkexpr(t5)), 11224 mkU32(0x80000000)), 11225 mkU8(31)), 11226 binop(Iop_And32, 11227 unop(Iop_64HIto32, mkexpr(t5)), 11228 mkU32(1)))); 11229 putDSPControl(IRExpr_ITE(mkexpr(t6), 11230 getDSPControl(), 11231 binop(Iop_Or32, 11232 getDSPControl(), 11233 binop(Iop_Shl32, 11234 mkU32(0x1), 11235 mkU8(ac+16))))); 11236 assign(t7, 11237 IRExpr_ITE(mkexpr(t6), 11238 mkexpr(t5), 11239 IRExpr_ITE(binop(Iop_CmpEQ32, 11240 binop(Iop_And32, 11241 unop(Iop_64HIto32, 11242 mkexpr(t5)), 11243 mkU32(1)), 11244 mkU32(0x0)), 11245 mkU64(0x000000007fffffffULL), 11246 mkU64(0xffffffff80000000ULL))) 11247 ); 11248 putAcc(ac, mkexpr(t7)); 11249 break; 11250 } 11251 case 0x14: { /* MAQ_S.W.PHL */ 11252 DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt); 11253 vassert(!mode64); 11254 t0 = newTemp(Ity_I32); 11255 t1 = newTemp(Ity_I32); 11256 t2 = newTemp(Ity_I32); 11257 t3 = newTemp(Ity_I1); 11258 t4 = newTemp(Ity_I32); 11259 t5 = newTemp(Ity_I64); 11260 11261 assign(t5, getAcc(ac)); 11262 11263 assign(t0, unop(Iop_16Sto32, 11264 unop(Iop_32HIto16, getIReg(rs)))); 11265 assign(t1, unop(Iop_16Sto32, 11266 unop(Iop_32HIto16, getIReg(rt)))); 11267 11268 assign(t2, binop(Iop_And32, 11269 unop(Iop_1Sto32, 11270 binop(Iop_CmpEQ32, 11271 binop(Iop_And32, 11272 mkexpr(t0), 11273 mkU32(0xffff)), 11274 mkU32(0x8000))), 11275 unop(Iop_1Sto32, 11276 binop(Iop_CmpEQ32, 11277 binop(Iop_And32, 11278 mkexpr(t1), 11279 mkU32(0xffff)), 11280 mkU32(0x8000))))); 11281 11282 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0))); 11283 11284 putDSPControl(IRExpr_ITE(mkexpr(t3), 11285 getDSPControl(), 11286 binop(Iop_Or32, 11287 getDSPControl(), 11288 binop(Iop_Shl32, 11289 mkU32(0x1), 11290 mkU8(ac+16))))); 11291 11292 assign(t4, unop(Iop_64to32, 11293 binop(Iop_MullS32, 11294 mkexpr(t0), mkexpr(t1)))); 11295 putAcc(ac, IRExpr_ITE(mkexpr(t3), 11296 binop(Iop_Add64, 11297 unop(Iop_32Sto64, 11298 binop(Iop_Shl32, 11299 mkexpr(t4), 11300 mkU8(0x1))), 11301 mkexpr(t5)), 11302 binop(Iop_Add64, 11303 mkexpr(t5), 11304 unop(Iop_32Sto64, 11305 mkU32(0x7fffffff))))); 11306 break; 11307 } 11308 case 0x16: { /* MAQ_S.W.PHR */ 11309 DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt); 11310 vassert(!mode64); 11311 t0 = newTemp(Ity_I32); 11312 t1 = newTemp(Ity_I32); 11313 t2 = newTemp(Ity_I32); 11314 t3 = newTemp(Ity_I1); 11315 t4 = newTemp(Ity_I32); 11316 t5 = newTemp(Ity_I64); 11317 11318 assign(t5, getAcc(ac)); 11319 11320 assign(t0, unop(Iop_16Sto32, 11321 unop(Iop_32to16, getIReg(rs)))); 11322 assign(t1, unop(Iop_16Sto32, 11323 unop(Iop_32to16, getIReg(rt)))); 11324 11325 assign(t2, binop(Iop_And32, 11326 unop(Iop_1Sto32, 11327 binop(Iop_CmpEQ32, 11328 binop(Iop_And32, 11329 mkexpr(t0), 11330 mkU32(0xffff)), 11331 mkU32(0x8000))), 11332 unop(Iop_1Sto32, 11333 binop(Iop_CmpEQ32, 11334 binop(Iop_And32, 11335 mkexpr(t1), 11336 mkU32(0xffff)), 11337 mkU32(0x8000))))); 11338 11339 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0))); 11340 11341 putDSPControl(IRExpr_ITE(mkexpr(t3), 11342 getDSPControl(), 11343 binop(Iop_Or32, 11344 getDSPControl(), 11345 binop(Iop_Shl32, 11346 mkU32(0x1), 11347 mkU8(ac+16))))); 11348 11349 assign(t4, unop(Iop_64to32, 11350 binop(Iop_MullS32, 11351 mkexpr(t0), mkexpr(t1)))); 11352 putAcc(ac, IRExpr_ITE(mkexpr(t3), 11353 binop(Iop_Add64, 11354 unop(Iop_32Sto64, 11355 binop(Iop_Shl32, 11356 mkexpr(t4), 11357 mkU8(0x1))), 11358 mkexpr(t5)), 11359 binop(Iop_Add64, 11360 mkexpr(t5), 11361 unop(Iop_32Sto64, 11362 mkU32(0x7fffffff))))); 11363 break; 11364 } 11365 case 0x18: { /* DPAQX_S.W.PH */ 11366 DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 11367 vassert(!mode64); 11368 t0 = newTemp(Ity_I64); 11369 t1 = newTemp(Ity_I64); 11370 t2 = newTemp(Ity_I1); 11371 t3 = newTemp(Ity_I1); 11372 t4 = newTemp(Ity_I64); 11373 t5 = newTemp(Ity_I64); 11374 t6 = newTemp(Ity_I1); 11375 t7 = newTemp(Ity_I1); 11376 t8 = newTemp(Ity_I64); 11377 t9 = newTemp(Ity_I64); 11378 11379 assign(t0, getAcc(ac)); 11380 11381 assign(t1, binop(Iop_Shl64, 11382 binop(Iop_MullS32, 11383 unop(Iop_16Sto32, 11384 unop(Iop_32HIto16, 11385 getIReg(rs))), 11386 unop(Iop_16Sto32, 11387 unop(Iop_32to16, 11388 getIReg(rt)))), 11389 mkU8(0x1))); 11390 assign(t2, binop(Iop_CmpEQ32, 11391 unop(Iop_16Uto32, 11392 unop(Iop_32HIto16, getIReg(rs))), 11393 mkU32(0x00008000))); 11394 assign(t3, binop(Iop_CmpEQ32, 11395 unop(Iop_16Uto32, 11396 unop(Iop_32to16, getIReg(rt))), 11397 mkU32(0x00008000))); 11398 assign(t4, 11399 IRExpr_ITE(mkexpr(t2), 11400 IRExpr_ITE(mkexpr(t3), 11401 mkU64(0x000000007fffffffULL), 11402 mkexpr(t1)), 11403 mkexpr(t1))); 11404 11405 putDSPControl(IRExpr_ITE(mkexpr(t2), 11406 IRExpr_ITE(mkexpr(t3), 11407 binop(Iop_Or32, 11408 getDSPControl(), 11409 binop(Iop_Shl32, 11410 mkU32(0x1), 11411 mkU8(ac+16))), 11412 getDSPControl()), 11413 getDSPControl())); 11414 11415 assign(t5, binop(Iop_Shl64, 11416 binop(Iop_MullS32, 11417 unop(Iop_16Sto32, 11418 unop(Iop_32to16, 11419 getIReg(rs))), 11420 unop(Iop_16Sto32, 11421 unop(Iop_32HIto16, 11422 getIReg(rt)))), 11423 mkU8(0x1))); 11424 assign(t6, binop(Iop_CmpEQ32, 11425 unop(Iop_16Uto32, 11426 unop(Iop_32to16, getIReg(rs))), 11427 mkU32(0x00008000))); 11428 assign(t7, binop(Iop_CmpEQ32, 11429 unop(Iop_16Uto32, 11430 unop(Iop_32HIto16, getIReg(rt))), 11431 mkU32(0x00008000))); 11432 assign(t8, 11433 IRExpr_ITE(mkexpr(t6), 11434 IRExpr_ITE(mkexpr(t7), 11435 mkU64(0x000000007fffffffULL), 11436 mkexpr(t5)), 11437 mkexpr(t5))); 11438 11439 putDSPControl(IRExpr_ITE(mkexpr(t6), 11440 IRExpr_ITE(mkexpr(t7), 11441 binop(Iop_Or32, 11442 getDSPControl(), 11443 binop(Iop_Shl32, 11444 mkU32(0x1), 11445 mkU8(ac+16) 11446 ) 11447 ), 11448 getDSPControl()), 11449 getDSPControl())); 11450 11451 assign(t9, binop(Iop_Add64, 11452 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)), 11453 mkexpr(t0))); 11454 putAcc(ac, mkexpr(t9)); 11455 break; 11456 } 11457 case 0x19: { /* DPSQX_S.W.PH */ 11458 DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 11459 vassert(!mode64); 11460 t0 = newTemp(Ity_I64); 11461 t1 = newTemp(Ity_I64); 11462 t2 = newTemp(Ity_I1); 11463 t3 = newTemp(Ity_I1); 11464 t4 = newTemp(Ity_I64); 11465 t5 = newTemp(Ity_I64); 11466 t6 = newTemp(Ity_I1); 11467 t7 = newTemp(Ity_I1); 11468 t8 = newTemp(Ity_I64); 11469 t9 = newTemp(Ity_I64); 11470 11471 assign(t0, getAcc(ac)); 11472 11473 assign(t1, binop(Iop_Shl64, 11474 binop(Iop_MullS32, 11475 unop(Iop_16Sto32, 11476 unop(Iop_32HIto16, 11477 getIReg(rs))), 11478 unop(Iop_16Sto32, 11479 unop(Iop_32to16, 11480 getIReg(rt)))), 11481 mkU8(0x1))); 11482 assign(t2, binop(Iop_CmpEQ32, 11483 unop(Iop_16Uto32, 11484 unop(Iop_32HIto16, getIReg(rs))), 11485 mkU32(0x00008000))); 11486 assign(t3, binop(Iop_CmpEQ32, 11487 unop(Iop_16Uto32, 11488 unop(Iop_32to16, getIReg(rt))), 11489 mkU32(0x00008000))); 11490 assign(t4, 11491 IRExpr_ITE(mkexpr(t2), 11492 IRExpr_ITE(mkexpr(t3), 11493 mkU64(0x000000007fffffffULL), 11494 mkexpr(t1)), 11495 mkexpr(t1))); 11496 11497 putDSPControl(IRExpr_ITE(mkexpr(t2), 11498 IRExpr_ITE(mkexpr(t3), 11499 binop(Iop_Or32, 11500 getDSPControl(), 11501 binop(Iop_Shl32, 11502 mkU32(0x1), 11503 mkU8(ac+16) 11504 ) 11505 ), 11506 getDSPControl()), 11507 getDSPControl())); 11508 11509 assign(t5, binop(Iop_Shl64, 11510 binop(Iop_MullS32, 11511 unop(Iop_16Sto32, 11512 unop(Iop_32to16, 11513 getIReg(rs))), 11514 unop(Iop_16Sto32, 11515 unop(Iop_32HIto16, 11516 getIReg(rt)))), 11517 mkU8(0x1))); 11518 assign(t6, binop(Iop_CmpEQ32, 11519 unop(Iop_16Uto32, 11520 unop(Iop_32to16, getIReg(rs))), 11521 mkU32(0x00008000))); 11522 assign(t7, binop(Iop_CmpEQ32, 11523 unop(Iop_16Uto32, 11524 unop(Iop_32HIto16, getIReg(rt))), 11525 mkU32(0x00008000))); 11526 assign(t8, 11527 IRExpr_ITE(mkexpr(t6), 11528 IRExpr_ITE(mkexpr(t7), 11529 mkU64(0x000000007fffffffULL), 11530 mkexpr(t5)), 11531 mkexpr(t5))); 11532 11533 putDSPControl(IRExpr_ITE(mkexpr(t6), 11534 IRExpr_ITE(mkexpr(t7), 11535 binop(Iop_Or32, 11536 getDSPControl(), 11537 binop(Iop_Shl32, 11538 mkU32(0x1), 11539 mkU8(ac+16) 11540 ) 11541 ), 11542 getDSPControl()), 11543 getDSPControl())); 11544 11545 assign(t9, binop(Iop_Sub64, 11546 mkexpr(t0), 11547 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)))); 11548 putAcc(ac, mkexpr(t9)); 11549 break; 11550 } 11551 case 0x1A: { /* DPAQX_SA.W.PH */ 11552 DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt); 11553 vassert(!mode64); 11554 t0 = newTemp(Ity_I64); 11555 t1 = newTemp(Ity_I64); 11556 t2 = newTemp(Ity_I1); 11557 t3 = newTemp(Ity_I1); 11558 t4 = newTemp(Ity_I64); 11559 t5 = newTemp(Ity_I64); 11560 t6 = newTemp(Ity_I1); 11561 t7 = newTemp(Ity_I1); 11562 t8 = newTemp(Ity_I64); 11563 t9 = newTemp(Ity_I64); 11564 t10 = newTemp(Ity_I32); 11565 11566 assign(t0, getAcc(ac)); 11567 /* Calculate the first cross dot product and saturate if 11568 needed. */ 11569 assign(t1, unop(Iop_32Sto64, 11570 binop(Iop_Shl32, 11571 binop(Iop_Mul32, 11572 unop(Iop_16Sto32, 11573 unop(Iop_32HIto16, 11574 getIReg(rs))), 11575 unop(Iop_16Sto32, 11576 unop(Iop_32to16, 11577 getIReg(rt)))), 11578 mkU8(0x1)))); 11579 11580 /* If both input arguments are equal 0x8000, saturate 11581 intermediate product and write to DSPControl 11582 register. */ 11583 assign(t2, binop(Iop_CmpEQ32, 11584 unop(Iop_16Uto32, 11585 unop(Iop_32HIto16, getIReg(rs))), 11586 mkU32(0x00008000))); 11587 assign(t3, binop(Iop_CmpEQ32, 11588 unop(Iop_16Uto32, 11589 unop(Iop_32to16, getIReg(rt))), 11590 mkU32(0x00008000))); 11591 11592 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 11593 binop(Iop_And32, 11594 unop(Iop_1Sto32, 11595 mkexpr(t2)), 11596 unop(Iop_1Sto32, 11597 mkexpr(t3))), 11598 mkU32(0)), 11599 mkU64(0x000000007fffffffULL), 11600 mkexpr(t1))); 11601 11602 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11603 binop(Iop_And32, 11604 unop(Iop_1Sto32, 11605 mkexpr(t2)), 11606 unop(Iop_1Sto32, 11607 mkexpr(t3))), 11608 mkU32(0)), 11609 binop(Iop_Or32, 11610 getDSPControl(), 11611 binop(Iop_Shl32, 11612 mkU32(0x1), 11613 mkU8(ac+16))), 11614 getDSPControl())); 11615 /* Calculate second cross dot product and saturate if 11616 needed. */ 11617 assign(t5, unop(Iop_32Sto64, 11618 binop(Iop_Shl32, 11619 binop(Iop_Mul32, 11620 unop(Iop_16Sto32, 11621 unop(Iop_32to16, 11622 getIReg(rs))), 11623 unop(Iop_16Sto32, 11624 unop(Iop_32HIto16, 11625 getIReg(rt)))), 11626 mkU8(0x1)))); 11627 11628 /* If both input arguments are equal 0x8000, saturate 11629 intermediate product and write to DSPControl 11630 register. */ 11631 assign(t6, binop(Iop_CmpEQ32, 11632 unop(Iop_16Uto32, 11633 unop(Iop_32to16, getIReg(rs))), 11634 mkU32(0x00008000))); 11635 assign(t7, binop(Iop_CmpEQ32, 11636 unop(Iop_16Uto32, 11637 unop(Iop_32HIto16, getIReg(rt))), 11638 mkU32(0x00008000))); 11639 11640 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32, 11641 binop(Iop_And32, 11642 unop(Iop_1Sto32, 11643 mkexpr(t6)), 11644 unop(Iop_1Sto32, 11645 mkexpr(t7))), 11646 mkU32(0)), 11647 mkU64(0x000000007fffffffULL), 11648 mkexpr(t5))); 11649 11650 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11651 binop(Iop_And32, 11652 unop(Iop_1Sto32, 11653 mkexpr(t6)), 11654 unop(Iop_1Sto32, 11655 mkexpr(t7))), 11656 mkU32(0)), 11657 binop(Iop_Or32, 11658 getDSPControl(), 11659 binop(Iop_Shl32, 11660 mkU32(0x1), 11661 mkU8(ac+16))), 11662 getDSPControl())); 11663 /* Subtract intermediate products from value in the 11664 accumulator. */ 11665 assign(t9, 11666 binop(Iop_Add64, 11667 mkexpr(t0), 11668 binop(Iop_Add64, mkexpr(t8), mkexpr(t4)))); 11669 11670 putAcc(ac, 11671 IRExpr_ITE(binop(Iop_CmpEQ32, 11672 binop(Iop_And32, 11673 unop(Iop_64HIto32, 11674 mkexpr(t9)), 11675 mkU32(0x80000000)), 11676 mkU32(0x0)), 11677 IRExpr_ITE(binop(Iop_CmpNE32, 11678 unop(Iop_64HIto32, 11679 binop(Iop_Shl64, 11680 mkexpr(t9), 11681 mkU8(1))), 11682 mkU32(0x0)), 11683 mkU64(0x000000007fffffffULL), 11684 mkexpr(t9)), 11685 IRExpr_ITE(binop(Iop_CmpNE32, 11686 unop(Iop_64HIto32, 11687 binop(Iop_Shl64, 11688 mkexpr(t9), 11689 mkU8(1))), 11690 mkU32(0xffffffff)), 11691 mkU64(0xffffffff80000000ULL), 11692 mkexpr(t9)))); 11693 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32, 11694 unop(Iop_64to32, 11695 mkexpr(t9)), 11696 unop(Iop_64to32, 11697 getAcc(ac))), 11698 getDSPControl(), 11699 binop(Iop_Or32, 11700 getDSPControl(), 11701 binop(Iop_Shl32, 11702 mkU32(0x1), 11703 mkU8(ac+16))))); 11704 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 11705 unop(Iop_64HIto32, 11706 mkexpr(t9)), 11707 unop(Iop_64HIto32, 11708 getAcc(ac))), 11709 mkexpr(t10), 11710 binop(Iop_Or32, 11711 getDSPControl(), 11712 binop(Iop_Shl32, 11713 mkU32(0x1), 11714 mkU8(ac+16))))); 11715 break; 11716 } 11717 case 0x1B: { /* DPSQX_SA.W.PH */ 11718 DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt); 11719 vassert(!mode64); 11720 t0 = newTemp(Ity_I64); 11721 t1 = newTemp(Ity_I64); 11722 t2 = newTemp(Ity_I1); 11723 t3 = newTemp(Ity_I1); 11724 t4 = newTemp(Ity_I64); 11725 t5 = newTemp(Ity_I64); 11726 t6 = newTemp(Ity_I1); 11727 t7 = newTemp(Ity_I1); 11728 t8 = newTemp(Ity_I64); 11729 t9 = newTemp(Ity_I64); 11730 t10 = newTemp(Ity_I32); 11731 11732 assign(t0, getAcc(ac)); 11733 /* Calculate the first cross dot product and saturate if 11734 needed. */ 11735 assign(t1, unop(Iop_32Sto64, 11736 binop(Iop_Shl32, 11737 binop(Iop_Mul32, 11738 unop(Iop_16Sto32, 11739 unop(Iop_32HIto16, 11740 getIReg(rs))), 11741 unop(Iop_16Sto32, 11742 unop(Iop_32to16, 11743 getIReg(rt)))), 11744 mkU8(0x1)))); 11745 11746 /* If both input arguments are equal 0x8000, saturate 11747 intermediate product and write to DSPControl 11748 register. */ 11749 assign(t2, binop(Iop_CmpEQ32, 11750 unop(Iop_16Uto32, 11751 unop(Iop_32HIto16, getIReg(rs))), 11752 mkU32(0x00008000))); 11753 assign(t3, binop(Iop_CmpEQ32, 11754 unop(Iop_16Uto32, 11755 unop(Iop_32to16, getIReg(rt))), 11756 mkU32(0x00008000))); 11757 11758 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 11759 binop(Iop_And32, 11760 unop(Iop_1Sto32, 11761 mkexpr(t2)), 11762 unop(Iop_1Sto32, 11763 mkexpr(t3))), 11764 mkU32(0)), 11765 mkU64(0x000000007fffffffULL), 11766 mkexpr(t1))); 11767 11768 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11769 binop(Iop_And32, 11770 unop(Iop_1Sto32, 11771 mkexpr(t2)), 11772 unop(Iop_1Sto32, 11773 mkexpr(t3))), 11774 mkU32(0)), 11775 binop(Iop_Or32, 11776 getDSPControl(), 11777 binop(Iop_Shl32, 11778 mkU32(0x1), 11779 mkU8(ac+16))), 11780 getDSPControl())); 11781 /* Calculate second cross dot product and saturate if 11782 needed. */ 11783 assign(t5, unop(Iop_32Sto64, 11784 binop(Iop_Shl32, 11785 binop(Iop_Mul32, 11786 unop(Iop_16Sto32, 11787 unop(Iop_32to16, 11788 getIReg(rs))), 11789 unop(Iop_16Sto32, 11790 unop(Iop_32HIto16, 11791 getIReg(rt)))), 11792 mkU8(0x1)))); 11793 11794 /* If both input arguments are equal 0x8000, saturate 11795 intermediate product and write to DSPControl 11796 register. */ 11797 assign(t6, binop(Iop_CmpEQ32, 11798 unop(Iop_16Uto32, 11799 unop(Iop_32to16, getIReg(rs))), 11800 mkU32(0x00008000))); 11801 assign(t7, binop(Iop_CmpEQ32, 11802 unop(Iop_16Uto32, 11803 unop(Iop_32HIto16, getIReg(rt))), 11804 mkU32(0x00008000))); 11805 11806 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32, 11807 binop(Iop_And32, 11808 unop(Iop_1Sto32, 11809 mkexpr(t6)), 11810 unop(Iop_1Sto32, 11811 mkexpr(t7))), 11812 mkU32(0)), 11813 mkU64(0x000000007fffffffULL), 11814 mkexpr(t5))); 11815 11816 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11817 binop(Iop_And32, 11818 unop(Iop_1Sto32, 11819 mkexpr(t6)), 11820 unop(Iop_1Sto32, 11821 mkexpr(t7))), 11822 mkU32(0)), 11823 binop(Iop_Or32, 11824 getDSPControl(), 11825 binop(Iop_Shl32, 11826 mkU32(0x1), 11827 mkU8(ac+16))), 11828 getDSPControl())); 11829 /* Subtract intermediate products from value in the 11830 accumulator. */ 11831 assign(t9, 11832 binop(Iop_Sub64, 11833 mkexpr(t0), 11834 binop(Iop_Add64, mkexpr(t8), mkexpr(t4)))); 11835 11836 putAcc(ac, 11837 IRExpr_ITE(binop(Iop_CmpEQ32, 11838 binop(Iop_And32, 11839 unop(Iop_64HIto32, 11840 mkexpr(t9)), 11841 mkU32(0x80000000)), 11842 mkU32(0x0)), 11843 IRExpr_ITE(binop(Iop_CmpNE32, 11844 unop(Iop_64HIto32, 11845 binop(Iop_Shl64, 11846 mkexpr(t9), 11847 mkU8(1))), 11848 mkU32(0x0)), 11849 mkU64(0x000000007fffffffULL), 11850 mkexpr(t9)), 11851 IRExpr_ITE(binop(Iop_CmpNE32, 11852 unop(Iop_64HIto32, 11853 binop(Iop_Shl64, 11854 mkexpr(t9), 11855 mkU8(1))), 11856 mkU32(0xffffffff)), 11857 mkU64(0xffffffff80000000ULL), 11858 mkexpr(t9)))); 11859 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32, 11860 unop(Iop_64to32, 11861 mkexpr(t9)), 11862 unop(Iop_64to32, 11863 getAcc(ac))), 11864 getDSPControl(), 11865 binop(Iop_Or32, 11866 getDSPControl(), 11867 binop(Iop_Shl32, 11868 mkU32(0x1), 11869 mkU8(ac+16))))); 11870 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 11871 unop(Iop_64HIto32, 11872 mkexpr(t9)), 11873 unop(Iop_64HIto32, 11874 getAcc(ac))), 11875 mkexpr(t10), 11876 binop(Iop_Or32, 11877 getDSPControl(), 11878 binop(Iop_Shl32, 11879 mkU32(0x1), 11880 mkU8(ac+16))))); 11881 break; 11882 } 11883 default: 11884 return -1; 11885 } 11886 break; /* end of DPAQ.W.PH */ 11887 } 11888 case 0x31: { /* APPEND */ 11889 switch(sa) { 11890 case 0x0: { /* APPEND */ 11891 DIP("append r%u, r%u, %u", rt, rs, rd); 11892 vassert(!mode64); 11893 t1 = newTemp(Ity_I32); 11894 t2 = newTemp(Ity_I32); 11895 t3 = newTemp(Ity_I32); 11896 11897 assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd))); 11898 11899 if (31 == rd) { 11900 putIReg(rt, binop(Iop_Or32, 11901 mkexpr(t1), 11902 binop(Iop_And32, 11903 getIReg(rs), 11904 mkU32(0x7fffffff)))); 11905 } else if (1 == rd) { 11906 putIReg(rt, 11907 binop(Iop_Or32, 11908 mkexpr(t1), 11909 binop(Iop_And32, 11910 getIReg(rs), mkU32(0x1)))); 11911 } else { 11912 assign(t2, 11913 unop(Iop_Not32, 11914 binop(Iop_Shl32, 11915 mkU32(0xffffffff), mkU8(rd)))); 11916 11917 putIReg(rt, binop(Iop_Or32, 11918 mkexpr(t1), 11919 binop(Iop_And32, 11920 getIReg(rs), mkexpr(t2)))); 11921 } 11922 break; 11923 } 11924 case 0x1: { /* PREPEND */ 11925 DIP("prepend r%u, r%u, %u", rt, rs, rd); 11926 vassert(!mode64); 11927 t1 = newTemp(Ity_I32); 11928 t2 = newTemp(Ity_I32); 11929 t3 = newTemp(Ity_I32); 11930 11931 if (0 != rd) { 11932 assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd))); 11933 11934 if (31 == rd) { 11935 putIReg(rt, binop(Iop_Or32, 11936 mkexpr(t1), 11937 binop(Iop_Shl32, 11938 binop(Iop_And32, 11939 getIReg(rs), 11940 mkU32(0x7fffffff)), 11941 mkU8(1)))); 11942 } else if (1 == rd) { 11943 putIReg(rt, binop(Iop_Or32, 11944 mkexpr(t1), 11945 binop(Iop_Shl32, 11946 binop(Iop_And32, 11947 getIReg(rs), 11948 mkU32(0x1)), 11949 mkU8(31)))); 11950 } else { 11951 assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1))); 11952 11953 assign(t3, unop(Iop_Not32, 11954 binop(Iop_Shl32, 11955 mkU32(0xffffffff), 11956 unop(Iop_32to8, mkexpr(t2))))); 11957 11958 putIReg(rt, binop(Iop_Or32, 11959 mkexpr(t1), 11960 binop(Iop_Shl32, 11961 binop(Iop_And32, 11962 getIReg(rs), 11963 mkexpr(t3)), 11964 mkU8(32-rd)))); 11965 } 11966 } 11967 break; 11968 } 11969 case 0x10: { /* BALIGN */ 11970 DIP("balign r%u, r%u, %u", rt, rs, rd); 11971 vassert(!mode64); 11972 t1 = newTemp(Ity_I32); 11973 t2 = newTemp(Ity_I32); 11974 t3 = newTemp(Ity_I32); 11975 11976 if ((2 != rd) && (0 != rd)) { 11977 assign(t1, binop(Iop_Shl32, 11978 binop(Iop_And32, 11979 mkU32(rd), mkU32(0x3)), 11980 mkU8(0x3))); 11981 assign(t2, binop(Iop_Shl32, 11982 getIReg(rt), 11983 unop(Iop_32to8, mkexpr(t1)))); 11984 assign(t3, binop(Iop_Shr32, 11985 getIReg(rs), 11986 unop(Iop_32to8, 11987 binop(Iop_Shl32, 11988 binop(Iop_Sub32, 11989 mkU32(0x4), 11990 binop(Iop_And32, 11991 mkU32(rd), 11992 mkU32(0x3))), 11993 mkU8(0x3))))); 11994 putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3))); 11995 } 11996 break; 11997 } 11998 default: 11999 return -1; 12000 } 12001 break; /* end of APPEND */ 12002 } 12003 default: 12004 return -1; 12005 } 12006 break; 12007 } 12008 default: 12009 return -1; 12010 } 12011 return 0; 12012 } 12013 12014 /*------------------------------------------------------------*/ 12015 /*--- Disassemble a single instruction ---*/ 12016 /*------------------------------------------------------------*/ 12017 12018 /* Disassemble a single instruction into IR. The instruction is 12019 located in host memory at guest_instr, and has guest IP of 12020 guest_PC_curr_instr, which will have been set before the call 12021 here. */ 12022 12023 static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, 12024 Addr), 12025 Bool resteerCisOk, 12026 void* callback_opaque, 12027 Long delta64, 12028 const VexArchInfo* archinfo, 12029 const VexAbiInfo* abiinfo, 12030 Bool sigill_diag ) 12031 { 12032 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7; 12033 12034 UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function, 12035 trap_code, imm, instr_index, p, msb, lsb, size, rot, sel; 12036 /* Additional variables for instruction fields in DSP ASE insructions */ 12037 UInt ac; 12038 12039 DisResult dres; 12040 12041 static IRExpr *lastn = NULL; /* last jump addr */ 12042 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */ 12043 12044 /* The running delta */ 12045 Int delta = (Int) delta64; 12046 12047 /* Holds eip at the start of the insn, so that we can print 12048 consistent error messages for unimplemented insns. */ 12049 Int delta_start = delta; 12050 12051 /* Are we in a delay slot ? */ 12052 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump; 12053 12054 /* Set result defaults. */ 12055 dres.whatNext = Dis_Continue; 12056 dres.len = 0; 12057 dres.continueAt = 0; 12058 dres.jk_StopHere = Ijk_INVALID; 12059 12060 delay_slot_branch = likely_delay_slot = delay_slot_jump = False; 12061 12062 const UChar *code = guest_code + delta; 12063 cins = getUInt(code); 12064 DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins); 12065 12066 if (delta != 0) { 12067 if (branch_or_jump(guest_code + delta - 4)) { 12068 if (lastn == NULL && bstmt == NULL) { 12069 vassert(0); 12070 } else { 12071 dres.whatNext = Dis_StopHere; 12072 if (lastn != NULL) { 12073 delay_slot_jump = True; 12074 } else if (bstmt != NULL) { 12075 delay_slot_branch = True; 12076 } 12077 } 12078 } 12079 12080 if (branch_or_link_likely(guest_code + delta - 4)) { 12081 likely_delay_slot = True; 12082 } 12083 } 12084 12085 /* Spot "Special" instructions (see comment at top of file). */ 12086 { 12087 /* Spot the 16-byte preamble: 12088 ****mips32**** 12089 "srl $0, $0, 13 12090 "srl $0, $0, 29 12091 "srl $0, $0, 3 12092 "srl $0, $0, 19 12093 12094 ****mips64**** 12095 dsll $0, $0, 3 12096 dsll $0, $0, 13 12097 dsll $0, $0, 29 12098 dsll $0, $0, 19 */ 12099 12100 UInt word1 = mode64 ? 0xF8 : 0x342; 12101 UInt word2 = mode64 ? 0x378 : 0x742; 12102 UInt word3 = mode64 ? 0x778 : 0xC2; 12103 UInt word4 = mode64 ? 0x4F8 : 0x4C2; 12104 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 && 12105 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) { 12106 /* Got a "Special" instruction preamble. Which one is it? */ 12107 if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) { 12108 /* $11 = client_request ( $12 ) */ 12109 DIP("$11 = client_request ( $12 )"); 12110 if (mode64) 12111 putPC(mkU64(guest_PC_curr_instr + 20)); 12112 else 12113 putPC(mkU32(guest_PC_curr_instr + 20)); 12114 dres.jk_StopHere = Ijk_ClientReq; 12115 dres.whatNext = Dis_StopHere; 12116 12117 goto decode_success; 12118 } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) { 12119 /* $11 = guest_NRADDR */ 12120 DIP("$11 = guest_NRADDR"); 12121 dres.len = 20; 12122 delta += 20; 12123 if (mode64) 12124 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State, 12125 guest_NRADDR), Ity_I64)); 12126 else 12127 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, 12128 guest_NRADDR), Ity_I32)); 12129 goto decode_success; 12130 } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) { 12131 /* branch-and-link-to-noredir $25 */ 12132 DIP("branch-and-link-to-noredir $25"); 12133 if (mode64) 12134 putIReg(31, mkU64(guest_PC_curr_instr + 20)); 12135 else 12136 putIReg(31, mkU32(guest_PC_curr_instr + 20)); 12137 putPC(getIReg(25)); 12138 dres.jk_StopHere = Ijk_NoRedir; 12139 dres.whatNext = Dis_StopHere; 12140 goto decode_success; 12141 } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) { 12142 /* IR injection */ 12143 DIP("IR injection"); 12144 #if defined (_MIPSEL) 12145 vex_inject_ir(irsb, Iend_LE); 12146 #elif defined (_MIPSEB) 12147 vex_inject_ir(irsb, Iend_BE); 12148 #endif 12149 if (mode64) { 12150 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART), 12151 mkU64(guest_PC_curr_instr))); 12152 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN), 12153 mkU64(20))); 12154 12155 putPC(mkU64(guest_PC_curr_instr + 20)); 12156 } else { 12157 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART), 12158 mkU32(guest_PC_curr_instr))); 12159 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN), 12160 mkU32(20))); 12161 12162 putPC(mkU32(guest_PC_curr_instr + 20)); 12163 } 12164 dres.whatNext = Dis_StopHere; 12165 dres.jk_StopHere = Ijk_InvalICache; 12166 dres.len = 20; 12167 delta += 20; 12168 goto decode_success; 12169 } 12170 12171 /* We don't know what it is. Set opc1/opc2 so decode_failure 12172 can print the insn following the Special-insn preamble. */ 12173 delta += 16; 12174 goto decode_failure; 12175 /*NOTREACHED*/} 12176 } 12177 12178 opcode = get_opcode(cins); 12179 imm = get_imm(cins); 12180 rs = get_rs(cins); 12181 rt = get_rt(cins); 12182 rd = get_rd(cins); 12183 sa = get_sa(cins); 12184 fs = get_fs(cins); 12185 fd = get_fd(cins); 12186 ft = get_ft(cins); 12187 tf = get_tf(cins); 12188 nd = get_nd(cins); 12189 sel = get_sel(cins); 12190 fmt = get_fmt(cins); 12191 instr_index = get_instr_index(cins); 12192 trap_code = get_code(cins); 12193 function = get_function(cins); 12194 IRType ty = mode64 ? Ity_I64 : Ity_I32; 12195 IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32; 12196 12197 ac = get_acNo(cins); 12198 12199 switch (opcode) { 12200 12201 case 0x03: /* JAL */ 12202 DIP("jal 0x%x", instr_index); 12203 if (mode64) { 12204 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 12205 t0 = newTemp(ty); 12206 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) | 12207 (instr_index << 2))); 12208 } else { 12209 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 12210 t0 = newTemp(ty); 12211 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 12212 (instr_index << 2))); 12213 } 12214 lastn = mkexpr(t0); 12215 break; 12216 case 0x02: /* J */ 12217 DIP("j 0x%x", instr_index); 12218 t0 = newTemp(ty); 12219 if (mode64) 12220 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) | 12221 (instr_index << 2))); 12222 else 12223 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 12224 (instr_index << 2))); 12225 lastn = mkexpr(t0); 12226 break; 12227 12228 case 0x11: { /* COP1 */ 12229 if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */ 12230 DIP("mfhc1 r%u, f%u", rt, fs); 12231 if (fp_mode64) { 12232 t0 = newTemp(Ity_I64); 12233 t1 = newTemp(Ity_I32); 12234 assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs))); 12235 assign(t1, unop(Iop_64HIto32, mkexpr(t0))); 12236 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 12237 } else { 12238 ILLEGAL_INSTRUCTON; 12239 } 12240 break; 12241 } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */ 12242 DIP("mthc1 r%u, f%u", rt, fs); 12243 if (fp_mode64) { 12244 t0 = newTemp(Ity_I64); 12245 assign(t0, binop(Iop_32HLto64, getIReg(rt), 12246 unop(Iop_ReinterpF32asI32, 12247 getLoFromF64(Ity_F64 /* 32FPR mode. */, 12248 getDReg(fs))))); 12249 putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12250 } else { 12251 ILLEGAL_INSTRUCTON; 12252 } 12253 break; 12254 } else if (fmt == 0x8) { /* BC */ 12255 /* FcConditionalCode(bc1_cc) */ 12256 UInt bc1_cc = get_bc1_cc(cins); 12257 t1 = newTemp(Ity_I1); 12258 t2 = newTemp(Ity_I32); 12259 t3 = newTemp(Ity_I1); 12260 12261 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc))); 12262 assign(t2, IRExpr_ITE(mkexpr(t1), 12263 binop(Iop_And32, 12264 binop(Iop_Shr32, getFCSR(), mkU8(23)), 12265 mkU32(0x1)), 12266 binop(Iop_And32, 12267 binop(Iop_Shr32, getFCSR(), 12268 mkU8(24 + bc1_cc)), 12269 mkU32(0x1)))); 12270 12271 if (tf == 1 && nd == 0) { 12272 /* branch on true */ 12273 DIP("bc1t %u, %u", bc1_cc, imm); 12274 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12275 dis_branch(False, mkexpr(t3), imm, &bstmt); 12276 break; 12277 } else if (tf == 0 && nd == 0) { 12278 /* branch on false */ 12279 DIP("bc1f %u, %u", bc1_cc, imm); 12280 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12281 dis_branch(False, mkexpr(t3), imm, &bstmt); 12282 break; 12283 } else if (nd == 1 && tf == 0) { 12284 DIP("bc1fl %u, %u", bc1_cc, imm); 12285 lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2), 12286 mkU32(0x0)), imm); 12287 break; 12288 } else if (nd == 1 && tf == 1) { 12289 DIP("bc1tl %u, %u", bc1_cc, imm); 12290 lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2), 12291 mkU32(0x0)), imm); 12292 break; 12293 } else 12294 goto decode_failure; 12295 } else { 12296 switch (function) { 12297 case 0x4: { /* SQRT.fmt */ 12298 switch (fmt) { 12299 case 0x10: { /* S */ 12300 IRExpr *rm = get_IR_roundingmode(); 12301 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm, 12302 getLoFromF64(tyF, getFReg(fs))))); 12303 break; 12304 } 12305 case 0x11: { /* D */ 12306 IRExpr *rm = get_IR_roundingmode(); 12307 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs))); 12308 break; 12309 } 12310 default: 12311 goto decode_failure; 12312 } 12313 } 12314 break; 12315 case 0x5: /* abs.fmt */ 12316 switch (fmt) { 12317 case 0x10: /* S */ 12318 DIP("abs.s f%u, f%u", fd, fs); 12319 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32, 12320 getLoFromF64(tyF, getFReg(fs))))); 12321 break; 12322 case 0x11: /* D */ 12323 DIP("abs.d f%u, f%u", fd, fs); 12324 putDReg(fd, unop(Iop_AbsF64, getDReg(fs))); 12325 break; 12326 default: 12327 goto decode_failure; 12328 } 12329 break; /* case 0x5 */ 12330 12331 case 0x02: /* MUL.fmt */ 12332 switch (fmt) { 12333 case 0x11: { /* D */ 12334 DIP("mul.d f%u, f%u, f%u", fd, fs, ft); 12335 IRExpr *rm = get_IR_roundingmode(); 12336 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs), 12337 getDReg(ft))); 12338 break; 12339 } 12340 case 0x10: { /* S */ 12341 DIP("mul.s f%u, f%u, f%u", fd, fs, ft); 12342 IRExpr *rm = get_IR_roundingmode(); 12343 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm, 12344 getLoFromF64(tyF, getFReg(fs)), 12345 getLoFromF64(tyF, getFReg(ft))))); 12346 break; 12347 } 12348 default: 12349 goto decode_failure; 12350 } 12351 break; /* MUL.fmt */ 12352 12353 case 0x03: /* DIV.fmt */ 12354 switch (fmt) { 12355 case 0x11: { /* D */ 12356 DIP("div.d f%u, f%u, f%u", fd, fs, ft); 12357 IRExpr *rm = get_IR_roundingmode(); 12358 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs), 12359 getDReg(ft))); 12360 break; 12361 } 12362 case 0x10: { /* S */ 12363 DIP("div.s f%u, f%u, f%u", fd, fs, ft); 12364 calculateFCSR(fs, ft, DIVS, False, 2); 12365 IRExpr *rm = get_IR_roundingmode(); 12366 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 12367 getLoFromF64(tyF, getFReg(fs)), 12368 getLoFromF64(tyF, getFReg(ft))))); 12369 break; 12370 } 12371 default: 12372 goto decode_failure; 12373 } 12374 break; /* DIV.fmt */ 12375 12376 case 0x01: /* SUB.fmt */ 12377 switch (fmt) { 12378 case 0x11: { /* D */ 12379 DIP("sub.d f%u, f%u, f%u", fd, fs, ft); 12380 calculateFCSR(fs, ft, SUBD, False, 2); 12381 IRExpr *rm = get_IR_roundingmode(); 12382 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), 12383 getDReg(ft))); 12384 break; 12385 } 12386 case 0x10: { /* S */ 12387 DIP("sub.s f%u, f%u, f%u", fd, fs, ft); 12388 calculateFCSR(fs, ft, SUBS, True, 2); 12389 IRExpr *rm = get_IR_roundingmode(); 12390 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm, 12391 getLoFromF64(tyF, getFReg(fs)), 12392 getLoFromF64(tyF, getFReg(ft))))); 12393 break; 12394 } 12395 default: 12396 goto decode_failure; 12397 } 12398 break; /* SUB.fmt */ 12399 12400 case 0x06: /* MOV.fmt */ 12401 switch (fmt) { 12402 case 0x11: /* D */ 12403 DIP("mov.d f%u, f%u", fd, fs); 12404 if (fp_mode64) { 12405 putDReg(fd, getDReg(fs)); 12406 } else { 12407 putFReg(fd, getFReg(fs)); 12408 putFReg(fd + 1, getFReg(fs + 1)); 12409 } 12410 break; 12411 case 0x10: /* S */ 12412 DIP("mov.s f%u, f%u", fd, fs); 12413 putFReg(fd, getFReg(fs)); 12414 break; 12415 default: 12416 goto decode_failure; 12417 } 12418 break; /* MOV.fmt */ 12419 12420 case 0x7: /* neg.fmt */ 12421 switch (fmt) { 12422 case 0x10: /* S */ 12423 DIP("neg.s f%u, f%u", fd, fs); 12424 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, 12425 getLoFromF64(tyF, getFReg(fs))))); 12426 break; 12427 case 0x11: /* D */ 12428 DIP("neg.d f%u, f%u", fd, fs); 12429 putDReg(fd, unop(Iop_NegF64, getDReg(fs))); 12430 break; 12431 default: 12432 goto decode_failure; 12433 } 12434 break; /* case 0x7 */ 12435 12436 case 0x08: /* ROUND.L.fmt */ 12437 switch (fmt) { 12438 case 0x10: /* S */ 12439 DIP("round.l.s f%u, f%u", fd, fs); 12440 if (fp_mode64) { 12441 calculateFCSR(fs, 0, ROUNDLS, True, 1); 12442 t0 = newTemp(Ity_I64); 12443 12444 assign(t0, binop(Iop_F32toI64S, mkU32(0x0), 12445 getLoFromF64(Ity_F64, getFReg(fs)))); 12446 12447 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12448 } else { 12449 ILLEGAL_INSTRUCTON; 12450 } 12451 break; 12452 case 0x11: /* D */ 12453 DIP("round.l.d f%u, f%u", fd, fs); 12454 if (fp_mode64) { 12455 calculateFCSR(fs, 0, ROUNDLD, False, 1); 12456 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0), 12457 getDReg(fs))); 12458 } else { 12459 ILLEGAL_INSTRUCTON; 12460 } 12461 break; 12462 default: 12463 goto decode_failure; 12464 12465 } 12466 break; /* ROUND.L.fmt */ 12467 12468 case 0x09: /* TRUNC.L.fmt */ 12469 switch (fmt) { 12470 case 0x10: /* S */ 12471 DIP("trunc.l.s f%u, f%u", fd, fs); 12472 if (fp_mode64) { 12473 calculateFCSR(fs, 0, TRUNCLS, True, 1); 12474 t0 = newTemp(Ity_I64); 12475 assign(t0, binop(Iop_F32toI64S, mkU32(0x3), 12476 getLoFromF64(Ity_F64, getFReg(fs)))); 12477 12478 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12479 } else { 12480 ILLEGAL_INSTRUCTON; 12481 } 12482 break; 12483 case 0x11: /* D */ 12484 DIP("trunc.l.d f%u, f%u", fd, fs); 12485 if (fp_mode64) { 12486 calculateFCSR(fs, 0, TRUNCLD, False, 1); 12487 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3), 12488 getDReg(fs))); 12489 } else { 12490 ILLEGAL_INSTRUCTON; 12491 } 12492 break; 12493 default: 12494 goto decode_failure; 12495 } 12496 break; /* TRUNC.L.fmt */ 12497 12498 case 0x15: /* RECIP.fmt */ 12499 switch (fmt) { 12500 case 0x10: { /* S */ 12501 DIP("recip.s f%u, f%u", fd, fs); 12502 IRExpr *rm = get_IR_roundingmode(); 12503 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, 12504 rm, unop(Iop_ReinterpI32asF32, 12505 mkU32(ONE_SINGLE)), getLoFromF64(tyF, 12506 getFReg(fs))))); 12507 break; 12508 } 12509 case 0x11: { /* D */ 12510 DIP("recip.d f%u, f%u", fd, fs); 12511 IRExpr *rm = get_IR_roundingmode(); 12512 /* putDReg(fd, 1.0/getDreg(fs)); */ 12513 putDReg(fd, triop(Iop_DivF64, rm, 12514 unop(Iop_ReinterpI64asF64, 12515 mkU64(ONE_DOUBLE)), getDReg(fs))); 12516 break; 12517 } 12518 default: 12519 goto decode_failure; 12520 12521 } 12522 break; /* case 0x15 */ 12523 12524 case 0x13: /* MOVN.fmt */ 12525 switch (fmt) { 12526 case 0x10: /* S */ 12527 DIP("movn.s f%u, f%u, r%u", fd, fs, rt); 12528 t1 = newTemp(Ity_F64); 12529 t2 = newTemp(Ity_F64); 12530 t3 = newTemp(Ity_I1); 12531 t4 = newTemp(Ity_F64); 12532 if (mode64) { 12533 assign(t1, getFReg(fs)); 12534 assign(t2, getFReg(fd)); 12535 assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); 12536 } else { 12537 if (fp_mode64) { 12538 assign(t1, getFReg(fs)); 12539 assign(t2, getFReg(fd)); 12540 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); 12541 } else { 12542 assign(t1, unop(Iop_F32toF64, getFReg(fs))); 12543 assign(t2, unop(Iop_F32toF64, getFReg(fd))); 12544 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); 12545 } 12546 } 12547 12548 assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2))); 12549 if (fp_mode64) { 12550 IRTemp f = newTemp(Ity_F64); 12551 IRTemp fd_hi = newTemp(Ity_I32); 12552 t5 = newTemp(Ity_I64); 12553 assign(f, getFReg(fd)); 12554 assign(fd_hi, unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64, 12555 mkexpr(f)))); 12556 12557 assign(t5, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12558 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True)); 12559 12560 putFReg(fd, unop (Iop_ReinterpI64asF64, mkexpr(t5))); 12561 } else 12562 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12563 mkexpr(t4))); 12564 break; 12565 case 0x11: /* D */ 12566 DIP("movn.d f%u, f%u, r%u", fd, fs, rt); 12567 12568 t3 = newTemp(Ity_I1); 12569 t4 = newTemp(Ity_F64); 12570 12571 if (mode64) 12572 assign(t3, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); 12573 else 12574 assign(t3, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); 12575 12576 putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd))); 12577 break; 12578 default: 12579 goto decode_failure; 12580 } 12581 break; /* MOVN.fmt */ 12582 12583 case 0x12: /* MOVZ.fmt */ 12584 switch (fmt) { 12585 case 0x10: /* S */ 12586 DIP("movz.s f%u, f%u, r%u", fd, fs, rt); 12587 12588 t1 = newTemp(Ity_F64); 12589 t2 = newTemp(Ity_F64); 12590 t3 = newTemp(Ity_I1); 12591 t4 = newTemp(Ity_F64); 12592 if (fp_mode64) { 12593 assign(t1, getFReg(fs)); 12594 assign(t2, getFReg(fd)); 12595 if (mode64) 12596 assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); 12597 else 12598 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); 12599 } else { 12600 assign(t1, unop(Iop_F32toF64, getFReg(fs))); 12601 assign(t2, unop(Iop_F32toF64, getFReg(fd))); 12602 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); 12603 } 12604 assign(t4, IRExpr_ITE(mkexpr(t3), mkexpr(t1), mkexpr(t2))); 12605 12606 if (fp_mode64) { 12607 IRTemp f = newTemp(Ity_F64); 12608 IRTemp fd_hi = newTemp(Ity_I32); 12609 t7 = newTemp(Ity_I64); 12610 assign(f, getFReg(fd)); 12611 assign(fd_hi, unop(Iop_64HIto32, 12612 unop(Iop_ReinterpF64asI64, mkexpr(f)))); 12613 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12614 unop(Iop_ReinterpF64asI64, mkexpr(t4))), True)); 12615 12616 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); 12617 } else 12618 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12619 mkexpr(t4))); 12620 12621 break; 12622 case 0x11: /* D */ 12623 DIP("movz.d f%u, f%u, r%u", fd, fs, rt); 12624 t3 = newTemp(Ity_I1); 12625 t4 = newTemp(Ity_F64); 12626 if (mode64) 12627 assign(t3, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); 12628 else 12629 assign(t3, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); 12630 12631 putDReg(fd, IRExpr_ITE(mkexpr(t3), getDReg(fs), getDReg(fd))); 12632 break; 12633 default: 12634 goto decode_failure; 12635 } 12636 break; /* MOVZ.fmt */ 12637 12638 case 0x11: /* MOVT.fmt */ 12639 if (tf == 1) { 12640 UInt mov_cc = get_mov_cc(cins); 12641 switch (fmt) { /* MOVCF = 010001 */ 12642 case 0x11: /* D */ 12643 DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc); 12644 t1 = newTemp(Ity_I1); 12645 t2 = newTemp(Ity_I32); 12646 t3 = newTemp(Ity_I1); 12647 t4 = newTemp(Ity_F64); 12648 12649 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12650 assign(t2, IRExpr_ITE(mkexpr(t1), 12651 binop(Iop_And32, 12652 binop(Iop_Shr32, getFCSR(), 12653 mkU8(23)), 12654 mkU32(0x1)), 12655 binop(Iop_And32, 12656 binop(Iop_Shr32, getFCSR(), 12657 mkU8(24 + mov_cc)), 12658 mkU32(0x1)) 12659 )); 12660 12661 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12662 assign(t4, IRExpr_ITE(mkexpr(t3), 12663 getDReg(fs), getDReg(fd))); 12664 putDReg(fd, mkexpr(t4)); 12665 break; 12666 case 0x10: /* S */ 12667 DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc); 12668 t1 = newTemp(Ity_I1); 12669 t2 = newTemp(Ity_I32); 12670 t3 = newTemp(Ity_I1); 12671 t4 = newTemp(Ity_F64); 12672 t5 = newTemp(Ity_F64); 12673 t6 = newTemp(Ity_F64); 12674 t7 = newTemp(Ity_I64); 12675 12676 if (fp_mode64) { 12677 assign(t5, getFReg(fs)); 12678 assign(t6, getFReg(fd)); 12679 } else { 12680 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 12681 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 12682 } 12683 12684 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12685 assign(t2, IRExpr_ITE(mkexpr(t1), 12686 binop(Iop_And32, 12687 binop(Iop_Shr32, getFCSR(), 12688 mkU8(23)), 12689 mkU32(0x1)), 12690 binop(Iop_And32, 12691 binop(Iop_Shr32, getFCSR(), 12692 mkU8(24 + mov_cc)), 12693 mkU32(0x1)) 12694 )); 12695 12696 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12697 assign(t4, IRExpr_ITE(mkexpr(t3), 12698 mkexpr(t5), mkexpr(t6))); 12699 12700 if (fp_mode64) { 12701 IRTemp f = newTemp(Ity_F64); 12702 IRTemp fd_hi = newTemp(Ity_I32); 12703 assign(f, getFReg(fd)); 12704 assign(fd_hi, unop(Iop_64HIto32, 12705 unop(Iop_ReinterpF64asI64, mkexpr(f)))); 12706 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12707 unop(Iop_ReinterpF64asI64, mkexpr(t4))), 12708 True)); 12709 12710 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); 12711 } else 12712 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12713 mkexpr(t4))); 12714 break; 12715 default: 12716 goto decode_failure; 12717 } 12718 } else if (tf == 0) /* movf.fmt */ 12719 { 12720 UInt mov_cc = get_mov_cc(cins); 12721 switch (fmt) /* MOVCF = 010001 */ 12722 { 12723 case 0x11: /* D */ 12724 DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc); 12725 t1 = newTemp(Ity_I1); 12726 t2 = newTemp(Ity_I32); 12727 t3 = newTemp(Ity_I1); 12728 t4 = newTemp(Ity_F64); 12729 12730 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12731 assign(t2, IRExpr_ITE(mkexpr(t1), 12732 binop(Iop_And32, 12733 binop(Iop_Shr32, getFCSR(), 12734 mkU8(23)), 12735 mkU32(0x1)), 12736 binop(Iop_And32, 12737 binop(Iop_Shr32, getFCSR(), 12738 mkU8(24 + mov_cc)), 12739 mkU32(0x1)) 12740 )); 12741 12742 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12743 assign(t4, IRExpr_ITE(mkexpr(t3), 12744 getDReg(fs), getDReg(fd))); 12745 putDReg(fd, mkexpr(t4)); 12746 break; 12747 case 0x10: /* S */ 12748 DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc); 12749 t1 = newTemp(Ity_I1); 12750 t2 = newTemp(Ity_I32); 12751 t3 = newTemp(Ity_I1); 12752 t4 = newTemp(Ity_F64); 12753 t5 = newTemp(Ity_F64); 12754 t6 = newTemp(Ity_F64); 12755 12756 if (fp_mode64) { 12757 assign(t5, getFReg(fs)); 12758 assign(t6, getFReg(fd)); 12759 } else { 12760 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 12761 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 12762 } 12763 12764 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12765 assign(t2, IRExpr_ITE(mkexpr(t1), 12766 binop(Iop_And32, 12767 binop(Iop_Shr32, getFCSR(), 12768 mkU8(23)), 12769 mkU32(0x1)), 12770 binop(Iop_And32, 12771 binop(Iop_Shr32, getFCSR(), 12772 mkU8(24 + mov_cc)), 12773 mkU32(0x1)) 12774 )); 12775 12776 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12777 assign(t4, IRExpr_ITE(mkexpr(t3), 12778 mkexpr(t5), mkexpr(t6))); 12779 12780 if (fp_mode64) { 12781 IRTemp f = newTemp(Ity_F64); 12782 IRTemp fd_hi = newTemp(Ity_I32); 12783 t7 = newTemp(Ity_I64); 12784 assign(f, getFReg(fd)); 12785 assign(fd_hi, unop(Iop_64HIto32, 12786 unop(Iop_ReinterpF64asI64, mkexpr(f)))); 12787 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12788 unop(Iop_ReinterpF64asI64, mkexpr(t4))), 12789 True)); 12790 12791 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); 12792 } else 12793 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12794 mkexpr(t4))); 12795 break; 12796 default: 12797 goto decode_failure; 12798 } 12799 } 12800 12801 break; /* MOVT.fmt */ 12802 12803 case 0x0: /* add.fmt */ 12804 switch (fmt) { 12805 case 0x10: { /* S */ 12806 DIP("add.s f%u, f%u, f%u", fd, fs, ft); 12807 calculateFCSR(fs, ft, ADDS, True, 2); 12808 IRExpr *rm = get_IR_roundingmode(); 12809 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, 12810 getLoFromF64(tyF, getFReg(fs)), 12811 getLoFromF64(tyF, getFReg(ft))))); 12812 break; 12813 } 12814 case 0x11: { /* D */ 12815 DIP("add.d f%u, f%u, f%u", fd, fs, ft); 12816 calculateFCSR(fs, ft, ADDD, False, 2); 12817 IRExpr *rm = get_IR_roundingmode(); 12818 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft))); 12819 break; 12820 } 12821 12822 case 0x4: /* MTC1 (Move Word to Floating Point) */ 12823 DIP("mtc1 r%u, f%u", rt, fs); 12824 if (fp_mode64) { 12825 t0 = newTemp(Ity_I32); 12826 t1 = newTemp(Ity_F32); 12827 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 12828 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 12829 12830 putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1))); 12831 } else 12832 putFReg(fs, unop(Iop_ReinterpI32asF32, getIReg(rt))); 12833 break; 12834 12835 case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */ 12836 DIP("dmtc1 r%u, f%u", rt, fs); 12837 vassert(mode64); 12838 putFReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt))); 12839 break; 12840 12841 case 0x0: /* MFC1 */ 12842 DIP("mfc1 r%u, f%u", rt, fs); 12843 if (fp_mode64) { 12844 t0 = newTemp(Ity_I64); 12845 t1 = newTemp(Ity_I32); 12846 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 12847 assign(t1, unop(Iop_64to32, mkexpr(t0))); 12848 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 12849 } else 12850 putIReg(rt, unop(Iop_ReinterpF32asI32, getFReg(fs))); 12851 break; 12852 12853 case 0x1: /* Doubleword Move from Floating Point DMFC1; 12854 MIPS64 */ 12855 DIP("dmfc1 r%u, f%u", rt, fs); 12856 putIReg(rt, unop(Iop_ReinterpF64asI64, getFReg(fs))); 12857 break; 12858 12859 case 0x6: /* CTC1 */ 12860 DIP("ctc1 r%u, f%u", rt, fs); 12861 t0 = newTemp(Ity_I32); 12862 t1 = newTemp(Ity_I32); 12863 t2 = newTemp(Ity_I32); 12864 t3 = newTemp(Ity_I32); 12865 t4 = newTemp(Ity_I32); 12866 t5 = newTemp(Ity_I32); 12867 t6 = newTemp(Ity_I32); 12868 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 12869 if (fs == 25) { /* FCCR */ 12870 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12871 mkU32(0x000000FE)), mkU8(24))); 12872 assign(t2, binop(Iop_And32, mkexpr(t0), 12873 mkU32(0x01000000))); 12874 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12875 mkU32(0x00000001)), mkU8(23))); 12876 assign(t4, binop(Iop_And32, mkexpr(t0), 12877 mkU32(0x007FFFFF))); 12878 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1), 12879 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3), 12880 mkexpr(t4)))); 12881 } else if (fs == 26) { /* FEXR */ 12882 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000))); 12883 assign(t2, binop(Iop_And32, mkexpr(t0), 12884 mkU32(0x0003F000))); 12885 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80))); 12886 assign(t4, binop(Iop_And32, mkexpr(t0), 12887 mkU32(0x0000007C))); 12888 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003))); 12889 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 12890 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 12891 mkexpr(t3), mkexpr(t4))), mkexpr(t5))); 12892 } else if (fs == 28) { 12893 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000))); 12894 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12895 mkU32(0x00000002)), mkU8(22))); 12896 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000))); 12897 assign(t4, binop(Iop_And32, mkexpr(t0), 12898 mkU32(0x00000F80))); 12899 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C))); 12900 assign(t6, binop(Iop_And32, mkexpr(t0), 12901 mkU32(0x00000003))); 12902 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 12903 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 12904 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32, 12905 mkexpr(t5), mkexpr(t6)))); 12906 } else if (fs == 31) { 12907 putFCSR(mkexpr(t0)); 12908 } 12909 break; 12910 case 0x2: /* CFC1 */ 12911 DIP("cfc1 r%u, f%u", rt, fs); 12912 t0 = newTemp(Ity_I32); 12913 t1 = newTemp(Ity_I32); 12914 t2 = newTemp(Ity_I32); 12915 t3 = newTemp(Ity_I32); 12916 t4 = newTemp(Ity_I32); 12917 t5 = newTemp(Ity_I32); 12918 t6 = newTemp(Ity_I32); 12919 assign(t0, getFCSR()); 12920 if (fs == 0) { 12921 putIReg(rt, mkWidenFrom32(ty, 12922 IRExpr_Get(offsetof(VexGuestMIPS32State, 12923 guest_FIR), 12924 Ity_I32), 12925 False)); 12926 } else if (fs == 25) { 12927 assign(t1, mkU32(0x000000FF)); 12928 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12929 mkU32(0xFE000000)), mkU8(25))); 12930 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12931 mkU32(0x00800000)), mkU8(23))); 12932 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12933 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12934 mkexpr(t3)), False)); 12935 } else if (fs == 26) { 12936 assign(t1, mkU32(0xFFFFF07C)); 12937 assign(t2, binop(Iop_And32, mkexpr(t0), 12938 mkU32(0x0003F000))); 12939 assign(t3, binop(Iop_And32, mkexpr(t0), 12940 mkU32(0x0000007C))); 12941 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12942 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12943 mkexpr(t3)), False)); 12944 } else if (fs == 28) { 12945 assign(t1, mkU32(0x00000F87)); 12946 assign(t2, binop(Iop_And32, mkexpr(t0), 12947 mkU32(0x00000F83))); 12948 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12949 mkU32(0x01000000)), mkU8(22))); 12950 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12951 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12952 mkexpr(t3)), False)); 12953 } else if (fs == 31) { 12954 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False)); 12955 } 12956 break; 12957 default: 12958 goto decode_failure; 12959 } 12960 break; 12961 12962 case 0x21: /* CVT.D */ 12963 switch (fmt) { 12964 case 0x10: /* S */ 12965 DIP("cvt.d.s f%u, f%u", fd, fs); 12966 calculateFCSR(fs, 0, CVTDS, True, 1); 12967 if (fp_mode64) { 12968 t0 = newTemp(Ity_I64); 12969 t1 = newTemp(Ity_I32); 12970 t3 = newTemp(Ity_F32); 12971 t4 = newTemp(Ity_F32); 12972 /* get lo half of FPR */ 12973 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 12974 12975 assign(t1, unop(Iop_64to32, mkexpr(t0))); 12976 12977 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 12978 12979 putFReg(fd, unop(Iop_F32toF64, mkexpr(t3))); 12980 } else 12981 putDReg(fd, unop(Iop_F32toF64, getFReg(fs))); 12982 break; 12983 12984 case 0x14: 12985 DIP("cvt.d.w %u, %u", fd, fs); 12986 calculateFCSR(fs, 0, CVTDW, True, 1); 12987 if (fp_mode64) { 12988 t0 = newTemp(Ity_I64); 12989 t1 = newTemp(Ity_I32); 12990 t3 = newTemp(Ity_F32); 12991 t4 = newTemp(Ity_F32); 12992 /* get lo half of FPR */ 12993 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 12994 12995 assign(t1, unop(Iop_64to32, mkexpr(t0))); 12996 putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1))); 12997 break; 12998 } else { 12999 t0 = newTemp(Ity_I32); 13000 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 13001 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0))); 13002 break; 13003 } 13004 13005 case 0x15: { /* L */ 13006 if (fp_mode64) { 13007 DIP("cvt.d.l %u, %u", fd, fs); 13008 calculateFCSR(fs, 0, CVTDL, False, 1); 13009 t0 = newTemp(Ity_I64); 13010 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13011 13012 putFReg(fd, binop(Iop_I64StoF64, 13013 get_IR_roundingmode(), mkexpr(t0))); 13014 break; 13015 } else 13016 goto decode_failure; 13017 } 13018 default: 13019 goto decode_failure; 13020 } 13021 break; /* CVT.D */ 13022 13023 case 0x20: /* cvt.s */ 13024 switch (fmt) { 13025 case 0x14: /* W */ 13026 DIP("cvt.s.w %u, %u", fd, fs); 13027 calculateFCSR(fs, 0, CVTSW, True, 1); 13028 if (fp_mode64) { 13029 t0 = newTemp(Ity_I64); 13030 t1 = newTemp(Ity_I32); 13031 t3 = newTemp(Ity_F32); 13032 t4 = newTemp(Ity_F32); 13033 /* get lo half of FPR */ 13034 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13035 13036 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13037 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32, 13038 get_IR_roundingmode(), mkexpr(t1)))); 13039 } else { 13040 t0 = newTemp(Ity_I32); 13041 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 13042 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(), 13043 mkexpr(t0))); 13044 } 13045 break; 13046 13047 case 0x11: /* D */ 13048 DIP("cvt.s.d %u, %u", fd, fs); 13049 calculateFCSR(fs, 0, CVTSD, False, 1); 13050 t0 = newTemp(Ity_F32); 13051 assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(), 13052 getDReg(fs))); 13053 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0))); 13054 break; 13055 13056 case 0x15: /* L */ 13057 DIP("cvt.s.l %u, %u", fd, fs); 13058 calculateFCSR(fs, 0, CVTSL, False, 1); 13059 t0 = newTemp(Ity_I64); 13060 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13061 13062 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32, 13063 get_IR_roundingmode(), mkexpr(t0)))); 13064 break; 13065 13066 default: 13067 goto decode_failure; 13068 } 13069 break; /* cvt.s */ 13070 13071 case 0x24: /* cvt.w */ 13072 switch (fmt) { 13073 case 0x10: /* S */ 13074 DIP("cvt.w.s %u, %u", fd, fs); 13075 calculateFCSR(fs, 0, CVTWS, True, 1); 13076 putFReg(fd, 13077 mkWidenFromF32(tyF, 13078 binop(Iop_RoundF32toInt, 13079 get_IR_roundingmode(), 13080 getLoFromF64(tyF, getFReg(fs)))) 13081 ); 13082 break; 13083 13084 case 0x11: 13085 DIP("cvt.w.d %u, %u", fd, fs); 13086 calculateFCSR(fs, 0, CVTWD, False, 1); 13087 t0 = newTemp(Ity_I32); 13088 t1 = newTemp(Ity_F32); 13089 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(), 13090 getDReg(fs))); 13091 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13092 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13093 break; 13094 13095 default: 13096 goto decode_failure; 13097 13098 } 13099 break; 13100 13101 case 0x25: /* cvt.l */ 13102 switch (fmt) { 13103 case 0x10: /* S */ 13104 DIP("cvt.l.s %u, %u", fd, fs); 13105 if (fp_mode64) { 13106 calculateFCSR(fs, 0, CVTLS, True, 1); 13107 t0 = newTemp(Ity_I64); 13108 13109 assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(), 13110 getLoFromF64(tyF, getFReg(fs)))); 13111 13112 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13113 } else { 13114 ILLEGAL_INSTRUCTON; 13115 } 13116 break; 13117 13118 case 0x11: { /* D */ 13119 DIP("cvt.l.d %u, %u", fd, fs); 13120 if (fp_mode64) { 13121 calculateFCSR(fs, 0, CVTLD, False, 1); 13122 putDReg(fd, binop(Iop_RoundF64toInt, 13123 get_IR_roundingmode(), getDReg(fs))); 13124 } else { 13125 ILLEGAL_INSTRUCTON; 13126 } 13127 break; 13128 } 13129 13130 default: 13131 goto decode_failure; 13132 } 13133 break; 13134 13135 case 0x0B: /* FLOOR.L.fmt */ 13136 switch (fmt) { 13137 case 0x10: /* S */ 13138 DIP("floor.l.s %u, %u", fd, fs); 13139 if (fp_mode64) { 13140 calculateFCSR(fs, 0, FLOORLS, True, 1); 13141 t0 = newTemp(Ity_I64); 13142 13143 assign(t0, binop(Iop_F32toI64S, mkU32(0x1), 13144 getLoFromF64(tyF, getFReg(fs)))); 13145 13146 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13147 } else { 13148 ILLEGAL_INSTRUCTON; 13149 } 13150 break; 13151 13152 case 0x11: /* D */ 13153 DIP("floor.l.d %u, %u", fd, fs); 13154 if (fp_mode64) { 13155 calculateFCSR(fs, 0, FLOORLD, False, 1); 13156 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1), 13157 getDReg(fs))); 13158 } else { 13159 ILLEGAL_INSTRUCTON; 13160 } 13161 break; 13162 default: 13163 goto decode_failure; 13164 } 13165 break; 13166 13167 case 0x0C: /* ROUND.W.fmt */ 13168 switch (fmt) { 13169 case 0x10: /* S */ 13170 DIP("round.w.s f%u, f%u", fd, fs); 13171 calculateFCSR(fs, 0, ROUNDWS, True, 1); 13172 if (fp_mode64) { 13173 t0 = newTemp(Ity_I64); 13174 t1 = newTemp(Ity_I32); 13175 t3 = newTemp(Ity_F32); 13176 t4 = newTemp(Ity_F32); 13177 /* get lo half of FPR */ 13178 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13179 13180 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13181 13182 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13183 13184 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x0), 13185 mkexpr(t3))); 13186 13187 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13188 } else 13189 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0), 13190 getFReg(fs))); 13191 break; 13192 13193 case 0x11: /* D */ 13194 DIP("round.w.d f%u, f%u", fd, fs); 13195 calculateFCSR(fs, 0, ROUNDWD, False, 1); 13196 if (fp_mode64) { 13197 t0 = newTemp(Ity_I32); 13198 assign(t0, binop(Iop_F64toI32S, mkU32(0x0), 13199 getDReg(fs))); 13200 putFReg(fd, mkWidenFromF32(tyF, 13201 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13202 } else { 13203 t0 = newTemp(Ity_I32); 13204 13205 assign(t0, binop(Iop_F64toI32S, mkU32(0x0), 13206 getDReg(fs))); 13207 13208 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13209 } 13210 break; 13211 default: 13212 goto decode_failure; 13213 13214 } 13215 break; /* ROUND.W.fmt */ 13216 13217 case 0x0F: /* FLOOR.W.fmt */ 13218 switch (fmt) { 13219 case 0x10: /* S */ 13220 DIP("floor.w.s f%u, f%u", fd, fs); 13221 calculateFCSR(fs, 0, FLOORWS, True, 1); 13222 if (fp_mode64) { 13223 t0 = newTemp(Ity_I64); 13224 t1 = newTemp(Ity_I32); 13225 t3 = newTemp(Ity_F32); 13226 t4 = newTemp(Ity_F32); 13227 /* get lo half of FPR */ 13228 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13229 13230 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13231 13232 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13233 13234 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x1), 13235 mkexpr(t3))); 13236 13237 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13238 } else 13239 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1), 13240 getFReg(fs))); 13241 break; 13242 13243 case 0x11: /* D */ 13244 DIP("floor.w.d f%u, f%u", fd, fs); 13245 calculateFCSR(fs, 0, FLOORWD, False, 1); 13246 if (fp_mode64) { 13247 t0 = newTemp(Ity_I32); 13248 assign(t0, binop(Iop_F64toI32S, mkU32(0x1), 13249 getDReg(fs))); 13250 putFReg(fd, mkWidenFromF32(tyF, 13251 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13252 break; 13253 } else { 13254 t0 = newTemp(Ity_I32); 13255 13256 assign(t0, binop(Iop_F64toI32S, mkU32(0x1), 13257 getDReg(fs))); 13258 13259 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13260 break; 13261 } 13262 default: 13263 goto decode_failure; 13264 13265 } 13266 break; /* FLOOR.W.fmt */ 13267 13268 case 0x0D: /* TRUNC.W */ 13269 switch (fmt) { 13270 case 0x10: /* S */ 13271 DIP("trunc.w.s %u, %u", fd, fs); 13272 calculateFCSR(fs, 0, TRUNCWS, True, 1); 13273 if (fp_mode64) { 13274 t0 = newTemp(Ity_I64); 13275 t1 = newTemp(Ity_I32); 13276 t3 = newTemp(Ity_F32); 13277 t4 = newTemp(Ity_F32); 13278 /* get lo half of FPR */ 13279 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13280 13281 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13282 13283 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13284 13285 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x3), 13286 mkexpr(t3))); 13287 13288 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13289 } else 13290 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3), 13291 getFReg(fs))); 13292 break; 13293 case 0x11: /* D */ 13294 DIP("trunc.w.d %u, %u", fd, fs); 13295 calculateFCSR(fs, 0, TRUNCWD, False, 1); 13296 if (fp_mode64) { 13297 t0 = newTemp(Ity_I32); 13298 13299 assign(t0, binop(Iop_F64toI32S, mkU32(0x3), 13300 getFReg(fs))); 13301 13302 putFReg(fd, mkWidenFromF32(tyF, 13303 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13304 } else { 13305 t0 = newTemp(Ity_I32); 13306 13307 assign(t0, binop(Iop_F64toI32S, mkU32(0x3), 13308 getDReg(fs))); 13309 13310 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13311 } 13312 break; 13313 default: 13314 goto decode_failure; 13315 13316 } 13317 break; 13318 13319 case 0x0E: /* CEIL.W.fmt */ 13320 switch (fmt) { 13321 case 0x10: /* S */ 13322 DIP("ceil.w.s %u, %u", fd, fs); 13323 calculateFCSR(fs, 0, CEILWS, True, 1); 13324 if (fp_mode64) { 13325 t0 = newTemp(Ity_I64); 13326 t1 = newTemp(Ity_I32); 13327 t3 = newTemp(Ity_F32); 13328 t4 = newTemp(Ity_F32); 13329 /* get lo half of FPR */ 13330 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13331 13332 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13333 13334 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13335 13336 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x2), 13337 mkexpr(t3))); 13338 13339 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13340 } else 13341 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2), 13342 getFReg(fs))); 13343 break; 13344 13345 case 0x11: /* D */ 13346 DIP("ceil.w.d %u, %u", fd, fs); 13347 calculateFCSR(fs, 0, CEILWD, False, 1); 13348 if (!fp_mode64) { 13349 t0 = newTemp(Ity_I32); 13350 assign(t0, binop(Iop_F64toI32S, mkU32(0x2), 13351 getDReg(fs))); 13352 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13353 } else { 13354 t0 = newTemp(Ity_I32); 13355 assign(t0, binop(Iop_F64toI32S, mkU32(0x2), 13356 getDReg(fs))); 13357 putFReg(fd, mkWidenFromF32(tyF, 13358 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13359 } 13360 break; 13361 default: 13362 goto decode_failure; 13363 13364 } 13365 break; 13366 13367 case 0x0A: /* CEIL.L.fmt */ 13368 switch (fmt) { 13369 case 0x10: /* S */ 13370 DIP("ceil.l.s %u, %u", fd, fs); 13371 if (fp_mode64) { 13372 calculateFCSR(fs, 0, CEILLS, True, 1); 13373 t0 = newTemp(Ity_I64); 13374 13375 assign(t0, binop(Iop_F32toI64S, mkU32(0x2), 13376 getLoFromF64(tyF, getFReg(fs)))); 13377 13378 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13379 } else { 13380 ILLEGAL_INSTRUCTON; 13381 } 13382 break; 13383 13384 case 0x11: /* D */ 13385 DIP("ceil.l.d %u, %u", fd, fs); 13386 if (fp_mode64) { 13387 calculateFCSR(fs, 0, CEILLD, False, 1); 13388 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2), 13389 getDReg(fs))); 13390 } else { 13391 ILLEGAL_INSTRUCTON; 13392 } 13393 break; 13394 13395 default: 13396 goto decode_failure; 13397 13398 } 13399 break; 13400 13401 case 0x16: /* RSQRT.fmt */ 13402 switch (fmt) { 13403 case 0x10: { /* S */ 13404 DIP("rsqrt.s %u, %u", fd, fs); 13405 IRExpr *rm = get_IR_roundingmode(); 13406 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 13407 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)), 13408 binop(Iop_SqrtF32, rm, getLoFromF64(tyF, 13409 getFReg(fs)))))); 13410 break; 13411 } 13412 case 0x11: { /* D */ 13413 DIP("rsqrt.d %u, %u", fd, fs); 13414 IRExpr *rm = get_IR_roundingmode(); 13415 putDReg(fd, triop(Iop_DivF64, rm, 13416 unop(Iop_ReinterpI64asF64, 13417 mkU64(ONE_DOUBLE)), 13418 binop(Iop_SqrtF64, rm, getDReg(fs)))); 13419 break; 13420 } 13421 default: 13422 goto decode_failure; 13423 13424 } 13425 break; 13426 13427 default: 13428 if (dis_instr_CCondFmt(cins)) 13429 break; 13430 goto decode_failure; 13431 13432 } 13433 13434 } 13435 } 13436 break; /* COP1 */ 13437 case 0x10: /* COP0 */ 13438 if (rs == 0) { /* MFC0 */ 13439 DIP("mfc0 r%u, r%u, %u", rt, rd, sel); 13440 IRTemp val = newTemp(Ity_I32); 13441 IRExpr** args = mkIRExprVec_3 (IRExpr_BBPTR(), mkU32(rd), mkU32(sel)); 13442 IRDirty *d = unsafeIRDirty_1_N(val, 13443 0, 13444 "mips32_dirtyhelper_mfc0", 13445 &mips32_dirtyhelper_mfc0, 13446 args); 13447 stmt(IRStmt_Dirty(d)); 13448 putIReg(rt, mkexpr(val)); 13449 } else if (rs == 1) { 13450 /* Doubleword Move from Coprocessor 0 - DMFC0; MIPS64 */ 13451 DIP("dmfc0 r%u, r%u, %u", rt, rd, sel); 13452 IRTemp val = newTemp(Ity_I64); 13453 IRExpr** args = mkIRExprVec_3 (IRExpr_BBPTR(), mkU64(rd), mkU64(sel)); 13454 IRDirty *d = unsafeIRDirty_1_N(val, 13455 0, 13456 "mips64_dirtyhelper_dmfc0", 13457 &mips64_dirtyhelper_dmfc0, 13458 args); 13459 stmt(IRStmt_Dirty(d)); 13460 putDReg(rt, mkexpr(val)); 13461 } else 13462 goto decode_failure; 13463 break; 13464 13465 case 0x31: /* LWC1 */ 13466 /* Load Word to Floating Point - LWC1 (MIPS32) */ 13467 DIP("lwc1 f%u, %u(r%u)", ft, imm, rs); 13468 if (fp_mode64) { 13469 t1 = newTemp(Ity_F32); 13470 t2 = newTemp(Ity_I64); 13471 if (mode64) { 13472 t0 = newTemp(Ity_I64); 13473 /* new LO */ 13474 assign(t0, binop(Iop_Add64, getIReg(rs), 13475 mkU64(extend_s_16to64(imm)))); 13476 } else { 13477 t0 = newTemp(Ity_I32); 13478 /* new LO */ 13479 assign(t0, binop(Iop_Add32, getIReg(rs), 13480 mkU32(extend_s_16to32(imm)))); 13481 } 13482 assign(t1, load(Ity_F32, mkexpr(t0))); 13483 assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, 13484 mkexpr(t1)), True)); 13485 putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2))); 13486 } else { 13487 t0 = newTemp(Ity_I32); 13488 assign(t0, binop(Iop_Add32, getIReg(rs), 13489 mkU32(extend_s_16to32(imm)))); 13490 putFReg(ft, load(Ity_F32, mkexpr(t0))); 13491 } 13492 break; 13493 13494 case 0x39: /* SWC1 */ 13495 DIP("swc1 f%u, %u(r%u)", ft, imm, rs); 13496 if (fp_mode64) { 13497 t0 = newTemp(Ity_I64); 13498 t2 = newTemp(Ity_I32); 13499 LOAD_STORE_PATTERN; 13500 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft))); 13501 assign(t2, unop(Iop_64to32, mkexpr(t0))); 13502 store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2))); 13503 } else { 13504 LOAD_STORE_PATTERN; 13505 store(mkexpr(t1), getFReg(ft)); 13506 } 13507 break; 13508 13509 case 0x33: /* PREF */ 13510 DIP("pref"); 13511 break; 13512 13513 case 0x35: 13514 /* Load Doubleword to Floating Point - LDC1 (MIPS32) */ 13515 DIP("ldc1 f%u, %u(%u)", rt, imm, rs); 13516 LOAD_STORE_PATTERN; 13517 putDReg(ft, load(Ity_F64, mkexpr(t1))); 13518 break; 13519 13520 case 0x3D: 13521 /* Store Doubleword from Floating Point - SDC1 */ 13522 DIP("sdc1 f%u, %u(%u)", ft, imm, rs); 13523 LOAD_STORE_PATTERN; 13524 store(mkexpr(t1), getDReg(ft)); 13525 break; 13526 13527 case 0x23: /* LW */ 13528 DIP("lw r%u, %u(r%u)", rt, imm, rs); 13529 LOAD_STORE_PATTERN; 13530 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True)); 13531 break; 13532 13533 case 0x20: /* LB */ 13534 DIP("lb r%u, %u(r%u)", rt, imm, rs); 13535 LOAD_STORE_PATTERN; 13536 if (mode64) 13537 putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 13538 else 13539 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 13540 break; 13541 13542 case 0x24: /* LBU */ 13543 DIP("lbu r%u, %u(r%u)", rt, imm, rs); 13544 LOAD_STORE_PATTERN; 13545 if (mode64) 13546 putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1)))); 13547 else 13548 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1)))); 13549 break; 13550 13551 case 0x21: /* LH */ 13552 DIP("lh r%u, %u(r%u)", rt, imm, rs); 13553 LOAD_STORE_PATTERN; 13554 if (mode64) 13555 putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1)))); 13556 else 13557 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1)))); 13558 break; 13559 13560 case 0x25: /* LHU */ 13561 DIP("lhu r%u, %u(r%u)", rt, imm, rs); 13562 LOAD_STORE_PATTERN; 13563 if (mode64) 13564 putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 13565 else 13566 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 13567 break; 13568 13569 case 0x0F: /* LUI */ 13570 p = (imm << 16); 13571 DIP("lui r%u, imm: 0x%x", rt, imm); 13572 if (mode64) 13573 putIReg(rt, mkU64(extend_s_32to64(p))); 13574 else 13575 putIReg(rt, mkU32(p)); 13576 break; 13577 13578 case 0x13: /* COP1X */ 13579 switch (function) { 13580 case 0x0: { /* LWXC1 */ 13581 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */ 13582 DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs); 13583 if (fp_mode64) { 13584 t0 = newTemp(Ity_I64); 13585 t1 = newTemp(Ity_I32); 13586 t3 = newTemp(Ity_F32); 13587 t4 = newTemp(Ity_I64); 13588 13589 t2 = newTemp(ty); 13590 /* new LO */ 13591 assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13592 getIReg(rt))); 13593 assign(t3, load(Ity_F32, mkexpr(t2))); 13594 13595 assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, 13596 mkexpr(t3)), True)); 13597 13598 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4))); 13599 } else { 13600 t0 = newTemp(Ity_I32); 13601 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 13602 putFReg(fd, load(Ity_F32, mkexpr(t0))); 13603 } 13604 break; 13605 } 13606 13607 case 0x1: { /* LDXC1 */ 13608 /* Load Doubleword Indexed to Floating Point 13609 LDXC1 (MIPS32r2 and MIPS64) */ 13610 if (fp_mode64) { 13611 DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs); 13612 t0 = newTemp(ty); 13613 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13614 getIReg(rt))); 13615 putFReg(fd, load(Ity_F64, mkexpr(t0))); 13616 break; 13617 } else { 13618 t0 = newTemp(Ity_I32); 13619 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 13620 13621 t1 = newTemp(Ity_I32); 13622 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); 13623 13624 #if defined (_MIPSEL) 13625 putFReg(fd, load(Ity_F32, mkexpr(t0))); 13626 putFReg(fd + 1, load(Ity_F32, mkexpr(t1))); 13627 #elif defined (_MIPSEB) 13628 putFReg(fd + 1, load(Ity_F32, mkexpr(t0))); 13629 putFReg(fd, load(Ity_F32, mkexpr(t1))); 13630 #endif 13631 break; 13632 } 13633 } 13634 13635 case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1; 13636 MIPS32r2 */ 13637 DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs); 13638 t0 = newTemp(Ity_I64); 13639 t1 = newTemp(Ity_I64); 13640 assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt))); 13641 assign(t1, binop(Iop_And64, mkexpr(t0), 13642 mkU64(0xfffffffffffffff8ULL))); 13643 putFReg(fd, load(Ity_F64, mkexpr(t1))); 13644 break; 13645 13646 case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */ 13647 DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs); 13648 if (fp_mode64) { 13649 t0 = newTemp(ty); 13650 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13651 getIReg(rt))); 13652 store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs))); 13653 13654 } else { 13655 t0 = newTemp(Ity_I32); 13656 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 13657 13658 store(mkexpr(t0), getFReg(fs)); 13659 } 13660 break; 13661 } 13662 case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */ 13663 DIP("sdc1 f%u, %u(%u)", ft, imm, rs); 13664 if (fp_mode64) { 13665 t0 = newTemp(ty); 13666 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13667 getIReg(rt))); 13668 store(mkexpr(t0), getFReg(fs)); 13669 } else { 13670 t0 = newTemp(Ity_I32); 13671 assign(t0, binop(Iop_Add32, getIReg(rs), getIReg(rt))); 13672 13673 t1 = newTemp(Ity_I32); 13674 assign(t1, binop(Iop_Add32, mkexpr(t0), mkU32(4))); 13675 13676 #if defined (_MIPSEL) 13677 store(mkexpr(t0), getFReg(fs)); 13678 store(mkexpr(t1), getFReg(fs + 1)); 13679 #elif defined (_MIPSEB) 13680 store(mkexpr(t0), getFReg(fs + 1)); 13681 store(mkexpr(t1), getFReg(fs)); 13682 #endif 13683 } 13684 break; 13685 } 13686 case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point - 13687 SUXC1; MIPS64 MIPS32r2 */ 13688 DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs); 13689 t0 = newTemp(Ity_I64); 13690 t1 = newTemp(Ity_I64); 13691 assign(t0, binop(Iop_Add64, getIReg(rs), getIReg(rt))); 13692 assign(t1, binop(Iop_And64, mkexpr(t0), mkU64(0xfffffffffffffff8ULL))); 13693 store(mkexpr(t1), getFReg(fs)); 13694 break; 13695 13696 case 0x0F: { 13697 DIP("prefx"); 13698 break; 13699 } 13700 case 0x20: { /* MADD.S */ 13701 DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13702 IRExpr *rm = get_IR_roundingmode(); 13703 t1 = newTemp(Ity_F32); 13704 assign(t1, qop(Iop_MAddF32, rm, 13705 getLoFromF64(tyF, getFReg(fmt)), 13706 getLoFromF64(tyF, getFReg(fs)), 13707 getLoFromF64(tyF, getFReg(ft)))); 13708 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13709 break; /* MADD.S */ 13710 } 13711 case 0x21: { /* MADD.D */ 13712 DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13713 IRExpr *rm = get_IR_roundingmode(); 13714 putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs), 13715 getDReg(ft))); 13716 break; /* MADD.D */ 13717 } 13718 case 0x28: { /* MSUB.S */ 13719 DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13720 IRExpr *rm = get_IR_roundingmode(); 13721 t1 = newTemp(Ity_F32); 13722 assign(t1, qop(Iop_MSubF32, rm, 13723 getLoFromF64(tyF, getFReg(fmt)), 13724 getLoFromF64(tyF, getFReg(fs)), 13725 getLoFromF64(tyF, getFReg(ft)))); 13726 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13727 break; /* MSUB.S */ 13728 } 13729 case 0x29: { /* MSUB.D */ 13730 DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13731 IRExpr *rm = get_IR_roundingmode(); 13732 putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs), 13733 getDReg(ft))); 13734 break; /* MSUB.D */ 13735 } 13736 case 0x30: { /* NMADD.S */ 13737 DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13738 IRExpr *rm = get_IR_roundingmode(); 13739 t1 = newTemp(Ity_F32); 13740 assign(t1, qop(Iop_MAddF32, rm, 13741 getLoFromF64(tyF, getFReg(fmt)), 13742 getLoFromF64(tyF, getFReg(fs)), 13743 getLoFromF64(tyF, getFReg(ft)))); 13744 13745 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1)))); 13746 break; /* NMADD.S */ 13747 } 13748 case 0x31: { /* NMADD.D */ 13749 DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13750 IRExpr *rm = get_IR_roundingmode(); 13751 t1 = newTemp(Ity_F64); 13752 assign(t1, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs), 13753 getDReg(ft))); 13754 putDReg(fd, unop(Iop_NegF64, mkexpr(t1))); 13755 break; /* NMADD.D */ 13756 } 13757 case 0x38: { /* NMSUBB.S */ 13758 DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13759 IRExpr *rm = get_IR_roundingmode(); 13760 t1 = newTemp(Ity_F32); 13761 assign(t1, qop(Iop_MSubF32, rm, 13762 getLoFromF64(tyF, getFReg(fmt)), 13763 getLoFromF64(tyF, getFReg(fs)), 13764 getLoFromF64(tyF, getFReg(ft)))); 13765 13766 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1)))); 13767 break; /* NMSUBB.S */ 13768 } 13769 case 0x39: { /* NMSUBB.D */ 13770 DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13771 IRExpr *rm = get_IR_roundingmode(); 13772 t1 = newTemp(Ity_F64); 13773 assign(t1, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs), 13774 getDReg(ft))); 13775 putDReg(fd, unop(Iop_NegF64, mkexpr(t1))); 13776 break; /* NMSUBB.D */ 13777 } 13778 13779 default: 13780 goto decode_failure; 13781 } 13782 break; 13783 13784 case 0x22: /* LWL */ 13785 DIP("lwl r%u, %u(r%u)", rt, imm, rs); 13786 if (mode64) { 13787 /* t1 = addr */ 13788 t1 = newTemp(Ity_I64); 13789 #if defined (_MIPSEL) 13790 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13791 #elif defined (_MIPSEB) 13792 assign(t1, binop(Iop_Xor64, 13793 mkU64(0x03), 13794 binop(Iop_Add64, 13795 getIReg(rs), 13796 mkU64(extend_s_16to64(imm))))); 13797 #endif 13798 /* t2 = word addr */ 13799 /* t4 = addr mod 4 */ 13800 LWX_SWX_PATTERN64; 13801 13802 /* t3 = word content - shifted */ 13803 t3 = newTemp(Ity_I32); 13804 assign(t3, binop(Iop_Shl32, 13805 load(Ity_I32, mkexpr(t2)), 13806 narrowTo(Ity_I8, 13807 binop(Iop_Shl32, 13808 binop(Iop_Sub32, 13809 mkU32(0x03), 13810 mkexpr(t4)), 13811 mkU8(3))))); 13812 13813 /* rt content - adjusted */ 13814 t5 = newTemp(Ity_I32); 13815 assign(t5, binop(Iop_And32, 13816 mkNarrowTo32(ty, getIReg(rt)), 13817 binop(Iop_Shr32, 13818 mkU32(0x00FFFFFF), 13819 narrowTo(Ity_I8, binop(Iop_Mul32, 13820 mkU32(0x08), 13821 mkexpr(t4)))))); 13822 13823 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), 13824 mkexpr(t3)), True)); 13825 } else { 13826 /* t1 = addr */ 13827 t1 = newTemp(Ity_I32); 13828 #if defined (_MIPSEL) 13829 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 13830 #elif defined (_MIPSEB) 13831 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 13832 mkU32(extend_s_16to32(imm))))); 13833 #endif 13834 13835 /* t2 = word addr */ 13836 /* t4 = addr mod 4 */ 13837 LWX_SWX_PATTERN; 13838 13839 /* t3 = word content - shifted */ 13840 t3 = newTemp(Ity_I32); 13841 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8, 13842 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), 13843 mkU8(3))))); 13844 13845 /* rt content - adjusted */ 13846 t5 = newTemp(Ity_I32); 13847 assign(t5, binop(Iop_And32, 13848 getIReg(rt), 13849 binop(Iop_Shr32, 13850 mkU32(0x00FFFFFF), 13851 narrowTo(Ity_I8, binop(Iop_Mul32, 13852 mkU32(0x08), 13853 mkexpr(t4)))))); 13854 13855 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 13856 } 13857 break; 13858 13859 case 0x26: /* LWR */ 13860 DIP("lwr r%u, %u(r%u)", rt, imm, rs); 13861 if (mode64) { 13862 /* t1 = addr */ 13863 t1 = newTemp(Ity_I64); 13864 #if defined (_MIPSEL) 13865 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13866 #elif defined (_MIPSEB) 13867 assign(t1, binop(Iop_Xor64, 13868 mkU64(0x3), 13869 binop(Iop_Add64, 13870 getIReg(rs), 13871 mkU64(extend_s_16to64(imm))))); 13872 #endif 13873 /* t2 = word addr */ 13874 /* t4 = addr mod 4 */ 13875 LWX_SWX_PATTERN64; 13876 13877 /* t3 = word content - shifted */ 13878 t3 = newTemp(Ity_I32); 13879 assign(t3, binop(Iop_Shr32, 13880 load(Ity_I32, mkexpr(t2)), 13881 narrowTo(Ity_I8, 13882 binop(Iop_Shl32, mkexpr(t4), mkU8(0x03))))); 13883 13884 /* rt content - adjusted */ 13885 t5 = newTemp(Ity_I32); 13886 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), 13887 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF), 13888 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 13889 13890 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), 13891 mkexpr(t3)), True)); 13892 13893 } else { 13894 /* t1 = addr */ 13895 t1 = newTemp(Ity_I32); 13896 #if defined (_MIPSEL) 13897 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 13898 #elif defined (_MIPSEB) 13899 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 13900 mkU32(extend_s_16to32(imm))))); 13901 #endif 13902 13903 /* t2 = word addr */ 13904 /* t4 = addr mod 4 */ 13905 LWX_SWX_PATTERN; 13906 13907 /* t3 = word content - shifted */ 13908 t3 = newTemp(Ity_I32); 13909 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)), 13910 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), 13911 mkU8(3))))); 13912 13913 /* rt content - adjusted */ 13914 t5 = newTemp(Ity_I32); 13915 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32, 13916 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, 13917 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 13918 13919 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 13920 } 13921 break; 13922 13923 case 0x2B: /* SW */ 13924 DIP("sw r%u, %u(r%u)", rt, imm, rs); 13925 LOAD_STORE_PATTERN; 13926 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))); 13927 break; 13928 13929 case 0x2C: { /* SDL rt, offset(base) MIPS64 */ 13930 DIP("sdl r%u, %u(r%u)", rt, imm, rs); 13931 vassert(mode64); 13932 IRTemp A_byte = newTemp(Ity_I8); 13933 IRTemp B_byte = newTemp(Ity_I8); 13934 IRTemp C_byte = newTemp(Ity_I8); 13935 IRTemp D_byte = newTemp(Ity_I8); 13936 IRTemp E_byte = newTemp(Ity_I8); 13937 IRTemp F_byte = newTemp(Ity_I8); 13938 IRTemp G_byte = newTemp(Ity_I8); 13939 IRTemp H_byte = newTemp(Ity_I8); 13940 IRTemp B_pos = newTemp(Ity_I64); 13941 IRTemp C_pos = newTemp(Ity_I64); 13942 IRTemp D_pos = newTemp(Ity_I64); 13943 IRTemp E_pos = newTemp(Ity_I64); 13944 IRTemp F_pos = newTemp(Ity_I64); 13945 IRTemp G_pos = newTemp(Ity_I64); 13946 13947 /* H byte */ 13948 assign(H_byte, getByteFromReg(rt, 0)); 13949 /* G byte */ 13950 assign(G_byte, getByteFromReg(rt, 1)); 13951 /* F byte */ 13952 assign(F_byte, getByteFromReg(rt, 2)); 13953 /* E byte */ 13954 assign(E_byte, getByteFromReg(rt, 3)); 13955 /* D byte */ 13956 assign(D_byte, getByteFromReg(rt, 4)); 13957 /* C byte */ 13958 assign(C_byte, getByteFromReg(rt, 5)); 13959 /* B byte */ 13960 assign(B_byte, getByteFromReg(rt, 6)); 13961 /* A byte */ 13962 assign(A_byte, getByteFromReg(rt, 7)); 13963 13964 /* t1 = addr */ 13965 t1 = newTemp(Ity_I64); 13966 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13967 13968 /* t2 = word addr */ 13969 t2 = newTemp(Ity_I64); 13970 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); 13971 13972 /* t3 = addr mod 7 */ 13973 t3 = newTemp(Ity_I64); 13974 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 13975 13976 #if defined (_MIPSEL) 13977 /* Calculate X_byte position. */ 13978 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)), 13979 mkU64(0x0), 13980 mkU64(0x1))); 13981 13982 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)), 13983 mkU64(0x0), 13984 mkU64(0x2))); 13985 13986 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)), 13987 mkU64(0x0), 13988 mkU64(0x3))); 13989 13990 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)), 13991 mkU64(0x0), 13992 mkU64(0x4))); 13993 13994 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)), 13995 mkU64(0x0), 13996 mkU64(0x5))); 13997 13998 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 13999 mkU64(0x1), 14000 mkU64(0x0))); 14001 14002 /* Store X_byte on the right place. */ 14003 store(mkexpr(t2), mkexpr(H_byte)); 14004 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14005 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14006 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14007 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14008 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14009 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14010 store(mkexpr(t1), mkexpr(A_byte)); 14011 14012 #else /* _MIPSEB */ 14013 /* Calculate X_byte position. */ 14014 assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 14015 mkU64(0x0), 14016 mkU64(0x1))); 14017 14018 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)), 14019 mkU64(0x2), 14020 mkU64(0x0))); 14021 14022 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)), 14023 mkU64(0x3), 14024 mkU64(0x0))); 14025 14026 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)), 14027 mkU64(0x4), 14028 mkU64(0x0))); 14029 14030 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)), 14031 mkU64(0x5), 14032 mkU64(0x0))); 14033 14034 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14035 mkU64(0x6), 14036 mkU64(0x7))); 14037 14038 /* Store X_byte on the right place. */ 14039 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte)); 14040 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14041 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14042 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14043 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14044 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14045 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14046 store(mkexpr(t1), mkexpr(A_byte)); 14047 #endif 14048 14049 break; 14050 } 14051 14052 case 0x2D: { 14053 /* SDR rt, offset(base) - MIPS64 */ 14054 vassert(mode64); 14055 DIP("sdr r%u, %u(r%u)", rt, imm, rs); 14056 IRTemp A_byte = newTemp(Ity_I8); 14057 IRTemp B_byte = newTemp(Ity_I8); 14058 IRTemp C_byte = newTemp(Ity_I8); 14059 IRTemp D_byte = newTemp(Ity_I8); 14060 IRTemp E_byte = newTemp(Ity_I8); 14061 IRTemp F_byte = newTemp(Ity_I8); 14062 IRTemp G_byte = newTemp(Ity_I8); 14063 IRTemp H_byte = newTemp(Ity_I8); 14064 IRTemp B_pos = newTemp(Ity_I64); 14065 IRTemp C_pos = newTemp(Ity_I64); 14066 IRTemp D_pos = newTemp(Ity_I64); 14067 IRTemp E_pos = newTemp(Ity_I64); 14068 IRTemp F_pos = newTemp(Ity_I64); 14069 IRTemp G_pos = newTemp(Ity_I64); 14070 14071 /* H byte */ 14072 assign(H_byte, getByteFromReg(rt, 0)); 14073 /* G byte */ 14074 assign(G_byte, getByteFromReg(rt, 1)); 14075 /* F byte */ 14076 assign(F_byte, getByteFromReg(rt, 2)); 14077 /* E byte */ 14078 assign(E_byte, getByteFromReg(rt, 3)); 14079 /* D byte */ 14080 assign(D_byte, getByteFromReg(rt, 4)); 14081 /* C byte */ 14082 assign(C_byte, getByteFromReg(rt, 5)); 14083 /* B byte */ 14084 assign(B_byte, getByteFromReg(rt, 6)); 14085 /* A byte */ 14086 assign(A_byte, getByteFromReg(rt, 7)); 14087 14088 /* t1 = addr */ 14089 t1 = newTemp(Ity_I64); 14090 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14091 14092 /* t2 = word addr */ 14093 t2 = newTemp(Ity_I64); 14094 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); 14095 14096 /* t3 = addr mod 7 */ 14097 t3 = newTemp(Ity_I64); 14098 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 14099 14100 #if defined (_MIPSEL) 14101 /* Calculate X_byte position. */ 14102 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)), 14103 mkU64(0x0), 14104 mkU64(0x6))); 14105 14106 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)), 14107 mkU64(0x0), 14108 mkU64(0x5))); 14109 14110 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)), 14111 mkU64(0x0), 14112 mkU64(0x4))); 14113 14114 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)), 14115 mkU64(0x0), 14116 mkU64(0x3))); 14117 14118 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)), 14119 mkU64(0x0), 14120 mkU64(0x2))); 14121 14122 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 14123 mkU64(0x0), 14124 mkU64(0x1))); 14125 14126 /* Store X_byte on the right place. */ 14127 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte)); 14128 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14129 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14130 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14131 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14132 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14133 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14134 store(mkexpr(t1), mkexpr(H_byte)); 14135 14136 #else /* _MIPSEB */ 14137 /* Calculate X_byte position. */ 14138 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)), 14139 mkU64(0x6), 14140 mkU64(0x0))); 14141 14142 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)), 14143 mkU64(0x5), 14144 mkU64(0x0))); 14145 14146 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)), 14147 mkU64(0x4), 14148 mkU64(0x0))); 14149 14150 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)), 14151 mkU64(0x3), 14152 mkU64(0x0))); 14153 14154 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)), 14155 mkU64(0x2), 14156 mkU64(0x0))); 14157 14158 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14159 mkU64(0x0), 14160 mkU64(0x1))); 14161 14162 /* Store X_byte on the right place. */ 14163 store(mkexpr(t2), mkexpr(A_byte)); 14164 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14165 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14166 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14167 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14168 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14169 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14170 store(mkexpr(t1), mkexpr(H_byte)); 14171 #endif 14172 break; 14173 } 14174 14175 case 0x28: /* SB */ 14176 DIP("sb r%u, %u(r%u)", rt, imm, rs); 14177 LOAD_STORE_PATTERN; 14178 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt))); 14179 break; 14180 14181 case 0x29: /* SH */ 14182 DIP("sh r%u, %u(r%u)", rt, imm, rs); 14183 LOAD_STORE_PATTERN; 14184 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt))); 14185 break; 14186 14187 case 0x2A: /* SWL */ 14188 DIP("swl r%u, %u(r%u)", rt, imm, rs); 14189 if (mode64) { 14190 IRTemp E_byte = newTemp(Ity_I8); 14191 IRTemp F_byte = newTemp(Ity_I8); 14192 IRTemp G_byte = newTemp(Ity_I8); 14193 IRTemp H_byte = newTemp(Ity_I8); 14194 IRTemp F_pos = newTemp(Ity_I64); 14195 IRTemp G_pos = newTemp(Ity_I64); 14196 14197 /* H byte */ 14198 assign(H_byte, getByteFromReg(rt, 0)); 14199 /* G byte */ 14200 assign(G_byte, getByteFromReg(rt, 1)); 14201 /* F byte */ 14202 assign(F_byte, getByteFromReg(rt, 2)); 14203 /* E byte */ 14204 assign(E_byte, getByteFromReg(rt, 3)); 14205 14206 /* t1 = addr */ 14207 t1 = newTemp(Ity_I64); 14208 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14209 14210 /* t2 = word addr */ 14211 t2 = newTemp(Ity_I64); 14212 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); 14213 14214 /* t3 = addr mod 4 */ 14215 t3 = newTemp(Ity_I64); 14216 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3))); 14217 14218 #if defined (_MIPSEL) 14219 /* Calculate X_byte position. */ 14220 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14221 mkU64(0x0), 14222 mkU64(0x1))); 14223 14224 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14225 mkU64(0x1), 14226 mkU64(0x0))); 14227 14228 /* Store X_byte on the right place. */ 14229 store(mkexpr(t2), mkexpr(H_byte)); 14230 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14231 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14232 store(mkexpr(t1), mkexpr(E_byte)); 14233 14234 #else /* _MIPSEB */ 14235 /* Calculate X_byte position. */ 14236 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14237 mkU64(0x0), 14238 mkU64(0x1))); 14239 14240 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14241 mkU64(0x2), 14242 mkU64(0x3))); 14243 14244 store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte)); 14245 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14246 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14247 store(mkexpr(t1), mkexpr(E_byte)); 14248 14249 #endif 14250 } else { 14251 IRTemp E_byte = newTemp(Ity_I8); 14252 IRTemp F_byte = newTemp(Ity_I8); 14253 IRTemp G_byte = newTemp(Ity_I8); 14254 IRTemp H_byte = newTemp(Ity_I8); 14255 IRTemp F_pos = newTemp(Ity_I32); 14256 IRTemp G_pos = newTemp(Ity_I32); 14257 14258 /* H byte */ 14259 assign(H_byte, getByteFromReg(rt, 0)); 14260 /* G byte */ 14261 assign(G_byte, getByteFromReg(rt, 1)); 14262 /* F byte */ 14263 assign(F_byte, getByteFromReg(rt, 2)); 14264 /* E byte */ 14265 assign(E_byte, getByteFromReg(rt, 3)); 14266 14267 /* t1 = addr */ 14268 t1 = newTemp(Ity_I32); 14269 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 14270 14271 /* t2 = word addr */ 14272 t2 = newTemp(Ity_I32); 14273 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL))); 14274 14275 /* t3 = addr mod 4 */ 14276 t3 = newTemp(Ity_I32); 14277 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3))); 14278 14279 #if defined (_MIPSEL) 14280 /* Calculate X_byte position. */ 14281 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14282 mkU32(0x0), 14283 mkU32(0x1))); 14284 14285 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14286 mkU32(0x1), 14287 mkU32(0x0))); 14288 14289 /* Store X_byte on the right place. */ 14290 store(mkexpr(t2), mkexpr(H_byte)); 14291 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14292 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14293 store(mkexpr(t1), mkexpr(E_byte)); 14294 14295 #else /* _MIPSEB */ 14296 /* Calculate X_byte position. */ 14297 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14298 mkU32(0x0), 14299 mkU32(0x1))); 14300 14301 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14302 mkU32(0x2), 14303 mkU32(0x3))); 14304 14305 store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte)); 14306 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14307 store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14308 store(mkexpr(t1), mkexpr(E_byte)); 14309 14310 #endif 14311 } 14312 break; 14313 14314 case 0x2E: /* SWR */ 14315 DIP("swr r%u, %u(r%u)", rt, imm, rs); 14316 if (mode64) { 14317 IRTemp E_byte = newTemp(Ity_I8); 14318 IRTemp F_byte = newTemp(Ity_I8); 14319 IRTemp G_byte = newTemp(Ity_I8); 14320 IRTemp H_byte = newTemp(Ity_I8); 14321 IRTemp F_pos = newTemp(Ity_I64); 14322 IRTemp G_pos = newTemp(Ity_I64); 14323 14324 /* H byte */ 14325 assign(H_byte, getByteFromReg(rt, 0)); 14326 /* G byte */ 14327 assign(G_byte, getByteFromReg(rt, 1)); 14328 /* F byte */ 14329 assign(F_byte, getByteFromReg(rt, 2)); 14330 /* E byte */ 14331 assign(E_byte, getByteFromReg(rt, 3)); 14332 14333 /* t1 = addr */ 14334 t1 = newTemp(Ity_I64); 14335 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14336 14337 /* t2 = word addr */ 14338 t2 = newTemp(Ity_I64); 14339 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); 14340 14341 /* t3 = addr mod 4 */ 14342 t3 = newTemp(Ity_I64); 14343 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3))); 14344 14345 #if defined (_MIPSEL) 14346 /* Calculate X_byte position. */ 14347 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14348 mkU64(0x2), 14349 mkU64(0x3))); 14350 14351 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14352 mkU64(0x0), 14353 mkU64(0x1))); 14354 14355 /* Store X_byte on the right place. */ 14356 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte)); 14357 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14358 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14359 store(mkexpr(t1), mkexpr(H_byte)); 14360 14361 #else /* _MIPSEB */ 14362 /* Calculate X_byte position. */ 14363 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14364 mkU64(0x1), 14365 mkU64(0x0))); 14366 14367 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14368 mkU64(0x0), 14369 mkU64(0x1))); 14370 14371 /* Store X_byte on the right place. */ 14372 store(mkexpr(t2), mkexpr(E_byte)); 14373 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14374 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14375 store(mkexpr(t1), mkexpr(H_byte)); 14376 #endif 14377 } else { 14378 IRTemp E_byte = newTemp(Ity_I8); 14379 IRTemp F_byte = newTemp(Ity_I8); 14380 IRTemp G_byte = newTemp(Ity_I8); 14381 IRTemp H_byte = newTemp(Ity_I8); 14382 IRTemp F_pos = newTemp(Ity_I32); 14383 IRTemp G_pos = newTemp(Ity_I32); 14384 14385 /* H byte */ 14386 assign(H_byte, getByteFromReg(rt, 0)); 14387 /* G byte */ 14388 assign(G_byte, getByteFromReg(rt, 1)); 14389 /* F byte */ 14390 assign(F_byte, getByteFromReg(rt, 2)); 14391 /* E byte */ 14392 assign(E_byte, getByteFromReg(rt, 3)); 14393 14394 /* t1 = addr */ 14395 t1 = newTemp(Ity_I32); 14396 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 14397 14398 /* t2 = word addr */ 14399 t2 = newTemp(Ity_I32); 14400 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL))); 14401 14402 /* t3 = addr mod 4 */ 14403 t3 = newTemp(Ity_I32); 14404 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3))); 14405 14406 #if defined (_MIPSEL) 14407 /* Calculate X_byte position. */ 14408 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14409 mkU32(0x2), 14410 mkU32(0x3))); 14411 14412 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14413 mkU32(0x0), 14414 mkU32(0x1))); 14415 14416 /* Store X_byte on the right place. */ 14417 store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte)); 14418 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14419 store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14420 store(mkexpr(t1), mkexpr(H_byte)); 14421 14422 #else /* _MIPSEB */ 14423 /* Calculate X_byte position. */ 14424 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14425 mkU32(0x1), 14426 mkU32(0x0))); 14427 14428 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14429 mkU32(0x0), 14430 mkU32(0x1))); 14431 14432 /* Store X_byte on the right place. */ 14433 store(mkexpr(t2), mkexpr(E_byte)); 14434 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14435 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14436 store(mkexpr(t1), mkexpr(H_byte)); 14437 #endif 14438 } 14439 break; 14440 14441 case 0x1C: /* Special2 */ 14442 switch (function) { 14443 /* Cavium Specific instructions */ 14444 case 0x03: case 0x32: case 0x33: /* DMUL, CINS , CINS32 */ 14445 case 0x3A: case 0x3B: case 0x2B: /* EXT, EXT32, SNE */ 14446 /* CVM Compare Instructions */ 14447 case 0x2A: case 0x2E: case 0x2F: /* SEQ, SEQI, SNEI */ 14448 /* CPU Load, Store, Memory, and Control Instructions */ 14449 case 0x18: case 0x19: /* SAA, SAAD */ 14450 case 0x1F: /* LAA, LAAD, LAI, LAID */ 14451 case 0x28: case 0x2C: case 0x2D: /* BADDU, POP, DPOP */ 14452 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 14453 if (dis_instr_CVM(cins)) 14454 break; 14455 goto decode_failure; 14456 } else { 14457 goto decode_failure; 14458 } 14459 break; 14460 14461 case 0x02: { /* MUL */ 14462 DIP("mul r%u, r%u, r%u", rd, rs, rt); 14463 if (mode64) { 14464 IRTemp tmpRs32 = newTemp(Ity_I32); 14465 IRTemp tmpRt32 = newTemp(Ity_I32); 14466 IRTemp tmpRes = newTemp(Ity_I32); 14467 14468 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14469 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 14470 assign(tmpRes, binop(Iop_Mul32, 14471 mkexpr(tmpRs32), mkexpr(tmpRt32))); 14472 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True)); 14473 } else 14474 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt))); 14475 break; 14476 } 14477 14478 case 0x00: { /* MADD */ 14479 if (mode64) { 14480 DIP("madd r%u, r%u", rs, rt); 14481 t1 = newTemp(Ity_I32); 14482 t2 = newTemp(Ity_I32); 14483 t3 = newTemp(Ity_I64); 14484 t4 = newTemp(Ity_I64); 14485 t5 = newTemp(Ity_I64); 14486 t6 = newTemp(Ity_I32); 14487 14488 assign(t1, mkNarrowTo32(ty, getHI())); 14489 assign(t2, mkNarrowTo32(ty, getLO())); 14490 14491 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 14492 mkNarrowTo32(ty, getIReg(rt)))); 14493 14494 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14495 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4))); 14496 14497 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14498 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14499 } else { 14500 if ( (1 <= ac) && ( 3 >= ac) ) { 14501 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14502 /* If DSP is present -> DSP ASE MADD */ 14503 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14504 if (0 != retVal ) { 14505 goto decode_failure_dsp; 14506 } 14507 break; 14508 } else { 14509 goto decode_failure_dsp; 14510 } 14511 } else { 14512 DIP("madd r%u, r%u", rs, rt); 14513 t1 = newTemp(Ity_I32); 14514 t2 = newTemp(Ity_I32); 14515 t3 = newTemp(Ity_I64); 14516 t4 = newTemp(Ity_I32); 14517 t5 = newTemp(Ity_I32); 14518 t6 = newTemp(Ity_I32); 14519 14520 assign(t1, getHI()); 14521 assign(t2, getLO()); 14522 14523 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 14524 14525 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 14526 mkexpr(t3)))); 14527 14528 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 14529 unop(Iop_64to32, mkexpr(t3))))); 14530 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 14531 14532 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, 14533 mkexpr(t3)))); 14534 putLO(mkexpr(t4)); 14535 break; 14536 } 14537 } 14538 break; 14539 } 14540 14541 case 0x01: { /* MADDU */ 14542 if (mode64) { 14543 DIP("maddu r%u, r%u", rs, rt); 14544 t1 = newTemp(Ity_I32); 14545 t2 = newTemp(Ity_I32); 14546 t3 = newTemp(Ity_I64); 14547 t4 = newTemp(Ity_I64); 14548 t5 = newTemp(Ity_I64); 14549 t6 = newTemp(Ity_I32); 14550 14551 assign(t1, mkNarrowTo32(ty, getHI())); 14552 assign(t2, mkNarrowTo32(ty, getLO())); 14553 14554 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 14555 mkNarrowTo32(ty, getIReg(rt)))); 14556 14557 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14558 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4))); 14559 14560 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14561 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14562 } else { 14563 if ( (1 <= ac) && ( 3 >= ac) ) { 14564 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14565 /* If DSP is present -> DSP ASE MADDU */ 14566 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14567 if (0 != retVal ) { 14568 goto decode_failure_dsp; 14569 } 14570 break; 14571 } else { 14572 goto decode_failure_dsp; 14573 } 14574 } else { 14575 DIP("maddu r%u, r%u", rs, rt); 14576 t1 = newTemp(Ity_I32); 14577 t2 = newTemp(Ity_I32); 14578 t3 = newTemp(Ity_I64); 14579 t4 = newTemp(Ity_I32); 14580 t5 = newTemp(Ity_I32); 14581 t6 = newTemp(Ity_I32); 14582 14583 assign(t1, getHI()); 14584 assign(t2, getLO()); 14585 14586 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 14587 14588 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 14589 mkexpr(t3)))); 14590 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 14591 unop(Iop_64to32, mkexpr(t3))))); 14592 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 14593 14594 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, 14595 mkexpr(t3)))); 14596 putLO(mkexpr(t4)); 14597 break; 14598 } 14599 } 14600 break; 14601 } 14602 14603 case 0x04: { /* MSUB */ 14604 if (mode64) { 14605 DIP("msub r%u, r%u", rs, rt); 14606 t1 = newTemp(Ity_I32); 14607 t2 = newTemp(Ity_I32); 14608 t3 = newTemp(Ity_I64); 14609 t4 = newTemp(Ity_I64); 14610 t5 = newTemp(Ity_I64); 14611 t6 = newTemp(Ity_I32); 14612 14613 assign(t1, mkNarrowTo32(ty, getHI())); 14614 assign(t2, mkNarrowTo32(ty, getLO())); 14615 14616 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 14617 mkNarrowTo32(ty, getIReg(rt)))); 14618 14619 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14620 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3))); 14621 14622 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14623 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14624 } else { 14625 if ( (1 <= ac) && ( 3 >= ac) ) { 14626 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14627 /* If DSP is present -> DSP ASE MSUB */ 14628 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14629 if (0 != retVal ) { 14630 goto decode_failure_dsp; 14631 } 14632 break; 14633 } else { 14634 goto decode_failure_dsp; 14635 } 14636 } else { 14637 DIP("msub r%u, r%u", rs, rt); 14638 t1 = newTemp(Ity_I32); 14639 t2 = newTemp(Ity_I32); 14640 t3 = newTemp(Ity_I64); 14641 t4 = newTemp(Ity_I32); 14642 t5 = newTemp(Ity_I1); 14643 t6 = newTemp(Ity_I32); 14644 14645 assign(t1, getHI()); 14646 assign(t2, getLO()); 14647 14648 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 14649 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */ 14650 14651 /* if lo<lo(mul) hi = hi - 1 */ 14652 assign(t5, binop(Iop_CmpLT32U, 14653 mkexpr(t2), 14654 mkexpr(t4))); 14655 14656 assign(t6, IRExpr_ITE(mkexpr(t5), 14657 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)), 14658 mkexpr(t1))); 14659 14660 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, 14661 mkexpr(t3)))); 14662 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 14663 break; 14664 } 14665 } 14666 break; 14667 } 14668 14669 case 0x05: { /* MSUBU */ 14670 if (mode64) { 14671 DIP("msubu r%u, r%u", rs, rt); 14672 t1 = newTemp(Ity_I32); 14673 t2 = newTemp(Ity_I32); 14674 t3 = newTemp(Ity_I64); 14675 t4 = newTemp(Ity_I64); 14676 t5 = newTemp(Ity_I64); 14677 t6 = newTemp(Ity_I32); 14678 14679 assign(t1, mkNarrowTo32(ty, getHI())); 14680 assign(t2, mkNarrowTo32(ty, getLO())); 14681 14682 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 14683 mkNarrowTo32(ty, getIReg(rt)))); 14684 14685 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14686 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3))); 14687 14688 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14689 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14690 } else { 14691 if ( (1 <= ac) && ( 3 >= ac) ) { 14692 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14693 /* If DSP is present -> DSP ASE MSUBU */ 14694 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14695 if (0 != retVal ) { 14696 goto decode_failure_dsp; 14697 } 14698 break; 14699 } else { 14700 goto decode_failure_dsp; 14701 } 14702 } else { 14703 DIP("msubu r%u, r%u", rs, rt); 14704 t1 = newTemp(Ity_I32); 14705 t2 = newTemp(Ity_I32); 14706 t3 = newTemp(Ity_I64); 14707 t4 = newTemp(Ity_I32); 14708 t5 = newTemp(Ity_I1); 14709 t6 = newTemp(Ity_I32); 14710 14711 assign(t1, getHI()); 14712 assign(t2, getLO()); 14713 14714 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 14715 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */ 14716 14717 /* if lo<lo(mul) hi = hi - 1 */ 14718 assign(t5, binop(Iop_CmpLT32U, 14719 mkexpr(t2), 14720 mkexpr(t4))); 14721 14722 assign(t6, IRExpr_ITE(mkexpr(t5), 14723 binop(Iop_Sub32, 14724 mkexpr(t1), 14725 mkU32(0x1)), 14726 mkexpr(t1))); 14727 14728 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, 14729 mkexpr(t3)))); 14730 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 14731 break; 14732 } 14733 } 14734 break; 14735 } 14736 14737 case 0x6: /* dmul MIPS64 - Netlogic */ 14738 DIP("dmul r%u, r%u, r%u", rd, rs, rt); 14739 t0 = newTemp(Ity_I128); 14740 14741 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt))); 14742 14743 putIReg(rd, unop(Iop_128to64, mkexpr(t0))); 14744 break; 14745 14746 case 0x10: /* LDADDW - Swap Word - Netlogic */ 14747 DIP("ldaddw r%u, r%u", rt, rs); 14748 t0 = newTemp(Ity_I32); 14749 t1 = newTemp(Ity_I32); 14750 t2 = newTemp(Ity_I32); 14751 t3 = newTemp(Ity_I64); 14752 t4 = newTemp(Ity_I32); 14753 t5 = newTemp(Ity_I32); 14754 t6 = newTemp(Ity_I32); 14755 14756 /* v = GPR[rt] */ 14757 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 14758 14759 /* GPR[rt] = memory[base]; */ 14760 assign(t1, load(Ity_I32, getIReg(rs))); 14761 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 14762 14763 /* memory[base] = memory[base] + v; */ 14764 store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1))); 14765 break; 14766 14767 case 0x12: /* LDADDD - Swap Word - Netlogic */ 14768 DIP("ldaddw r%u, r%u", rt, rs); 14769 t0 = newTemp(Ity_I64); 14770 t1 = newTemp(Ity_I64); 14771 14772 /* v = GPR[rt] */ 14773 assign(t0, getIReg(rt)); 14774 14775 /* GPR[rt] = memory[base]; */ 14776 assign(t1, load(Ity_I64, getIReg(rs))); 14777 putIReg(rt, mkexpr(t1)); 14778 14779 /* memory[base] = memory[base] + v; */ 14780 store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1))); 14781 break; 14782 14783 case 0x14: /* SWAPW - Swap Word - Netlogic */ 14784 DIP("swapw r%u, r%u", rt, rs); 14785 t0 = newTemp(Ity_I32); 14786 t1 = newTemp(Ity_I32); 14787 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 14788 assign(t1, load(Ity_I32, getIReg(rs))); 14789 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 14790 store(getIReg(rs), mkexpr(t0)); 14791 break; 14792 14793 case 0x16: /* SWAPD - Swap Double - Netlogic */ 14794 DIP("swapw r%u, r%u", rt, rs); 14795 t0 = newTemp(Ity_I64); 14796 t1 = newTemp(Ity_I64); 14797 assign(t0, getIReg(rt)); 14798 assign(t1, load(Ity_I64, getIReg(rs))); 14799 putIReg(rt, mkexpr(t1)); 14800 store(getIReg(rs), mkexpr(t0)); 14801 break; 14802 14803 case 0x20: { /* CLZ */ 14804 DIP("clz r%u, r%u", rd, rs); 14805 if (mode64) { 14806 IRTemp tmpClz32 = newTemp(Ity_I32); 14807 IRTemp tmpRs32 = newTemp(Ity_I32); 14808 14809 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14810 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32))); 14811 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True)); 14812 } else { 14813 t1 = newTemp(Ity_I1); 14814 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0))); 14815 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14816 mkU32(0x00000020), 14817 unop(Iop_Clz32, getIReg(rs)))); 14818 } 14819 break; 14820 } 14821 14822 case 0x21: { /* CLO */ 14823 DIP("clo r%u, r%u", rd, rs); 14824 if (mode64) { 14825 IRTemp tmpClo32 = newTemp(Ity_I32); 14826 IRTemp tmpRs32 = newTemp(Ity_I32); 14827 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14828 14829 t1 = newTemp(Ity_I1); 14830 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff))); 14831 assign(tmpClo32, IRExpr_ITE(mkexpr(t1), 14832 mkU32(0x00000020), 14833 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32))))); 14834 14835 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True)); 14836 break; 14837 } else { 14838 t1 = newTemp(Ity_I1); 14839 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff))); 14840 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14841 mkU32(0x00000020), 14842 unop(Iop_Clz32, 14843 unop(Iop_Not32, getIReg(rs))))); 14844 break; 14845 } 14846 } 14847 14848 case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */ 14849 DIP("dclz r%u, r%u", rd, rs); 14850 t1 = newTemp(Ity_I1); 14851 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0))); 14852 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14853 mkU64(0x00000040), 14854 unop(Iop_Clz64, getIReg(rs)))); 14855 break; 14856 14857 case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */ 14858 DIP("dclo r%u, r%u", rd, rs); 14859 t1 = newTemp(Ity_I1); 14860 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), 14861 mkU64(0xffffffffffffffffULL))); 14862 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14863 mkU64(0x40), 14864 unop(Iop_Clz64, unop(Iop_Not64, 14865 getIReg(rs))))); 14866 break; 14867 14868 default: 14869 goto decode_failure; 14870 } 14871 break; 14872 14873 case 0x1F: /* Special3 */ 14874 switch (function) { 14875 case 0x01: { 14876 /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */ 14877 msb = get_msb(cins); 14878 lsb = get_lsb(cins); 14879 size = msb + 1; 14880 UInt srcPos = lsb; 14881 UInt dstSz = msb + 33; 14882 t1 = newTemp(Ity_I64); 14883 DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1); 14884 14885 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */ 14886 UChar rsAmt = 64 - dstSz; /* right shift amount; */ 14887 14888 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 14889 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 14890 14891 break; 14892 } 14893 case 0x02: { 14894 /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */ 14895 msb = get_msb(cins); 14896 lsb = get_lsb(cins); 14897 size = msb + 1; 14898 UInt srcPos = lsb + 32; 14899 UInt dstSz = msb + 1; 14900 DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz); 14901 t1 = newTemp(Ity_I64); 14902 14903 vassert(srcPos >= 32 && srcPos < 64); 14904 vassert(dstSz > 0 && dstSz <= 32); 14905 vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64); 14906 14907 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */ 14908 UChar rsAmt = 64 - dstSz; /* right shift amount; */ 14909 14910 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 14911 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 14912 break; 14913 } 14914 case 0x05: { 14915 /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */ 14916 msb = get_msb(cins); 14917 lsb = get_lsb(cins); 14918 size = msb + 1; 14919 UInt dstPos = lsb; 14920 UInt srcSz = msb - lsb + 33; 14921 t1 = newTemp(ty); 14922 t2 = newTemp(ty); 14923 t3 = newTemp(ty); 14924 t4 = newTemp(ty); 14925 IRTemp tmpT1 = newTemp(ty); 14926 IRTemp tmpT2 = newTemp(ty); 14927 IRTemp tmpT3 = newTemp(ty); 14928 IRTemp tmpT4 = newTemp(ty); 14929 IRTemp tmpT5 = newTemp(ty); 14930 IRTemp tmpT6 = newTemp(ty); 14931 IRTemp tmpT7 = newTemp(ty); 14932 IRTemp tmpRs = newTemp(ty); 14933 IRTemp tmpRt = newTemp(ty); 14934 IRTemp tmpRd = newTemp(ty); 14935 14936 assign(tmpRs, getIReg(rs)); 14937 assign(tmpRt, getIReg(rt)); 14938 DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb); 14939 14940 UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */ 14941 UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */ 14942 14943 assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 14944 assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1))); 14945 assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt))); 14946 assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1))); 14947 14948 lsAmt = 63 - dstPos; /* left shift amount; */ 14949 rsAmt = 63 - dstPos; /* right shift amount; */ 14950 14951 assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 14952 assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1))); 14953 assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt))); 14954 assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1))); 14955 14956 /* extract size from src register */ 14957 lsAmt = 64 - srcSz; /* left shift amount; */ 14958 rsAmt = 64 - (lsb + srcSz); /* right shift amount; */ 14959 14960 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 14961 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt))); 14962 14963 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4))); 14964 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7))); 14965 putIReg(rt, mkexpr(tmpRd)); 14966 break; 14967 } 14968 case 0x06: { 14969 /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */ 14970 msb = get_msb(cins); 14971 lsb = get_lsb(cins); 14972 size = msb + 1; 14973 UInt dstPos = lsb + 32; 14974 UInt srcSz = msb - lsb + 1; 14975 IRTemp tmpT1 = newTemp(ty); 14976 IRTemp tmpT2 = newTemp(ty); 14977 IRTemp tmpT3 = newTemp(ty); 14978 IRTemp tmpT4 = newTemp(ty); 14979 IRTemp tmpT5 = newTemp(ty); 14980 IRTemp tmpT6 = newTemp(ty); 14981 IRTemp tmpT7 = newTemp(ty); 14982 IRTemp tmpT8 = newTemp(ty); 14983 IRTemp tmpT9 = newTemp(ty); 14984 IRTemp tmpRs = newTemp(ty); 14985 IRTemp tmpRt = newTemp(ty); 14986 IRTemp tmpRd = newTemp(ty); 14987 14988 assign(tmpRs, getIReg(rs)); 14989 assign(tmpRt, getIReg(rt)); 14990 DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb); 14991 14992 UChar lsAmt = 64 - srcSz; /* left shift amount; */ 14993 UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */ 14994 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 14995 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt))); 14996 14997 lsAmt = 64 - dstPos; /* left shift amount; */ 14998 rsAmt = 64 - dstPos; /* right shift amount; */ 14999 assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 15000 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt))); 15001 15002 lsAmt = dstPos; /* left shift amount; */ 15003 rsAmt = srcSz; /* right shift amount; */ 15004 assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 15005 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt))); 15006 15007 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt))); 15008 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt))); 15009 15010 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4))); 15011 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9))); 15012 putIReg(rt, mkexpr(tmpRd)); 15013 break; 15014 } 15015 case 0x07: { 15016 /* Doubleword Insert Bit Field - DINS; MIPS64r2 */ 15017 IRTemp tmp1 = newTemp(ty); 15018 IRTemp tmpT1 = newTemp(ty); 15019 IRTemp tmpT2 = newTemp(ty); 15020 IRTemp tmpT3 = newTemp(ty); 15021 IRTemp tmpT4 = newTemp(ty); 15022 IRTemp tmpT5 = newTemp(ty); 15023 IRTemp tmpT6 = newTemp(ty); 15024 IRTemp tmpT7 = newTemp(ty); 15025 IRTemp tmpT8 = newTemp(ty); 15026 IRTemp tmpT9 = newTemp(ty); 15027 IRTemp tmp = newTemp(ty); 15028 IRTemp tmpRs = newTemp(ty); 15029 IRTemp tmpRt = newTemp(ty); 15030 IRTemp tmpRd = newTemp(ty); 15031 15032 assign(tmpRs, getIReg(rs)); 15033 assign(tmpRt, getIReg(rt)); 15034 15035 msb = get_msb(cins); 15036 lsb = get_lsb(cins); 15037 size = msb + 1; 15038 DIP("dins r%u, r%u, %u, %u", rt, rs, lsb, 15039 msb - lsb + 1); 15040 UChar lsAmt = 63 - lsb; /* left shift amount; */ 15041 UChar rsAmt = 63 - lsb; /* right shift amount; */ 15042 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 15043 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 15044 assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt))); 15045 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1))); 15046 15047 lsAmt = msb; /* left shift amount; */ 15048 rsAmt = 1; /*right shift amount; */ 15049 assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 15050 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt))); 15051 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt))); 15052 assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt))); 15053 15054 lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */ 15055 rsAmt = 64 - (msb + 1); /* right shift amount; */ 15056 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 15057 assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt))); 15058 15059 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8))); 15060 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9))); 15061 putIReg(rt, mkexpr(tmpRd)); 15062 break; 15063 } 15064 case 0x24: /* DBSHFL */ 15065 lsb = get_lsb(cins); 15066 IRTemp tmpRs = newTemp(ty); 15067 IRTemp tmpRt = newTemp(ty); 15068 IRTemp tmpRd = newTemp(ty); 15069 assign(tmpRs, getIReg(rs)); 15070 assign(tmpRt, getIReg(rt)); 15071 switch (lsb) { 15072 case 0x02: { /* DSBH */ 15073 DIP("dsbh r%u, r%u", rd, rt); 15074 IRTemp tmpT1 = newTemp(ty); 15075 IRTemp tmpT2 = newTemp(ty); 15076 IRTemp tmpT3 = newTemp(ty); 15077 IRTemp tmpT4 = newTemp(ty); 15078 IRTemp tmpT5 = newTemp(Ity_I64); 15079 IRTemp tmpT6 = newTemp(ty); 15080 assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL)); 15081 assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL)); 15082 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5))); 15083 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8))); 15084 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6))); 15085 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8))); 15086 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2))); 15087 putIReg(rd, mkexpr(tmpRd)); 15088 break; 15089 } 15090 case 0x05: { /* DSHD */ 15091 DIP("dshd r%u, r%u\n", rd, rt); 15092 IRTemp tmpT1 = newTemp(ty); 15093 IRTemp tmpT2 = newTemp(ty); 15094 IRTemp tmpT3 = newTemp(ty); 15095 IRTemp tmpT4 = newTemp(ty); 15096 IRTemp tmpT5 = newTemp(Ity_I64); 15097 IRTemp tmpT6 = newTemp(ty); 15098 IRTemp tmpT7 = newTemp(ty); 15099 IRTemp tmpT8 = newTemp(ty); 15100 IRTemp tmpT9 = newTemp(ty); 15101 assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL)); 15102 assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL)); 15103 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5))); 15104 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16))); 15105 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6))); 15106 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16))); 15107 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2))); 15108 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32))); 15109 assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32))); 15110 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9))); 15111 putIReg(rd, mkexpr(tmpRd)); 15112 break; 15113 } 15114 default: 15115 vex_printf("\nop6o10 = %u", lsb); 15116 goto decode_failure;; 15117 } 15118 break; 15119 case 0x3B: { /* RDHWR */ 15120 DIP("rdhwr r%u, r%u", rt, rd); 15121 if (rd == 29) { 15122 putIReg(rt, getULR()); 15123 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2)) 15124 } else if (rd == 1 15125 || (rd == 31 15126 && VEX_MIPS_COMP_ID(archinfo->hwcaps) 15127 == VEX_PRID_COMP_CAVIUM)) { 15128 if (mode64) { 15129 IRTemp val = newTemp(Ity_I64); 15130 IRExpr** args = mkIRExprVec_2 (mkU64(rt), mkU64(rd)); 15131 IRDirty *d = unsafeIRDirty_1_N(val, 15132 0, 15133 "mips64_dirtyhelper_rdhwr", 15134 &mips64_dirtyhelper_rdhwr, 15135 args); 15136 stmt(IRStmt_Dirty(d)); 15137 putIReg(rt, mkexpr(val)); 15138 } else { 15139 IRTemp val = newTemp(Ity_I32); 15140 IRExpr** args = mkIRExprVec_2 (mkU32(rt), mkU32(rd)); 15141 IRDirty *d = unsafeIRDirty_1_N(val, 15142 0, 15143 "mips32_dirtyhelper_rdhwr", 15144 &mips32_dirtyhelper_rdhwr, 15145 args); 15146 stmt(IRStmt_Dirty(d)); 15147 putIReg(rt, mkexpr(val)); 15148 } 15149 #endif 15150 } else 15151 goto decode_failure; 15152 break; 15153 } 15154 case 0x04: /* INS */ 15155 msb = get_msb(cins); 15156 lsb = get_lsb(cins); 15157 size = msb - lsb + 1; 15158 DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb); 15159 15160 vassert(lsb + size <= 32); 15161 vassert(lsb + size > 0); 15162 15163 /* put size bits from rs at the pos in temporary */ 15164 t0 = newTemp(Ity_I32); 15165 t3 = newTemp(Ity_I32); 15166 /* shift left for 32 - size to clear leading bits and get zeros 15167 at the end */ 15168 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)), 15169 mkU8(32 - size))); 15170 /* now set it at pos */ 15171 t1 = newTemp(Ity_I32); 15172 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb))); 15173 15174 if (lsb > 0) { 15175 t2 = newTemp(Ity_I32); 15176 /* clear everything but lower pos bits from rt */ 15177 assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)), 15178 mkU8(32 - lsb))); 15179 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb))); 15180 } else 15181 assign(t3, mkU32(0)); 15182 15183 if (msb < 31) { 15184 t4 = newTemp(Ity_I32); 15185 /* clear everything but upper msb + 1 bits from rt */ 15186 assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)), 15187 mkU8(msb + 1))); 15188 t5 = newTemp(Ity_I32); 15189 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1))); 15190 15191 /* now combine these registers */ 15192 if (lsb > 0) { 15193 t6 = newTemp(Ity_I32); 15194 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1))); 15195 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6), 15196 mkexpr(t3)), True)); 15197 } else { 15198 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1), 15199 mkexpr(t5)), True)); 15200 } 15201 } else { 15202 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1), 15203 mkexpr(t3)), True)); 15204 } 15205 break; 15206 15207 case 0x00: /* EXT */ 15208 msb = get_msb(cins); 15209 lsb = get_lsb(cins); 15210 size = msb + 1; 15211 DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb); 15212 vassert(lsb + size <= 32); 15213 vassert(lsb + size > 0); 15214 /* put size bits from rs at the top of in temporary */ 15215 if (lsb + size < 32) { 15216 t0 = newTemp(Ity_I32); 15217 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)), 15218 mkU8(32 - lsb - size))); 15219 15220 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0), 15221 mkU8(32 - size)), True)); 15222 } else { 15223 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, 15224 mkNarrowTo32(ty, getIReg(rs)), 15225 mkU8(32 - size)), True)); 15226 } 15227 break; 15228 15229 case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */ 15230 msb = get_msb(cins); 15231 lsb = get_lsb(cins); 15232 size = msb + 1; 15233 DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1); 15234 t1 = newTemp(Ity_I64); 15235 vassert(lsb >= 0 && lsb < 32); 15236 vassert(size > 0 && size <= 32); 15237 vassert((lsb + size) > 0 && (lsb + size) <= 63); 15238 15239 UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */ 15240 UChar rsAmt = 63 - msb; /* right shift amount; */ 15241 15242 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 15243 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 15244 15245 break; 15246 15247 case 0x20: /* BSHFL */ 15248 switch (sa) { 15249 case 0x02: /* WSBH */ 15250 DIP("wsbh r%u, r%u", rd, rt); 15251 t0 = newTemp(Ity_I32); 15252 t1 = newTemp(Ity_I32); 15253 t2 = newTemp(Ity_I32); 15254 t3 = newTemp(Ity_I32); 15255 assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty, 15256 getIReg(rt)), mkU32(0x00FF0000)), 15257 mkU8(0x8))); 15258 assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty, 15259 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8))); 15260 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty, 15261 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8))); 15262 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty, 15263 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8))); 15264 putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32, 15265 mkexpr(t0), mkexpr(t1)), 15266 binop(Iop_Or32, mkexpr(t2), 15267 mkexpr(t3))), True)); 15268 break; 15269 15270 case 0x10: /* SEB */ 15271 DIP("seb r%u, r%u", rd, rt); 15272 if (mode64) 15273 putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt)))); 15274 else 15275 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt)))); 15276 break; 15277 15278 case 0x18: /* SEH */ 15279 DIP("seh r%u, r%u", rd, rt); 15280 if (mode64) 15281 putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt)))); 15282 else 15283 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 15284 break; 15285 15286 default: 15287 goto decode_failure; 15288 15289 } 15290 break; /* BSHFL */ 15291 15292 /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */ 15293 case 0xA: /* LX */ 15294 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 15295 if (dis_instr_CVM(cins)) 15296 break; 15297 goto decode_failure; 15298 } 15299 case 0xC: /* INSV */ 15300 case 0x38: { /* EXTR.W */ 15301 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15302 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15303 if (0 != retVal ) { 15304 goto decode_failure_dsp; 15305 } 15306 break; 15307 } else { 15308 goto decode_failure_dsp; 15309 } 15310 break; 15311 } 15312 case 0x10: { /* ADDU.QB */ 15313 switch(sa) { 15314 case 0xC: /* SUBU_S.PH */ 15315 case 0xD: /* ADDU_S.PH */ 15316 case 0x1E: { /* MULQ_S.PH */ 15317 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15318 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15319 if (0 != retVal ) { 15320 goto decode_failure_dsp; 15321 } 15322 break; 15323 } else { 15324 goto decode_failure_dsp; 15325 } 15326 break; 15327 } 15328 default: { 15329 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15330 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15331 if (0 != retVal ) { 15332 goto decode_failure_dsp; 15333 } 15334 break; 15335 } else { 15336 goto decode_failure_dsp; 15337 } 15338 break; 15339 } 15340 } 15341 break; 15342 } 15343 case 0x11: { /* CMPU.EQ.QB */ 15344 switch(sa) { 15345 case 0x18: /* CMPGDU.EQ.QB */ 15346 case 0x19: /* CMPGDU.LT.QB */ 15347 case 0x1A: /* CMPGDU.LE.QB */ 15348 case 0x0D: /* PRECR.QB.PH */ 15349 case 0x1E: /* PRECR_SRA.PH.W */ 15350 case 0x1F: { /* PRECR_SRA_R.PH.W */ 15351 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15352 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15353 if (0 != retVal ) { 15354 goto decode_failure_dsp; 15355 } 15356 break; 15357 } else { 15358 goto decode_failure_dsp; 15359 } 15360 break; 15361 } 15362 default: { 15363 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15364 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15365 if (0 != retVal ) { 15366 goto decode_failure_dsp; 15367 } 15368 break; 15369 } else { 15370 goto decode_failure_dsp; 15371 } 15372 break; 15373 } 15374 } 15375 break; 15376 } 15377 case 0x12: { /* ABSQ_S.PH */ 15378 switch(sa){ 15379 case 0x1: { /* ABSQ_S.QB */ 15380 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15381 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15382 if (0 != retVal ) { 15383 goto decode_failure_dsp; 15384 } 15385 break; 15386 } else { 15387 goto decode_failure_dsp; 15388 } 15389 break; 15390 } 15391 default: { 15392 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15393 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15394 if (0 != retVal ) { 15395 goto decode_failure_dsp; 15396 } 15397 break; 15398 } else { 15399 goto decode_failure_dsp; 15400 } 15401 break; 15402 } 15403 } 15404 break; 15405 } 15406 case 0x13: { /* SHLL.QB */ 15407 switch(sa) { 15408 case 0x04: /* SHRA.QB */ 15409 case 0x05: /* SHRA_R.QB */ 15410 case 0x06: /* SHRAV.QB */ 15411 case 0x07: /* SHRAV_R.QB */ 15412 case 0x19: /* SHLR.PH */ 15413 case 0x1B: { /* SHLRV.PH */ 15414 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15415 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15416 if (0 != retVal ) { 15417 goto decode_failure_dsp; 15418 } 15419 break; 15420 } else { 15421 goto decode_failure_dsp; 15422 } 15423 break; 15424 } 15425 default: { 15426 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15427 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15428 if (0 != retVal ) { 15429 goto decode_failure_dsp; 15430 } 15431 break; 15432 } else { 15433 goto decode_failure_dsp; 15434 } 15435 break; 15436 } 15437 } 15438 break; 15439 } 15440 case 0x30: { /* DPAQ.W.PH */ 15441 switch(sa) { 15442 case 0x0: /* DPA.W.PH */ 15443 case 0x18: /* DPAQX_S.W.PH */ 15444 case 0x1A: /* DPAQX_SA.W.PH */ 15445 case 0x8: /* DPAX.W.PH */ 15446 case 0x1: /* DPS.W.PH */ 15447 case 0x19: /* DPSQX_S.W.PH */ 15448 case 0x1B: /* DPSQX_SA.W.PH */ 15449 case 0x9: /* DPSX.W.PH */ 15450 case 0x2: { /* MULSA.W.PH */ 15451 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15452 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15453 if (0 != retVal ) { 15454 goto decode_failure_dsp; 15455 } 15456 break; 15457 } else { 15458 goto decode_failure_dsp; 15459 } 15460 break; 15461 } 15462 default: { 15463 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15464 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15465 if (0 != retVal ) { 15466 goto decode_failure_dsp; 15467 } 15468 break; 15469 } else { 15470 goto decode_failure_dsp; 15471 } 15472 break; 15473 } 15474 } 15475 break; 15476 } 15477 case 0x18: /* ADDUH.QB/MUL.PH */ 15478 case 0x31: { /* APPEND */ 15479 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15480 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15481 if (0 != retVal ) { 15482 goto decode_failure_dsp; 15483 } 15484 break; 15485 } else { 15486 goto decode_failure_dsp; 15487 } 15488 } 15489 default: 15490 goto decode_failure; 15491 15492 } 15493 break; /* Special3 */ 15494 15495 case 0x3B: 15496 if (0x3B == function && 15497 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) { 15498 /*RDHWR*/ 15499 DIP("rdhwr r%u, r%u", rt, rd); 15500 if (rd == 29) { 15501 putIReg(rt, getULR()); 15502 } else 15503 goto decode_failure; 15504 break; 15505 } else { 15506 goto decode_failure; 15507 } 15508 15509 case 0x00: /* Special */ 15510 15511 switch (function) { 15512 case 0x1: { 15513 UInt mov_cc = get_mov_cc(cins); 15514 if (tf == 0) { /* MOVF */ 15515 DIP("movf r%u, r%u, %u", rd, rs, mov_cc); 15516 t1 = newTemp(Ity_I1); 15517 t2 = newTemp(Ity_I32); 15518 t3 = newTemp(Ity_I1); 15519 15520 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 15521 assign(t2, IRExpr_ITE(mkexpr(t1), 15522 binop(Iop_And32, 15523 binop(Iop_Shr32, getFCSR(), 15524 mkU8(23)), 15525 mkU32(0x1)), 15526 binop(Iop_And32, 15527 binop(Iop_Shr32, getFCSR(), 15528 mkU8(24 + mov_cc)), 15529 mkU32(0x1)) 15530 )); 15531 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 15532 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd))); 15533 } else if (tf == 1) { /* MOVT */ 15534 DIP("movt r%u, r%u, %u", rd, rs, mov_cc); 15535 t1 = newTemp(Ity_I1); 15536 t2 = newTemp(Ity_I32); 15537 t3 = newTemp(Ity_I1); 15538 15539 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 15540 assign(t2, IRExpr_ITE(mkexpr(t1), 15541 binop(Iop_And32, 15542 binop(Iop_Shr32, getFCSR(), 15543 mkU8(23)), 15544 mkU32(0x1)), 15545 binop(Iop_And32, 15546 binop(Iop_Shr32, getFCSR(), 15547 mkU8(24 + mov_cc)), 15548 mkU32(0x1)) 15549 )); 15550 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 15551 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd))); 15552 } 15553 break; 15554 } 15555 case 0x0A: { /* MOVZ */ 15556 DIP("movz r%u, r%u, r%u", rd, rs, rt); 15557 t1 = newTemp(ty); 15558 t2 = newTemp(ty); 15559 if (mode64) { 15560 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64, 15561 getIReg(rt), mkU64(0x0))))); 15562 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64, 15563 getIReg(rt), mkU64(0x0))))); 15564 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs), 15565 mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2)))); 15566 } else { 15567 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 15568 mkU32(0x0)))); 15569 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 15570 mkU32(0x0)))); 15571 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 15572 mkexpr(t1)), binop(Iop_And32, getIReg(rd), 15573 mkexpr(t2)))); 15574 } 15575 break; 15576 } 15577 15578 case 0x0B: { /* MOVN */ 15579 DIP("movn r%u, r%u, r%u", rd, rs, rt); 15580 t1 = newTemp(ty); 15581 t2 = newTemp(ty); 15582 if (mode64) { 15583 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64, 15584 getIReg(rt), mkU64(0x0))))); 15585 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64, 15586 getIReg(rt), mkU64(0x0))))); 15587 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs), 15588 mkexpr(t2)), binop(Iop_And64, getIReg(rd), 15589 mkexpr(t1)))); 15590 } else { 15591 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 15592 mkU32(0x0)))); 15593 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 15594 mkU32(0x0)))); 15595 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 15596 mkexpr(t2)), binop(Iop_And32, getIReg(rd), 15597 mkexpr(t1)))); 15598 } 15599 break; 15600 } 15601 15602 case 0x18: { /* MULT */ 15603 if ( (1 <= ac) && ( 3 >= ac) ) { 15604 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15605 /* If DSP is present -> DSP ASE MULT */ 15606 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15607 if (0 != retVal ) { 15608 goto decode_failure_dsp; 15609 } 15610 break; 15611 } else { 15612 goto decode_failure_dsp; 15613 } 15614 } else { 15615 DIP("mult r%u, r%u", rs, rt); 15616 t2 = newTemp(Ity_I64); 15617 15618 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 15619 mkNarrowTo32(ty, getIReg(rt)))); 15620 15621 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15622 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15623 break; 15624 } 15625 } 15626 case 0x19: { /* MULTU */ 15627 if ( (1 <= ac) && ( 3 >= ac) ) { 15628 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15629 /* If DSP is present -> DSP ASE MULTU */ 15630 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15631 if (0 != retVal ) { 15632 goto decode_failure_dsp; 15633 } 15634 break; 15635 } else { 15636 goto decode_failure_dsp; 15637 } 15638 } else { 15639 DIP("multu r%u, r%u", rs, rt); 15640 t2 = newTemp(Ity_I64); 15641 15642 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 15643 mkNarrowTo32(ty, getIReg(rt)))); 15644 15645 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15646 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15647 break; 15648 } 15649 } 15650 case 0x20: { /* ADD */ 15651 DIP("add r%u, r%u, r%u", rd, rs, rt); 15652 IRTemp tmpRs32 = newTemp(Ity_I32); 15653 IRTemp tmpRt32 = newTemp(Ity_I32); 15654 15655 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 15656 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15657 15658 t0 = newTemp(Ity_I32); 15659 t1 = newTemp(Ity_I32); 15660 t2 = newTemp(Ity_I32); 15661 t3 = newTemp(Ity_I32); 15662 t4 = newTemp(Ity_I32); 15663 /* dst = src0 + src1 15664 if (sign(src0 ) != sign(src1 )) 15665 goto no overflow; 15666 if (sign(dst) == sign(src0 )) 15667 goto no overflow; 15668 we have overflow! */ 15669 15670 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32))); 15671 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32))); 15672 assign(t2, unop(Iop_1Uto32, 15673 binop(Iop_CmpEQ32, 15674 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)), 15675 mkU32(0x80000000)))); 15676 15677 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 15678 assign(t4, unop(Iop_1Uto32, 15679 binop(Iop_CmpNE32, 15680 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)), 15681 mkU32(0x80000000)))); 15682 15683 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, 15684 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)), 15685 mkU32(0)), 15686 Ijk_SigFPE_IntOvf, 15687 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 15688 IRConst_U32(guest_PC_curr_instr + 4), 15689 OFFB_PC)); 15690 15691 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True)); 15692 break; 15693 } 15694 case 0x1A: /* DIV */ 15695 DIP("div r%u, r%u", rs, rt); 15696 if (mode64) { 15697 t2 = newTemp(Ity_I64); 15698 15699 assign(t2, binop(Iop_DivModS64to32, 15700 getIReg(rs), mkNarrowTo32(ty, getIReg(rt)))); 15701 15702 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15703 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15704 } else { 15705 t1 = newTemp(Ity_I64); 15706 t2 = newTemp(Ity_I64); 15707 15708 assign(t1, unop(Iop_32Sto64, getIReg(rs))); 15709 assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt))); 15710 15711 putHI(unop(Iop_64HIto32, mkexpr(t2))); 15712 putLO(unop(Iop_64to32, mkexpr(t2))); 15713 } 15714 break; 15715 15716 case 0x1B: /* DIVU */ 15717 DIP("divu r%u, r%u", rs, rt); 15718 if (mode64) { 15719 t2 = newTemp(Ity_I64); 15720 15721 assign(t2, binop(Iop_DivModU64to32, 15722 getIReg(rs), mkNarrowTo32(ty, getIReg(rt)))); 15723 15724 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15725 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15726 } else { 15727 t1 = newTemp(Ity_I64); 15728 t2 = newTemp(Ity_I64); 15729 assign(t1, unop(Iop_32Uto64, getIReg(rs))); 15730 assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt))); 15731 putHI(unop(Iop_64HIto32, mkexpr(t2))); 15732 putLO(unop(Iop_64to32, mkexpr(t2))); 15733 } 15734 break; 15735 15736 case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */ 15737 DIP("dmult r%u, r%u", rs, rt); 15738 t0 = newTemp(Ity_I128); 15739 15740 assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt))); 15741 15742 putHI(unop(Iop_128HIto64, mkexpr(t0))); 15743 putLO(unop(Iop_128to64, mkexpr(t0))); 15744 break; 15745 15746 case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */ 15747 DIP("dmultu r%u, r%u", rs, rt); 15748 t0 = newTemp(Ity_I128); 15749 15750 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt))); 15751 15752 putHI(unop(Iop_128HIto64, mkexpr(t0))); 15753 putLO(unop(Iop_128to64, mkexpr(t0))); 15754 break; 15755 15756 case 0x1E: /* Doubleword Divide DDIV; MIPS64 */ 15757 DIP("ddiv r%u, r%u", rs, rt); 15758 t1 = newTemp(Ity_I128); 15759 15760 assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt))); 15761 15762 putHI(unop(Iop_128HIto64, mkexpr(t1))); 15763 putLO(unop(Iop_128to64, mkexpr(t1))); 15764 break; 15765 15766 case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */ 15767 DIP("ddivu r%u, r%u", rs, rt); 15768 t1 = newTemp(Ity_I128); 15769 t2 = newTemp(Ity_I128); 15770 15771 assign(t1, binop(Iop_64HLto128, mkU64(0), getIReg(rs))); 15772 15773 assign(t2, binop(Iop_DivModU128to64, mkexpr(t1), getIReg(rt))); 15774 15775 putHI(unop(Iop_128HIto64, mkexpr(t2))); 15776 putLO(unop(Iop_128to64, mkexpr(t2))); 15777 break; 15778 15779 case 0x10: { /* MFHI */ 15780 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15781 /* If DSP is present -> DSP ASE MFHI */ 15782 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15783 if (0 != retVal ) { 15784 goto decode_failure; 15785 } 15786 break; 15787 } else { 15788 DIP("mfhi r%u", rd); 15789 putIReg(rd, getHI()); 15790 break; 15791 } 15792 } 15793 15794 case 0x11: { /* MTHI */ 15795 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15796 /* If DSP is present -> DSP ASE MTHI */ 15797 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15798 if (0 != retVal ) { 15799 goto decode_failure; 15800 } 15801 break; 15802 } else { 15803 DIP("mthi r%u", rs); 15804 putHI(getIReg(rs)); 15805 break; 15806 } 15807 } 15808 15809 case 0x12: { /* MFLO */ 15810 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15811 /* If DSP is present -> DSP ASE MFLO */ 15812 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15813 if (0 != retVal ) { 15814 goto decode_failure; 15815 } 15816 break; 15817 } else { 15818 DIP("mflo r%u", rd); 15819 putIReg(rd, getLO()); 15820 break; 15821 } 15822 } 15823 15824 case 0x13: { /* MTLO */ 15825 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15826 /* If DSP is present -> DSP ASE MTLO */ 15827 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15828 if (0 != retVal ) { 15829 goto decode_failure; 15830 } 15831 break; 15832 } else { 15833 DIP("mtlo r%u", rs); 15834 putLO(getIReg(rs)); 15835 break; 15836 } 15837 } 15838 15839 case 0x21: /* ADDU */ 15840 DIP("addu r%u, r%u, r%u", rd, rs, rt); 15841 if (mode64) { 15842 ALU_PATTERN64(Iop_Add32); 15843 } else { 15844 ALU_PATTERN(Iop_Add32); 15845 } 15846 break; 15847 15848 case 0x22: { /* SUB */ 15849 DIP("sub r%u, r%u, r%u", rd, rs, rt); 15850 IRTemp tmpRs32 = newTemp(Ity_I32); 15851 IRTemp tmpRt32 = newTemp(Ity_I32); 15852 15853 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 15854 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15855 t0 = newTemp(Ity_I32); 15856 t1 = newTemp(Ity_I32); 15857 t2 = newTemp(Ity_I32); 15858 t3 = newTemp(Ity_I32); 15859 t4 = newTemp(Ity_I32); 15860 t5 = newTemp(Ity_I32); 15861 /* dst = src0 + (-1 * src1) 15862 if(sign(src0 ) != sign((-1 * src1) )) 15863 goto no overflow; 15864 if(sign(dst) == sign(src0 )) 15865 goto no overflow; 15866 we have overflow! */ 15867 15868 assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1))); 15869 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5))); 15870 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5))); 15871 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32, 15872 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000)))); 15873 15874 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 15875 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32, 15876 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000)))); 15877 15878 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2), 15879 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf, 15880 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 15881 IRConst_U32(guest_PC_curr_instr + 4), 15882 OFFB_PC)); 15883 15884 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True)); 15885 break; 15886 } 15887 case 0x23: /* SUBU */ 15888 DIP("subu r%u, r%u, r%u", rd, rs, rt); 15889 if (mode64) { 15890 ALU_PATTERN64(Iop_Sub32); 15891 } else { 15892 ALU_PATTERN(Iop_Sub32); 15893 } 15894 break; 15895 15896 case 0x24: /* AND */ 15897 DIP("and r%u, r%u, r%u", rd, rs, rt); 15898 if (mode64) { 15899 ALU_PATTERN(Iop_And64); 15900 } else { 15901 ALU_PATTERN(Iop_And32); 15902 } 15903 break; 15904 15905 case 0x25: /* OR */ 15906 DIP("or r%u, r%u, r%u", rd, rs, rt); 15907 if (mode64) { 15908 ALU_PATTERN(Iop_Or64); 15909 } else { 15910 ALU_PATTERN(Iop_Or32); 15911 } 15912 break; 15913 15914 case 0x26: /* XOR */ 15915 DIP("xor r%u, r%u, r%u", rd, rs, rt); 15916 if (mode64) { 15917 ALU_PATTERN(Iop_Xor64); 15918 } else { 15919 ALU_PATTERN(Iop_Xor32); 15920 } 15921 break; 15922 15923 case 0x27: /* NOR */ 15924 DIP("nor r%u, r%u, r%u", rd, rs, rt); 15925 if (mode64) 15926 putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs), 15927 getIReg(rt)))); 15928 else 15929 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs), 15930 getIReg(rt)))); 15931 break; 15932 15933 case 0x08: /* JR */ 15934 DIP("jr r%u", rs); 15935 t0 = newTemp(ty); 15936 assign(t0, getIReg(rs)); 15937 lastn = mkexpr(t0); 15938 break; 15939 15940 case 0x09: /* JALR */ 15941 DIP("jalr r%u r%u", rd, rs); 15942 if (mode64) { 15943 putIReg(rd, mkU64(guest_PC_curr_instr + 8)); 15944 t0 = newTemp(Ity_I64); 15945 assign(t0, getIReg(rs)); 15946 lastn = mkexpr(t0); 15947 } else { 15948 putIReg(rd, mkU32(guest_PC_curr_instr + 8)); 15949 t0 = newTemp(Ity_I32); 15950 assign(t0, getIReg(rs)); 15951 lastn = mkexpr(t0); 15952 } 15953 break; 15954 15955 case 0x0C: /* SYSCALL */ 15956 DIP("syscall"); 15957 if (mode64) 15958 putPC(mkU64(guest_PC_curr_instr + 4)); 15959 else 15960 putPC(mkU32(guest_PC_curr_instr + 4)); 15961 dres.jk_StopHere = Ijk_Sys_syscall; 15962 dres.whatNext = Dis_StopHere; 15963 break; 15964 15965 case 0x2A: /* SLT */ 15966 DIP("slt r%u, r%u, r%u", rd, rs, rt); 15967 if (mode64) 15968 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs), 15969 getIReg(rt)))); 15970 else 15971 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 15972 getIReg(rt)))); 15973 break; 15974 15975 case 0x2B: /* SLTU */ 15976 DIP("sltu r%u, r%u, r%u", rd, rs, rt); 15977 if (mode64) 15978 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs), 15979 getIReg(rt)))); 15980 else 15981 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 15982 getIReg(rt)))); 15983 break; 15984 15985 case 0x00: { /* SLL */ 15986 DIP("sll r%u, r%u, %u", rd, rt, sa); 15987 IRTemp tmpRt32 = newTemp(Ity_I32); 15988 IRTemp tmpSh32 = newTemp(Ity_I32); 15989 IRTemp tmpRd = newTemp(Ity_I64); 15990 if (mode64) { 15991 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15992 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa))); 15993 assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 15994 putIReg(rd, mkexpr(tmpRd)); 15995 } else 15996 SXX_PATTERN(Iop_Shl32); 15997 break; 15998 } 15999 16000 case 0x04: { /* SLLV */ 16001 DIP("sllv r%u, r%u, r%u", rd, rt, rs); 16002 if (mode64) { 16003 IRTemp tmpRs8 = newTemp(Ity_I8); 16004 IRTemp tmpRt32 = newTemp(Ity_I32); 16005 IRTemp tmpSh32 = newTemp(Ity_I32); 16006 IRTemp tmp = newTemp(ty); 16007 assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs), 16008 mkSzImm(ty, 31))); 16009 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 16010 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16011 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8))); 16012 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16013 } else { 16014 SXXV_PATTERN(Iop_Shl32); 16015 } 16016 break; 16017 } 16018 16019 case 0x03: /* SRA */ 16020 DIP("sra r%u, r%u, %u", rd, rt, sa); 16021 if (mode64) { 16022 IRTemp tmpRt32 = newTemp(Ity_I32); 16023 IRTemp tmpSh32 = newTemp(Ity_I32); 16024 16025 t1 = newTemp(Ity_I64); 16026 t2 = newTemp(Ity_I64); 16027 t3 = newTemp(Ity_I64); 16028 16029 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */ 16030 mkU64(0xFFFFFFFF00000000ULL))); 16031 16032 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa))); 16033 16034 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16035 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa))); 16036 16037 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16038 } else { 16039 SXX_PATTERN(Iop_Sar32); 16040 } 16041 break; 16042 16043 case 0x07: /* SRAV */ 16044 DIP("srav r%u, r%u, r%u", rd, rt, rs); 16045 if (mode64) { 16046 IRTemp tmpRt32 = newTemp(Ity_I32); 16047 IRTemp tmpSh32 = newTemp(Ity_I32); 16048 16049 t1 = newTemp(Ity_I64); 16050 t2 = newTemp(Ity_I64); 16051 t3 = newTemp(Ity_I64); 16052 t4 = newTemp(Ity_I8); 16053 16054 assign(t4, unop(Iop_32to8, binop(Iop_And32, 16055 mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F)))); 16056 16057 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */ 16058 mkU64(0xFFFFFFFF00000000ULL))); 16059 16060 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4))); 16061 16062 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16063 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4))); 16064 16065 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16066 } else { 16067 SXXV_PATTERN(Iop_Sar32); 16068 } 16069 break; 16070 16071 case 0x02: { /* SRL */ 16072 rot = get_rot(cins); 16073 if (rot) { 16074 DIP("rotr r%u, r%u, %u", rd, rt, sa); 16075 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty, 16076 getIReg(rt)), sa), True)); 16077 } else { 16078 DIP("srl r%u, r%u, %u", rd, rt, sa); 16079 if (mode64) { 16080 IRTemp tmpSh32 = newTemp(Ity_I32); 16081 IRTemp tmpRt32 = newTemp(Ity_I32); 16082 16083 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16084 assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa))); 16085 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16086 } else { 16087 SXX_PATTERN(Iop_Shr32); 16088 } 16089 } 16090 break; 16091 } 16092 16093 case 0x06: { 16094 rot = get_rotv(cins); 16095 if (rot) { 16096 DIP("rotrv r%u, r%u, r%u", rd, rt, rs); 16097 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty, 16098 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True)); 16099 break; 16100 } else { /* SRLV */ 16101 DIP("srlv r%u, r%u, r%u", rd, rt, rs); 16102 if (mode64) { 16103 SXXV_PATTERN64(Iop_Shr32); 16104 } else { 16105 SXXV_PATTERN(Iop_Shr32); 16106 } 16107 break; 16108 } 16109 } 16110 16111 case 0x0D: /* BREAK */ 16112 DIP("break 0x%x", trap_code); 16113 if (mode64) 16114 jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4)); 16115 else 16116 jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4)); 16117 vassert(dres.whatNext == Dis_StopHere); 16118 break; 16119 16120 case 0x30: { /* TGE */ 16121 DIP("tge r%u, r%u %u", rs, rt, trap_code); 16122 if (mode64) { 16123 if (trap_code == 7) 16124 stmt (IRStmt_Exit (unop (Iop_Not1, 16125 binop (Iop_CmpLT64S, 16126 getIReg (rs), 16127 getIReg (rt))), 16128 Ijk_SigFPE_IntDiv, 16129 IRConst_U64(guest_PC_curr_instr + 4), 16130 OFFB_PC)); 16131 else if (trap_code == 6) 16132 stmt (IRStmt_Exit (unop (Iop_Not1, 16133 binop (Iop_CmpLT64S, 16134 getIReg (rs), 16135 getIReg (rt))), 16136 Ijk_SigFPE_IntOvf, 16137 IRConst_U64(guest_PC_curr_instr + 4), 16138 OFFB_PC)); 16139 else 16140 stmt (IRStmt_Exit (unop (Iop_Not1, 16141 binop (Iop_CmpLT64S, 16142 getIReg (rs), 16143 getIReg (rt))), 16144 Ijk_SigTRAP, 16145 IRConst_U64(guest_PC_curr_instr + 4), 16146 OFFB_PC)); 16147 } else { 16148 if (trap_code == 7) 16149 stmt (IRStmt_Exit (unop (Iop_Not1, 16150 binop (Iop_CmpLT32S, 16151 getIReg (rs), 16152 getIReg (rt))), 16153 Ijk_SigFPE_IntDiv, 16154 IRConst_U32(guest_PC_curr_instr + 4), 16155 OFFB_PC)); 16156 else if (trap_code == 6) 16157 stmt (IRStmt_Exit (unop (Iop_Not1, 16158 binop (Iop_CmpLT32S, 16159 getIReg (rs), 16160 getIReg (rt))), 16161 Ijk_SigFPE_IntOvf, 16162 IRConst_U32(guest_PC_curr_instr + 4), 16163 OFFB_PC)); 16164 else 16165 stmt (IRStmt_Exit (unop (Iop_Not1, 16166 binop (Iop_CmpLT32S, 16167 getIReg (rs), 16168 getIReg (rt))), 16169 Ijk_SigTRAP, 16170 IRConst_U32(guest_PC_curr_instr + 4), 16171 OFFB_PC)); 16172 } 16173 break; 16174 } 16175 case 0x31: { /* TGEU */ 16176 DIP("tgeu r%u, r%u %u", rs, rt, trap_code); 16177 if (mode64) { 16178 if (trap_code == 7) 16179 stmt (IRStmt_Exit (unop (Iop_Not1, 16180 binop (Iop_CmpLT64U, 16181 getIReg (rs), 16182 getIReg (rt))), 16183 Ijk_SigFPE_IntDiv, 16184 IRConst_U64(guest_PC_curr_instr + 4), 16185 OFFB_PC)); 16186 else if (trap_code == 6) 16187 stmt (IRStmt_Exit (unop (Iop_Not1, 16188 binop (Iop_CmpLT64U, 16189 getIReg (rs), 16190 getIReg (rt))), 16191 Ijk_SigFPE_IntOvf, 16192 IRConst_U64(guest_PC_curr_instr + 4), 16193 OFFB_PC)); 16194 else 16195 stmt (IRStmt_Exit (unop (Iop_Not1, 16196 binop (Iop_CmpLT64U, 16197 getIReg (rs), 16198 getIReg (rt))), 16199 Ijk_SigTRAP, 16200 IRConst_U64(guest_PC_curr_instr + 4), 16201 OFFB_PC)); 16202 } else { 16203 if (trap_code == 7) 16204 stmt (IRStmt_Exit (unop (Iop_Not1, 16205 binop (Iop_CmpLT32U, 16206 getIReg (rs), 16207 getIReg (rt))), 16208 Ijk_SigFPE_IntDiv, 16209 IRConst_U32(guest_PC_curr_instr + 4), 16210 OFFB_PC)); 16211 else if (trap_code == 6) 16212 stmt (IRStmt_Exit (unop (Iop_Not1, 16213 binop (Iop_CmpLT32U, 16214 getIReg (rs), 16215 getIReg (rt))), 16216 Ijk_SigFPE_IntOvf, 16217 IRConst_U32(guest_PC_curr_instr + 4), 16218 OFFB_PC)); 16219 else 16220 stmt (IRStmt_Exit (unop (Iop_Not1, 16221 binop (Iop_CmpLT32U, 16222 getIReg (rs), 16223 getIReg (rt))), 16224 Ijk_SigTRAP, 16225 IRConst_U32(guest_PC_curr_instr + 4), 16226 OFFB_PC)); 16227 } 16228 break; 16229 } 16230 case 0x32: { /* TLT */ 16231 DIP("tlt r%u, r%u %u", rs, rt, trap_code); 16232 if (mode64) { 16233 if (trap_code == 7) 16234 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16235 getIReg(rt)), Ijk_SigFPE_IntDiv, 16236 IRConst_U64(guest_PC_curr_instr + 4), 16237 OFFB_PC)); 16238 else if (trap_code == 6) 16239 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16240 getIReg(rt)), Ijk_SigFPE_IntOvf, 16241 IRConst_U64(guest_PC_curr_instr + 4), 16242 OFFB_PC)); 16243 else 16244 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16245 getIReg(rt)), Ijk_SigTRAP, 16246 IRConst_U64(guest_PC_curr_instr + 4), 16247 OFFB_PC)); 16248 } else { 16249 if (trap_code == 7) 16250 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16251 getIReg(rt)), Ijk_SigFPE_IntDiv, 16252 IRConst_U32(guest_PC_curr_instr + 4), 16253 OFFB_PC)); 16254 else if (trap_code == 6) 16255 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16256 getIReg(rt)), Ijk_SigFPE_IntOvf, 16257 IRConst_U32(guest_PC_curr_instr + 4), 16258 OFFB_PC)); 16259 else 16260 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16261 getIReg(rt)), Ijk_SigTRAP, 16262 IRConst_U32(guest_PC_curr_instr + 4), 16263 OFFB_PC)); 16264 } 16265 break; 16266 } 16267 case 0x33: { /* TLTU */ 16268 DIP("tltu r%u, r%u %u", rs, rt, trap_code); 16269 if (mode64) { 16270 if (trap_code == 7) 16271 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16272 getIReg(rt)), Ijk_SigFPE_IntDiv, 16273 IRConst_U64(guest_PC_curr_instr + 4), 16274 OFFB_PC)); 16275 else if (trap_code == 6) 16276 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16277 getIReg(rt)), Ijk_SigFPE_IntOvf, 16278 IRConst_U64(guest_PC_curr_instr + 4), 16279 OFFB_PC)); 16280 else 16281 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16282 getIReg(rt)), Ijk_SigTRAP, 16283 IRConst_U64(guest_PC_curr_instr + 4), 16284 OFFB_PC)); 16285 } else { 16286 if (trap_code == 7) 16287 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16288 getIReg(rt)), Ijk_SigFPE_IntDiv, 16289 IRConst_U32(guest_PC_curr_instr + 4), 16290 OFFB_PC)); 16291 else if (trap_code == 6) 16292 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16293 getIReg(rt)), Ijk_SigFPE_IntOvf, 16294 IRConst_U32(guest_PC_curr_instr + 4), 16295 OFFB_PC)); 16296 else 16297 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16298 getIReg (rt)), Ijk_SigTRAP, 16299 IRConst_U32(guest_PC_curr_instr + 4), 16300 OFFB_PC)); 16301 } 16302 break; 16303 } 16304 case 0x34: { /* TEQ */ 16305 DIP("teq r%u, r%u, %u", rs, rt, trap_code); 16306 if (mode64) { 16307 if (trap_code == 7) 16308 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16309 getIReg(rt)), Ijk_SigFPE_IntDiv, 16310 IRConst_U64(guest_PC_curr_instr + 4), 16311 OFFB_PC)); 16312 else if (trap_code == 6) 16313 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16314 getIReg(rt)), Ijk_SigFPE_IntOvf, 16315 IRConst_U64(guest_PC_curr_instr + 4), 16316 OFFB_PC)); 16317 else 16318 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16319 getIReg(rt)), Ijk_SigTRAP, 16320 IRConst_U64(guest_PC_curr_instr + 4), 16321 OFFB_PC)); 16322 } else { 16323 if (trap_code == 7) 16324 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16325 getIReg(rt)), Ijk_SigFPE_IntDiv, 16326 IRConst_U32(guest_PC_curr_instr + 4), 16327 OFFB_PC)); 16328 else if (trap_code == 6) 16329 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16330 getIReg(rt)), Ijk_SigFPE_IntOvf, 16331 IRConst_U32(guest_PC_curr_instr + 4), 16332 OFFB_PC)); 16333 else 16334 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16335 getIReg(rt)), Ijk_SigTRAP, 16336 IRConst_U32(guest_PC_curr_instr + 4), 16337 OFFB_PC)); 16338 } 16339 break; 16340 } 16341 case 0x36: { /* TNE */ 16342 DIP("tne r%u, r%u %u", rs, rt, trap_code); 16343 if (mode64) { 16344 if (trap_code == 7) 16345 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16346 getIReg(rt)), Ijk_SigFPE_IntDiv, 16347 IRConst_U64(guest_PC_curr_instr + 4), 16348 OFFB_PC)); 16349 else if (trap_code == 6) 16350 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16351 getIReg(rt)), Ijk_SigFPE_IntOvf, 16352 IRConst_U64(guest_PC_curr_instr + 4), 16353 OFFB_PC)); 16354 else 16355 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16356 getIReg(rt)), Ijk_SigTRAP, 16357 IRConst_U64(guest_PC_curr_instr + 4), 16358 OFFB_PC)); 16359 } else { 16360 if (trap_code == 7) 16361 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16362 getIReg(rt)), Ijk_SigFPE_IntDiv, 16363 IRConst_U32(guest_PC_curr_instr + 4), 16364 OFFB_PC)); 16365 else if (trap_code == 6) 16366 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16367 getIReg(rt)), Ijk_SigFPE_IntOvf, 16368 IRConst_U32(guest_PC_curr_instr + 4), 16369 OFFB_PC)); 16370 else 16371 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16372 getIReg(rt)), Ijk_SigTRAP, 16373 IRConst_U32(guest_PC_curr_instr + 4), 16374 OFFB_PC)); 16375 } 16376 break; 16377 } 16378 case 0x14: 16379 case 0x16: 16380 case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */ 16381 case 0x38: 16382 case 0x3A: 16383 case 0x3B: /* DSLL, DROTL:DSRL, DSRA */ 16384 case 0x3C: 16385 case 0x3E: 16386 case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */ 16387 if (dis_instr_shrt(cins)) 16388 break; 16389 goto decode_failure; 16390 16391 case 0x0F: /* SYNC */ 16392 DIP("sync 0x%x", sel); 16393 /* Just ignore it. */ 16394 break; 16395 16396 case 0x2C: { /* Doubleword Add - DADD; MIPS64 */ 16397 DIP("dadd r%u, r%u, r%u", rd, rs, rt); 16398 IRTemp tmpRs64 = newTemp(Ity_I64); 16399 IRTemp tmpRt64 = newTemp(Ity_I64); 16400 16401 assign(tmpRs64, getIReg(rs)); 16402 assign(tmpRt64, getIReg(rt)); 16403 16404 t0 = newTemp(Ity_I64); 16405 t1 = newTemp(Ity_I64); 16406 t2 = newTemp(Ity_I64); 16407 t3 = newTemp(Ity_I64); 16408 t4 = newTemp(Ity_I64); 16409 /* dst = src0 + src1 16410 if(sign(src0 ) != sign(src1 )) 16411 goto no overflow; 16412 if(sign(dst) == sign(src0 )) 16413 goto no overflow; 16414 we have overflow! */ 16415 16416 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64))); 16417 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64))); 16418 assign(t2, unop(Iop_1Uto64, 16419 binop(Iop_CmpEQ64, 16420 binop(Iop_And64, mkexpr(t1), 16421 mkU64(0x8000000000000000ULL)), 16422 mkU64(0x8000000000000000ULL)))); 16423 16424 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16425 assign(t4, unop(Iop_1Uto64, 16426 binop(Iop_CmpNE64, 16427 binop(Iop_And64, mkexpr(t3), 16428 mkU64(0x8000000000000000ULL)), 16429 mkU64(0x8000000000000000ULL)))); 16430 16431 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, 16432 binop(Iop_Or64, mkexpr(t2), mkexpr(t4)), 16433 mkU64(0)), 16434 Ijk_SigFPE_IntOvf, 16435 IRConst_U64(guest_PC_curr_instr + 4), 16436 OFFB_PC)); 16437 16438 putIReg(rd, mkexpr(t0)); 16439 break; 16440 } 16441 16442 case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */ 16443 DIP("daddu r%u, r%u, r%u", rd, rs, rt); 16444 ALU_PATTERN(Iop_Add64); 16445 break; 16446 16447 case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */ 16448 DIP("dsub r%u, r%u, r%u", rd, rs, rt); 16449 IRTemp tmpRs64 = newTemp(Ity_I64); 16450 IRTemp tmpRt64 = newTemp(Ity_I64); 16451 16452 assign(tmpRs64, getIReg(rs)); 16453 assign(tmpRt64, getIReg(rt)); 16454 t0 = newTemp(Ity_I64); 16455 t1 = newTemp(Ity_I64); 16456 t2 = newTemp(Ity_I64); 16457 t3 = newTemp(Ity_I64); 16458 t4 = newTemp(Ity_I64); 16459 t5 = newTemp(Ity_I64); 16460 /* dst = src0 + (-1 * src1) 16461 if(sign(src0 ) != sign((-1 * src1) )) 16462 goto no overflow; 16463 if(sign(dst) == sign(src0 )) 16464 goto no overflow; 16465 we have overflow! */ 16466 16467 assign(t5, binop(Iop_Mul64, 16468 mkexpr(tmpRt64), 16469 mkU64(0xffffffffffffffffULL))); 16470 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5))); 16471 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5))); 16472 assign(t2, unop(Iop_1Sto64, 16473 binop(Iop_CmpEQ64, 16474 binop(Iop_And64, 16475 mkexpr(t1), 16476 mkU64(0x8000000000000000ULL)), 16477 mkU64(0x8000000000000000ULL)))); 16478 16479 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16480 assign(t4, unop(Iop_1Sto64, 16481 binop(Iop_CmpNE64, 16482 binop(Iop_And64, 16483 mkexpr(t3), 16484 mkU64(0x8000000000000000ULL)), 16485 mkU64(0x8000000000000000ULL)))); 16486 16487 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2), 16488 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf, 16489 IRConst_U64(guest_PC_curr_instr + 4), 16490 OFFB_PC)); 16491 16492 putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt))); 16493 break; 16494 } 16495 16496 case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */ 16497 DIP("dsub r%u, r%u,r%u", rd, rt, rt); 16498 ALU_PATTERN(Iop_Sub64); 16499 break; 16500 16501 default: 16502 goto decode_failure; 16503 } 16504 break; 16505 16506 case 0x01: /* Regimm */ 16507 16508 switch (rt) { 16509 case 0x00: /* BLTZ */ 16510 DIP("bltz r%u, %u", rs, imm); 16511 if (mode64) { 16512 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16513 callback_opaque, &bstmt)) 16514 goto decode_failure; 16515 } else 16516 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16517 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 16518 break; 16519 16520 case 0x01: /* BGEZ */ 16521 DIP("bgez r%u, %u", rs, imm); 16522 if (mode64) { 16523 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16524 callback_opaque, &bstmt)) 16525 goto decode_failure; 16526 } else 16527 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16528 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 16529 break; 16530 16531 case 0x02: /* BLTZL */ 16532 DIP("bltzl r%u, %u", rs, imm); 16533 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16534 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16535 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16536 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16537 imm); 16538 break; 16539 16540 case 0x03: /* BGEZL */ 16541 DIP("bgezl r%u, %u", rs, imm); 16542 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16543 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16544 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16545 mode64 ? mkU64(0x0) : mkU32(0x0)), imm); 16546 break; 16547 16548 case 0x10: /* BLTZAL */ 16549 DIP("bltzal r%u, %u", rs, imm); 16550 if (mode64) { 16551 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16552 callback_opaque, &bstmt)) 16553 goto decode_failure; 16554 } else 16555 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16556 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 16557 break; 16558 16559 case 0x12: /* BLTZALL */ 16560 DIP("bltzall r%u, %u", rs, imm); 16561 putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) : 16562 mkU32(guest_PC_curr_instr + 8)); 16563 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16564 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16565 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16566 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16567 imm); 16568 break; 16569 16570 case 0x11: /* BGEZAL */ 16571 DIP("bgezal r%u, %u", rs, imm); 16572 if (mode64) { 16573 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16574 callback_opaque, &bstmt)) 16575 goto decode_failure; 16576 } else 16577 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16578 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 16579 break; 16580 16581 case 0x13: /* BGEZALL */ 16582 DIP("bgezall r%u, %u", rs, imm); 16583 if (mode64) { 16584 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 16585 lastn = dis_branch_likely(binop(Iop_CmpNE64, 16586 binop(Iop_And64, 16587 getIReg(rs), 16588 mkU64(0x8000000000000000ULL)), 16589 mkU64(0x0)), 16590 imm); 16591 } else { 16592 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 16593 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 16594 getIReg(rs), mkU32(0x80000000)), 16595 mkU32(0x0)), imm); 16596 } 16597 break; 16598 16599 case 0x08: /* TGEI */ 16600 DIP("tgei r%u, %u %u", rs, imm, trap_code); 16601 if (mode64) { 16602 stmt (IRStmt_Exit (unop (Iop_Not1, 16603 binop (Iop_CmpLT64S, 16604 getIReg (rs), 16605 mkU64 (extend_s_16to64 (imm)))), 16606 Ijk_SigTRAP, 16607 IRConst_U64(guest_PC_curr_instr + 4), 16608 OFFB_PC)); 16609 } else { 16610 stmt (IRStmt_Exit (unop (Iop_Not1, 16611 binop (Iop_CmpLT32S, 16612 getIReg (rs), 16613 mkU32 (extend_s_16to32 (imm)))), 16614 Ijk_SigTRAP, 16615 IRConst_U32(guest_PC_curr_instr + 4), 16616 OFFB_PC)); 16617 } 16618 break; 16619 16620 case 0x09: { /* TGEIU */ 16621 DIP("tgeiu r%u, %u %u", rs, imm, trap_code); 16622 if (mode64) { 16623 stmt (IRStmt_Exit (unop (Iop_Not1, 16624 binop (Iop_CmpLT64U, 16625 getIReg (rs), 16626 mkU64 (extend_s_16to64 (imm)))), 16627 Ijk_SigTRAP, 16628 IRConst_U64(guest_PC_curr_instr + 4), 16629 OFFB_PC)); 16630 } else { 16631 stmt (IRStmt_Exit (unop (Iop_Not1, 16632 binop (Iop_CmpLT32U, 16633 getIReg (rs), 16634 mkU32 (extend_s_16to32 (imm)))), 16635 Ijk_SigTRAP, 16636 IRConst_U32(guest_PC_curr_instr + 4), 16637 OFFB_PC)); 16638 } 16639 break; 16640 } 16641 case 0x0A: { /* TLTI */ 16642 DIP("tlti r%u, %u %u", rs, imm, trap_code); 16643 if (mode64) { 16644 stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs), 16645 mkU64 (extend_s_16to64 (imm))), 16646 Ijk_SigTRAP, 16647 IRConst_U64(guest_PC_curr_instr + 4), 16648 OFFB_PC)); 16649 } else { 16650 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), 16651 mkU32 (extend_s_16to32 (imm))), 16652 Ijk_SigTRAP, 16653 IRConst_U32(guest_PC_curr_instr + 4), 16654 OFFB_PC)); 16655 } 16656 break; 16657 } 16658 case 0x0B: { /* TLTIU */ 16659 DIP("tltiu r%u, %u %u", rs, imm, trap_code); 16660 if (mode64) { 16661 stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs), 16662 mkU64 (extend_s_16to64 (imm))), 16663 Ijk_SigTRAP, 16664 IRConst_U64(guest_PC_curr_instr + 4), 16665 OFFB_PC)); 16666 } else { 16667 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), 16668 mkU32 (extend_s_16to32 (imm))), 16669 Ijk_SigTRAP, 16670 IRConst_U32(guest_PC_curr_instr + 4), 16671 OFFB_PC)); 16672 } 16673 break; 16674 } 16675 case 0x0C: { /* TEQI */ 16676 DIP("teqi r%u, %u %u", rs, imm, trap_code); 16677 if (mode64) { 16678 stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs), 16679 mkU64 (extend_s_16to64 (imm))), 16680 Ijk_SigTRAP, 16681 IRConst_U64(guest_PC_curr_instr + 4), 16682 OFFB_PC)); 16683 } else { 16684 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), 16685 mkU32 (extend_s_16to32 (imm))), 16686 Ijk_SigTRAP, 16687 IRConst_U32(guest_PC_curr_instr + 4), 16688 OFFB_PC)); 16689 } 16690 break; 16691 } 16692 case 0x0E: { /* TNEI */ 16693 DIP("tnei r%u, %u %u", rs, imm, trap_code); 16694 if (mode64) { 16695 stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs), 16696 mkU64 (extend_s_16to64 (imm))), 16697 Ijk_SigTRAP, 16698 IRConst_U64(guest_PC_curr_instr + 4), 16699 OFFB_PC)); 16700 } else { 16701 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), 16702 mkU32 (extend_s_16to32 (imm))), 16703 Ijk_SigTRAP, 16704 IRConst_U32(guest_PC_curr_instr + 4), 16705 OFFB_PC)); 16706 } 16707 break; 16708 } 16709 case 0x1C: { /* BPOSGE32 */ 16710 DIP("bposge32 %u", imm); 16711 vassert(!mode64); 16712 t0 = newTemp(Ity_I32); 16713 /* Get pos field from DSPControl register. */ 16714 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 16715 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0), 16716 mkU32(32))), imm, &bstmt); 16717 } 16718 case 0x1F: 16719 /* SYNCI */ 16720 /* Just ignore it */ 16721 break; 16722 16723 default: 16724 goto decode_failure; 16725 } 16726 break; 16727 16728 case 0x04: 16729 DIP("beq r%u, r%u, %u", rs, rt, imm); 16730 if (mode64) 16731 dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)), 16732 imm, &bstmt); 16733 else 16734 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), 16735 imm, &bstmt); 16736 break; 16737 16738 case 0x14: 16739 DIP("beql r%u, r%u, %u", rs, rt, imm); 16740 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16741 getIReg(rs), getIReg(rt)), imm); 16742 break; 16743 16744 case 0x05: 16745 DIP("bne r%u, r%u, %u", rs, rt, imm); 16746 if (mode64) 16747 dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)), 16748 imm, &bstmt); 16749 else 16750 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)), 16751 imm, &bstmt); 16752 break; 16753 16754 case 0x15: 16755 DIP("bnel r%u, r%u, %u", rs, rt, imm); 16756 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32, 16757 getIReg(rs), getIReg(rt)), imm); 16758 break; 16759 16760 case 0x07: /* BGTZ */ 16761 DIP("bgtz r%u, %u", rs, imm); 16762 if (mode64) 16763 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs), 16764 mkU64(0x00))), imm, &bstmt); 16765 else 16766 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs), 16767 mkU32(0x00))), imm, &bstmt); 16768 break; 16769 16770 case 0x17: /* BGTZL */ 16771 DIP("bgtzl r%u, %u", rs, imm); 16772 if (mode64) 16773 lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs), 16774 mkU64(0x00)), imm); 16775 else 16776 lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), 16777 mkU32(0x00)), imm); 16778 break; 16779 16780 case 0x06: /* BLEZ */ 16781 DIP("blez r%u, %u", rs, imm); 16782 if (mode64) 16783 dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)), 16784 imm, &bstmt); 16785 else 16786 dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm, 16787 &bstmt); 16788 break; 16789 16790 case 0x16: /* BLEZL */ 16791 DIP("blezl r%u, %u", rs, imm); 16792 lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S : 16793 Iop_CmpLE32S, getIReg(rs), mode64 ? 16794 mkU64(0x0) : mkU32(0x0)))), imm); 16795 break; 16796 16797 case 0x08: { /* ADDI */ 16798 DIP("addi r%u, r%u, %u", rt, rs, imm); 16799 IRTemp tmpRs32 = newTemp(Ity_I32); 16800 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 16801 16802 t0 = newTemp(Ity_I32); 16803 t1 = newTemp(Ity_I32); 16804 t2 = newTemp(Ity_I32); 16805 t3 = newTemp(Ity_I32); 16806 t4 = newTemp(Ity_I32); 16807 /* dst = src0 + sign(imm) 16808 if(sign(src0 ) != sign(imm )) 16809 goto no overflow; 16810 if(sign(dst) == sign(src0 )) 16811 goto no overflow; 16812 we have overflow! */ 16813 16814 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), 16815 mkU32(extend_s_16to32(imm)))); 16816 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), 16817 mkU32(extend_s_16to32(imm)))); 16818 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32, 16819 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000)))); 16820 16821 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 16822 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32, 16823 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000)))); 16824 16825 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2), 16826 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf, 16827 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 16828 IRConst_U32(guest_PC_curr_instr + 4), 16829 OFFB_PC)); 16830 16831 putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True)); 16832 break; 16833 } 16834 case 0x09: /* ADDIU */ 16835 DIP("addiu r%u, r%u, %u", rt, rs, imm); 16836 if (mode64) { 16837 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32, 16838 mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))), 16839 True)); 16840 } else 16841 putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm)))); 16842 break; 16843 16844 case 0x0C: /* ANDI */ 16845 DIP("andi r%u, r%u, %u", rt, rs, imm); 16846 if (mode64) { 16847 ALUI_PATTERN64(Iop_And64); 16848 } else { 16849 ALUI_PATTERN(Iop_And32); 16850 } 16851 break; 16852 16853 case 0x0E: /* XORI */ 16854 DIP("xori r%u, r%u, %u", rt, rs, imm); 16855 if (mode64) { 16856 ALUI_PATTERN64(Iop_Xor64); 16857 } else { 16858 ALUI_PATTERN(Iop_Xor32); 16859 } 16860 break; 16861 16862 case 0x0D: /* ORI */ 16863 DIP("ori r%u, r%u, %u", rt, rs, imm); 16864 if (mode64) { 16865 ALUI_PATTERN64(Iop_Or64); 16866 } else { 16867 ALUI_PATTERN(Iop_Or32); 16868 } 16869 break; 16870 16871 case 0x0A: /* SLTI */ 16872 DIP("slti r%u, r%u, %u", rt, rs, imm); 16873 if (mode64) 16874 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs), 16875 mkU64(extend_s_16to64(imm))))); 16876 else 16877 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 16878 mkU32(extend_s_16to32(imm))))); 16879 break; 16880 16881 case 0x0B: /* SLTIU */ 16882 DIP("sltiu r%u, r%u, %u", rt, rs, imm); 16883 if (mode64) 16884 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs), 16885 mkU64(extend_s_16to64(imm))))); 16886 else 16887 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 16888 mkU32(extend_s_16to32(imm))))); 16889 break; 16890 16891 case 0x18: { /* Doubleword Add Immidiate - DADD; MIPS64 */ 16892 DIP("daddi r%u, r%u, %u", rt, rs, imm); 16893 IRTemp tmpRs64 = newTemp(Ity_I64); 16894 assign(tmpRs64, getIReg(rs)); 16895 16896 t0 = newTemp(Ity_I64); 16897 t1 = newTemp(Ity_I64); 16898 t2 = newTemp(Ity_I64); 16899 t3 = newTemp(Ity_I64); 16900 t4 = newTemp(Ity_I64); 16901 /* dst = src0 + sign(imm) 16902 if(sign(src0 ) != sign(imm )) 16903 goto no overflow; 16904 if(sign(dst) == sign(src0 )) 16905 goto no overflow; 16906 we have overflow! */ 16907 16908 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), 16909 mkU64(extend_s_16to64(imm)))); 16910 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), 16911 mkU64(extend_s_16to64(imm)))); 16912 assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64, 16913 mkexpr(t1), mkU64(0x8000000000000000ULL)), 16914 mkU64(0x8000000000000000ULL)))); 16915 16916 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16917 assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64, 16918 mkexpr(t3), mkU64(0x8000000000000000ULL)), 16919 mkU64(0x8000000000000000ULL)))); 16920 16921 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2), 16922 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf, 16923 IRConst_U64(guest_PC_curr_instr + 4), 16924 OFFB_PC)); 16925 16926 putIReg(rt, mkexpr(t0)); 16927 break; 16928 } 16929 16930 case 0x19: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */ 16931 DIP("daddiu r%u, r%u, %u", rt, rs, imm); 16932 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16933 break; 16934 16935 case 0x1A: { 16936 /* Load Doubleword Left - LDL; MIPS64 */ 16937 vassert(mode64); 16938 DIP("ldl r%u, %u(r%u)", rt, imm, rs); 16939 /* t1 = addr */ 16940 #if defined (_MIPSEL) 16941 t1 = newTemp(Ity_I64); 16942 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16943 #elif defined (_MIPSEB) 16944 t1 = newTemp(Ity_I64); 16945 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs), 16946 mkU64(extend_s_16to64(imm))))); 16947 #endif 16948 /* t2 = word addr */ 16949 /* t4 = addr mod 8 */ 16950 LWX_SWX_PATTERN64_1; 16951 16952 /* t3 = word content - shifted */ 16953 t3 = newTemp(Ity_I64); 16954 assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)), 16955 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07), 16956 mkexpr(t4)), mkU8(3))))); 16957 16958 /* rt content - adjusted */ 16959 t5 = newTemp(Ity_I64); 16960 t6 = newTemp(Ity_I64); 16961 t7 = newTemp(Ity_I64); 16962 16963 assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8))); 16964 16965 assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL), 16966 narrowTo(Ity_I8, mkexpr(t5)))); 16967 16968 assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6))); 16969 16970 putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3))); 16971 break; 16972 } 16973 16974 case 0x1B: { 16975 /* Load Doubleword Right - LDR; MIPS64 */ 16976 vassert(mode64); 16977 DIP("ldr r%u,%u(r%u)", rt, imm, rs); 16978 /* t1 = addr */ 16979 #if defined (_MIPSEL) 16980 t1 = newTemp(Ity_I64); 16981 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16982 #elif defined (_MIPSEB) 16983 t1 = newTemp(Ity_I64); 16984 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs), 16985 mkU64(extend_s_16to64(imm))))); 16986 #endif 16987 /* t2 = word addr */ 16988 /* t4 = addr mod 8 */ 16989 LWX_SWX_PATTERN64_1; 16990 16991 /* t3 = word content - shifted */ 16992 t3 = newTemp(Ity_I64); 16993 assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)), 16994 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3))))); 16995 16996 /* rt content - adjusted */ 16997 t5 = newTemp(Ity_I64); 16998 assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64, 16999 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL), 17000 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3))))))); 17001 17002 putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3))); 17003 break; 17004 } 17005 17006 case 0x27: /* Load Word unsigned - LWU; MIPS64 */ 17007 DIP("lwu r%u,%u(r%u)", rt, imm, rs); 17008 LOAD_STORE_PATTERN; 17009 17010 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False)); 17011 break; 17012 17013 case 0x30: /* LL / LWC0 */ 17014 DIP("ll r%u, %u(r%u)", rt, imm, rs); 17015 LOAD_STORE_PATTERN; 17016 17017 t2 = newTemp(Ity_I32); 17018 #if defined (_MIPSEL) 17019 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ )); 17020 #elif defined (_MIPSEB) 17021 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ )); 17022 #endif 17023 if (mode64) 17024 putIReg(rt, unop(Iop_32Sto64, mkexpr(t2))); 17025 else 17026 putIReg(rt, mkexpr(t2)); 17027 break; 17028 17029 case 0x34: /* Load Linked Doubleword - LLD; MIPS64 */ 17030 DIP("lld r%u, %u(r%u)", rt, imm, rs); 17031 LOAD_STORE_PATTERN; 17032 17033 t2 = newTemp(Ity_I64); 17034 #if defined (_MIPSEL) 17035 stmt(IRStmt_LLSC 17036 (Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ )); 17037 #elif defined (_MIPSEB) 17038 stmt(IRStmt_LLSC 17039 (Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ )); 17040 #endif 17041 17042 putIReg(rt, mkexpr(t2)); 17043 break; 17044 17045 case 0x38: /* SC / SWC0 */ 17046 DIP("sc r%u, %u(r%u)", rt, imm, rs); 17047 LOAD_STORE_PATTERN; 17048 17049 t2 = newTemp(Ity_I1); 17050 #if defined (_MIPSEL) 17051 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)))); 17052 #elif defined (_MIPSEB) 17053 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt)))); 17054 #endif 17055 17056 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2))); 17057 break; 17058 17059 case 0x3C: /* Store Conditional Doubleword - SCD; MIPS64 */ 17060 DIP("sdc r%u, %u(r%u)", rt, imm, rs); 17061 LOAD_STORE_PATTERN; 17062 17063 t2 = newTemp(Ity_I1); 17064 #if defined (_MIPSEL) 17065 stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), getIReg(rt))); 17066 #elif defined (_MIPSEB) 17067 stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), getIReg(rt))); 17068 #endif 17069 17070 putIReg(rt, unop(Iop_1Uto64, mkexpr(t2))); 17071 break; 17072 17073 case 0x37: /* Load Doubleword - LD; MIPS64 */ 17074 DIP("ld r%u, %u(r%u)", rt, imm, rs); 17075 LOAD_STORE_PATTERN; 17076 putIReg(rt, load(Ity_I64, mkexpr(t1))); 17077 break; 17078 17079 case 0x3F: /* Store Doubleword - SD; MIPS64 */ 17080 DIP("sd r%u, %u(r%u)", rt, imm, rs); 17081 LOAD_STORE_PATTERN; 17082 store(mkexpr(t1), getIReg(rt)); 17083 break; 17084 17085 case 0x32: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */ 17086 /* Cavium Specific instructions. */ 17087 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17088 DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm); 17089 t0 = newTemp(Ity_I32); 17090 t1 = newTemp(Ity_I32); 17091 assign(t0, mkU32(0x1)); 17092 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt))); 17093 dis_branch(False, binop(Iop_CmpEQ32, 17094 binop(Iop_And32, 17095 mkexpr(t1), 17096 mkNarrowTo32(ty, getIReg(rs))), 17097 mkU32(0x0)), 17098 imm, &bstmt); 17099 break; 17100 } else { 17101 goto decode_failure; 17102 } 17103 17104 case 0x36: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */ 17105 /* Cavium Specific instructions. */ 17106 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17107 DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm); 17108 t0 = newTemp(Ity_I64); 17109 t1 = newTemp(Ity_I8); /* Shift. */ 17110 t2 = newTemp(Ity_I64); 17111 assign(t0, mkU64(0x1)); 17112 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32))); 17113 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1))); 17114 dis_branch(False, binop(Iop_CmpEQ64, 17115 binop(Iop_And64, 17116 mkexpr(t2), 17117 getIReg(rs)), 17118 mkU64(0x0)), 17119 imm, &bstmt); 17120 break; 17121 } else { 17122 goto decode_failure; 17123 } 17124 17125 case 0x3A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */ 17126 /* Cavium Specific instructions. */ 17127 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17128 DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm); 17129 t0 = newTemp(Ity_I32); 17130 t1 = newTemp(Ity_I32); 17131 assign(t0, mkU32(0x1)); 17132 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt))); 17133 dis_branch(False, binop(Iop_CmpNE32, 17134 binop(Iop_And32, 17135 mkexpr(t1), 17136 mkNarrowTo32(ty, getIReg(rs))), 17137 mkU32(0x0)), 17138 imm, &bstmt); 17139 break; 17140 } else { 17141 goto decode_failure; 17142 } 17143 17144 case 0x3E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */ 17145 /* Cavium Specific instructions. */ 17146 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17147 DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm); 17148 t0 = newTemp(Ity_I64); 17149 t1 = newTemp(Ity_I8); /* Shift. */ 17150 t2 = newTemp(Ity_I64); 17151 assign(t0, mkU64(0x1)); 17152 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32))); 17153 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1))); 17154 dis_branch(False, binop(Iop_CmpNE64, 17155 binop(Iop_And64, 17156 mkexpr(t2), 17157 getIReg(rs)), 17158 mkU64(0x0)), 17159 imm, &bstmt); 17160 break; 17161 } else { 17162 goto decode_failure; 17163 } 17164 17165 default: 17166 goto decode_failure; 17167 17168 decode_failure_dsp: 17169 vex_printf("Error occured while trying to decode MIPS32 DSP " 17170 "instruction.\nYour platform probably doesn't support " 17171 "MIPS32 DSP ASE.\n"); 17172 decode_failure: 17173 /* All decode failures end up here. */ 17174 if (sigill_diag) 17175 vex_printf("vex mips->IR: unhandled instruction bytes: " 17176 "0x%x 0x%x 0x%x 0x%x\n", 17177 (UInt) getIByte(delta_start + 0), 17178 (UInt) getIByte(delta_start + 1), 17179 (UInt) getIByte(delta_start + 2), 17180 (UInt) getIByte(delta_start + 3)); 17181 17182 /* Tell the dispatcher that this insn cannot be decoded, and so has 17183 not been executed, and (is currently) the next to be executed. 17184 EIP should be up-to-date since it made so at the start bnezof each 17185 insn, but nevertheless be paranoid and update it again right 17186 now. */ 17187 if (mode64) { 17188 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC), 17189 mkU64(guest_PC_curr_instr))); 17190 jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr); 17191 } else { 17192 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC), 17193 mkU32(guest_PC_curr_instr))); 17194 jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr); 17195 } 17196 dres.whatNext = Dis_StopHere; 17197 dres.len = 0; 17198 return dres; 17199 } /* switch (opc) for the main (primary) opcode switch. */ 17200 17201 /* All MIPS insn have 4 bytes */ 17202 17203 if (delay_slot_branch) { 17204 delay_slot_branch = False; 17205 stmt(bstmt); 17206 bstmt = NULL; 17207 if (mode64) 17208 putPC(mkU64(guest_PC_curr_instr + 4)); 17209 else 17210 putPC(mkU32(guest_PC_curr_instr + 4)); 17211 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 17212 Ijk_Call : Ijk_Boring; 17213 } 17214 17215 if (likely_delay_slot) { 17216 dres.jk_StopHere = Ijk_Boring; 17217 dres.whatNext = Dis_StopHere; 17218 putPC(lastn); 17219 lastn = NULL; 17220 } 17221 if (delay_slot_jump) { 17222 putPC(lastn); 17223 lastn = NULL; 17224 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 17225 Ijk_Call : Ijk_Boring; 17226 } 17227 17228 decode_success: 17229 /* All decode successes end up here. */ 17230 switch (dres.whatNext) { 17231 case Dis_Continue: 17232 if (mode64) 17233 putPC(mkU64(guest_PC_curr_instr + 4)); 17234 else 17235 putPC(mkU32(guest_PC_curr_instr + 4)); 17236 break; 17237 case Dis_ResteerU: 17238 case Dis_ResteerC: 17239 putPC(mkU32(dres.continueAt)); 17240 break; 17241 case Dis_StopHere: 17242 break; 17243 default: 17244 vassert(0); 17245 break; 17246 } 17247 17248 /* On MIPS we need to check if the last instruction in block is branch or 17249 jump. */ 17250 if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4) 17251 && (dres.whatNext != Dis_StopHere)) 17252 if (branch_or_jump(guest_code + delta + 4)) { 17253 dres.whatNext = Dis_StopHere; 17254 dres.jk_StopHere = Ijk_Boring; 17255 if (mode64) 17256 putPC(mkU64(guest_PC_curr_instr + 4)); 17257 else 17258 putPC(mkU32(guest_PC_curr_instr + 4)); 17259 } 17260 dres.len = 4; 17261 17262 DIP("\n"); 17263 17264 return dres; 17265 17266 } 17267 17268 /*------------------------------------------------------------*/ 17269 /*--- Top-level fn ---*/ 17270 /*------------------------------------------------------------*/ 17271 17272 /* Disassemble a single instruction into IR. The instruction 17273 is located in host memory at &guest_code[delta]. */ 17274 DisResult disInstr_MIPS( IRSB* irsb_IN, 17275 Bool (*resteerOkFn) ( void *, Addr ), 17276 Bool resteerCisOk, 17277 void* callback_opaque, 17278 const UChar* guest_code_IN, 17279 Long delta, 17280 Addr guest_IP, 17281 VexArch guest_arch, 17282 const VexArchInfo* archinfo, 17283 const VexAbiInfo* abiinfo, 17284 VexEndness host_endness_IN, 17285 Bool sigill_diag_IN ) 17286 { 17287 DisResult dres; 17288 /* Set globals (see top of this file) */ 17289 vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64); 17290 17291 mode64 = guest_arch != VexArchMIPS32; 17292 #if (__mips_fpr==64) 17293 fp_mode64 = ((VEX_MIPS_REV(archinfo->hwcaps) == VEX_PRID_CPU_32FPR) 17294 || guest_arch == VexArchMIPS64); 17295 #endif 17296 17297 guest_code = guest_code_IN; 17298 irsb = irsb_IN; 17299 host_endness = host_endness_IN; 17300 #if defined(VGP_mips32_linux) 17301 guest_PC_curr_instr = (Addr32)guest_IP; 17302 #elif defined(VGP_mips64_linux) 17303 guest_PC_curr_instr = (Addr64)guest_IP; 17304 #endif 17305 17306 dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque, 17307 delta, archinfo, abiinfo, sigill_diag_IN); 17308 17309 return dres; 17310 } 17311 17312 /*--------------------------------------------------------------------*/ 17313 /*--- end guest_mips_toIR.c ---*/ 17314 /*--------------------------------------------------------------------*/ 17315