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-2017 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 #define LLADDR_INVALID \ 553 (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF)) 554 555 /*------------------------------------------------------------*/ 556 /*--- Field helpers ---*/ 557 /*------------------------------------------------------------*/ 558 559 static UInt get_opcode(UInt mipsins) 560 { 561 return (0xFC000000 & mipsins) >> 26; 562 } 563 564 static UInt get_rs(UInt mipsins) 565 { 566 return (0x03E00000 & mipsins) >> 21; 567 } 568 569 static UInt get_rt(UInt mipsins) 570 { 571 return (0x001F0000 & mipsins) >> 16; 572 } 573 574 static UInt get_imm(UInt mipsins) 575 { 576 return (0x0000FFFF & mipsins); 577 } 578 579 static UInt get_instr_index(UInt mipsins) 580 { 581 return (0x03FFFFFF & mipsins); 582 } 583 584 static UInt get_rd(UInt mipsins) 585 { 586 return (0x0000F800 & mipsins) >> 11; 587 } 588 589 static UInt get_sa(UInt mipsins) 590 { 591 return (0x000007C0 & mipsins) >> 6; 592 } 593 594 static UInt get_function(UInt mipsins) 595 { 596 return (0x0000003F & mipsins); 597 } 598 599 static UInt get_ft(UInt mipsins) 600 { 601 return (0x001F0000 & mipsins) >> 16; 602 } 603 604 static UInt get_fs(UInt mipsins) 605 { 606 return (0x0000F800 & mipsins) >> 11; 607 } 608 609 static UInt get_fd(UInt mipsins) 610 { 611 return (0x000007C0 & mipsins) >> 6; 612 } 613 614 static UInt get_mov_cc(UInt mipsins) 615 { 616 return (0x001C0000 & mipsins) >> 18; 617 } 618 619 static UInt get_bc1_cc(UInt mipsins) 620 { 621 return (0x001C0000 & mipsins) >> 18; 622 } 623 624 static UInt get_fpc_cc(UInt mipsins) 625 { 626 return (0x00000700 & mipsins) >> 8; 627 } 628 629 static UInt get_tf(UInt mipsins) 630 { 631 return (0x00010000 & mipsins) >> 16; 632 } 633 634 static UInt get_nd(UInt mipsins) 635 { 636 return (0x00020000 & mipsins) >> 17; 637 } 638 639 static UInt get_fmt(UInt mipsins) 640 { 641 return (0x03E00000 & mipsins) >> 21; 642 } 643 644 static UInt get_FC(UInt mipsins) 645 { 646 return (0x000000F0 & mipsins) >> 4; 647 } 648 649 static UInt get_cond(UInt mipsins) 650 { 651 return (0x0000000F & mipsins); 652 } 653 654 /* for break & syscall */ 655 static UInt get_code(UInt mipsins) 656 { 657 return (0xFFC0 & mipsins) >> 6; 658 } 659 660 static UInt get_lsb(UInt mipsins) 661 { 662 return (0x7C0 & mipsins) >> 6; 663 } 664 665 static UInt get_msb(UInt mipsins) 666 { 667 return (0x0000F800 & mipsins) >> 11; 668 } 669 670 static UInt get_rot(UInt mipsins) 671 { 672 return (0x00200000 & mipsins) >> 21; 673 } 674 675 static UInt get_rotv(UInt mipsins) 676 { 677 return (0x00000040 & mipsins) >> 6; 678 } 679 680 static UInt get_sel(UInt mipsins) 681 { 682 return (0x00000007 & mipsins); 683 } 684 685 /* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them, 686 except for MFHI and MFLO. */ 687 static UInt get_acNo(UInt mipsins) 688 { 689 return (0x00001800 & mipsins) >> 11; 690 } 691 692 /* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */ 693 static UInt get_acNo_mfhilo(UInt mipsins) 694 { 695 return (0x00600000 & mipsins) >> 21; 696 } 697 698 /* Get mask field (helper function for wrdsp instruction). */ 699 static UInt get_wrdspMask(UInt mipsins) 700 { 701 return (0x001ff800 & mipsins) >> 11; 702 } 703 704 /* Get mask field (helper function for rddsp instruction). */ 705 static UInt get_rddspMask(UInt mipsins) 706 { 707 return (0x03ff0000 & mipsins) >> 16; 708 } 709 710 /* Get shift field (helper function for DSP ASE instructions). */ 711 static UInt get_shift(UInt mipsins) 712 { 713 return (0x03f00000 & mipsins) >> 20; 714 } 715 716 /* Get immediate field for DSP ASE instructions. */ 717 static UInt get_dspImm(UInt mipsins) 718 { 719 return (0x03ff0000 & mipsins) >> 16; 720 } 721 722 static Bool branch_or_jump(const UChar * addr) 723 { 724 UInt fmt; 725 UInt cins = getUInt(addr); 726 727 UInt opcode = get_opcode(cins); 728 UInt rt = get_rt(cins); 729 UInt function = get_function(cins); 730 731 /* bgtz, blez, bne, beq, jal */ 732 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04 733 || opcode == 0x03 || opcode == 0x02) { 734 return True; 735 } 736 737 /* bgez */ 738 if (opcode == 0x01 && rt == 0x01) { 739 return True; 740 } 741 742 /* bgezal */ 743 if (opcode == 0x01 && rt == 0x11) { 744 return True; 745 } 746 747 /* bltzal */ 748 if (opcode == 0x01 && rt == 0x10) { 749 return True; 750 } 751 752 /* bltz */ 753 if (opcode == 0x01 && rt == 0x00) { 754 return True; 755 } 756 757 /* jalr */ 758 if (opcode == 0x00 && function == 0x09) { 759 return True; 760 } 761 762 /* jr */ 763 if (opcode == 0x00 && function == 0x08) { 764 return True; 765 } 766 767 if (opcode == 0x11) { 768 /*bc1f & bc1t */ 769 fmt = get_fmt(cins); 770 if (fmt == 0x08) { 771 return True; 772 } 773 } 774 775 /* bposge32 */ 776 if (opcode == 0x01 && rt == 0x1c) { 777 return True; 778 } 779 780 /* Cavium Specific instructions. */ 781 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) { 782 /* BBIT0, BBIT1, BBIT032, BBIT132 */ 783 return True; 784 } 785 786 return False; 787 } 788 789 static Bool is_Branch_or_Jump_and_Link(const UChar * addr) 790 { 791 UInt cins = getUInt(addr); 792 793 UInt opcode = get_opcode(cins); 794 UInt rt = get_rt(cins); 795 UInt function = get_function(cins); 796 797 /* jal */ 798 if (opcode == 0x02) { 799 return True; 800 } 801 802 /* bgezal */ 803 if (opcode == 0x01 && rt == 0x11) { 804 return True; 805 } 806 807 /* bltzal */ 808 if (opcode == 0x01 && rt == 0x10) { 809 return True; 810 } 811 812 /* jalr */ 813 if (opcode == 0x00 && function == 0x09) { 814 return True; 815 } 816 817 return False; 818 } 819 820 static Bool branch_or_link_likely(const UChar * addr) 821 { 822 UInt cins = getUInt(addr); 823 UInt opcode = get_opcode(cins); 824 UInt rt = get_rt(cins); 825 826 /* bgtzl, blezl, bnel, beql */ 827 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14) 828 return True; 829 830 /* bgezl */ 831 if (opcode == 0x01 && rt == 0x03) 832 return True; 833 834 /* bgezall */ 835 if (opcode == 0x01 && rt == 0x13) 836 return True; 837 838 /* bltzall */ 839 if (opcode == 0x01 && rt == 0x12) 840 return True; 841 842 /* bltzl */ 843 if (opcode == 0x01 && rt == 0x02) 844 return True; 845 846 return False; 847 } 848 849 /*------------------------------------------------------------*/ 850 /*--- Helper bits and pieces for creating IR fragments. ---*/ 851 /*------------------------------------------------------------*/ 852 853 static IRExpr *mkU8(UInt i) 854 { 855 vassert(i < 256); 856 return IRExpr_Const(IRConst_U8((UChar) i)); 857 } 858 859 /* Create an expression node for a 16-bit integer constant. */ 860 static IRExpr *mkU16(UInt i) 861 { 862 return IRExpr_Const(IRConst_U16(i)); 863 } 864 865 /* Create an expression node for a 32-bit integer constant. */ 866 static IRExpr *mkU32(UInt i) 867 { 868 return IRExpr_Const(IRConst_U32(i)); 869 } 870 871 /* Create an expression node for a 64-bit integer constant. */ 872 static IRExpr *mkU64(ULong i) 873 { 874 return IRExpr_Const(IRConst_U64(i)); 875 } 876 877 static IRExpr *mkexpr(IRTemp tmp) 878 { 879 return IRExpr_RdTmp(tmp); 880 } 881 882 static IRExpr *unop(IROp op, IRExpr * a) 883 { 884 return IRExpr_Unop(op, a); 885 } 886 887 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2) 888 { 889 return IRExpr_Binop(op, a1, a2); 890 } 891 892 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3) 893 { 894 return IRExpr_Triop(op, a1, a2, a3); 895 } 896 897 static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3, 898 IRExpr * a4 ) 899 { 900 return IRExpr_Qop(op, a1, a2, a3, a4); 901 } 902 903 static IRExpr *load(IRType ty, IRExpr * addr) 904 { 905 IRExpr *load1 = NULL; 906 #if defined (_MIPSEL) 907 load1 = IRExpr_Load(Iend_LE, ty, addr); 908 #elif defined (_MIPSEB) 909 load1 = IRExpr_Load(Iend_BE, ty, addr); 910 #endif 911 return load1; 912 } 913 914 /* Add a statement to the list held by "irsb". */ 915 static void stmt(IRStmt * st) 916 { 917 addStmtToIRSB(irsb, st); 918 } 919 920 static void assign(IRTemp dst, IRExpr * e) 921 { 922 stmt(IRStmt_WrTmp(dst, e)); 923 } 924 925 static void store(IRExpr * addr, IRExpr * data) 926 { 927 #if defined (_MIPSEL) 928 stmt(IRStmt_Store(Iend_LE, addr, data)); 929 #elif defined (_MIPSEB) 930 stmt(IRStmt_Store(Iend_BE, addr, data)); 931 #endif 932 } 933 934 /* Generate a new temporary of the given type. */ 935 static IRTemp newTemp(IRType ty) 936 { 937 vassert(isPlausibleIRType(ty)); 938 return newIRTemp(irsb->tyenv, ty); 939 } 940 941 /* Generate an expression for SRC rotated right by ROT. */ 942 static IRExpr *genROR32(IRExpr * src, Int rot) 943 { 944 vassert(rot >= 0 && rot < 32); 945 if (rot == 0) 946 return src; 947 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)), 948 binop(Iop_Shr32, src, mkU8(rot))); 949 } 950 951 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs) 952 { 953 IRTemp t0 = newTemp(Ity_I8); 954 IRTemp t1 = newTemp(Ity_I8); 955 956 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F)))); 957 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0))); 958 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)), 959 binop(Iop_Shr32, src, mkexpr(t0))); 960 } 961 962 static UShort extend_s_10to16(UInt x) 963 { 964 return (UShort) ((((Int) x) << 22) >> 22); 965 } 966 967 static ULong extend_s_10to32(UInt x) 968 { 969 return (ULong)((((Long) x) << 22) >> 22); 970 } 971 972 static ULong extend_s_10to64(UInt x) 973 { 974 return (ULong)((((Long) x) << 54) >> 54); 975 } 976 977 static UInt extend_s_16to32(UInt x) 978 { 979 return (UInt) ((((Int) x) << 16) >> 16); 980 } 981 982 static UInt extend_s_18to32(UInt x) 983 { 984 return (UInt) ((((Int) x) << 14) >> 14); 985 } 986 987 static ULong extend_s_16to64 ( UInt x ) 988 { 989 return (ULong) ((((Long) x) << 48) >> 48); 990 } 991 992 static ULong extend_s_18to64 ( UInt x ) 993 { 994 return (ULong) ((((Long) x) << 46) >> 46); 995 } 996 997 static ULong extend_s_32to64 ( UInt x ) 998 { 999 return (ULong) ((((Long) x) << 32) >> 32); 1000 } 1001 1002 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 ) 1003 { 1004 vassert(dres->whatNext == Dis_Continue); 1005 vassert(dres->len == 0); 1006 vassert(dres->continueAt == 0); 1007 vassert(dres->jk_StopHere == Ijk_INVALID); 1008 dres->whatNext = Dis_StopHere; 1009 dres->jk_StopHere = kind; 1010 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) ); 1011 } 1012 1013 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 ) 1014 { 1015 vassert(dres->whatNext == Dis_Continue); 1016 vassert(dres->len == 0); 1017 vassert(dres->continueAt == 0); 1018 vassert(dres->jk_StopHere == Ijk_INVALID); 1019 dres->whatNext = Dis_StopHere; 1020 dres->jk_StopHere = kind; 1021 stmt(IRStmt_Put(OFFB_PC, mkU64(d64))); 1022 } 1023 1024 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions). 1025 This function should be called before any other operation if widening 1026 multiplications are used. */ 1027 static IRExpr *getAcc(UInt acNo) 1028 { 1029 vassert(!mode64); 1030 vassert(acNo <= 3); 1031 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64); 1032 } 1033 1034 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE 1035 instructions). */ 1036 static IRExpr *getDSPControl(void) 1037 { 1038 vassert(!mode64); 1039 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32); 1040 } 1041 1042 /* Put value to DSPControl register. Expression e is written to DSPControl as 1043 is. If only certain bits of DSPControl need to be changed, it should be done 1044 before calling putDSPControl(). It could be done by reading DSPControl and 1045 ORing it with appropriate mask. */ 1046 static void putDSPControl(IRExpr * e) 1047 { 1048 vassert(!mode64); 1049 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e)); 1050 } 1051 1052 /* Fetch a byte from the guest insn stream. */ 1053 static UChar getIByte(Int delta) 1054 { 1055 return guest_code[delta]; 1056 } 1057 1058 static IRExpr *getIReg(UInt iregNo) 1059 { 1060 if (0 == iregNo) { 1061 return mode64 ? mkU64(0x0) : mkU32(0x0); 1062 } else { 1063 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1064 vassert(iregNo < 32); 1065 return IRExpr_Get(integerGuestRegOffset(iregNo), ty); 1066 } 1067 } 1068 1069 static IRExpr *getHI(void) 1070 { 1071 if (mode64) 1072 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64); 1073 else 1074 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32); 1075 } 1076 1077 static IRExpr *getLO(void) 1078 { 1079 if (mode64) 1080 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64); 1081 else 1082 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32); 1083 } 1084 1085 static IRExpr *getFCSR(void) 1086 { 1087 if (mode64) 1088 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32); 1089 else 1090 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32); 1091 } 1092 1093 static IRExpr *getLLaddr(void) 1094 { 1095 if (mode64) 1096 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64); 1097 else 1098 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32); 1099 } 1100 1101 static IRExpr *getLLdata(void) 1102 { 1103 if (mode64) 1104 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64); 1105 else 1106 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32); 1107 } 1108 1109 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */ 1110 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos) 1111 { 1112 UInt pos = byte_pos * 8; 1113 if (mode64) 1114 return unop(Iop_64to8, binop(Iop_And64, 1115 binop(Iop_Shr64, getIReg(reg), mkU8(pos)), 1116 mkU64(0xFF))); 1117 else 1118 return unop(Iop_32to8, binop(Iop_And32, 1119 binop(Iop_Shr32, getIReg(reg), mkU8(pos)), 1120 mkU32(0xFF))); 1121 } 1122 1123 static void putFCSR(IRExpr * e) 1124 { 1125 if (mode64) 1126 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e)); 1127 else 1128 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e)); 1129 } 1130 1131 static void putLLaddr(IRExpr * e) 1132 { 1133 if (mode64) 1134 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e)); 1135 else 1136 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e)); 1137 } 1138 1139 static void putLLdata(IRExpr * e) 1140 { 1141 if (mode64) 1142 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e)); 1143 else 1144 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e)); 1145 } 1146 1147 /* fs - fpu source register number. 1148 inst - fpu instruction that needs to be executed. 1149 sz32 - size of source register. 1150 opN - number of operads: 1151 1 - unary operation. 1152 2 - binary operation. */ 1153 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN) 1154 { 1155 IRDirty *d; 1156 IRTemp fcsr = newTemp(Ity_I32); 1157 /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper. */ 1158 if (fp_mode64) 1159 d = unsafeIRDirty_1_N(fcsr, 0, 1160 "mips_dirtyhelper_calculate_FCSR_fp64", 1161 &mips_dirtyhelper_calculate_FCSR_fp64, 1162 mkIRExprVec_4(IRExpr_GSPTR(), 1163 mkU32(fs), 1164 mkU32(ft), 1165 mkU32(inst))); 1166 else 1167 d = unsafeIRDirty_1_N(fcsr, 0, 1168 "mips_dirtyhelper_calculate_FCSR_fp32", 1169 &mips_dirtyhelper_calculate_FCSR_fp32, 1170 mkIRExprVec_4(IRExpr_GSPTR(), 1171 mkU32(fs), 1172 mkU32(ft), 1173 mkU32(inst))); 1174 1175 if (opN == 1) { /* Unary operation. */ 1176 /* Declare we're reading guest state. */ 1177 if (sz32 || fp_mode64) 1178 d->nFxState = 2; 1179 else 1180 d->nFxState = 3; 1181 vex_bzero(&d->fxState, sizeof(d->fxState)); 1182 1183 d->fxState[0].fx = Ifx_Read; /* read */ 1184 if (mode64) 1185 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1186 else 1187 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1188 d->fxState[0].size = sizeof(UInt); 1189 d->fxState[1].fx = Ifx_Read; /* read */ 1190 d->fxState[1].offset = floatGuestRegOffset(fs); 1191 d->fxState[1].size = sizeof(ULong); 1192 1193 if (!(sz32 || fp_mode64)) { 1194 d->fxState[2].fx = Ifx_Read; /* read */ 1195 d->fxState[2].offset = floatGuestRegOffset(fs+1); 1196 d->fxState[2].size = sizeof(ULong); 1197 } 1198 } else if (opN == 2) { /* Binary operation. */ 1199 /* Declare we're reading guest state. */ 1200 if (sz32 || fp_mode64) 1201 d->nFxState = 3; 1202 else 1203 d->nFxState = 5; 1204 vex_bzero(&d->fxState, sizeof(d->fxState)); 1205 1206 d->fxState[0].fx = Ifx_Read; /* read */ 1207 if (mode64) 1208 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1209 else 1210 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1211 d->fxState[0].size = sizeof(UInt); 1212 d->fxState[1].fx = Ifx_Read; /* read */ 1213 d->fxState[1].offset = floatGuestRegOffset(fs); 1214 d->fxState[1].size = sizeof(ULong); 1215 d->fxState[2].fx = Ifx_Read; /* read */ 1216 d->fxState[2].offset = floatGuestRegOffset(ft); 1217 d->fxState[2].size = sizeof(ULong); 1218 1219 if (!(sz32 || fp_mode64)) { 1220 d->fxState[3].fx = Ifx_Read; /* read */ 1221 d->fxState[3].offset = floatGuestRegOffset(fs+1); 1222 d->fxState[3].size = sizeof(ULong); 1223 d->fxState[4].fx = Ifx_Read; /* read */ 1224 d->fxState[4].offset = floatGuestRegOffset(ft+1); 1225 d->fxState[4].size = sizeof(ULong); 1226 } 1227 } 1228 1229 stmt(IRStmt_Dirty(d)); 1230 1231 putFCSR(mkexpr(fcsr)); 1232 } 1233 1234 static IRExpr *getULR(void) 1235 { 1236 if (mode64) 1237 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64); 1238 else 1239 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32); 1240 } 1241 1242 static void putIReg(UInt archreg, IRExpr * e) 1243 { 1244 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1245 vassert(archreg < 32); 1246 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1247 if (archreg != 0) 1248 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e)); 1249 } 1250 1251 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src) 1252 { 1253 vassert(ty == Ity_I32 || ty == Ity_I64); 1254 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1255 } 1256 1257 static void putLO(IRExpr * e) 1258 { 1259 if (mode64) { 1260 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e)); 1261 } else { 1262 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e)); 1263 /* Add value to lower 32 bits of ac0 to maintain compatibility between 1264 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits 1265 unchanged. */ 1266 IRTemp t_lo = newTemp(Ity_I32); 1267 IRTemp t_hi = newTemp(Ity_I32); 1268 assign(t_lo, e); 1269 assign(t_hi, unop(Iop_64HIto32, getAcc(0))); 1270 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1271 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1272 } 1273 } 1274 1275 static void putHI(IRExpr * e) 1276 { 1277 if (mode64) { 1278 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e)); 1279 } else { 1280 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e)); 1281 /* Add value to higher 32 bits of ac0 to maintain compatibility between 1282 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits 1283 unchanged. */ 1284 IRTemp t_lo = newTemp(Ity_I32); 1285 IRTemp t_hi = newTemp(Ity_I32); 1286 assign(t_hi, e); 1287 assign(t_lo, unop(Iop_64to32, getAcc(0))); 1288 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1289 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1290 } 1291 } 1292 1293 /* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */ 1294 static void putAcc(UInt acNo, IRExpr * e) 1295 { 1296 vassert(!mode64); 1297 vassert(acNo <= 3); 1298 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64); 1299 stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e)); 1300 /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility 1301 between MIPS32 and MIPS DSP ASE insn sets. */ 1302 if (0 == acNo) { 1303 putLO(unop(Iop_64to32, e)); 1304 putHI(unop(Iop_64HIto32, e)); 1305 } 1306 } 1307 1308 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src ) 1309 { 1310 vassert(ty == Ity_I32 || ty == Ity_I64); 1311 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1312 } 1313 1314 static void putPC(IRExpr * e) 1315 { 1316 stmt(IRStmt_Put(OFFB_PC, e)); 1317 } 1318 1319 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined) 1320 { 1321 vassert(ty == Ity_I32 || ty == Ity_I64); 1322 if (ty == Ity_I32) 1323 return src; 1324 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1325 } 1326 1327 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some 1328 of these combinations make sense. */ 1329 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e) 1330 { 1331 IRType src_ty = typeOfIRExpr(irsb->tyenv, e); 1332 if (src_ty == dst_ty) 1333 return e; 1334 if (src_ty == Ity_I32 && dst_ty == Ity_I16) 1335 return unop(Iop_32to16, e); 1336 if (src_ty == Ity_I32 && dst_ty == Ity_I8) 1337 return unop(Iop_32to8, e); 1338 if (src_ty == Ity_I64 && dst_ty == Ity_I8) { 1339 vassert(mode64); 1340 return unop(Iop_64to8, e); 1341 } 1342 if (src_ty == Ity_I64 && dst_ty == Ity_I16) { 1343 vassert(mode64); 1344 return unop(Iop_64to16, e); 1345 } 1346 vpanic("narrowTo(mips)"); 1347 return 0; 1348 } 1349 1350 static IRExpr *getLoFromF64(IRType ty, IRExpr * src) 1351 { 1352 vassert(ty == Ity_F32 || ty == Ity_F64); 1353 if (ty == Ity_F64) { 1354 IRTemp t0, t1; 1355 t0 = newTemp(Ity_I64); 1356 t1 = newTemp(Ity_I32); 1357 assign(t0, unop(Iop_ReinterpF64asI64, src)); 1358 assign(t1, unop(Iop_64to32, mkexpr(t0))); 1359 return unop(Iop_ReinterpI32asF32, mkexpr(t1)); 1360 } else 1361 return src; 1362 } 1363 1364 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src) 1365 { 1366 vassert(ty == Ity_F32 || ty == Ity_F64); 1367 if (ty == Ity_F64) { 1368 IRTemp t0 = newTemp(Ity_I32); 1369 IRTemp t1 = newTemp(Ity_I64); 1370 assign(t0, unop(Iop_ReinterpF32asI32, src)); 1371 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0))); 1372 return unop(Iop_ReinterpI64asF64, mkexpr(t1)); 1373 } else 1374 return src; 1375 } 1376 1377 /* Convenience function to move to next instruction on condition. */ 1378 static void mips_next_insn_if(IRExpr *condition) { 1379 vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1); 1380 1381 stmt(IRStmt_Exit(condition, Ijk_Boring, 1382 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 1383 IRConst_U32(guest_PC_curr_instr + 4), 1384 OFFB_PC)); 1385 } 1386 1387 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm) 1388 { 1389 ULong branch_offset; 1390 IRTemp t0; 1391 1392 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1393 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1394 is added to the address of the instruction following 1395 the branch (not the branch itself), in the branch delay slot, to form 1396 a PC-relative effective target address. */ 1397 if (mode64) 1398 branch_offset = extend_s_18to64(imm << 2); 1399 else 1400 branch_offset = extend_s_18to32(imm << 2); 1401 1402 t0 = newTemp(Ity_I1); 1403 assign(t0, guard); 1404 1405 if (mode64) 1406 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1407 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC)); 1408 else 1409 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1410 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC)); 1411 1412 irsb->jumpkind = Ijk_Boring; 1413 1414 if (mode64) 1415 return mkU64(guest_PC_curr_instr + 4 + branch_offset); 1416 else 1417 return mkU32(guest_PC_curr_instr + 4 + branch_offset); 1418 } 1419 1420 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set) 1421 { 1422 ULong branch_offset; 1423 IRTemp t0; 1424 1425 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */ 1426 if (mode64) 1427 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 1428 else 1429 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 1430 } 1431 1432 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1433 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1434 is added to the address of the instruction following 1435 the branch (not the branch itself), in the branch delay slot, to form 1436 a PC-relative effective target address. */ 1437 1438 if (mode64) 1439 branch_offset = extend_s_18to64(imm << 2); 1440 else 1441 branch_offset = extend_s_18to32(imm << 2); 1442 1443 t0 = newTemp(Ity_I1); 1444 assign(t0, guard); 1445 if (mode64) 1446 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1447 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset), 1448 OFFB_PC); 1449 else 1450 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1451 IRConst_U32(guest_PC_curr_instr + 4 + 1452 (UInt) branch_offset), OFFB_PC); 1453 } 1454 1455 static IRExpr *getFReg(UInt fregNo) 1456 { 1457 vassert(fregNo < 32); 1458 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1459 return IRExpr_Get(floatGuestRegOffset(fregNo), ty); 1460 } 1461 1462 static IRExpr *getDReg(UInt dregNo) 1463 { 1464 vassert(dregNo < 32); 1465 if (fp_mode64) { 1466 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64); 1467 } else { 1468 /* Read a floating point register pair and combine their contents into a 1469 64-bit value */ 1470 IRTemp t0 = newTemp(Ity_F32); 1471 IRTemp t1 = newTemp(Ity_F32); 1472 IRTemp t2 = newTemp(Ity_F64); 1473 IRTemp t3 = newTemp(Ity_I32); 1474 IRTemp t4 = newTemp(Ity_I32); 1475 IRTemp t5 = newTemp(Ity_I64); 1476 1477 assign(t0, getFReg(dregNo & (~1))); 1478 assign(t1, getFReg(dregNo | 1)); 1479 1480 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); 1481 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); 1482 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3))); 1483 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5))); 1484 1485 return mkexpr(t2); 1486 } 1487 } 1488 1489 static void putFReg(UInt dregNo, IRExpr * e) 1490 { 1491 vassert(dregNo < 32); 1492 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1493 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1494 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1495 } 1496 1497 static void putDReg(UInt dregNo, IRExpr * e) 1498 { 1499 if (fp_mode64) { 1500 vassert(dregNo < 32); 1501 IRType ty = Ity_F64; 1502 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1503 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1504 } else { 1505 vassert(dregNo < 32); 1506 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1507 IRTemp t1 = newTemp(Ity_F64); 1508 IRTemp t4 = newTemp(Ity_I32); 1509 IRTemp t5 = newTemp(Ity_I32); 1510 IRTemp t6 = newTemp(Ity_I64); 1511 assign(t1, e); 1512 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1))); 1513 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */ 1514 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */ 1515 putFReg(dregNo & (~1), unop(Iop_ReinterpI32asF32, mkexpr(t5))); 1516 putFReg(dregNo | 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); 1517 } 1518 } 1519 1520 static void setFPUCondCode(IRExpr * e, UInt cc) 1521 { 1522 if (cc == 0) { 1523 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF))); 1524 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23)))); 1525 } else { 1526 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32, 1527 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc))))); 1528 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc)))); 1529 } 1530 } 1531 1532 static IRExpr* get_IR_roundingmode ( void ) 1533 { 1534 /* 1535 rounding mode | MIPS | IR 1536 ------------------------ 1537 to nearest | 00 | 00 1538 to zero | 01 | 11 1539 to +infinity | 10 | 10 1540 to -infinity | 11 | 01 1541 */ 1542 IRTemp rm_MIPS = newTemp(Ity_I32); 1543 /* Last two bits in FCSR are rounding mode. */ 1544 1545 if (mode64) 1546 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State, 1547 guest_FCSR), Ity_I32), mkU32(3))); 1548 else 1549 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State, 1550 guest_FCSR), Ity_I32), mkU32(3))); 1551 1552 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */ 1553 1554 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32, 1555 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2))); 1556 } 1557 1558 /* sz, ULong -> IRExpr */ 1559 static IRExpr *mkSzImm ( IRType ty, ULong imm64 ) 1560 { 1561 vassert(ty == Ity_I32 || ty == Ity_I64); 1562 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64); 1563 } 1564 1565 static IRConst *mkSzConst ( IRType ty, ULong imm64 ) 1566 { 1567 vassert(ty == Ity_I32 || ty == Ity_I64); 1568 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64)); 1569 } 1570 1571 /* Make sure we get valid 32 and 64bit addresses */ 1572 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1573 { 1574 vassert(ty == Ity_I32 || ty == Ity_I64); 1575 return (ty == Ity_I64 ? (Addr64) addr : 1576 (Addr64) extend_s_32to64(toUInt(addr))); 1577 } 1578 1579 /* Shift and Rotate instructions for MIPS64 */ 1580 static Bool dis_instr_shrt ( UInt theInstr ) 1581 { 1582 UInt opc2 = get_function(theInstr); 1583 UChar regRs = get_rs(theInstr); 1584 UChar regRt = get_rt(theInstr); 1585 UChar regRd = get_rd(theInstr); 1586 UChar uImmsa = get_sa(theInstr); 1587 Long sImmsa = extend_s_16to64(uImmsa); 1588 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1589 IRTemp tmp = newTemp(ty); 1590 IRTemp tmpOr = newTemp(ty); 1591 IRTemp tmpRt = newTemp(ty); 1592 IRTemp tmpRs = newTemp(ty); 1593 IRTemp tmpRd = newTemp(ty); 1594 1595 assign(tmpRs, getIReg(regRs)); 1596 assign(tmpRt, getIReg(regRt)); 1597 1598 switch (opc2) { 1599 case 0x3A: 1600 if ((regRs & 0x01) == 0) { 1601 /* Doubleword Shift Right Logical - DSRL; MIPS64 */ 1602 DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa); 1603 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1604 putIReg(regRd, mkexpr(tmpRd)); 1605 } else if ((regRs & 0x01) == 1) { 1606 /* Doubleword Rotate Right - DROTR; MIPS64r2 */ 1607 vassert(mode64); 1608 DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa); 1609 IRTemp tmpL = newTemp(ty); 1610 IRTemp tmpR = newTemp(ty); 1611 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1612 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa))); 1613 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1614 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1615 putIReg(regRd, mkexpr(tmpRd)); 1616 } else 1617 return False; 1618 break; 1619 1620 case 0x3E: 1621 if ((regRs & 0x01) == 0) { 1622 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */ 1623 DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32); 1624 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1625 putIReg(regRd, mkexpr(tmpRd)); 1626 } else if ((regRs & 0x01) == 1) { 1627 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */ 1628 DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1629 vassert(mode64); 1630 IRTemp tmpL = newTemp(ty); 1631 IRTemp tmpR = newTemp(ty); 1632 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */ 1633 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1634 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), 1635 mkU8(63 - (uImmsa + 32)))); 1636 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1637 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1638 putIReg(regRd, mkexpr(tmpRd)); 1639 } else 1640 return False; 1641 break; 1642 1643 case 0x16: 1644 if ((uImmsa & 0x01) == 0) { 1645 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */ 1646 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs); 1647 IRTemp tmpRs8 = newTemp(Ity_I8); 1648 /* s = tmpRs[5..0] */ 1649 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63))); 1650 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1651 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1652 putIReg(regRd, mkexpr(tmpRd)); 1653 } else if ((uImmsa & 0x01) == 1) { 1654 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */ 1655 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs); 1656 IRTemp tmpL = newTemp(ty); 1657 IRTemp tmpR = newTemp(ty); 1658 IRTemp tmpRs8 = newTemp(Ity_I8); 1659 IRTemp tmpLs8 = newTemp(Ity_I8); 1660 IRTemp tmp64 = newTemp(ty); 1661 /* s = tmpRs[5...0] 1662 m = 64 - s 1663 (tmpRt << s) | (tmpRt >> m) */ 1664 1665 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1666 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64))); 1667 1668 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp))); 1669 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64))); 1670 1671 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1672 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8))); 1673 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1))); 1674 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR))); 1675 1676 putIReg(regRd, mkexpr(tmpOr)); 1677 } else 1678 return False; 1679 break; 1680 1681 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */ 1682 DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa); 1683 vassert(mode64); 1684 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa))); 1685 putIReg(regRd, mkexpr(tmpRd)); 1686 break; 1687 1688 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */ 1689 DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1690 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1691 putIReg(regRd, mkexpr(tmpRd)); 1692 break; 1693 1694 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */ 1695 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs); 1696 IRTemp tmpRs8 = newTemp(Ity_I8); 1697 1698 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1699 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1700 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1701 putIReg(regRd, mkexpr(tmpRd)); 1702 break; 1703 } 1704 1705 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */ 1706 DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa); 1707 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa))); 1708 putIReg(regRd, mkexpr(tmpRd)); 1709 break; 1710 1711 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32; 1712 MIPS64 */ 1713 DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1714 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1715 putIReg(regRd, mkexpr(tmpRd)); 1716 break; 1717 1718 case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV; 1719 MIPS64 */ 1720 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs); 1721 IRTemp tmpRs8 = newTemp(Ity_I8); 1722 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1723 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1724 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1725 putIReg(regRd, mkexpr(tmpRd)); 1726 break; 1727 1728 } 1729 1730 default: 1731 return False; 1732 1733 } 1734 return True; 1735 } 1736 1737 static IROp mkSzOp ( IRType ty, IROp op8 ) 1738 { 1739 Int adj; 1740 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64); 1741 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 1742 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 1743 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 1744 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8); 1745 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3)); 1746 return adj + op8; 1747 } 1748 1749 /*********************************************************/ 1750 /*--- Floating Point Compare ---*/ 1751 /*********************************************************/ 1752 /* Function that returns a string that represent mips cond 1753 mnemonic for the input code. */ 1754 static const HChar* showCondCode(UInt code) { 1755 const HChar* ret; 1756 switch (code) { 1757 case 0: ret = "f"; break; 1758 case 1: ret = "un"; break; 1759 case 2: ret = "eq"; break; 1760 case 3: ret = "ueq"; break; 1761 case 4: ret = "olt"; break; 1762 case 5: ret = "ult"; break; 1763 case 6: ret = "ole"; break; 1764 case 7: ret = "ule"; break; 1765 case 8: ret = "sf"; break; 1766 case 9: ret = "ngle"; break; 1767 case 10: ret = "seq"; break; 1768 case 11: ret = "ngl"; break; 1769 case 12: ret = "lt"; break; 1770 case 13: ret = "nge"; break; 1771 case 14: ret = "le"; break; 1772 case 15: ret = "ngt"; break; 1773 default: vpanic("showCondCode"); break; 1774 } 1775 return ret; 1776 } 1777 1778 static Bool dis_instr_CCondFmt ( UInt cins ) 1779 { 1780 IRTemp t0, t1, t2, t3, tmp5, tmp6; 1781 IRTemp ccIR = newTemp(Ity_I32); 1782 IRTemp ccMIPS = newTemp(Ity_I32); 1783 UInt FC = get_FC(cins); 1784 UInt fmt = get_fmt(cins); 1785 UInt fs = get_fs(cins); 1786 UInt ft = get_ft(cins); 1787 UInt cond = get_cond(cins); 1788 1789 if (FC == 0x3) { /* C.cond.fmt */ 1790 UInt fpc_cc = get_fpc_cc(cins); 1791 switch (fmt) { 1792 case 0x10: { /* C.cond.S */ 1793 DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft); 1794 if (fp_mode64) { 1795 t0 = newTemp(Ity_I32); 1796 t1 = newTemp(Ity_I32); 1797 t2 = newTemp(Ity_I32); 1798 t3 = newTemp(Ity_I32); 1799 1800 tmp5 = newTemp(Ity_F64); 1801 tmp6 = newTemp(Ity_F64); 1802 1803 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1804 getFReg(fs)))); 1805 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1806 getFReg(ft)))); 1807 1808 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6))); 1809 putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1810 mkexpr(ccIR), True)); 1811 /* Map compare result from IR to MIPS 1812 FP cmp result | MIPS | IR 1813 -------------------------- 1814 UN | 0x1 | 0x45 1815 EQ | 0x2 | 0x40 1816 GT | 0x4 | 0x00 1817 LT | 0x8 | 0x01 1818 */ 1819 1820 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1821 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1822 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1823 binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)), 1824 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1825 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1826 mkU32(1)))))); 1827 putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1828 mkexpr(ccMIPS), True)); 1829 1830 /* UN */ 1831 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1832 /* EQ */ 1833 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1834 mkU8(0x1)), mkU32(0x1))); 1835 /* NGT */ 1836 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1837 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1))); 1838 /* LT */ 1839 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1840 mkU8(0x3)), mkU32(0x1))); 1841 switch (cond) { 1842 case 0x0: 1843 setFPUCondCode(mkU32(0), fpc_cc); 1844 break; 1845 case 0x1: 1846 setFPUCondCode(mkexpr(t0), fpc_cc); 1847 break; 1848 case 0x2: 1849 setFPUCondCode(mkexpr(t1), fpc_cc); 1850 break; 1851 case 0x3: 1852 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1853 fpc_cc); 1854 break; 1855 case 0x4: 1856 setFPUCondCode(mkexpr(t3), fpc_cc); 1857 break; 1858 case 0x5: 1859 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1860 fpc_cc); 1861 break; 1862 case 0x6: 1863 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1864 fpc_cc); 1865 break; 1866 case 0x7: 1867 setFPUCondCode(mkexpr(t2), fpc_cc); 1868 break; 1869 case 0x8: 1870 setFPUCondCode(mkU32(0), fpc_cc); 1871 break; 1872 case 0x9: 1873 setFPUCondCode(mkexpr(t0), fpc_cc); 1874 break; 1875 case 0xA: 1876 setFPUCondCode(mkexpr(t1), fpc_cc); 1877 break; 1878 case 0xB: 1879 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1880 fpc_cc); 1881 break; 1882 case 0xC: 1883 setFPUCondCode(mkexpr(t3), fpc_cc); 1884 break; 1885 case 0xD: 1886 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1887 fpc_cc); 1888 break; 1889 case 0xE: 1890 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1891 fpc_cc); 1892 break; 1893 case 0xF: 1894 setFPUCondCode(mkexpr(t2), fpc_cc); 1895 break; 1896 1897 default: 1898 return False; 1899 } 1900 1901 } else { 1902 t0 = newTemp(Ity_I32); 1903 t1 = newTemp(Ity_I32); 1904 t2 = newTemp(Ity_I32); 1905 t3 = newTemp(Ity_I32); 1906 1907 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)), 1908 unop(Iop_F32toF64, getFReg(ft)))); 1909 /* Map compare result from IR to MIPS 1910 FP cmp result | MIPS | IR 1911 -------------------------- 1912 UN | 0x1 | 0x45 1913 EQ | 0x2 | 0x40 1914 GT | 0x4 | 0x00 1915 LT | 0x8 | 0x01 1916 */ 1917 1918 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1919 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1920 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1921 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), 1922 mkU32(2)), binop(Iop_And32, 1923 binop(Iop_Xor32, mkexpr(ccIR), 1924 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1925 mkU32(1)))))); 1926 /* UN */ 1927 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1928 /* EQ */ 1929 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1930 mkU8(0x1)), mkU32(0x1))); 1931 /* NGT */ 1932 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1933 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 1934 /* LT */ 1935 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1936 mkU8(0x3)), mkU32(0x1))); 1937 1938 switch (cond) { 1939 case 0x0: 1940 setFPUCondCode(mkU32(0), fpc_cc); 1941 break; 1942 case 0x1: 1943 setFPUCondCode(mkexpr(t0), fpc_cc); 1944 break; 1945 case 0x2: 1946 setFPUCondCode(mkexpr(t1), fpc_cc); 1947 break; 1948 case 0x3: 1949 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1950 fpc_cc); 1951 break; 1952 case 0x4: 1953 setFPUCondCode(mkexpr(t3), fpc_cc); 1954 break; 1955 case 0x5: 1956 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1957 fpc_cc); 1958 break; 1959 case 0x6: 1960 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1961 fpc_cc); 1962 break; 1963 case 0x7: 1964 setFPUCondCode(mkexpr(t2), fpc_cc); 1965 break; 1966 case 0x8: 1967 setFPUCondCode(mkU32(0), fpc_cc); 1968 break; 1969 case 0x9: 1970 setFPUCondCode(mkexpr(t0), fpc_cc); 1971 break; 1972 case 0xA: 1973 setFPUCondCode(mkexpr(t1), fpc_cc); 1974 break; 1975 case 0xB: 1976 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1977 fpc_cc); 1978 break; 1979 case 0xC: 1980 setFPUCondCode(mkexpr(t3), fpc_cc); 1981 break; 1982 case 0xD: 1983 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1984 fpc_cc); 1985 break; 1986 case 0xE: 1987 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1988 fpc_cc); 1989 break; 1990 case 0xF: 1991 setFPUCondCode(mkexpr(t2), fpc_cc); 1992 break; 1993 1994 default: 1995 return False; 1996 } 1997 } 1998 } 1999 break; 2000 2001 case 0x11: { /* C.cond.D */ 2002 DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft); 2003 t0 = newTemp(Ity_I32); 2004 t1 = newTemp(Ity_I32); 2005 t2 = newTemp(Ity_I32); 2006 t3 = newTemp(Ity_I32); 2007 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); 2008 /* Map compare result from IR to MIPS 2009 FP cmp result | MIPS | IR 2010 -------------------------- 2011 UN | 0x1 | 0x45 2012 EQ | 0x2 | 0x40 2013 GT | 0x4 | 0x00 2014 LT | 0x8 | 0x01 2015 */ 2016 2017 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 2018 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 2019 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 2020 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)), 2021 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 2022 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 2023 mkU32(1)))))); 2024 2025 /* UN */ 2026 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 2027 /* EQ */ 2028 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 2029 mkU8(0x1)), mkU32(0x1))); 2030 /* NGT */ 2031 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 2032 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 2033 /* LT */ 2034 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 2035 mkU8(0x3)), mkU32(0x1))); 2036 2037 switch (cond) { 2038 case 0x0: 2039 setFPUCondCode(mkU32(0), fpc_cc); 2040 break; 2041 case 0x1: 2042 setFPUCondCode(mkexpr(t0), fpc_cc); 2043 break; 2044 case 0x2: 2045 setFPUCondCode(mkexpr(t1), fpc_cc); 2046 break; 2047 case 0x3: 2048 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2049 fpc_cc); 2050 break; 2051 case 0x4: 2052 setFPUCondCode(mkexpr(t3), fpc_cc); 2053 break; 2054 case 0x5: 2055 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2056 fpc_cc); 2057 break; 2058 case 0x6: 2059 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2060 fpc_cc); 2061 break; 2062 case 0x7: 2063 setFPUCondCode(mkexpr(t2), fpc_cc); 2064 break; 2065 case 0x8: 2066 setFPUCondCode(mkU32(0), fpc_cc); 2067 break; 2068 case 0x9: 2069 setFPUCondCode(mkexpr(t0), fpc_cc); 2070 break; 2071 case 0xA: 2072 setFPUCondCode(mkexpr(t1), fpc_cc); 2073 break; 2074 case 0xB: 2075 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2076 fpc_cc); 2077 break; 2078 case 0xC: 2079 setFPUCondCode(mkexpr(t3), fpc_cc); 2080 break; 2081 case 0xD: 2082 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2083 fpc_cc); 2084 break; 2085 case 0xE: 2086 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2087 fpc_cc); 2088 break; 2089 case 0xF: 2090 setFPUCondCode(mkexpr(t2), fpc_cc); 2091 break; 2092 default: 2093 return False; 2094 } 2095 } 2096 break; 2097 2098 default: 2099 return False; 2100 } 2101 } else { 2102 return False; 2103 } 2104 2105 return True; 2106 } 2107 2108 /*********************************************************/ 2109 /*--- Branch Instructions for mips64 ---*/ 2110 /*********************************************************/ 2111 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres, 2112 Bool(*resteerOkFn) (void *, Addr), 2113 void *callback_opaque, IRStmt ** set ) 2114 { 2115 UInt jmpKind = 0; 2116 UChar opc1 = get_opcode(theInstr); 2117 UChar regRs = get_rs(theInstr); 2118 UChar regRt = get_rt(theInstr); 2119 UInt offset = get_imm(theInstr); 2120 Long sOffset = extend_s_16to64(offset); 2121 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2122 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S; 2123 2124 IRTemp tmp = newTemp(ty); 2125 IRTemp tmpRs = newTemp(ty); 2126 IRTemp tmpRt = newTemp(ty); 2127 IRTemp tmpLt = newTemp(ty); 2128 IRTemp tmpReg0 = newTemp(ty); 2129 2130 UChar regLnk = 31; /* reg 31 is link reg in MIPS */ 2131 Addr64 addrTgt = 0; 2132 Addr64 cia = guest_PC_curr_instr; 2133 2134 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0); 2135 IRExpr *eNia = mkSzImm(ty, cia + 8); 2136 IRExpr *eCond = NULL; 2137 2138 assign(tmpRs, getIReg(regRs)); 2139 assign(tmpRt, getIReg(regRt)); 2140 assign(tmpReg0, getIReg(0)); 2141 2142 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0)); 2143 2144 switch (opc1) { 2145 case 0x01: 2146 switch (regRt) { 2147 case 0x00: { /* BLTZ rs, offset */ 2148 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2149 IRTemp tmpLtRes = newTemp(Ity_I1); 2150 2151 assign(tmp, eConst0); 2152 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2153 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2154 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2155 2156 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt), 2157 mkexpr(tmpReg0)); 2158 2159 jmpKind = Ijk_Boring; 2160 break; 2161 } 2162 2163 case 0x01: { /* BGEZ rs, offset */ 2164 IRTemp tmpLtRes = newTemp(Ity_I1); 2165 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2166 2167 assign(tmp, eConst0); 2168 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2169 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2170 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2171 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2172 mkexpr(tmpReg0)); 2173 2174 jmpKind = Ijk_Boring; 2175 break; 2176 } 2177 2178 case 0x11: { /* BGEZAL rs, offset */ 2179 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2180 putIReg(regLnk, eNia); 2181 IRTemp tmpLtRes = newTemp(Ity_I1); 2182 2183 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0)); 2184 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2185 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2186 2187 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2188 mkexpr(tmpReg0)); 2189 2190 jmpKind = Ijk_Call; 2191 break; 2192 } 2193 2194 case 0x10: { /* BLTZAL rs, offset */ 2195 IRTemp tmpLtRes = newTemp(Ity_I1); 2196 IRTemp tmpRes = newTemp(ty); 2197 2198 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2199 putIReg(regLnk, eNia); 2200 2201 assign(tmp, eConst0); 2202 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2203 assign(tmpRes, mode64 ? unop(Iop_1Uto64, 2204 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2205 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes), 2206 mkexpr(tmpReg0)); 2207 2208 jmpKind = Ijk_Call; 2209 break; 2210 } 2211 2212 } 2213 break; 2214 default: 2215 return False; 2216 } 2217 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC); 2218 return True; 2219 } 2220 2221 /*********************************************************/ 2222 /*--- Cavium Specific Instructions ---*/ 2223 /*********************************************************/ 2224 2225 /* Convenience function to yield to thread scheduler */ 2226 static void jump_back(IRExpr *condition) 2227 { 2228 stmt( IRStmt_Exit(condition, 2229 Ijk_Yield, 2230 IRConst_U64( guest_PC_curr_instr ), 2231 OFFB_PC) ); 2232 } 2233 2234 /* Based on s390_irgen_load_and_add32. */ 2235 static void mips_load_store32(IRTemp op1addr, IRTemp new_val, 2236 IRTemp expd, UChar rd, Bool putIntoRd) 2237 { 2238 IRCAS *cas; 2239 IRTemp old_mem = newTemp(Ity_I32); 2240 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2241 2242 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2243 #if defined (_MIPSEL) 2244 Iend_LE, mkexpr(op1addr), 2245 #else /* _MIPSEB */ 2246 Iend_BE, mkexpr(op1addr), 2247 #endif 2248 NULL, mkexpr(expd), /* expected value */ 2249 NULL, mkexpr(new_val) /* new value */); 2250 stmt(IRStmt_CAS(cas)); 2251 2252 /* If old_mem contains the expected value, then the CAS succeeded. 2253 Otherwise, it did not */ 2254 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd))); 2255 if (putIntoRd) 2256 putIReg(rd, mkWidenFrom32(ty, mkexpr(old_mem), True)); 2257 } 2258 2259 /* Based on s390_irgen_load_and_add64. */ 2260 static void mips_load_store64(IRTemp op1addr, IRTemp new_val, 2261 IRTemp expd, UChar rd, Bool putIntoRd) 2262 { 2263 IRCAS *cas; 2264 IRTemp old_mem = newTemp(Ity_I64); 2265 vassert(mode64); 2266 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2267 #if defined (_MIPSEL) 2268 Iend_LE, mkexpr(op1addr), 2269 #else /* _MIPSEB */ 2270 Iend_BE, mkexpr(op1addr), 2271 #endif 2272 NULL, mkexpr(expd), /* expected value */ 2273 NULL, mkexpr(new_val) /* new value */); 2274 stmt(IRStmt_CAS(cas)); 2275 2276 /* If old_mem contains the expected value, then the CAS succeeded. 2277 Otherwise, it did not */ 2278 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd))); 2279 if (putIntoRd) 2280 putIReg(rd, mkexpr(old_mem)); 2281 } 2282 2283 static Bool dis_instr_CVM ( UInt theInstr ) 2284 { 2285 UChar opc2 = get_function(theInstr); 2286 UChar opc1 = get_opcode(theInstr); 2287 UChar regRs = get_rs(theInstr); 2288 UChar regRt = get_rt(theInstr); 2289 UChar regRd = get_rd(theInstr); 2290 /* MIPS trap instructions extract code from theInstr[15:6]. 2291 Cavium OCTEON instructions SNEI, SEQI extract immediate operands 2292 from the same bit field [15:6]. */ 2293 UInt imm = get_code(theInstr); 2294 UChar lenM1 = get_msb(theInstr); 2295 UChar p = get_lsb(theInstr); 2296 IRType ty = mode64? Ity_I64 : Ity_I32; 2297 IRTemp tmp = newTemp(ty); 2298 IRTemp tmpRs = newTemp(ty); 2299 IRTemp tmpRt = newTemp(ty); 2300 IRTemp t1 = newTemp(ty); 2301 UInt size; 2302 assign(tmpRs, getIReg(regRs)); 2303 2304 switch(opc1) { 2305 case 0x1C: { 2306 switch(opc2) { 2307 case 0x03: { /* DMUL rd, rs, rt */ 2308 DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt); 2309 IRTemp t0 = newTemp(Ity_I128); 2310 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt))); 2311 putIReg(regRd, unop(Iop_128to64, mkexpr(t0))); 2312 break; 2313 } 2314 2315 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */ 2316 DIP("saa r%u, (r%u)", regRt, regRs); 2317 IRTemp addr = newTemp(Ity_I64); 2318 IRTemp new_val = newTemp(Ity_I32); 2319 IRTemp old = newTemp(Ity_I32); 2320 assign(addr, getIReg(regRs)); 2321 assign(old, load(Ity_I32, mkexpr(addr))); 2322 assign(new_val, binop(Iop_Add32, 2323 mkexpr(old), 2324 mkNarrowTo32(ty, getIReg(regRt)))); 2325 mips_load_store32(addr, new_val, old, 0, False); 2326 break; 2327 } 2328 2329 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */ 2330 case 0x19: { 2331 DIP( "saad r%u, (r%u)", regRt, regRs); 2332 IRTemp addr = newTemp(Ity_I64); 2333 IRTemp new_val = newTemp(Ity_I64); 2334 IRTemp old = newTemp(Ity_I64); 2335 assign(addr, getIReg(regRs)); 2336 assign(old, load(Ity_I64, mkexpr(addr))); 2337 assign(new_val, binop(Iop_Add64, 2338 mkexpr(old), 2339 getIReg(regRt))); 2340 mips_load_store64(addr, new_val, old, 0, False); 2341 break; 2342 } 2343 2344 /* LAI, LAID, LAD, LADD, LAS, LASD, 2345 LAC, LACD, LAA, LAAD, LAW, LAWD */ 2346 case 0x1f: { 2347 UInt opc3 = get_sa(theInstr); 2348 IRTemp addr = newTemp(Ity_I64); 2349 switch (opc3) { 2350 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */ 2351 case 0x02: { 2352 DIP("lai r%u,(r%u)\n", regRd, regRs); 2353 IRTemp new_val = newTemp(Ity_I32); 2354 IRTemp old = newTemp(Ity_I32); 2355 assign(addr, getIReg(regRs)); 2356 assign(old, load(Ity_I32, mkexpr(addr))); 2357 assign(new_val, binop(Iop_Add32, 2358 mkexpr(old), 2359 mkU32(1))); 2360 mips_load_store32(addr, new_val, old, regRd, True); 2361 break; 2362 } 2363 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */ 2364 case 0x03: { 2365 DIP("laid r%u,(r%u)\n", regRd, regRs); 2366 IRTemp new_val = newTemp(Ity_I64); 2367 IRTemp old = newTemp(Ity_I64); 2368 assign(addr, getIReg(regRs)); 2369 assign(old, load(Ity_I64, mkexpr(addr))); 2370 assign(new_val, binop(Iop_Add64, 2371 mkexpr(old), 2372 mkU64(1))); 2373 mips_load_store64(addr, new_val, old, regRd, True); 2374 break; 2375 } 2376 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */ 2377 case 0x06: { 2378 DIP("lad r%u,(r%u)\n", regRd, regRs); 2379 IRTemp new_val = newTemp(Ity_I32); 2380 IRTemp old = newTemp(Ity_I32); 2381 assign(addr, getIReg(regRs)); 2382 assign(old, load(Ity_I32, mkexpr(addr))); 2383 assign(new_val, binop(Iop_Sub32, 2384 mkexpr(old), 2385 mkU32(1))); 2386 mips_load_store32(addr, new_val, old, regRd, True); 2387 break; 2388 } 2389 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */ 2390 case 0x07: { 2391 DIP("ladd r%u,(r%u)\n", regRd, regRs); 2392 IRTemp new_val = newTemp(Ity_I64); 2393 IRTemp old = newTemp(Ity_I64); 2394 assign(addr, getIReg(regRs)); 2395 assign(old, load(Ity_I64, mkexpr(addr))); 2396 assign(new_val, binop(Iop_Sub64, 2397 mkexpr(old), 2398 mkU64(1))); 2399 mips_load_store64(addr, new_val, old, regRd, True); 2400 break; 2401 } 2402 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */ 2403 case 0x0a: { 2404 DIP("las r%u,(r%u)\n", regRd, regRs); 2405 IRTemp new_val = newTemp(Ity_I32); 2406 IRTemp old = newTemp(Ity_I32); 2407 assign(addr, getIReg(regRs)); 2408 assign(new_val, mkU32(0xffffffff)); 2409 assign(old, load(Ity_I32, mkexpr(addr))); 2410 mips_load_store32(addr, new_val, old, regRd, True); 2411 break; 2412 } 2413 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */ 2414 case 0x0b: { 2415 DIP("lasd r%u,(r%u)\n", regRd, regRs); 2416 IRTemp new_val = newTemp(Ity_I64); 2417 IRTemp old = newTemp(Ity_I64); 2418 assign(addr, getIReg(regRs)); 2419 assign(new_val, mkU64(0xffffffffffffffffULL)); 2420 assign(old, load(Ity_I64, mkexpr(addr))); 2421 mips_load_store64(addr, new_val, old, regRd, True); 2422 break; 2423 } 2424 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */ 2425 case 0x0e: { 2426 DIP("lac r%u,(r%u)\n", regRd, regRs); 2427 IRTemp new_val = newTemp(Ity_I32); 2428 IRTemp old = newTemp(Ity_I32); 2429 assign(addr, getIReg(regRs)); 2430 assign(new_val, mkU32(0)); 2431 assign(old, load(Ity_I32, mkexpr(addr))); 2432 mips_load_store32(addr, new_val, old, regRd, True); 2433 break; 2434 } 2435 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */ 2436 case 0x0f: { 2437 DIP("lacd r%u,(r%u)\n", regRd, regRs); 2438 IRTemp new_val = newTemp(Ity_I64); 2439 IRTemp old = newTemp(Ity_I64); 2440 assign(addr, getIReg(regRs)); 2441 assign(new_val, mkU64(0)); 2442 assign(old, load(Ity_I64, mkexpr(addr))); 2443 mips_load_store64(addr, new_val, old, regRd, True); 2444 break; 2445 } 2446 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */ 2447 case 0x12: { 2448 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt); 2449 IRTemp new_val = newTemp(Ity_I32); 2450 IRTemp old = newTemp(Ity_I32); 2451 assign(addr, getIReg(regRs)); 2452 assign(old, load(Ity_I32, mkexpr(addr))); 2453 assign(new_val, binop(Iop_Add32, 2454 mkexpr(old), 2455 mkNarrowTo32(ty, getIReg(regRt)))); 2456 mips_load_store32(addr, new_val, old, regRd, True); 2457 break; 2458 } 2459 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */ 2460 case 0x13: { 2461 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt); 2462 IRTemp new_val = newTemp(Ity_I64); 2463 IRTemp old = newTemp(Ity_I64); 2464 assign(addr, getIReg(regRs)); 2465 assign(old, load(Ity_I64, mkexpr(addr))); 2466 assign(new_val, binop(Iop_Add64, 2467 load(Ity_I64, mkexpr(addr)), 2468 getIReg(regRt))); 2469 mips_load_store64(addr, new_val, old, regRd, True); 2470 break; 2471 } 2472 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */ 2473 case 0x16: { 2474 DIP("law r%u,(r%u)\n", regRd, regRs); 2475 IRTemp new_val = newTemp(Ity_I32); 2476 IRTemp old = newTemp(Ity_I32); 2477 assign(addr, getIReg(regRs)); 2478 assign(new_val, mkNarrowTo32(ty, getIReg(regRt))); 2479 assign(old, load(Ity_I32, mkexpr(addr))); 2480 mips_load_store32(addr, new_val, old, regRd, True); 2481 break; 2482 } 2483 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */ 2484 case 0x17: { 2485 DIP("lawd r%u,(r%u)\n", regRd, regRs); 2486 IRTemp new_val = newTemp(Ity_I64); 2487 IRTemp old = newTemp(Ity_I64); 2488 assign(addr, getIReg(regRs)); 2489 assign(new_val, getIReg(regRt)); 2490 assign(old, load(Ity_I64, mkexpr(addr))); 2491 mips_load_store64(addr, new_val, old, regRd, True); 2492 break; 2493 } 2494 default: 2495 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3); 2496 vex_printf("Instruction=0x%08x\n", theInstr); 2497 return False; 2498 } 2499 break; 2500 } 2501 2502 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */ 2503 case 0x28: { 2504 DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd); 2505 IRTemp t0 = newTemp(Ity_I8); 2506 2507 assign(t0, binop(Iop_Add8, 2508 mkNarrowTo8(ty, getIReg(regRs)), 2509 mkNarrowTo8(ty, getIReg(regRt)))); 2510 2511 if (mode64) 2512 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2513 unop(Iop_8Uto64, mkexpr(t0)), 2514 mkSzImm(ty, 0xFF))); 2515 else 2516 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2517 unop(Iop_8Uto32, mkexpr(t0)), 2518 mkSzImm(ty, 0xFF))); 2519 break; 2520 } 2521 2522 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */ 2523 int i, shift[5]; 2524 IRTemp mask[5]; 2525 IRTemp old = newTemp(ty); 2526 IRTemp nyu = IRTemp_INVALID; 2527 assign(old, getIReg(regRs)); 2528 DIP("pop r%u, r%u", regRd, regRs); 2529 2530 for (i = 0; i < 5; i++) { 2531 mask[i] = newTemp(ty); 2532 shift[i] = 1 << i; 2533 } 2534 if(mode64) { 2535 assign(mask[0], mkU64(0x0000000055555555)); 2536 assign(mask[1], mkU64(0x0000000033333333)); 2537 assign(mask[2], mkU64(0x000000000F0F0F0F)); 2538 assign(mask[3], mkU64(0x0000000000FF00FF)); 2539 assign(mask[4], mkU64(0x000000000000FFFF)); 2540 2541 for (i = 0; i < 5; i++) { 2542 nyu = newTemp(ty); 2543 assign(nyu, 2544 binop(Iop_Add64, 2545 binop(Iop_And64, 2546 mkexpr(old), mkexpr(mask[i])), 2547 binop(Iop_And64, 2548 binop(Iop_Shr64, 2549 mkexpr(old), mkU8(shift[i])), 2550 mkexpr(mask[i])))); 2551 old = nyu; 2552 } 2553 } else { 2554 assign(mask[0], mkU32(0x55555555)); 2555 assign(mask[1], mkU32(0x33333333)); 2556 assign(mask[2], mkU32(0x0F0F0F0F)); 2557 assign(mask[3], mkU32(0x00FF00FF)); 2558 assign(mask[4], mkU32(0x0000FFFF)); 2559 assign(old, getIReg(regRs)); 2560 2561 for (i = 0; i < 5; i++) { 2562 nyu = newTemp(ty); 2563 assign(nyu, 2564 binop(Iop_Add32, 2565 binop(Iop_And32, 2566 mkexpr(old), mkexpr(mask[i])), 2567 binop(Iop_And32, 2568 binop(Iop_Shr32, 2569 mkexpr(old), mkU8(shift[i])), 2570 mkexpr(mask[i])))); 2571 old = nyu; 2572 } 2573 } 2574 putIReg(regRd, mkexpr(nyu)); 2575 break; 2576 } 2577 2578 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */ 2579 case 0x2d: { 2580 int i, shift[6]; 2581 IRTemp mask[6]; 2582 IRTemp old = newTemp(ty); 2583 IRTemp nyu = IRTemp_INVALID; 2584 DIP("dpop r%u, r%u", regRd, regRs); 2585 2586 for (i = 0; i < 6; i++) { 2587 mask[i] = newTemp(ty); 2588 shift[i] = 1 << i; 2589 } 2590 vassert(mode64); /*Caution! Only for Mode 64*/ 2591 assign(mask[0], mkU64(0x5555555555555555ULL)); 2592 assign(mask[1], mkU64(0x3333333333333333ULL)); 2593 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL)); 2594 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL)); 2595 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL)); 2596 assign(mask[5], mkU64(0x00000000FFFFFFFFULL)); 2597 assign(old, getIReg(regRs)); 2598 for (i = 0; i < 6; i++) { 2599 nyu = newTemp(Ity_I64); 2600 assign(nyu, 2601 binop(Iop_Add64, 2602 binop(Iop_And64, 2603 mkexpr(old), mkexpr(mask[i])), 2604 binop(Iop_And64, 2605 binop(Iop_Shr64, 2606 mkexpr(old), mkU8(shift[i])), 2607 mkexpr(mask[i])))); 2608 old = nyu; 2609 } 2610 putIReg(regRd, mkexpr(nyu)); 2611 break; 2612 } 2613 2614 case 0x32: /* 5. CINS rd, rs, p, lenm1 */ 2615 DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1); 2616 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2617 mkU8(64-( lenM1+1 )))); 2618 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2619 mkU8(64-(p+lenM1+1)))); 2620 putIReg( regRt, mkexpr(tmpRt)); 2621 break; 2622 2623 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */ 2624 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1); 2625 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2626 mkU8(64-( lenM1+1 )))); 2627 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2628 mkU8(32-(p+lenM1+1)))); 2629 putIReg( regRt, mkexpr(tmpRt)); 2630 break; 2631 2632 case 0x3A: /* 3. EXTS rt, rs, p len */ 2633 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2634 size = lenM1 + 1; /* lenm1+1 */ 2635 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */ 2636 UChar rsAmt = 64 - size; /* lenm1+1 */ 2637 tmp = newTemp(Ity_I64); 2638 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 2639 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt))); 2640 break; 2641 2642 case 0x3B: /* 4. EXTS32 rt, rs, p len */ 2643 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2644 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2645 mkU8(32-(p+lenM1+1)))); 2646 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp), 2647 mkU8(64-(lenM1+1))) ); 2648 putIReg( regRt, mkexpr(tmpRt)); 2649 break; 2650 2651 case 0x2B: /* 20. SNE rd, rs, rt */ 2652 DIP("sne r%u, r%u, r%u", regRd,regRs, regRt); 2653 if (mode64) 2654 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64, 2655 getIReg(regRs), 2656 getIReg(regRt)))); 2657 else 2658 putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32, 2659 getIReg(regRs), 2660 getIReg(regRt)))); 2661 break; 2662 2663 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */ 2664 DIP("seq r%u, r%u, %d", regRd, regRs, regRt); 2665 if (mode64) 2666 putIReg(regRd, unop(Iop_1Uto64, 2667 binop(Iop_CmpEQ64, getIReg(regRs), 2668 getIReg(regRt)))); 2669 else 2670 putIReg(regRd, unop(Iop_1Uto32, 2671 binop(Iop_CmpEQ32, getIReg(regRs), 2672 getIReg(regRt)))); 2673 break; 2674 2675 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */ 2676 DIP("seqi r%u, r%u, %u", regRt, regRs, imm); 2677 if (mode64) 2678 putIReg(regRt, unop(Iop_1Uto64, 2679 binop(Iop_CmpEQ64, getIReg(regRs), 2680 mkU64(extend_s_10to64(imm))))); 2681 else 2682 putIReg(regRt, unop(Iop_1Uto32, 2683 binop(Iop_CmpEQ32, getIReg(regRs), 2684 mkU32(extend_s_10to32(imm))))); 2685 break; 2686 2687 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */ 2688 DIP("snei r%u, r%u, %u", regRt, regRs, imm); 2689 if (mode64) 2690 putIReg(regRt, unop(Iop_1Uto64, 2691 binop(Iop_CmpNE64, 2692 getIReg(regRs), 2693 mkU64(extend_s_10to64(imm))))); 2694 else 2695 putIReg(regRt, unop(Iop_1Uto32, 2696 binop(Iop_CmpNE32, 2697 getIReg(regRs), 2698 mkU32(extend_s_10to32(imm))))); 2699 break; 2700 2701 default: 2702 return False; 2703 } 2704 break; 2705 } /* opc1 0x1C ends here*/ 2706 case 0x1F: { 2707 switch(opc2) { 2708 case 0x0A: { // lx - Load indexed instructions 2709 switch (get_sa(theInstr)) { 2710 case 0x00: { // LWX rd, index(base) 2711 DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs); 2712 LOADX_STORE_PATTERN; 2713 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2714 True)); 2715 break; 2716 } 2717 case 0x04: // LHX rd, index(base) 2718 DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs); 2719 LOADX_STORE_PATTERN; 2720 if (mode64) 2721 putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16, 2722 mkexpr(t1)))); 2723 else 2724 putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16, 2725 mkexpr(t1)))); 2726 break; 2727 case 0x08: { // LDX rd, index(base) 2728 DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs); 2729 vassert(mode64); /* Currently Implemented only for n64 */ 2730 LOADX_STORE_PATTERN; 2731 putIReg(regRd, load(Ity_I64, mkexpr(t1))); 2732 break; 2733 } 2734 case 0x06: { // LBUX rd, index(base) 2735 DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs); 2736 LOADX_STORE_PATTERN; 2737 if (mode64) 2738 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8, 2739 mkexpr(t1)))); 2740 else 2741 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8, 2742 mkexpr(t1)))); 2743 break; 2744 } 2745 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON) 2746 DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs); 2747 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/ 2748 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2749 False)); 2750 break; 2751 } 2752 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON) 2753 DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs); 2754 LOADX_STORE_PATTERN; 2755 if (mode64) 2756 putIReg(regRd, 2757 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 2758 else 2759 putIReg(regRd, 2760 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 2761 break; 2762 } 2763 case 0x16: { // LBX rd, index(base) (Cavium OCTEON) 2764 DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt); 2765 LOADX_STORE_PATTERN; 2766 if (mode64) 2767 putIReg(regRd, 2768 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 2769 else 2770 putIReg(regRd, 2771 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 2772 break; 2773 } 2774 default: 2775 vex_printf("\nUnhandled LX instruction opc3 = %x\n", 2776 get_sa(theInstr)); 2777 return False; 2778 } 2779 break; 2780 } 2781 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/ 2782 break; 2783 } /* opc1 = 0x1F ends here*/ 2784 default: 2785 return False; 2786 } /* main opc1 switch ends here */ 2787 return True; 2788 } 2789 2790 /*------------------------------------------------------------*/ 2791 /*--- Disassemble a single DSP ASE instruction ---*/ 2792 /*------------------------------------------------------------*/ 2793 2794 static UInt disDSPInstr_MIPS_WRK ( UInt cins ) 2795 { 2796 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, 2797 t15, t16, t17; 2798 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask, 2799 wrdsp_mask, dsp_imm, shift; 2800 2801 opcode = get_opcode(cins); 2802 rs = get_rs(cins); 2803 rt = get_rt(cins); 2804 rd = get_rd(cins); 2805 sa = get_sa(cins); 2806 function = get_function(cins); 2807 ac = get_acNo(cins); 2808 ac_mfhilo = get_acNo_mfhilo(cins); 2809 rddsp_mask = get_rddspMask(cins); 2810 wrdsp_mask = get_wrdspMask(cins); 2811 dsp_imm = get_dspImm(cins); 2812 shift = get_shift(cins); 2813 2814 switch (opcode) { 2815 case 0x00: { /* Special */ 2816 switch (function) { 2817 case 0x10: { /* MFHI */ 2818 DIP("mfhi ac%u r%u", ac_mfhilo, rd); 2819 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo))); 2820 break; 2821 } 2822 2823 case 0x11: { /* MTHI */ 2824 DIP("mthi ac%u r%u", ac, rs); 2825 t1 = newTemp(Ity_I32); 2826 assign(t1, unop(Iop_64to32, getAcc(ac))); 2827 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1))); 2828 break; 2829 } 2830 2831 case 0x12: { /* MFLO */ 2832 DIP("mflo ac%u r%u", ac_mfhilo, rd); 2833 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo))); 2834 break; 2835 } 2836 2837 case 0x13: { /* MTLO */ 2838 DIP("mtlo ac%u r%u", ac, rs); 2839 t1 = newTemp(Ity_I32); 2840 assign(t1, unop(Iop_64HIto32, getAcc(ac))); 2841 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs))); 2842 break; 2843 } 2844 2845 case 0x18: { /* MULT */ 2846 DIP("mult ac%u r%u, r%u", ac, rs, rt); 2847 t1 = newTemp(Ity_I64); 2848 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2849 mkNarrowTo32(Ity_I32, getIReg(rt)))); 2850 putAcc(ac, mkexpr(t1)); 2851 break; 2852 } 2853 2854 case 0x19: { /* MULTU */ 2855 DIP("multu ac%u r%u, r%u", ac, rs, rt); 2856 t1 = newTemp(Ity_I64); 2857 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2858 mkNarrowTo32(Ity_I32, 2859 getIReg(rt)))); 2860 putAcc(ac, mkexpr(t1)); 2861 break; 2862 } 2863 } 2864 break; 2865 } 2866 case 0x1C: { /* Special2 */ 2867 switch (function) { 2868 case 0x00: { /* MADD */ 2869 DIP("madd ac%u, r%u, r%u", ac, rs, rt); 2870 t1 = newTemp(Ity_I64); 2871 t2 = newTemp(Ity_I64); 2872 t3 = newTemp(Ity_I64); 2873 2874 assign(t1, getAcc(ac)); 2875 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2876 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2))); 2877 2878 putAcc(ac, mkexpr(t3)); 2879 break; 2880 } 2881 case 0x01: { /* MADDU */ 2882 DIP("maddu ac%u r%u, r%u", ac, rs, rt); 2883 t1 = newTemp(Ity_I64); 2884 t2 = newTemp(Ity_I64); 2885 t3 = newTemp(Ity_I64); 2886 2887 assign(t1, getAcc(ac)); 2888 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2889 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1))); 2890 2891 putAcc(ac, mkexpr(t3)); 2892 break; 2893 } 2894 case 0x04: { /* MSUB */ 2895 DIP("msub ac%u r%u, r%u", ac, rs, rt); 2896 t1 = newTemp(Ity_I64); 2897 t2 = newTemp(Ity_I64); 2898 t3 = newTemp(Ity_I64); 2899 2900 assign(t1, getAcc(ac)); 2901 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2902 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2903 2904 putAcc(ac, mkexpr(t3)); 2905 break; 2906 } 2907 case 0x05: { /* MSUBU */ 2908 DIP("msubu ac%u r%u, r%u", ac, rs, rt); 2909 t1 = newTemp(Ity_I64); 2910 t2 = newTemp(Ity_I64); 2911 t3 = newTemp(Ity_I64); 2912 2913 assign(t1, getAcc(ac)); 2914 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2915 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2916 2917 putAcc(ac, mkexpr(t3)); 2918 break; 2919 } 2920 } 2921 break; 2922 } 2923 case 0x1F: { /* Special3 */ 2924 switch (function) { 2925 case 0x12: { /* ABSQ_S.PH */ 2926 switch (sa) { 2927 case 0x1: { /* ABSQ_S.QB */ 2928 DIP("absq_s.qb r%u, r%u", rd, rt); 2929 vassert(!mode64); 2930 t0 = newTemp(Ity_I8); 2931 t1 = newTemp(Ity_I1); 2932 t2 = newTemp(Ity_I1); 2933 t3 = newTemp(Ity_I8); 2934 t4 = newTemp(Ity_I8); 2935 t5 = newTemp(Ity_I1); 2936 t6 = newTemp(Ity_I1); 2937 t7 = newTemp(Ity_I8); 2938 t8 = newTemp(Ity_I8); 2939 t9 = newTemp(Ity_I1); 2940 t10 = newTemp(Ity_I1); 2941 t11 = newTemp(Ity_I8); 2942 t12 = newTemp(Ity_I8); 2943 t13 = newTemp(Ity_I1); 2944 t14 = newTemp(Ity_I1); 2945 t15 = newTemp(Ity_I8); 2946 t16 = newTemp(Ity_I32); 2947 t17 = newTemp(Ity_I32); 2948 2949 /* Absolute value of the rightmost byte (bits 7-0). */ 2950 /* t0 - rightmost byte. */ 2951 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt)))); 2952 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */ 2953 assign(t1, binop(Iop_CmpEQ32, 2954 unop(Iop_8Uto32, mkexpr(t0)), 2955 mkU32(0x00000080))); 2956 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 2957 assign(t2, unop(Iop_32to1, 2958 binop(Iop_Shr32, 2959 binop(Iop_And32, 2960 getIReg(rt), 2961 mkU32(0x00000080)), 2962 mkU8(0x7)))); 2963 /* t3 holds abs(t0). */ 2964 assign(t3, IRExpr_ITE(mkexpr(t1), 2965 mkU8(0x7F), 2966 IRExpr_ITE(mkexpr(t2), 2967 binop(Iop_Add8, 2968 unop(Iop_Not8, 2969 mkexpr(t0)), 2970 mkU8(0x1)), 2971 mkexpr(t0)))); 2972 2973 /* Absolute value of bits 15-8. */ 2974 /* t4 - input byte. */ 2975 assign(t4, 2976 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt)))); 2977 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */ 2978 assign(t5, binop(Iop_CmpEQ32, 2979 unop(Iop_8Uto32, mkexpr(t4)), 2980 mkU32(0x00000080))); 2981 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 2982 assign(t6, unop(Iop_32to1, 2983 binop(Iop_Shr32, 2984 binop(Iop_And32, 2985 getIReg(rt), 2986 mkU32(0x00008000)), 2987 mkU8(15)))); 2988 /* t3 holds abs(t4). */ 2989 assign(t7, IRExpr_ITE(mkexpr(t5), 2990 mkU8(0x7F), 2991 IRExpr_ITE(mkexpr(t6), 2992 binop(Iop_Add8, 2993 unop(Iop_Not8, 2994 mkexpr(t4)), 2995 mkU8(0x1)), 2996 mkexpr(t4)))); 2997 2998 /* Absolute value of bits 23-15. */ 2999 /* t8 - input byte. */ 3000 assign(t8, 3001 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt)))); 3002 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */ 3003 assign(t9, binop(Iop_CmpEQ32, 3004 unop(Iop_8Uto32, mkexpr(t8)), 3005 mkU32(0x00000080))); 3006 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */ 3007 assign(t10, unop(Iop_32to1, 3008 binop(Iop_Shr32, 3009 binop(Iop_And32, 3010 getIReg(rt), 3011 mkU32(0x00800000)), 3012 mkU8(23)))); 3013 /* t3 holds abs(t8). */ 3014 assign(t11, IRExpr_ITE(mkexpr(t9), 3015 mkU8(0x7F), 3016 IRExpr_ITE(mkexpr(t10), 3017 binop(Iop_Add8, 3018 unop(Iop_Not8, 3019 mkexpr(t8)), 3020 mkU8(0x1)), 3021 mkexpr(t8)))); 3022 3023 /* Absolute value of bits 31-24. */ 3024 /* t12 - input byte. */ 3025 assign(t12, 3026 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt)))); 3027 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */ 3028 assign(t13, binop(Iop_CmpEQ32, 3029 unop(Iop_8Uto32, mkexpr(t12)), 3030 mkU32(0x00000080))); 3031 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */ 3032 assign(t14, unop(Iop_32to1, 3033 binop(Iop_Shr32, 3034 binop(Iop_And32, 3035 getIReg(rt), 3036 mkU32(0x80000000)), 3037 mkU8(31)))); 3038 /* t15 holds abs(t12). */ 3039 assign(t15, IRExpr_ITE(mkexpr(t13), 3040 mkU8(0x7F), 3041 IRExpr_ITE(mkexpr(t14), 3042 binop(Iop_Add8, 3043 unop(Iop_Not8, 3044 mkexpr(t12)), 3045 mkU8(0x1)), 3046 mkexpr(t12)))); 3047 3048 /* t16 holds !0 if any of input bytes is 0x80 or 0 3049 otherwise. */ 3050 assign(t16, 3051 binop(Iop_Or32, 3052 binop(Iop_Or32, 3053 binop(Iop_Or32, 3054 unop(Iop_1Sto32, mkexpr(t13)), 3055 unop(Iop_1Sto32, mkexpr(t9))), 3056 unop(Iop_1Sto32, mkexpr(t5))), 3057 unop(Iop_1Sto32, mkexpr(t1)))); 3058 3059 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 3060 mkexpr(t16), 3061 mkU32(0x0)), 3062 getDSPControl(), 3063 binop(Iop_Or32, 3064 getDSPControl(), 3065 mkU32(0x00100000)))); 3066 3067 /* t17 = t15|t11|t7|t3 */ 3068 assign(t17, 3069 binop(Iop_16HLto32, 3070 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)), 3071 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3)))); 3072 3073 putIReg(rd, mkexpr(t17)); 3074 break; 3075 } 3076 case 0x2: { /* REPL.QB */ 3077 DIP("repl.qb r%u, %u", rd, dsp_imm); 3078 vassert(!mode64); 3079 3080 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) | 3081 (dsp_imm << 8) | (dsp_imm))); 3082 break; 3083 } 3084 case 0x3: { /* REPLV.QB */ 3085 DIP("replv.qb r%u, r%u", rd, rt); 3086 vassert(!mode64); 3087 t0 = newTemp(Ity_I8); 3088 3089 assign(t0, unop(Iop_32to8, 3090 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 3091 putIReg(rd, 3092 binop(Iop_16HLto32, 3093 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)), 3094 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)))); 3095 break; 3096 } 3097 case 0x4: { /* PRECEQU.PH.QBL */ 3098 DIP("precequ.ph.qbl r%u, r%u", rd, rt); 3099 vassert(!mode64); 3100 3101 putIReg(rd, binop(Iop_Or32, 3102 binop(Iop_Shr32, 3103 binop(Iop_And32, 3104 getIReg(rt), 3105 mkU32(0xff000000)), 3106 mkU8(1)), 3107 binop(Iop_Shr32, 3108 binop(Iop_And32, 3109 getIReg(rt), 3110 mkU32(0x00ff0000)), 3111 mkU8(9)))); 3112 break; 3113 } 3114 case 0x5: { /* PRECEQU.PH.QBR */ 3115 DIP("precequ.ph.qbr r%u, r%u", rd, rt); 3116 vassert(!mode64); 3117 3118 putIReg(rd, binop(Iop_Or32, 3119 binop(Iop_Shl32, 3120 binop(Iop_And32, 3121 getIReg(rt), 3122 mkU32(0x0000ff00)), 3123 mkU8(15)), 3124 binop(Iop_Shl32, 3125 binop(Iop_And32, 3126 getIReg(rt), 3127 mkU32(0x000000ff)), 3128 mkU8(7)))); 3129 break; 3130 } 3131 case 0x6: { /* PRECEQU.PH.QBLA */ 3132 DIP("precequ.ph.qbla r%u, r%u", rd, rt); 3133 vassert(!mode64); 3134 3135 putIReg(rd, binop(Iop_Or32, 3136 binop(Iop_Shr32, 3137 binop(Iop_And32, 3138 getIReg(rt), 3139 mkU32(0xff000000)), 3140 mkU8(1)), 3141 binop(Iop_Shr32, 3142 binop(Iop_And32, 3143 getIReg(rt), 3144 mkU32(0x0000ff00)), 3145 mkU8(1)))); 3146 break; 3147 } 3148 case 0x7: { /* PRECEQU.PH.QBRA */ 3149 DIP("precequ.ph.qbra r%u, r%u", rd, rt); 3150 vassert(!mode64); 3151 3152 putIReg(rd, binop(Iop_Or32, 3153 binop(Iop_Shl32, 3154 binop(Iop_And32, 3155 getIReg(rt), 3156 mkU32(0x00ff0000)), 3157 mkU8(7)), 3158 binop(Iop_Shl32, 3159 binop(Iop_And32, 3160 getIReg(rt), 3161 mkU32(0x000000ff)), 3162 mkU8(7)))); 3163 break; 3164 } 3165 case 0x9: { /* ABSQ_S.PH */ 3166 DIP("absq_s.ph r%u, r%u", rd, rt); 3167 vassert(!mode64); 3168 t0 = newTemp(Ity_I16); 3169 t1 = newTemp(Ity_I1); 3170 t2 = newTemp(Ity_I1); 3171 t3 = newTemp(Ity_I16); 3172 t4 = newTemp(Ity_I16); 3173 t5 = newTemp(Ity_I1); 3174 t6 = newTemp(Ity_I1); 3175 t7 = newTemp(Ity_I16); 3176 t8 = newTemp(Ity_I32); 3177 t9 = newTemp(Ity_I32); 3178 3179 /* t0 holds lower 16 bits of value in rt. */ 3180 assign(t0, unop(Iop_32to16, getIReg(rt))); 3181 /* t1 holds 1 if t0 is equal to 0x8000. */ 3182 assign(t1, binop(Iop_CmpEQ32, 3183 unop(Iop_16Uto32, mkexpr(t0)), 3184 mkU32(0x00008000))); 3185 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 3186 assign(t2, unop(Iop_32to1, 3187 binop(Iop_Shr32, 3188 binop(Iop_And32, 3189 getIReg(rt), 3190 mkU32(0x00008000)), 3191 mkU8(15)))); 3192 /* t3 holds abs(t0). */ 3193 assign(t3, IRExpr_ITE(mkexpr(t1), 3194 mkU16(0x7FFF), 3195 IRExpr_ITE(mkexpr(t2), 3196 binop(Iop_Add16, 3197 unop(Iop_Not16, 3198 mkexpr(t0)), 3199 mkU16(0x1)), 3200 mkexpr(t0)))); 3201 3202 /* t4 holds lower 16 bits of value in rt. */ 3203 assign(t4, unop(Iop_32HIto16, getIReg(rt))); 3204 /* t5 holds 1 if t4 is equal to 0x8000. */ 3205 assign(t5, binop(Iop_CmpEQ32, 3206 unop(Iop_16Uto32, mkexpr(t4)), 3207 mkU32(0x00008000))); 3208 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 3209 assign(t6, unop(Iop_32to1, 3210 binop(Iop_Shr32, 3211 binop(Iop_And32, 3212 getIReg(rt), 3213 mkU32(0x80000000)), 3214 mkU8(31)))); 3215 /* t7 holds abs(t4). */ 3216 assign(t7, IRExpr_ITE(mkexpr(t5), 3217 mkU16(0x7FFF), 3218 IRExpr_ITE(mkexpr(t6), 3219 binop(Iop_Add16, 3220 unop(Iop_Not16, 3221 mkexpr(t4)), 3222 mkU16(0x1)), 3223 mkexpr(t4)))); 3224 /* If any of the two input halfwords is equal 0x8000, 3225 set bit 20 in DSPControl register. */ 3226 assign(t8, binop(Iop_Or32, 3227 unop(Iop_1Sto32, mkexpr(t5)), 3228 unop(Iop_1Sto32, mkexpr(t1)))); 3229 3230 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 3231 mkexpr(t8), 3232 mkU32(0x0)), 3233 getDSPControl(), 3234 binop(Iop_Or32, 3235 getDSPControl(), 3236 mkU32(0x00100000)))); 3237 3238 /* t9 = t7|t3 */ 3239 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 3240 3241 putIReg(rd, mkexpr(t9)); 3242 break; 3243 } 3244 case 0xA: { /* REPL.PH */ 3245 DIP("repl.ph r%u, %u", rd, dsp_imm); 3246 vassert(!mode64); 3247 UShort immediate = extend_s_10to16(dsp_imm); 3248 3249 putIReg(rd, mkU32(immediate << 16 | immediate)); 3250 break; 3251 } 3252 case 0xB: { /* REPLV.PH */ 3253 DIP("replv.ph r%u, r%u", rd, rt); 3254 vassert(!mode64); 3255 3256 putIReg(rd, binop(Iop_16HLto32, 3257 unop(Iop_32to16, getIReg(rt)), 3258 unop(Iop_32to16, getIReg(rt)))); 3259 break; 3260 } 3261 case 0xC: { /* PRECEQ.W.PHL */ 3262 DIP("preceq.w.phl r%u, r%u", rd, rt); 3263 vassert(!mode64); 3264 putIReg(rd, binop(Iop_And32, 3265 getIReg(rt), 3266 mkU32(0xffff0000))); 3267 break; 3268 } 3269 case 0xD: { /* PRECEQ.W.PHR */ 3270 DIP("preceq.w.phr r%u, r%u", rd, rt); 3271 vassert(!mode64); 3272 putIReg(rd, binop(Iop_16HLto32, 3273 unop(Iop_32to16, getIReg(rt)), 3274 mkU16(0x0))); 3275 break; 3276 } 3277 case 0x11: { /* ABSQ_S.W */ 3278 DIP("absq_s.w r%u, r%u", rd, rt); 3279 vassert(!mode64); 3280 t0 = newTemp(Ity_I1); 3281 t1 = newTemp(Ity_I1); 3282 t2 = newTemp(Ity_I32); 3283 3284 assign(t0, 3285 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 3286 3287 putDSPControl(IRExpr_ITE(mkexpr(t0), 3288 binop(Iop_Or32, 3289 getDSPControl(), 3290 mkU32(0x00100000)), 3291 getDSPControl())); 3292 3293 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0))); 3294 3295 assign(t2, IRExpr_ITE(mkexpr(t0), 3296 mkU32(0x7FFFFFFF), 3297 IRExpr_ITE(mkexpr(t1), 3298 binop(Iop_Add32, 3299 unop(Iop_Not32, 3300 getIReg(rt)), 3301 mkU32(0x1)), 3302 getIReg(rt)))); 3303 putIReg(rd, mkexpr(t2)); 3304 break; 3305 } 3306 case 0x1B: { /* BITREV */ 3307 DIP("bitrev r%u, r%u", rd, rt); 3308 vassert(!mode64); 3309 /* 32bit reversal as seen on Bit Twiddling Hacks site 3310 http://graphics.stanford.edu/~seander/bithacks.html 3311 section ReverseParallel */ 3312 t1 = newTemp(Ity_I32); 3313 t2 = newTemp(Ity_I32); 3314 t3 = newTemp(Ity_I32); 3315 t4 = newTemp(Ity_I32); 3316 t5 = newTemp(Ity_I32); 3317 3318 assign(t1, binop(Iop_Or32, 3319 binop(Iop_Shr32, 3320 binop(Iop_And32, 3321 getIReg(rt), 3322 mkU32(0xaaaaaaaa)), 3323 mkU8(0x1)), 3324 binop(Iop_Shl32, 3325 binop(Iop_And32, 3326 getIReg(rt), 3327 mkU32(0x55555555)), 3328 mkU8(0x1)))); 3329 assign(t2, binop(Iop_Or32, 3330 binop(Iop_Shr32, 3331 binop(Iop_And32, 3332 mkexpr(t1), 3333 mkU32(0xcccccccc)), 3334 mkU8(0x2)), 3335 binop(Iop_Shl32, 3336 binop(Iop_And32, 3337 mkexpr(t1), 3338 mkU32(0x33333333)), 3339 mkU8(0x2)))); 3340 assign(t3, binop(Iop_Or32, 3341 binop(Iop_Shr32, 3342 binop(Iop_And32, 3343 mkexpr(t2), 3344 mkU32(0xf0f0f0f0)), 3345 mkU8(0x4)), 3346 binop(Iop_Shl32, 3347 binop(Iop_And32, 3348 mkexpr(t2), 3349 mkU32(0x0f0f0f0f)), 3350 mkU8(0x4)))); 3351 assign(t4, binop(Iop_Or32, 3352 binop(Iop_Shr32, 3353 binop(Iop_And32, 3354 mkexpr(t3), 3355 mkU32(0xff00ff00)), 3356 mkU8(0x8)), 3357 binop(Iop_Shl32, 3358 binop(Iop_And32, 3359 mkexpr(t3), 3360 mkU32(0x00ff00ff)), 3361 mkU8(0x8)))); 3362 assign(t5, binop(Iop_Or32, 3363 binop(Iop_Shr32, 3364 mkexpr(t4), 3365 mkU8(0x10)), 3366 binop(Iop_Shl32, 3367 mkexpr(t4), 3368 mkU8(0x10)))); 3369 putIReg(rd, binop(Iop_Shr32, 3370 mkexpr(t5), 3371 mkU8(16))); 3372 break; 3373 } 3374 case 0x1C: { /* PRECEU.PH.QBL */ 3375 DIP("preceu.ph.qbl r%u, r%u", rd, rt); 3376 vassert(!mode64); 3377 3378 putIReg(rd, binop(Iop_Or32, 3379 binop(Iop_Shr32, 3380 binop(Iop_And32, 3381 getIReg(rt), 3382 mkU32(0xff000000)), 3383 mkU8(8)), 3384 binop(Iop_Shr32, 3385 binop(Iop_And32, 3386 getIReg(rt), 3387 mkU32(0x00ff0000)), 3388 mkU8(16)))); 3389 break; 3390 } 3391 case 0x1E: { /* PRECEU.PH.QBLA */ 3392 DIP("preceu.ph.qbla r%u, r%u", rd, rt); 3393 vassert(!mode64); 3394 3395 putIReg(rd, binop(Iop_Or32, 3396 binop(Iop_Shr32, 3397 binop(Iop_And32, 3398 getIReg(rt), 3399 mkU32(0xff000000)), 3400 mkU8(8)), 3401 binop(Iop_Shr32, 3402 binop(Iop_And32, 3403 getIReg(rt), 3404 mkU32(0x0000ff00)), 3405 mkU8(8)))); 3406 break; 3407 } 3408 case 0x1D: { /* PRECEU.PH.QBR */ 3409 DIP("preceu.ph.qbr r%u, r%u", rd, rt); 3410 vassert(!mode64); 3411 3412 putIReg(rd, binop(Iop_Or32, 3413 binop(Iop_Shl32, 3414 binop(Iop_And32, 3415 getIReg(rt), 3416 mkU32(0x0000ff00)), 3417 mkU8(8)), 3418 binop(Iop_And32, 3419 getIReg(rt), 3420 mkU32(0x000000ff)))); 3421 break; 3422 } 3423 case 0x1F: { /* PRECEU.PH.QBRA */ 3424 DIP("preceu.ph.qbra r%u, r%u", rd, rt); 3425 vassert(!mode64); 3426 3427 putIReg(rd, binop(Iop_Or32, 3428 binop(Iop_And32, 3429 getIReg(rt), 3430 mkU32(0x00ff0000)), 3431 binop(Iop_And32, 3432 getIReg(rt), 3433 mkU32(0x000000ff)))); 3434 break; 3435 } 3436 default: 3437 return -1; 3438 } 3439 break; /* end of ABSQ_S.PH */ 3440 } 3441 case 0x38: { /* EXTR.W */ 3442 switch(sa) { 3443 case 0x0: { /* EXTR.W */ 3444 DIP("extr.w r%u, ac%u, %u", rt, ac, rs); 3445 vassert(!mode64); 3446 t0 = newTemp(Ity_I64); 3447 t1 = newTemp(Ity_I64); 3448 t2 = newTemp(Ity_I32); 3449 t3 = newTemp(Ity_I1); 3450 t4 = newTemp(Ity_I1); 3451 t5 = newTemp(Ity_I1); 3452 t6 = newTemp(Ity_I1); 3453 t7 = newTemp(Ity_I32); 3454 t8 = newTemp(Ity_I64); 3455 t9 = newTemp(Ity_I64); 3456 t10 = newTemp(Ity_I1); 3457 t11 = newTemp(Ity_I1); 3458 t12 = newTemp(Ity_I1); 3459 t13 = newTemp(Ity_I1); 3460 t14 = newTemp(Ity_I32); 3461 3462 assign(t0, getAcc(ac)); 3463 if (0 == rs) { 3464 assign(t1, mkexpr(t0)); 3465 } else { 3466 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 3467 } 3468 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3469 assign(t3, binop(Iop_CmpNE32, 3470 unop(Iop_64HIto32, 3471 mkexpr(t1)), 3472 mkU32(0))); 3473 assign(t4, binop(Iop_CmpNE32, 3474 binop(Iop_And32, 3475 unop(Iop_64to32, 3476 mkexpr(t1)), 3477 mkU32(0x80000000)), 3478 mkU32(0))); 3479 /* Check if bits 63..31 of the result in t1 aren't 3480 0x1ffffffff. */ 3481 assign(t5, binop(Iop_CmpNE32, 3482 unop(Iop_64HIto32, 3483 mkexpr(t1)), 3484 mkU32(0xffffffff))); 3485 assign(t6, binop(Iop_CmpNE32, 3486 binop(Iop_And32, 3487 unop(Iop_64to32, 3488 mkexpr(t1)), 3489 mkU32(0x80000000)), 3490 mkU32(0x80000000))); 3491 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3492 control register. */ 3493 assign(t7, binop(Iop_And32, 3494 binop(Iop_Or32, 3495 unop(Iop_1Sto32, mkexpr(t3)), 3496 unop(Iop_1Sto32, mkexpr(t4))), 3497 binop(Iop_Or32, 3498 unop(Iop_1Sto32, mkexpr(t5)), 3499 unop(Iop_1Sto32, mkexpr(t6))))); 3500 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3501 mkexpr(t7), 3502 mkU32(0)), 3503 binop(Iop_Or32, 3504 getDSPControl(), 3505 mkU32(0x00800000)), 3506 getDSPControl())); 3507 3508 /* If the last discarded bit is 1, there would be carry 3509 when rounding, otherwise there wouldn't. We use that 3510 fact and just add the value of the last discarded bit 3511 to the least sifgnificant bit of the shifted value 3512 from acc. */ 3513 if (0 == rs) { 3514 assign(t8, mkU64(0x0ULL)); 3515 } else { 3516 assign(t8, binop(Iop_And64, 3517 binop(Iop_Shr64, 3518 mkexpr(t0), 3519 mkU8(rs-1)), 3520 mkU64(0x1ULL))); 3521 } 3522 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3523 3524 /* Repeat previous steps for the rounded value. */ 3525 assign(t10, binop(Iop_CmpNE32, 3526 unop(Iop_64HIto32, 3527 mkexpr(t9)), 3528 mkU32(0))); 3529 assign(t11, binop(Iop_CmpNE32, 3530 binop(Iop_And32, 3531 unop(Iop_64to32, 3532 mkexpr(t9)), 3533 mkU32(0x80000000)), 3534 mkU32(0))); 3535 3536 assign(t12, binop(Iop_CmpNE32, 3537 unop(Iop_64HIto32, 3538 mkexpr(t9)), 3539 mkU32(0xffffffff))); 3540 assign(t13, binop(Iop_CmpNE32, 3541 binop(Iop_And32, 3542 unop(Iop_64to32, 3543 mkexpr(t9)), 3544 mkU32(0x80000000)), 3545 mkU32(0x80000000))); 3546 3547 assign(t14, binop(Iop_And32, 3548 binop(Iop_Or32, 3549 unop(Iop_1Sto32, mkexpr(t10)), 3550 unop(Iop_1Sto32, mkexpr(t11))), 3551 binop(Iop_Or32, 3552 unop(Iop_1Sto32, mkexpr(t12)), 3553 unop(Iop_1Sto32, mkexpr(t13))))); 3554 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3555 mkexpr(t14), 3556 mkU32(0)), 3557 binop(Iop_Or32, 3558 getDSPControl(), 3559 mkU32(0x00800000)), 3560 getDSPControl())); 3561 if (0 == rs) { 3562 putIReg(rt, unop(Iop_64to32, mkexpr(t0))); 3563 } else { 3564 putIReg(rt, unop(Iop_64to32, mkexpr(t1))); 3565 } 3566 break; 3567 } 3568 case 0x1: { /* EXTRV.W */ 3569 DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs); 3570 vassert(!mode64); 3571 t0 = newTemp(Ity_I64); 3572 t1 = newTemp(Ity_I64); 3573 t2 = newTemp(Ity_I32); 3574 t3 = newTemp(Ity_I1); 3575 t4 = newTemp(Ity_I1); 3576 t5 = newTemp(Ity_I1); 3577 t6 = newTemp(Ity_I1); 3578 t7 = newTemp(Ity_I32); 3579 t8 = newTemp(Ity_I64); 3580 t9 = newTemp(Ity_I64); 3581 t10 = newTemp(Ity_I1); 3582 t11 = newTemp(Ity_I1); 3583 t12 = newTemp(Ity_I1); 3584 t13 = newTemp(Ity_I1); 3585 t14 = newTemp(Ity_I32); 3586 t15 = newTemp(Ity_I8); 3587 3588 assign(t15, unop(Iop_32to8, 3589 binop(Iop_And32, 3590 getIReg(rs), 3591 mkU32(0x1f)))); 3592 assign(t0, getAcc(ac)); 3593 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3594 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 3595 unop(Iop_8Uto32, 3596 mkexpr(t15)), 3597 mkU32(0)), 3598 unop(Iop_64to32, mkexpr(t0)), 3599 unop(Iop_64to32, mkexpr(t1)))); 3600 3601 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3602 assign(t3, binop(Iop_CmpNE32, 3603 unop(Iop_64HIto32, 3604 mkexpr(t1)), 3605 mkU32(0))); 3606 assign(t4, binop(Iop_CmpNE32, 3607 binop(Iop_And32, 3608 unop(Iop_64to32, 3609 mkexpr(t1)), 3610 mkU32(0x80000000)), 3611 mkU32(0))); 3612 /* Check if bits 63..31 of the result in t1 aren't 3613 0x1ffffffff. */ 3614 assign(t5, binop(Iop_CmpNE32, 3615 unop(Iop_64HIto32, 3616 mkexpr(t1)), 3617 mkU32(0xffffffff))); 3618 assign(t6, binop(Iop_CmpNE32, 3619 binop(Iop_And32, 3620 unop(Iop_64to32, 3621 mkexpr(t1)), 3622 mkU32(0x80000000)), 3623 mkU32(0x80000000))); 3624 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3625 control register. */ 3626 assign(t7, binop(Iop_And32, 3627 binop(Iop_Or32, 3628 unop(Iop_1Sto32, mkexpr(t3)), 3629 unop(Iop_1Sto32, mkexpr(t4))), 3630 binop(Iop_Or32, 3631 unop(Iop_1Sto32, mkexpr(t5)), 3632 unop(Iop_1Sto32, mkexpr(t6))))); 3633 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3634 mkexpr(t7), 3635 mkU32(0)), 3636 binop(Iop_Or32, 3637 getDSPControl(), 3638 mkU32(0x00800000)), 3639 getDSPControl())); 3640 3641 /* If the last discarded bit is 1, there would be carry 3642 when rounding, otherwise there wouldn't. We use that 3643 fact and just add the value of the last discarded bit 3644 to the least sifgnificant bit of the shifted value 3645 from acc. */ 3646 assign(t8, 3647 IRExpr_ITE(binop(Iop_CmpEQ32, 3648 unop(Iop_8Uto32, 3649 mkexpr(t15)), 3650 mkU32(0)), 3651 mkU64(0x0ULL), 3652 binop(Iop_And64, 3653 binop(Iop_Shr64, 3654 mkexpr(t0), 3655 unop(Iop_32to8, 3656 binop(Iop_Sub32, 3657 unop(Iop_8Uto32, 3658 mkexpr(t15)), 3659 mkU32(1)))), 3660 mkU64(0x1ULL)))); 3661 3662 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3663 3664 /* Repeat previous steps for the rounded value. */ 3665 assign(t10, binop(Iop_CmpNE32, 3666 unop(Iop_64HIto32, 3667 mkexpr(t9)), 3668 mkU32(0))); 3669 assign(t11, binop(Iop_CmpNE32, 3670 binop(Iop_And32, 3671 unop(Iop_64to32, 3672 mkexpr(t9)), 3673 mkU32(0x80000000)), 3674 mkU32(0))); 3675 3676 assign(t12, binop(Iop_CmpNE32, 3677 unop(Iop_64HIto32, 3678 mkexpr(t9)), 3679 mkU32(0xffffffff))); 3680 assign(t13, binop(Iop_CmpNE32, 3681 binop(Iop_And32, 3682 unop(Iop_64to32, 3683 mkexpr(t9)), 3684 mkU32(0x80000000)), 3685 mkU32(0x80000000))); 3686 3687 assign(t14, binop(Iop_And32, 3688 binop(Iop_Or32, 3689 unop(Iop_1Sto32, mkexpr(t10)), 3690 unop(Iop_1Sto32, mkexpr(t11))), 3691 binop(Iop_Or32, 3692 unop(Iop_1Sto32, mkexpr(t12)), 3693 unop(Iop_1Sto32, mkexpr(t13))))); 3694 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3695 mkexpr(t14), 3696 mkU32(0)), 3697 binop(Iop_Or32, 3698 getDSPControl(), 3699 mkU32(0x00800000)), 3700 getDSPControl())); 3701 break; 3702 } 3703 case 0x2: { /* EXTP */ 3704 DIP("extp r%u, ac%u, %u", rt, ac, rs); 3705 vassert(!mode64); 3706 t0 = newTemp(Ity_I64); 3707 t1 = newTemp(Ity_I32); 3708 t2 = newTemp(Ity_I1); 3709 t3 = newTemp(Ity_I1); 3710 t4 = newTemp(Ity_I8); 3711 t5 = newTemp(Ity_I64); 3712 t6 = newTemp(Ity_I64); 3713 t7 = newTemp(Ity_I32); 3714 3715 assign(t0, getAcc(ac)); 3716 /* Extract pos field of DSPControl register. */ 3717 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3718 3719 /* Check if (pos - size) >= 0 [size <= pos] 3720 if (pos < size) 3721 put 1 to EFI field of DSPControl register 3722 else 3723 extract bits from acc and put 0 to EFI field of 3724 DSPCtrl */ 3725 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 3726 3727 putDSPControl(IRExpr_ITE(mkexpr(t2), 3728 binop(Iop_Or32, 3729 binop(Iop_And32, 3730 getDSPControl(), 3731 mkU32(0xffffbfff)), 3732 mkU32(0x4000)), 3733 binop(Iop_And32, 3734 getDSPControl(), 3735 mkU32(0xffffbfff)))); 3736 3737 /* If pos <= 31, shift right the value from the acc 3738 (pos-size) times and take (size+1) bits from the least 3739 significant positions. Otherwise, shift left the value 3740 (63-pos) times, take (size+1) bits from the most 3741 significant positions and shift right (31-size) times.*/ 3742 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3743 3744 assign(t4, 3745 IRExpr_ITE(mkexpr(t3), 3746 unop(Iop_32to8, 3747 binop(Iop_Sub32, 3748 mkexpr(t1), mkU32(rs))), 3749 unop(Iop_32to8, 3750 binop(Iop_Sub32, 3751 mkU32(63), mkexpr(t1))))); 3752 3753 assign(t5, IRExpr_ITE(mkexpr(t3), 3754 binop(Iop_Shr64, 3755 mkexpr(t0), mkexpr(t4)), 3756 binop(Iop_Shl64, 3757 mkexpr(t0), mkexpr(t4)))); 3758 3759 /* t6 holds a mask for bit extraction */ 3760 assign(t6, 3761 IRExpr_ITE(mkexpr(t3), 3762 unop(Iop_Not64, 3763 binop(Iop_Shl64, 3764 mkU64(0xffffffffffffffffULL), 3765 mkU8(rs+1))), 3766 unop(Iop_Not64, 3767 binop(Iop_Shr64, 3768 mkU64(0xffffffffffffffffULL), 3769 mkU8(rs+1))))); 3770 3771 assign(t7, IRExpr_ITE(mkexpr(t3), 3772 unop(Iop_64to32, 3773 binop(Iop_And64, 3774 mkexpr(t5), 3775 mkexpr(t6))), 3776 binop(Iop_Shr32, 3777 unop(Iop_64HIto32, 3778 binop(Iop_And64, 3779 mkexpr(t5), 3780 mkexpr(t6))), 3781 mkU8(31-rs)))); 3782 3783 putIReg(rt, mkexpr(t7)); 3784 break; 3785 } 3786 case 0x3: { /* EXTPV */ 3787 DIP("extpv r%u, ac%u, r%u", rt, ac, rs); 3788 vassert(!mode64); 3789 t0 = newTemp(Ity_I64); 3790 t1 = newTemp(Ity_I32); 3791 t2 = newTemp(Ity_I1); 3792 t3 = newTemp(Ity_I1); 3793 t4 = newTemp(Ity_I8); 3794 t5 = newTemp(Ity_I64); 3795 t6 = newTemp(Ity_I64); 3796 t7 = newTemp(Ity_I32); 3797 t8 = newTemp(Ity_I32); 3798 3799 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 3800 assign(t0, getAcc(ac)); 3801 /* Extract pos field of DSPControl register. */ 3802 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3803 3804 /* Check if (pos - size) >= 0 [size <= pos] 3805 if (pos < size) 3806 put 1 to EFI field of DSPControl register 3807 else 3808 extract bits from acc and put 0 to EFI field of 3809 DSPCtrl */ 3810 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 3811 3812 putDSPControl(IRExpr_ITE(mkexpr(t2), 3813 binop(Iop_Or32, 3814 binop(Iop_And32, 3815 getDSPControl(), 3816 mkU32(0xffffbfff)), 3817 mkU32(0x4000)), 3818 binop(Iop_And32, 3819 getDSPControl(), 3820 mkU32(0xffffbfff)))); 3821 3822 /* If pos <= 31, shift right the value from the acc 3823 (pos-size) times and take (size+1) bits from the least 3824 significant positions. Otherwise, shift left the value 3825 (63-pos) times, take (size+1) bits from the most 3826 significant positions and shift right (31-size) 3827 times. */ 3828 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3829 3830 assign(t4, 3831 IRExpr_ITE(mkexpr(t3), 3832 unop(Iop_32to8, 3833 binop(Iop_Sub32, 3834 mkexpr(t1), mkexpr(t8))), 3835 unop(Iop_32to8, 3836 binop(Iop_Sub32, 3837 mkU32(63), mkexpr(t1))))); 3838 3839 assign(t5, IRExpr_ITE(mkexpr(t3), 3840 binop(Iop_Shr64, 3841 mkexpr(t0), mkexpr(t4)), 3842 binop(Iop_Shl64, 3843 mkexpr(t0), mkexpr(t4)))); 3844 3845 /* t6 holds a mask for bit extraction. */ 3846 assign(t6, 3847 IRExpr_ITE(mkexpr(t3), 3848 unop(Iop_Not64, 3849 binop(Iop_Shl64, 3850 mkU64(0xffffffffffffffffULL), 3851 unop(Iop_32to8, 3852 binop(Iop_Add32, 3853 mkexpr(t8), 3854 mkU32(1))))), 3855 unop(Iop_Not64, 3856 binop(Iop_Shr64, 3857 mkU64(0xffffffffffffffffULL), 3858 unop(Iop_32to8, 3859 binop(Iop_Add32, 3860 mkexpr(t8), 3861 mkU32(1))))))); 3862 3863 assign(t7, IRExpr_ITE(mkexpr(t3), 3864 unop(Iop_64to32, 3865 binop(Iop_And64, 3866 mkexpr(t5), 3867 mkexpr(t6))), 3868 binop(Iop_Shr32, 3869 unop(Iop_64HIto32, 3870 binop(Iop_And64, 3871 mkexpr(t5), 3872 mkexpr(t6))), 3873 unop(Iop_32to8, 3874 binop(Iop_Sub32, 3875 mkU32(31), 3876 mkexpr(t8)))))); 3877 3878 putIReg(rt, mkexpr(t7)); 3879 break; 3880 } 3881 case 0x4: { /* EXTR_R.W */ 3882 DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs); 3883 vassert(!mode64); 3884 t0 = newTemp(Ity_I64); 3885 t1 = newTemp(Ity_I64); 3886 t2 = newTemp(Ity_I32); 3887 t3 = newTemp(Ity_I1); 3888 t4 = newTemp(Ity_I1); 3889 t5 = newTemp(Ity_I1); 3890 t6 = newTemp(Ity_I1); 3891 t7 = newTemp(Ity_I32); 3892 t8 = newTemp(Ity_I64); 3893 t9 = newTemp(Ity_I64); 3894 t10 = newTemp(Ity_I1); 3895 t11 = newTemp(Ity_I1); 3896 t12 = newTemp(Ity_I1); 3897 t13 = newTemp(Ity_I1); 3898 t14 = newTemp(Ity_I32); 3899 t15 = newTemp(Ity_I64); 3900 t16 = newTemp(Ity_I1); 3901 3902 assign(t0, getAcc(ac)); 3903 assign(t16, binop(Iop_CmpEQ32, 3904 mkU32(rs), 3905 mkU32(0))); 3906 assign(t1, IRExpr_ITE(mkexpr(t16), 3907 mkexpr(t0), 3908 binop(Iop_Sar64, 3909 mkexpr(t0), 3910 mkU8(rs)))); 3911 /* If the last discarded bit is 1, there would be carry 3912 when rounding, otherwise there wouldn't. We use that 3913 fact and just add the value of the last discarded bit 3914 to the least significant bit of the shifted value 3915 from acc. */ 3916 assign(t15, binop(Iop_Shr64, 3917 mkexpr(t0), 3918 unop(Iop_32to8, 3919 binop(Iop_Sub32, 3920 binop(Iop_And32, 3921 mkU32(rs), 3922 mkU32(0x1f)), 3923 mkU32(1))))); 3924 3925 assign(t8, 3926 IRExpr_ITE(mkexpr(t16), 3927 mkU64(0x0ULL), 3928 binop(Iop_And64, 3929 mkexpr(t15), 3930 mkU64(0x0000000000000001ULL)))); 3931 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3932 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 3933 3934 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3935 assign(t3, binop(Iop_CmpNE32, 3936 unop(Iop_64HIto32, 3937 mkexpr(t1)), 3938 mkU32(0))); 3939 assign(t4, binop(Iop_CmpNE32, 3940 binop(Iop_And32, 3941 unop(Iop_64to32, 3942 mkexpr(t1)), 3943 mkU32(0x80000000)), 3944 mkU32(0))); 3945 3946 /* Check if bits 63..31 of the result in t1 aren't 3947 0x1ffffffff. */ 3948 assign(t5, binop(Iop_CmpNE32, 3949 unop(Iop_64HIto32, 3950 mkexpr(t1)), 3951 mkU32(0xffffffff))); 3952 assign(t6, binop(Iop_CmpNE32, 3953 binop(Iop_And32, 3954 unop(Iop_64to32, 3955 mkexpr(t1)), 3956 mkU32(0x80000000)), 3957 mkU32(0x80000000))); 3958 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3959 control register. */ 3960 assign(t7, binop(Iop_And32, 3961 binop(Iop_Or32, 3962 unop(Iop_1Sto32, mkexpr(t3)), 3963 unop(Iop_1Sto32, mkexpr(t4))), 3964 binop(Iop_Or32, 3965 unop(Iop_1Sto32, mkexpr(t5)), 3966 unop(Iop_1Sto32, mkexpr(t6))))); 3967 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3968 mkexpr(t7), 3969 mkU32(0)), 3970 binop(Iop_Or32, 3971 getDSPControl(), 3972 mkU32(0x00800000)), 3973 getDSPControl())); 3974 3975 /* Repeat previous steps for the rounded value. */ 3976 assign(t10, binop(Iop_CmpNE32, 3977 unop(Iop_64HIto32, 3978 mkexpr(t9)), 3979 mkU32(0))); 3980 assign(t11, binop(Iop_CmpNE32, 3981 binop(Iop_And32, 3982 unop(Iop_64to32, 3983 mkexpr(t9)), 3984 mkU32(0x80000000)), 3985 mkU32(0))); 3986 3987 assign(t12, binop(Iop_CmpNE32, 3988 unop(Iop_64HIto32, 3989 mkexpr(t9)), 3990 mkU32(0xffffffff))); 3991 assign(t13, binop(Iop_CmpNE32, 3992 binop(Iop_And32, 3993 unop(Iop_64to32, 3994 mkexpr(t9)), 3995 mkU32(0x80000000)), 3996 mkU32(0x80000000))); 3997 3998 assign(t14, binop(Iop_And32, 3999 binop(Iop_Or32, 4000 unop(Iop_1Sto32, mkexpr(t10)), 4001 unop(Iop_1Sto32, mkexpr(t11))), 4002 binop(Iop_Or32, 4003 unop(Iop_1Sto32, mkexpr(t12)), 4004 unop(Iop_1Sto32, mkexpr(t13))))); 4005 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4006 mkexpr(t14), 4007 mkU32(0)), 4008 binop(Iop_Or32, 4009 getDSPControl(), 4010 mkU32(0x00800000)), 4011 getDSPControl())); 4012 break; 4013 } 4014 case 0x5: { /* EXTRV_R.W */ 4015 DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs); 4016 vassert(!mode64); 4017 t0 = newTemp(Ity_I64); 4018 t1 = newTemp(Ity_I64); 4019 t2 = newTemp(Ity_I32); 4020 t3 = newTemp(Ity_I1); 4021 t4 = newTemp(Ity_I1); 4022 t5 = newTemp(Ity_I1); 4023 t6 = newTemp(Ity_I1); 4024 t7 = newTemp(Ity_I32); 4025 t8 = newTemp(Ity_I64); 4026 t9 = newTemp(Ity_I64); 4027 t10 = newTemp(Ity_I1); 4028 t11 = newTemp(Ity_I1); 4029 t12 = newTemp(Ity_I1); 4030 t13 = newTemp(Ity_I1); 4031 t14 = newTemp(Ity_I32); 4032 t15 = newTemp(Ity_I8); 4033 4034 assign(t15, unop(Iop_32to8, 4035 binop(Iop_And32, 4036 getIReg(rs), 4037 mkU32(0x1f)))); 4038 assign(t0, getAcc(ac)); 4039 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 4040 4041 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4042 assign(t3, binop(Iop_CmpNE32, 4043 unop(Iop_64HIto32, 4044 mkexpr(t1)), 4045 mkU32(0))); 4046 assign(t4, binop(Iop_CmpNE32, 4047 binop(Iop_And32, 4048 unop(Iop_64to32, 4049 mkexpr(t1)), 4050 mkU32(0x80000000)), 4051 mkU32(0))); 4052 /* Check if bits 63..31 of the result in t1 aren't 4053 0x1ffffffff. */ 4054 assign(t5, binop(Iop_CmpNE32, 4055 unop(Iop_64HIto32, 4056 mkexpr(t1)), 4057 mkU32(0xffffffff))); 4058 assign(t6, binop(Iop_CmpNE32, 4059 binop(Iop_And32, 4060 unop(Iop_64to32, 4061 mkexpr(t1)), 4062 mkU32(0x80000000)), 4063 mkU32(0x80000000))); 4064 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4065 control register. */ 4066 assign(t7, binop(Iop_And32, 4067 binop(Iop_Or32, 4068 unop(Iop_1Sto32, mkexpr(t3)), 4069 unop(Iop_1Sto32, mkexpr(t4))), 4070 binop(Iop_Or32, 4071 unop(Iop_1Sto32, mkexpr(t5)), 4072 unop(Iop_1Sto32, mkexpr(t6))))); 4073 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4074 mkexpr(t7), 4075 mkU32(0)), 4076 binop(Iop_Or32, 4077 getDSPControl(), 4078 mkU32(0x00800000)), 4079 getDSPControl())); 4080 4081 /* If the last discarded bit is 1, there would be carry 4082 when rounding, otherwise there wouldn't. We use that 4083 fact and just add the value of the last discarded bit 4084 to the least sifgnificant bit of the shifted value 4085 from acc. */ 4086 assign(t8, 4087 IRExpr_ITE(binop(Iop_CmpEQ32, 4088 unop(Iop_8Uto32, 4089 mkexpr(t15)), 4090 mkU32(0)), 4091 mkU64(0x0ULL), 4092 binop(Iop_And64, 4093 binop(Iop_Shr64, 4094 mkexpr(t0), 4095 unop(Iop_32to8, 4096 binop(Iop_Sub32, 4097 unop(Iop_8Uto32, 4098 mkexpr(t15)), 4099 mkU32(1)))), 4100 mkU64(0x1ULL)))); 4101 4102 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4103 /* Put rounded value in destination register. */ 4104 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 4105 4106 /* Repeat previous steps for the rounded value. */ 4107 assign(t10, binop(Iop_CmpNE32, 4108 unop(Iop_64HIto32, 4109 mkexpr(t9)), 4110 mkU32(0))); 4111 assign(t11, binop(Iop_CmpNE32, 4112 binop(Iop_And32, 4113 unop(Iop_64to32, 4114 mkexpr(t9)), 4115 mkU32(0x80000000)), 4116 mkU32(0))); 4117 4118 assign(t12, binop(Iop_CmpNE32, 4119 unop(Iop_64HIto32, 4120 mkexpr(t9)), 4121 mkU32(0xffffffff))); 4122 assign(t13, binop(Iop_CmpNE32, 4123 binop(Iop_And32, 4124 unop(Iop_64to32, 4125 mkexpr(t9)), 4126 mkU32(0x80000000)), 4127 mkU32(0x80000000))); 4128 4129 assign(t14, binop(Iop_And32, 4130 binop(Iop_Or32, 4131 unop(Iop_1Sto32, mkexpr(t10)), 4132 unop(Iop_1Sto32, mkexpr(t11))), 4133 binop(Iop_Or32, 4134 unop(Iop_1Sto32, mkexpr(t12)), 4135 unop(Iop_1Sto32, mkexpr(t13))))); 4136 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4137 mkexpr(t14), 4138 mkU32(0)), 4139 binop(Iop_Or32, 4140 getDSPControl(), 4141 mkU32(0x00800000)), 4142 getDSPControl())); 4143 break; 4144 } 4145 case 0x6: { /* EXTR_RS.W */ 4146 DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs); 4147 vassert(!mode64); 4148 t0 = newTemp(Ity_I64); 4149 t1 = newTemp(Ity_I64); 4150 t2 = newTemp(Ity_I32); 4151 t3 = newTemp(Ity_I1); 4152 t4 = newTemp(Ity_I1); 4153 t5 = newTemp(Ity_I1); 4154 t6 = newTemp(Ity_I1); 4155 t7 = newTemp(Ity_I32); 4156 t8 = newTemp(Ity_I64); 4157 t9 = newTemp(Ity_I64); 4158 t10 = newTemp(Ity_I1); 4159 t11 = newTemp(Ity_I1); 4160 t12 = newTemp(Ity_I1); 4161 t13 = newTemp(Ity_I1); 4162 t14 = newTemp(Ity_I32); 4163 t16 = newTemp(Ity_I32); 4164 4165 assign(t0, getAcc(ac)); 4166 if (0 == rs) { 4167 assign(t1, mkexpr(t0)); 4168 } else { 4169 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4170 } 4171 4172 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4173 assign(t3, binop(Iop_CmpNE32, 4174 unop(Iop_64HIto32, 4175 mkexpr(t1)), 4176 mkU32(0))); 4177 assign(t4, binop(Iop_CmpNE32, 4178 binop(Iop_And32, 4179 unop(Iop_64to32, 4180 mkexpr(t1)), 4181 mkU32(0x80000000)), 4182 mkU32(0))); 4183 /* Check if bits 63..31 of the result in t1 aren't 4184 0x1ffffffff. */ 4185 assign(t5, binop(Iop_CmpNE32, 4186 unop(Iop_64HIto32, 4187 mkexpr(t1)), 4188 mkU32(0xffffffff))); 4189 assign(t6, binop(Iop_CmpNE32, 4190 binop(Iop_And32, 4191 unop(Iop_64to32, 4192 mkexpr(t1)), 4193 mkU32(0x80000000)), 4194 mkU32(0x80000000))); 4195 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4196 control register. */ 4197 assign(t7, binop(Iop_And32, 4198 binop(Iop_Or32, 4199 unop(Iop_1Sto32, mkexpr(t3)), 4200 unop(Iop_1Sto32, mkexpr(t4))), 4201 binop(Iop_Or32, 4202 unop(Iop_1Sto32, mkexpr(t5)), 4203 unop(Iop_1Sto32, mkexpr(t6))))); 4204 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4205 mkexpr(t7), 4206 mkU32(0)), 4207 binop(Iop_Or32, 4208 getDSPControl(), 4209 mkU32(0x00800000)), 4210 getDSPControl())); 4211 4212 /* If the last discarded bit is 1, there would be carry 4213 when rounding, otherwise there wouldn't. We use that 4214 fact and just add the value of the last discarded bit 4215 to the least sifgnificant bit of the shifted value 4216 from acc. */ 4217 if (0 == rs) { 4218 assign(t8, mkU64(0x0ULL)); 4219 } else { 4220 assign(t8, binop(Iop_And64, 4221 binop(Iop_Shr64, 4222 mkexpr(t0), 4223 mkU8(rs-1)), 4224 mkU64(0x1ULL))); 4225 } 4226 4227 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4228 4229 /* Repeat previous steps for the rounded value. */ 4230 assign(t10, binop(Iop_CmpNE32, 4231 unop(Iop_64HIto32, 4232 mkexpr(t9)), 4233 mkU32(0))); 4234 assign(t11, binop(Iop_CmpNE32, 4235 binop(Iop_And32, 4236 unop(Iop_64to32, 4237 mkexpr(t9)), 4238 mkU32(0x80000000)), 4239 mkU32(0))); 4240 4241 assign(t12, binop(Iop_CmpNE32, 4242 unop(Iop_64HIto32, 4243 mkexpr(t9)), 4244 mkU32(0xffffffff))); 4245 assign(t13, binop(Iop_CmpNE32, 4246 binop(Iop_And32, 4247 unop(Iop_64to32, 4248 mkexpr(t9)), 4249 mkU32(0x80000000)), 4250 mkU32(0x80000000))); 4251 4252 assign(t14, binop(Iop_And32, 4253 binop(Iop_Or32, 4254 unop(Iop_1Sto32, mkexpr(t10)), 4255 unop(Iop_1Sto32, mkexpr(t11))), 4256 binop(Iop_Or32, 4257 unop(Iop_1Sto32, mkexpr(t12)), 4258 unop(Iop_1Sto32, mkexpr(t13))))); 4259 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4260 mkexpr(t14), 4261 mkU32(0)), 4262 binop(Iop_Or32, 4263 getDSPControl(), 4264 mkU32(0x00800000)), 4265 getDSPControl())); 4266 4267 assign(t16, binop(Iop_And32, 4268 unop(Iop_64HIto32, 4269 mkexpr(t9)), 4270 mkU32(0x80000000))); 4271 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4272 mkexpr(t14), 4273 mkU32(0)), 4274 IRExpr_ITE(binop(Iop_CmpEQ32, 4275 mkexpr(t16), 4276 mkU32(0)), 4277 mkU32(0x7fffffff), 4278 mkU32(0x80000000)), 4279 unop(Iop_64to32, mkexpr(t9)))); 4280 break; 4281 } 4282 case 0x7: { /* EXTRV_RS.W */ 4283 DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs); 4284 vassert(!mode64); 4285 t0 = newTemp(Ity_I64); 4286 t1 = newTemp(Ity_I64); 4287 t2 = newTemp(Ity_I32); 4288 t3 = newTemp(Ity_I1); 4289 t4 = newTemp(Ity_I1); 4290 t5 = newTemp(Ity_I1); 4291 t6 = newTemp(Ity_I1); 4292 t7 = newTemp(Ity_I32); 4293 t8 = newTemp(Ity_I64); 4294 t9 = newTemp(Ity_I64); 4295 t10 = newTemp(Ity_I1); 4296 t11 = newTemp(Ity_I1); 4297 t12 = newTemp(Ity_I1); 4298 t13 = newTemp(Ity_I1); 4299 t14 = newTemp(Ity_I32); 4300 t15 = newTemp(Ity_I32); 4301 t16 = newTemp(Ity_I32); 4302 t17 = newTemp(Ity_I1); 4303 4304 assign(t15, binop(Iop_And32, 4305 getIReg(rs), 4306 mkU32(0x1f))); 4307 assign(t17, binop(Iop_CmpEQ32, 4308 mkexpr(t15), 4309 mkU32(0))); 4310 assign(t0, getAcc(ac)); 4311 assign(t1, IRExpr_ITE(mkexpr(t17), 4312 mkexpr(t0), 4313 binop(Iop_Sar64, 4314 mkexpr(t0), 4315 unop(Iop_32to8, 4316 mkexpr(t15))))); 4317 4318 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4319 assign(t3, binop(Iop_CmpNE32, 4320 unop(Iop_64HIto32, 4321 mkexpr(t1)), 4322 mkU32(0))); 4323 assign(t4, binop(Iop_CmpNE32, 4324 binop(Iop_And32, 4325 unop(Iop_64to32, 4326 mkexpr(t1)), 4327 mkU32(0x80000000)), 4328 mkU32(0))); 4329 /* Check if bits 63..31 of the result in t1 aren't 4330 0x1ffffffff. */ 4331 assign(t5, binop(Iop_CmpNE32, 4332 unop(Iop_64HIto32, 4333 mkexpr(t1)), 4334 mkU32(0xffffffff))); 4335 assign(t6, binop(Iop_CmpNE32, 4336 binop(Iop_And32, 4337 unop(Iop_64to32, 4338 mkexpr(t1)), 4339 mkU32(0x80000000)), 4340 mkU32(0x80000000))); 4341 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4342 control register. */ 4343 assign(t7, binop(Iop_And32, 4344 binop(Iop_Or32, 4345 unop(Iop_1Sto32, mkexpr(t3)), 4346 unop(Iop_1Sto32, mkexpr(t4))), 4347 binop(Iop_Or32, 4348 unop(Iop_1Sto32, mkexpr(t5)), 4349 unop(Iop_1Sto32, mkexpr(t6))))); 4350 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4351 mkexpr(t7), 4352 mkU32(0)), 4353 binop(Iop_Or32, 4354 getDSPControl(), 4355 mkU32(0x00800000)), 4356 getDSPControl())); 4357 4358 /* If the last discarded bit is 1, there would be carry 4359 when rounding, otherwise there wouldn't. We use that 4360 fact and just add the value of the last discarded bit 4361 to the least sifgnificant bit of the shifted value 4362 from acc. */ 4363 assign(t8, 4364 IRExpr_ITE(mkexpr(t17), 4365 mkU64(0x0ULL), 4366 binop(Iop_And64, 4367 binop(Iop_Shr64, 4368 mkexpr(t0), 4369 unop(Iop_32to8, 4370 binop(Iop_Sub32, 4371 mkexpr(t15), 4372 mkU32(1)))), 4373 mkU64(0x1ULL)))); 4374 4375 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4376 4377 /* Repeat previous steps for the rounded value. */ 4378 assign(t10, binop(Iop_CmpNE32, 4379 unop(Iop_64HIto32, 4380 mkexpr(t9)), 4381 mkU32(0))); 4382 assign(t11, binop(Iop_CmpNE32, 4383 binop(Iop_And32, 4384 unop(Iop_64to32, 4385 mkexpr(t9)), 4386 mkU32(0x80000000)), 4387 mkU32(0))); 4388 4389 assign(t12, binop(Iop_CmpNE32, 4390 unop(Iop_64HIto32, 4391 mkexpr(t9)), 4392 mkU32(0xffffffff))); 4393 assign(t13, binop(Iop_CmpNE32, 4394 binop(Iop_And32, 4395 unop(Iop_64to32, 4396 mkexpr(t9)), 4397 mkU32(0x80000000)), 4398 mkU32(0x80000000))); 4399 4400 assign(t14, binop(Iop_And32, 4401 binop(Iop_Or32, 4402 unop(Iop_1Sto32, mkexpr(t10)), 4403 unop(Iop_1Sto32, mkexpr(t11))), 4404 binop(Iop_Or32, 4405 unop(Iop_1Sto32, mkexpr(t12)), 4406 unop(Iop_1Sto32, mkexpr(t13))))); 4407 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4408 mkexpr(t14), 4409 mkU32(0)), 4410 binop(Iop_Or32, 4411 getDSPControl(), 4412 mkU32(0x00800000)), 4413 getDSPControl())); 4414 4415 assign(t16, binop(Iop_And32, 4416 unop(Iop_64HIto32, 4417 mkexpr(t9)), 4418 mkU32(0x80000000))); 4419 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4420 mkexpr(t14), 4421 mkU32(0)), 4422 IRExpr_ITE(binop(Iop_CmpEQ32, 4423 mkexpr(t16), 4424 mkU32(0)), 4425 mkU32(0x7fffffff), 4426 mkU32(0x80000000)), 4427 unop(Iop_64to32, mkexpr(t9)))); 4428 break; 4429 } 4430 case 0xA: { /* EXTPDP */ 4431 DIP("extpdp r%u, ac%u, %u", rt, ac, rs); 4432 vassert(!mode64); 4433 t0 = newTemp(Ity_I64); 4434 t1 = newTemp(Ity_I32); 4435 t2 = newTemp(Ity_I1); 4436 t3 = newTemp(Ity_I1); 4437 t4 = newTemp(Ity_I8); 4438 t5 = newTemp(Ity_I64); 4439 t6 = newTemp(Ity_I64); 4440 t7 = newTemp(Ity_I32); 4441 t8 = newTemp(Ity_I32); 4442 4443 assign(t0, getAcc(ac)); 4444 /* Extract pos field of DSPControl register. */ 4445 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4446 4447 /* Check if (pos - size) >= 0 [size <= pos] 4448 if (pos < size) 4449 put 1 to EFI field of DSPControl register 4450 else 4451 extract bits from acc and put 0 to EFI field of 4452 DSPCtrl */ 4453 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 4454 4455 assign(t8, binop(Iop_Or32, 4456 binop(Iop_And32, 4457 getDSPControl(), 4458 mkU32(0xffffbfc0)), 4459 binop(Iop_And32, 4460 binop(Iop_Sub32, 4461 binop(Iop_And32, 4462 getDSPControl(), 4463 mkU32(0x3f)), 4464 mkU32(rs+1)), 4465 mkU32(0x3f)))); 4466 putDSPControl(IRExpr_ITE(mkexpr(t2), 4467 binop(Iop_Or32, 4468 binop(Iop_And32, 4469 getDSPControl(), 4470 mkU32(0xffffbfff)), 4471 mkU32(0x4000)), 4472 mkexpr(t8))); 4473 4474 /* If pos <= 31, shift right the value from the acc 4475 (pos-size) times and take (size+1) bits from the least 4476 significant positions. Otherwise, shift left the value 4477 (63-pos) times, take (size+1) bits from the most 4478 significant positions and shift right (31-size) times. 4479 */ 4480 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4481 4482 assign(t4, 4483 IRExpr_ITE(mkexpr(t3), 4484 unop(Iop_32to8, 4485 binop(Iop_Sub32, 4486 mkexpr(t1), mkU32(rs))), 4487 unop(Iop_32to8, 4488 binop(Iop_Sub32, 4489 mkU32(63), mkexpr(t1))))); 4490 4491 assign(t5, IRExpr_ITE(mkexpr(t3), 4492 binop(Iop_Shr64, 4493 mkexpr(t0), mkexpr(t4)), 4494 binop(Iop_Shl64, 4495 mkexpr(t0), mkexpr(t4)))); 4496 4497 /* t6 holds a mask for bit extraction. */ 4498 assign(t6, 4499 IRExpr_ITE(mkexpr(t3), 4500 unop(Iop_Not64, 4501 binop(Iop_Shl64, 4502 mkU64(0xffffffffffffffffULL), 4503 mkU8(rs+1))), 4504 unop(Iop_Not64, 4505 binop(Iop_Shr64, 4506 mkU64(0xffffffffffffffffULL), 4507 mkU8(rs+1))))); 4508 4509 assign(t7, IRExpr_ITE(mkexpr(t3), 4510 unop(Iop_64to32, 4511 binop(Iop_And64, 4512 mkexpr(t5), 4513 mkexpr(t6))), 4514 binop(Iop_Shr32, 4515 unop(Iop_64HIto32, 4516 binop(Iop_And64, 4517 mkexpr(t5), 4518 mkexpr(t6))), 4519 mkU8(31-rs)))); 4520 4521 putIReg(rt, mkexpr(t7)); 4522 break; 4523 } 4524 case 0xB: { /* EXTPDPV */ 4525 DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs); 4526 vassert(!mode64); 4527 t0 = newTemp(Ity_I64); 4528 t1 = newTemp(Ity_I32); 4529 t2 = newTemp(Ity_I1); 4530 t3 = newTemp(Ity_I1); 4531 t4 = newTemp(Ity_I8); 4532 t5 = newTemp(Ity_I64); 4533 t6 = newTemp(Ity_I64); 4534 t7 = newTemp(Ity_I32); 4535 t8 = newTemp(Ity_I32); 4536 t9 = newTemp(Ity_I32); 4537 4538 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 4539 assign(t0, getAcc(ac)); 4540 /* Extract pos field of DSPControl register. */ 4541 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4542 4543 /* Check if (pos - size) >= 0 [size <= pos] 4544 if (pos < size) 4545 put 1 to EFI field of DSPControl register 4546 else 4547 extract bits from acc and put 0 to EFI field of 4548 DSPCtrl */ 4549 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 4550 4551 assign(t9, binop(Iop_Or32, 4552 binop(Iop_And32, 4553 getDSPControl(), 4554 mkU32(0xffffbfc0)), 4555 binop(Iop_And32, 4556 binop(Iop_Sub32, 4557 binop(Iop_And32, 4558 getDSPControl(), 4559 mkU32(0x3f)), 4560 binop(Iop_Add32, 4561 mkexpr(t8), 4562 mkU32(0x1))), 4563 mkU32(0x3f)))); 4564 putDSPControl(IRExpr_ITE(mkexpr(t2), 4565 binop(Iop_Or32, 4566 binop(Iop_And32, 4567 getDSPControl(), 4568 mkU32(0xffffbfff)), 4569 mkU32(0x4000)), 4570 mkexpr(t9))); 4571 4572 /* If pos <= 31, shift right the value from the acc 4573 (pos-size) times and take (size+1) bits from the least 4574 significant positions. Otherwise, shift left the value 4575 (63-pos) times, take (size+1) bits from the most 4576 significant positions and shift right (31-size) times. 4577 */ 4578 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4579 4580 assign(t4, 4581 IRExpr_ITE(mkexpr(t3), 4582 unop(Iop_32to8, 4583 binop(Iop_Sub32, 4584 mkexpr(t1), mkexpr(t8))), 4585 unop(Iop_32to8, 4586 binop(Iop_Sub32, 4587 mkU32(63), mkexpr(t1))))); 4588 4589 assign(t5, IRExpr_ITE(mkexpr(t3), 4590 binop(Iop_Shr64, 4591 mkexpr(t0), mkexpr(t4)), 4592 binop(Iop_Shl64, 4593 mkexpr(t0), mkexpr(t4)))); 4594 4595 /* t6 holds a mask for bit extraction. */ 4596 assign(t6, 4597 IRExpr_ITE(mkexpr(t3), 4598 unop(Iop_Not64, 4599 binop(Iop_Shl64, 4600 mkU64(0xffffffffffffffffULL), 4601 unop(Iop_32to8, 4602 binop(Iop_Add32, 4603 mkexpr(t8), 4604 mkU32(1))))), 4605 unop(Iop_Not64, 4606 binop(Iop_Shr64, 4607 mkU64(0xffffffffffffffffULL), 4608 unop(Iop_32to8, 4609 binop(Iop_Add32, 4610 mkexpr(t8), 4611 mkU32(1))))))); 4612 4613 assign(t7, IRExpr_ITE(mkexpr(t3), 4614 unop(Iop_64to32, 4615 binop(Iop_And64, 4616 mkexpr(t5), 4617 mkexpr(t6))), 4618 binop(Iop_Shr32, 4619 unop(Iop_64HIto32, 4620 binop(Iop_And64, 4621 mkexpr(t5), 4622 mkexpr(t6))), 4623 unop(Iop_32to8, 4624 binop(Iop_Sub32, 4625 mkU32(31), 4626 mkexpr(t8)))))); 4627 4628 putIReg(rt, mkexpr(t7)); 4629 break; 4630 } 4631 case 0xE: { /* EXTR_S.H */ 4632 DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs); 4633 vassert(!mode64); 4634 t0 = newTemp(Ity_I64); 4635 t1 = newTemp(Ity_I64); 4636 t2 = newTemp(Ity_I32); 4637 t3 = newTemp(Ity_I64); 4638 t4 = newTemp(Ity_I32); 4639 t5 = newTemp(Ity_I32); 4640 t6 = newTemp(Ity_I64); 4641 t7 = newTemp(Ity_I32); 4642 t9 = newTemp(Ity_I32); 4643 4644 assign(t0, getAcc(ac)); 4645 4646 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4647 4648 assign(t2, binop(Iop_Or32, 4649 getDSPControl(), mkU32(0x00800000))); 4650 4651 assign(t9, binop(Iop_And32, 4652 unop(Iop_64to32, 4653 mkexpr(t1)), 4654 mkU32(0x80000000))); 4655 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4656 mkexpr(t9), 4657 binop(Iop_And32, 4658 unop(Iop_64HIto32, 4659 mkexpr(t0)), 4660 mkU32(0x80000000))), 4661 mkexpr(t2), 4662 getDSPControl())); 4663 4664 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4665 1. subtract 0x7fff from t1 4666 2. if the resulting number is positive (sign bit = 0) 4667 and any of the other bits is 1, the value is > 0. */ 4668 assign(t3, binop(Iop_Sub64, 4669 mkexpr(t1), 4670 mkU64(0x0000000000007fffULL))); 4671 assign(t4, binop(Iop_And32, 4672 binop(Iop_Or32, 4673 unop(Iop_1Sto32, 4674 binop(Iop_CmpNE32, 4675 mkU32(0), 4676 binop(Iop_And32, 4677 unop(Iop_64HIto32, 4678 mkexpr(t3)), 4679 mkU32(0x7fffffff)))), 4680 unop(Iop_1Sto32, 4681 binop(Iop_CmpNE32, 4682 mkU32(0), 4683 unop(Iop_64to32, 4684 mkexpr(t3))))), 4685 unop(Iop_1Sto32, 4686 binop(Iop_CmpEQ32, 4687 binop(Iop_And32, 4688 unop(Iop_64HIto32, 4689 mkexpr(t3)), 4690 mkU32(0x80000000)), 4691 mkU32(0))))); 4692 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4693 mkU32(0), 4694 mkexpr(t4)), 4695 binop(Iop_Or32, 4696 getDSPControl(), 4697 mkU32(0x00800000)), 4698 getDSPControl())); 4699 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4700 1. subtract t1 from 0xffffffffffff8000 4701 2. if the resulting number is positive (sign bit = 0) 4702 and any of the other bits is 1, the value is > 0 */ 4703 assign(t6, binop(Iop_Sub64, 4704 mkU64(0xffffffffffff8000ULL), 4705 mkexpr(t1))); 4706 assign(t7, binop(Iop_And32, 4707 binop(Iop_Or32, 4708 unop(Iop_1Sto32, 4709 binop(Iop_CmpNE32, 4710 mkU32(0), 4711 binop(Iop_And32, 4712 unop(Iop_64HIto32, 4713 mkexpr(t6)), 4714 mkU32(0x7fffffff)))), 4715 unop(Iop_1Sto32, 4716 binop(Iop_CmpNE32, 4717 mkU32(0), 4718 unop(Iop_64to32, 4719 mkexpr(t6))))), 4720 unop(Iop_1Sto32, 4721 binop(Iop_CmpEQ32, 4722 binop(Iop_And32, 4723 unop(Iop_64HIto32, 4724 mkexpr(t6)), 4725 mkU32(0x80000000)), 4726 mkU32(0))))); 4727 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4728 mkU32(0), 4729 mkexpr(t7)), 4730 binop(Iop_Or32, 4731 getDSPControl(), 4732 mkU32(0x00800000)), 4733 getDSPControl())); 4734 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4735 mkU32(0), 4736 mkexpr(t4)), 4737 mkU32(0x00007fff), 4738 IRExpr_ITE(binop(Iop_CmpNE32, 4739 mkU32(0), 4740 mkexpr(t7)), 4741 mkU32(0xffff8000), 4742 unop(Iop_64to32, 4743 mkexpr(t1))))); 4744 break; 4745 } 4746 case 0xF: { /* EXTRV_S.H */ 4747 DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs); 4748 vassert(!mode64); 4749 t0 = newTemp(Ity_I64); 4750 t1 = newTemp(Ity_I64); 4751 t2 = newTemp(Ity_I32); 4752 t3 = newTemp(Ity_I64); 4753 t4 = newTemp(Ity_I32); 4754 t5 = newTemp(Ity_I32); 4755 t6 = newTemp(Ity_I64); 4756 t7 = newTemp(Ity_I32); 4757 t9 = newTemp(Ity_I32); 4758 4759 assign(t0, getAcc(ac)); 4760 4761 assign(t1, binop(Iop_Sar64, 4762 mkexpr(t0), 4763 unop(Iop_32to8, 4764 binop(Iop_And32, 4765 getIReg(rs), 4766 mkU32(0x1f))))); 4767 4768 assign(t2, binop(Iop_Or32, 4769 getDSPControl(), mkU32(0x00800000))); 4770 4771 assign(t9, binop(Iop_And32, 4772 unop(Iop_64to32, 4773 mkexpr(t1)), 4774 mkU32(0x80000000))); 4775 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4776 mkexpr(t9), 4777 binop(Iop_And32, 4778 unop(Iop_64HIto32, 4779 mkexpr(t0)), 4780 mkU32(0x80000000))), 4781 mkexpr(t2), 4782 getDSPControl())); 4783 4784 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4785 1. subtract 0x7fff from t1 4786 2. if the resulting number is positive (sign bit = 0) 4787 and any of the other bits is 1, the value is > 0. */ 4788 assign(t3, binop(Iop_Sub64, 4789 mkexpr(t1), 4790 mkU64(0x0000000000007fffULL))); 4791 assign(t4, binop(Iop_And32, 4792 binop(Iop_Or32, 4793 unop(Iop_1Sto32, 4794 binop(Iop_CmpNE32, 4795 mkU32(0), 4796 binop(Iop_And32, 4797 unop(Iop_64HIto32, 4798 mkexpr(t3)), 4799 mkU32(0x7fffffff)))), 4800 unop(Iop_1Sto32, 4801 binop(Iop_CmpNE32, 4802 mkU32(0), 4803 unop(Iop_64to32, 4804 mkexpr(t3))))), 4805 unop(Iop_1Sto32, 4806 binop(Iop_CmpEQ32, 4807 binop(Iop_And32, 4808 unop(Iop_64HIto32, 4809 mkexpr(t3)), 4810 mkU32(0x80000000)), 4811 mkU32(0))))); 4812 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4813 mkU32(0), 4814 mkexpr(t4)), 4815 binop(Iop_Or32, 4816 getDSPControl(), 4817 mkU32(0x00800000)), 4818 getDSPControl())); 4819 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4820 1. subtract t1 from 0xffffffffffff8000 4821 2. if the resulting number is positive (sign bit = 0) 4822 and any of the other bits is 1, the value is > 0 */ 4823 assign(t6, binop(Iop_Sub64, 4824 mkU64(0xffffffffffff8000ULL), 4825 mkexpr(t1))); 4826 assign(t7, binop(Iop_And32, 4827 binop(Iop_Or32, 4828 unop(Iop_1Sto32, 4829 binop(Iop_CmpNE32, 4830 mkU32(0), 4831 binop(Iop_And32, 4832 unop(Iop_64HIto32, 4833 mkexpr(t6)), 4834 mkU32(0x7fffffff)))), 4835 unop(Iop_1Sto32, 4836 binop(Iop_CmpNE32, 4837 mkU32(0), 4838 unop(Iop_64to32, 4839 mkexpr(t6))))), 4840 unop(Iop_1Sto32, 4841 binop(Iop_CmpEQ32, 4842 binop(Iop_And32, 4843 unop(Iop_64HIto32, 4844 mkexpr(t6)), 4845 mkU32(0x80000000)), 4846 mkU32(0))))); 4847 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4848 mkU32(0), 4849 mkexpr(t7)), 4850 binop(Iop_Or32, 4851 getDSPControl(), 4852 mkU32(0x00800000)), 4853 getDSPControl())); 4854 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4855 mkU32(0), 4856 mkexpr(t4)), 4857 mkU32(0x00007fff), 4858 IRExpr_ITE(binop(Iop_CmpNE32, 4859 mkU32(0), 4860 mkexpr(t7)), 4861 mkU32(0xffff8000), 4862 unop(Iop_64to32, 4863 mkexpr(t1))))); 4864 break; 4865 } 4866 case 0x12: { /* RDDSP*/ 4867 DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask); 4868 vassert(!mode64); 4869 4870 putIReg(rd, mkU32(0x0)); 4871 4872 if ((rddsp_mask & 0x1) == 0x1) { 4873 /* Read pos field (bits 5-0) of DSPControl register. */ 4874 putIReg(rd, binop(Iop_Or32, 4875 getIReg(rd), 4876 binop(Iop_And32, 4877 getDSPControl(), 4878 mkU32(0x0000003F)))); 4879 } 4880 4881 if ((rddsp_mask & 0x2) == 0x2) { 4882 /* Read scount field (bits 12-7) of DSPControl 4883 register. */ 4884 putIReg(rd, binop(Iop_Or32, 4885 getIReg(rd), 4886 binop(Iop_And32, 4887 getDSPControl(), 4888 mkU32(0x00001F80)))); 4889 } 4890 4891 if ((rddsp_mask & 0x4) == 0x4) { 4892 /* Read C field (bit 13) of DSPControl register. */ 4893 putIReg(rd, binop(Iop_Or32, 4894 getIReg(rd), 4895 binop(Iop_And32, 4896 getDSPControl(), 4897 mkU32(0x00002000)))); 4898 } 4899 4900 if ((rddsp_mask & 0x8) == 0x8) { 4901 /* Read outflag field (bit s 23-16) of DSPControl 4902 register. */ 4903 putIReg(rd, binop(Iop_Or32, 4904 getIReg(rd), 4905 binop(Iop_And32, 4906 getDSPControl(), 4907 mkU32(0x00FF0000)))); 4908 } 4909 4910 if ((rddsp_mask & 0x10) == 0x10) { 4911 /* Read ccond field (bits 31-24) of DSPControl 4912 register. */ 4913 putIReg(rd, binop(Iop_Or32, 4914 getIReg(rd), 4915 binop(Iop_And32, 4916 getDSPControl(), 4917 mkU32(0xFF000000)))); 4918 } 4919 4920 if ((rddsp_mask & 0x20) == 0x20) { 4921 /* Read EFI field (bit 14) of DSPControl register. */ 4922 putIReg(rd, binop(Iop_Or32, 4923 getIReg(rd), 4924 binop(Iop_And32, 4925 getDSPControl(), 4926 mkU32(0x00004000)))); 4927 } 4928 4929 if ((rddsp_mask & 0x3f) == 0x3f) { 4930 /* Read all fields of DSPControl register. */ 4931 putIReg(rd, getDSPControl()); 4932 } 4933 break; 4934 } 4935 case 0x13: { /* WRDSP */ 4936 DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask); 4937 vassert(!mode64); 4938 4939 if ((wrdsp_mask & 0x3f) == 0x3f) { 4940 /* If mips64 put all fields of rs, except bit 15 and bit 4941 6, to DSPControl register, otherwise put all except 4942 bits 15, 6 and bits 31..28. */ 4943 putDSPControl(mode64 ? 4944 binop(Iop_And32, 4945 getIReg(rs), 4946 mkU32(0xffff7fbf)) : 4947 binop(Iop_And32, 4948 getIReg(rs), 4949 mkU32(0x0fff7fbf))); 4950 } else { 4951 if ((wrdsp_mask & 0x1) == 0x1) { 4952 /* Put bits 5-0 of rs to DSPControl register pos 4953 field. */ 4954 putDSPControl(binop(Iop_Or32, 4955 binop(Iop_And32, 4956 getDSPControl(), 4957 mkU32(0xFFFF7F40)), 4958 binop(Iop_And32, 4959 getIReg(rs), 4960 mkU32(0x0000003F)))); 4961 } 4962 4963 if ((wrdsp_mask & 0x2) == 0x2) { 4964 /* Put bits 12-7 of rs to DSPControl scount field. */ 4965 putDSPControl(binop(Iop_Or32, 4966 binop(Iop_And32, 4967 getDSPControl(), 4968 mkU32(0xFFFFE03F)), 4969 binop(Iop_And32, 4970 getIReg(rs), 4971 mkU32(0x00001F80)))); 4972 } 4973 4974 if ((wrdsp_mask & 0x4) == 0x4) { 4975 /* Put bit 13 of rs to DSPControl register C 4976 field. */ 4977 putDSPControl(binop(Iop_Or32, 4978 binop(Iop_And32, 4979 getDSPControl(), 4980 mkU32(0xFFFF5FBF)), 4981 binop(Iop_And32, 4982 getIReg(rs), 4983 mkU32(0x00002000)))); 4984 } 4985 4986 if ((wrdsp_mask & 0x8) == 0x8) { 4987 /* Put bits 23-16 of rs to DSPControl reg outflag 4988 field. */ 4989 putDSPControl(binop(Iop_Or32, 4990 binop(Iop_And32, 4991 getDSPControl(), 4992 mkU32(0xFF007FBF)), 4993 binop(Iop_And32, 4994 getIReg(rs), 4995 mkU32(0x00FF0000)))); 4996 } 4997 4998 if ((wrdsp_mask & 0x10) == 0x10) { 4999 /* Put bits 31-24 of rs to DSPControl reg ccond 5000 field. */ 5001 putDSPControl(binop(Iop_Or32, 5002 binop(Iop_And32, 5003 getDSPControl(), 5004 mkU32(0x00FF7FBF)), 5005 binop(Iop_And32, 5006 getIReg(rs), 5007 mode64 ? mkU32(0xFF000000) 5008 : mkU32(0x0F000000)) 5009 ) 5010 ); 5011 } 5012 5013 if ((wrdsp_mask & 0x20) == 0x20) { 5014 /* Put bit 14 of rs to DSPControl register EFI 5015 field. */ 5016 putDSPControl(binop(Iop_Or32, 5017 binop(Iop_And32, 5018 getDSPControl(), 5019 mkU32(0xFFFF3FBF)), 5020 binop(Iop_And32, 5021 getIReg(rs), 5022 mkU32(0x00004000)))); 5023 } 5024 } 5025 break; 5026 } 5027 case 0x1A: { /* SHILO */ 5028 DIP("shilo ac%u, %u", ac, shift); 5029 vassert(!mode64); 5030 t0 = newTemp(Ity_I64); 5031 t1 = newTemp(Ity_I64); 5032 5033 assign(t0, getAcc(ac)); 5034 5035 putAcc(ac, mkexpr(t0)); 5036 5037 if (0x20 == (shift & 0x3f)) { 5038 putAcc(ac, binop(Iop_32HLto64, 5039 unop(Iop_64to32, mkexpr(t0)), 5040 mkU32(0x0))); 5041 } else if (0x20 == (shift & 0x20)) { 5042 assign(t1, binop(Iop_Shl64, 5043 mkexpr(t0), 5044 unop(Iop_32to8, 5045 binop(Iop_Add32, 5046 unop(Iop_Not32, 5047 mkU32(shift)), 5048 mkU32(0x1))))); 5049 5050 putAcc(ac, mkexpr(t1)); 5051 } else { 5052 assign(t1, binop(Iop_Shr64, mkexpr(t0), mkU8(shift))); 5053 5054 putAcc(ac, mkexpr(t1)); 5055 } 5056 break; 5057 } 5058 case 0x1B: { /* SHILOV */ 5059 DIP("shilov ac%u, r%u", ac, rs); 5060 vassert(!mode64); 5061 t0 = newTemp(Ity_I64); 5062 t1 = newTemp(Ity_I32); 5063 t2 = newTemp(Ity_I1); 5064 t3 = newTemp(Ity_I64); 5065 t4 = newTemp(Ity_I64); 5066 5067 assign(t0, getAcc(ac)); 5068 assign(t1, binop(Iop_And32, getIReg(rs), mkU32(0x3f))); 5069 assign(t2, binop(Iop_CmpEQ32, mkexpr(t1), mkU32(0x20))); 5070 assign(t3, binop(Iop_Shl64, 5071 mkexpr(t0), 5072 unop(Iop_32to8, 5073 binop(Iop_Add32, 5074 unop(Iop_Not32, 5075 mkexpr(t1)), 5076 mkU32(0x1))))); 5077 assign(t4, binop(Iop_Shr64, 5078 mkexpr(t0), 5079 unop(Iop_32to8, 5080 mkexpr(t1)))); 5081 5082 putAcc(ac, 5083 IRExpr_ITE(mkexpr(t2), 5084 binop(Iop_32HLto64, 5085 unop(Iop_64to32, mkexpr(t0)), 5086 mkU32(0x0)), 5087 IRExpr_ITE(binop(Iop_CmpEQ32, 5088 binop(Iop_And32, 5089 mkexpr(t1), 5090 mkU32(0x20)), 5091 mkU32(0x20)), 5092 mkexpr(t3), 5093 mkexpr(t4)))); 5094 break; 5095 } 5096 case 0x1F: { /* MTHLIP */ 5097 DIP("mthlip r%u, ac%u", rs, ac); 5098 vassert(!mode64); 5099 t0 = newTemp(Ity_I64); 5100 t1 = newTemp(Ity_I32); 5101 t2 = newTemp(Ity_I32); 5102 t3 = newTemp(Ity_I1); 5103 5104 assign(t0, getAcc(ac)); 5105 putAcc(ac, binop(Iop_32HLto64, 5106 unop(Iop_64to32, mkexpr(t0)), 5107 getIReg(rs))); 5108 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5109 putDSPControl(IRExpr_ITE(binop(Iop_CmpLE32U, 5110 mkU32(32), 5111 mkexpr(t1)), 5112 binop(Iop_Or32, 5113 binop(Iop_Sub32, 5114 mkexpr(t1), 5115 mkU32(32)), 5116 binop(Iop_And32, 5117 getDSPControl(), 5118 mkU32(0xffffffc0))), 5119 binop(Iop_Or32, 5120 binop(Iop_Add32, 5121 mkexpr(t1), 5122 mkU32(32)), 5123 binop(Iop_And32, 5124 getDSPControl(), 5125 mkU32(0xffffffc0))))); 5126 break; 5127 } 5128 default: 5129 return -1; 5130 } 5131 break; /* end of EXTR.W */ 5132 } 5133 case 0xA: { /* LX */ 5134 switch(sa) { 5135 case 0x0: { /* LWX */ 5136 DIP("lwx r%u, r%u(r%u)", rd, rt, rs); 5137 vassert(!mode64); 5138 t0 = newTemp(Ity_I32); 5139 5140 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5141 5142 putIReg(rd, load(Ity_I32, mkexpr(t0))); 5143 break; 5144 } 5145 case 0x4: { /* LHX */ 5146 DIP("lhx r%u, r%u(r%u)", rd, rt, rs); 5147 vassert(!mode64); 5148 t0 = newTemp(Ity_I32); 5149 5150 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5151 5152 putIReg(rd, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t0)))); 5153 break; 5154 } 5155 case 0x6: { /* LBUX */ 5156 DIP("lbux r%u, r%u(r%u)", rd, rt, rs); 5157 vassert(!mode64); 5158 t0 = newTemp(Ity_I32); 5159 5160 assign(t0, binop(Iop_Add32, getIReg(rt), getIReg(rs))); 5161 5162 putIReg(rd, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t0)))); 5163 break; 5164 } 5165 default: 5166 return -1; 5167 } 5168 break; /* end of LX */ 5169 } 5170 case 0xC: { /* INSV */ 5171 switch(sa) { 5172 case 0x0: { /* INSV */ 5173 DIP("insv r%u, r%u", rt, rs); 5174 vassert(!mode64); 5175 5176 t0 = newTemp(Ity_I32); 5177 t1 = newTemp(Ity_I32); 5178 t2 = newTemp(Ity_I8); 5179 t3 = newTemp(Ity_I8); 5180 t4 = newTemp(Ity_I32); 5181 t5 = newTemp(Ity_I1); 5182 t6 = newTemp(Ity_I32); 5183 t7 = newTemp(Ity_I32); 5184 t8 = newTemp(Ity_I32); 5185 t9 = newTemp(Ity_I32); 5186 5187 /* t0 <- pos field of DSPControl register. */ 5188 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 5189 /* t1 <- scount field of DSPControl register. */ 5190 assign(t1, binop(Iop_Shr32, 5191 binop(Iop_And32, 5192 getDSPControl(), 5193 mkU32(0x1f80)), 5194 mkU8(7))); 5195 5196 assign(t2, unop(Iop_32to8, 5197 binop(Iop_Add32, 5198 mkexpr(t1), 5199 mkexpr(t0)))); 5200 5201 /* 32-(pos+size) most significant bits of rt. */ 5202 assign(t6, binop(Iop_Shl32, 5203 binop(Iop_Shr32, 5204 getIReg(rt), 5205 mkexpr(t2)), 5206 mkexpr(t2))); 5207 5208 assign(t3, unop(Iop_32to8, 5209 binop(Iop_Sub32, 5210 mkU32(32), 5211 mkexpr(t0)))); 5212 /* Pos least significant bits of rt. */ 5213 assign(t7, binop(Iop_Shr32, 5214 binop(Iop_Shl32, 5215 getIReg(rt), 5216 mkexpr(t3)), 5217 mkexpr(t3))); 5218 5219 /* Size least significant bits of rs, 5220 shifted to appropriate position. */ 5221 assign(t8, binop(Iop_Shl32, 5222 binop(Iop_And32, 5223 getIReg(rs), 5224 unop(Iop_Not32, 5225 binop(Iop_Shl32, 5226 mkU32(0xffffffff), 5227 unop(Iop_32to8, 5228 mkexpr(t1))))), 5229 unop(Iop_32to8, 5230 mkexpr(t0)))); 5231 5232 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 5233 mkexpr(t0), 5234 mkU32(0)), 5235 IRExpr_ITE(binop(Iop_CmpEQ32, 5236 mkexpr(t1), 5237 mkU32(32)), 5238 getIReg(rs), 5239 binop(Iop_Or32, 5240 mkexpr(t6), 5241 mkexpr(t8))), 5242 IRExpr_ITE(binop(Iop_CmpEQ32, 5243 unop(Iop_8Uto32, 5244 mkexpr(t2)), 5245 mkU32(32)), 5246 binop(Iop_Or32, 5247 mkexpr(t7), 5248 mkexpr(t8)), 5249 binop(Iop_Or32, 5250 binop(Iop_Or32, 5251 mkexpr(t6), 5252 mkexpr(t7)), 5253 mkexpr(t8))))); 5254 break; 5255 } 5256 default: 5257 return -1; 5258 } 5259 break; /* enf of INSV */ 5260 } 5261 case 0x10: { /* ADDU.QB */ 5262 switch(sa) { 5263 case 0x00: { /* ADDU.QB */ 5264 DIP("addu.qb r%u, r%u, r%u", rd, rs, rt); 5265 vassert(!mode64); 5266 t0 = newTemp(Ity_I32); 5267 t1 = newTemp(Ity_I1); 5268 t2 = newTemp(Ity_I32); 5269 t3 = newTemp(Ity_I1); 5270 t4 = newTemp(Ity_I32); 5271 t5 = newTemp(Ity_I1); 5272 t6 = newTemp(Ity_I32); 5273 t7 = newTemp(Ity_I1); 5274 t8 = newTemp(Ity_I32); 5275 5276 /* Add rightmost bytes of rs and rt. */ 5277 assign(t0, 5278 binop(Iop_Add32, 5279 unop(Iop_8Uto32, 5280 unop(Iop_16to8, 5281 unop(Iop_32to16, getIReg(rs)))), 5282 unop(Iop_8Uto32, 5283 unop(Iop_16to8, 5284 unop(Iop_32to16, getIReg(rt)))))); 5285 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5286 assign(t1, binop(Iop_CmpEQ32, 5287 binop(Iop_And32, 5288 mkexpr(t0), 5289 mkU32(0x00000100)), 5290 mkU32(0x00000100))); 5291 5292 /* Add bits 15-8 of rs and rt. */ 5293 assign(t2, 5294 binop(Iop_Add32, 5295 unop(Iop_8Uto32, 5296 unop(Iop_16HIto8, 5297 unop(Iop_32to16, getIReg(rs)))), 5298 unop(Iop_8Uto32, 5299 unop(Iop_16HIto8, 5300 unop(Iop_32to16, getIReg(rt)))))); 5301 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5302 assign(t3, binop(Iop_CmpEQ32, 5303 binop(Iop_And32, 5304 mkexpr(t2), 5305 mkU32(0x00000100)), 5306 mkU32(0x00000100))); 5307 5308 /* Add bits 15-8 of rs and rt. */ 5309 assign(t4, 5310 binop(Iop_Add32, 5311 unop(Iop_8Uto32, 5312 unop(Iop_16to8, 5313 unop(Iop_32HIto16, getIReg(rs)))), 5314 unop(Iop_8Uto32, 5315 unop(Iop_16to8, 5316 unop(Iop_32HIto16, getIReg(rt)))))); 5317 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5318 assign(t5, binop(Iop_CmpEQ32, 5319 binop(Iop_And32, 5320 mkexpr(t4), 5321 mkU32(0x00000100)), 5322 mkU32(0x00000100))); 5323 5324 /* Add bits 15-8 of rs and rt. */ 5325 assign(t6, 5326 binop(Iop_Add32, 5327 unop(Iop_8Uto32, 5328 unop(Iop_16HIto8, 5329 unop(Iop_32HIto16, getIReg(rs)))), 5330 unop(Iop_8Uto32, 5331 unop(Iop_16HIto8, 5332 unop(Iop_32HIto16, getIReg(rt)))))); 5333 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5334 assign(t7, binop(Iop_CmpEQ32, 5335 binop(Iop_And32, 5336 mkexpr(t6), 5337 mkU32(0x00000100)), 5338 mkU32(0x00000100))); 5339 5340 assign(t8, 5341 binop(Iop_Or32, 5342 binop(Iop_Or32, 5343 binop(Iop_Or32, 5344 unop(Iop_1Sto32, mkexpr(t7)), 5345 unop(Iop_1Sto32, mkexpr(t5))), 5346 unop(Iop_1Sto32, mkexpr(t3))), 5347 unop(Iop_1Sto32, mkexpr(t1)))); 5348 5349 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5350 mkexpr(t8), 5351 mkU32(0x0)), 5352 getDSPControl(), 5353 binop(Iop_Or32, 5354 getDSPControl(), 5355 mkU32(0x00100000)))); 5356 5357 putIReg(rd, binop(Iop_16HLto32, 5358 binop(Iop_8HLto16, 5359 unop(Iop_32to8, mkexpr(t6)), 5360 unop(Iop_32to8, mkexpr(t4))), 5361 binop(Iop_8HLto16, 5362 unop(Iop_32to8, mkexpr(t2)), 5363 unop(Iop_32to8, mkexpr(t0))))); 5364 break; 5365 } 5366 case 0x1: { /* SUBU.QB */ 5367 DIP("subu.qb r%u, r%u, r%u", rd, rs, rt); 5368 vassert(!mode64); 5369 t0 = newTemp(Ity_I32); 5370 t1 = newTemp(Ity_I1); 5371 t2 = newTemp(Ity_I32); 5372 t3 = newTemp(Ity_I1); 5373 t4 = newTemp(Ity_I32); 5374 t5 = newTemp(Ity_I1); 5375 t6 = newTemp(Ity_I32); 5376 t7 = newTemp(Ity_I1); 5377 t8 = newTemp(Ity_I32); 5378 5379 /* Subtract rightmost bytes of rs and rt. */ 5380 assign(t0, 5381 binop(Iop_Sub32, 5382 unop(Iop_8Uto32, 5383 unop(Iop_16to8, 5384 unop(Iop_32to16, getIReg(rs)))), 5385 unop(Iop_8Uto32, 5386 unop(Iop_16to8, 5387 unop(Iop_32to16, getIReg(rt)))))); 5388 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5389 assign(t1, binop(Iop_CmpEQ32, 5390 binop(Iop_And32, 5391 mkexpr(t0), 5392 mkU32(0x00000100)), 5393 mkU32(0x00000100))); 5394 5395 /* Subtract bits 15-8 of rs and rt. */ 5396 assign(t2, 5397 binop(Iop_Sub32, 5398 unop(Iop_8Uto32, 5399 unop(Iop_16HIto8, 5400 unop(Iop_32to16, getIReg(rs)))), 5401 unop(Iop_8Uto32, 5402 unop(Iop_16HIto8, 5403 unop(Iop_32to16, getIReg(rt)))))); 5404 /* t3 will be 1 if there is overflow, 0 otherwise. */ 5405 assign(t3, binop(Iop_CmpEQ32, 5406 binop(Iop_And32, 5407 mkexpr(t2), 5408 mkU32(0x00000100)), 5409 mkU32(0x00000100))); 5410 5411 /* Subtract bits 15-8 of rs and rt. */ 5412 assign(t4, 5413 binop(Iop_Sub32, 5414 unop(Iop_8Uto32, 5415 unop(Iop_16to8, 5416 unop(Iop_32HIto16, getIReg(rs)))), 5417 unop(Iop_8Uto32, 5418 unop(Iop_16to8, 5419 unop(Iop_32HIto16, getIReg(rt)))))); 5420 /* t5 will be 1 if there is overflow, 0 otherwise. */ 5421 assign(t5, binop(Iop_CmpEQ32, 5422 binop(Iop_And32, 5423 mkexpr(t4), 5424 mkU32(0x00000100)), 5425 mkU32(0x00000100))); 5426 5427 /* Subtract bits 15-8 of rs and rt. */ 5428 assign(t6, 5429 binop(Iop_Sub32, 5430 unop(Iop_8Uto32, 5431 unop(Iop_16HIto8, 5432 unop(Iop_32HIto16, getIReg(rs)))), 5433 unop(Iop_8Uto32, 5434 unop(Iop_16HIto8, 5435 unop(Iop_32HIto16, getIReg(rt)))))); 5436 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5437 assign(t7, binop(Iop_CmpEQ32, 5438 binop(Iop_And32, 5439 mkexpr(t6), 5440 mkU32(0x00000100)), 5441 mkU32(0x00000100))); 5442 5443 assign(t8, binop(Iop_Or32, 5444 binop(Iop_Or32, 5445 binop(Iop_Or32, 5446 unop(Iop_1Sto32, mkexpr(t7)), 5447 unop(Iop_1Sto32, mkexpr(t5))), 5448 unop(Iop_1Sto32, mkexpr(t3))), 5449 unop(Iop_1Sto32, mkexpr(t1)))); 5450 5451 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5452 mkexpr(t8), 5453 mkU32(0x0)), 5454 getDSPControl(), 5455 binop(Iop_Or32, 5456 getDSPControl(), 5457 mkU32(0x00100000)))); 5458 5459 putIReg(rd, binop(Iop_16HLto32, 5460 binop(Iop_8HLto16, 5461 unop(Iop_32to8, mkexpr(t6)), 5462 unop(Iop_32to8, mkexpr(t4))), 5463 binop(Iop_8HLto16, 5464 unop(Iop_32to8, mkexpr(t2)), 5465 unop(Iop_32to8, mkexpr(t0))))); 5466 break; 5467 } 5468 case 0x04: { /* ADDU_S.QB */ 5469 DIP("addu_s.qb r%u, r%u, r%u", rd, rs, rt); 5470 vassert(!mode64); 5471 t0 = newTemp(Ity_I32); 5472 t1 = newTemp(Ity_I1); 5473 t2 = newTemp(Ity_I8); 5474 t3 = newTemp(Ity_I32); 5475 t4 = newTemp(Ity_I1); 5476 t5 = newTemp(Ity_I8); 5477 t6 = newTemp(Ity_I32); 5478 t7 = newTemp(Ity_I1); 5479 t8 = newTemp(Ity_I8); 5480 t9 = newTemp(Ity_I32); 5481 t10 = newTemp(Ity_I1); 5482 t11 = newTemp(Ity_I8); 5483 t12 = newTemp(Ity_I32); 5484 5485 /* Add rightmost bytes of rs and rt. */ 5486 assign(t0, 5487 binop(Iop_Add32, 5488 unop(Iop_8Uto32, 5489 unop(Iop_16to8, 5490 unop(Iop_32to16, getIReg(rs)))), 5491 unop(Iop_8Uto32, 5492 unop(Iop_16to8, 5493 unop(Iop_32to16, getIReg(rt)))))); 5494 /* t1 will be 1 if there is overflow, 0 otherwise. */ 5495 assign(t1, binop(Iop_CmpEQ32, 5496 binop(Iop_And32, 5497 mkexpr(t0), 5498 mkU32(0x00000100)), 5499 mkU32(0x00000100))); 5500 /* Saturate if necessary. */ 5501 assign(t2, IRExpr_ITE(mkexpr(t1), 5502 mkU8(0xff), 5503 unop(Iop_32to8, mkexpr(t0)))); 5504 5505 /* Add bits 15-8 of rs and rt. */ 5506 assign(t3, 5507 binop(Iop_Add32, 5508 unop(Iop_8Uto32, 5509 unop(Iop_16HIto8, 5510 unop(Iop_32to16, getIReg(rs)))), 5511 unop(Iop_8Uto32, 5512 unop(Iop_16HIto8, 5513 unop(Iop_32to16, getIReg(rt)))))); 5514 /* t4 will be 1 if there is overflow, 0 otherwise. */ 5515 assign(t4, binop(Iop_CmpEQ32, 5516 binop(Iop_And32, 5517 mkexpr(t3), 5518 mkU32(0x00000100)), 5519 mkU32(0x00000100))); 5520 /* Saturate if necessary. */ 5521 assign(t5, IRExpr_ITE(mkexpr(t4), 5522 mkU8(0xff), 5523 unop(Iop_32to8, mkexpr(t3)))); 5524 5525 /* Add bits 15-8 of rs and rt. */ 5526 assign(t6, 5527 binop(Iop_Add32, 5528 unop(Iop_8Uto32, 5529 unop(Iop_16to8, 5530 unop(Iop_32HIto16, getIReg(rs)))), 5531 unop(Iop_8Uto32, 5532 unop(Iop_16to8, 5533 unop(Iop_32HIto16, getIReg(rt)))))); 5534 /* t7 will be 1 if there is overflow, 0 otherwise. */ 5535 assign(t7, binop(Iop_CmpEQ32, 5536 binop(Iop_And32, 5537 mkexpr(t6), 5538 mkU32(0x00000100)), 5539 mkU32(0x00000100))); 5540 /* Saturate if necessary. */ 5541 assign(t8, IRExpr_ITE(mkexpr(t7), 5542 mkU8(0xff), 5543 unop(Iop_32to8, mkexpr(t6)))); 5544 5545 /* Add bits 15-8 of rs and rt. */ 5546 assign(t9, 5547 binop(Iop_Add32, 5548 unop(Iop_8Uto32, 5549 unop(Iop_16HIto8, 5550 unop(Iop_32HIto16, getIReg(rs)))), 5551 unop(Iop_8Uto32, 5552 unop(Iop_16HIto8, 5553 unop(Iop_32HIto16, getIReg(rt)))))); 5554 /* t10 will be 1 if there is overflow, 0 otherwise. */ 5555 assign(t10, binop(Iop_CmpEQ32, 5556 binop(Iop_And32, 5557 mkexpr(t9), 5558 mkU32(0x00000100)), 5559 mkU32(0x00000100))); 5560 /* Saturate if necessary. */ 5561 assign(t11, IRExpr_ITE(mkexpr(t10), 5562 mkU8(0xff), 5563 unop(Iop_32to8, mkexpr(t9)))); 5564 5565 assign(t12, 5566 binop(Iop_Or32, 5567 binop(Iop_Or32, 5568 binop(Iop_Or32, 5569 unop(Iop_1Sto32, mkexpr(t10)), 5570 unop(Iop_1Sto32, mkexpr(t7))), 5571 unop(Iop_1Sto32, mkexpr(t4))), 5572 unop(Iop_1Sto32, mkexpr(t1)))); 5573 5574 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 5575 mkexpr(t12), 5576 mkU32(0x0)), 5577 getDSPControl(), 5578 binop(Iop_Or32, 5579 getDSPControl(), 5580 mkU32(0x00100000)))); 5581 5582 putIReg(rd, 5583 binop(Iop_16HLto32, 5584 binop(Iop_8HLto16, mkexpr(t11), mkexpr(t8)), 5585 binop(Iop_8HLto16, mkexpr(t5), mkexpr(t2)))); 5586 break; 5587 } 5588 case 0x05: { /* SUBU_S.QB */ 5589 DIP("subu_s.qb r%u, r%u, r%u", rd, rs, rt); 5590 vassert(!mode64); 5591 t1 = newTemp(Ity_I32); 5592 t2 = newTemp(Ity_I1); 5593 t3 = newTemp(Ity_I1); 5594 t4 = newTemp(Ity_I1); 5595 t5 = newTemp(Ity_I1); 5596 t6 = newTemp(Ity_I32); 5597 t7 = newTemp(Ity_I32); 5598 t8 = newTemp(Ity_I32); 5599 t9 = newTemp(Ity_I32); 5600 5601 /* Use C function to easily calculate the result 5602 and write it in the register more conveniently 5603 Underflow is checked using step by step subtraction. */ 5604 assign(t1, binop(Iop_QSub8Ux4, getIReg(rs), getIReg(rt))); 5605 5606 /* Subtract each byte of rs and rt. */ 5607 assign(t6, 5608 binop(Iop_Sub32, 5609 unop(Iop_8Uto32, 5610 unop(Iop_16to8, 5611 unop(Iop_32to16, getIReg(rs)))), 5612 unop(Iop_8Uto32, 5613 unop(Iop_16to8, 5614 unop(Iop_32to16, getIReg(rt)))))); 5615 assign(t7, 5616 binop(Iop_Sub32, 5617 unop(Iop_8Uto32, 5618 unop(Iop_16HIto8, 5619 unop(Iop_32to16, getIReg(rs)))), 5620 unop(Iop_8Uto32, 5621 unop(Iop_16HIto8, 5622 unop(Iop_32to16, getIReg(rt)))))); 5623 assign(t8, 5624 binop(Iop_Sub32, 5625 unop(Iop_8Uto32, 5626 unop(Iop_16to8, 5627 unop(Iop_32HIto16, getIReg(rs)))), 5628 unop(Iop_8Uto32, 5629 unop(Iop_16to8, 5630 unop(Iop_32HIto16, getIReg(rt)))))); 5631 assign(t9, 5632 binop(Iop_Sub32, 5633 unop(Iop_8Uto32, 5634 unop(Iop_16HIto8, 5635 unop(Iop_32HIto16, getIReg(rs)))), 5636 unop(Iop_8Uto32, 5637 unop(Iop_16HIto8, 5638 unop(Iop_32HIto16, getIReg(rt)))))); 5639 5640 /* Put 1 to bit 20 in DSPControl if there is underflow 5641 in either byte. */ 5642 assign(t2, binop(Iop_CmpEQ32, 5643 binop(Iop_And32, 5644 mkexpr(t6), 5645 mkU32(0x00000100)), 5646 mkU32(0x00000100))); 5647 putDSPControl(IRExpr_ITE(mkexpr(t2), 5648 binop(Iop_Or32, 5649 getDSPControl(), 5650 mkU32(0x00100000)), 5651 getDSPControl())); 5652 assign(t3, binop(Iop_CmpEQ32, 5653 binop(Iop_And32, 5654 mkexpr(t7), 5655 mkU32(0x00000100)), 5656 mkU32(0x00000100))); 5657 putDSPControl(IRExpr_ITE(mkexpr(t3), 5658 binop(Iop_Or32, 5659 getDSPControl(), 5660 mkU32(0x00100000)), 5661 getDSPControl())); 5662 assign(t4, binop(Iop_CmpEQ32, 5663 binop(Iop_And32, 5664 mkexpr(t8), 5665 mkU32(0x00000100)), 5666 mkU32(0x00000100))); 5667 putDSPControl(IRExpr_ITE(mkexpr(t4), 5668 binop(Iop_Or32, 5669 getDSPControl(), 5670 mkU32(0x00100000)), 5671 getDSPControl())); 5672 assign(t5, binop(Iop_CmpEQ32, 5673 binop(Iop_And32, 5674 mkexpr(t9), 5675 mkU32(0x00000100)), 5676 mkU32(0x00000100))); 5677 putDSPControl(IRExpr_ITE(mkexpr(t5), 5678 binop(Iop_Or32, 5679 getDSPControl(), 5680 mkU32(0x00100000)), 5681 getDSPControl())); 5682 putIReg(rd, mkexpr(t1)); 5683 break; 5684 } 5685 case 0x6: { /* MULEU_S.PH.QBL */ 5686 DIP("muleu_s.ph.qbl r%u, r%u, r%u", rd, rs, rt); 5687 vassert(!mode64); 5688 t0 = newTemp(Ity_I32); 5689 t1 = newTemp(Ity_I32); 5690 t2 = newTemp(Ity_I1); 5691 t3 = newTemp(Ity_I1); 5692 5693 assign(t0, 5694 unop(Iop_64to32, 5695 binop(Iop_MullU32, 5696 unop(Iop_8Uto32, 5697 unop(Iop_16HIto8, 5698 unop(Iop_32HIto16, 5699 getIReg(rs)))), 5700 unop(Iop_16Uto32, 5701 unop(Iop_32HIto16, getIReg(rt)))))); 5702 assign(t1, 5703 unop(Iop_64to32, 5704 binop(Iop_MullU32, 5705 unop(Iop_8Uto32, 5706 unop(Iop_16to8, 5707 unop(Iop_32HIto16, 5708 getIReg(rs)))), 5709 unop(Iop_16Uto32, 5710 unop(Iop_32to16, getIReg(rt)))))); 5711 5712 assign(t2, binop(Iop_CmpNE32, 5713 mkU32(0x0), 5714 binop(Iop_And32, 5715 mkexpr(t0), 5716 mkU32(0x03ff0000)))); 5717 assign(t3, binop(Iop_CmpNE32, 5718 mkU32(0x0), 5719 binop(Iop_And32, 5720 mkexpr(t1), 5721 mkU32(0x03ff0000)))); 5722 putDSPControl(IRExpr_ITE(mkexpr(t2), 5723 binop(Iop_Or32, 5724 getDSPControl(), 5725 mkU32(0x200000)), 5726 IRExpr_ITE(mkexpr(t3), 5727 binop(Iop_Or32, 5728 getDSPControl(), 5729 mkU32(0x200000)), 5730 getDSPControl()))); 5731 putIReg(rd, 5732 binop(Iop_16HLto32, 5733 IRExpr_ITE(mkexpr(t2), 5734 mkU16(0xffff), 5735 unop(Iop_32to16, mkexpr(t0))), 5736 IRExpr_ITE(mkexpr(t3), 5737 mkU16(0xffff), 5738 unop(Iop_32to16, mkexpr(t1))))); 5739 break; 5740 } 5741 case 0x7: { /* MULEU_S.PH.QBR */ 5742 DIP("muleu_s.ph.qbr r%u, r%u, r%u", rd, rs, rt); 5743 vassert(!mode64); 5744 t0 = newTemp(Ity_I32); 5745 t1 = newTemp(Ity_I32); 5746 t2 = newTemp(Ity_I1); 5747 t3 = newTemp(Ity_I1); 5748 5749 assign(t0, unop(Iop_64to32, 5750 binop(Iop_MullU32, 5751 unop(Iop_8Uto32, 5752 unop(Iop_16HIto8, 5753 unop(Iop_32to16, 5754 getIReg(rs)))), 5755 unop(Iop_16Uto32, 5756 unop(Iop_32HIto16, 5757 getIReg(rt)))))); 5758 assign(t1, unop(Iop_64to32, 5759 binop(Iop_MullU32, 5760 unop(Iop_8Uto32, 5761 unop(Iop_16to8, 5762 unop(Iop_32to16, 5763 getIReg(rs)))), 5764 unop(Iop_16Uto32, 5765 unop(Iop_32to16, 5766 getIReg(rt)))))); 5767 5768 assign(t2, binop(Iop_CmpNE32, 5769 mkU32(0x0), 5770 binop(Iop_And32, 5771 mkexpr(t0), 5772 mkU32(0x03ff0000)))); 5773 assign(t3, binop(Iop_CmpNE32, 5774 mkU32(0x0), 5775 binop(Iop_And32, 5776 mkexpr(t1), 5777 mkU32(0x03ff0000)))); 5778 putDSPControl(IRExpr_ITE(mkexpr(t2), 5779 binop(Iop_Or32, 5780 getDSPControl(), 5781 mkU32(0x200000)), 5782 IRExpr_ITE(mkexpr(t3), 5783 binop(Iop_Or32, 5784 getDSPControl(), 5785 mkU32(0x200000)), 5786 getDSPControl()))); 5787 putIReg(rd, binop(Iop_16HLto32, 5788 IRExpr_ITE(mkexpr(t2), 5789 mkU16(0xffff), 5790 unop(Iop_32to16, 5791 mkexpr(t0))), 5792 IRExpr_ITE(mkexpr(t3), 5793 mkU16(0xffff), 5794 unop(Iop_32to16, 5795 mkexpr(t1))))); 5796 break; 5797 } 5798 case 0x08: { /* ADDU.PH */ 5799 DIP("addu.ph r%u, r%u, r%u", rd, rs, rt); 5800 vassert(!mode64); 5801 t0 = newTemp(Ity_I32); 5802 t1 = newTemp(Ity_I1); 5803 t2 = newTemp(Ity_I32); 5804 t3 = newTemp(Ity_I1); 5805 5806 /* Add lower halves. */ 5807 assign(t0, binop(Iop_Add32, 5808 unop(Iop_16Uto32, 5809 unop(Iop_32to16, getIReg(rs))), 5810 unop(Iop_16Uto32, 5811 unop(Iop_32to16, getIReg(rt))))); 5812 5813 /* Detect overflow. */ 5814 assign(t1, binop(Iop_CmpLT32U, 5815 unop(Iop_16Uto32, 5816 unop(Iop_32to16, mkexpr(t0))), 5817 unop(Iop_16Uto32, 5818 unop(Iop_32to16, getIReg(rs))))); 5819 5820 putDSPControl(IRExpr_ITE(mkexpr(t1), 5821 binop(Iop_Or32, 5822 getDSPControl(), 5823 mkU32(0x00100000)), 5824 getDSPControl())); 5825 5826 /* Add higher halves. */ 5827 assign(t2, binop(Iop_Add32, 5828 unop(Iop_16Uto32, 5829 unop(Iop_32HIto16, getIReg(rs))), 5830 unop(Iop_16Uto32, 5831 unop(Iop_32HIto16, getIReg(rt))))); 5832 5833 /* Detect overflow. */ 5834 assign(t3, binop(Iop_CmpLT32U, 5835 unop(Iop_16Uto32, 5836 unop(Iop_32to16, mkexpr(t2))), 5837 unop(Iop_16Uto32, 5838 unop(Iop_32HIto16, 5839 getIReg(rs))))); 5840 5841 putDSPControl(IRExpr_ITE(mkexpr(t3), 5842 binop(Iop_Or32, 5843 getDSPControl(), 5844 mkU32(0x00100000)), 5845 getDSPControl())); 5846 5847 putIReg(rd, binop(Iop_16HLto32, 5848 unop(Iop_32to16, mkexpr(t2)), 5849 unop(Iop_32to16, mkexpr(t0)))); 5850 break; 5851 } 5852 case 0x9: { /* SUBU.PH */ 5853 DIP("subu.ph r%u, r%u, r%u", rd, rs, rt); 5854 vassert(!mode64); 5855 t0 = newTemp(Ity_I32); 5856 t1 = newTemp(Ity_I1); 5857 t2 = newTemp(Ity_I32); 5858 t3 = newTemp(Ity_I1); 5859 5860 /* Substract lower halves. */ 5861 assign(t0, binop(Iop_Sub32, 5862 unop(Iop_16Uto32, 5863 unop(Iop_32to16, getIReg(rs))), 5864 unop(Iop_16Uto32, 5865 unop(Iop_32to16, getIReg(rt))))); 5866 5867 /* Detect underflow. */ 5868 assign(t1, binop(Iop_CmpNE32, 5869 binop(Iop_And32, 5870 mkexpr(t0), 5871 mkU32(0x00010000)), 5872 mkU32(0x0))); 5873 5874 putDSPControl(IRExpr_ITE(mkexpr(t1), 5875 binop(Iop_Or32, 5876 getDSPControl(), 5877 mkU32(0x00100000)), 5878 getDSPControl())); 5879 5880 /* Subtract higher halves. */ 5881 assign(t2, binop(Iop_Sub32, 5882 unop(Iop_16Uto32, 5883 unop(Iop_32HIto16, getIReg(rs))), 5884 unop(Iop_16Uto32, 5885 unop(Iop_32HIto16, getIReg(rt))))); 5886 5887 /* Detect underflow. */ 5888 assign(t3, binop(Iop_CmpNE32, 5889 binop(Iop_And32, 5890 mkexpr(t2), 5891 mkU32(0x00010000)), 5892 mkU32(0x0))); 5893 5894 putDSPControl(IRExpr_ITE(mkexpr(t3), 5895 binop(Iop_Or32, 5896 getDSPControl(), 5897 mkU32(0x00100000)), 5898 getDSPControl())); 5899 5900 putIReg(rd, binop(Iop_16HLto32, 5901 unop(Iop_32to16, mkexpr(t2)), 5902 unop(Iop_32to16, mkexpr(t0)))); 5903 break; 5904 } 5905 case 0xA: { /* ADDQ.PH */ 5906 DIP("addq.ph r%u, r%u, r%u", rd, rs, rt); 5907 vassert(!mode64); 5908 t0 = newTemp(Ity_I32); 5909 t1 = newTemp(Ity_I1); 5910 t2 = newTemp(Ity_I32); 5911 t3 = newTemp(Ity_I1); 5912 t6 = newTemp(Ity_I32); 5913 t7 = newTemp(Ity_I32); 5914 5915 /* Add lower halves. */ 5916 assign(t0, binop(Iop_Add32, 5917 unop(Iop_16Sto32, 5918 unop(Iop_32to16, getIReg(rs))), 5919 unop(Iop_16Sto32, 5920 unop(Iop_32to16, getIReg(rt))))); 5921 5922 /* Bit 16 of the result. */ 5923 assign(t6, binop(Iop_And32, 5924 unop(Iop_16Uto32, 5925 unop(Iop_32HIto16, mkexpr(t0))), 5926 mkU32(0x1))); 5927 /* Detect overflow. */ 5928 assign(t1, binop(Iop_CmpNE32, 5929 binop(Iop_Shr32, 5930 binop(Iop_And32, 5931 mkexpr(t0), 5932 mkU32(0x8000)), 5933 mkU8(15)), 5934 mkexpr(t6))); 5935 5936 putDSPControl(IRExpr_ITE(mkexpr(t1), 5937 binop(Iop_Or32, 5938 getDSPControl(), 5939 mkU32(0x00100000)), 5940 getDSPControl())); 5941 5942 /* Add higher halves. */ 5943 assign(t2, binop(Iop_Add32, 5944 unop(Iop_16Sto32, 5945 unop(Iop_32HIto16, getIReg(rs))), 5946 unop(Iop_16Sto32, 5947 unop(Iop_32HIto16, getIReg(rt))))); 5948 5949 /* Bit 16 of the result. */ 5950 assign(t7, binop(Iop_And32, 5951 unop(Iop_16Uto32, 5952 unop(Iop_32HIto16, mkexpr(t2))), 5953 mkU32(0x1))); 5954 /* Detect overflow. */ 5955 assign(t3, binop(Iop_CmpNE32, 5956 binop(Iop_Shr32, 5957 binop(Iop_And32, 5958 mkexpr(t2), 5959 mkU32(0x00008000)), 5960 mkU8(15)), 5961 mkexpr(t7))); 5962 5963 putDSPControl(IRExpr_ITE(mkexpr(t3), 5964 binop(Iop_Or32, 5965 getDSPControl(), 5966 mkU32(0x00100000)), 5967 getDSPControl())); 5968 5969 putIReg(rd, binop(Iop_16HLto32, 5970 unop(Iop_32to16, mkexpr(t2)), 5971 unop(Iop_32to16, mkexpr(t0)))); 5972 break; 5973 } 5974 case 0xB: { /* SUBQ.PH */ 5975 DIP("subq.ph r%u, r%u, r%u", rd, rs, rt); 5976 vassert(!mode64); 5977 t0 = newTemp(Ity_I32); 5978 t1 = newTemp(Ity_I1); 5979 t2 = newTemp(Ity_I32); 5980 t3 = newTemp(Ity_I1); 5981 t6 = newTemp(Ity_I32); 5982 t7 = newTemp(Ity_I32); 5983 5984 /* Subtract lower halves. */ 5985 assign(t0, binop(Iop_Sub32, 5986 unop(Iop_16Sto32, 5987 unop(Iop_32to16, getIReg(rs))), 5988 unop(Iop_16Sto32, 5989 unop(Iop_32to16, getIReg(rt))))); 5990 5991 /* Bit 16 of the result. */ 5992 assign(t6, binop(Iop_And32, 5993 unop(Iop_16Uto32, 5994 unop(Iop_32HIto16, mkexpr(t0))), 5995 mkU32(0x1))); 5996 /* Compare the signs of input value and the result. */ 5997 assign(t1, binop(Iop_CmpNE32, 5998 binop(Iop_Shr32, 5999 binop(Iop_And32, 6000 mkexpr(t0), 6001 mkU32(0x8000)), 6002 mkU8(15)), 6003 mkexpr(t6))); 6004 6005 putDSPControl(IRExpr_ITE(mkexpr(t1), 6006 binop(Iop_Or32, 6007 getDSPControl(), 6008 mkU32(0x00100000)), 6009 getDSPControl())); 6010 6011 /* Subtract higher halves. */ 6012 assign(t2, binop(Iop_Sub32, 6013 unop(Iop_16Sto32, 6014 unop(Iop_32HIto16, getIReg(rs))), 6015 unop(Iop_16Sto32, 6016 unop(Iop_32HIto16, getIReg(rt))))); 6017 6018 /* Bit 16 of the result. */ 6019 assign(t7, binop(Iop_And32, 6020 unop(Iop_16Uto32, 6021 unop(Iop_32HIto16, mkexpr(t2))), 6022 mkU32(0x1))); 6023 /* Compare the signs of input value and the result. */ 6024 assign(t3, binop(Iop_CmpNE32, 6025 binop(Iop_Shr32, 6026 binop(Iop_And32, 6027 mkexpr(t2), 6028 mkU32(0x00008000)), 6029 mkU8(15)), 6030 mkexpr(t7))); 6031 6032 putDSPControl(IRExpr_ITE(mkexpr(t3), 6033 binop(Iop_Or32, 6034 getDSPControl(), 6035 mkU32(0x00100000)), 6036 getDSPControl())); 6037 6038 putIReg(rd, binop(Iop_16HLto32, 6039 unop(Iop_32to16, mkexpr(t2)), 6040 unop(Iop_32to16, mkexpr(t0)))); 6041 break; 6042 } 6043 case 0xC: { /* ADDU_S.PH */ 6044 DIP("addu_s.ph r%u, r%u, r%u", rd, rs, rt); 6045 vassert(!mode64); 6046 t0 = newTemp(Ity_I32); 6047 t1 = newTemp(Ity_I1); 6048 t2 = newTemp(Ity_I32); 6049 t3 = newTemp(Ity_I1); 6050 6051 /* Add lower halves. */ 6052 assign(t0, binop(Iop_Add32, 6053 unop(Iop_16Uto32, 6054 unop(Iop_32to16, getIReg(rs))), 6055 unop(Iop_16Uto32, 6056 unop(Iop_32to16, getIReg(rt))))); 6057 6058 /* Detect overflow. */ 6059 assign(t1, binop(Iop_CmpLT32U, 6060 unop(Iop_16Uto32, 6061 unop(Iop_32to16, mkexpr(t0))), 6062 unop(Iop_16Uto32, 6063 unop(Iop_32to16, getIReg(rs))))); 6064 6065 putDSPControl(IRExpr_ITE(mkexpr(t1), 6066 binop(Iop_Or32, 6067 getDSPControl(), 6068 mkU32(0x00100000)), 6069 getDSPControl())); 6070 6071 /* Add higher halves. */ 6072 assign(t2, binop(Iop_Add32, 6073 unop(Iop_16Uto32, 6074 unop(Iop_32HIto16, getIReg(rs))), 6075 unop(Iop_16Uto32, 6076 unop(Iop_32HIto16, getIReg(rt))))); 6077 6078 /* Detect overflow. */ 6079 assign(t3, binop(Iop_CmpLT32U, 6080 unop(Iop_16Uto32, 6081 unop(Iop_32to16, mkexpr(t2))), 6082 unop(Iop_16Uto32, 6083 unop(Iop_32HIto16, getIReg(rs))))); 6084 6085 putDSPControl(IRExpr_ITE(mkexpr(t3), 6086 binop(Iop_Or32, 6087 getDSPControl(), 6088 mkU32(0x00100000)), 6089 getDSPControl())); 6090 6091 putIReg(rd, binop(Iop_16HLto32, 6092 IRExpr_ITE(mkexpr(t3), 6093 mkU16(0xffff), 6094 unop(Iop_32to16, 6095 mkexpr(t2))), 6096 IRExpr_ITE(mkexpr(t1), 6097 mkU16(0xffff), 6098 unop(Iop_32to16, 6099 mkexpr(t0))))); 6100 break; 6101 } 6102 case 0xD: { /* SUBU_S.PH */ 6103 DIP("subu_s.ph r%u, r%u, r%u", rd, rs, rt); 6104 vassert(!mode64); 6105 t0 = newTemp(Ity_I32); 6106 t1 = newTemp(Ity_I1); 6107 t2 = newTemp(Ity_I32); 6108 t3 = newTemp(Ity_I1); 6109 6110 /* Subtract lower halves. */ 6111 assign(t0, binop(Iop_Sub32, 6112 unop(Iop_16Uto32, 6113 unop(Iop_32to16, getIReg(rs))), 6114 unop(Iop_16Uto32, 6115 unop(Iop_32to16, getIReg(rt))))); 6116 6117 /* Detect underflow. */ 6118 assign(t1, binop(Iop_CmpNE32, 6119 binop(Iop_And32, 6120 mkexpr(t0), mkU32(0x00010000)), 6121 mkU32(0x0))); 6122 6123 putDSPControl(IRExpr_ITE(mkexpr(t1), 6124 binop(Iop_Or32, 6125 getDSPControl(), 6126 mkU32(0x00100000)), 6127 getDSPControl())); 6128 6129 /* Subtract higher halves. */ 6130 assign(t2, binop(Iop_Sub32, 6131 unop(Iop_16Uto32, 6132 unop(Iop_32HIto16, getIReg(rs))), 6133 unop(Iop_16Uto32, 6134 unop(Iop_32HIto16, getIReg(rt))))); 6135 6136 /* Detect underflow. */ 6137 assign(t3, binop(Iop_CmpNE32, 6138 binop(Iop_And32, 6139 mkexpr(t2), mkU32(0x00010000)), 6140 mkU32(0x0))); 6141 6142 putDSPControl(IRExpr_ITE(mkexpr(t3), 6143 binop(Iop_Or32, 6144 getDSPControl(), 6145 mkU32(0x00100000)), 6146 getDSPControl())); 6147 6148 putIReg(rd, 6149 binop(Iop_16HLto32, 6150 IRExpr_ITE(mkexpr(t3), 6151 mkU16(0x0000), 6152 unop(Iop_32to16, mkexpr(t2))), 6153 IRExpr_ITE(mkexpr(t1), 6154 mkU16(0x0000), 6155 unop(Iop_32to16, mkexpr(t0))))); 6156 break; 6157 } 6158 case 0xE: { /* ADDQ_S.PH */ 6159 DIP("addq_s.ph r%u r%u, r%u", rd, rs, rt); 6160 vassert(!mode64); 6161 t0 = newTemp(Ity_I32); 6162 t1 = newTemp(Ity_I1); 6163 t2 = newTemp(Ity_I32); 6164 t3 = newTemp(Ity_I1); 6165 t4 = newTemp(Ity_I16); 6166 t5 = newTemp(Ity_I16); 6167 t6 = newTemp(Ity_I32); 6168 t7 = newTemp(Ity_I32); 6169 6170 /* Add lower halves. */ 6171 assign(t0, binop(Iop_Add32, 6172 unop(Iop_16Sto32, 6173 unop(Iop_32to16, getIReg(rs))), 6174 unop(Iop_16Sto32, 6175 unop(Iop_32to16, getIReg(rt))))); 6176 6177 /* Bit 16 of the result. */ 6178 assign(t6, binop(Iop_And32, 6179 unop(Iop_16Uto32, 6180 unop(Iop_32HIto16, mkexpr(t0))), 6181 mkU32(0x1))); 6182 /* Detect overflow. */ 6183 assign(t1, binop(Iop_CmpNE32, 6184 binop(Iop_Shr32, 6185 binop(Iop_And32, 6186 mkexpr(t0), 6187 mkU32(0x8000)), 6188 mkU8(15)), 6189 mkexpr(t6))); 6190 6191 putDSPControl(IRExpr_ITE(mkexpr(t1), 6192 binop(Iop_Or32, 6193 getDSPControl(), 6194 mkU32(0x00100000)), 6195 getDSPControl())); 6196 /* Saturate if needed. */ 6197 assign(t4, IRExpr_ITE(mkexpr(t1), 6198 IRExpr_ITE(binop(Iop_CmpEQ32, 6199 mkexpr(t6), 6200 mkU32(0x0)), 6201 mkU16(0x7fff), 6202 mkU16(0x8000)), 6203 unop(Iop_32to16, mkexpr(t0)))); 6204 6205 /* Add higher halves. */ 6206 assign(t2, binop(Iop_Add32, 6207 unop(Iop_16Sto32, 6208 unop(Iop_32HIto16, getIReg(rs))), 6209 unop(Iop_16Sto32, 6210 unop(Iop_32HIto16, getIReg(rt))))); 6211 6212 /* Bit 16 of the result. */ 6213 assign(t7, binop(Iop_And32, 6214 unop(Iop_16Uto32, 6215 unop(Iop_32HIto16, mkexpr(t2))), 6216 mkU32(0x1))); 6217 /* Detect overflow. */ 6218 assign(t3, binop(Iop_CmpNE32, 6219 binop(Iop_Shr32, 6220 binop(Iop_And32, 6221 mkexpr(t2), 6222 mkU32(0x00008000)), 6223 mkU8(15)), 6224 mkexpr(t7))); 6225 6226 putDSPControl(IRExpr_ITE(mkexpr(t3), 6227 binop(Iop_Or32, 6228 getDSPControl(), 6229 mkU32(0x00100000)), 6230 getDSPControl())); 6231 /* Saturate if needed. */ 6232 assign(t5, IRExpr_ITE(mkexpr(t3), 6233 IRExpr_ITE(binop(Iop_CmpEQ32, 6234 mkexpr(t7), 6235 mkU32(0x0)), 6236 mkU16(0x7fff), 6237 mkU16(0x8000)), 6238 unop(Iop_32to16, mkexpr(t2)))); 6239 6240 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6241 break; 6242 } 6243 case 0xF: { /* SUBQ_S.PH */ 6244 DIP("subq_s.ph r%u r%u, r%u", rd, rs, rt); 6245 vassert(!mode64); 6246 t0 = newTemp(Ity_I32); 6247 t1 = newTemp(Ity_I1); 6248 t2 = newTemp(Ity_I32); 6249 t3 = newTemp(Ity_I1); 6250 t4 = newTemp(Ity_I16); 6251 t5 = newTemp(Ity_I16); 6252 t6 = newTemp(Ity_I32); 6253 t7 = newTemp(Ity_I32); 6254 6255 /* Subtract lower halves. */ 6256 assign(t0, binop(Iop_Sub32, 6257 unop(Iop_16Sto32, 6258 unop(Iop_32to16, getIReg(rs))), 6259 unop(Iop_16Sto32, 6260 unop(Iop_32to16, getIReg(rt))))); 6261 6262 /* Bit 16 of the result. */ 6263 assign(t6, binop(Iop_And32, 6264 unop(Iop_16Uto32, 6265 unop(Iop_32HIto16, mkexpr(t0))), 6266 mkU32(0x1))); 6267 /* Detect overflow or underflow. */ 6268 assign(t1, binop(Iop_CmpNE32, 6269 binop(Iop_Shr32, 6270 binop(Iop_And32, 6271 mkexpr(t0), 6272 mkU32(0x8000)), 6273 mkU8(15)), 6274 mkexpr(t6))); 6275 6276 putDSPControl(IRExpr_ITE(mkexpr(t1), 6277 binop(Iop_Or32, 6278 getDSPControl(), 6279 mkU32(0x00100000)), 6280 getDSPControl())); 6281 /* Saturate if needed. */ 6282 assign(t4, IRExpr_ITE(mkexpr(t1), 6283 IRExpr_ITE(binop(Iop_CmpEQ32, 6284 mkexpr(t6), 6285 mkU32(0x0)), 6286 mkU16(0x7fff), 6287 mkU16(0x8000)), 6288 unop(Iop_32to16, mkexpr(t0)))); 6289 6290 /* Subtract higher halves. */ 6291 assign(t2, binop(Iop_Sub32, 6292 unop(Iop_16Sto32, 6293 unop(Iop_32HIto16, getIReg(rs))), 6294 unop(Iop_16Sto32, 6295 unop(Iop_32HIto16, getIReg(rt))))); 6296 6297 /* Bit 16 of the result. */ 6298 assign(t7, binop(Iop_And32, 6299 unop(Iop_16Uto32, 6300 unop(Iop_32HIto16, mkexpr(t2))), 6301 mkU32(0x1))); 6302 /* Detect overflow or underflow. */ 6303 assign(t3, binop(Iop_CmpNE32, 6304 binop(Iop_Shr32, 6305 binop(Iop_And32, 6306 mkexpr(t2), 6307 mkU32(0x00008000)), 6308 mkU8(15)), 6309 mkexpr(t7))); 6310 6311 putDSPControl(IRExpr_ITE(mkexpr(t3), 6312 binop(Iop_Or32, 6313 getDSPControl(), 6314 mkU32(0x00100000)), 6315 getDSPControl())); 6316 /* Saturate if needed. */ 6317 assign(t5, IRExpr_ITE(mkexpr(t3), 6318 IRExpr_ITE(binop(Iop_CmpEQ32, 6319 mkexpr(t7), 6320 mkU32(0x0)), 6321 mkU16(0x7fff), 6322 mkU16(0x8000)), 6323 unop(Iop_32to16, mkexpr(t2)))); 6324 6325 putIReg(rd, binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))); 6326 break; 6327 } 6328 case 0x10: { /* ADDSC */ 6329 DIP("addsc r%u, r%u, r%u", rd, rs, rt); 6330 vassert(!mode64); 6331 t0 = newTemp(Ity_I64); 6332 t1 = newTemp(Ity_I1); 6333 6334 /* The carry bit result out of the addition operation is 6335 written to bit 13(the c field) of the DSPControl reg. */ 6336 assign(t0, binop(Iop_Add64, 6337 unop(Iop_32Uto64, getIReg(rs)), 6338 unop(Iop_32Uto64, getIReg(rt)))); 6339 6340 assign(t1, binop(Iop_CmpEQ32, 6341 binop(Iop_And32, 6342 unop(Iop_64HIto32, mkexpr(t0)), 6343 mkU32(0x1)), 6344 mkU32(0x1))); 6345 putDSPControl(IRExpr_ITE(mkexpr(t1), 6346 binop(Iop_Or32, 6347 getDSPControl(), 6348 mkU32(0x2000)), 6349 binop(Iop_And32, 6350 getDSPControl(), 6351 mkU32(0xffffdfff)))); 6352 6353 putIReg(rd, unop(Iop_64to32, mkexpr(t0))); 6354 break; 6355 } 6356 case 0x11: { /* ADDWC */ 6357 DIP("addwc r%u, r%u, r%u", rd, rs, rt); 6358 vassert(!mode64); 6359 t0 = newTemp(Ity_I32); 6360 t1 = newTemp(Ity_I64); 6361 t2 = newTemp(Ity_I32); 6362 t3 = newTemp(Ity_I32); 6363 t4 = newTemp(Ity_I1); 6364 6365 /* Get carry bit from DSPControl register. */ 6366 assign(t0, binop(Iop_Shr32, 6367 binop(Iop_And32, 6368 getDSPControl(), 6369 mkU32(0x2000)), 6370 mkU8(0xd))); 6371 assign(t1, binop(Iop_Add64, 6372 unop(Iop_32Sto64, getIReg(rs)), 6373 unop(Iop_32Sto64, 6374 binop(Iop_Add32, 6375 getIReg(rt), 6376 mkexpr(t0))))); 6377 6378 /* Extract bits 32 and 31. */ 6379 assign(t2, binop(Iop_And32, 6380 unop(Iop_64HIto32, mkexpr(t1)), 6381 mkU32(0x1))); 6382 assign(t3, binop(Iop_Shr32, 6383 binop(Iop_And32, 6384 unop(Iop_64to32, mkexpr(t1)), 6385 mkU32(0x80000000)), 6386 mkU8(31))); 6387 assign(t4, binop(Iop_CmpNE32, mkexpr(t2), mkexpr(t3))); 6388 6389 putDSPControl(IRExpr_ITE(mkexpr(t4), 6390 binop(Iop_Or32, 6391 getDSPControl(), 6392 mkU32(0x00100000)), 6393 getDSPControl())); 6394 putIReg(rd, unop(Iop_64to32, mkexpr(t1))); 6395 break; 6396 } 6397 case 0x12: { /* MODSUB */ 6398 DIP("modsub r%u, r%u, r%u", rd, rs, rt); 6399 vassert(!mode64); 6400 t0 = newTemp(Ity_I32); 6401 t1 = newTemp(Ity_I32); 6402 t2 = newTemp(Ity_I32); 6403 6404 /* decr_7..0 */ 6405 assign(t0, 6406 unop(Iop_8Uto32, 6407 unop(Iop_16to8, 6408 unop(Iop_32to16, getIReg(rt))))); 6409 6410 /* lastindex_15..0 */ 6411 assign(t1, 6412 unop(Iop_16Uto32, 6413 binop(Iop_8HLto16, 6414 unop(Iop_16to8, 6415 unop(Iop_32HIto16, getIReg(rt))), 6416 unop(Iop_16HIto8, 6417 unop(Iop_32to16, getIReg(rt)))))); 6418 /* temp_15..0 */ 6419 assign(t2, 6420 IRExpr_ITE(binop(Iop_CmpEQ32, 6421 getIReg(rs), 6422 mkU32(0x00000000)), 6423 mkexpr(t1), 6424 binop(Iop_Sub32, 6425 getIReg(rs), mkexpr(t0)))); 6426 putIReg(rd, mkexpr(t2)); 6427 break; 6428 } 6429 case 0x14: { /* RADDU.W.QB */ 6430 DIP("raddu.w.qb r%u, r%u", rd, rs); 6431 vassert(!mode64); 6432 putIReg(rd, binop(Iop_Add32, 6433 binop(Iop_Add32, 6434 unop(Iop_8Uto32, 6435 unop(Iop_16to8, 6436 unop(Iop_32to16, 6437 getIReg(rs)))), 6438 unop(Iop_8Uto32, 6439 unop(Iop_16HIto8, 6440 unop(Iop_32to16, 6441 getIReg(rs))))), 6442 binop(Iop_Add32, 6443 unop(Iop_8Uto32, 6444 unop(Iop_16to8, 6445 unop(Iop_32HIto16, 6446 getIReg(rs)))), 6447 unop(Iop_8Uto32, 6448 unop(Iop_16HIto8, 6449 unop(Iop_32HIto16, 6450 getIReg(rs))))))); 6451 break; 6452 } 6453 case 0x16: { /* ADDQ_S.W */ 6454 DIP("addq_s.w r%u, r%u, r%u", rd, rs, rt); 6455 vassert(!mode64); 6456 t0 = newTemp(Ity_I64); 6457 t1 = newTemp(Ity_I1); 6458 t2 = newTemp(Ity_I32); 6459 t3 = newTemp(Ity_I32); 6460 6461 assign(t0, binop(Iop_Add64, 6462 unop(Iop_32Sto64, getIReg(rs)), 6463 unop(Iop_32Sto64, getIReg(rt)))); 6464 6465 assign(t3, binop(Iop_And32, 6466 unop(Iop_64HIto32, mkexpr(t0)), 6467 mkU32(0x1))); 6468 assign(t1, binop(Iop_CmpNE32, 6469 binop(Iop_Shr32, 6470 binop(Iop_And32, 6471 unop(Iop_64to32, mkexpr(t0)), 6472 mkU32(0x80000000)), 6473 mkU8(31)), 6474 mkexpr(t3))); 6475 6476 putDSPControl(IRExpr_ITE(mkexpr(t1), 6477 binop(Iop_Or32, 6478 getDSPControl(), 6479 mkU32(0x00100000)), 6480 getDSPControl())); 6481 6482 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6483 IRExpr_ITE(binop(Iop_CmpEQ32, 6484 mkexpr(t3), 6485 mkU32(0x0)), 6486 mkU32(0x7fffffff), 6487 mkU32(0x80000000)), 6488 unop(Iop_64to32, mkexpr(t0)))); 6489 break; 6490 } 6491 case 0x17: { /* SUBQ_S.W */ 6492 DIP("subq_s.w r%u, r%u, r%u", rd, rs, rt); 6493 vassert(!mode64); 6494 t0 = newTemp(Ity_I64); 6495 t1 = newTemp(Ity_I1); 6496 t2 = newTemp(Ity_I32); 6497 t3 = newTemp(Ity_I32); 6498 6499 assign(t0, binop(Iop_Sub64, 6500 unop(Iop_32Sto64, getIReg(rs)), 6501 unop(Iop_32Sto64, getIReg(rt)))); 6502 6503 assign(t3, binop(Iop_And32, 6504 unop(Iop_64HIto32, mkexpr(t0)), 6505 mkU32(0x1))); 6506 assign(t1, binop(Iop_CmpNE32, 6507 binop(Iop_Shr32, 6508 binop(Iop_And32, 6509 unop(Iop_64to32, mkexpr(t0)), 6510 mkU32(0x80000000)), 6511 mkU8(31)), 6512 mkexpr(t3))); 6513 6514 putDSPControl(IRExpr_ITE(mkexpr(t1), 6515 binop(Iop_Or32, 6516 getDSPControl(), 6517 mkU32(0x00100000)), 6518 getDSPControl())); 6519 6520 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6521 IRExpr_ITE(binop(Iop_CmpEQ32, 6522 mkexpr(t3), 6523 mkU32(0x0)), 6524 mkU32(0x7fffffff), 6525 mkU32(0x80000000)), 6526 unop(Iop_64to32, mkexpr(t0)))); 6527 break; 6528 } 6529 case 0x1C: { /* MULEQ_S.W.PHL */ 6530 DIP("muleq_s.w.phl r%u, r%u, r%u", rd, rs, rt); 6531 vassert(!mode64); 6532 t0 = newTemp(Ity_I32); 6533 t1 = newTemp(Ity_I1); 6534 t2 = newTemp(Ity_I1); 6535 t3 = newTemp(Ity_I32); 6536 6537 assign(t0, 6538 binop(Iop_Shl32, 6539 binop(Iop_Mul32, 6540 unop(Iop_16Sto32, 6541 unop(Iop_32HIto16, getIReg(rt))), 6542 unop(Iop_16Sto32, 6543 unop(Iop_32HIto16, getIReg(rs)))), 6544 mkU8(0x1))); 6545 assign(t1, binop(Iop_CmpEQ32, 6546 binop(Iop_And32, 6547 getIReg(rt), 6548 mkU32(0xffff0000)), 6549 mkU32(0x80000000))); 6550 assign(t2, binop(Iop_CmpEQ32, 6551 binop(Iop_And32, 6552 getIReg(rs), 6553 mkU32(0xffff0000)), 6554 mkU32(0x80000000))); 6555 assign(t3, IRExpr_ITE(mkexpr(t1), 6556 IRExpr_ITE(mkexpr(t2), 6557 binop(Iop_Or32, 6558 getDSPControl(), 6559 mkU32(0x00200000)), 6560 getDSPControl()), 6561 getDSPControl())); 6562 putDSPControl(mkexpr(t3)); 6563 6564 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6565 IRExpr_ITE(mkexpr(t2), 6566 mkU32(0x7fffffff), 6567 mkexpr(t0)), 6568 mkexpr(t0))); 6569 break; 6570 } 6571 case 0x1D: { /* MULEQ_S.W.PHR */ 6572 DIP("muleq_s.w.phr r%u, r%u, r%u", rd, rs, rt); 6573 vassert(!mode64); 6574 t0 = newTemp(Ity_I32); 6575 t1 = newTemp(Ity_I1); 6576 t2 = newTemp(Ity_I1); 6577 6578 assign(t0, 6579 binop(Iop_Shl32, 6580 binop(Iop_Mul32, 6581 unop(Iop_16Sto32, 6582 unop(Iop_32to16, getIReg(rt))), 6583 unop(Iop_16Sto32, 6584 unop(Iop_32to16, getIReg(rs)))), 6585 mkU8(0x1))); 6586 assign(t1, binop(Iop_CmpEQ32, 6587 binop(Iop_And32, 6588 getIReg(rt), 6589 mkU32(0xffff)), 6590 mkU32(0x8000))); 6591 assign(t2, binop(Iop_CmpEQ32, 6592 binop(Iop_And32, 6593 getIReg(rs), 6594 mkU32(0xffff)), 6595 mkU32(0x8000))); 6596 putDSPControl(IRExpr_ITE(mkexpr(t1), 6597 IRExpr_ITE(mkexpr(t2), 6598 binop(Iop_Or32, 6599 getDSPControl(), 6600 mkU32(0x00200000) 6601 ), 6602 getDSPControl()), 6603 getDSPControl())); 6604 putIReg(rd, IRExpr_ITE(mkexpr(t1), 6605 IRExpr_ITE(mkexpr(t2), 6606 mkU32(0x7fffffff), 6607 mkexpr(t0)), 6608 mkexpr(t0))); 6609 break; 6610 } 6611 case 0x1E: { /* MULQ_S.PH */ 6612 DIP("mulq_s.ph r%u, r%u, r%u", rd, rs, rt); 6613 vassert(!mode64); 6614 t0 = newTemp(Ity_I32); 6615 t1 = newTemp(Ity_I32); 6616 t2 = newTemp(Ity_I16); 6617 t3 = newTemp(Ity_I16); 6618 t5 = newTemp(Ity_I32); 6619 t6 = newTemp(Ity_I32); 6620 t7 = newTemp(Ity_I32); 6621 t8 = newTemp(Ity_I32); 6622 6623 assign(t5, 6624 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rs)))); 6625 assign(t6, 6626 unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 6627 6628 assign(t7, 6629 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rs)))); 6630 assign(t8, 6631 unop(Iop_16Sto32, unop(Iop_32HIto16, getIReg(rt)))); 6632 6633 assign(t0, binop(Iop_And32, 6634 unop(Iop_1Sto32, 6635 binop(Iop_CmpEQ32, 6636 binop(Iop_And32, 6637 mkexpr(t5), 6638 mkU32(0xffff)), 6639 mkU32(0x8000))), 6640 unop(Iop_1Sto32, 6641 binop(Iop_CmpEQ32, 6642 binop(Iop_And32, 6643 mkexpr(t6), 6644 mkU32(0xffff)), 6645 mkU32(0x8000))))); 6646 assign(t1, binop(Iop_And32, 6647 unop(Iop_1Sto32, 6648 binop(Iop_CmpEQ32, 6649 binop(Iop_And32, 6650 mkexpr(t7), 6651 mkU32(0xffff)), 6652 mkU32(0x8000))), 6653 unop(Iop_1Sto32, 6654 binop(Iop_CmpEQ32, 6655 binop(Iop_And32, 6656 mkexpr(t8), 6657 mkU32(0xffff)), 6658 mkU32(0x8000))))); 6659 6660 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 6661 binop(Iop_Or32, 6662 mkexpr(t0), 6663 mkexpr(t1)), 6664 mkU32(0x0)), 6665 getDSPControl(), 6666 binop(Iop_Or32, 6667 getDSPControl(), 6668 mkU32(0x200000)))); 6669 6670 assign(t2, unop(Iop_32HIto16, 6671 binop(Iop_Shl32, 6672 unop(Iop_64to32, 6673 binop(Iop_MullS32, 6674 mkexpr(t7), 6675 mkexpr(t8))), 6676 mkU8(0x1)))); 6677 assign(t3, unop(Iop_32HIto16, 6678 binop(Iop_Shl32, 6679 unop(Iop_64to32, 6680 binop(Iop_MullS32, 6681 mkexpr(t5), 6682 mkexpr(t6))), 6683 mkU8(0x1)))); 6684 putIReg(rd, binop(Iop_16HLto32, 6685 IRExpr_ITE(binop(Iop_CmpEQ32, 6686 mkexpr(t1), 6687 mkU32(0x0)), 6688 mkexpr(t2), 6689 mkU16(0x7fff)), 6690 IRExpr_ITE(binop(Iop_CmpEQ32, 6691 mkexpr(t0), 6692 mkU32(0x0)), 6693 mkexpr(t3), 6694 mkU16(0x7fff)))); 6695 break; 6696 } 6697 case 0x1F: { /* MULQ_RS.PH */ 6698 DIP("mulq_rs.ph r%u, r%u, r%u", rd, rs, rt); 6699 vassert(!mode64); 6700 t0 = newTemp(Ity_I32); 6701 t1 = newTemp(Ity_I1); 6702 t2 = newTemp(Ity_I1); 6703 t3 = newTemp(Ity_I16); 6704 t4 = newTemp(Ity_I32); 6705 t5 = newTemp(Ity_I1); 6706 t6 = newTemp(Ity_I1); 6707 t7 = newTemp(Ity_I16); 6708 6709 /* Multiply and round lower halfwords. */ 6710 assign(t0, binop(Iop_Add32, 6711 binop(Iop_Shl32, 6712 binop(Iop_Mul32, 6713 unop(Iop_16Sto32, 6714 unop(Iop_32to16, 6715 getIReg(rt))), 6716 unop(Iop_16Sto32, 6717 unop(Iop_32to16, 6718 getIReg(rs)))), 6719 mkU8(0x1)), 6720 mkU32(0x00008000))); 6721 assign(t1, binop(Iop_CmpEQ32, 6722 binop(Iop_And32, 6723 getIReg(rt), mkU32(0xffff)), 6724 mkU32(0x8000))); 6725 assign(t2, binop(Iop_CmpEQ32, 6726 binop(Iop_And32, 6727 getIReg(rs), mkU32(0xffff)), 6728 mkU32(0x8000))); 6729 putDSPControl(IRExpr_ITE(mkexpr(t1), 6730 IRExpr_ITE(mkexpr(t2), 6731 binop(Iop_Or32, 6732 getDSPControl(), 6733 mkU32(0x00200000) 6734 ), 6735 getDSPControl()), 6736 getDSPControl())); 6737 assign(t3, IRExpr_ITE(mkexpr(t1), 6738 IRExpr_ITE(mkexpr(t2), 6739 mkU16(0x7fff), 6740 unop(Iop_32HIto16, 6741 mkexpr(t0))), 6742 unop(Iop_32HIto16, mkexpr(t0)))); 6743 6744 /* Multiply and round higher halfwords. */ 6745 assign(t4, binop(Iop_Add32, 6746 binop(Iop_Shl32, 6747 binop(Iop_Mul32, 6748 unop(Iop_16Sto32, 6749 unop(Iop_32HIto16, 6750 getIReg(rt))), 6751 unop(Iop_16Sto32, 6752 unop(Iop_32HIto16, 6753 getIReg(rs)))), 6754 mkU8(0x1)), 6755 mkU32(0x00008000))); 6756 assign(t5, binop(Iop_CmpEQ32, 6757 binop(Iop_And32, 6758 getIReg(rt), 6759 mkU32(0xffff0000)), 6760 mkU32(0x80000000))); 6761 assign(t6, binop(Iop_CmpEQ32, 6762 binop(Iop_And32, 6763 getIReg(rs), 6764 mkU32(0xffff0000)), 6765 mkU32(0x80000000))); 6766 putDSPControl(IRExpr_ITE(mkexpr(t5), 6767 IRExpr_ITE(mkexpr(t6), 6768 binop(Iop_Or32, 6769 getDSPControl(), 6770 mkU32(0x00200000)), 6771 getDSPControl()), 6772 getDSPControl())); 6773 assign(t7, IRExpr_ITE(mkexpr(t5), 6774 IRExpr_ITE(mkexpr(t6), 6775 mkU16(0x7fff), 6776 unop(Iop_32HIto16, 6777 mkexpr(t4))), 6778 unop(Iop_32HIto16, mkexpr(t4)))); 6779 6780 putIReg(rd, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 6781 break; 6782 } 6783 default: 6784 return -1; 6785 } 6786 break; /* end of ADDU.QB */ 6787 } 6788 case 0x11: { /* CMPU.EQ.QB */ 6789 switch(sa) { 6790 case 0x0: { /* CMPU.EQ.QB */ 6791 DIP("cmpu.eq.qb r%u, r%u", rs, rt); 6792 vassert(!mode64); 6793 t1 = newTemp(Ity_I1); 6794 t2 = newTemp(Ity_I1); 6795 t3 = newTemp(Ity_I1); 6796 t4 = newTemp(Ity_I1); 6797 6798 assign(t1, 6799 binop(Iop_CmpEQ32, 6800 binop(Iop_And32, getIReg(rs), mkU32(0xff)), 6801 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 6802 putDSPControl(IRExpr_ITE(mkexpr(t1), 6803 binop(Iop_Or32, 6804 getDSPControl(), 6805 mkU32(0x01000000)), 6806 binop(Iop_And32, 6807 getDSPControl(), 6808 mkU32(0xfeffffff)))); 6809 6810 assign(t2, binop(Iop_CmpEQ32, 6811 unop(Iop_8Uto32, 6812 unop(Iop_16HIto8, 6813 unop(Iop_32to16, 6814 getIReg(rs)))), 6815 unop(Iop_8Uto32, 6816 unop(Iop_16HIto8, 6817 unop(Iop_32to16, 6818 getIReg(rt)))))); 6819 putDSPControl(IRExpr_ITE(mkexpr(t2), 6820 binop(Iop_Or32, 6821 getDSPControl(), 6822 mkU32(0x02000000)), 6823 binop(Iop_And32, 6824 getDSPControl(), 6825 mkU32(0xfdffffff)))); 6826 6827 assign(t3, binop(Iop_CmpEQ32, 6828 unop(Iop_8Uto32, 6829 unop(Iop_16to8, 6830 unop(Iop_32HIto16, 6831 getIReg(rs)))), 6832 unop(Iop_8Uto32, 6833 unop(Iop_16to8, 6834 unop(Iop_32HIto16, 6835 getIReg(rt)))))); 6836 putDSPControl(IRExpr_ITE(mkexpr(t3), 6837 binop(Iop_Or32, 6838 getDSPControl(), 6839 mkU32(0x04000000)), 6840 binop(Iop_And32, 6841 getDSPControl(), 6842 mkU32(0xfbffffff)))); 6843 6844 assign(t4, binop(Iop_CmpEQ32, 6845 unop(Iop_8Uto32, 6846 unop(Iop_16HIto8, 6847 unop(Iop_32HIto16, 6848 getIReg(rs)))), 6849 unop(Iop_8Uto32, 6850 unop(Iop_16HIto8, 6851 unop(Iop_32HIto16, 6852 getIReg(rt)))))); 6853 putDSPControl(IRExpr_ITE(mkexpr(t4), 6854 binop(Iop_Or32, 6855 getDSPControl(), 6856 mkU32(0x08000000)), 6857 binop(Iop_And32, 6858 getDSPControl(), 6859 mkU32(0xf7ffffff)))); 6860 break; 6861 } 6862 case 0x1: { /* CMPU.LT.QB */ 6863 DIP("cmpu.lt.qb r%u, r%u", rs, rt); 6864 vassert(!mode64); 6865 t1 = newTemp(Ity_I1); 6866 t2 = newTemp(Ity_I1); 6867 t3 = newTemp(Ity_I1); 6868 t4 = newTemp(Ity_I1); 6869 6870 assign(t1, binop(Iop_CmpLT32U, 6871 unop(Iop_8Uto32, 6872 unop(Iop_16to8, 6873 unop(Iop_32to16, 6874 getIReg(rs)))), 6875 unop(Iop_8Uto32, 6876 unop(Iop_16to8, 6877 unop(Iop_32to16, 6878 getIReg(rt)))))); 6879 putDSPControl(IRExpr_ITE(mkexpr(t1), 6880 binop(Iop_Or32, 6881 getDSPControl(), 6882 mkU32(0x01000000)), 6883 binop(Iop_And32, 6884 getDSPControl(), 6885 mkU32(0xfeffffff)))); 6886 6887 assign(t2, binop(Iop_CmpLT32U, 6888 unop(Iop_8Uto32, 6889 unop(Iop_16HIto8, 6890 unop(Iop_32to16, 6891 getIReg(rs)))), 6892 unop(Iop_8Uto32, 6893 unop(Iop_16HIto8, 6894 unop(Iop_32to16, 6895 getIReg(rt)))))); 6896 putDSPControl(IRExpr_ITE(mkexpr(t2), 6897 binop(Iop_Or32, 6898 getDSPControl(), 6899 mkU32(0x02000000)), 6900 binop(Iop_And32, 6901 getDSPControl(), 6902 mkU32(0xfdffffff)))); 6903 6904 assign(t3, binop(Iop_CmpLT32U, 6905 unop(Iop_8Uto32, 6906 unop(Iop_16to8, 6907 unop(Iop_32HIto16, 6908 getIReg(rs)))), 6909 unop(Iop_8Uto32, 6910 unop(Iop_16to8, 6911 unop(Iop_32HIto16, 6912 getIReg(rt)))))); 6913 putDSPControl(IRExpr_ITE(mkexpr(t3), 6914 binop(Iop_Or32, 6915 getDSPControl(), 6916 mkU32(0x04000000)), 6917 binop(Iop_And32, 6918 getDSPControl(), 6919 mkU32(0xfbffffff)))); 6920 6921 assign(t4, binop(Iop_CmpLT32U, 6922 unop(Iop_8Uto32, 6923 unop(Iop_16HIto8, 6924 unop(Iop_32HIto16, 6925 getIReg(rs)))), 6926 unop(Iop_8Uto32, 6927 unop(Iop_16HIto8, 6928 unop(Iop_32HIto16, 6929 getIReg(rt)))))); 6930 putDSPControl(IRExpr_ITE(mkexpr(t4), 6931 binop(Iop_Or32, 6932 getDSPControl(), 6933 mkU32(0x08000000)), 6934 binop(Iop_And32, 6935 getDSPControl(), 6936 mkU32(0xf7ffffff)))); 6937 break; 6938 } 6939 case 0x2: { /* CMPU.LE.QB */ 6940 DIP("cmpu.le.qb r%u, r%u", rs, rt); 6941 vassert(!mode64); 6942 t1 = newTemp(Ity_I1); 6943 t2 = newTemp(Ity_I1); 6944 t3 = newTemp(Ity_I1); 6945 t4 = newTemp(Ity_I1); 6946 6947 assign(t1, binop(Iop_CmpLE32U, 6948 unop(Iop_8Uto32, 6949 unop(Iop_16to8, 6950 unop(Iop_32to16, 6951 getIReg(rs)))), 6952 unop(Iop_8Uto32, 6953 unop(Iop_16to8, 6954 unop(Iop_32to16, 6955 getIReg(rt)))))); 6956 putDSPControl(IRExpr_ITE(mkexpr(t1), 6957 binop(Iop_Or32, 6958 getDSPControl(), 6959 mkU32(0x01000000)), 6960 binop(Iop_And32, 6961 getDSPControl(), 6962 mkU32(0xfeffffff)))); 6963 6964 assign(t2, binop(Iop_CmpLE32U, 6965 unop(Iop_8Uto32, 6966 unop(Iop_16HIto8, 6967 unop(Iop_32to16, 6968 getIReg(rs)))), 6969 unop(Iop_8Uto32, 6970 unop(Iop_16HIto8, 6971 unop(Iop_32to16, 6972 getIReg(rt)))))); 6973 putDSPControl(IRExpr_ITE(mkexpr(t2), 6974 binop(Iop_Or32, 6975 getDSPControl(), 6976 mkU32(0x02000000)), 6977 binop(Iop_And32, 6978 getDSPControl(), 6979 mkU32(0xfdffffff)))); 6980 6981 assign(t3, binop(Iop_CmpLE32U, 6982 unop(Iop_8Uto32, 6983 unop(Iop_16to8, 6984 unop(Iop_32HIto16, 6985 getIReg(rs)))), 6986 unop(Iop_8Uto32, 6987 unop(Iop_16to8, 6988 unop(Iop_32HIto16, 6989 getIReg(rt)))))); 6990 putDSPControl(IRExpr_ITE(mkexpr(t3), 6991 binop(Iop_Or32, 6992 getDSPControl(), 6993 mkU32(0x04000000)), 6994 binop(Iop_And32, 6995 getDSPControl(), 6996 mkU32(0xfbffffff)))); 6997 6998 assign(t4, binop(Iop_CmpLE32U, 6999 unop(Iop_8Uto32, 7000 unop(Iop_16HIto8, 7001 unop(Iop_32HIto16, 7002 getIReg(rs)))), 7003 unop(Iop_8Uto32, 7004 unop(Iop_16HIto8, 7005 unop(Iop_32HIto16, 7006 getIReg(rt)))))); 7007 putDSPControl(IRExpr_ITE(mkexpr(t4), 7008 binop(Iop_Or32, 7009 getDSPControl(), 7010 mkU32(0x08000000)), 7011 binop(Iop_And32, 7012 getDSPControl(), 7013 mkU32(0xf7ffffff)))); 7014 break; 7015 } 7016 case 0x3: { /* PICK.QB */ 7017 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt); 7018 vassert(!mode64); 7019 t0 = newTemp(Ity_I32); 7020 t1 = newTemp(Ity_I8); 7021 t2 = newTemp(Ity_I8); 7022 t3 = newTemp(Ity_I8); 7023 t4 = newTemp(Ity_I8); 7024 7025 assign(t0, getDSPControl()); 7026 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32, 7027 binop(Iop_And32, 7028 mkexpr(t0), 7029 mkU32(0x01000000)), 7030 mkU32(0x0)), 7031 unop(Iop_16to8, 7032 unop(Iop_32to16, 7033 getIReg(rs))), 7034 unop(Iop_16to8, 7035 unop(Iop_32to16, 7036 getIReg(rt))))); 7037 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32, 7038 binop(Iop_And32, 7039 mkexpr(t0), 7040 mkU32(0x02000000)), 7041 mkU32(0x0)), 7042 unop(Iop_16HIto8, 7043 unop(Iop_32to16, getIReg(rs))), 7044 unop(Iop_16HIto8, 7045 unop(Iop_32to16, 7046 getIReg(rt))))); 7047 assign(t3, IRExpr_ITE(binop(Iop_CmpNE32, 7048 binop(Iop_And32, 7049 mkexpr(t0), 7050 mkU32(0x04000000)), 7051 mkU32(0x0)), 7052 unop(Iop_16to8, 7053 unop(Iop_32HIto16, 7054 getIReg(rs))), 7055 unop(Iop_16to8, 7056 unop(Iop_32HIto16, 7057 getIReg(rt))))); 7058 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 7059 binop(Iop_And32, 7060 mkexpr(t0), 7061 mkU32(0x08000000)), 7062 mkU32(0x0)), 7063 unop(Iop_16HIto8, 7064 unop(Iop_32HIto16, 7065 getIReg(rs))), 7066 unop(Iop_16HIto8, 7067 unop(Iop_32HIto16, 7068 getIReg(rt))))); 7069 putIReg(rd, 7070 binop(Iop_16HLto32, 7071 binop(Iop_8HLto16, mkexpr(t4), mkexpr(t3)), 7072 binop(Iop_8HLto16, mkexpr(t2), mkexpr(t1)))); 7073 break; 7074 } 7075 case 0x4: { /* CMPGU.EQ.QB */ 7076 DIP("cmpgu.eq.qb r%u, r%u, r%u", rd, rs, rt); 7077 vassert(!mode64); 7078 t1 = newTemp(Ity_I1); 7079 t2 = newTemp(Ity_I1); 7080 t3 = newTemp(Ity_I1); 7081 t4 = newTemp(Ity_I1); 7082 t5 = newTemp(Ity_I32); 7083 t6 = newTemp(Ity_I32); 7084 t7 = newTemp(Ity_I32); 7085 t8 = newTemp(Ity_I32); 7086 7087 assign(t1, binop(Iop_CmpEQ32, 7088 unop(Iop_8Uto32, 7089 unop(Iop_16to8, 7090 unop(Iop_32to16, getIReg(rs)))), 7091 unop(Iop_8Uto32, 7092 unop(Iop_16to8, 7093 unop(Iop_32to16, 7094 getIReg(rt)))))); 7095 assign(t5, IRExpr_ITE(mkexpr(t1), 7096 mkU32(0x00000001), mkU32(0))); 7097 7098 assign(t2, binop(Iop_CmpEQ32, 7099 unop(Iop_8Uto32, 7100 unop(Iop_16HIto8, 7101 unop(Iop_32to16, getIReg(rs)))), 7102 unop(Iop_8Uto32, 7103 unop(Iop_16HIto8, 7104 unop(Iop_32to16, 7105 getIReg(rt)))))); 7106 assign(t6, IRExpr_ITE(mkexpr(t2), 7107 mkU32(0x00000002), mkU32(0))); 7108 7109 assign(t3, binop(Iop_CmpEQ32, 7110 unop(Iop_8Uto32, 7111 unop(Iop_16to8, 7112 unop(Iop_32HIto16, 7113 getIReg(rs)))), 7114 unop(Iop_8Uto32, 7115 unop(Iop_16to8, 7116 unop(Iop_32HIto16, 7117 getIReg(rt)))))); 7118 assign(t7, IRExpr_ITE(mkexpr(t3), 7119 mkU32(0x00000004), mkU32(0))); 7120 7121 assign(t4, binop(Iop_CmpEQ32, 7122 unop(Iop_8Uto32, 7123 unop(Iop_16HIto8, 7124 unop(Iop_32HIto16, 7125 getIReg(rs)))), 7126 unop(Iop_8Uto32, 7127 unop(Iop_16HIto8, 7128 unop(Iop_32HIto16, 7129 getIReg(rt)))))); 7130 assign(t8, IRExpr_ITE(mkexpr(t4), 7131 mkU32(0x00000008), mkU32(0))); 7132 7133 putIReg(rd, binop(Iop_Or32, 7134 binop(Iop_Or32, 7135 binop(Iop_Or32, 7136 mkexpr(t5), mkexpr(t6)), 7137 mkexpr(t7)), 7138 mkexpr(t8))); 7139 break; 7140 } 7141 case 0x5: { /* CMPGU.LT.QB */ 7142 DIP("cmpgu.lt.qb r%u, r%u, r%u", rd, rs, rt); 7143 vassert(!mode64); 7144 t1 = newTemp(Ity_I1); 7145 t2 = newTemp(Ity_I1); 7146 t3 = newTemp(Ity_I1); 7147 t4 = newTemp(Ity_I1); 7148 t5 = newTemp(Ity_I32); 7149 t6 = newTemp(Ity_I32); 7150 t7 = newTemp(Ity_I32); 7151 t8 = newTemp(Ity_I32); 7152 7153 assign(t1, binop(Iop_CmpLT32U, 7154 unop(Iop_8Uto32, 7155 unop(Iop_16to8, 7156 unop(Iop_32to16, getIReg(rs)))), 7157 unop(Iop_8Uto32, 7158 unop(Iop_16to8, 7159 unop(Iop_32to16, 7160 getIReg(rt)))))); 7161 assign(t5, IRExpr_ITE(mkexpr(t1), 7162 mkU32(0x00000001), mkU32(0))); 7163 7164 assign(t2, binop(Iop_CmpLT32U, 7165 unop(Iop_8Uto32, 7166 unop(Iop_16HIto8, 7167 unop(Iop_32to16, getIReg(rs)))), 7168 unop(Iop_8Uto32, 7169 unop(Iop_16HIto8, 7170 unop(Iop_32to16, 7171 getIReg(rt)))))); 7172 assign(t6, IRExpr_ITE(mkexpr(t2), 7173 mkU32(0x00000002), mkU32(0))); 7174 7175 assign(t3, binop(Iop_CmpLT32U, 7176 unop(Iop_8Uto32, 7177 unop(Iop_16to8, 7178 unop(Iop_32HIto16, 7179 getIReg(rs)))), 7180 unop(Iop_8Uto32, 7181 unop(Iop_16to8, 7182 unop(Iop_32HIto16, 7183 getIReg(rt)))))); 7184 assign(t7, IRExpr_ITE(mkexpr(t3), 7185 mkU32(0x00000004), mkU32(0))); 7186 7187 assign(t4, binop(Iop_CmpLT32U, 7188 unop(Iop_8Uto32, 7189 unop(Iop_16HIto8, 7190 unop(Iop_32HIto16, 7191 getIReg(rs)))), 7192 unop(Iop_8Uto32, 7193 unop(Iop_16HIto8, 7194 unop(Iop_32HIto16, 7195 getIReg(rt)))))); 7196 assign(t8, IRExpr_ITE(mkexpr(t4), 7197 mkU32(0x00000008), mkU32(0))); 7198 putIReg(rd, binop(Iop_Or32, 7199 binop(Iop_Or32, 7200 binop(Iop_Or32, 7201 mkexpr(t5), mkexpr(t6)), 7202 mkexpr(t7)), 7203 mkexpr(t8))); 7204 break; 7205 } 7206 case 0x6: { /* CMPGU.LE.QB */ 7207 DIP("cmpgu.le.qb r%u, r%u, r%u", rd, rs, rt); 7208 vassert(!mode64); 7209 t1 = newTemp(Ity_I1); 7210 t2 = newTemp(Ity_I1); 7211 t3 = newTemp(Ity_I1); 7212 t4 = newTemp(Ity_I1); 7213 t5 = newTemp(Ity_I32); 7214 t6 = newTemp(Ity_I32); 7215 t7 = newTemp(Ity_I32); 7216 t8 = newTemp(Ity_I32); 7217 7218 assign(t1, binop(Iop_CmpLE32U, 7219 unop(Iop_8Uto32, 7220 unop(Iop_16to8, 7221 unop(Iop_32to16, getIReg(rs)))), 7222 unop(Iop_8Uto32, 7223 unop(Iop_16to8, 7224 unop(Iop_32to16, 7225 getIReg(rt)))))); 7226 assign(t5, IRExpr_ITE(mkexpr(t1), 7227 mkU32(0x00000001), mkU32(0))); 7228 7229 assign(t2, binop(Iop_CmpLE32U, 7230 unop(Iop_8Uto32, 7231 unop(Iop_16HIto8, 7232 unop(Iop_32to16, getIReg(rs)))), 7233 unop(Iop_8Uto32, 7234 unop(Iop_16HIto8, 7235 unop(Iop_32to16, 7236 getIReg(rt)))))); 7237 assign(t6, IRExpr_ITE(mkexpr(t2), 7238 mkU32(0x00000002), mkU32(0))); 7239 7240 assign(t3, binop(Iop_CmpLE32U, 7241 unop(Iop_8Uto32, 7242 unop(Iop_16to8, 7243 unop(Iop_32HIto16, 7244 getIReg(rs)))), 7245 unop(Iop_8Uto32, 7246 unop(Iop_16to8, 7247 unop(Iop_32HIto16, 7248 getIReg(rt)))))); 7249 assign(t7, IRExpr_ITE(mkexpr(t3), 7250 mkU32(0x00000004), mkU32(0))); 7251 7252 assign(t4, binop(Iop_CmpLE32U, 7253 unop(Iop_8Uto32, 7254 unop(Iop_16HIto8, 7255 unop(Iop_32HIto16, 7256 getIReg(rs)))), 7257 unop(Iop_8Uto32, 7258 unop(Iop_16HIto8, 7259 unop(Iop_32HIto16, 7260 getIReg(rt)))))); 7261 assign(t8, IRExpr_ITE(mkexpr(t4), 7262 mkU32(0x00000008), mkU32(0))); 7263 putIReg(rd, binop(Iop_Or32, 7264 binop(Iop_Or32, 7265 binop(Iop_Or32, 7266 mkexpr(t5), mkexpr(t6)), 7267 mkexpr(t7)), 7268 mkexpr(t8))); 7269 break; 7270 } 7271 case 0x8: { /* CMP.EQ.PH */ 7272 DIP("cmp.eq.ph r%u, r%u", rs, rt); 7273 vassert(!mode64); 7274 t1 = newTemp(Ity_I1); 7275 t2 = newTemp(Ity_I1); 7276 7277 assign(t1, binop(Iop_CmpEQ16, 7278 unop(Iop_32to16, getIReg(rs)), 7279 unop(Iop_32to16, getIReg(rt)))); 7280 putDSPControl(IRExpr_ITE(mkexpr(t1), 7281 binop(Iop_Or32, 7282 getDSPControl(), 7283 mkU32(0x01000000)), 7284 binop(Iop_And32, 7285 getDSPControl(), 7286 mkU32(0xfeffffff)))); 7287 assign(t2, binop(Iop_CmpEQ16, 7288 unop(Iop_32HIto16, getIReg(rs)), 7289 unop(Iop_32HIto16, getIReg(rt)))); 7290 putDSPControl(IRExpr_ITE(mkexpr(t2), 7291 binop(Iop_Or32, 7292 getDSPControl(), 7293 mkU32(0x02000000)), 7294 binop(Iop_And32, 7295 getDSPControl(), 7296 mkU32(0xfdffffff)))); 7297 break; 7298 } 7299 case 0x9: { /* CMP.LT.PH */ 7300 DIP("cmp.lt.ph r%u, r%u", rs, rt); 7301 vassert(!mode64); 7302 t1 = newTemp(Ity_I1); 7303 t2 = newTemp(Ity_I1); 7304 7305 assign(t1, binop(Iop_CmpLT32S, 7306 unop(Iop_16Sto32, 7307 unop(Iop_32to16, getIReg(rs))), 7308 unop(Iop_16Sto32, 7309 unop(Iop_32to16, getIReg(rt))))); 7310 putDSPControl(IRExpr_ITE(mkexpr(t1), 7311 binop(Iop_Or32, 7312 getDSPControl(), 7313 mkU32(0x01000000)), 7314 binop(Iop_And32, 7315 getDSPControl(), 7316 mkU32(0xfeffffff)))); 7317 7318 assign(t2, binop(Iop_CmpLT32S, 7319 unop(Iop_16Sto32, 7320 unop(Iop_32HIto16, getIReg(rs))), 7321 unop(Iop_16Sto32, 7322 unop(Iop_32HIto16, getIReg(rt))))); 7323 putDSPControl(IRExpr_ITE(mkexpr(t2), 7324 binop(Iop_Or32, 7325 getDSPControl(), 7326 mkU32(0x02000000)), 7327 binop(Iop_And32, 7328 getDSPControl(), 7329 mkU32(0xfdffffff)))); 7330 break; 7331 } 7332 case 0xA: { /* CMP.LE.PH */ 7333 DIP("cmp.le.ph r%u, r%u", rs, rt); 7334 vassert(!mode64); 7335 t1 = newTemp(Ity_I1); 7336 t2 = newTemp(Ity_I1); 7337 7338 assign(t1, binop(Iop_CmpLE32S, 7339 unop(Iop_16Sto32, 7340 unop(Iop_32to16, getIReg(rs))), 7341 unop(Iop_16Sto32, 7342 unop(Iop_32to16, getIReg(rt))))); 7343 putDSPControl(IRExpr_ITE(mkexpr(t1), 7344 binop(Iop_Or32, 7345 getDSPControl(), 7346 mkU32(0x01000000)), 7347 binop(Iop_And32, 7348 getDSPControl(), 7349 mkU32(0xfeffffff)))); 7350 7351 assign(t2, binop(Iop_CmpLE32S, 7352 unop(Iop_16Sto32, 7353 unop(Iop_32HIto16, getIReg(rs))), 7354 unop(Iop_16Sto32, 7355 unop(Iop_32HIto16, getIReg(rt))))); 7356 putDSPControl(IRExpr_ITE(mkexpr(t2), 7357 binop(Iop_Or32, 7358 getDSPControl(), 7359 mkU32(0x02000000)), 7360 binop(Iop_And32, 7361 getDSPControl(), 7362 mkU32(0xfdffffff)))); 7363 break; 7364 } 7365 case 0xB: { /* PICK.PH */ 7366 DIP("pick.qb r%u, r%u, r%u", rd, rs, rt); 7367 vassert(!mode64); 7368 t0 = newTemp(Ity_I32); 7369 t1 = newTemp(Ity_I16); 7370 t2 = newTemp(Ity_I16); 7371 7372 assign(t0, getDSPControl()); 7373 7374 assign(t1, IRExpr_ITE(binop(Iop_CmpNE32, 7375 binop(Iop_And32, 7376 mkexpr(t0), 7377 mkU32(0x01000000)), 7378 mkU32(0x0)), 7379 unop(Iop_32to16, getIReg(rs)), 7380 unop(Iop_32to16, getIReg(rt)))); 7381 7382 assign(t2, IRExpr_ITE(binop(Iop_CmpNE32, 7383 binop(Iop_And32, 7384 mkexpr(t0), 7385 mkU32(0x02000000)), 7386 mkU32(0x0)), 7387 unop(Iop_32HIto16, getIReg(rs)), 7388 unop(Iop_32HIto16, getIReg(rt)))); 7389 7390 putIReg(rd, binop(Iop_16HLto32, mkexpr(t2), mkexpr(t1))); 7391 break; 7392 } 7393 case 0xC: { /* PRECRQ.QB.PH */ 7394 DIP("precrq.qb.ph r%u, r%u, %u", rd, rs, rt); 7395 vassert(!mode64); 7396 putIReg(rd, 7397 binop(Iop_16HLto32, 7398 binop(Iop_8HLto16, 7399 unop(Iop_16HIto8, 7400 unop(Iop_32HIto16, getIReg(rs))), 7401 unop(Iop_16HIto8, 7402 unop(Iop_32to16, getIReg(rs)))), 7403 binop(Iop_8HLto16, 7404 unop(Iop_16HIto8, 7405 unop(Iop_32HIto16, getIReg(rt))), 7406 unop(Iop_16HIto8, 7407 unop(Iop_32to16, getIReg(rt)))))); 7408 break; 7409 } 7410 case 0xD: { /* PRECR.QB.PH */ 7411 DIP("precr.qb.ph r%u, r%u, r%u", rd, rs, rt); 7412 vassert(!mode64); 7413 7414 putIReg(rd, 7415 binop(Iop_16HLto32, 7416 binop(Iop_8HLto16, 7417 unop(Iop_16to8, 7418 unop(Iop_32HIto16, getIReg(rs))), 7419 unop(Iop_16to8, 7420 unop(Iop_32to16, getIReg(rs)))), 7421 binop(Iop_8HLto16, 7422 unop(Iop_16to8, 7423 unop(Iop_32HIto16, getIReg(rt))), 7424 unop(Iop_16to8, 7425 unop(Iop_32to16, getIReg(rt)))))); 7426 break; 7427 } 7428 case 0xF: { /* PRECRQU_S.QB.PH */ 7429 DIP("precrqu_s.qb.ph r%u, r%u, %u", rd, rs, rt); 7430 vassert(!mode64); 7431 t0 = newTemp(Ity_I8); 7432 t1 = newTemp(Ity_I8); 7433 t2 = newTemp(Ity_I8); 7434 t3 = newTemp(Ity_I8); 7435 t4 = newTemp(Ity_I8); 7436 t5 = newTemp(Ity_I32); 7437 t6 = newTemp(Ity_I1); 7438 t7 = newTemp(Ity_I8); 7439 t8 = newTemp(Ity_I1); 7440 t9 = newTemp(Ity_I32); 7441 t10 = newTemp(Ity_I8); 7442 t11 = newTemp(Ity_I1); 7443 t12 = newTemp(Ity_I32); 7444 t13 = newTemp(Ity_I8); 7445 t14 = newTemp(Ity_I1); 7446 t15 = newTemp(Ity_I32); 7447 7448 assign(t4, IRExpr_ITE(binop(Iop_CmpLT32U, 7449 mkU32(0x7f80), 7450 binop(Iop_And32, 7451 unop(Iop_16Uto32, 7452 unop(Iop_32to16, 7453 getIReg(rs))), 7454 mkU32(0x7fff))), 7455 mkU8(0xff), 7456 unop(Iop_16HIto8, 7457 unop(Iop_32to16, 7458 binop(Iop_Shl32, 7459 getIReg(rs), 7460 mkU8(1)))))); 7461 assign(t0, IRExpr_ITE(binop(Iop_CmpEQ32, 7462 binop(Iop_And32, 7463 unop(Iop_16Uto32, 7464 unop(Iop_32to16, 7465 getIReg(rs))), 7466 mkU32(0x00008000)), 7467 mkU32(0x0)), 7468 mkexpr(t4), 7469 mkU8(0x0))); 7470 assign(t5, binop(Iop_And32, 7471 unop(Iop_16Uto32, 7472 unop(Iop_32to16, 7473 getIReg(rs))), 7474 mkU32(0x00008000))); 7475 assign(t6, binop(Iop_CmpLT32U, 7476 mkU32(0x7f80), 7477 binop(Iop_And32, 7478 unop(Iop_16Uto32, 7479 unop(Iop_32to16, 7480 getIReg(rs))), 7481 mkU32(0x7fff)))); 7482 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 7483 mkexpr(t5), 7484 mkU32(0x0)), 7485 IRExpr_ITE(mkexpr(t6), 7486 binop(Iop_Or32, 7487 getDSPControl(), 7488 mkU32(0x00400000) 7489 ), 7490 getDSPControl()), 7491 binop(Iop_Or32, 7492 getDSPControl(), 7493 mkU32(0x00400000)))); 7494 7495 assign(t7, IRExpr_ITE(binop(Iop_CmpLT32U, 7496 mkU32(0x7f80), 7497 binop(Iop_And32, 7498 unop(Iop_16Uto32, 7499 unop(Iop_32HIto16, 7500 getIReg(rs))), 7501 mkU32(0x7fff))), 7502 mkU8(0xff), 7503 unop(Iop_16HIto8, 7504 unop(Iop_32HIto16, 7505 binop(Iop_Shl32, 7506 getIReg(rs), 7507 mkU8(1)))))); 7508 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32, 7509 binop(Iop_And32, 7510 unop(Iop_16Uto32, 7511 unop(Iop_32HIto16, 7512 getIReg(rs))), 7513 mkU32(0x00008000)), 7514 mkU32(0x0)), 7515 mkexpr(t7), 7516 mkU8(0x0))); 7517 assign(t8, binop(Iop_CmpEQ32, 7518 binop(Iop_And32, 7519 unop(Iop_16Uto32, 7520 unop(Iop_32HIto16, 7521 getIReg(rs))), 7522 mkU32(0x00008000)), 7523 mkU32(0x0))); 7524 assign(t9, IRExpr_ITE(binop(Iop_CmpLT32U, 7525 mkU32(0x7f80), 7526 binop(Iop_And32, 7527 unop(Iop_16Uto32, 7528 unop(Iop_32HIto16, 7529 getIReg(rs))), 7530 mkU32(0x7fff))), 7531 binop(Iop_Or32, 7532 getDSPControl(), 7533 mkU32(0x00400000)), 7534 getDSPControl())); 7535 putDSPControl(IRExpr_ITE(mkexpr(t8), 7536 mkexpr(t9), 7537 binop(Iop_Or32, 7538 getDSPControl(), 7539 mkU32(0x00400000)))); 7540 7541 assign(t10, IRExpr_ITE(binop(Iop_CmpLT32U, 7542 mkU32(0x7f80), 7543 binop(Iop_And32, 7544 unop(Iop_16Uto32, 7545 unop(Iop_32to16, 7546 getIReg(rt))), 7547 mkU32(0x7fff))), 7548 mkU8(0xff), 7549 unop(Iop_16HIto8, 7550 unop(Iop_32to16, 7551 binop(Iop_Shl32, 7552 getIReg(rt), 7553 mkU8(1)))))); 7554 assign(t2, IRExpr_ITE(binop(Iop_CmpEQ32, 7555 binop(Iop_And32, 7556 unop(Iop_16Uto32, 7557 unop(Iop_32to16, 7558 getIReg(rt))), 7559 mkU32(0x00008000)), 7560 mkU32(0x0)), 7561 mkexpr(t10), 7562 mkU8(0x0))); 7563 assign(t11, binop(Iop_CmpEQ32, 7564 binop(Iop_And32, 7565 unop(Iop_16Uto32, 7566 unop(Iop_32to16, 7567 getIReg(rt))), 7568 mkU32(0x00008000)), 7569 mkU32(0x0))); 7570 assign(t12, IRExpr_ITE(binop(Iop_CmpLT32U, 7571 mkU32(0x7f80), 7572 binop(Iop_And32, 7573 unop(Iop_16Uto32, 7574 unop(Iop_32to16, 7575 getIReg(rt))), 7576 mkU32(0x7fff))), 7577 binop(Iop_Or32, 7578 getDSPControl(), 7579 mkU32(0x00400000)), 7580 getDSPControl())); 7581 putDSPControl(IRExpr_ITE(mkexpr(t11), 7582 mkexpr(t12), 7583 binop(Iop_Or32, 7584 getDSPControl(), 7585 mkU32(0x00400000)))); 7586 7587 assign(t13, IRExpr_ITE(binop(Iop_CmpLT32U, 7588 mkU32(0x7f80), 7589 binop(Iop_And32, 7590 unop(Iop_16Uto32, 7591 unop(Iop_32HIto16, 7592 getIReg(rt))), 7593 mkU32(0x7fff))), 7594 mkU8(0xff), 7595 unop(Iop_16HIto8, 7596 unop(Iop_32HIto16, 7597 binop(Iop_Shl32, 7598 getIReg(rt), 7599 mkU8(1)))))); 7600 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32, 7601 binop(Iop_And32, 7602 unop(Iop_16Uto32, 7603 unop(Iop_32HIto16, 7604 getIReg(rt))), 7605 mkU32(0x00008000)), 7606 mkU32(0x0)), 7607 mkexpr(t13), 7608 mkU8(0x0))); 7609 assign(t14, binop(Iop_CmpEQ32, 7610 binop(Iop_And32, 7611 unop(Iop_16Uto32, 7612 unop(Iop_32HIto16, 7613 getIReg(rt))), 7614 mkU32(0x00008000)), 7615 mkU32(0x0))); 7616 assign(t15, IRExpr_ITE(binop(Iop_CmpLT32U, 7617 mkU32(0x7f80), 7618 binop(Iop_And32, 7619 unop(Iop_16Uto32, 7620 unop(Iop_32HIto16, 7621 getIReg(rt))), 7622 mkU32(0x7fff))), 7623 binop(Iop_Or32, 7624 getDSPControl(), 7625 mkU32(0x00400000)), 7626 getDSPControl())); 7627 putDSPControl(IRExpr_ITE(mkexpr(t14), 7628 mkexpr(t15), 7629 binop(Iop_Or32, 7630 getDSPControl(), 7631 mkU32(0x00400000)))); 7632 7633 putIReg(rd, binop(Iop_16HLto32, 7634 binop(Iop_8HLto16, 7635 mkexpr(t1), mkexpr(t0)), 7636 binop(Iop_8HLto16, 7637 mkexpr(t3), mkexpr(t2)))); 7638 break; 7639 } 7640 case 0x14: { /* PRECRQ.PH.W */ 7641 DIP("precrq.ph.w r%u, r%u, %u", rd, rs, rt); 7642 vassert(!mode64); 7643 putIReg(rd, binop(Iop_16HLto32, 7644 unop(Iop_32HIto16, getIReg(rs)), 7645 unop(Iop_32HIto16, getIReg(rt)))); 7646 break; 7647 } 7648 case 0x15: { /* PRECRQ_RS.PH.W */ 7649 DIP("precrq_rs.ph.w r%u, r%u, %u", rd, rs, rt); 7650 vassert(!mode64); 7651 t0 = newTemp(Ity_I64); 7652 t1 = newTemp(Ity_I1); 7653 t2 = newTemp(Ity_I32); 7654 t3 = newTemp(Ity_I64); 7655 t4 = newTemp(Ity_I1); 7656 t5 = newTemp(Ity_I32); 7657 7658 assign(t0, binop(Iop_Add64, 7659 binop(Iop_32HLto64, 7660 binop(Iop_Shr32, 7661 binop(Iop_And32, 7662 getIReg(rs), 7663 mkU32(0x80000000)), 7664 mkU8(31)), 7665 getIReg(rs)), 7666 mkU64(0x0000000000008000ULL))); 7667 assign(t1, binop(Iop_CmpNE32, 7668 binop(Iop_And32, 7669 unop(Iop_64HIto32, mkexpr(t0)), 7670 mkU32(0x1)), 7671 binop(Iop_And32, 7672 binop(Iop_Shr32, 7673 unop(Iop_64to32, mkexpr(t0)), 7674 mkU8(31)), 7675 mkU32(0x1)))); 7676 assign(t2, IRExpr_ITE(mkexpr(t1), 7677 mkU32(0x7fffffff), 7678 unop(Iop_64to32, mkexpr(t0)))); 7679 putDSPControl(IRExpr_ITE(mkexpr(t1), 7680 binop(Iop_Or32, 7681 getDSPControl(), 7682 mkU32(0x400000)), 7683 getDSPControl())); 7684 assign(t3, binop(Iop_Add64, 7685 binop(Iop_32HLto64, 7686 binop(Iop_Shr32, 7687 binop(Iop_And32, 7688 getIReg(rt), 7689 mkU32(0x80000000)), 7690 mkU8(31)), 7691 getIReg(rt)), 7692 mkU64(0x0000000000008000ULL))); 7693 assign(t4, binop(Iop_CmpNE32, 7694 binop(Iop_And32, 7695 unop(Iop_64HIto32, mkexpr(t3)), 7696 mkU32(0x1)), 7697 binop(Iop_And32, 7698 binop(Iop_Shr32, 7699 unop(Iop_64to32, mkexpr(t3)), 7700 mkU8(31)), 7701 mkU32(0x1)))); 7702 assign(t5, IRExpr_ITE(mkexpr(t4), 7703 mkU32(0x7fffffff), 7704 unop(Iop_64to32, mkexpr(t3)))); 7705 putDSPControl(IRExpr_ITE(mkexpr(t4), 7706 binop(Iop_Or32, 7707 getDSPControl(), 7708 mkU32(0x400000)), 7709 getDSPControl())); 7710 putIReg(rd, binop(Iop_16HLto32, 7711 unop(Iop_32HIto16, mkexpr(t2)), 7712 unop(Iop_32HIto16, mkexpr(t5)))); 7713 break; 7714 } 7715 case 0x1E: { /* PRECR_SRA.PH.W */ 7716 DIP("precr_sra.ph.w r%u, r%u, %u", rt, rs, rd); 7717 vassert(!mode64); 7718 7719 if (0 == rd) { 7720 putIReg(rt, binop(Iop_16HLto32, 7721 unop(Iop_32to16, getIReg(rt)), 7722 unop(Iop_32to16, getIReg(rs)))); 7723 } else { 7724 putIReg(rt, binop(Iop_16HLto32, 7725 unop(Iop_32to16, binop(Iop_Sar32, 7726 getIReg(rt), 7727 mkU8(rd))), 7728 unop(Iop_32to16, binop(Iop_Sar32, 7729 getIReg(rs), 7730 mkU8(rd))))); 7731 } 7732 break; 7733 } 7734 case 0x1F: { /* PRECR_SRA_R.PH.W */ 7735 DIP("precr_sra_r.ph.w r%u, r%u, %u", rt, rs, rd); 7736 vassert(!mode64); 7737 7738 t0 = newTemp(Ity_I32); 7739 t1 = newTemp(Ity_I32); 7740 7741 if (0 == rd) { 7742 putIReg(rt, binop(Iop_16HLto32, 7743 unop(Iop_32to16, getIReg(rt)), 7744 unop(Iop_32to16, getIReg(rs)))); 7745 } else { 7746 assign(t0, binop(Iop_Shr32, 7747 binop(Iop_Add32, 7748 binop(Iop_Sar32, 7749 getIReg(rt), 7750 mkU8(rd-1)), 7751 mkU32(0x1)), 7752 mkU8(0x1))); 7753 assign(t1, binop(Iop_Shr32, 7754 binop(Iop_Add32, 7755 binop(Iop_Sar32, 7756 getIReg(rs), 7757 mkU8(rd-1)), 7758 mkU32(0x1)), 7759 mkU8(0x1))); 7760 putIReg(rt, binop(Iop_16HLto32, 7761 unop(Iop_32to16, mkexpr(t0)), 7762 unop(Iop_32to16, mkexpr(t1)))); 7763 }; 7764 break; 7765 } 7766 case 0xE: { /* PACKRL.PH */ 7767 DIP("packrl.ph r%u, r%u, r%u", rd, rs, rt); 7768 vassert(!mode64); 7769 7770 putIReg(rd, binop(Iop_16HLto32, 7771 unop(Iop_32to16, getIReg(rs)), 7772 unop(Iop_32HIto16, getIReg(rt)))); 7773 break; 7774 } 7775 case 0x18: { /* CMPGDU.EQ.QB */ 7776 DIP("cmpgdu.eq.qb r%u, r%u, r%u", rd, rs, rt); 7777 vassert(!mode64); 7778 t1 = newTemp(Ity_I1); 7779 t2 = newTemp(Ity_I1); 7780 t3 = newTemp(Ity_I1); 7781 t4 = newTemp(Ity_I1); 7782 t5 = newTemp(Ity_I32); 7783 t6 = newTemp(Ity_I32); 7784 t7 = newTemp(Ity_I32); 7785 t8 = newTemp(Ity_I32); 7786 7787 assign(t1, 7788 binop(Iop_CmpEQ32, 7789 unop(Iop_8Uto32, 7790 unop(Iop_16to8, 7791 unop(Iop_32to16, getIReg(rs)))), 7792 unop(Iop_8Uto32, 7793 unop(Iop_16to8, 7794 unop(Iop_32to16, getIReg(rt)))))); 7795 assign(t5, IRExpr_ITE(mkexpr(t1), 7796 mkU32(0x00000001), mkU32(0))); 7797 putDSPControl(IRExpr_ITE(mkexpr(t1), 7798 binop(Iop_Or32, 7799 getDSPControl(), 7800 mkU32(0x01000000)), 7801 binop(Iop_And32, 7802 getDSPControl(), 7803 mkU32(0xfeffffff)))); 7804 7805 assign(t2, binop(Iop_CmpEQ32, 7806 unop(Iop_8Uto32, 7807 unop(Iop_16HIto8, 7808 unop(Iop_32to16, getIReg(rs)))), 7809 unop(Iop_8Uto32, 7810 unop(Iop_16HIto8, 7811 unop(Iop_32to16, 7812 getIReg(rt)))))); 7813 assign(t6, IRExpr_ITE(mkexpr(t2), 7814 mkU32(0x00000002), mkU32(0))); 7815 putDSPControl(IRExpr_ITE(mkexpr(t2), 7816 binop(Iop_Or32, 7817 getDSPControl(), 7818 mkU32(0x02000000)), 7819 binop(Iop_And32, 7820 getDSPControl(), 7821 mkU32(0xfdffffff)))); 7822 7823 assign(t3, binop(Iop_CmpEQ32, 7824 unop(Iop_8Uto32, 7825 unop(Iop_16to8, 7826 unop(Iop_32HIto16, 7827 getIReg(rs)))), 7828 unop(Iop_8Uto32, 7829 unop(Iop_16to8, 7830 unop(Iop_32HIto16, 7831 getIReg(rt)))))); 7832 assign(t7, IRExpr_ITE(mkexpr(t3), 7833 mkU32(0x00000004), mkU32(0))); 7834 putDSPControl(IRExpr_ITE(mkexpr(t3), 7835 binop(Iop_Or32, 7836 getDSPControl(), 7837 mkU32(0x04000000)), 7838 binop(Iop_And32, 7839 getDSPControl(), 7840 mkU32(0xfbffffff)))); 7841 7842 assign(t4, binop(Iop_CmpEQ32, 7843 unop(Iop_8Uto32, 7844 unop(Iop_16HIto8, 7845 unop(Iop_32HIto16, 7846 getIReg(rs)))), 7847 unop(Iop_8Uto32, 7848 unop(Iop_16HIto8, 7849 unop(Iop_32HIto16, 7850 getIReg(rt)))))); 7851 assign(t8, IRExpr_ITE(mkexpr(t4), 7852 mkU32(0x00000008), mkU32(0))); 7853 putDSPControl(IRExpr_ITE(mkexpr(t4), 7854 binop(Iop_Or32, 7855 getDSPControl(), 7856 mkU32(0x08000000)), 7857 binop(Iop_And32, 7858 getDSPControl(), 7859 mkU32(0xf7ffffff)))); 7860 7861 putIReg(rd, binop(Iop_Or32, 7862 binop(Iop_Or32, 7863 binop(Iop_Or32, 7864 mkexpr(t5), mkexpr(t6)), 7865 mkexpr(t7)), 7866 mkexpr(t8))); 7867 break; 7868 } 7869 case 0x19: { /* CMPGDU.LT.QB */ 7870 DIP("cmpgdu.lt.qb r%u, r%u, r%u", rd, rs, rt); 7871 vassert(!mode64); 7872 t1 = newTemp(Ity_I1); 7873 t2 = newTemp(Ity_I1); 7874 t3 = newTemp(Ity_I1); 7875 t4 = newTemp(Ity_I1); 7876 t5 = newTemp(Ity_I32); 7877 t6 = newTemp(Ity_I32); 7878 t7 = newTemp(Ity_I32); 7879 t8 = newTemp(Ity_I32); 7880 7881 assign(t1, binop(Iop_CmpLT32U, 7882 unop(Iop_8Uto32, 7883 unop(Iop_16to8, 7884 unop(Iop_32to16, getIReg(rs)))), 7885 unop(Iop_8Uto32, 7886 unop(Iop_16to8, 7887 unop(Iop_32to16, 7888 getIReg(rt)))))); 7889 assign(t5, IRExpr_ITE(mkexpr(t1), 7890 mkU32(0x00000001), mkU32(0))); 7891 putDSPControl(IRExpr_ITE(mkexpr(t1), 7892 binop(Iop_Or32, 7893 getDSPControl(), 7894 mkU32(0x01000000)), 7895 binop(Iop_And32, 7896 getDSPControl(), 7897 mkU32(0xfeffffff)))); 7898 7899 assign(t2, binop(Iop_CmpLT32U, 7900 unop(Iop_8Uto32, 7901 unop(Iop_16HIto8, 7902 unop(Iop_32to16, getIReg(rs)))), 7903 unop(Iop_8Uto32, 7904 unop(Iop_16HIto8, 7905 unop(Iop_32to16, 7906 getIReg(rt)))))); 7907 assign(t6, IRExpr_ITE(mkexpr(t2), 7908 mkU32(0x00000002), mkU32(0))); 7909 putDSPControl(IRExpr_ITE(mkexpr(t2), 7910 binop(Iop_Or32, 7911 getDSPControl(), 7912 mkU32(0x02000000)), 7913 binop(Iop_And32, 7914 getDSPControl(), 7915 mkU32(0xfdffffff)))); 7916 7917 assign(t3, binop(Iop_CmpLT32U, 7918 unop(Iop_8Uto32, 7919 unop(Iop_16to8, 7920 unop(Iop_32HIto16, 7921 getIReg(rs)))), 7922 unop(Iop_8Uto32, 7923 unop(Iop_16to8, 7924 unop(Iop_32HIto16, 7925 getIReg(rt)))))); 7926 assign(t7, IRExpr_ITE(mkexpr(t3), 7927 mkU32(0x00000004), mkU32(0))); 7928 putDSPControl(IRExpr_ITE(mkexpr(t3), 7929 binop(Iop_Or32, 7930 getDSPControl(), 7931 mkU32(0x04000000)), 7932 binop(Iop_And32, 7933 getDSPControl(), 7934 mkU32(0xfbffffff)))); 7935 7936 assign(t4, binop(Iop_CmpLT32U, 7937 unop(Iop_8Uto32, 7938 unop(Iop_16HIto8, 7939 unop(Iop_32HIto16, 7940 getIReg(rs)))), 7941 unop(Iop_8Uto32, 7942 unop(Iop_16HIto8, 7943 unop(Iop_32HIto16, 7944 getIReg(rt)))))); 7945 assign(t8, IRExpr_ITE(mkexpr(t4), 7946 mkU32(0x00000008), mkU32(0))); 7947 putDSPControl(IRExpr_ITE(mkexpr(t4), 7948 binop(Iop_Or32, 7949 getDSPControl(), 7950 mkU32(0x08000000)), 7951 binop(Iop_And32, 7952 getDSPControl(), 7953 mkU32(0xf7ffffff)))); 7954 7955 putIReg(rd, binop(Iop_Or32, 7956 binop(Iop_Or32, 7957 binop(Iop_Or32, 7958 mkexpr(t5), mkexpr(t6)), 7959 mkexpr(t7)), 7960 mkexpr(t8))); 7961 break; 7962 } 7963 case 0x1A: { /* CMPGDU.LE.QB */ 7964 DIP("cmpgdu.le.qb r%u, r%u, r%u", rd, rs, rt); 7965 vassert(!mode64); 7966 t1 = newTemp(Ity_I1); 7967 t2 = newTemp(Ity_I1); 7968 t3 = newTemp(Ity_I1); 7969 t4 = newTemp(Ity_I1); 7970 t5 = newTemp(Ity_I32); 7971 t6 = newTemp(Ity_I32); 7972 t7 = newTemp(Ity_I32); 7973 t8 = newTemp(Ity_I32); 7974 7975 assign(t1, binop(Iop_CmpLE32U, 7976 unop(Iop_8Uto32, 7977 unop(Iop_16to8, 7978 unop(Iop_32to16, getIReg(rs)))), 7979 unop(Iop_8Uto32, 7980 unop(Iop_16to8, 7981 unop(Iop_32to16, 7982 getIReg(rt)))))); 7983 assign(t5, IRExpr_ITE(mkexpr(t1), 7984 mkU32(0x00000001), 7985 mkU32(0))); 7986 putDSPControl(IRExpr_ITE(mkexpr(t1), 7987 binop(Iop_Or32, 7988 getDSPControl(), 7989 mkU32(0x01000000)), 7990 binop(Iop_And32, 7991 getDSPControl(), 7992 mkU32(0xfeffffff)))); 7993 7994 assign(t2, binop(Iop_CmpLE32U, 7995 unop(Iop_8Uto32, 7996 unop(Iop_16HIto8, 7997 unop(Iop_32to16, getIReg(rs)))), 7998 unop(Iop_8Uto32, 7999 unop(Iop_16HIto8, 8000 unop(Iop_32to16, 8001 getIReg(rt)))))); 8002 assign(t6, IRExpr_ITE(mkexpr(t2), 8003 mkU32(0x00000002), mkU32(0))); 8004 putDSPControl(IRExpr_ITE(mkexpr(t2), 8005 binop(Iop_Or32, 8006 getDSPControl(), 8007 mkU32(0x02000000)), 8008 binop(Iop_And32, 8009 getDSPControl(), 8010 mkU32(0xfdffffff)))); 8011 8012 assign(t3, binop(Iop_CmpLE32U, 8013 unop(Iop_8Uto32, 8014 unop(Iop_16to8, 8015 unop(Iop_32HIto16, 8016 getIReg(rs)))), 8017 unop(Iop_8Uto32, 8018 unop(Iop_16to8, 8019 unop(Iop_32HIto16, 8020 getIReg(rt)))))); 8021 assign(t7, IRExpr_ITE(mkexpr(t3), 8022 mkU32(0x00000004), mkU32(0))); 8023 putDSPControl(IRExpr_ITE(mkexpr(t3), 8024 binop(Iop_Or32, 8025 getDSPControl(), 8026 mkU32(0x04000000)), 8027 binop(Iop_And32, 8028 getDSPControl(), 8029 mkU32(0xfbffffff)))); 8030 8031 assign(t4, binop(Iop_CmpLE32U, 8032 unop(Iop_8Uto32, 8033 unop(Iop_16HIto8, 8034 unop(Iop_32HIto16, 8035 getIReg(rs)))), 8036 unop(Iop_8Uto32, 8037 unop(Iop_16HIto8, 8038 unop(Iop_32HIto16, 8039 getIReg(rt)))))); 8040 assign(t8, IRExpr_ITE(mkexpr(t4), 8041 mkU32(0x00000008), mkU32(0))); 8042 putDSPControl(IRExpr_ITE(mkexpr(t4), 8043 binop(Iop_Or32, 8044 getDSPControl(), 8045 mkU32(0x08000000)), 8046 binop(Iop_And32, 8047 getDSPControl(), 8048 mkU32(0xf7ffffff)))); 8049 8050 putIReg(rd, binop(Iop_Or32, 8051 binop(Iop_Or32, 8052 binop(Iop_Or32, 8053 mkexpr(t5), mkexpr(t6)), 8054 mkexpr(t7)), 8055 mkexpr(t8))); 8056 break; 8057 } 8058 default: 8059 return -1; 8060 } 8061 break; /* end of CMPU.EQ.QB */ 8062 } 8063 case 0x13: { /* SHLL.QB */ 8064 switch(sa) { 8065 case 0x0: { /* SHLL.QB */ 8066 DIP("shll.qb r%u, r%u, %u", rd, rt, rs); 8067 vassert(!mode64); 8068 t0 = newTemp(Ity_I32); 8069 t1 = newTemp(Ity_I1); 8070 t2 = newTemp(Ity_I1); 8071 t3 = newTemp(Ity_I32); 8072 t4 = newTemp(Ity_I1); 8073 t5 = newTemp(Ity_I1); 8074 t6 = newTemp(Ity_I32); 8075 t7 = newTemp(Ity_I1); 8076 t8 = newTemp(Ity_I1); 8077 t9 = newTemp(Ity_I1); 8078 t10 = newTemp(Ity_I1); 8079 8080 if (0 == rs) { 8081 putIReg(rd, getIReg(rt)); 8082 } else { 8083 /* Shift bits 7..0 and 23..16. */ 8084 assign(t0, binop(Iop_Shl32, 8085 binop(Iop_And32, 8086 getIReg(rt), 8087 mkU32(0x00ff00ff)), 8088 mkU8(rs))); 8089 assign(t1, binop(Iop_CmpNE32, 8090 binop(Iop_And32, 8091 mkexpr(t0), 8092 mkU32(0xff000000)), 8093 mkU32(0x00000000))); 8094 assign(t2, binop(Iop_CmpNE32, 8095 binop(Iop_And32, 8096 mkexpr(t0), 8097 mkU32(0xff000000)), 8098 mkU32(0xff000000))); 8099 assign(t7, binop(Iop_CmpNE32, 8100 binop(Iop_And32, 8101 mkexpr(t0), 8102 mkU32(0x0000ff00)), 8103 mkU32(0x00000000))); 8104 assign(t8, binop(Iop_CmpNE32, 8105 binop(Iop_And32, 8106 mkexpr(t0), 8107 mkU32(0x0000ff00)), 8108 mkU32(0x000ff00))); 8109 /* Shift bits 15..8 and 31..24. */ 8110 assign(t3, binop(Iop_Shl32, 8111 binop(Iop_Shr32, 8112 binop(Iop_And32, 8113 getIReg(rt), 8114 mkU32(0xff00ff00)), 8115 mkU8(8)), 8116 mkU8(rs))); 8117 assign(t4, binop(Iop_CmpNE32, 8118 binop(Iop_And32, 8119 mkexpr(t3), 8120 mkU32(0xff000000)), 8121 mkU32(0x00000000))); 8122 assign(t5, binop(Iop_CmpNE32, 8123 binop(Iop_And32, 8124 mkexpr(t3), 8125 mkU32(0xff000000)), 8126 mkU32(0xff000000))); 8127 assign(t9, binop(Iop_CmpNE32, 8128 binop(Iop_And32, 8129 mkexpr(t3), 8130 mkU32(0x0000ff00)), 8131 mkU32(0x00000000))); 8132 assign(t10, binop(Iop_CmpNE32, 8133 binop(Iop_And32, 8134 mkexpr(t3), 8135 mkU32(0x0000ff00)), 8136 mkU32(0x0000ff00))); 8137 8138 assign(t6, binop(Iop_Or32, 8139 binop(Iop_Or32, 8140 binop(Iop_And32, 8141 unop(Iop_1Uto32, 8142 mkexpr(t1)), 8143 unop(Iop_1Uto32, 8144 mkexpr(t2))), 8145 binop(Iop_And32, 8146 unop(Iop_1Uto32, 8147 mkexpr(t7)), 8148 unop(Iop_1Uto32, 8149 mkexpr(t8)))), 8150 binop(Iop_Or32, 8151 binop(Iop_And32, 8152 unop(Iop_1Uto32, 8153 mkexpr(t4)), 8154 unop(Iop_1Uto32, 8155 mkexpr(t5))), 8156 binop(Iop_And32, 8157 unop(Iop_1Uto32, 8158 mkexpr(t9)), 8159 unop(Iop_1Uto32, 8160 mkexpr(t10)))))); 8161 8162 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8163 mkexpr(t6), 8164 mkU32(0x0)), 8165 binop(Iop_Or32, 8166 getDSPControl(), 8167 mkU32(0x400000)), 8168 getDSPControl())); 8169 putIReg(rd, binop(Iop_Or32, 8170 binop(Iop_Shl32, 8171 binop(Iop_And32, 8172 mkexpr(t3), 8173 mkU32(0x00ff00ff)), 8174 mkU8(8)), 8175 binop(Iop_And32, 8176 mkexpr(t0), 8177 mkU32(0x00ff00ff)))); 8178 } 8179 break; 8180 } 8181 case 0x3: { /* SHRL.QB */ 8182 DIP("shrl.qb r%u, r%u, %u", rd, rt, rs); 8183 vassert(!mode64); 8184 t0 = newTemp(Ity_I32); 8185 t1 = newTemp(Ity_I8); 8186 t2 = newTemp(Ity_I32); 8187 t3 = newTemp(Ity_I8); 8188 t4 = newTemp(Ity_I32); 8189 t5 = newTemp(Ity_I8); 8190 t6 = newTemp(Ity_I32); 8191 t7 = newTemp(Ity_I8); 8192 t9 = newTemp(Ity_I32); 8193 8194 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7))); 8195 assign(t0, unop(Iop_8Uto32, 8196 unop(Iop_16to8, 8197 unop(Iop_32to16, getIReg(rt))))); 8198 assign(t1, unop(Iop_32to8, 8199 binop(Iop_Shr32, 8200 mkexpr(t0), 8201 unop(Iop_32to8, mkexpr(t9))))); 8202 8203 assign(t2, unop(Iop_8Uto32, 8204 unop(Iop_16HIto8, 8205 unop(Iop_32to16, getIReg(rt))))); 8206 assign(t3, unop(Iop_32to8, 8207 binop(Iop_Shr32, 8208 mkexpr(t2), 8209 unop(Iop_32to8, mkexpr(t9))))); 8210 8211 assign(t4, unop(Iop_8Uto32, 8212 unop(Iop_16to8, 8213 unop(Iop_32HIto16, getIReg(rt))))); 8214 assign(t5, unop(Iop_32to8, 8215 binop(Iop_Shr32, 8216 mkexpr(t4), 8217 unop(Iop_32to8, mkexpr(t9))))); 8218 8219 assign(t6, unop(Iop_8Uto32, 8220 unop(Iop_16HIto8, 8221 unop(Iop_32HIto16, getIReg(rt))))); 8222 assign(t7, unop(Iop_32to8, 8223 binop(Iop_Shr32, 8224 mkexpr(t6), 8225 unop(Iop_32to8, mkexpr(t9))))); 8226 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8227 mkexpr(t9), 8228 mkU32(0x0)), 8229 getIReg(rt), 8230 binop(Iop_16HLto32, 8231 binop(Iop_8HLto16, 8232 mkexpr(t7), 8233 mkexpr(t5)), 8234 binop(Iop_8HLto16, 8235 mkexpr(t3), 8236 mkexpr(t1))))); 8237 break; 8238 } 8239 case 0x2: { /* SHLLV.QB */ 8240 DIP("shllv.qb r%u, r%u, r%u", rd, rt, rs); 8241 vassert(!mode64); 8242 t0 = newTemp(Ity_I32); 8243 t1 = newTemp(Ity_I1); 8244 t2 = newTemp(Ity_I1); 8245 t3 = newTemp(Ity_I32); 8246 t4 = newTemp(Ity_I1); 8247 t5 = newTemp(Ity_I1); 8248 t6 = newTemp(Ity_I32); 8249 t7 = newTemp(Ity_I1); 8250 t8 = newTemp(Ity_I1); 8251 t9 = newTemp(Ity_I1); 8252 t10 = newTemp(Ity_I1); 8253 t11 = newTemp(Ity_I8); 8254 8255 assign(t11, unop(Iop_32to8, 8256 binop(Iop_And32, 8257 getIReg(rs), 8258 mkU32(0x7)))); 8259 /* Shift bits 7..0 and 23..16. */ 8260 assign(t0, binop(Iop_Shl32, 8261 binop(Iop_And32, 8262 getIReg(rt), 8263 mkU32(0x00ff00ff)), 8264 mkexpr(t11))); 8265 assign(t1, binop(Iop_CmpNE32, 8266 binop(Iop_And32, 8267 mkexpr(t0), 8268 mkU32(0xff000000)), 8269 mkU32(0x00000000))); 8270 assign(t2, binop(Iop_CmpNE32, 8271 binop(Iop_And32, 8272 mkexpr(t0), 8273 mkU32(0xff000000)), 8274 mkU32(0xff000000))); 8275 assign(t7, binop(Iop_CmpNE32, 8276 binop(Iop_And32, 8277 mkexpr(t0), 8278 mkU32(0x0000ff00)), 8279 mkU32(0x00000000))); 8280 assign(t8, binop(Iop_CmpNE32, 8281 binop(Iop_And32, 8282 mkexpr(t0), 8283 mkU32(0x0000ff00)), 8284 mkU32(0x000ff00))); 8285 /* Shift bits 15..8 and 31..24. */ 8286 assign(t3, binop(Iop_Shl32, 8287 binop(Iop_Shr32, 8288 binop(Iop_And32, 8289 getIReg(rt), 8290 mkU32(0xff00ff00)), 8291 mkU8(8)), 8292 mkexpr(t11))); 8293 assign(t4, binop(Iop_CmpNE32, 8294 binop(Iop_And32, 8295 mkexpr(t3), 8296 mkU32(0xff000000)), 8297 mkU32(0x00000000))); 8298 assign(t5, binop(Iop_CmpNE32, 8299 binop(Iop_And32, 8300 mkexpr(t3), 8301 mkU32(0xff000000)), 8302 mkU32(0xff000000))); 8303 assign(t9, binop(Iop_CmpNE32, 8304 binop(Iop_And32, 8305 mkexpr(t3), 8306 mkU32(0x0000ff00)), 8307 mkU32(0x00000000))); 8308 assign(t10, binop(Iop_CmpNE32, 8309 binop(Iop_And32, 8310 mkexpr(t3), 8311 mkU32(0x0000ff00)), 8312 mkU32(0x0000ff00))); 8313 8314 assign(t6, binop(Iop_Or32, 8315 binop(Iop_Or32, 8316 binop(Iop_And32, 8317 unop(Iop_1Uto32, 8318 mkexpr(t1)), 8319 unop(Iop_1Uto32, 8320 mkexpr(t2))), 8321 binop(Iop_And32, 8322 unop(Iop_1Uto32, 8323 mkexpr(t7)), 8324 unop(Iop_1Uto32, 8325 mkexpr(t8)))), 8326 binop(Iop_Or32, 8327 binop(Iop_And32, 8328 unop(Iop_1Uto32, 8329 mkexpr(t4)), 8330 unop(Iop_1Uto32, 8331 mkexpr(t5))), 8332 binop(Iop_And32, 8333 unop(Iop_1Uto32, 8334 mkexpr(t9)), 8335 unop(Iop_1Uto32, 8336 mkexpr(t10)))))); 8337 8338 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 8339 mkexpr(t6), 8340 mkU32(0x0)), 8341 binop(Iop_Or32, 8342 getDSPControl(), 8343 mkU32(0x400000)), 8344 getDSPControl())); 8345 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8346 unop(Iop_8Uto32, mkexpr(t11)), 8347 mkU32(0)), 8348 getIReg(rt), 8349 binop(Iop_Or32, 8350 binop(Iop_Shl32, 8351 binop(Iop_And32, 8352 mkexpr(t3), 8353 mkU32(0xff00ff)), 8354 mkU8(8)), 8355 binop(Iop_And32, 8356 mkexpr(t0), 8357 mkU32(0x00ff00ff))))); 8358 break; 8359 } 8360 case 0x1: { /* SHRLV.QB */ 8361 DIP("shrlv.qb r%u, r%u, r%u", rd, rt, rs); 8362 vassert(!mode64); 8363 t0 = newTemp(Ity_I8); 8364 t1 = newTemp(Ity_I8); 8365 t2 = newTemp(Ity_I8); 8366 t3 = newTemp(Ity_I8); 8367 8368 assign(t0, unop(Iop_32to8, 8369 binop(Iop_Shr32, 8370 unop(Iop_8Uto32, 8371 unop(Iop_32to8, getIReg(rt))), 8372 mkU8(rs)))); 8373 assign(t1, unop(Iop_32to8, 8374 binop(Iop_Shr32, 8375 unop(Iop_8Uto32, 8376 unop(Iop_16HIto8, 8377 unop(Iop_32to16, 8378 getIReg(rt)))), 8379 mkU8(rs)))); 8380 assign(t2, unop(Iop_32to8, 8381 binop(Iop_Shr32, 8382 unop(Iop_8Uto32, 8383 unop(Iop_16to8, 8384 unop(Iop_32HIto16, 8385 getIReg(rt)))), 8386 mkU8(rs)))); 8387 assign(t3, unop(Iop_32to8, 8388 binop(Iop_Shr32, 8389 unop(Iop_8Uto32, 8390 unop(Iop_16HIto8, 8391 unop(Iop_32HIto16, 8392 getIReg(rt)))), 8393 mkU8(rs)))); 8394 putIReg(rd, 8395 binop(Iop_16HLto32, 8396 binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)), 8397 binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0)))); 8398 break; 8399 } 8400 case 0x4: { /* SHRA.QB */ 8401 DIP("shra.qb r%u, r%u, %u", rd, rt, rs); 8402 vassert(!mode64); 8403 t0 = newTemp(Ity_I32); 8404 t1 = newTemp(Ity_I32); 8405 t2 = newTemp(Ity_I32); 8406 t3 = newTemp(Ity_I32); 8407 t4 = newTemp(Ity_I32); 8408 t5 = newTemp(Ity_I32); 8409 t6 = newTemp(Ity_I32); 8410 t7 = newTemp(Ity_I32); 8411 t8 = newTemp(Ity_I32); 8412 t9 = newTemp(Ity_I32); 8413 t10 = newTemp(Ity_I32); 8414 t11 = newTemp(Ity_I32); 8415 8416 /* ========== GPR[rt]_31..24 ========== */ 8417 assign(t1, 8418 unop(Iop_8Uto32, 8419 unop(Iop_16HIto8, 8420 unop(Iop_32HIto16, getIReg(rt))))); 8421 assign(t2, 8422 binop(Iop_Shr32, mkexpr(t1), mkU8(rs))); 8423 /* tempD_7..0 */ 8424 assign(t0, 8425 binop(Iop_Or32, 8426 mkexpr(t2), 8427 binop(Iop_Shl32, 8428 IRExpr_ITE(binop(Iop_CmpEQ32, 8429 binop(Iop_And32, 8430 mkexpr(t1), 8431 mkU32(0x00000080) 8432 ), 8433 mkU32(0x00000080)), 8434 mkU32(0xFFFFFFFF), 8435 mkU32(0x00000000)), 8436 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8437 8438 /* ========== GPR[rt]_23..16 ========== */ 8439 assign(t4, 8440 unop(Iop_8Uto32, 8441 unop(Iop_16to8, 8442 unop(Iop_32HIto16, getIReg(rt))))); 8443 assign(t5, binop(Iop_Shr32, mkexpr(t4), mkU8(rs))); 8444 /* tempC_7..0 */ 8445 assign(t3, 8446 binop(Iop_Or32, 8447 mkexpr(t5), 8448 binop(Iop_Shl32, 8449 IRExpr_ITE(binop(Iop_CmpEQ32, 8450 binop(Iop_And32, 8451 mkexpr(t4), 8452 mkU32(0x00000080) 8453 ), 8454 mkU32(0x00000080)), 8455 mkU32(0xFFFFFFFF), 8456 mkU32(0x00000000)), 8457 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8458 8459 /* ========== GPR[rt]_15..8 ========== */ 8460 assign(t7, 8461 unop(Iop_8Uto32, 8462 unop(Iop_16HIto8, 8463 unop(Iop_32to16, getIReg(rt))))); 8464 assign(t8, binop(Iop_Shr32, mkexpr(t7), mkU8(rs))); 8465 /* tempB_7..0 */ 8466 assign(t6, 8467 binop(Iop_Or32, 8468 mkexpr(t8), 8469 binop(Iop_Shl32, 8470 IRExpr_ITE(binop(Iop_CmpEQ32, 8471 binop(Iop_And32, 8472 mkexpr(t7), 8473 mkU32(0x00000080) 8474 ), 8475 mkU32(0x00000080)), 8476 mkU32(0xFFFFFFFF), 8477 mkU32(0x00000000)), 8478 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8479 8480 /* ========== GPR[rt]_7..0 ========== */ 8481 assign(t10, 8482 unop(Iop_8Uto32, 8483 unop(Iop_16to8, 8484 unop(Iop_32to16, getIReg(rt))))); 8485 assign(t11, binop(Iop_Shr32, mkexpr(t10), mkU8(rs))); 8486 /* tempB_7..0 */ 8487 assign(t9, 8488 binop(Iop_Or32, 8489 mkexpr(t11), 8490 binop(Iop_Shl32, 8491 IRExpr_ITE(binop(Iop_CmpEQ32, 8492 binop(Iop_And32, 8493 mkexpr(t10), 8494 mkU32(0x00000080) 8495 ), 8496 mkU32(0x00000080)), 8497 mkU32(0xFFFFFFFF), 8498 mkU32(0x00000000)), 8499 binop(Iop_Sub8, mkU8(0x8), mkU8(rs))))); 8500 8501 putIReg(rd, 8502 binop(Iop_16HLto32, 8503 binop(Iop_8HLto16, 8504 unop(Iop_32to8, mkexpr(t0)), 8505 unop(Iop_32to8, mkexpr(t3))), 8506 binop(Iop_8HLto16, 8507 unop(Iop_32to8, mkexpr(t6)), 8508 unop(Iop_32to8, mkexpr(t9))))); 8509 break; 8510 } 8511 case 0x5: { /* SHRA_R.QB */ 8512 DIP("shra_r.qb r%u, r%u, %u", rd, rt, rs); 8513 vassert(!mode64); 8514 t0 = newTemp(Ity_I32); 8515 t1 = newTemp(Ity_I8); 8516 t2 = newTemp(Ity_I32); 8517 t3 = newTemp(Ity_I8); 8518 t4 = newTemp(Ity_I32); 8519 t5 = newTemp(Ity_I8); 8520 t6 = newTemp(Ity_I32); 8521 t7 = newTemp(Ity_I8); 8522 8523 if (0 == rs) { 8524 putIReg(rd, getIReg(rt)); 8525 } else { 8526 assign(t0, unop(Iop_8Sto32, 8527 unop(Iop_16to8, 8528 unop(Iop_32to16, getIReg(rt))))); 8529 assign(t1, unop(Iop_32to8, 8530 binop(Iop_Sar32, 8531 binop(Iop_Add32, 8532 mkexpr(t0), 8533 binop(Iop_Shl32, 8534 mkU32(0x1), 8535 mkU8(rs-1))), 8536 mkU8(rs)))); 8537 8538 assign(t2, unop(Iop_8Sto32, 8539 unop(Iop_16HIto8, 8540 unop(Iop_32to16, getIReg(rt))))); 8541 assign(t3, unop(Iop_32to8, 8542 binop(Iop_Sar32, 8543 binop(Iop_Add32, 8544 mkexpr(t2), 8545 binop(Iop_Shl32, 8546 mkU32(0x1), 8547 mkU8(rs-1))), 8548 mkU8(rs)))); 8549 8550 assign(t4, unop(Iop_8Sto32, 8551 unop(Iop_16to8, 8552 unop(Iop_32HIto16, getIReg(rt))))); 8553 assign(t5, unop(Iop_32to8, 8554 binop(Iop_Sar32, 8555 binop(Iop_Add32, 8556 mkexpr(t4), 8557 binop(Iop_Shl32, 8558 mkU32(0x1), 8559 mkU8(rs-1))), 8560 mkU8(rs)))); 8561 8562 assign(t6, unop(Iop_8Sto32, 8563 unop(Iop_16HIto8, 8564 unop(Iop_32HIto16, getIReg(rt))))); 8565 assign(t7, unop(Iop_32to8, 8566 binop(Iop_Sar32, 8567 binop(Iop_Add32, 8568 mkexpr(t6), 8569 binop(Iop_Shl32, 8570 mkU32(0x1), 8571 mkU8(rs-1))), 8572 mkU8(rs)))); 8573 putIReg(rd, binop(Iop_16HLto32, 8574 binop(Iop_8HLto16, 8575 mkexpr(t7), mkexpr(t5)), 8576 binop(Iop_8HLto16, 8577 mkexpr(t3), mkexpr(t1)))); 8578 } 8579 break; 8580 } 8581 case 0x6: { /* SHRAV.QB */ 8582 DIP("shrav.qb r%u, r%u, %u", rd, rt, rs); 8583 vassert(!mode64); 8584 8585 t0 = newTemp(Ity_I32); 8586 t1 = newTemp(Ity_I32); 8587 t2 = newTemp(Ity_I32); 8588 8589 t3 = newTemp(Ity_I32); 8590 t4 = newTemp(Ity_I32); 8591 t5 = newTemp(Ity_I32); 8592 8593 t6 = newTemp(Ity_I32); 8594 t7 = newTemp(Ity_I32); 8595 t8 = newTemp(Ity_I32); 8596 8597 t9 = newTemp(Ity_I32); 8598 t10 = newTemp(Ity_I32); 8599 t11 = newTemp(Ity_I32); 8600 8601 /* ========== GPR[rt]_31..24 ========== */ 8602 assign(t1, 8603 unop(Iop_8Uto32, 8604 unop(Iop_16HIto8, 8605 unop(Iop_32HIto16, getIReg(rt))))); 8606 assign(t2, 8607 binop(Iop_Shr32, 8608 mkexpr(t1), 8609 unop(Iop_32to8, binop(Iop_And32, 8610 getIReg(rs), 8611 mkU32(0x7))))); 8612 /* tempD_7..0 */ 8613 assign(t0, 8614 binop(Iop_Or32, 8615 mkexpr(t2), 8616 binop(Iop_Shl32, 8617 IRExpr_ITE(binop(Iop_CmpEQ32, 8618 binop(Iop_And32, 8619 mkexpr(t1), 8620 mkU32(0x00000080) 8621 ), 8622 mkU32(0x00000080)), 8623 mkU32(0xFFFFFFFF), 8624 mkU32(0x00000000)), 8625 binop(Iop_Sub8, 8626 mkU8(0x8), 8627 unop(Iop_32to8, binop(Iop_And32, 8628 getIReg(rs), 8629 mkU32(0x7))) 8630 )))); 8631 8632 /* ========== GPR[rt]_23..16 ========== */ 8633 assign(t4, 8634 unop(Iop_8Uto32, 8635 unop(Iop_16to8, 8636 unop(Iop_32HIto16, getIReg(rt))))); 8637 assign(t5, 8638 binop(Iop_Shr32, 8639 mkexpr(t4), 8640 unop(Iop_32to8, binop(Iop_And32, 8641 getIReg(rs), 8642 mkU32(0x7))))); 8643 /* tempC_7..0 */ 8644 assign(t3, 8645 binop(Iop_Or32, 8646 mkexpr(t5), 8647 binop(Iop_Shl32, 8648 IRExpr_ITE(binop(Iop_CmpEQ32, 8649 binop(Iop_And32, 8650 mkexpr(t4), 8651 mkU32(0x00000080) 8652 ), 8653 mkU32(0x00000080)), 8654 mkU32(0xFFFFFFFF), 8655 mkU32(0x00000000)), 8656 binop(Iop_Sub8, 8657 mkU8(0x8), 8658 unop(Iop_32to8, binop(Iop_And32, 8659 getIReg(rs), 8660 mkU32(0x7))) 8661 )))); 8662 8663 /* ========== GPR[rt]_15..8 ========== */ 8664 assign(t7, 8665 unop(Iop_8Uto32, 8666 unop(Iop_16HIto8, 8667 unop(Iop_32to16, getIReg(rt))))); 8668 assign(t8, 8669 binop(Iop_Shr32, 8670 mkexpr(t7), 8671 unop(Iop_32to8, binop(Iop_And32, 8672 getIReg(rs), 8673 mkU32(0x7))))); 8674 /* tempB_7..0 */ 8675 assign(t6, 8676 binop(Iop_Or32, 8677 mkexpr(t8), 8678 binop(Iop_Shl32, 8679 IRExpr_ITE(binop(Iop_CmpEQ32, 8680 binop(Iop_And32, 8681 mkexpr(t7), 8682 mkU32(0x00000080) 8683 ), 8684 mkU32(0x00000080)), 8685 mkU32(0xFFFFFFFF), 8686 mkU32(0x00000000)), 8687 binop(Iop_Sub8, 8688 mkU8(0x8), 8689 unop(Iop_32to8, binop(Iop_And32, 8690 getIReg(rs), 8691 mkU32(0x7))) 8692 )))); 8693 8694 /* ========== GPR[rt]_7..0 ========== */ 8695 assign(t10, 8696 unop(Iop_8Uto32, 8697 unop(Iop_16to8, 8698 unop(Iop_32to16, getIReg(rt))))); 8699 assign(t11, 8700 binop(Iop_Shr32, 8701 mkexpr(t10), 8702 unop(Iop_32to8, binop(Iop_And32, 8703 getIReg(rs), 8704 mkU32(0x7))))); 8705 /* tempB_7..0 */ 8706 assign(t9, 8707 binop(Iop_Or32, 8708 mkexpr(t11), 8709 binop(Iop_Shl32, 8710 IRExpr_ITE(binop(Iop_CmpEQ32, 8711 binop(Iop_And32, 8712 mkexpr(t10), 8713 mkU32(0x00000080) 8714 ), 8715 mkU32(0x00000080)), 8716 mkU32(0xFFFFFFFF), 8717 mkU32(0x00000000)), 8718 binop(Iop_Sub8, 8719 mkU8(0x8), 8720 unop(Iop_32to8, binop(Iop_And32, 8721 getIReg(rs), 8722 mkU32(0x7))) 8723 )))); 8724 8725 putIReg(rd, 8726 binop(Iop_16HLto32, 8727 binop(Iop_8HLto16, 8728 unop(Iop_32to8, 8729 IRExpr_ITE(binop(Iop_CmpEQ32, 8730 binop(Iop_And32, 8731 mkU32(rs), 8732 mkU32(0x7) 8733 ), 8734 mkU32(0x0)), 8735 mkexpr(t1), 8736 mkexpr(t0))), 8737 unop(Iop_32to8, 8738 IRExpr_ITE(binop(Iop_CmpEQ32, 8739 binop(Iop_And32, 8740 mkU32(rs), 8741 mkU32(0x7) 8742 ), 8743 mkU32(0x0)), 8744 mkexpr(t2), 8745 mkexpr(t3)))), 8746 binop(Iop_8HLto16, 8747 unop(Iop_32to8, 8748 IRExpr_ITE(binop(Iop_CmpEQ32, 8749 binop(Iop_And32, 8750 mkU32(rs), 8751 mkU32(0x7) 8752 ), 8753 mkU32(0x0)), 8754 mkexpr(t5), 8755 mkexpr(t6))), 8756 unop(Iop_32to8, 8757 IRExpr_ITE(binop(Iop_CmpEQ32, 8758 binop(Iop_And32, 8759 mkU32(rs), 8760 mkU32(0x7) 8761 ), 8762 mkU32(0x0)), 8763 mkexpr(t8), 8764 mkexpr(t9)))))); 8765 break; 8766 } 8767 case 0x7: { /* SHRAV_R.QB */ 8768 DIP("shrav_r.qb r%u, r%u, r%u", rd, rt, rs); 8769 vassert(!mode64); 8770 t0 = newTemp(Ity_I32); 8771 t1 = newTemp(Ity_I8); 8772 t2 = newTemp(Ity_I32); 8773 t3 = newTemp(Ity_I8); 8774 t4 = newTemp(Ity_I32); 8775 t5 = newTemp(Ity_I8); 8776 t6 = newTemp(Ity_I32); 8777 t7 = newTemp(Ity_I8); 8778 t8 = newTemp(Ity_I8); 8779 t9 = newTemp(Ity_I32); 8780 8781 assign(t9, binop(Iop_And32, getIReg(rs), mkU32(0x7))); 8782 assign(t8, unop(Iop_32to8, 8783 binop(Iop_Sub32, mkexpr(t9), mkU32(0x1)))); 8784 assign(t0, unop(Iop_8Sto32, 8785 unop(Iop_16to8, 8786 unop(Iop_32to16, getIReg(rt))))); 8787 assign(t1, unop(Iop_32to8, 8788 binop(Iop_Sar32, 8789 binop(Iop_Add32, 8790 mkexpr(t0), 8791 binop(Iop_Shl32, 8792 mkU32(0x1), 8793 mkexpr(t8))), 8794 unop(Iop_32to8, 8795 mkexpr(t9))))); 8796 8797 assign(t2, unop(Iop_8Sto32, 8798 unop(Iop_16HIto8, 8799 unop(Iop_32to16, getIReg(rt))))); 8800 assign(t3, unop(Iop_32to8, 8801 binop(Iop_Sar32, 8802 binop(Iop_Add32, 8803 mkexpr(t2), 8804 binop(Iop_Shl32, 8805 mkU32(0x1), 8806 mkexpr(t8))), 8807 unop(Iop_32to8, mkexpr(t9))))); 8808 8809 assign(t4, unop(Iop_8Sto32, 8810 unop(Iop_16to8, 8811 unop(Iop_32HIto16, getIReg(rt))))); 8812 assign(t5, unop(Iop_32to8, 8813 binop(Iop_Sar32, 8814 binop(Iop_Add32, 8815 mkexpr(t4), 8816 binop(Iop_Shl32, 8817 mkU32(0x1), 8818 mkexpr(t8))), 8819 unop(Iop_32to8, mkexpr(t9))))); 8820 8821 assign(t6, unop(Iop_8Sto32, 8822 unop(Iop_16HIto8, 8823 unop(Iop_32HIto16, getIReg(rt))))); 8824 assign(t7, unop(Iop_32to8, 8825 binop(Iop_Sar32, 8826 binop(Iop_Add32, 8827 mkexpr(t6), 8828 binop(Iop_Shl32, 8829 mkU32(0x1), 8830 mkexpr(t8))), 8831 unop(Iop_32to8, mkexpr(t9))))); 8832 putIReg(rd, IRExpr_ITE(binop(Iop_CmpEQ32, 8833 mkexpr(t9), 8834 mkU32(0x0)), 8835 getIReg(rt), 8836 binop(Iop_16HLto32, 8837 binop(Iop_8HLto16, 8838 mkexpr(t7), 8839 mkexpr(t5)), 8840 binop(Iop_8HLto16, 8841 mkexpr(t3), 8842 mkexpr(t1))))); 8843 break; 8844 } 8845 case 0x8: { /* SHLL.PH */ 8846 DIP("shll.ph r%u, r%u, %u", rd, rt, rs); 8847 vassert(!mode64); 8848 t0 = newTemp(Ity_I32); 8849 t1 = newTemp(Ity_I32); 8850 t2 = newTemp(Ity_I32); 8851 t3 = newTemp(Ity_I32); 8852 t4 = newTemp(Ity_I32); 8853 t5 = newTemp(Ity_I32); 8854 t6 = newTemp(Ity_I32); 8855 t7 = newTemp(Ity_I32); 8856 8857 if (0 == rs) { 8858 putIReg(rd, getIReg(rt)); 8859 } else { 8860 /* Shift lower 16 bits. */ 8861 assign(t0, binop(Iop_Shl32, 8862 unop(Iop_16Sto32, 8863 unop(Iop_32to16, getIReg(rt))), 8864 mkU8(rs))); 8865 8866 assign(t1, unop(Iop_1Uto32, 8867 binop(Iop_CmpNE32, 8868 binop(Iop_Sar32, 8869 mkexpr(t0), 8870 mkU8(16)), 8871 mkU32(0)))); 8872 assign(t2, unop(Iop_1Uto32, 8873 binop(Iop_CmpNE32, 8874 binop(Iop_Sar32, 8875 mkexpr(t0), 8876 mkU8(16)), 8877 mkU32(0xffffffff)))); 8878 assign(t3, binop(Iop_And32, 8879 mkexpr(t1), 8880 mkexpr(t2))); 8881 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8882 mkexpr(t3), 8883 mkU32(0x1)), 8884 binop(Iop_Or32, 8885 getDSPControl(), 8886 mkU32(0x400000)), 8887 getDSPControl())); 8888 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8889 binop(Iop_And32, 8890 getIReg(rt), 8891 mkU32(0x00008000)), 8892 binop(Iop_And32, 8893 mkexpr(t0), 8894 mkU32(0x00008000)) 8895 ), 8896 getDSPControl(), 8897 binop(Iop_Or32, 8898 getDSPControl(), 8899 mkU32(0x400000)))); 8900 /* Shift higher 16 bits. */ 8901 assign(t4, binop(Iop_Shl32, 8902 unop(Iop_16Sto32, 8903 unop(Iop_32HIto16, getIReg(rt))), 8904 mkU8(rs))); 8905 8906 assign(t5, unop(Iop_1Uto32, 8907 binop(Iop_CmpNE32, 8908 binop(Iop_Sar32, 8909 mkexpr(t4), 8910 mkU8(16)), 8911 mkU32(0)))); 8912 assign(t6, unop(Iop_1Uto32, 8913 binop(Iop_CmpNE32, 8914 binop(Iop_Sar32, 8915 mkexpr(t4), 8916 mkU8(16)), 8917 mkU32(0xffffffff)))); 8918 assign(t7, binop(Iop_And32, 8919 mkexpr(t5), 8920 mkexpr(t6))); 8921 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8922 mkexpr(t7), 8923 mkU32(0x1)), 8924 binop(Iop_Or32, 8925 getDSPControl(), 8926 mkU32(0x400000)), 8927 getDSPControl())); 8928 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8929 mkexpr(t7), 8930 mkU32(0x1)), 8931 binop(Iop_Or32, 8932 getDSPControl(), 8933 mkU32(0x400000)), 8934 getDSPControl())); 8935 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 8936 binop(Iop_And32, 8937 getIReg(rt), 8938 mkU32(0x80000000)), 8939 binop(Iop_Shl32, 8940 binop(Iop_And32, 8941 mkexpr(t4), 8942 mkU32(0x00008000)), 8943 mkU8(16)) 8944 ), 8945 getDSPControl(), 8946 binop(Iop_Or32, 8947 getDSPControl(), 8948 mkU32(0x400000)))); 8949 putIReg(rd, binop(Iop_16HLto32, 8950 unop(Iop_32to16, mkexpr(t4)), 8951 unop(Iop_32to16, mkexpr(t0)))); 8952 } 8953 break; 8954 } 8955 case 0x9: { /* SHRA.PH */ 8956 DIP("shra.ph r%u, r%u, %u", rd, rt, rs); 8957 vassert(!mode64); 8958 t0 = newTemp(Ity_I32); 8959 t1 = newTemp(Ity_I32); 8960 if (0 == rs) { 8961 putIReg(rd, getIReg(rt)); 8962 } else { 8963 assign(t0, binop(Iop_Sar32, 8964 unop(Iop_16Sto32, 8965 unop(Iop_32to16, getIReg(rt))), 8966 mkU8(rs))); 8967 assign(t1, binop(Iop_Sar32, 8968 unop(Iop_16Sto32, 8969 unop(Iop_32HIto16, getIReg(rt))), 8970 mkU8(rs))); 8971 putIReg(rd, binop(Iop_16HLto32, 8972 unop(Iop_32to16, mkexpr(t1)), 8973 unop(Iop_32to16, mkexpr(t0)))); 8974 } 8975 break; 8976 } 8977 case 0xA: { /* SHLLV.PH */ 8978 DIP("shllv.ph r%u, r%u, r%u", rd, rt, rs); 8979 vassert(!mode64); 8980 t0 = newTemp(Ity_I32); 8981 t2 = newTemp(Ity_I32); 8982 t3 = newTemp(Ity_I1); 8983 t4 = newTemp(Ity_I1); 8984 t5 = newTemp(Ity_I32); 8985 t6 = newTemp(Ity_I32); 8986 t7 = newTemp(Ity_I1); 8987 t8 = newTemp(Ity_I1); 8988 t9 = newTemp(Ity_I32); 8989 t10 = newTemp(Ity_I32); 8990 t11 = newTemp(Ity_I32); 8991 t12 = newTemp(Ity_I1); 8992 t13 = newTemp(Ity_I1); 8993 8994 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 8995 8996 /* Shift lower 16 bits. */ 8997 assign(t2, binop(Iop_Shl32, 8998 unop(Iop_16Sto32, 8999 unop(Iop_32to16, getIReg(rt))), 9000 unop(Iop_32to8, mkexpr(t0)))); 9001 9002 assign(t3, binop(Iop_CmpNE32, 9003 unop(Iop_16Sto32, 9004 unop(Iop_32HIto16, mkexpr(t2))), 9005 mkU32(0x00000000))); 9006 assign(t4, binop(Iop_CmpNE32, 9007 unop(Iop_16Sto32, 9008 unop(Iop_32HIto16, mkexpr(t2))), 9009 mkU32(0xffffffff))); 9010 assign(t10, binop(Iop_And32, 9011 unop(Iop_1Sto32, mkexpr(t3)), 9012 unop(Iop_1Sto32, mkexpr(t4)))); 9013 assign(t5, binop(Iop_Shr32, 9014 binop(Iop_And32, 9015 getIReg(rt), 9016 mkU32(0x00008000)), 9017 mkU8(15))); 9018 assign(t12, binop(Iop_CmpEQ32, 9019 mkexpr(t5), 9020 binop(Iop_Shr32, 9021 binop(Iop_And32, 9022 mkexpr(t2), 9023 mkU32(0x00008000)), 9024 mkU8(15)))); 9025 9026 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9027 mkexpr(t10), 9028 mkU32(0x0)), 9029 binop(Iop_Or32, 9030 getDSPControl(), 9031 mkU32(0x400000)), 9032 IRExpr_ITE(mkexpr(t12), 9033 getDSPControl(), 9034 binop(Iop_Or32, 9035 getDSPControl(), 9036 mkU32(0x400000))) 9037 )); 9038 /* Shift higher 16 bits. */ 9039 assign(t6, binop(Iop_Shl32, 9040 unop(Iop_16Sto32, 9041 unop(Iop_32HIto16, getIReg(rt))), 9042 unop(Iop_32to8, mkexpr(t0)))); 9043 9044 assign(t7, binop(Iop_CmpNE32, 9045 unop(Iop_16Sto32, 9046 unop(Iop_32HIto16, mkexpr(t6))), 9047 mkU32(0x00000000))); 9048 assign(t8, binop(Iop_CmpNE32, 9049 unop(Iop_16Sto32, 9050 unop(Iop_32HIto16, mkexpr(t6))), 9051 mkU32(0xffffffff))); 9052 assign(t11, binop(Iop_And32, 9053 unop(Iop_1Sto32, mkexpr(t7)), 9054 unop(Iop_1Sto32, mkexpr(t8)))); 9055 9056 assign(t9, binop(Iop_Shr32, 9057 binop(Iop_And32, 9058 getIReg(rt), 9059 mkU32(0x80000000)), 9060 mkU8(31))); 9061 assign(t13, binop(Iop_CmpEQ32, 9062 mkexpr(t9), 9063 binop(Iop_Shr32, 9064 binop(Iop_And32, 9065 mkexpr(t6), 9066 mkU32(0x00008000)), 9067 mkU8(15)))); 9068 9069 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9070 mkexpr(t11), 9071 mkU32(0x0)), 9072 binop(Iop_Or32, 9073 getDSPControl(), 9074 mkU32(0x400000)), 9075 IRExpr_ITE(mkexpr(t13), 9076 getDSPControl(), 9077 binop(Iop_Or32, 9078 getDSPControl(), 9079 mkU32(0x400000))) 9080 )); 9081 9082 putIReg(rd, binop(Iop_16HLto32, 9083 unop(Iop_32to16, mkexpr(t6)), 9084 unop(Iop_32to16, mkexpr(t2)))); 9085 break; 9086 } 9087 case 0xB: { /* SHRAV.PH */ 9088 DIP("shrav.ph r%u, r%u, r%u", rd, rt, rs); 9089 vassert(!mode64); 9090 t0 = newTemp(Ity_I32); 9091 t1 = newTemp(Ity_I1); 9092 t2 = newTemp(Ity_I32); 9093 t3 = newTemp(Ity_I32); 9094 9095 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9096 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9097 assign(t2, binop(Iop_Sar32, 9098 unop(Iop_16Sto32, 9099 unop(Iop_32to16, getIReg(rt))), 9100 unop(Iop_32to8, mkexpr(t0)))); 9101 assign(t3, binop(Iop_Sar32, 9102 unop(Iop_16Sto32, 9103 unop(Iop_32HIto16, getIReg(rt))), 9104 unop(Iop_32to8, mkexpr(t0)))); 9105 putIReg(rd, 9106 binop(Iop_16HLto32, 9107 IRExpr_ITE(mkexpr(t1), 9108 unop(Iop_32HIto16, getIReg(rt)), 9109 unop(Iop_32to16, mkexpr(t3))), 9110 IRExpr_ITE(mkexpr(t1), 9111 unop(Iop_32to16, getIReg(rt)), 9112 unop(Iop_32to16, mkexpr(t2))))); 9113 break; 9114 } 9115 case 0xC: { /* SHLL_S.PH */ 9116 DIP("shll_s.ph r%u, r%u, %u", rd, rt, rs); 9117 vassert(!mode64); 9118 t0 = newTemp(Ity_I32); 9119 t1 = newTemp(Ity_I32); 9120 t2 = newTemp(Ity_I32); 9121 t3 = newTemp(Ity_I32); 9122 t4 = newTemp(Ity_I32); 9123 t5 = newTemp(Ity_I32); 9124 t6 = newTemp(Ity_I32); 9125 t7 = newTemp(Ity_I32); 9126 t8 = newTemp(Ity_I32); 9127 t9 = newTemp(Ity_I32); 9128 t10 = newTemp(Ity_I32); 9129 t11 = newTemp(Ity_I32); 9130 t12 = newTemp(Ity_I32); 9131 t13 = newTemp(Ity_I32); 9132 t14 = newTemp(Ity_I32); 9133 9134 if (0 == rs) { 9135 putIReg(rd, getIReg(rt)); 9136 } else { 9137 /* Shift lower 16 bits. */ 9138 assign(t0, binop(Iop_Shl32, 9139 unop(Iop_16Sto32, 9140 unop(Iop_32to16, getIReg(rt))), 9141 mkU8(rs))); 9142 9143 assign(t1, unop(Iop_1Uto32, 9144 binop(Iop_CmpNE32, 9145 binop(Iop_Sar32, 9146 mkexpr(t0), 9147 mkU8(16)), 9148 mkU32(0)))); 9149 assign(t2, unop(Iop_1Uto32, 9150 binop(Iop_CmpNE32, 9151 binop(Iop_Sar32, 9152 mkexpr(t0), 9153 mkU8(16)), 9154 mkU32(0xffffffff)))); 9155 assign(t3, binop(Iop_And32, 9156 mkexpr(t1), 9157 mkexpr(t2))); 9158 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9159 mkexpr(t3), 9160 mkU32(0x1)), 9161 binop(Iop_Or32, 9162 getDSPControl(), 9163 mkU32(0x400000)), 9164 getDSPControl())); 9165 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9166 binop(Iop_And32, 9167 getIReg(rt), 9168 mkU32(0x00008000)), 9169 binop(Iop_And32, 9170 mkexpr(t0), 9171 mkU32(0x00008000)) 9172 ), 9173 getDSPControl(), 9174 binop(Iop_Or32, 9175 getDSPControl(), 9176 mkU32(0x400000)))); 9177 assign(t8, 9178 IRExpr_ITE(binop(Iop_CmpEQ32, 9179 mkexpr(t3), 9180 mkU32(0x1)), 9181 IRExpr_ITE(binop(Iop_CmpEQ32, 9182 binop(Iop_And32, 9183 getIReg(rt), 9184 mkU32(0x8000)), 9185 mkU32(0)), 9186 mkU32(0x00007fff), 9187 mkU32(0x00008000)), 9188 binop(Iop_And32, 9189 mkexpr(t0), 9190 mkU32(0x0000ffff)))); 9191 assign(t10, 9192 IRExpr_ITE(binop(Iop_CmpEQ32, 9193 binop(Iop_And32, 9194 getIReg(rt), 9195 mkU32(0x00008000)), 9196 binop(Iop_And32, 9197 mkexpr(t0), 9198 mkU32(0x00008000))), 9199 mkexpr(t8), 9200 IRExpr_ITE(binop(Iop_CmpEQ32, 9201 binop(Iop_And32, 9202 getIReg(rt), 9203 mkU32(0x8000)), 9204 mkU32(0)), 9205 mkU32(0x00007fff), 9206 mkU32(0x00008000)))); 9207 /* Shift higher 16 bits. */ 9208 assign(t4, binop(Iop_Shl32, 9209 unop(Iop_16Sto32, 9210 unop(Iop_32HIto16, getIReg(rt))), 9211 mkU8(rs))); 9212 9213 assign(t5, unop(Iop_1Uto32, 9214 binop(Iop_CmpNE32, 9215 binop(Iop_Sar32, 9216 mkexpr(t4), 9217 mkU8(16)), 9218 mkU32(0)))); 9219 assign(t6, unop(Iop_1Uto32, 9220 binop(Iop_CmpNE32, 9221 binop(Iop_Sar32, 9222 mkexpr(t4), 9223 mkU8(16)), 9224 mkU32(0xffffffff)))); 9225 assign(t7, binop(Iop_And32, 9226 mkexpr(t5), 9227 mkexpr(t6))); 9228 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9229 mkexpr(t7), 9230 mkU32(0x1)), 9231 binop(Iop_Or32, 9232 getDSPControl(), 9233 mkU32(0x400000)), 9234 getDSPControl())); 9235 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9236 mkexpr(t7), 9237 mkU32(0x1)), 9238 binop(Iop_Or32, 9239 getDSPControl(), 9240 mkU32(0x400000)), 9241 getDSPControl())); 9242 assign(t12, binop(Iop_Shl32, 9243 binop(Iop_And32, 9244 mkexpr(t4), 9245 mkU32(0x8000)), 9246 mkU8(16))); 9247 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9248 binop(Iop_And32, 9249 getIReg(rt), 9250 mkU32(0x80000000)), 9251 mkexpr(t12)), 9252 getDSPControl(), 9253 binop(Iop_Or32, 9254 getDSPControl(), 9255 mkU32(0x400000)))); 9256 assign(t13, IRExpr_ITE(binop(Iop_CmpEQ32, 9257 binop(Iop_And32, 9258 getIReg(rt), 9259 mkU32(0x80000000)), 9260 mkU32(0)), 9261 mkU32(0x7fff0000), 9262 mkU32(0x80000000))); 9263 assign(t9, 9264 IRExpr_ITE(binop(Iop_CmpEQ32, 9265 mkexpr(t7), 9266 mkU32(0x1)), 9267 mkexpr(t13), 9268 binop(Iop_Shl32, 9269 binop(Iop_And32, 9270 mkexpr(t4), 9271 mkU32(0x0000ffff)), 9272 mkU8(16)))); 9273 assign(t14, IRExpr_ITE(binop(Iop_CmpEQ32, 9274 binop(Iop_And32, 9275 getIReg(rt), 9276 mkU32(0x80000000)), 9277 mkU32(0)), 9278 mkU32(0x7fff0000), 9279 mkU32(0x80000000))); 9280 assign(t11, 9281 IRExpr_ITE(binop(Iop_CmpEQ32, 9282 binop(Iop_And32, 9283 getIReg(rt), 9284 mkU32(0x80000000)), 9285 binop(Iop_Shl32, 9286 binop(Iop_And32, 9287 mkexpr(t4), 9288 mkU32(0x00008000)), 9289 mkU8(16))), 9290 mkexpr(t9), 9291 mkexpr(t14))); 9292 putIReg(rd, binop(Iop_Or32, 9293 mkexpr(t10), 9294 mkexpr(t11))); 9295 } 9296 break; 9297 } 9298 case 0xD: { /* SHRA_R.PH */ 9299 DIP("shra.ph r%u, r%u, %u", rd, rt, rs); 9300 vassert(!mode64); 9301 t0 = newTemp(Ity_I32); 9302 t1 = newTemp(Ity_I32); 9303 if (0 == rs) { 9304 putIReg(rd, getIReg(rt)); 9305 } else { 9306 assign(t0, binop(Iop_Sar32, 9307 binop(Iop_Add32, 9308 unop(Iop_16Sto32, 9309 unop(Iop_32to16, 9310 getIReg(rt))), 9311 binop(Iop_Shl32, 9312 mkU32(0x1), 9313 mkU8(rs-1))), 9314 mkU8(rs))); 9315 assign(t1, binop(Iop_Sar32, 9316 binop(Iop_Add32, 9317 unop(Iop_16Sto32, 9318 unop(Iop_32HIto16, 9319 getIReg(rt))), 9320 binop(Iop_Shl32, 9321 mkU32(0x1), 9322 mkU8(rs-1))), 9323 mkU8(rs))); 9324 putIReg(rd, binop(Iop_16HLto32, 9325 unop(Iop_32to16, mkexpr(t1)), 9326 unop(Iop_32to16, mkexpr(t0)))); 9327 } 9328 break; 9329 } 9330 case 0xE: { /* SHLLV_S.PH */ 9331 DIP("shllv_s.ph r%u, r%u, r%u", rd, rt, rs); 9332 vassert(!mode64); 9333 t0 = newTemp(Ity_I32); 9334 t2 = newTemp(Ity_I32); 9335 t3 = newTemp(Ity_I1); 9336 t4 = newTemp(Ity_I1); 9337 t5 = newTemp(Ity_I32); 9338 t6 = newTemp(Ity_I32); 9339 t7 = newTemp(Ity_I1); 9340 t8 = newTemp(Ity_I1); 9341 t9 = newTemp(Ity_I32); 9342 t10 = newTemp(Ity_I32); 9343 t11 = newTemp(Ity_I32); 9344 t12 = newTemp(Ity_I1); 9345 t13 = newTemp(Ity_I1); 9346 t14 = newTemp(Ity_I16); 9347 t15 = newTemp(Ity_I16); 9348 t16 = newTemp(Ity_I16); 9349 t17 = newTemp(Ity_I16); 9350 9351 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9352 9353 /* Shift lower 16 bits. */ 9354 assign(t2, binop(Iop_Shl32, 9355 unop(Iop_16Sto32, 9356 unop(Iop_32to16, getIReg(rt))), 9357 unop(Iop_32to8, mkexpr(t0)))); 9358 9359 assign(t3, binop(Iop_CmpNE32, 9360 unop(Iop_16Sto32, 9361 unop(Iop_32HIto16, mkexpr(t2))), 9362 mkU32(0x00000000))); 9363 assign(t4, binop(Iop_CmpNE32, 9364 unop(Iop_16Sto32, 9365 unop(Iop_32HIto16, mkexpr(t2))), 9366 mkU32(0xffffffff))); 9367 assign(t10, binop(Iop_And32, 9368 unop(Iop_1Sto32, mkexpr(t3)), 9369 unop(Iop_1Sto32, mkexpr(t4)))); 9370 assign(t5, binop(Iop_Shr32, 9371 binop(Iop_And32, 9372 getIReg(rt), 9373 mkU32(0x00008000)), 9374 mkU8(15))); 9375 assign(t12, binop(Iop_CmpEQ32, 9376 mkexpr(t5), 9377 binop(Iop_Shr32, 9378 binop(Iop_And32, 9379 mkexpr(t2), 9380 mkU32(0x00008000)), 9381 mkU8(15)))); 9382 9383 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9384 mkexpr(t10), 9385 mkU32(0x0)), 9386 binop(Iop_Or32, 9387 getDSPControl(), 9388 mkU32(0x400000)), 9389 IRExpr_ITE(mkexpr(t12), 9390 getDSPControl(), 9391 binop(Iop_Or32, 9392 getDSPControl(), 9393 mkU32(0x400000))) 9394 )); 9395 assign(t14, IRExpr_ITE(binop(Iop_CmpNE32, 9396 mkexpr(t5), 9397 mkU32(0x0)), 9398 mkU16(0x8000), 9399 mkU16(0x7fff))); 9400 assign(t15, IRExpr_ITE(binop(Iop_CmpNE32, 9401 mkexpr(t10), 9402 mkU32(0x0)), 9403 mkexpr(t14), 9404 IRExpr_ITE(mkexpr(t12), 9405 unop(Iop_32to16, 9406 mkexpr(t2)), 9407 mkexpr(t14)))); 9408 /* Shift higher 16 bits. */ 9409 assign(t6, binop(Iop_Shl32, 9410 unop(Iop_16Sto32, 9411 unop(Iop_32HIto16, getIReg(rt))), 9412 unop(Iop_32to8, mkexpr(t0)))); 9413 9414 assign(t7, binop(Iop_CmpNE32, 9415 unop(Iop_16Sto32, 9416 unop(Iop_32HIto16, mkexpr(t6))), 9417 mkU32(0x00000000))); 9418 assign(t8, binop(Iop_CmpNE32, 9419 unop(Iop_16Sto32, 9420 unop(Iop_32HIto16, mkexpr(t6))), 9421 mkU32(0xffffffff))); 9422 assign(t11, binop(Iop_And32, 9423 unop(Iop_1Sto32, mkexpr(t7)), 9424 unop(Iop_1Sto32, mkexpr(t8)))); 9425 9426 assign(t9, binop(Iop_Shr32, 9427 binop(Iop_And32, 9428 getIReg(rt), 9429 mkU32(0x80000000)), 9430 mkU8(31))); 9431 assign(t13, binop(Iop_CmpEQ32, 9432 mkexpr(t9), 9433 binop(Iop_Shr32, 9434 binop(Iop_And32, 9435 mkexpr(t6), 9436 mkU32(0x00008000)), 9437 mkU8(15)))); 9438 9439 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9440 mkexpr(t11), 9441 mkU32(0x0)), 9442 binop(Iop_Or32, 9443 getDSPControl(), 9444 mkU32(0x400000)), 9445 IRExpr_ITE(mkexpr(t13), 9446 getDSPControl(), 9447 binop(Iop_Or32, 9448 getDSPControl(), 9449 mkU32(0x400000))) 9450 )); 9451 9452 assign(t16, IRExpr_ITE(binop(Iop_CmpNE32, 9453 mkexpr(t9), 9454 mkU32(0x0)), 9455 mkU16(0x8000), 9456 mkU16(0x7fff))); 9457 assign(t17, IRExpr_ITE(binop(Iop_CmpNE32, 9458 mkexpr(t11), 9459 mkU32(0x0)), 9460 mkexpr(t16), 9461 IRExpr_ITE(mkexpr(t13), 9462 unop(Iop_32to16, 9463 mkexpr(t6)), 9464 mkexpr(t16)))); 9465 9466 putIReg(rd, binop(Iop_16HLto32, mkexpr(t17), mkexpr(t15))); 9467 break; 9468 } 9469 case 0xF: { /* SHRAV_R.PH */ 9470 DIP("shrav_r.ph r%u, r%u, r%u", rd, rt, rs); 9471 vassert(!mode64); 9472 t0 = newTemp(Ity_I32); 9473 t1 = newTemp(Ity_I1); 9474 t2 = newTemp(Ity_I8); 9475 t3 = newTemp(Ity_I32); 9476 t4 = newTemp(Ity_I32); 9477 9478 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9479 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9480 assign(t2, unop(Iop_32to8, 9481 binop(Iop_Sub32, mkexpr(t0), mkU32(1)))); 9482 9483 assign(t3, binop(Iop_Sar32, 9484 binop(Iop_Add32, 9485 unop(Iop_16Sto32, 9486 unop(Iop_32to16, getIReg(rt))), 9487 binop(Iop_Shl32, 9488 mkU32(0x1), 9489 mkexpr(t2))), 9490 unop(Iop_32to8, mkexpr(t0)))); 9491 assign(t4, binop(Iop_Sar32, 9492 binop(Iop_Add32, 9493 unop(Iop_16Sto32, 9494 unop(Iop_32HIto16, 9495 getIReg(rt))), 9496 binop(Iop_Shl32, 9497 mkU32(0x1), 9498 mkexpr(t2))), 9499 unop(Iop_32to8, mkexpr(t0)))); 9500 9501 putIReg(rd, binop(Iop_16HLto32, 9502 IRExpr_ITE(mkexpr(t1), 9503 unop(Iop_32HIto16, 9504 getIReg(rt)), 9505 unop(Iop_32to16, 9506 mkexpr(t4))), 9507 IRExpr_ITE(mkexpr(t1), 9508 unop(Iop_32to16, getIReg(rt)), 9509 unop(Iop_32to16, 9510 mkexpr(t3))))); 9511 break; 9512 } 9513 case 0x14: { /* SHLL_S.W */ 9514 DIP("shll_s.w r%u, r%u, %u", rd, rt, rs); 9515 vassert(!mode64); 9516 t0 = newTemp(Ity_I32); 9517 t1 = newTemp(Ity_I32); 9518 t2 = newTemp(Ity_I32); 9519 t3 = newTemp(Ity_I32); 9520 t4 = newTemp(Ity_I32); 9521 t5 = newTemp(Ity_I32); 9522 9523 if (0 == rs) { 9524 putIReg(rd, getIReg(rt)); 9525 } else { 9526 /* t0-bits that will be discarded, sign extended to 9527 32bits. */ 9528 assign(t0, binop(Iop_Sar32, 9529 binop(Iop_And32, 9530 getIReg(rt), 9531 binop(Iop_Sar32, 9532 mkU32(0x80000000), 9533 mkU8(rs-1))), 9534 mkU8(32-rs))); 9535 9536 assign(t1, IRExpr_ITE(binop(Iop_CmpEQ32, 9537 binop(Iop_And32, 9538 getIReg(rt), 9539 mkU32(0x80000000)), 9540 mkU32(0x0)), 9541 mkU32(0x7fffffff), 9542 mkU32(0x80000000))); 9543 9544 assign(t2, binop(Iop_Shl32, getIReg(rt), mkU8(rs))); 9545 assign(t3, IRExpr_ITE(binop(Iop_CmpEQ32, 9546 binop(Iop_And32, 9547 getIReg(rt), 9548 mkU32(0x80000000)), 9549 binop(Iop_And32, 9550 mkexpr(t2), 9551 mkU32(0x80000000))), 9552 mkexpr(t2), 9553 mkexpr(t1))); 9554 9555 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 9556 mkexpr(t0), 9557 mkU32(0x0)), 9558 IRExpr_ITE(binop(Iop_CmpNE32, 9559 mkexpr(t0), 9560 mkU32(0xffffffff) 9561 ), 9562 mkexpr(t1), 9563 mkexpr(t3)), 9564 mkexpr(t3))); 9565 assign(t5, IRExpr_ITE(binop(Iop_CmpNE32, 9566 mkexpr(t0), 9567 mkU32(0xffffffff)), 9568 binop(Iop_Or32, 9569 getDSPControl(), 9570 mkU32(0x400000)), 9571 getDSPControl())); 9572 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 9573 mkexpr(t0), 9574 mkU32(0x0)), 9575 mkexpr(t5), 9576 getDSPControl())); 9577 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 9578 binop(Iop_And32, 9579 getIReg(rt), 9580 mkU32(0x80000000)), 9581 binop(Iop_And32, 9582 mkexpr(t2), 9583 mkU32(0x80000000)) 9584 ), 9585 getDSPControl(), 9586 binop(Iop_Or32, 9587 getDSPControl(), 9588 mkU32(0x400000)))); 9589 putIReg(rd, mkexpr(t4)); 9590 } 9591 break; 9592 } 9593 case 0x15: { /* SHRA_R.W */ 9594 DIP("shra_r.w r%u, r%u, %u", rd, rt, rs); 9595 vassert(!mode64); 9596 if (0 == rs) { 9597 putIReg(rd, getIReg(rt)); 9598 } else { 9599 putIReg(rd, binop(Iop_Add32, 9600 binop(Iop_Sar32, 9601 getIReg(rt), mkU8(rs)), 9602 binop(Iop_Shr32, 9603 binop(Iop_And32, 9604 getIReg(rt), 9605 binop(Iop_Shl32, 9606 mkU32(0x1), 9607 mkU8(rs-1))), 9608 mkU8(rs-1)))); 9609 } 9610 break; 9611 } 9612 case 0x16: { /* SHLLV_S.W */ 9613 DIP("shllv_s.w r%u, r%u, r%u", rd, rt, rs); 9614 vassert(!mode64); 9615 t0 = newTemp(Ity_I32); 9616 t1 = newTemp(Ity_I1); 9617 t2 = newTemp(Ity_I32); 9618 t3 = newTemp(Ity_I64); 9619 t4 = newTemp(Ity_I1); 9620 t5 = newTemp(Ity_I1); 9621 t6 = newTemp(Ity_I32); 9622 t7 = newTemp(Ity_I1); 9623 t8 = newTemp(Ity_I32); 9624 9625 /* Check if shift amount is zero. */ 9626 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 9627 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9628 9629 /* t2 = sign of the input value. */ 9630 assign(t2, binop(Iop_Shr32, 9631 binop(Iop_And32, 9632 getIReg(rt), 9633 mkU32(0x80000000)), 9634 mkU8(31))); 9635 /* Shift left input value and check for overflow. */ 9636 assign(t3, binop(Iop_Shl64, 9637 unop(Iop_32Sto64, getIReg(rt)), 9638 unop(Iop_32to8, mkexpr(t0)))); 9639 assign(t4, binop(Iop_CmpNE32, 9640 unop(Iop_64HIto32, mkexpr(t3)), 9641 mkU32(0x00000000))); 9642 assign(t5, binop(Iop_CmpNE32, 9643 unop(Iop_64HIto32, mkexpr(t3)), 9644 mkU32(0xffffffff))); 9645 assign(t6, binop(Iop_And32, 9646 unop(Iop_1Uto32, mkexpr(t4)), 9647 unop(Iop_1Uto32, mkexpr(t5)))); 9648 assign(t7, binop(Iop_CmpEQ32, 9649 binop(Iop_Shr32, 9650 binop(Iop_And32, 9651 getIReg(rt), 9652 mkU32(0x80000000)), 9653 mkU8(31)), 9654 binop(Iop_Shr32, 9655 binop(Iop_And32, 9656 unop(Iop_64to32, mkexpr(t3)), 9657 mkU32(0x80000000)), 9658 mkU8(31)))); 9659 9660 putDSPControl(IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)), 9661 binop(Iop_Or32, 9662 getDSPControl(), 9663 mkU32(0x400000)), 9664 IRExpr_ITE(mkexpr(t7), 9665 getDSPControl(), 9666 binop(Iop_Or32, 9667 getDSPControl(), 9668 mkU32(0x400000))) 9669 )); 9670 9671 assign(t8, IRExpr_ITE(unop(Iop_32to1, 9672 mkexpr(t2)), 9673 mkU32(0x80000000), 9674 mkU32(0x7fffffff))); 9675 putIReg(rd, IRExpr_ITE(unop(Iop_32to1, mkexpr(t6)), 9676 IRExpr_ITE(unop(Iop_32to1, 9677 mkexpr(t2)), 9678 mkU32(0x80000000), 9679 mkU32(0x7fffffff)), 9680 IRExpr_ITE(mkexpr(t7), 9681 unop(Iop_64to32, 9682 mkexpr(t3)), 9683 mkexpr(t8)))); 9684 break; 9685 } 9686 case 0x17: { /* SHRAV_R.W */ 9687 DIP("shrav_r.w r%u, r%u, r%u", rd, rt, rs); 9688 vassert(!mode64); 9689 t0 = newTemp(Ity_I32); 9690 t1 = newTemp(Ity_I1); 9691 t2 = newTemp(Ity_I8); 9692 t3 = newTemp(Ity_I32); 9693 9694 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 9695 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9696 assign(t2, unop(Iop_32to8, 9697 binop(Iop_Sub32, mkexpr(t0), mkU32(1)))); 9698 9699 putIReg(rd, IRExpr_ITE(mkexpr(t1), 9700 getIReg(rt), 9701 binop(Iop_Sar32, 9702 binop(Iop_Add32, 9703 binop(Iop_Sar32, 9704 getIReg(rt), 9705 mkexpr(t2)), 9706 mkU32(0x1)), 9707 mkU8(1)))); 9708 break; 9709 } 9710 case 0x19: { /* SHRL.PH */ 9711 DIP("shrl.ph r%u, r%u, %u", rd, rt, rs); 9712 vassert(!mode64); 9713 t0 = newTemp(Ity_I32); 9714 t1 = newTemp(Ity_I32); 9715 assign(t0, binop(Iop_Shr32, 9716 unop(Iop_16Uto32, 9717 unop(Iop_32to16, getIReg(rt))), 9718 mkU8(rs))); 9719 assign(t1, binop(Iop_Shr32, 9720 unop(Iop_16Uto32, 9721 unop(Iop_32HIto16, getIReg(rt))), 9722 mkU8(rs))); 9723 putIReg(rd, binop(Iop_16HLto32, 9724 unop(Iop_32to16, mkexpr(t1)), 9725 unop(Iop_32to16, mkexpr(t0)))); 9726 break; 9727 } 9728 case 0x1B: { /* SHRLV.PH */ 9729 DIP("shrlv.ph r%u, r%u, r%u", rd, rt, rs); 9730 vassert(!mode64); 9731 t0 = newTemp(Ity_I32); 9732 t1 = newTemp(Ity_I1); 9733 t2 = newTemp(Ity_I32); 9734 t3 = newTemp(Ity_I32); 9735 t4 = newTemp(Ity_I16); 9736 t5 = newTemp(Ity_I16); 9737 9738 /* Get shift amount from lower 5 bits of rs 9739 and check if it is zero. */ 9740 assign(t0, binop(Iop_And32, getIReg(rs), mkU32(0x0f))); 9741 assign(t1, binop(Iop_CmpEQ32, mkexpr(t0), mkU32(0x0))); 9742 9743 assign(t2, binop(Iop_Shr32, 9744 unop(Iop_16Uto32, 9745 unop(Iop_32to16, getIReg(rt))), 9746 unop(Iop_32to8, mkexpr(t0)))); 9747 assign(t3, binop(Iop_Shr32, 9748 unop(Iop_16Uto32, 9749 unop(Iop_32HIto16, getIReg(rt))), 9750 unop(Iop_32to8, mkexpr(t0)))); 9751 9752 assign(t4, IRExpr_ITE(mkexpr(t1), 9753 unop(Iop_32HIto16, getIReg(rt)), 9754 unop(Iop_32to16, mkexpr(t3)))); 9755 assign(t5, IRExpr_ITE(mkexpr(t1), 9756 unop(Iop_32to16, getIReg(rt)), 9757 unop(Iop_32to16, mkexpr(t2)))); 9758 putIReg(rd, binop(Iop_16HLto32, mkexpr(t4), mkexpr(t5))); 9759 break; 9760 } 9761 default: 9762 return -1; 9763 } 9764 break; /* end of SHLL.QB */ 9765 } 9766 case 0x18: { /* ADDUH.QB/MUL.PH */ 9767 switch(sa) { 9768 case 0x00: { /* ADDUH.QB */ 9769 DIP("adduh.qb r%u, r%u, r%u", rd, rs, rt); 9770 vassert(!mode64); 9771 t0 = newTemp(Ity_I32); 9772 9773 assign(t0, binop(Iop_HAdd8Ux4, getIReg(rs), getIReg(rt))); 9774 9775 putIReg(rd, mkexpr(t0)); 9776 break; 9777 } 9778 case 0x1: { /* SUBUH.QB */ 9779 DIP("subuh.qb r%u, r%u, r%u", rd, rs, rt); 9780 vassert(!mode64); 9781 t0 = newTemp(Ity_I32); 9782 9783 assign(t0, binop(Iop_HSub8Ux4, getIReg(rs), getIReg(rt))); 9784 9785 putIReg(rd, mkexpr(t0)); 9786 break; 9787 } 9788 case 0x02: { /* ADDUH_R.QB */ 9789 DIP("adduh_r.qb r%u, r%u, r%u", rd, rs, rt); 9790 vassert(!mode64); 9791 t0 = newTemp(Ity_I32); 9792 t1 = newTemp(Ity_I32); 9793 t2 = newTemp(Ity_I8); 9794 t3 = newTemp(Ity_I32); 9795 t4 = newTemp(Ity_I32); 9796 t5 = newTemp(Ity_I8); 9797 t6 = newTemp(Ity_I32); 9798 t7 = newTemp(Ity_I32); 9799 t8 = newTemp(Ity_I8); 9800 t9 = newTemp(Ity_I32); 9801 t10 = newTemp(Ity_I32); 9802 t11 = newTemp(Ity_I8); 9803 9804 /* Extract input bytes, add values, add 1 and half the 9805 result. */ 9806 assign(t0, unop(Iop_8Uto32, 9807 unop(Iop_16to8, 9808 unop(Iop_32to16, getIReg(rs))))); 9809 assign(t1, unop(Iop_8Uto32, 9810 unop(Iop_16to8, 9811 unop(Iop_32to16, getIReg(rt))))); 9812 assign(t2, unop(Iop_16to8, 9813 unop(Iop_32to16, 9814 binop(Iop_Shr32, 9815 binop(Iop_Add32, 9816 binop(Iop_Add32, 9817 mkexpr(t0), 9818 mkexpr(t1)), 9819 mkU32(0x00000001)), 9820 mkU8(0x01))))); 9821 9822 assign(t3, unop(Iop_8Uto32, 9823 unop(Iop_16HIto8, 9824 unop(Iop_32to16, getIReg(rs))))); 9825 assign(t4, unop(Iop_8Uto32, 9826 unop(Iop_16HIto8, 9827 unop(Iop_32to16, getIReg(rt))))); 9828 assign(t5, unop(Iop_16to8, 9829 unop(Iop_32to16, 9830 binop(Iop_Shr32, 9831 binop(Iop_Add32, 9832 binop(Iop_Add32, 9833 mkexpr(t3), 9834 mkexpr(t4)), 9835 mkU32(0x00000001)), 9836 mkU8(0x01))))); 9837 9838 assign(t6, unop(Iop_8Uto32, 9839 unop(Iop_16to8, 9840 unop(Iop_32HIto16, getIReg(rs))))); 9841 assign(t7, unop(Iop_8Uto32, 9842 unop(Iop_16to8, 9843 unop(Iop_32HIto16, getIReg(rt))))); 9844 assign(t8, unop(Iop_16to8, 9845 unop(Iop_32to16, 9846 binop(Iop_Shr32, 9847 binop(Iop_Add32, 9848 binop(Iop_Add32, 9849 mkexpr(t7), 9850 mkexpr(t6)), 9851 mkU32(0x00000001)), 9852 mkU8(0x01))))); 9853 9854 assign(t9, unop(Iop_8Uto32, 9855 unop(Iop_16HIto8, 9856 unop(Iop_32HIto16, getIReg(rs))))); 9857 assign(t10, unop(Iop_8Uto32, 9858 unop(Iop_16HIto8, 9859 unop(Iop_32HIto16, getIReg(rt))))); 9860 assign(t11, unop(Iop_16to8, 9861 unop(Iop_32to16, 9862 binop(Iop_Shr32, 9863 binop(Iop_Add32, 9864 binop(Iop_Add32, 9865 mkexpr(t9), 9866 mkexpr(t10)), 9867 mkU32(0x00000001)), 9868 mkU8(0x01))))); 9869 9870 putIReg(rd, binop(Iop_16HLto32, 9871 binop(Iop_8HLto16, 9872 mkexpr(t11), mkexpr(t8)), 9873 binop(Iop_8HLto16, 9874 mkexpr(t5), mkexpr(t2)))); 9875 break; 9876 } 9877 case 0x3: { /* SUBUH_R.QB */ 9878 DIP("subuh_r.qb r%u, r%u, r%u", rd, rs, rt); 9879 vassert(!mode64); 9880 t1 = newTemp(Ity_I32); 9881 t2 = newTemp(Ity_I32); 9882 t3 = newTemp(Ity_I32); 9883 t4 = newTemp(Ity_I32); 9884 t5 = newTemp(Ity_I32); 9885 t6 = newTemp(Ity_I32); 9886 t7 = newTemp(Ity_I32); 9887 t8 = newTemp(Ity_I32); 9888 t9 = newTemp(Ity_I8); 9889 t10 = newTemp(Ity_I8); 9890 t11 = newTemp(Ity_I8); 9891 t12 = newTemp(Ity_I8); 9892 9893 /* Extract each byte of rs and rt. */ 9894 assign(t1, unop(Iop_8Uto32, 9895 unop(Iop_16to8, 9896 unop(Iop_32to16, getIReg(rs))))); 9897 assign(t2, unop(Iop_8Uto32, 9898 unop(Iop_16HIto8, 9899 unop(Iop_32to16, getIReg(rs))))); 9900 assign(t3, unop(Iop_8Uto32, 9901 unop(Iop_16to8, 9902 unop(Iop_32HIto16, getIReg(rs))))); 9903 assign(t4, unop(Iop_8Uto32, 9904 unop(Iop_16HIto8, 9905 unop(Iop_32HIto16, getIReg(rs))))); 9906 9907 assign(t5, unop(Iop_8Uto32, 9908 unop(Iop_16to8, 9909 unop(Iop_32to16, getIReg(rt))))); 9910 assign(t6, unop(Iop_8Uto32, 9911 unop(Iop_16HIto8, 9912 unop(Iop_32to16, getIReg(rt))))); 9913 assign(t7, unop(Iop_8Uto32, 9914 unop(Iop_16to8, 9915 unop(Iop_32HIto16, getIReg(rt))))); 9916 assign(t8, unop(Iop_8Uto32, 9917 unop(Iop_16HIto8, 9918 unop(Iop_32HIto16, getIReg(rt))))); 9919 9920 /* Add 1 to each resulting byte and half the results. */ 9921 assign(t9, unop(Iop_16to8, 9922 unop(Iop_32to16, 9923 binop(Iop_Shr32, 9924 binop(Iop_Add32, 9925 binop(Iop_Sub32, 9926 mkexpr(t1), 9927 mkexpr(t5)), 9928 mkU32(0x00000001)), 9929 mkU8(0x01))))); 9930 assign(t10, unop(Iop_16to8, 9931 unop(Iop_32to16, 9932 binop(Iop_Shr32, 9933 binop(Iop_Add32, 9934 binop(Iop_Sub32, 9935 mkexpr(t2), 9936 mkexpr(t6)), 9937 mkU32(0x00000001)), 9938 mkU8(0x01))))); 9939 assign(t11, unop(Iop_16to8, 9940 unop(Iop_32to16, 9941 binop(Iop_Shr32, 9942 binop(Iop_Add32, 9943 binop(Iop_Sub32, 9944 mkexpr(t3), 9945 mkexpr(t7)), 9946 mkU32(0x00000001)), 9947 mkU8(0x01))))); 9948 assign(t12, unop(Iop_16to8, 9949 unop(Iop_32to16, 9950 binop(Iop_Shr32, 9951 binop(Iop_Add32, 9952 binop(Iop_Sub32, 9953 mkexpr(t4), 9954 mkexpr(t8)), 9955 mkU32(0x00000001)), 9956 mkU8(0x01))))); 9957 9958 putIReg(rd, binop(Iop_16HLto32, 9959 binop(Iop_8HLto16, 9960 mkexpr(t12), mkexpr(t11)), 9961 binop(Iop_8HLto16, 9962 mkexpr(t10), mkexpr(t9)))); 9963 break; 9964 } 9965 case 0x8: { /* ADDQH.PH */ 9966 DIP("addqh.ph r%u, r%u, r%u", rd, rs, rt); 9967 vassert(!mode64); 9968 t0 = newTemp(Ity_I32); 9969 t1 = newTemp(Ity_I16); 9970 t2 = newTemp(Ity_I32); 9971 t3 = newTemp(Ity_I16); 9972 9973 /* Add lower halfs of rs and rt 9974 and right shift the result by 1. */ 9975 assign(t0, binop(Iop_Add32, 9976 unop(Iop_16Sto32, 9977 unop(Iop_32to16, getIReg(rs))), 9978 unop(Iop_16Sto32, 9979 unop(Iop_32to16, getIReg(rt))))); 9980 assign(t1, unop(Iop_32to16, 9981 binop(Iop_Shr32, 9982 binop(Iop_And32, 9983 mkexpr(t0), 9984 mkU32(0x0001fffe)), 9985 mkU8(0x1)))); 9986 /* Add higher halfs of rs and rt 9987 and right shift the result by 1. */ 9988 assign(t2, binop(Iop_Add32, 9989 unop(Iop_16Sto32, 9990 unop(Iop_32HIto16, getIReg(rs))), 9991 unop(Iop_16Sto32, 9992 unop(Iop_32HIto16, getIReg(rt))))); 9993 assign(t3, unop(Iop_32to16, 9994 binop(Iop_Shr32, 9995 binop(Iop_And32, 9996 mkexpr(t2), 9997 mkU32(0x0001fffe)), 9998 mkU8(0x1)))); 9999 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 10000 break; 10001 } 10002 case 0x9: { /* SUBQH.PH */ 10003 DIP("subqh.ph r%u, r%u, r%u", rd, rs, rt); 10004 vassert(!mode64); 10005 10006 putIReg(rd, binop(Iop_HSub16Sx2, 10007 getIReg(rs), getIReg(rt))); 10008 break; 10009 } 10010 case 0xA: {/* ADDQH_R.PH */ 10011 DIP("addqh_r.ph r%u, r%u, r%u", rd, rs, rt); 10012 vassert(!mode64); 10013 t0 = newTemp(Ity_I32); 10014 t1 = newTemp(Ity_I16); 10015 t2 = newTemp(Ity_I32); 10016 t3 = newTemp(Ity_I16); 10017 10018 /* Add lower halfs of rs and rt, add 1 10019 and right shift the result by 1. */ 10020 assign(t0, binop(Iop_Add32, 10021 unop(Iop_16Sto32, 10022 unop(Iop_32to16, getIReg(rs))), 10023 unop(Iop_16Sto32, 10024 unop(Iop_32to16, getIReg(rt))))); 10025 assign(t1, unop(Iop_32to16, 10026 binop(Iop_Shr32, 10027 binop(Iop_And32, 10028 binop(Iop_Add32, 10029 mkexpr(t0), 10030 mkU32(0x1)), 10031 mkU32(0x0001fffe)), 10032 mkU8(0x1)))); 10033 /* Add higher halfs of rs and rt, add 1 10034 and right shift the result by 1. */ 10035 assign(t2, binop(Iop_Add32, 10036 unop(Iop_16Sto32, 10037 unop(Iop_32HIto16, getIReg(rs))), 10038 unop(Iop_16Sto32, 10039 unop(Iop_32HIto16, getIReg(rt))))); 10040 assign(t3, unop(Iop_32to16, 10041 binop(Iop_Shr32, 10042 binop(Iop_And32, 10043 binop(Iop_Add32, 10044 mkexpr(t2), 10045 mkU32(0x1)), 10046 mkU32(0x0001fffe)), 10047 mkU8(0x1)))); 10048 10049 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 10050 break; 10051 } 10052 case 0xB: { /* SUBQH_R.PH */ 10053 DIP("subqh_r.ph r%u, r%u, r%u", rd, rs, rt); 10054 vassert(!mode64); 10055 t0 = newTemp(Ity_I32); 10056 t1 = newTemp(Ity_I16); 10057 t2 = newTemp(Ity_I32); 10058 t3 = newTemp(Ity_I16); 10059 10060 /* Sub lower halfs of rs and rt, add 1 10061 and right shift the result by 1. */ 10062 assign(t0, binop(Iop_Sub32, 10063 unop(Iop_16Sto32, 10064 unop(Iop_32to16, getIReg(rs))), 10065 unop(Iop_16Sto32, 10066 unop(Iop_32to16, getIReg(rt))))); 10067 assign(t1, unop(Iop_32to16, 10068 binop(Iop_Shr32, 10069 binop(Iop_And32, 10070 binop(Iop_Add32, 10071 mkexpr(t0), 10072 mkU32(0x1)), 10073 mkU32(0x0001fffe)), 10074 mkU8(0x1)))); 10075 /* Sub higher halfs of rs and rt, add 1 10076 and right shift the result by 1. */ 10077 assign(t2, binop(Iop_Sub32, 10078 unop(Iop_16Sto32, 10079 unop(Iop_32HIto16, getIReg(rs))), 10080 unop(Iop_16Sto32, 10081 unop(Iop_32HIto16, getIReg(rt))))); 10082 assign(t3, unop(Iop_32to16, 10083 binop(Iop_Shr32, 10084 binop(Iop_And32, 10085 binop(Iop_Add32, 10086 mkexpr(t2), 10087 mkU32(0x1)), 10088 mkU32(0x0001fffe)), 10089 mkU8(0x1)))); 10090 10091 putIReg(rd, binop(Iop_16HLto32, mkexpr(t3), mkexpr(t1))); 10092 break; 10093 } 10094 case 0xC: { /* MUL.PH */ 10095 DIP("mul.ph r%u, r%u, r%u", rd, rs, rt); 10096 vassert(!mode64); 10097 t0 = newTemp(Ity_I32); 10098 t1 = newTemp(Ity_I32); 10099 t2 = newTemp(Ity_I32); 10100 10101 assign(t0, 10102 binop(Iop_Mul32, 10103 unop(Iop_16Sto32, 10104 unop(Iop_32HIto16, getIReg(rs))), 10105 unop(Iop_16Sto32, 10106 unop(Iop_32HIto16, getIReg(rt))))); 10107 /* DSP Control flag. */ 10108 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10109 binop(Iop_CmpLE32S, 10110 mkexpr(t0), 10111 mkU32(0x7FFF))), 10112 binop(Iop_Or32, 10113 getDSPControl(), 10114 mkU32(0x00200000)), 10115 IRExpr_ITE(binop(Iop_CmpLT32S, 10116 mkexpr(t0), 10117 mkU32(0xFFFF8000) 10118 ), 10119 binop(Iop_Or32, 10120 getDSPControl(), 10121 mkU32(0x00200000) 10122 ), 10123 getDSPControl()))); 10124 10125 assign(t1, 10126 binop(Iop_Mul32, 10127 unop(Iop_16Sto32, 10128 unop(Iop_32to16, getIReg(rs))), 10129 unop(Iop_16Sto32, 10130 unop(Iop_32to16, getIReg(rt))))); 10131 /* DSP Control flag. */ 10132 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10133 binop(Iop_CmpLE32S, 10134 mkexpr(t1), 10135 mkU32(0x7FFF))), 10136 binop(Iop_Or32, 10137 getDSPControl(), 10138 mkU32(0x00200000)), 10139 IRExpr_ITE(binop(Iop_CmpLT32S, 10140 mkexpr(t1), 10141 mkU32(0xFFFF8000) 10142 ), 10143 binop(Iop_Or32, 10144 getDSPControl(), 10145 mkU32(0x00200000) 10146 ), 10147 getDSPControl()))); 10148 10149 assign(t2, binop(Iop_16HLto32, 10150 unop(Iop_32to16, mkexpr(t0)), 10151 unop(Iop_32to16, mkexpr(t1)))); 10152 putIReg(rd, mkexpr(t2)); 10153 break; 10154 } 10155 case 0xE: { /* MUL_S.PH */ 10156 DIP("mul_s.ph r%u r%u, r%u", rd, rs, rt); 10157 vassert(!mode64); 10158 10159 t0 = newTemp(Ity_I32); 10160 t1 = newTemp(Ity_I32); 10161 t2 = newTemp(Ity_I32); 10162 t3 = newTemp(Ity_I32); 10163 t4 = newTemp(Ity_I32); 10164 10165 /* t0 - signed intermediate result. */ 10166 assign(t0, 10167 binop(Iop_Mul32, 10168 unop(Iop_16Sto32, 10169 unop(Iop_32HIto16, getIReg(rs))), 10170 unop(Iop_16Sto32, 10171 unop(Iop_32HIto16, getIReg(rt))))); 10172 10173 assign(t1, 10174 IRExpr_ITE(unop(Iop_Not1, 10175 binop(Iop_CmpLE32S, 10176 mkexpr(t0), 10177 mkU32(0x7FFF))), 10178 mkU32(0x00007FFF), 10179 IRExpr_ITE(binop(Iop_CmpLT32S, 10180 mkexpr(t0), 10181 mkU32(0xFFFF8000)), 10182 mkU32(0xFFFF8000), 10183 mkexpr(t0)))); 10184 10185 /* DSP Control flag. */ 10186 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10187 binop(Iop_CmpLE32S, 10188 mkexpr(t0), 10189 mkU32(0x7FFF))), 10190 binop(Iop_Or32, 10191 getDSPControl(), 10192 mkU32(0x00200000)), 10193 IRExpr_ITE(binop(Iop_CmpLT32S, 10194 mkexpr(t0), 10195 mkU32(0xFFFF8000) 10196 ), 10197 binop(Iop_Or32, 10198 getDSPControl(), 10199 mkU32(0x00200000) 10200 ), 10201 getDSPControl()))); 10202 10203 /* t2 - signed intermediate result. */ 10204 assign(t2, binop(Iop_Mul32, 10205 unop(Iop_16Sto32, 10206 unop(Iop_32to16, getIReg(rs))), 10207 unop(Iop_16Sto32, 10208 unop(Iop_32to16, getIReg(rt))))); 10209 10210 assign(t3, IRExpr_ITE(unop(Iop_Not1, 10211 binop(Iop_CmpLE32S, 10212 mkexpr(t2), 10213 mkU32(0x7FFF))), 10214 mkU32(0x00007FFF), 10215 IRExpr_ITE(binop(Iop_CmpLT32S, 10216 mkexpr(t2), 10217 mkU32(0xFFFF8000)), 10218 mkU32(0xFFFF8000), 10219 mkexpr(t2)))); 10220 10221 /* DSP Control flag. */ 10222 putDSPControl(IRExpr_ITE(unop(Iop_Not1, 10223 binop(Iop_CmpLE32S, 10224 mkexpr(t2), 10225 mkU32(0x7FFF))), 10226 binop(Iop_Or32, 10227 getDSPControl(), 10228 mkU32(0x00200000)), 10229 IRExpr_ITE(binop(Iop_CmpLT32S, 10230 mkexpr(t2), 10231 mkU32(0xFFFF8000) 10232 ), 10233 binop(Iop_Or32, 10234 getDSPControl(), 10235 mkU32(0x00200000) 10236 ), 10237 getDSPControl()))); 10238 10239 assign(t4, binop(Iop_16HLto32, 10240 unop(Iop_32to16, mkexpr(t1)), 10241 unop(Iop_32to16, mkexpr(t3)))); 10242 putIReg(rd, mkexpr(t4)); 10243 break; 10244 } 10245 case 0x10: { /* ADDQH.W */ 10246 DIP("addqh.w r%u, r%u, r%u", rd, rs, rt); 10247 vassert(!mode64); 10248 t0 = newTemp(Ity_I64); 10249 t1 = newTemp(Ity_I64); 10250 10251 assign(t0, binop(Iop_Add64, 10252 unop(Iop_32Sto64, getIReg(rs)), 10253 unop(Iop_32Sto64, getIReg(rt)))); 10254 assign(t1, binop(Iop_And64, 10255 mkexpr(t0), 10256 mkU64(0x00000001fffffffeULL))); 10257 putIReg(rd, unop(Iop_64to32, 10258 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1)))); 10259 break; 10260 } 10261 case 0x11: { /* SUBQH.W */ 10262 DIP("subqh.w r%u, r%u, r%u", rd, rs, rt); 10263 vassert(!mode64); 10264 t0 = newTemp(Ity_I64); 10265 t1 = newTemp(Ity_I64); 10266 10267 assign(t0, binop(Iop_Sub64, 10268 unop(Iop_32Sto64, getIReg(rs)), 10269 unop(Iop_32Sto64, getIReg(rt)))); 10270 assign(t1, binop(Iop_And64, 10271 mkexpr(t0), 10272 mkU64(0x00000001fffffffeULL))); 10273 putIReg(rd, unop(Iop_64to32, 10274 binop(Iop_Shr64, mkexpr(t1), mkU8(0x1)))); 10275 break; 10276 } 10277 case 0x12: { /* ADDQH_R.W */ 10278 DIP("addqh_r.w r%u, r%u, r%u", rd, rs, rt); 10279 vassert(!mode64); 10280 t0 = newTemp(Ity_I64); 10281 t1 = newTemp(Ity_I64); 10282 t2 = newTemp(Ity_I64); 10283 10284 assign(t0, binop(Iop_Add64, 10285 unop(Iop_32Sto64, getIReg(rs)), 10286 unop(Iop_32Sto64, getIReg(rt)))); 10287 assign(t1, binop(Iop_Add64, 10288 mkexpr(t0), 10289 mkU64(0x0000000000000001ULL))); 10290 assign(t2, binop(Iop_And64, 10291 mkexpr(t1), 10292 mkU64(0x00000001fffffffeULL))); 10293 putIReg(rd, unop(Iop_64to32, 10294 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1)))); 10295 break; 10296 } 10297 case 0x13: { /* SUBQH_R.W */ 10298 DIP("subqh_r.w r%u, r%u, r%u", rd, rs, rt); 10299 vassert(!mode64); 10300 t0 = newTemp(Ity_I64); 10301 t1 = newTemp(Ity_I64); 10302 t2 = newTemp(Ity_I64); 10303 10304 assign(t0, binop(Iop_Sub64, 10305 unop(Iop_32Sto64, getIReg(rs)), 10306 unop(Iop_32Sto64, getIReg(rt)))); 10307 assign(t1, binop(Iop_Add64, 10308 mkexpr(t0), 10309 mkU64(0x0000000000000001ULL))); 10310 assign(t2, binop(Iop_And64, 10311 mkexpr(t1), 10312 mkU64(0x00000001fffffffeULL))); 10313 putIReg(rd, unop(Iop_64to32, 10314 binop(Iop_Shr64, mkexpr(t2), mkU8(0x1)))); 10315 break; 10316 } 10317 case 0x16: { /* MULQ_S.W */ 10318 DIP("mulq_s.w r%u, r%u, r%u", rd, rs, rt); 10319 vassert(!mode64); 10320 t0 = newTemp(Ity_I64); 10321 t1 = newTemp(Ity_I1); 10322 t2 = newTemp(Ity_I1); 10323 10324 assign(t0, binop(Iop_Shl64, 10325 binop(Iop_MullS32, 10326 getIReg(rt), getIReg(rs)), 10327 mkU8(0x1))); 10328 assign(t1, binop(Iop_CmpEQ32, 10329 getIReg(rt), mkU32(0x80000000))); 10330 assign(t2, binop(Iop_CmpEQ32, 10331 getIReg(rs), mkU32(0x80000000))); 10332 10333 putDSPControl(IRExpr_ITE(mkexpr(t1), 10334 IRExpr_ITE(mkexpr(t2), 10335 binop(Iop_Or32, 10336 getDSPControl(), 10337 mkU32(0x00200000) 10338 ), 10339 getDSPControl()), 10340 getDSPControl())); 10341 putIReg(rd, IRExpr_ITE(mkexpr(t1), 10342 IRExpr_ITE(mkexpr(t2), 10343 mkU32(0x7fffffff), 10344 unop(Iop_64HIto32, 10345 mkexpr(t0))), 10346 unop(Iop_64HIto32, mkexpr(t0)))); 10347 break; 10348 } 10349 case 0x17: { /* MULQ_RS.W */ 10350 DIP("mulq_rs.w r%u, r%u, r%u", rd, rs, rt); 10351 vassert(!mode64); 10352 t0 = newTemp(Ity_I64); 10353 t1 = newTemp(Ity_I1); 10354 t2 = newTemp(Ity_I1); 10355 10356 assign(t0, binop(Iop_Add64, 10357 binop(Iop_Shl64, 10358 binop(Iop_MullS32, 10359 getIReg(rt), 10360 getIReg(rs)), 10361 mkU8(0x1)), 10362 mkU64(0x0000000080000000ULL))); 10363 assign(t1, 10364 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 10365 assign(t2, 10366 binop(Iop_CmpEQ32, getIReg(rs), mkU32(0x80000000))); 10367 putDSPControl(IRExpr_ITE(mkexpr(t1), 10368 IRExpr_ITE(mkexpr(t2), 10369 binop(Iop_Or32, 10370 getDSPControl(), 10371 mkU32(0x00200000) 10372 ), 10373 getDSPControl()), 10374 getDSPControl())); 10375 putIReg(rd, IRExpr_ITE(mkexpr(t1), 10376 IRExpr_ITE(mkexpr(t2), 10377 mkU32(0x7fffffff), 10378 unop(Iop_64HIto32, 10379 mkexpr(t0))), 10380 unop(Iop_64HIto32, mkexpr(t0)))); 10381 break; 10382 } 10383 default: 10384 return -1; 10385 } 10386 break; /* end of ADDUH.QB/MUL.PH */ 10387 } 10388 case 0x30: { /* DPAQ.W.PH */ 10389 switch(sa) { 10390 case 0x0: { /* DPA.W.PH */ 10391 DIP("dpa.w.ph ac%u, r%u, r%u", ac, rs, rt); 10392 vassert(!mode64); 10393 10394 t0 = newTemp(Ity_I64); 10395 t1 = newTemp(Ity_I64); 10396 t2 = newTemp(Ity_I64); 10397 10398 assign(t0, 10399 unop(Iop_32Sto64, 10400 binop(Iop_Mul32, 10401 unop(Iop_16Sto32, 10402 unop(Iop_32HIto16, getIReg(rs))), 10403 unop(Iop_16Sto32, 10404 unop(Iop_32HIto16, getIReg(rt)))))); 10405 assign(t1, 10406 unop(Iop_32Sto64, 10407 binop(Iop_Mul32, 10408 unop(Iop_16Sto32, 10409 unop(Iop_32to16, getIReg(rs))), 10410 unop(Iop_16Sto32, 10411 unop(Iop_32to16, getIReg(rt)))))); 10412 assign(t2, 10413 binop(Iop_Add64, 10414 getAcc(ac), 10415 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10416 putAcc(ac, mkexpr(t2)); 10417 break; 10418 } 10419 case 0x1: { /* DPS.W.PH */ 10420 DIP("dps.w.ph ac%u, r%u, r%u", ac, rs, rt); 10421 vassert(!mode64); 10422 10423 t0 = newTemp(Ity_I64); 10424 t1 = newTemp(Ity_I64); 10425 t2 = newTemp(Ity_I64); 10426 10427 assign(t0, 10428 unop(Iop_32Sto64, 10429 binop(Iop_Mul32, 10430 unop(Iop_16Sto32, 10431 unop(Iop_32HIto16, getIReg(rs))), 10432 unop(Iop_16Sto32, 10433 unop(Iop_32HIto16, getIReg(rt)))))); 10434 assign(t1, 10435 unop(Iop_32Sto64, 10436 binop(Iop_Mul32, 10437 unop(Iop_16Sto32, 10438 unop(Iop_32to16, getIReg(rs))), 10439 unop(Iop_16Sto32, 10440 unop(Iop_32to16, getIReg(rt)))))); 10441 assign(t2, 10442 binop(Iop_Sub64, 10443 getAcc(ac), 10444 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10445 putAcc(ac, mkexpr(t2)); 10446 break; 10447 } 10448 case 0x2: { /* MULSA.W.PH */ 10449 DIP("mulsa.w.ph ac%u, r%u, r%u", ac, rs, rt); 10450 vassert(!mode64); 10451 t0 = newTemp(Ity_I32); 10452 t1 = newTemp(Ity_I32); 10453 t2 = newTemp(Ity_I32); 10454 t3 = newTemp(Ity_I1); 10455 t4 = newTemp(Ity_I64); 10456 10457 assign(t4, getAcc(ac)); 10458 assign(t0, binop(Iop_Mul32, 10459 unop(Iop_16Sto32, 10460 unop(Iop_32to16, getIReg(rt))), 10461 unop(Iop_16Sto32, 10462 unop(Iop_32to16, getIReg(rs))))); 10463 assign(t1, binop(Iop_Mul32, 10464 unop(Iop_16Sto32, 10465 unop(Iop_32HIto16, getIReg(rt))), 10466 unop(Iop_16Sto32, 10467 unop(Iop_32HIto16, getIReg(rs))))); 10468 assign(t2, binop(Iop_Sub32, mkexpr(t1), mkexpr(t0))); 10469 putAcc(ac, binop(Iop_Add64, 10470 mkexpr(t4), 10471 unop(Iop_32Sto64, mkexpr(t2)))); 10472 break; 10473 } 10474 case 0x3: { /* DPAU.H.QBL */ 10475 DIP("dpau.h.qbl ac%u, r%u, r%u", ac, rs, rt); 10476 vassert(!mode64); 10477 t0 = newTemp(Ity_I32); 10478 t1 = newTemp(Ity_I32); 10479 t2 = newTemp(Ity_I64); 10480 t3 = newTemp(Ity_I64); 10481 10482 assign(t0, 10483 binop(Iop_Mul32, 10484 unop(Iop_8Uto32, 10485 unop(Iop_16HIto8, 10486 unop(Iop_32HIto16, getIReg(rs)))), 10487 unop(Iop_8Uto32, 10488 unop(Iop_16HIto8, 10489 unop(Iop_32HIto16, getIReg(rt)))))); 10490 assign(t1, 10491 binop(Iop_Mul32, 10492 unop(Iop_8Uto32, 10493 unop(Iop_16to8, 10494 unop(Iop_32HIto16, getIReg(rs)))), 10495 unop(Iop_8Uto32, 10496 unop(Iop_16to8, 10497 unop(Iop_32HIto16, getIReg(rt)))))); 10498 assign(t2, 10499 unop(Iop_32Uto64, 10500 binop(Iop_Add32, 10501 mkexpr(t0), 10502 mkexpr(t1)))); 10503 assign(t3, 10504 binop(Iop_Add64, getAcc(ac), mkexpr(t2))); 10505 putAcc(ac, mkexpr(t3)); 10506 break; 10507 } 10508 case 0x4: { /* DPAQ_S.W.PH */ 10509 DIP("dpaq_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 10510 vassert(!mode64); 10511 t0 = newTemp(Ity_I64); 10512 t1 = newTemp(Ity_I64); 10513 t2 = newTemp(Ity_I1); 10514 t3 = newTemp(Ity_I1); 10515 t4 = newTemp(Ity_I64); 10516 t5 = newTemp(Ity_I64); 10517 t6 = newTemp(Ity_I1); 10518 t7 = newTemp(Ity_I1); 10519 t8 = newTemp(Ity_I64); 10520 t9 = newTemp(Ity_I64); 10521 10522 assign(t0, getAcc(ac)); 10523 10524 assign(t1, binop(Iop_Shl64, 10525 binop(Iop_MullS32, 10526 unop(Iop_16Sto32, 10527 unop(Iop_32HIto16, 10528 getIReg(rs))), 10529 unop(Iop_16Sto32, 10530 unop(Iop_32HIto16, 10531 getIReg(rt)))), 10532 mkU8(0x1))); 10533 assign(t2, binop(Iop_CmpEQ32, 10534 unop(Iop_16Uto32, 10535 unop(Iop_32HIto16, getIReg(rs))), 10536 mkU32(0x00008000))); 10537 assign(t3, binop(Iop_CmpEQ32, 10538 unop(Iop_16Uto32, 10539 unop(Iop_32HIto16, getIReg(rt))), 10540 mkU32(0x00008000))); 10541 assign(t4, 10542 IRExpr_ITE(mkexpr(t2), 10543 IRExpr_ITE(mkexpr(t3), 10544 mkU64(0x000000007fffffffULL), 10545 mkexpr(t1)), 10546 mkexpr(t1))); 10547 10548 putDSPControl(IRExpr_ITE(mkexpr(t2), 10549 IRExpr_ITE(mkexpr(t3), 10550 binop(Iop_Or32, 10551 getDSPControl(), 10552 binop(Iop_Shl32, 10553 mkU32(0x1), 10554 mkU8(ac+16) 10555 ) 10556 ), 10557 getDSPControl()), 10558 getDSPControl())); 10559 10560 assign(t5, binop(Iop_Shl64, 10561 binop(Iop_MullS32, 10562 unop(Iop_16Sto32, 10563 unop(Iop_32to16, getIReg(rs))), 10564 unop(Iop_16Sto32, 10565 unop(Iop_32to16, getIReg(rt))) 10566 ), 10567 mkU8(0x1))); 10568 assign(t6, binop(Iop_CmpEQ32, 10569 unop(Iop_16Uto32, 10570 unop(Iop_32to16, getIReg(rs))), 10571 mkU32(0x00008000))); 10572 assign(t7, binop(Iop_CmpEQ32, 10573 unop(Iop_16Uto32, 10574 unop(Iop_32to16, getIReg(rt))), 10575 mkU32(0x00008000))); 10576 assign(t8, 10577 IRExpr_ITE(mkexpr(t6), 10578 IRExpr_ITE(mkexpr(t7), 10579 mkU64(0x000000007fffffffULL), 10580 mkexpr(t5)), 10581 mkexpr(t5))); 10582 10583 putDSPControl(IRExpr_ITE(mkexpr(t6), 10584 IRExpr_ITE(mkexpr(t7), 10585 binop(Iop_Or32, 10586 getDSPControl(), 10587 binop(Iop_Shl32, 10588 mkU32(0x1), 10589 mkU8(ac+16) 10590 ) 10591 ), 10592 getDSPControl()), 10593 getDSPControl())); 10594 10595 assign(t9, binop(Iop_Add64, 10596 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)), 10597 mkexpr(t0))); 10598 putAcc(ac, mkexpr(t9)); 10599 break; 10600 } 10601 case 0x5: { /* DPSQ_S.W.PH */ 10602 DIP("dpsq_s.w.ph ac%u r%u, r%u", ac, rs, rt); 10603 vassert(!mode64); 10604 t0 = newTemp(Ity_I64); 10605 t1 = newTemp(Ity_I64); 10606 t2 = newTemp(Ity_I1); 10607 t3 = newTemp(Ity_I1); 10608 t4 = newTemp(Ity_I64); 10609 t5 = newTemp(Ity_I64); 10610 t6 = newTemp(Ity_I1); 10611 t7 = newTemp(Ity_I1); 10612 t8 = newTemp(Ity_I64); 10613 t9 = newTemp(Ity_I64); 10614 10615 assign(t0, getAcc(ac)); 10616 10617 assign(t1, binop(Iop_Shl64, 10618 binop(Iop_MullS32, 10619 unop(Iop_16Sto32, 10620 unop(Iop_32HIto16, 10621 getIReg(rs))), 10622 unop(Iop_16Sto32, 10623 unop(Iop_32HIto16, 10624 getIReg(rt)))), 10625 mkU8(0x1))); 10626 assign(t2, binop(Iop_CmpEQ32, 10627 unop(Iop_16Uto32, 10628 unop(Iop_32HIto16, getIReg(rs))), 10629 mkU32(0x00008000))); 10630 assign(t3, binop(Iop_CmpEQ32, 10631 unop(Iop_16Uto32, 10632 unop(Iop_32HIto16, getIReg(rt))), 10633 mkU32(0x00008000))); 10634 assign(t4, 10635 IRExpr_ITE(mkexpr(t2), 10636 IRExpr_ITE(mkexpr(t3), 10637 mkU64(0x000000007fffffffULL), 10638 mkexpr(t1)), 10639 mkexpr(t1))); 10640 10641 putDSPControl(IRExpr_ITE(mkexpr(t2), 10642 IRExpr_ITE(mkexpr(t3), 10643 binop(Iop_Or32, 10644 getDSPControl(), 10645 binop(Iop_Shl32, 10646 mkU32(0x1), 10647 mkU8(ac+16) 10648 ) 10649 ), 10650 getDSPControl()), 10651 getDSPControl())); 10652 10653 assign(t5, 10654 binop(Iop_Shl64, 10655 binop(Iop_MullS32, 10656 unop(Iop_16Sto32, 10657 unop(Iop_32to16, getIReg(rs))), 10658 unop(Iop_16Sto32, 10659 unop(Iop_32to16, getIReg(rt)))), 10660 mkU8(0x1))); 10661 assign(t6, binop(Iop_CmpEQ32, 10662 unop(Iop_16Uto32, 10663 unop(Iop_32to16, getIReg(rs))), 10664 mkU32(0x00008000))); 10665 assign(t7, binop(Iop_CmpEQ32, 10666 unop(Iop_16Uto32, 10667 unop(Iop_32to16, getIReg(rt))), 10668 mkU32(0x00008000))); 10669 assign(t8, 10670 IRExpr_ITE(mkexpr(t6), 10671 IRExpr_ITE(mkexpr(t7), 10672 mkU64(0x000000007fffffffULL), 10673 mkexpr(t5)), 10674 mkexpr(t5))); 10675 10676 putDSPControl(IRExpr_ITE(mkexpr(t6), 10677 IRExpr_ITE(mkexpr(t7), 10678 binop(Iop_Or32, 10679 getDSPControl(), 10680 binop(Iop_Shl32, 10681 mkU32(0x1), 10682 mkU8(ac+16) 10683 ) 10684 ), 10685 getDSPControl()), 10686 getDSPControl())); 10687 10688 assign(t9, 10689 binop(Iop_Sub64, 10690 mkexpr(t0), 10691 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)))); 10692 putAcc(ac, mkexpr(t9)); 10693 break; 10694 } 10695 case 0x6: { /* MULSAQ_S.W.PH */ 10696 DIP("mulsaq_s.w.ph ac%u r%u, r%u", ac, rs, rt); 10697 vassert(!mode64); 10698 10699 t0 = newTemp(Ity_I32); 10700 t1 = newTemp(Ity_I32); 10701 t2 = newTemp(Ity_I32); 10702 t3 = newTemp(Ity_I32); 10703 t4 = newTemp(Ity_I32); 10704 t5 = newTemp(Ity_I32); 10705 t6 = newTemp(Ity_I64); 10706 t7 = newTemp(Ity_I64); 10707 t8 = newTemp(Ity_I32); 10708 t9 = newTemp(Ity_I32); 10709 10710 assign(t0, unop(Iop_16Sto32, 10711 unop(Iop_32HIto16, getIReg(rs)))); 10712 assign(t1, unop(Iop_16Sto32, 10713 unop(Iop_32HIto16, getIReg(rt)))); 10714 10715 assign(t8, binop(Iop_And32, 10716 unop(Iop_1Sto32, 10717 binop(Iop_CmpEQ32, 10718 unop(Iop_16Uto32, 10719 unop(Iop_32HIto16, 10720 getIReg(rs))), 10721 mkU32(0x8000))), 10722 unop(Iop_1Sto32, 10723 binop(Iop_CmpEQ32, 10724 unop(Iop_16Uto32, 10725 unop(Iop_32HIto16, 10726 getIReg(rt))), 10727 mkU32(0x8000))))); 10728 /* DSPControl_outflag:16+acc <- 1 */ 10729 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 10730 mkexpr(t8), 10731 mkU32(0x0)), 10732 binop(Iop_Or32, 10733 getDSPControl(), 10734 binop(Iop_Shl32, 10735 mkU32(0x00010000), 10736 mkU8(ac))), 10737 getDSPControl())); 10738 10739 /* tempB_31..0 */ 10740 assign(t2, 10741 IRExpr_ITE(binop(Iop_CmpNE32, 10742 mkexpr(t8), mkU32(0x0)), 10743 mkU32(0x7FFFFFFF), 10744 binop(Iop_Shl32, 10745 binop(Iop_Mul32, 10746 mkexpr(t0), mkexpr(t1)), 10747 mkU8(1)))); 10748 10749 assign(t3, unop(Iop_16Sto32, 10750 unop(Iop_32to16, getIReg(rs)))); 10751 assign(t4, unop(Iop_16Sto32, 10752 unop(Iop_32to16, getIReg(rt)))); 10753 10754 assign(t9, binop(Iop_And32, 10755 unop(Iop_1Sto32, 10756 binop(Iop_CmpEQ32, 10757 unop(Iop_16Uto32, 10758 unop(Iop_32to16, 10759 getIReg(rs))), 10760 mkU32(0x8000))), 10761 unop(Iop_1Sto32, 10762 binop(Iop_CmpEQ32, 10763 unop(Iop_16Uto32, 10764 unop(Iop_32to16, 10765 getIReg(rt))), 10766 mkU32(0x8000))))); 10767 /* DSPControl_outflag:16+acc <- 1 */ 10768 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 10769 mkexpr(t9), 10770 mkU32(0x0)), 10771 binop(Iop_Or32, 10772 getDSPControl(), 10773 binop(Iop_Shl32, 10774 mkU32(0x00010000), 10775 mkU8(ac))), 10776 getDSPControl())); 10777 /* tempA_31..0 */ 10778 assign(t5, 10779 IRExpr_ITE(binop(Iop_CmpNE32, 10780 mkexpr(t9), 10781 mkU32(0x0)), 10782 mkU32(0x7FFFFFFF), 10783 binop(Iop_Shl32, 10784 binop(Iop_Mul32, 10785 mkexpr(t3), 10786 mkexpr(t4)), 10787 mkU8(1)))); 10788 /* dotp_63..0 */ 10789 assign(t6, 10790 binop(Iop_Sub64, 10791 unop(Iop_32Sto64, mkexpr(t2)), 10792 unop(Iop_32Sto64, mkexpr(t5)))); 10793 /* tempC_63..0 */ 10794 assign(t7, binop(Iop_Add64, getAcc(ac), mkexpr(t6))); 10795 10796 putAcc(ac, mkexpr(t7)); 10797 break; 10798 } 10799 case 0x7: { /* DPAU.H.QBR */ 10800 DIP("dpau.h.qbr ac%u, r%u, r%u", ac, rs, rt); 10801 vassert(!mode64); 10802 t0 = newTemp(Ity_I32); 10803 t1 = newTemp(Ity_I32); 10804 t2 = newTemp(Ity_I64); 10805 t3 = newTemp(Ity_I64); 10806 10807 assign(t0, 10808 binop(Iop_Mul32, 10809 unop(Iop_8Uto32, 10810 unop(Iop_16HIto8, 10811 unop(Iop_32to16, getIReg(rs)))), 10812 unop(Iop_8Uto32, 10813 unop(Iop_16HIto8, 10814 unop(Iop_32to16, getIReg(rt)))))); 10815 assign(t1, 10816 binop(Iop_Mul32, 10817 unop(Iop_8Uto32, 10818 unop(Iop_16to8, 10819 unop(Iop_32to16, getIReg(rs)))), 10820 unop(Iop_8Uto32, 10821 unop(Iop_16to8, 10822 unop(Iop_32to16, getIReg(rt)))))); 10823 assign(t2, unop(Iop_32Uto64, 10824 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 10825 assign(t3, binop(Iop_Add64, getAcc(ac), mkexpr(t2))); 10826 putAcc(ac, mkexpr(t3)); 10827 break; 10828 } 10829 case 0x8: { /* DPAX.W.PH */ 10830 DIP("dpax.w.ph ac%u, r%u, r%u", ac, rs, rt); 10831 vassert(!mode64); 10832 t0 = newTemp(Ity_I64); 10833 t1 = newTemp(Ity_I64); 10834 t2 = newTemp(Ity_I64); 10835 10836 assign(t0, 10837 unop(Iop_32Sto64, 10838 binop(Iop_Mul32, 10839 unop(Iop_16Sto32, 10840 unop(Iop_32HIto16, getIReg(rs))), 10841 unop(Iop_16Sto32, 10842 unop(Iop_32to16, getIReg(rt)))))); 10843 assign(t1, 10844 unop(Iop_32Sto64, 10845 binop(Iop_Mul32, 10846 unop(Iop_16Sto32, 10847 unop(Iop_32to16, getIReg(rs))), 10848 unop(Iop_16Sto32, 10849 unop(Iop_32HIto16, getIReg(rt)))))); 10850 assign(t2, 10851 binop(Iop_Add64, 10852 getAcc(ac), 10853 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10854 putAcc(ac, mkexpr(t2)); 10855 break; 10856 } 10857 case 0x9: { /* DPSX.W.PH */ 10858 DIP("dpsx.w.ph ac%u r%u, r%u", ac, rs, rt); 10859 vassert(!mode64); 10860 10861 t0 = newTemp(Ity_I64); 10862 t1 = newTemp(Ity_I64); 10863 t2 = newTemp(Ity_I64); 10864 10865 assign(t0, 10866 unop(Iop_32Sto64, 10867 binop(Iop_Mul32, 10868 unop(Iop_16Sto32, 10869 unop(Iop_32HIto16, getIReg(rs))), 10870 unop(Iop_16Sto32, 10871 unop(Iop_32to16, getIReg(rt)))))); 10872 assign(t1, 10873 unop(Iop_32Sto64, 10874 binop(Iop_Mul32, 10875 unop(Iop_16Sto32, 10876 unop(Iop_32to16, getIReg(rs))), 10877 unop(Iop_16Sto32, 10878 unop(Iop_32HIto16, getIReg(rt)))))); 10879 assign(t2, 10880 binop(Iop_Sub64, 10881 getAcc(ac), 10882 binop(Iop_Add64, mkexpr(t0), mkexpr(t1)))); 10883 putAcc(ac, mkexpr(t2)); 10884 break; 10885 } 10886 case 0xB: { /* DPSU.H.QBL */ 10887 DIP("dpsu.h.qbl ac%u, r%u, r%u", ac, rs, rt); 10888 vassert(!mode64); 10889 10890 t0 = newTemp(Ity_I32); 10891 t1 = newTemp(Ity_I32); 10892 t2 = newTemp(Ity_I64); 10893 t3 = newTemp(Ity_I64); 10894 10895 assign(t0, 10896 binop(Iop_Mul32, 10897 unop(Iop_8Uto32, 10898 unop(Iop_16HIto8, 10899 unop(Iop_32HIto16, getIReg(rs)))), 10900 unop(Iop_8Uto32, 10901 unop(Iop_16HIto8, 10902 unop(Iop_32HIto16, getIReg(rt)))))); 10903 assign(t1, 10904 binop(Iop_Mul32, 10905 unop(Iop_8Uto32, 10906 unop(Iop_16to8, 10907 unop(Iop_32HIto16, getIReg(rs)))), 10908 unop(Iop_8Uto32, 10909 unop(Iop_16to8, 10910 unop(Iop_32HIto16, getIReg(rt)))))); 10911 assign(t2, 10912 unop(Iop_32Uto64, 10913 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 10914 assign(t3, 10915 binop(Iop_Sub64, getAcc(ac), mkexpr(t2))); 10916 putAcc(ac, mkexpr(t3)); 10917 break; 10918 } 10919 case 0xC: { /* DPAQ_SA.L.W */ 10920 DIP("dpaq_sa.l.w ac%u, r%u, r%u", ac, rs, rt); 10921 vassert(!mode64); 10922 t0 = newTemp(Ity_I64); 10923 t1 = newTemp(Ity_I64); 10924 t2 = newTemp(Ity_I1); 10925 t3 = newTemp(Ity_I1); 10926 t4 = newTemp(Ity_I64); 10927 t5 = newTemp(Ity_I64); 10928 t6 = newTemp(Ity_I64); 10929 t7 = newTemp(Ity_I64); 10930 t8 = newTemp(Ity_I1); 10931 t9 = newTemp(Ity_I1); 10932 10933 assign(t0, getAcc(ac)); 10934 10935 assign(t1, binop(Iop_Shl64, 10936 binop(Iop_MullS32, 10937 getIReg(rs), getIReg(rt)), 10938 mkU8(0x1))); 10939 10940 assign(t2, binop(Iop_CmpEQ32, 10941 getIReg(rs), 10942 mkU32(0x80000000))); 10943 assign(t3, binop(Iop_CmpEQ32, 10944 getIReg(rt), 10945 mkU32(0x80000000))); 10946 10947 assign(t4, 10948 IRExpr_ITE(mkexpr(t2), 10949 IRExpr_ITE(mkexpr(t3), 10950 mkU64(0x7fffffffffffffffULL), 10951 mkexpr(t1)), 10952 mkexpr(t1))); 10953 10954 putDSPControl(IRExpr_ITE(mkexpr(t2), 10955 IRExpr_ITE(mkexpr(t3), 10956 binop(Iop_Or32, 10957 getDSPControl(), 10958 binop(Iop_Shl32, 10959 mkU32(0x1), 10960 mkU8(ac+16) 10961 ) 10962 ), 10963 getDSPControl()), 10964 getDSPControl())); 10965 10966 assign(t5, binop(Iop_Add64, 10967 unop(Iop_32Uto64, 10968 unop(Iop_64to32, mkexpr(t0))), 10969 unop(Iop_32Uto64, 10970 unop(Iop_64to32, mkexpr(t4))))); 10971 assign(t6, 10972 binop(Iop_Add64, 10973 binop(Iop_Add64, 10974 unop(Iop_32Sto64, 10975 unop(Iop_64HIto32, mkexpr(t0))), 10976 unop(Iop_32Sto64, 10977 unop(Iop_64HIto32, mkexpr(t4)))), 10978 unop(Iop_32Uto64, 10979 binop(Iop_And32, 10980 unop(Iop_64HIto32, mkexpr(t5)), 10981 mkU32(0x1))))); 10982 assign(t7, binop(Iop_32HLto64, 10983 unop(Iop_64to32, mkexpr(t6)), 10984 unop(Iop_64to32, mkexpr(t5)))); 10985 assign(t8, binop(Iop_CmpEQ32, 10986 binop(Iop_Shr32, 10987 binop(Iop_And32, 10988 unop(Iop_64to32, mkexpr(t6)), 10989 mkU32(0x80000000)), 10990 mkU8(31)), 10991 binop(Iop_And32, 10992 unop(Iop_64HIto32, mkexpr(t6)), 10993 mkU32(0x00000001)))); 10994 assign(t9, binop(Iop_CmpEQ32, 10995 binop(Iop_And32, 10996 unop(Iop_64HIto32, 10997 mkexpr(t6)), 10998 mkU32(0x00000001)), 10999 mkU32(0x1))); 11000 putDSPControl(IRExpr_ITE(mkexpr(t8), 11001 getDSPControl(), 11002 binop(Iop_Or32, 11003 getDSPControl(), 11004 binop(Iop_Shl32, 11005 mkU32(0x1), 11006 mkU8(ac+16))))); 11007 putAcc(ac, 11008 IRExpr_ITE(mkexpr(t8), 11009 mkexpr(t7), 11010 IRExpr_ITE(mkexpr(t9), 11011 mkU64(0x8000000000000000ULL), 11012 mkU64(0x7fffffffffffffffULL))) 11013 ); 11014 break; 11015 } 11016 case 0xD: { /* DPSQ_SA.L.W */ 11017 DIP("dpsq_sa.l.w ac%u, r%u, r%u", ac, rs, rt); 11018 vassert(!mode64); 11019 t0 = newTemp(Ity_I64); 11020 t1 = newTemp(Ity_I64); 11021 t2 = newTemp(Ity_I1); 11022 t3 = newTemp(Ity_I1); 11023 t4 = newTemp(Ity_I64); 11024 t5 = newTemp(Ity_I64); 11025 t6 = newTemp(Ity_I64); 11026 t7 = newTemp(Ity_I64); 11027 t8 = newTemp(Ity_I1); 11028 t9 = newTemp(Ity_I1); 11029 11030 assign(t0, getAcc(ac)); 11031 11032 assign(t1, binop(Iop_Shl64, 11033 binop(Iop_MullS32, 11034 getIReg(rs), getIReg(rt)), 11035 mkU8(0x1))); 11036 11037 assign(t2, binop(Iop_CmpEQ32, 11038 getIReg(rs), 11039 mkU32(0x80000000))); 11040 assign(t3, binop(Iop_CmpEQ32, 11041 getIReg(rt), 11042 mkU32(0x80000000))); 11043 11044 assign(t4, 11045 IRExpr_ITE(mkexpr(t2), 11046 IRExpr_ITE(mkexpr(t3), 11047 mkU64(0x7fffffffffffffffULL), 11048 mkexpr(t1)), 11049 mkexpr(t1))); 11050 11051 putDSPControl(IRExpr_ITE(mkexpr(t2), 11052 IRExpr_ITE(mkexpr(t3), 11053 binop(Iop_Or32, 11054 getDSPControl(), 11055 binop(Iop_Shl32, 11056 mkU32(0x1), 11057 mkU8(ac+16) 11058 ) 11059 ), 11060 getDSPControl()), 11061 getDSPControl())); 11062 11063 assign(t5, binop(Iop_Sub64, 11064 unop(Iop_32Uto64, 11065 unop(Iop_64to32, mkexpr(t0))), 11066 unop(Iop_32Uto64, 11067 unop(Iop_64to32, mkexpr(t4))))); 11068 assign(t6, binop(Iop_Sub64, 11069 binop(Iop_Add64, 11070 unop(Iop_32Sto64, 11071 unop(Iop_64HIto32, mkexpr(t0)) 11072 ), 11073 unop(Iop_32Sto64, 11074 unop(Iop_1Sto32, 11075 binop(Iop_CmpLT32U, 11076 unop(Iop_64to32, 11077 mkexpr(t0)), 11078 unop(Iop_64to32, 11079 mkexpr(t4)))))), 11080 unop(Iop_32Sto64, 11081 unop(Iop_64HIto32, mkexpr(t4))))); 11082 assign(t7, binop(Iop_32HLto64, 11083 unop(Iop_64to32, mkexpr(t6)), 11084 unop(Iop_64to32, mkexpr(t5)))); 11085 assign(t8, binop(Iop_CmpEQ32, 11086 binop(Iop_Shr32, 11087 binop(Iop_And32, 11088 unop(Iop_64to32, mkexpr(t6)), 11089 mkU32(0x80000000)), 11090 mkU8(31)), 11091 binop(Iop_And32, 11092 unop(Iop_64HIto32, mkexpr(t6)), 11093 mkU32(0x00000001)))); 11094 assign(t9, binop(Iop_CmpEQ32, 11095 binop(Iop_And32, 11096 unop(Iop_64HIto32, mkexpr(t6)), 11097 mkU32(0x00000001)), 11098 mkU32(0x1))); 11099 putDSPControl(IRExpr_ITE(mkexpr(t8), 11100 getDSPControl(), 11101 binop(Iop_Or32, 11102 getDSPControl(), 11103 binop(Iop_Shl32, 11104 mkU32(0x1), 11105 mkU8(ac+16))))); 11106 putAcc(ac, 11107 IRExpr_ITE(mkexpr(t8), 11108 mkexpr(t7), 11109 IRExpr_ITE(mkexpr(t9), 11110 mkU64(0x8000000000000000ULL), 11111 mkU64(0x7fffffffffffffffULL))) 11112 ); 11113 break; 11114 } 11115 case 0xF: { /* DPSU.H.QBR */ 11116 DIP("dpsu.h.qbr ac%u r%u, r%u", ac, rs, rt); 11117 vassert(!mode64); 11118 11119 t0 = newTemp(Ity_I32); 11120 t1 = newTemp(Ity_I32); 11121 t2 = newTemp(Ity_I64); 11122 t3 = newTemp(Ity_I64); 11123 11124 assign(t0, 11125 binop(Iop_Mul32, 11126 unop(Iop_8Uto32, 11127 unop(Iop_16HIto8, 11128 unop(Iop_32to16, getIReg(rs)))), 11129 unop(Iop_8Uto32, 11130 unop(Iop_16HIto8, 11131 unop(Iop_32to16, getIReg(rt)))))); 11132 assign(t1, 11133 binop(Iop_Mul32, 11134 unop(Iop_8Uto32, 11135 unop(Iop_16to8, 11136 unop(Iop_32to16, getIReg(rs)))), 11137 unop(Iop_8Uto32, 11138 unop(Iop_16to8, 11139 unop(Iop_32to16, getIReg(rt)))))); 11140 assign(t2, unop(Iop_32Uto64, 11141 binop(Iop_Add32, mkexpr(t0), mkexpr(t1)))); 11142 assign(t3, binop(Iop_Sub64, getAcc(ac), mkexpr(t2))); 11143 putAcc(ac, mkexpr(t3)); 11144 11145 break; 11146 } 11147 case 0x10: { /* MAQ_SA.W.PHL */ 11148 DIP("maq_sa.w.phl ac%u, r%u, r%u", ac, rs, rt); 11149 vassert(!mode64); 11150 t0 = newTemp(Ity_I64); 11151 t1 = newTemp(Ity_I64); 11152 t2 = newTemp(Ity_I1); 11153 t3 = newTemp(Ity_I1); 11154 t4 = newTemp(Ity_I64); 11155 t5 = newTemp(Ity_I64); 11156 t6 = newTemp(Ity_I1); 11157 t7 = newTemp(Ity_I64); 11158 11159 assign(t0, getAcc(ac)); 11160 assign(t1, unop(Iop_32Sto64, 11161 binop(Iop_Shl32, 11162 binop(Iop_Mul32, 11163 unop(Iop_16Sto32, 11164 unop(Iop_32HIto16, 11165 getIReg(rs))), 11166 unop(Iop_16Sto32, 11167 unop(Iop_32HIto16, 11168 getIReg(rt)))), 11169 mkU8(0x1)))); 11170 11171 /* If both input arguments are equal 0x8000, saturate 11172 intermediate product and write to DSPControl register. 11173 */ 11174 assign(t2, binop(Iop_CmpEQ32, 11175 unop(Iop_16Uto32, 11176 unop(Iop_32HIto16, getIReg(rs))), 11177 mkU32(0x00008000))); 11178 assign(t3, binop(Iop_CmpEQ32, 11179 unop(Iop_16Uto32, 11180 unop(Iop_32HIto16, getIReg(rt))), 11181 mkU32(0x00008000))); 11182 11183 assign(t4, 11184 IRExpr_ITE(mkexpr(t2), 11185 IRExpr_ITE(mkexpr(t3), 11186 mkU64(0x000000007fffffffULL), 11187 mkexpr(t1)), 11188 mkexpr(t1))); 11189 11190 putDSPControl(IRExpr_ITE(mkexpr(t2), 11191 IRExpr_ITE(mkexpr(t3), 11192 binop(Iop_Or32, 11193 getDSPControl(), 11194 binop(Iop_Shl32, 11195 mkU32(0x1), 11196 mkU8(ac+16) 11197 ) 11198 ), 11199 getDSPControl()), 11200 getDSPControl())); 11201 /* Add intermediate product and value in the 11202 accumulator. */ 11203 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4))); 11204 11205 /* Compare bits 31 and 32 of the value in t5. */ 11206 assign(t6, binop(Iop_CmpEQ32, 11207 binop(Iop_Shr32, 11208 binop(Iop_And32, 11209 unop(Iop_64to32, mkexpr(t5)), 11210 mkU32(0x80000000)), 11211 mkU8(31)), 11212 binop(Iop_And32, 11213 unop(Iop_64HIto32, mkexpr(t5)), 11214 mkU32(1)))); 11215 putDSPControl(IRExpr_ITE(mkexpr(t6), 11216 getDSPControl(), 11217 binop(Iop_Or32, 11218 getDSPControl(), 11219 binop(Iop_Shl32, 11220 mkU32(0x1), 11221 mkU8(ac+16))))); 11222 assign(t7, 11223 IRExpr_ITE(mkexpr(t6), 11224 mkexpr(t5), 11225 IRExpr_ITE(binop(Iop_CmpEQ32, 11226 binop(Iop_And32, 11227 unop(Iop_64HIto32, 11228 mkexpr(t5)), 11229 mkU32(1)), 11230 mkU32(0x0)), 11231 mkU64(0x000000007fffffffULL), 11232 mkU64(0xffffffff80000000ULL))) 11233 ); 11234 putAcc(ac, mkexpr(t7)); 11235 break; 11236 } 11237 case 0x12: { /* MAQ_SA.W.PHR */ 11238 DIP("maq_sa.w.phr ac%u, r%u, r%u", ac, rs, rt); 11239 vassert(!mode64); 11240 t0 = newTemp(Ity_I64); 11241 t1 = newTemp(Ity_I64); 11242 t2 = newTemp(Ity_I1); 11243 t3 = newTemp(Ity_I1); 11244 t4 = newTemp(Ity_I64); 11245 t5 = newTemp(Ity_I64); 11246 t6 = newTemp(Ity_I1); 11247 t7 = newTemp(Ity_I64); 11248 11249 assign(t0, getAcc(ac)); 11250 assign(t1, unop(Iop_32Sto64, 11251 binop(Iop_Shl32, 11252 binop(Iop_Mul32, 11253 unop(Iop_16Sto32, 11254 unop(Iop_32to16, 11255 getIReg(rs))), 11256 unop(Iop_16Sto32, 11257 unop(Iop_32to16, 11258 getIReg(rt)))), 11259 mkU8(0x1)))); 11260 11261 /* If both input arguments are equal 0x8000, saturate 11262 intermediate product and write to DSPControl 11263 register. */ 11264 assign(t2, binop(Iop_CmpEQ32, 11265 unop(Iop_16Uto32, 11266 unop(Iop_32to16, getIReg(rs))), 11267 mkU32(0x00008000))); 11268 assign(t3, binop(Iop_CmpEQ32, 11269 unop(Iop_16Uto32, 11270 unop(Iop_32to16, getIReg(rt))), 11271 mkU32(0x00008000))); 11272 11273 assign(t4, 11274 IRExpr_ITE(mkexpr(t2), 11275 IRExpr_ITE(mkexpr(t3), 11276 mkU64(0x000000007fffffffULL), 11277 mkexpr(t1)), 11278 mkexpr(t1))); 11279 11280 putDSPControl(IRExpr_ITE(mkexpr(t2), 11281 IRExpr_ITE(mkexpr(t3), 11282 binop(Iop_Or32, 11283 getDSPControl(), 11284 binop(Iop_Shl32, 11285 mkU32(0x1), 11286 mkU8(ac+16) 11287 ) 11288 ), 11289 getDSPControl()), 11290 getDSPControl())); 11291 /* Add intermediate product and value in the 11292 accumulator. */ 11293 assign(t5, binop(Iop_Add64, mkexpr(t0), mkexpr(t4))); 11294 11295 /* Compare bits 31 and 32 of the value in t5. */ 11296 assign(t6, binop(Iop_CmpEQ32, 11297 binop(Iop_Shr32, 11298 binop(Iop_And32, 11299 unop(Iop_64to32, mkexpr(t5)), 11300 mkU32(0x80000000)), 11301 mkU8(31)), 11302 binop(Iop_And32, 11303 unop(Iop_64HIto32, mkexpr(t5)), 11304 mkU32(1)))); 11305 putDSPControl(IRExpr_ITE(mkexpr(t6), 11306 getDSPControl(), 11307 binop(Iop_Or32, 11308 getDSPControl(), 11309 binop(Iop_Shl32, 11310 mkU32(0x1), 11311 mkU8(ac+16))))); 11312 assign(t7, 11313 IRExpr_ITE(mkexpr(t6), 11314 mkexpr(t5), 11315 IRExpr_ITE(binop(Iop_CmpEQ32, 11316 binop(Iop_And32, 11317 unop(Iop_64HIto32, 11318 mkexpr(t5)), 11319 mkU32(1)), 11320 mkU32(0x0)), 11321 mkU64(0x000000007fffffffULL), 11322 mkU64(0xffffffff80000000ULL))) 11323 ); 11324 putAcc(ac, mkexpr(t7)); 11325 break; 11326 } 11327 case 0x14: { /* MAQ_S.W.PHL */ 11328 DIP("maq_s.w.phl ac%u, r%u, r%u", ac, rs, rt); 11329 vassert(!mode64); 11330 t0 = newTemp(Ity_I32); 11331 t1 = newTemp(Ity_I32); 11332 t2 = newTemp(Ity_I32); 11333 t3 = newTemp(Ity_I1); 11334 t4 = newTemp(Ity_I32); 11335 t5 = newTemp(Ity_I64); 11336 11337 assign(t5, getAcc(ac)); 11338 11339 assign(t0, unop(Iop_16Sto32, 11340 unop(Iop_32HIto16, getIReg(rs)))); 11341 assign(t1, unop(Iop_16Sto32, 11342 unop(Iop_32HIto16, getIReg(rt)))); 11343 11344 assign(t2, binop(Iop_And32, 11345 unop(Iop_1Sto32, 11346 binop(Iop_CmpEQ32, 11347 binop(Iop_And32, 11348 mkexpr(t0), 11349 mkU32(0xffff)), 11350 mkU32(0x8000))), 11351 unop(Iop_1Sto32, 11352 binop(Iop_CmpEQ32, 11353 binop(Iop_And32, 11354 mkexpr(t1), 11355 mkU32(0xffff)), 11356 mkU32(0x8000))))); 11357 11358 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0))); 11359 11360 putDSPControl(IRExpr_ITE(mkexpr(t3), 11361 getDSPControl(), 11362 binop(Iop_Or32, 11363 getDSPControl(), 11364 binop(Iop_Shl32, 11365 mkU32(0x1), 11366 mkU8(ac+16))))); 11367 11368 assign(t4, unop(Iop_64to32, 11369 binop(Iop_MullS32, 11370 mkexpr(t0), mkexpr(t1)))); 11371 putAcc(ac, IRExpr_ITE(mkexpr(t3), 11372 binop(Iop_Add64, 11373 unop(Iop_32Sto64, 11374 binop(Iop_Shl32, 11375 mkexpr(t4), 11376 mkU8(0x1))), 11377 mkexpr(t5)), 11378 binop(Iop_Add64, 11379 mkexpr(t5), 11380 unop(Iop_32Sto64, 11381 mkU32(0x7fffffff))))); 11382 break; 11383 } 11384 case 0x16: { /* MAQ_S.W.PHR */ 11385 DIP("maq_s.w.phr ac%u, r%u, r%u", ac, rs, rt); 11386 vassert(!mode64); 11387 t0 = newTemp(Ity_I32); 11388 t1 = newTemp(Ity_I32); 11389 t2 = newTemp(Ity_I32); 11390 t3 = newTemp(Ity_I1); 11391 t4 = newTemp(Ity_I32); 11392 t5 = newTemp(Ity_I64); 11393 11394 assign(t5, getAcc(ac)); 11395 11396 assign(t0, unop(Iop_16Sto32, 11397 unop(Iop_32to16, getIReg(rs)))); 11398 assign(t1, unop(Iop_16Sto32, 11399 unop(Iop_32to16, getIReg(rt)))); 11400 11401 assign(t2, binop(Iop_And32, 11402 unop(Iop_1Sto32, 11403 binop(Iop_CmpEQ32, 11404 binop(Iop_And32, 11405 mkexpr(t0), 11406 mkU32(0xffff)), 11407 mkU32(0x8000))), 11408 unop(Iop_1Sto32, 11409 binop(Iop_CmpEQ32, 11410 binop(Iop_And32, 11411 mkexpr(t1), 11412 mkU32(0xffff)), 11413 mkU32(0x8000))))); 11414 11415 assign(t3, binop(Iop_CmpEQ32, mkexpr(t2), mkU32(0x0))); 11416 11417 putDSPControl(IRExpr_ITE(mkexpr(t3), 11418 getDSPControl(), 11419 binop(Iop_Or32, 11420 getDSPControl(), 11421 binop(Iop_Shl32, 11422 mkU32(0x1), 11423 mkU8(ac+16))))); 11424 11425 assign(t4, unop(Iop_64to32, 11426 binop(Iop_MullS32, 11427 mkexpr(t0), mkexpr(t1)))); 11428 putAcc(ac, IRExpr_ITE(mkexpr(t3), 11429 binop(Iop_Add64, 11430 unop(Iop_32Sto64, 11431 binop(Iop_Shl32, 11432 mkexpr(t4), 11433 mkU8(0x1))), 11434 mkexpr(t5)), 11435 binop(Iop_Add64, 11436 mkexpr(t5), 11437 unop(Iop_32Sto64, 11438 mkU32(0x7fffffff))))); 11439 break; 11440 } 11441 case 0x18: { /* DPAQX_S.W.PH */ 11442 DIP("dpaqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 11443 vassert(!mode64); 11444 t0 = newTemp(Ity_I64); 11445 t1 = newTemp(Ity_I64); 11446 t2 = newTemp(Ity_I1); 11447 t3 = newTemp(Ity_I1); 11448 t4 = newTemp(Ity_I64); 11449 t5 = newTemp(Ity_I64); 11450 t6 = newTemp(Ity_I1); 11451 t7 = newTemp(Ity_I1); 11452 t8 = newTemp(Ity_I64); 11453 t9 = newTemp(Ity_I64); 11454 11455 assign(t0, getAcc(ac)); 11456 11457 assign(t1, binop(Iop_Shl64, 11458 binop(Iop_MullS32, 11459 unop(Iop_16Sto32, 11460 unop(Iop_32HIto16, 11461 getIReg(rs))), 11462 unop(Iop_16Sto32, 11463 unop(Iop_32to16, 11464 getIReg(rt)))), 11465 mkU8(0x1))); 11466 assign(t2, binop(Iop_CmpEQ32, 11467 unop(Iop_16Uto32, 11468 unop(Iop_32HIto16, getIReg(rs))), 11469 mkU32(0x00008000))); 11470 assign(t3, binop(Iop_CmpEQ32, 11471 unop(Iop_16Uto32, 11472 unop(Iop_32to16, getIReg(rt))), 11473 mkU32(0x00008000))); 11474 assign(t4, 11475 IRExpr_ITE(mkexpr(t2), 11476 IRExpr_ITE(mkexpr(t3), 11477 mkU64(0x000000007fffffffULL), 11478 mkexpr(t1)), 11479 mkexpr(t1))); 11480 11481 putDSPControl(IRExpr_ITE(mkexpr(t2), 11482 IRExpr_ITE(mkexpr(t3), 11483 binop(Iop_Or32, 11484 getDSPControl(), 11485 binop(Iop_Shl32, 11486 mkU32(0x1), 11487 mkU8(ac+16))), 11488 getDSPControl()), 11489 getDSPControl())); 11490 11491 assign(t5, binop(Iop_Shl64, 11492 binop(Iop_MullS32, 11493 unop(Iop_16Sto32, 11494 unop(Iop_32to16, 11495 getIReg(rs))), 11496 unop(Iop_16Sto32, 11497 unop(Iop_32HIto16, 11498 getIReg(rt)))), 11499 mkU8(0x1))); 11500 assign(t6, binop(Iop_CmpEQ32, 11501 unop(Iop_16Uto32, 11502 unop(Iop_32to16, getIReg(rs))), 11503 mkU32(0x00008000))); 11504 assign(t7, binop(Iop_CmpEQ32, 11505 unop(Iop_16Uto32, 11506 unop(Iop_32HIto16, getIReg(rt))), 11507 mkU32(0x00008000))); 11508 assign(t8, 11509 IRExpr_ITE(mkexpr(t6), 11510 IRExpr_ITE(mkexpr(t7), 11511 mkU64(0x000000007fffffffULL), 11512 mkexpr(t5)), 11513 mkexpr(t5))); 11514 11515 putDSPControl(IRExpr_ITE(mkexpr(t6), 11516 IRExpr_ITE(mkexpr(t7), 11517 binop(Iop_Or32, 11518 getDSPControl(), 11519 binop(Iop_Shl32, 11520 mkU32(0x1), 11521 mkU8(ac+16) 11522 ) 11523 ), 11524 getDSPControl()), 11525 getDSPControl())); 11526 11527 assign(t9, binop(Iop_Add64, 11528 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)), 11529 mkexpr(t0))); 11530 putAcc(ac, mkexpr(t9)); 11531 break; 11532 } 11533 case 0x19: { /* DPSQX_S.W.PH */ 11534 DIP("dpsqx_s.w.ph ac%u, r%u, r%u", ac, rs, rt); 11535 vassert(!mode64); 11536 t0 = newTemp(Ity_I64); 11537 t1 = newTemp(Ity_I64); 11538 t2 = newTemp(Ity_I1); 11539 t3 = newTemp(Ity_I1); 11540 t4 = newTemp(Ity_I64); 11541 t5 = newTemp(Ity_I64); 11542 t6 = newTemp(Ity_I1); 11543 t7 = newTemp(Ity_I1); 11544 t8 = newTemp(Ity_I64); 11545 t9 = newTemp(Ity_I64); 11546 11547 assign(t0, getAcc(ac)); 11548 11549 assign(t1, binop(Iop_Shl64, 11550 binop(Iop_MullS32, 11551 unop(Iop_16Sto32, 11552 unop(Iop_32HIto16, 11553 getIReg(rs))), 11554 unop(Iop_16Sto32, 11555 unop(Iop_32to16, 11556 getIReg(rt)))), 11557 mkU8(0x1))); 11558 assign(t2, binop(Iop_CmpEQ32, 11559 unop(Iop_16Uto32, 11560 unop(Iop_32HIto16, getIReg(rs))), 11561 mkU32(0x00008000))); 11562 assign(t3, binop(Iop_CmpEQ32, 11563 unop(Iop_16Uto32, 11564 unop(Iop_32to16, getIReg(rt))), 11565 mkU32(0x00008000))); 11566 assign(t4, 11567 IRExpr_ITE(mkexpr(t2), 11568 IRExpr_ITE(mkexpr(t3), 11569 mkU64(0x000000007fffffffULL), 11570 mkexpr(t1)), 11571 mkexpr(t1))); 11572 11573 putDSPControl(IRExpr_ITE(mkexpr(t2), 11574 IRExpr_ITE(mkexpr(t3), 11575 binop(Iop_Or32, 11576 getDSPControl(), 11577 binop(Iop_Shl32, 11578 mkU32(0x1), 11579 mkU8(ac+16) 11580 ) 11581 ), 11582 getDSPControl()), 11583 getDSPControl())); 11584 11585 assign(t5, binop(Iop_Shl64, 11586 binop(Iop_MullS32, 11587 unop(Iop_16Sto32, 11588 unop(Iop_32to16, 11589 getIReg(rs))), 11590 unop(Iop_16Sto32, 11591 unop(Iop_32HIto16, 11592 getIReg(rt)))), 11593 mkU8(0x1))); 11594 assign(t6, binop(Iop_CmpEQ32, 11595 unop(Iop_16Uto32, 11596 unop(Iop_32to16, getIReg(rs))), 11597 mkU32(0x00008000))); 11598 assign(t7, binop(Iop_CmpEQ32, 11599 unop(Iop_16Uto32, 11600 unop(Iop_32HIto16, getIReg(rt))), 11601 mkU32(0x00008000))); 11602 assign(t8, 11603 IRExpr_ITE(mkexpr(t6), 11604 IRExpr_ITE(mkexpr(t7), 11605 mkU64(0x000000007fffffffULL), 11606 mkexpr(t5)), 11607 mkexpr(t5))); 11608 11609 putDSPControl(IRExpr_ITE(mkexpr(t6), 11610 IRExpr_ITE(mkexpr(t7), 11611 binop(Iop_Or32, 11612 getDSPControl(), 11613 binop(Iop_Shl32, 11614 mkU32(0x1), 11615 mkU8(ac+16) 11616 ) 11617 ), 11618 getDSPControl()), 11619 getDSPControl())); 11620 11621 assign(t9, binop(Iop_Sub64, 11622 mkexpr(t0), 11623 binop(Iop_Add64, mkexpr(t4), mkexpr(t8)))); 11624 putAcc(ac, mkexpr(t9)); 11625 break; 11626 } 11627 case 0x1A: { /* DPAQX_SA.W.PH */ 11628 DIP("dpaqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt); 11629 vassert(!mode64); 11630 t0 = newTemp(Ity_I64); 11631 t1 = newTemp(Ity_I64); 11632 t2 = newTemp(Ity_I1); 11633 t3 = newTemp(Ity_I1); 11634 t4 = newTemp(Ity_I64); 11635 t5 = newTemp(Ity_I64); 11636 t6 = newTemp(Ity_I1); 11637 t7 = newTemp(Ity_I1); 11638 t8 = newTemp(Ity_I64); 11639 t9 = newTemp(Ity_I64); 11640 t10 = newTemp(Ity_I32); 11641 11642 assign(t0, getAcc(ac)); 11643 /* Calculate the first cross dot product and saturate if 11644 needed. */ 11645 assign(t1, unop(Iop_32Sto64, 11646 binop(Iop_Shl32, 11647 binop(Iop_Mul32, 11648 unop(Iop_16Sto32, 11649 unop(Iop_32HIto16, 11650 getIReg(rs))), 11651 unop(Iop_16Sto32, 11652 unop(Iop_32to16, 11653 getIReg(rt)))), 11654 mkU8(0x1)))); 11655 11656 /* If both input arguments are equal 0x8000, saturate 11657 intermediate product and write to DSPControl 11658 register. */ 11659 assign(t2, binop(Iop_CmpEQ32, 11660 unop(Iop_16Uto32, 11661 unop(Iop_32HIto16, getIReg(rs))), 11662 mkU32(0x00008000))); 11663 assign(t3, binop(Iop_CmpEQ32, 11664 unop(Iop_16Uto32, 11665 unop(Iop_32to16, getIReg(rt))), 11666 mkU32(0x00008000))); 11667 11668 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 11669 binop(Iop_And32, 11670 unop(Iop_1Sto32, 11671 mkexpr(t2)), 11672 unop(Iop_1Sto32, 11673 mkexpr(t3))), 11674 mkU32(0)), 11675 mkU64(0x000000007fffffffULL), 11676 mkexpr(t1))); 11677 11678 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11679 binop(Iop_And32, 11680 unop(Iop_1Sto32, 11681 mkexpr(t2)), 11682 unop(Iop_1Sto32, 11683 mkexpr(t3))), 11684 mkU32(0)), 11685 binop(Iop_Or32, 11686 getDSPControl(), 11687 binop(Iop_Shl32, 11688 mkU32(0x1), 11689 mkU8(ac+16))), 11690 getDSPControl())); 11691 /* Calculate second cross dot product and saturate if 11692 needed. */ 11693 assign(t5, unop(Iop_32Sto64, 11694 binop(Iop_Shl32, 11695 binop(Iop_Mul32, 11696 unop(Iop_16Sto32, 11697 unop(Iop_32to16, 11698 getIReg(rs))), 11699 unop(Iop_16Sto32, 11700 unop(Iop_32HIto16, 11701 getIReg(rt)))), 11702 mkU8(0x1)))); 11703 11704 /* If both input arguments are equal 0x8000, saturate 11705 intermediate product and write to DSPControl 11706 register. */ 11707 assign(t6, binop(Iop_CmpEQ32, 11708 unop(Iop_16Uto32, 11709 unop(Iop_32to16, getIReg(rs))), 11710 mkU32(0x00008000))); 11711 assign(t7, binop(Iop_CmpEQ32, 11712 unop(Iop_16Uto32, 11713 unop(Iop_32HIto16, getIReg(rt))), 11714 mkU32(0x00008000))); 11715 11716 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32, 11717 binop(Iop_And32, 11718 unop(Iop_1Sto32, 11719 mkexpr(t6)), 11720 unop(Iop_1Sto32, 11721 mkexpr(t7))), 11722 mkU32(0)), 11723 mkU64(0x000000007fffffffULL), 11724 mkexpr(t5))); 11725 11726 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11727 binop(Iop_And32, 11728 unop(Iop_1Sto32, 11729 mkexpr(t6)), 11730 unop(Iop_1Sto32, 11731 mkexpr(t7))), 11732 mkU32(0)), 11733 binop(Iop_Or32, 11734 getDSPControl(), 11735 binop(Iop_Shl32, 11736 mkU32(0x1), 11737 mkU8(ac+16))), 11738 getDSPControl())); 11739 /* Subtract intermediate products from value in the 11740 accumulator. */ 11741 assign(t9, 11742 binop(Iop_Add64, 11743 mkexpr(t0), 11744 binop(Iop_Add64, mkexpr(t8), mkexpr(t4)))); 11745 11746 putAcc(ac, 11747 IRExpr_ITE(binop(Iop_CmpEQ32, 11748 binop(Iop_And32, 11749 unop(Iop_64HIto32, 11750 mkexpr(t9)), 11751 mkU32(0x80000000)), 11752 mkU32(0x0)), 11753 IRExpr_ITE(binop(Iop_CmpNE32, 11754 unop(Iop_64HIto32, 11755 binop(Iop_Shl64, 11756 mkexpr(t9), 11757 mkU8(1))), 11758 mkU32(0x0)), 11759 mkU64(0x000000007fffffffULL), 11760 mkexpr(t9)), 11761 IRExpr_ITE(binop(Iop_CmpNE32, 11762 unop(Iop_64HIto32, 11763 binop(Iop_Shl64, 11764 mkexpr(t9), 11765 mkU8(1))), 11766 mkU32(0xffffffff)), 11767 mkU64(0xffffffff80000000ULL), 11768 mkexpr(t9)))); 11769 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32, 11770 unop(Iop_64to32, 11771 mkexpr(t9)), 11772 unop(Iop_64to32, 11773 getAcc(ac))), 11774 getDSPControl(), 11775 binop(Iop_Or32, 11776 getDSPControl(), 11777 binop(Iop_Shl32, 11778 mkU32(0x1), 11779 mkU8(ac+16))))); 11780 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 11781 unop(Iop_64HIto32, 11782 mkexpr(t9)), 11783 unop(Iop_64HIto32, 11784 getAcc(ac))), 11785 mkexpr(t10), 11786 binop(Iop_Or32, 11787 getDSPControl(), 11788 binop(Iop_Shl32, 11789 mkU32(0x1), 11790 mkU8(ac+16))))); 11791 break; 11792 } 11793 case 0x1B: { /* DPSQX_SA.W.PH */ 11794 DIP("dpsqx_sa.w.ph ac%u, r%u, r%u", ac, rs, rt); 11795 vassert(!mode64); 11796 t0 = newTemp(Ity_I64); 11797 t1 = newTemp(Ity_I64); 11798 t2 = newTemp(Ity_I1); 11799 t3 = newTemp(Ity_I1); 11800 t4 = newTemp(Ity_I64); 11801 t5 = newTemp(Ity_I64); 11802 t6 = newTemp(Ity_I1); 11803 t7 = newTemp(Ity_I1); 11804 t8 = newTemp(Ity_I64); 11805 t9 = newTemp(Ity_I64); 11806 t10 = newTemp(Ity_I32); 11807 11808 assign(t0, getAcc(ac)); 11809 /* Calculate the first cross dot product and saturate if 11810 needed. */ 11811 assign(t1, unop(Iop_32Sto64, 11812 binop(Iop_Shl32, 11813 binop(Iop_Mul32, 11814 unop(Iop_16Sto32, 11815 unop(Iop_32HIto16, 11816 getIReg(rs))), 11817 unop(Iop_16Sto32, 11818 unop(Iop_32to16, 11819 getIReg(rt)))), 11820 mkU8(0x1)))); 11821 11822 /* If both input arguments are equal 0x8000, saturate 11823 intermediate product and write to DSPControl 11824 register. */ 11825 assign(t2, binop(Iop_CmpEQ32, 11826 unop(Iop_16Uto32, 11827 unop(Iop_32HIto16, getIReg(rs))), 11828 mkU32(0x00008000))); 11829 assign(t3, binop(Iop_CmpEQ32, 11830 unop(Iop_16Uto32, 11831 unop(Iop_32to16, getIReg(rt))), 11832 mkU32(0x00008000))); 11833 11834 assign(t4, IRExpr_ITE(binop(Iop_CmpNE32, 11835 binop(Iop_And32, 11836 unop(Iop_1Sto32, 11837 mkexpr(t2)), 11838 unop(Iop_1Sto32, 11839 mkexpr(t3))), 11840 mkU32(0)), 11841 mkU64(0x000000007fffffffULL), 11842 mkexpr(t1))); 11843 11844 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11845 binop(Iop_And32, 11846 unop(Iop_1Sto32, 11847 mkexpr(t2)), 11848 unop(Iop_1Sto32, 11849 mkexpr(t3))), 11850 mkU32(0)), 11851 binop(Iop_Or32, 11852 getDSPControl(), 11853 binop(Iop_Shl32, 11854 mkU32(0x1), 11855 mkU8(ac+16))), 11856 getDSPControl())); 11857 /* Calculate second cross dot product and saturate if 11858 needed. */ 11859 assign(t5, unop(Iop_32Sto64, 11860 binop(Iop_Shl32, 11861 binop(Iop_Mul32, 11862 unop(Iop_16Sto32, 11863 unop(Iop_32to16, 11864 getIReg(rs))), 11865 unop(Iop_16Sto32, 11866 unop(Iop_32HIto16, 11867 getIReg(rt)))), 11868 mkU8(0x1)))); 11869 11870 /* If both input arguments are equal 0x8000, saturate 11871 intermediate product and write to DSPControl 11872 register. */ 11873 assign(t6, binop(Iop_CmpEQ32, 11874 unop(Iop_16Uto32, 11875 unop(Iop_32to16, getIReg(rs))), 11876 mkU32(0x00008000))); 11877 assign(t7, binop(Iop_CmpEQ32, 11878 unop(Iop_16Uto32, 11879 unop(Iop_32HIto16, getIReg(rt))), 11880 mkU32(0x00008000))); 11881 11882 assign(t8, IRExpr_ITE(binop(Iop_CmpNE32, 11883 binop(Iop_And32, 11884 unop(Iop_1Sto32, 11885 mkexpr(t6)), 11886 unop(Iop_1Sto32, 11887 mkexpr(t7))), 11888 mkU32(0)), 11889 mkU64(0x000000007fffffffULL), 11890 mkexpr(t5))); 11891 11892 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 11893 binop(Iop_And32, 11894 unop(Iop_1Sto32, 11895 mkexpr(t6)), 11896 unop(Iop_1Sto32, 11897 mkexpr(t7))), 11898 mkU32(0)), 11899 binop(Iop_Or32, 11900 getDSPControl(), 11901 binop(Iop_Shl32, 11902 mkU32(0x1), 11903 mkU8(ac+16))), 11904 getDSPControl())); 11905 /* Subtract intermediate products from value in the 11906 accumulator. */ 11907 assign(t9, 11908 binop(Iop_Sub64, 11909 mkexpr(t0), 11910 binop(Iop_Add64, mkexpr(t8), mkexpr(t4)))); 11911 11912 putAcc(ac, 11913 IRExpr_ITE(binop(Iop_CmpEQ32, 11914 binop(Iop_And32, 11915 unop(Iop_64HIto32, 11916 mkexpr(t9)), 11917 mkU32(0x80000000)), 11918 mkU32(0x0)), 11919 IRExpr_ITE(binop(Iop_CmpNE32, 11920 unop(Iop_64HIto32, 11921 binop(Iop_Shl64, 11922 mkexpr(t9), 11923 mkU8(1))), 11924 mkU32(0x0)), 11925 mkU64(0x000000007fffffffULL), 11926 mkexpr(t9)), 11927 IRExpr_ITE(binop(Iop_CmpNE32, 11928 unop(Iop_64HIto32, 11929 binop(Iop_Shl64, 11930 mkexpr(t9), 11931 mkU8(1))), 11932 mkU32(0xffffffff)), 11933 mkU64(0xffffffff80000000ULL), 11934 mkexpr(t9)))); 11935 assign(t10, IRExpr_ITE(binop(Iop_CmpEQ32, 11936 unop(Iop_64to32, 11937 mkexpr(t9)), 11938 unop(Iop_64to32, 11939 getAcc(ac))), 11940 getDSPControl(), 11941 binop(Iop_Or32, 11942 getDSPControl(), 11943 binop(Iop_Shl32, 11944 mkU32(0x1), 11945 mkU8(ac+16))))); 11946 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 11947 unop(Iop_64HIto32, 11948 mkexpr(t9)), 11949 unop(Iop_64HIto32, 11950 getAcc(ac))), 11951 mkexpr(t10), 11952 binop(Iop_Or32, 11953 getDSPControl(), 11954 binop(Iop_Shl32, 11955 mkU32(0x1), 11956 mkU8(ac+16))))); 11957 break; 11958 } 11959 default: 11960 return -1; 11961 } 11962 break; /* end of DPAQ.W.PH */ 11963 } 11964 case 0x31: { /* APPEND */ 11965 switch(sa) { 11966 case 0x0: { /* APPEND */ 11967 DIP("append r%u, r%u, %u", rt, rs, rd); 11968 vassert(!mode64); 11969 t1 = newTemp(Ity_I32); 11970 t2 = newTemp(Ity_I32); 11971 t3 = newTemp(Ity_I32); 11972 11973 assign(t1, binop(Iop_Shl32, getIReg(rt), mkU8(rd))); 11974 11975 if (31 == rd) { 11976 putIReg(rt, binop(Iop_Or32, 11977 mkexpr(t1), 11978 binop(Iop_And32, 11979 getIReg(rs), 11980 mkU32(0x7fffffff)))); 11981 } else if (1 == rd) { 11982 putIReg(rt, 11983 binop(Iop_Or32, 11984 mkexpr(t1), 11985 binop(Iop_And32, 11986 getIReg(rs), mkU32(0x1)))); 11987 } else { 11988 assign(t2, 11989 unop(Iop_Not32, 11990 binop(Iop_Shl32, 11991 mkU32(0xffffffff), mkU8(rd)))); 11992 11993 putIReg(rt, binop(Iop_Or32, 11994 mkexpr(t1), 11995 binop(Iop_And32, 11996 getIReg(rs), mkexpr(t2)))); 11997 } 11998 break; 11999 } 12000 case 0x1: { /* PREPEND */ 12001 DIP("prepend r%u, r%u, %u", rt, rs, rd); 12002 vassert(!mode64); 12003 t1 = newTemp(Ity_I32); 12004 t2 = newTemp(Ity_I32); 12005 t3 = newTemp(Ity_I32); 12006 12007 if (0 != rd) { 12008 assign(t1, binop(Iop_Shr32, getIReg(rt), mkU8(rd))); 12009 12010 if (31 == rd) { 12011 putIReg(rt, binop(Iop_Or32, 12012 mkexpr(t1), 12013 binop(Iop_Shl32, 12014 binop(Iop_And32, 12015 getIReg(rs), 12016 mkU32(0x7fffffff)), 12017 mkU8(1)))); 12018 } else if (1 == rd) { 12019 putIReg(rt, binop(Iop_Or32, 12020 mkexpr(t1), 12021 binop(Iop_Shl32, 12022 binop(Iop_And32, 12023 getIReg(rs), 12024 mkU32(0x1)), 12025 mkU8(31)))); 12026 } else { 12027 assign(t2, binop(Iop_Add32, mkU32(rd), mkU32(0x1))); 12028 12029 assign(t3, unop(Iop_Not32, 12030 binop(Iop_Shl32, 12031 mkU32(0xffffffff), 12032 unop(Iop_32to8, mkexpr(t2))))); 12033 12034 putIReg(rt, binop(Iop_Or32, 12035 mkexpr(t1), 12036 binop(Iop_Shl32, 12037 binop(Iop_And32, 12038 getIReg(rs), 12039 mkexpr(t3)), 12040 mkU8(32-rd)))); 12041 } 12042 } 12043 break; 12044 } 12045 case 0x10: { /* BALIGN */ 12046 DIP("balign r%u, r%u, %u", rt, rs, rd); 12047 vassert(!mode64); 12048 t1 = newTemp(Ity_I32); 12049 t2 = newTemp(Ity_I32); 12050 t3 = newTemp(Ity_I32); 12051 12052 if ((2 != rd) && (0 != rd)) { 12053 assign(t1, binop(Iop_Shl32, 12054 binop(Iop_And32, 12055 mkU32(rd), mkU32(0x3)), 12056 mkU8(0x3))); 12057 assign(t2, binop(Iop_Shl32, 12058 getIReg(rt), 12059 unop(Iop_32to8, mkexpr(t1)))); 12060 assign(t3, binop(Iop_Shr32, 12061 getIReg(rs), 12062 unop(Iop_32to8, 12063 binop(Iop_Shl32, 12064 binop(Iop_Sub32, 12065 mkU32(0x4), 12066 binop(Iop_And32, 12067 mkU32(rd), 12068 mkU32(0x3))), 12069 mkU8(0x3))))); 12070 putIReg(rt, binop(Iop_Or32, mkexpr(t2), mkexpr(t3))); 12071 } 12072 break; 12073 } 12074 default: 12075 return -1; 12076 } 12077 break; /* end of APPEND */ 12078 } 12079 default: 12080 return -1; 12081 } 12082 break; 12083 } 12084 default: 12085 return -1; 12086 } 12087 return 0; 12088 } 12089 12090 /*------------------------------------------------------------*/ 12091 /*--- Disassemble a single instruction ---*/ 12092 /*------------------------------------------------------------*/ 12093 12094 /* Disassemble a single instruction into IR. The instruction is 12095 located in host memory at guest_instr, and has guest IP of 12096 guest_PC_curr_instr, which will have been set before the call 12097 here. */ 12098 12099 static DisResult disInstr_MIPS_WRK ( Bool(*resteerOkFn) (/*opaque */void *, 12100 Addr), 12101 Bool resteerCisOk, 12102 void* callback_opaque, 12103 Long delta64, 12104 const VexArchInfo* archinfo, 12105 const VexAbiInfo* abiinfo, 12106 Bool sigill_diag ) 12107 { 12108 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7; 12109 12110 UInt opcode, cins, rs, rt, rd, sa, ft, fs, fd, fmt, tf, nd, function, 12111 trap_code, imm, instr_index, p, msb, lsb, size, rot, sel; 12112 /* Additional variables for instruction fields in DSP ASE insructions */ 12113 UInt ac; 12114 12115 DisResult dres; 12116 12117 static IRExpr *lastn = NULL; /* last jump addr */ 12118 static IRStmt *bstmt = NULL; /* branch (Exit) stmt */ 12119 12120 /* The running delta */ 12121 Int delta = (Int) delta64; 12122 12123 /* Holds eip at the start of the insn, so that we can print 12124 consistent error messages for unimplemented insns. */ 12125 Int delta_start = delta; 12126 12127 /* Are we in a delay slot ? */ 12128 Bool delay_slot_branch, likely_delay_slot, delay_slot_jump; 12129 12130 /* Set result defaults. */ 12131 dres.whatNext = Dis_Continue; 12132 dres.len = 0; 12133 dres.continueAt = 0; 12134 dres.jk_StopHere = Ijk_INVALID; 12135 dres.hint = Dis_HintNone; 12136 12137 delay_slot_branch = likely_delay_slot = delay_slot_jump = False; 12138 12139 const UChar *code = guest_code + delta; 12140 cins = getUInt(code); 12141 DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, cins); 12142 12143 if (delta != 0) { 12144 if (branch_or_jump(guest_code + delta - 4)) { 12145 if (lastn == NULL && bstmt == NULL) { 12146 vassert(0); 12147 } else { 12148 dres.whatNext = Dis_StopHere; 12149 if (lastn != NULL) { 12150 delay_slot_jump = True; 12151 } else if (bstmt != NULL) { 12152 delay_slot_branch = True; 12153 } 12154 } 12155 } 12156 12157 if (branch_or_link_likely(guest_code + delta - 4)) { 12158 likely_delay_slot = True; 12159 } 12160 } 12161 12162 /* Spot "Special" instructions (see comment at top of file). */ 12163 { 12164 /* Spot the 16-byte preamble: 12165 ****mips32**** 12166 "srl $0, $0, 13 12167 "srl $0, $0, 29 12168 "srl $0, $0, 3 12169 "srl $0, $0, 19 12170 12171 ****mips64**** 12172 dsll $0, $0, 3 12173 dsll $0, $0, 13 12174 dsll $0, $0, 29 12175 dsll $0, $0, 19 */ 12176 12177 UInt word1 = mode64 ? 0xF8 : 0x342; 12178 UInt word2 = mode64 ? 0x378 : 0x742; 12179 UInt word3 = mode64 ? 0x778 : 0xC2; 12180 UInt word4 = mode64 ? 0x4F8 : 0x4C2; 12181 if (getUInt(code + 0) == word1 && getUInt(code + 4) == word2 && 12182 getUInt(code + 8) == word3 && getUInt(code + 12) == word4) { 12183 /* Got a "Special" instruction preamble. Which one is it? */ 12184 if (getUInt(code + 16) == 0x01ad6825 /* or $13, $13, $13 */ ) { 12185 /* $11 = client_request ( $12 ) */ 12186 DIP("$11 = client_request ( $12 )"); 12187 if (mode64) 12188 putPC(mkU64(guest_PC_curr_instr + 20)); 12189 else 12190 putPC(mkU32(guest_PC_curr_instr + 20)); 12191 dres.jk_StopHere = Ijk_ClientReq; 12192 dres.whatNext = Dis_StopHere; 12193 12194 goto decode_success; 12195 } else if (getUInt(code + 16) == 0x01ce7025 /* or $14, $14, $14 */ ) { 12196 /* $11 = guest_NRADDR */ 12197 DIP("$11 = guest_NRADDR"); 12198 dres.len = 20; 12199 delta += 20; 12200 if (mode64) 12201 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS64State, 12202 guest_NRADDR), Ity_I64)); 12203 else 12204 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State, 12205 guest_NRADDR), Ity_I32)); 12206 goto decode_success; 12207 } else if (getUInt(code + 16) == 0x01ef7825 /* or $15, $15, $15 */ ) { 12208 /* branch-and-link-to-noredir $25 */ 12209 DIP("branch-and-link-to-noredir $25"); 12210 if (mode64) 12211 putIReg(31, mkU64(guest_PC_curr_instr + 20)); 12212 else 12213 putIReg(31, mkU32(guest_PC_curr_instr + 20)); 12214 putPC(getIReg(25)); 12215 dres.jk_StopHere = Ijk_NoRedir; 12216 dres.whatNext = Dis_StopHere; 12217 goto decode_success; 12218 } else if (getUInt(code + 16) == 0x016b5825 /* or $11,$11,$11 */ ) { 12219 /* IR injection */ 12220 DIP("IR injection"); 12221 #if defined (_MIPSEL) 12222 vex_inject_ir(irsb, Iend_LE); 12223 #elif defined (_MIPSEB) 12224 vex_inject_ir(irsb, Iend_BE); 12225 #endif 12226 if (mode64) { 12227 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMSTART), 12228 mkU64(guest_PC_curr_instr))); 12229 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_CMLEN), 12230 mkU64(20))); 12231 12232 putPC(mkU64(guest_PC_curr_instr + 20)); 12233 } else { 12234 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMSTART), 12235 mkU32(guest_PC_curr_instr))); 12236 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_CMLEN), 12237 mkU32(20))); 12238 12239 putPC(mkU32(guest_PC_curr_instr + 20)); 12240 } 12241 dres.whatNext = Dis_StopHere; 12242 dres.jk_StopHere = Ijk_InvalICache; 12243 dres.len = 20; 12244 delta += 20; 12245 goto decode_success; 12246 } 12247 12248 /* We don't know what it is. Set opc1/opc2 so decode_failure 12249 can print the insn following the Special-insn preamble. */ 12250 delta += 16; 12251 goto decode_failure; 12252 /*NOTREACHED*/} 12253 } 12254 12255 opcode = get_opcode(cins); 12256 imm = get_imm(cins); 12257 rs = get_rs(cins); 12258 rt = get_rt(cins); 12259 rd = get_rd(cins); 12260 sa = get_sa(cins); 12261 fs = get_fs(cins); 12262 fd = get_fd(cins); 12263 ft = get_ft(cins); 12264 tf = get_tf(cins); 12265 nd = get_nd(cins); 12266 sel = get_sel(cins); 12267 fmt = get_fmt(cins); 12268 instr_index = get_instr_index(cins); 12269 trap_code = get_code(cins); 12270 function = get_function(cins); 12271 IRType ty = mode64 ? Ity_I64 : Ity_I32; 12272 IRType tyF = fp_mode64 ? Ity_F64 : Ity_F32; 12273 12274 ac = get_acNo(cins); 12275 12276 switch (opcode) { 12277 12278 case 0x03: /* JAL */ 12279 DIP("jal 0x%x", instr_index); 12280 if (mode64) { 12281 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 12282 t0 = newTemp(ty); 12283 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) | 12284 (instr_index << 2))); 12285 } else { 12286 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 12287 t0 = newTemp(ty); 12288 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 12289 (instr_index << 2))); 12290 } 12291 lastn = mkexpr(t0); 12292 break; 12293 case 0x02: /* J */ 12294 DIP("j 0x%x", instr_index); 12295 t0 = newTemp(ty); 12296 if (mode64) 12297 assign(t0, mkU64((guest_PC_curr_instr & 0xFFFFFFFFF0000000ULL) | 12298 (instr_index << 2))); 12299 else 12300 assign(t0, mkU32((guest_PC_curr_instr & 0xF0000000) | 12301 (instr_index << 2))); 12302 lastn = mkexpr(t0); 12303 break; 12304 12305 case 0x11: { /* COP1 */ 12306 if (fmt == 0x3 && fd == 0 && function == 0) { /* MFHC1 */ 12307 DIP("mfhc1 r%u, f%u", rt, fs); 12308 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) { 12309 if (fp_mode64) { 12310 t0 = newTemp(Ity_I64); 12311 t1 = newTemp(Ity_I32); 12312 assign(t0, unop(Iop_ReinterpF64asI64, getDReg(fs))); 12313 assign(t1, unop(Iop_64HIto32, mkexpr(t0))); 12314 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 12315 break; 12316 } else { 12317 putIReg(rt, mkWidenFrom32(ty, unop(Iop_ReinterpF32asI32, 12318 getFReg(fs | 1)), True)); 12319 break; 12320 } 12321 } 12322 ILLEGAL_INSTRUCTON; 12323 break; 12324 } else if (fmt == 0x7 && fd == 0 && function == 0) { /* MTHC1 */ 12325 DIP("mthc1 r%u, f%u", rt, fs); 12326 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) { 12327 if (fp_mode64) { 12328 t0 = newTemp(Ity_I64); 12329 assign(t0, binop(Iop_32HLto64, mkNarrowTo32(ty, getIReg(rt)), 12330 unop(Iop_ReinterpF32asI32, 12331 getLoFromF64(Ity_F64, getDReg(fs))))); 12332 putDReg(fs, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12333 break; 12334 } else { 12335 putFReg(fs | 1, unop(Iop_ReinterpI32asF32, 12336 mkNarrowTo32(ty, getIReg(rt)))); 12337 break; 12338 } 12339 } 12340 ILLEGAL_INSTRUCTON; 12341 break; 12342 } else if (fmt == 0x8) { /* BC */ 12343 /* FcConditionalCode(bc1_cc) */ 12344 UInt bc1_cc = get_bc1_cc(cins); 12345 t1 = newTemp(Ity_I1); 12346 t2 = newTemp(Ity_I32); 12347 t3 = newTemp(Ity_I1); 12348 12349 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(bc1_cc))); 12350 assign(t2, IRExpr_ITE(mkexpr(t1), 12351 binop(Iop_And32, 12352 binop(Iop_Shr32, getFCSR(), mkU8(23)), 12353 mkU32(0x1)), 12354 binop(Iop_And32, 12355 binop(Iop_Shr32, getFCSR(), 12356 mkU8(24 + bc1_cc)), 12357 mkU32(0x1)))); 12358 12359 if (tf == 1 && nd == 0) { 12360 /* branch on true */ 12361 DIP("bc1t %u, %u", bc1_cc, imm); 12362 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12363 dis_branch(False, mkexpr(t3), imm, &bstmt); 12364 break; 12365 } else if (tf == 0 && nd == 0) { 12366 /* branch on false */ 12367 DIP("bc1f %u, %u", bc1_cc, imm); 12368 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12369 dis_branch(False, mkexpr(t3), imm, &bstmt); 12370 break; 12371 } else if (nd == 1 && tf == 0) { 12372 DIP("bc1fl %u, %u", bc1_cc, imm); 12373 lastn = dis_branch_likely(binop(Iop_CmpNE32, mkexpr(t2), 12374 mkU32(0x0)), imm); 12375 break; 12376 } else if (nd == 1 && tf == 1) { 12377 DIP("bc1tl %u, %u", bc1_cc, imm); 12378 lastn = dis_branch_likely(binop(Iop_CmpEQ32, mkexpr(t2), 12379 mkU32(0x0)), imm); 12380 break; 12381 } else 12382 goto decode_failure; 12383 } else { 12384 switch (function) { 12385 case 0x4: { /* SQRT.fmt */ 12386 switch (fmt) { 12387 case 0x10: { /* S */ 12388 IRExpr *rm = get_IR_roundingmode(); 12389 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_SqrtF32, rm, 12390 getLoFromF64(tyF, getFReg(fs))))); 12391 break; 12392 } 12393 case 0x11: { /* D */ 12394 IRExpr *rm = get_IR_roundingmode(); 12395 putDReg(fd, binop(Iop_SqrtF64, rm, getDReg(fs))); 12396 break; 12397 } 12398 default: 12399 goto decode_failure; 12400 } 12401 } 12402 break; 12403 case 0x5: /* abs.fmt */ 12404 switch (fmt) { 12405 case 0x10: /* S */ 12406 DIP("abs.s f%u, f%u", fd, fs); 12407 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_AbsF32, 12408 getLoFromF64(tyF, getFReg(fs))))); 12409 break; 12410 case 0x11: /* D */ 12411 DIP("abs.d f%u, f%u", fd, fs); 12412 putDReg(fd, unop(Iop_AbsF64, getDReg(fs))); 12413 break; 12414 default: 12415 goto decode_failure; 12416 } 12417 break; /* case 0x5 */ 12418 12419 case 0x02: /* MUL.fmt */ 12420 switch (fmt) { 12421 case 0x11: { /* D */ 12422 DIP("mul.d f%u, f%u, f%u", fd, fs, ft); 12423 IRExpr *rm = get_IR_roundingmode(); 12424 putDReg(fd, triop(Iop_MulF64, rm, getDReg(fs), 12425 getDReg(ft))); 12426 break; 12427 } 12428 case 0x10: { /* S */ 12429 DIP("mul.s f%u, f%u, f%u", fd, fs, ft); 12430 IRExpr *rm = get_IR_roundingmode(); 12431 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_MulF32, rm, 12432 getLoFromF64(tyF, getFReg(fs)), 12433 getLoFromF64(tyF, getFReg(ft))))); 12434 break; 12435 } 12436 default: 12437 goto decode_failure; 12438 } 12439 break; /* MUL.fmt */ 12440 12441 case 0x03: /* DIV.fmt */ 12442 switch (fmt) { 12443 case 0x11: { /* D */ 12444 DIP("div.d f%u, f%u, f%u", fd, fs, ft); 12445 IRExpr *rm = get_IR_roundingmode(); 12446 putDReg(fd, triop(Iop_DivF64, rm, getDReg(fs), 12447 getDReg(ft))); 12448 break; 12449 } 12450 case 0x10: { /* S */ 12451 DIP("div.s f%u, f%u, f%u", fd, fs, ft); 12452 calculateFCSR(fs, ft, DIVS, False, 2); 12453 IRExpr *rm = get_IR_roundingmode(); 12454 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 12455 getLoFromF64(tyF, getFReg(fs)), 12456 getLoFromF64(tyF, getFReg(ft))))); 12457 break; 12458 } 12459 default: 12460 goto decode_failure; 12461 } 12462 break; /* DIV.fmt */ 12463 12464 case 0x01: /* SUB.fmt */ 12465 switch (fmt) { 12466 case 0x11: { /* D */ 12467 DIP("sub.d f%u, f%u, f%u", fd, fs, ft); 12468 calculateFCSR(fs, ft, SUBD, False, 2); 12469 IRExpr *rm = get_IR_roundingmode(); 12470 putDReg(fd, triop(Iop_SubF64, rm, getDReg(fs), 12471 getDReg(ft))); 12472 break; 12473 } 12474 case 0x10: { /* S */ 12475 DIP("sub.s f%u, f%u, f%u", fd, fs, ft); 12476 calculateFCSR(fs, ft, SUBS, True, 2); 12477 IRExpr *rm = get_IR_roundingmode(); 12478 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_SubF32, rm, 12479 getLoFromF64(tyF, getFReg(fs)), 12480 getLoFromF64(tyF, getFReg(ft))))); 12481 break; 12482 } 12483 default: 12484 goto decode_failure; 12485 } 12486 break; /* SUB.fmt */ 12487 12488 case 0x06: /* MOV.fmt */ 12489 switch (fmt) { 12490 case 0x11: /* D */ 12491 DIP("mov.d f%u, f%u", fd, fs); 12492 if (fp_mode64) { 12493 putDReg(fd, getDReg(fs)); 12494 } else { 12495 putFReg(fd, getFReg(fs)); 12496 putFReg(fd + 1, getFReg(fs + 1)); 12497 } 12498 break; 12499 case 0x10: /* S */ 12500 DIP("mov.s f%u, f%u", fd, fs); 12501 putFReg(fd, getFReg(fs)); 12502 break; 12503 default: 12504 goto decode_failure; 12505 } 12506 break; /* MOV.fmt */ 12507 12508 case 0x7: /* neg.fmt */ 12509 switch (fmt) { 12510 case 0x10: /* S */ 12511 DIP("neg.s f%u, f%u", fd, fs); 12512 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, 12513 getLoFromF64(tyF, getFReg(fs))))); 12514 break; 12515 case 0x11: /* D */ 12516 DIP("neg.d f%u, f%u", fd, fs); 12517 putDReg(fd, unop(Iop_NegF64, getDReg(fs))); 12518 break; 12519 default: 12520 goto decode_failure; 12521 } 12522 break; /* case 0x7 */ 12523 12524 case 0x08: /* ROUND.L.fmt */ 12525 switch (fmt) { 12526 case 0x10: /* S */ 12527 DIP("round.l.s f%u, f%u", fd, fs); 12528 if (fp_mode64) { 12529 calculateFCSR(fs, 0, ROUNDLS, True, 1); 12530 t0 = newTemp(Ity_I64); 12531 12532 assign(t0, binop(Iop_F32toI64S, mkU32(0x0), 12533 getLoFromF64(Ity_F64, getFReg(fs)))); 12534 12535 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12536 } else { 12537 ILLEGAL_INSTRUCTON; 12538 } 12539 break; 12540 case 0x11: /* D */ 12541 DIP("round.l.d f%u, f%u", fd, fs); 12542 if (fp_mode64) { 12543 calculateFCSR(fs, 0, ROUNDLD, False, 1); 12544 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x0), 12545 getDReg(fs))); 12546 } else { 12547 ILLEGAL_INSTRUCTON; 12548 } 12549 break; 12550 default: 12551 goto decode_failure; 12552 12553 } 12554 break; /* ROUND.L.fmt */ 12555 12556 case 0x09: /* TRUNC.L.fmt */ 12557 switch (fmt) { 12558 case 0x10: /* S */ 12559 DIP("trunc.l.s f%u, f%u", fd, fs); 12560 if (fp_mode64) { 12561 calculateFCSR(fs, 0, TRUNCLS, True, 1); 12562 t0 = newTemp(Ity_I64); 12563 assign(t0, binop(Iop_F32toI64S, mkU32(0x3), 12564 getLoFromF64(Ity_F64, getFReg(fs)))); 12565 12566 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 12567 } else { 12568 ILLEGAL_INSTRUCTON; 12569 } 12570 break; 12571 case 0x11: /* D */ 12572 DIP("trunc.l.d f%u, f%u", fd, fs); 12573 if (fp_mode64) { 12574 calculateFCSR(fs, 0, TRUNCLD, False, 1); 12575 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x3), 12576 getDReg(fs))); 12577 } else { 12578 ILLEGAL_INSTRUCTON; 12579 } 12580 break; 12581 default: 12582 goto decode_failure; 12583 } 12584 break; /* TRUNC.L.fmt */ 12585 12586 case 0x15: /* RECIP.fmt */ 12587 switch (fmt) { 12588 case 0x10: { /* S */ 12589 DIP("recip.s f%u, f%u", fd, fs); 12590 IRExpr *rm = get_IR_roundingmode(); 12591 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, 12592 rm, unop(Iop_ReinterpI32asF32, 12593 mkU32(ONE_SINGLE)), getLoFromF64(tyF, 12594 getFReg(fs))))); 12595 break; 12596 } 12597 case 0x11: { /* D */ 12598 DIP("recip.d f%u, f%u", fd, fs); 12599 IRExpr *rm = get_IR_roundingmode(); 12600 /* putDReg(fd, 1.0/getDreg(fs)); */ 12601 putDReg(fd, triop(Iop_DivF64, rm, 12602 unop(Iop_ReinterpI64asF64, 12603 mkU64(ONE_DOUBLE)), getDReg(fs))); 12604 break; 12605 } 12606 default: 12607 goto decode_failure; 12608 12609 } 12610 break; /* case 0x15 */ 12611 12612 case 0x13: /* MOVN.fmt */ 12613 switch (fmt) { 12614 case 0x10: /* S */ 12615 DIP("movn.s f%u, f%u, r%u", fd, fs, rt); 12616 t1 = newTemp(Ity_I1); 12617 12618 if (mode64) 12619 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); 12620 else 12621 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); 12622 12623 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd))); 12624 break; 12625 case 0x11: /* D */ 12626 DIP("movn.d f%u, f%u, r%u", fd, fs, rt); 12627 t1 = newTemp(Ity_I1); 12628 12629 if (mode64) 12630 assign(t1, binop(Iop_CmpNE64, mkU64(0), getIReg(rt))); 12631 else 12632 assign(t1, binop(Iop_CmpNE32, mkU32(0), getIReg(rt))); 12633 12634 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd))); 12635 break; 12636 default: 12637 goto decode_failure; 12638 } 12639 break; /* MOVN.fmt */ 12640 12641 case 0x12: /* MOVZ.fmt */ 12642 switch (fmt) { 12643 case 0x10: /* S */ 12644 DIP("movz.s f%u, f%u, r%u", fd, fs, rt); 12645 t1 = newTemp(Ity_I1); 12646 12647 if (mode64) 12648 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); 12649 else 12650 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); 12651 12652 putFReg(fd, IRExpr_ITE(mkexpr(t1), getFReg(fs), getFReg(fd))); 12653 break; 12654 case 0x11: /* D */ 12655 DIP("movz.d f%u, f%u, r%u", fd, fs, rt); 12656 t1 = newTemp(Ity_I1); 12657 12658 if (mode64) 12659 assign(t1, binop(Iop_CmpEQ64, mkU64(0), getIReg(rt))); 12660 else 12661 assign(t1, binop(Iop_CmpEQ32, mkU32(0), getIReg(rt))); 12662 12663 putDReg(fd, IRExpr_ITE(mkexpr(t1), getDReg(fs), getDReg(fd))); 12664 break; 12665 default: 12666 goto decode_failure; 12667 } 12668 break; /* MOVZ.fmt */ 12669 12670 case 0x11: /* MOVT.fmt */ 12671 if (tf == 1) { 12672 UInt mov_cc = get_mov_cc(cins); 12673 switch (fmt) { /* MOVCF = 010001 */ 12674 case 0x11: /* D */ 12675 DIP("movt.d f%u, f%u, %u", fd, fs, mov_cc); 12676 t1 = newTemp(Ity_I1); 12677 t2 = newTemp(Ity_I32); 12678 t3 = newTemp(Ity_I1); 12679 t4 = newTemp(Ity_F64); 12680 12681 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12682 assign(t2, IRExpr_ITE(mkexpr(t1), 12683 binop(Iop_And32, 12684 binop(Iop_Shr32, getFCSR(), 12685 mkU8(23)), 12686 mkU32(0x1)), 12687 binop(Iop_And32, 12688 binop(Iop_Shr32, getFCSR(), 12689 mkU8(24 + mov_cc)), 12690 mkU32(0x1)) 12691 )); 12692 12693 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12694 assign(t4, IRExpr_ITE(mkexpr(t3), 12695 getDReg(fs), getDReg(fd))); 12696 putDReg(fd, mkexpr(t4)); 12697 break; 12698 case 0x10: /* S */ 12699 DIP("movt.s f%u, f%u, %u", fd, fs, mov_cc); 12700 t1 = newTemp(Ity_I1); 12701 t2 = newTemp(Ity_I32); 12702 t3 = newTemp(Ity_I1); 12703 t4 = newTemp(Ity_F64); 12704 t5 = newTemp(Ity_F64); 12705 t6 = newTemp(Ity_F64); 12706 t7 = newTemp(Ity_I64); 12707 12708 if (fp_mode64) { 12709 assign(t5, getFReg(fs)); 12710 assign(t6, getFReg(fd)); 12711 } else { 12712 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 12713 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 12714 } 12715 12716 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12717 assign(t2, IRExpr_ITE(mkexpr(t1), 12718 binop(Iop_And32, 12719 binop(Iop_Shr32, getFCSR(), 12720 mkU8(23)), 12721 mkU32(0x1)), 12722 binop(Iop_And32, 12723 binop(Iop_Shr32, getFCSR(), 12724 mkU8(24 + mov_cc)), 12725 mkU32(0x1)) 12726 )); 12727 12728 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 12729 assign(t4, IRExpr_ITE(mkexpr(t3), 12730 mkexpr(t5), mkexpr(t6))); 12731 12732 if (fp_mode64) { 12733 IRTemp f = newTemp(Ity_F64); 12734 IRTemp fd_hi = newTemp(Ity_I32); 12735 assign(f, getFReg(fd)); 12736 assign(fd_hi, unop(Iop_64HIto32, 12737 unop(Iop_ReinterpF64asI64, mkexpr(f)))); 12738 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12739 unop(Iop_ReinterpF64asI64, mkexpr(t4))), 12740 True)); 12741 12742 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); 12743 } else 12744 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12745 mkexpr(t4))); 12746 break; 12747 default: 12748 goto decode_failure; 12749 } 12750 } else if (tf == 0) /* movf.fmt */ 12751 { 12752 UInt mov_cc = get_mov_cc(cins); 12753 switch (fmt) /* MOVCF = 010001 */ 12754 { 12755 case 0x11: /* D */ 12756 DIP("movf.d f%u, f%u, %u", fd, fs, mov_cc); 12757 t1 = newTemp(Ity_I1); 12758 t2 = newTemp(Ity_I32); 12759 t3 = newTemp(Ity_I1); 12760 t4 = newTemp(Ity_F64); 12761 12762 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12763 assign(t2, IRExpr_ITE(mkexpr(t1), 12764 binop(Iop_And32, 12765 binop(Iop_Shr32, getFCSR(), 12766 mkU8(23)), 12767 mkU32(0x1)), 12768 binop(Iop_And32, 12769 binop(Iop_Shr32, getFCSR(), 12770 mkU8(24 + mov_cc)), 12771 mkU32(0x1)) 12772 )); 12773 12774 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12775 assign(t4, IRExpr_ITE(mkexpr(t3), 12776 getDReg(fs), getDReg(fd))); 12777 putDReg(fd, mkexpr(t4)); 12778 break; 12779 case 0x10: /* S */ 12780 DIP("movf.s f%u, f%u, %u", fd, fs, mov_cc); 12781 t1 = newTemp(Ity_I1); 12782 t2 = newTemp(Ity_I32); 12783 t3 = newTemp(Ity_I1); 12784 t4 = newTemp(Ity_F64); 12785 t5 = newTemp(Ity_F64); 12786 t6 = newTemp(Ity_F64); 12787 12788 if (fp_mode64) { 12789 assign(t5, getFReg(fs)); 12790 assign(t6, getFReg(fd)); 12791 } else { 12792 assign(t5, unop(Iop_F32toF64, getFReg(fs))); 12793 assign(t6, unop(Iop_F32toF64, getFReg(fd))); 12794 } 12795 12796 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 12797 assign(t2, IRExpr_ITE(mkexpr(t1), 12798 binop(Iop_And32, 12799 binop(Iop_Shr32, getFCSR(), 12800 mkU8(23)), 12801 mkU32(0x1)), 12802 binop(Iop_And32, 12803 binop(Iop_Shr32, getFCSR(), 12804 mkU8(24 + mov_cc)), 12805 mkU32(0x1)) 12806 )); 12807 12808 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 12809 assign(t4, IRExpr_ITE(mkexpr(t3), 12810 mkexpr(t5), mkexpr(t6))); 12811 12812 if (fp_mode64) { 12813 IRTemp f = newTemp(Ity_F64); 12814 IRTemp fd_hi = newTemp(Ity_I32); 12815 t7 = newTemp(Ity_I64); 12816 assign(f, getFReg(fd)); 12817 assign(fd_hi, unop(Iop_64HIto32, 12818 unop(Iop_ReinterpF64asI64, mkexpr(f)))); 12819 assign(t7, mkWidenFrom32(Ity_I64, unop(Iop_64to32, 12820 unop(Iop_ReinterpF64asI64, mkexpr(t4))), 12821 True)); 12822 12823 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t7))); 12824 } else 12825 putFReg(fd, binop(Iop_F64toF32, get_IR_roundingmode(), 12826 mkexpr(t4))); 12827 break; 12828 default: 12829 goto decode_failure; 12830 } 12831 } 12832 12833 break; /* MOVT.fmt */ 12834 12835 case 0x0: /* add.fmt */ 12836 switch (fmt) { 12837 case 0x10: { /* S */ 12838 DIP("add.s f%u, f%u, f%u", fd, fs, ft); 12839 calculateFCSR(fs, ft, ADDS, True, 2); 12840 IRExpr *rm = get_IR_roundingmode(); 12841 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_AddF32, rm, 12842 getLoFromF64(tyF, getFReg(fs)), 12843 getLoFromF64(tyF, getFReg(ft))))); 12844 break; 12845 } 12846 case 0x11: { /* D */ 12847 DIP("add.d f%u, f%u, f%u", fd, fs, ft); 12848 calculateFCSR(fs, ft, ADDD, False, 2); 12849 IRExpr *rm = get_IR_roundingmode(); 12850 putDReg(fd, triop(Iop_AddF64, rm, getDReg(fs), getDReg(ft))); 12851 break; 12852 } 12853 12854 case 0x4: /* MTC1 (Move Word to Floating Point) */ 12855 DIP("mtc1 r%u, f%u", rt, fs); 12856 if (fp_mode64) { 12857 t0 = newTemp(Ity_I32); 12858 t1 = newTemp(Ity_F32); 12859 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 12860 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 12861 12862 putFReg(fs, mkWidenFromF32(tyF, mkexpr(t1))); 12863 } else 12864 putFReg(fs, unop(Iop_ReinterpI32asF32, 12865 mkNarrowTo32(ty, getIReg(rt)))); 12866 break; 12867 12868 case 0x5: /* Doubleword Move to Floating Point DMTC1; MIPS64 */ 12869 DIP("dmtc1 r%u, f%u", rt, fs); 12870 vassert(mode64); 12871 putDReg(fs, unop(Iop_ReinterpI64asF64, getIReg(rt))); 12872 break; 12873 12874 case 0x0: /* MFC1 */ 12875 DIP("mfc1 r%u, f%u", rt, fs); 12876 if (fp_mode64) { 12877 t0 = newTemp(Ity_I64); 12878 t1 = newTemp(Ity_I32); 12879 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 12880 assign(t1, unop(Iop_64to32, mkexpr(t0))); 12881 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 12882 } else 12883 putIReg(rt, mkWidenFrom32(ty, 12884 unop(Iop_ReinterpF32asI32, getFReg(fs)), 12885 True)); 12886 break; 12887 12888 case 0x1: /* Doubleword Move from Floating Point DMFC1; 12889 MIPS64 */ 12890 DIP("dmfc1 r%u, f%u", rt, fs); 12891 putIReg(rt, unop(Iop_ReinterpF64asI64, getDReg(fs))); 12892 break; 12893 12894 case 0x6: /* CTC1 */ 12895 DIP("ctc1 r%u, f%u", rt, fs); 12896 t0 = newTemp(Ity_I32); 12897 t1 = newTemp(Ity_I32); 12898 t2 = newTemp(Ity_I32); 12899 t3 = newTemp(Ity_I32); 12900 t4 = newTemp(Ity_I32); 12901 t5 = newTemp(Ity_I32); 12902 t6 = newTemp(Ity_I32); 12903 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 12904 if (fs == 25) { /* FCCR */ 12905 assign(t1, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12906 mkU32(0x000000FE)), mkU8(24))); 12907 assign(t2, binop(Iop_And32, mkexpr(t0), 12908 mkU32(0x01000000))); 12909 assign(t3, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12910 mkU32(0x00000001)), mkU8(23))); 12911 assign(t4, binop(Iop_And32, mkexpr(t0), 12912 mkU32(0x007FFFFF))); 12913 putFCSR(binop(Iop_Or32, binop(Iop_Or32, mkexpr(t1), 12914 mkexpr(t2)), binop(Iop_Or32, mkexpr(t3), 12915 mkexpr(t4)))); 12916 } else if (fs == 26) { /* FEXR */ 12917 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFFFC0000))); 12918 assign(t2, binop(Iop_And32, mkexpr(t0), 12919 mkU32(0x0003F000))); 12920 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00000F80))); 12921 assign(t4, binop(Iop_And32, mkexpr(t0), 12922 mkU32(0x0000007C))); 12923 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x00000003))); 12924 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 12925 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 12926 mkexpr(t3), mkexpr(t4))), mkexpr(t5))); 12927 } else if (fs == 28) { 12928 assign(t1, binop(Iop_And32, getFCSR(), mkU32(0xFE000000))); 12929 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkexpr(t0), 12930 mkU32(0x00000002)), mkU8(22))); 12931 assign(t3, binop(Iop_And32, getFCSR(), mkU32(0x00FFF000))); 12932 assign(t4, binop(Iop_And32, mkexpr(t0), 12933 mkU32(0x00000F80))); 12934 assign(t5, binop(Iop_And32, getFCSR(), mkU32(0x0000007C))); 12935 assign(t6, binop(Iop_And32, mkexpr(t0), 12936 mkU32(0x00000003))); 12937 putFCSR(binop(Iop_Or32, binop(Iop_Or32, binop(Iop_Or32, 12938 mkexpr(t1), mkexpr(t2)), binop(Iop_Or32, 12939 mkexpr(t3), mkexpr(t4))), binop(Iop_Or32, 12940 mkexpr(t5), mkexpr(t6)))); 12941 } else if (fs == 31) { 12942 putFCSR(mkexpr(t0)); 12943 } 12944 break; 12945 case 0x2: /* CFC1 */ 12946 DIP("cfc1 r%u, f%u", rt, fs); 12947 t0 = newTemp(Ity_I32); 12948 t1 = newTemp(Ity_I32); 12949 t2 = newTemp(Ity_I32); 12950 t3 = newTemp(Ity_I32); 12951 t4 = newTemp(Ity_I32); 12952 t5 = newTemp(Ity_I32); 12953 t6 = newTemp(Ity_I32); 12954 assign(t0, getFCSR()); 12955 if (fs == 0) { 12956 putIReg(rt, mkWidenFrom32(ty, 12957 IRExpr_Get(offsetof(VexGuestMIPS32State, 12958 guest_FIR), 12959 Ity_I32), 12960 False)); 12961 } else if (fs == 25) { 12962 assign(t1, mkU32(0x000000FF)); 12963 assign(t2, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12964 mkU32(0xFE000000)), mkU8(25))); 12965 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12966 mkU32(0x00800000)), mkU8(23))); 12967 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12968 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12969 mkexpr(t3)), False)); 12970 } else if (fs == 26) { 12971 assign(t1, mkU32(0xFFFFF07C)); 12972 assign(t2, binop(Iop_And32, mkexpr(t0), 12973 mkU32(0x0003F000))); 12974 assign(t3, binop(Iop_And32, mkexpr(t0), 12975 mkU32(0x0000007C))); 12976 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12977 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12978 mkexpr(t3)), False)); 12979 } else if (fs == 28) { 12980 assign(t1, mkU32(0x00000F87)); 12981 assign(t2, binop(Iop_And32, mkexpr(t0), 12982 mkU32(0x00000F83))); 12983 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkexpr(t0), 12984 mkU32(0x01000000)), mkU8(22))); 12985 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, 12986 binop(Iop_Or32, mkexpr(t1), mkexpr(t2)), 12987 mkexpr(t3)), False)); 12988 } else if (fs == 31) { 12989 putIReg(rt, mkWidenFrom32(ty, getFCSR(), False)); 12990 } 12991 break; 12992 default: 12993 goto decode_failure; 12994 } 12995 break; 12996 12997 case 0x21: /* CVT.D */ 12998 switch (fmt) { 12999 case 0x10: /* S */ 13000 DIP("cvt.d.s f%u, f%u", fd, fs); 13001 calculateFCSR(fs, 0, CVTDS, True, 1); 13002 if (fp_mode64) { 13003 t0 = newTemp(Ity_I64); 13004 t1 = newTemp(Ity_I32); 13005 t3 = newTemp(Ity_F32); 13006 t4 = newTemp(Ity_F32); 13007 /* get lo half of FPR */ 13008 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13009 13010 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13011 13012 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13013 13014 putFReg(fd, unop(Iop_F32toF64, mkexpr(t3))); 13015 } else 13016 putDReg(fd, unop(Iop_F32toF64, getFReg(fs))); 13017 break; 13018 13019 case 0x14: 13020 DIP("cvt.d.w %u, %u", fd, fs); 13021 calculateFCSR(fs, 0, CVTDW, True, 1); 13022 if (fp_mode64) { 13023 t0 = newTemp(Ity_I64); 13024 t1 = newTemp(Ity_I32); 13025 t3 = newTemp(Ity_F32); 13026 t4 = newTemp(Ity_F32); 13027 /* get lo half of FPR */ 13028 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13029 13030 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13031 putDReg(fd,unop(Iop_I32StoF64, mkexpr(t1))); 13032 break; 13033 } else { 13034 t0 = newTemp(Ity_I32); 13035 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 13036 putDReg(fd, unop(Iop_I32StoF64, mkexpr(t0))); 13037 break; 13038 } 13039 13040 case 0x15: { /* L */ 13041 if (fp_mode64) { 13042 DIP("cvt.d.l %u, %u", fd, fs); 13043 calculateFCSR(fs, 0, CVTDL, False, 1); 13044 t0 = newTemp(Ity_I64); 13045 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13046 13047 putFReg(fd, binop(Iop_I64StoF64, 13048 get_IR_roundingmode(), mkexpr(t0))); 13049 break; 13050 } else 13051 goto decode_failure; 13052 } 13053 default: 13054 goto decode_failure; 13055 } 13056 break; /* CVT.D */ 13057 13058 case 0x20: /* cvt.s */ 13059 switch (fmt) { 13060 case 0x14: /* W */ 13061 DIP("cvt.s.w %u, %u", fd, fs); 13062 calculateFCSR(fs, 0, CVTSW, True, 1); 13063 if (fp_mode64) { 13064 t0 = newTemp(Ity_I64); 13065 t1 = newTemp(Ity_I32); 13066 t3 = newTemp(Ity_F32); 13067 t4 = newTemp(Ity_F32); 13068 /* get lo half of FPR */ 13069 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13070 13071 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13072 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I32StoF32, 13073 get_IR_roundingmode(), mkexpr(t1)))); 13074 } else { 13075 t0 = newTemp(Ity_I32); 13076 assign(t0, unop(Iop_ReinterpF32asI32, getFReg(fs))); 13077 putFReg(fd, binop(Iop_I32StoF32, get_IR_roundingmode(), 13078 mkexpr(t0))); 13079 } 13080 break; 13081 13082 case 0x11: /* D */ 13083 DIP("cvt.s.d %u, %u", fd, fs); 13084 calculateFCSR(fs, 0, CVTSD, False, 1); 13085 t0 = newTemp(Ity_F32); 13086 assign(t0, binop(Iop_F64toF32, get_IR_roundingmode(), 13087 getDReg(fs))); 13088 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t0))); 13089 break; 13090 13091 case 0x15: /* L */ 13092 DIP("cvt.s.l %u, %u", fd, fs); 13093 if (fp_mode64) { 13094 calculateFCSR(fs, 0, CVTSL, False, 1); 13095 t0 = newTemp(Ity_I64); 13096 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13097 13098 putFReg(fd, mkWidenFromF32(tyF, binop(Iop_I64StoF32, 13099 get_IR_roundingmode(), mkexpr(t0)))); 13100 } else { 13101 ILLEGAL_INSTRUCTON; 13102 } 13103 break; 13104 13105 default: 13106 goto decode_failure; 13107 } 13108 break; /* cvt.s */ 13109 13110 case 0x24: /* cvt.w */ 13111 switch (fmt) { 13112 case 0x10: /* S */ 13113 DIP("cvt.w.s %u, %u", fd, fs); 13114 calculateFCSR(fs, 0, CVTWS, True, 1); 13115 putFReg(fd, 13116 mkWidenFromF32(tyF, 13117 binop(Iop_RoundF32toInt, 13118 get_IR_roundingmode(), 13119 getLoFromF64(tyF, getFReg(fs)))) 13120 ); 13121 break; 13122 13123 case 0x11: 13124 DIP("cvt.w.d %u, %u", fd, fs); 13125 calculateFCSR(fs, 0, CVTWD, False, 1); 13126 t0 = newTemp(Ity_I32); 13127 t1 = newTemp(Ity_F32); 13128 assign(t0, binop(Iop_F64toI32S, get_IR_roundingmode(), 13129 getDReg(fs))); 13130 assign(t1, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13131 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13132 break; 13133 13134 default: 13135 goto decode_failure; 13136 13137 } 13138 break; 13139 13140 case 0x25: /* cvt.l */ 13141 switch (fmt) { 13142 case 0x10: /* S */ 13143 DIP("cvt.l.s %u, %u", fd, fs); 13144 if (fp_mode64) { 13145 calculateFCSR(fs, 0, CVTLS, True, 1); 13146 t0 = newTemp(Ity_I64); 13147 13148 assign(t0, binop(Iop_F32toI64S, get_IR_roundingmode(), 13149 getLoFromF64(tyF, getFReg(fs)))); 13150 13151 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13152 } else { 13153 ILLEGAL_INSTRUCTON; 13154 } 13155 break; 13156 13157 case 0x11: { /* D */ 13158 DIP("cvt.l.d %u, %u", fd, fs); 13159 if (fp_mode64) { 13160 calculateFCSR(fs, 0, CVTLD, False, 1); 13161 putDReg(fd, binop(Iop_RoundF64toInt, 13162 get_IR_roundingmode(), getDReg(fs))); 13163 } else { 13164 ILLEGAL_INSTRUCTON; 13165 } 13166 break; 13167 } 13168 13169 default: 13170 goto decode_failure; 13171 } 13172 break; 13173 13174 case 0x0B: /* FLOOR.L.fmt */ 13175 switch (fmt) { 13176 case 0x10: /* S */ 13177 DIP("floor.l.s %u, %u", fd, fs); 13178 if (fp_mode64) { 13179 calculateFCSR(fs, 0, FLOORLS, True, 1); 13180 t0 = newTemp(Ity_I64); 13181 13182 assign(t0, binop(Iop_F32toI64S, mkU32(0x1), 13183 getLoFromF64(tyF, getFReg(fs)))); 13184 13185 putDReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13186 } else { 13187 ILLEGAL_INSTRUCTON; 13188 } 13189 break; 13190 13191 case 0x11: /* D */ 13192 DIP("floor.l.d %u, %u", fd, fs); 13193 if (fp_mode64) { 13194 calculateFCSR(fs, 0, FLOORLD, False, 1); 13195 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x1), 13196 getDReg(fs))); 13197 } else { 13198 ILLEGAL_INSTRUCTON; 13199 } 13200 break; 13201 default: 13202 goto decode_failure; 13203 } 13204 break; 13205 13206 case 0x0C: /* ROUND.W.fmt */ 13207 switch (fmt) { 13208 case 0x10: /* S */ 13209 DIP("round.w.s f%u, f%u", fd, fs); 13210 calculateFCSR(fs, 0, ROUNDWS, True, 1); 13211 if (fp_mode64) { 13212 t0 = newTemp(Ity_I64); 13213 t1 = newTemp(Ity_I32); 13214 t3 = newTemp(Ity_F32); 13215 t4 = newTemp(Ity_F32); 13216 /* get lo half of FPR */ 13217 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13218 13219 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13220 13221 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13222 13223 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x0), 13224 mkexpr(t3))); 13225 13226 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13227 } else 13228 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x0), 13229 getFReg(fs))); 13230 break; 13231 13232 case 0x11: /* D */ 13233 DIP("round.w.d f%u, f%u", fd, fs); 13234 calculateFCSR(fs, 0, ROUNDWD, False, 1); 13235 if (fp_mode64) { 13236 t0 = newTemp(Ity_I32); 13237 assign(t0, binop(Iop_F64toI32S, mkU32(0x0), 13238 getDReg(fs))); 13239 putFReg(fd, mkWidenFromF32(tyF, 13240 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13241 } else { 13242 t0 = newTemp(Ity_I32); 13243 13244 assign(t0, binop(Iop_F64toI32S, mkU32(0x0), 13245 getDReg(fs))); 13246 13247 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13248 } 13249 break; 13250 default: 13251 goto decode_failure; 13252 13253 } 13254 break; /* ROUND.W.fmt */ 13255 13256 case 0x0F: /* FLOOR.W.fmt */ 13257 switch (fmt) { 13258 case 0x10: /* S */ 13259 DIP("floor.w.s f%u, f%u", fd, fs); 13260 calculateFCSR(fs, 0, FLOORWS, True, 1); 13261 if (fp_mode64) { 13262 t0 = newTemp(Ity_I64); 13263 t1 = newTemp(Ity_I32); 13264 t3 = newTemp(Ity_F32); 13265 t4 = newTemp(Ity_F32); 13266 /* get lo half of FPR */ 13267 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13268 13269 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13270 13271 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13272 13273 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x1), 13274 mkexpr(t3))); 13275 13276 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13277 } else 13278 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x1), 13279 getFReg(fs))); 13280 break; 13281 13282 case 0x11: /* D */ 13283 DIP("floor.w.d f%u, f%u", fd, fs); 13284 calculateFCSR(fs, 0, FLOORWD, False, 1); 13285 if (fp_mode64) { 13286 t0 = newTemp(Ity_I32); 13287 assign(t0, binop(Iop_F64toI32S, mkU32(0x1), 13288 getDReg(fs))); 13289 putFReg(fd, mkWidenFromF32(tyF, 13290 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13291 break; 13292 } else { 13293 t0 = newTemp(Ity_I32); 13294 13295 assign(t0, binop(Iop_F64toI32S, mkU32(0x1), 13296 getDReg(fs))); 13297 13298 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13299 break; 13300 } 13301 default: 13302 goto decode_failure; 13303 13304 } 13305 break; /* FLOOR.W.fmt */ 13306 13307 case 0x0D: /* TRUNC.W */ 13308 switch (fmt) { 13309 case 0x10: /* S */ 13310 DIP("trunc.w.s %u, %u", fd, fs); 13311 calculateFCSR(fs, 0, TRUNCWS, True, 1); 13312 if (fp_mode64) { 13313 t0 = newTemp(Ity_I64); 13314 t1 = newTemp(Ity_I32); 13315 t3 = newTemp(Ity_F32); 13316 t4 = newTemp(Ity_F32); 13317 /* get lo half of FPR */ 13318 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13319 13320 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13321 13322 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13323 13324 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x3), 13325 mkexpr(t3))); 13326 13327 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13328 } else 13329 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x3), 13330 getFReg(fs))); 13331 break; 13332 case 0x11: /* D */ 13333 DIP("trunc.w.d %u, %u", fd, fs); 13334 calculateFCSR(fs, 0, TRUNCWD, False, 1); 13335 if (fp_mode64) { 13336 t0 = newTemp(Ity_I32); 13337 13338 assign(t0, binop(Iop_F64toI32S, mkU32(0x3), 13339 getFReg(fs))); 13340 13341 putFReg(fd, mkWidenFromF32(tyF, 13342 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13343 } else { 13344 t0 = newTemp(Ity_I32); 13345 13346 assign(t0, binop(Iop_F64toI32S, mkU32(0x3), 13347 getDReg(fs))); 13348 13349 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13350 } 13351 break; 13352 default: 13353 goto decode_failure; 13354 13355 } 13356 break; 13357 13358 case 0x0E: /* CEIL.W.fmt */ 13359 switch (fmt) { 13360 case 0x10: /* S */ 13361 DIP("ceil.w.s %u, %u", fd, fs); 13362 calculateFCSR(fs, 0, CEILWS, True, 1); 13363 if (fp_mode64) { 13364 t0 = newTemp(Ity_I64); 13365 t1 = newTemp(Ity_I32); 13366 t3 = newTemp(Ity_F32); 13367 t4 = newTemp(Ity_F32); 13368 /* get lo half of FPR */ 13369 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(fs))); 13370 13371 assign(t1, unop(Iop_64to32, mkexpr(t0))); 13372 13373 assign(t3, unop(Iop_ReinterpI32asF32, mkexpr(t1))); 13374 13375 assign(t4, binop(Iop_RoundF32toInt, mkU32(0x2), 13376 mkexpr(t3))); 13377 13378 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t4))); 13379 } else 13380 putFReg(fd, binop(Iop_RoundF32toInt, mkU32(0x2), 13381 getFReg(fs))); 13382 break; 13383 13384 case 0x11: /* D */ 13385 DIP("ceil.w.d %u, %u", fd, fs); 13386 calculateFCSR(fs, 0, CEILWD, False, 1); 13387 if (!fp_mode64) { 13388 t0 = newTemp(Ity_I32); 13389 assign(t0, binop(Iop_F64toI32S, mkU32(0x2), 13390 getDReg(fs))); 13391 putFReg(fd, unop(Iop_ReinterpI32asF32, mkexpr(t0))); 13392 } else { 13393 t0 = newTemp(Ity_I32); 13394 assign(t0, binop(Iop_F64toI32S, mkU32(0x2), 13395 getDReg(fs))); 13396 putFReg(fd, mkWidenFromF32(tyF, 13397 unop(Iop_ReinterpI32asF32, mkexpr(t0)))); 13398 } 13399 break; 13400 default: 13401 goto decode_failure; 13402 13403 } 13404 break; 13405 13406 case 0x0A: /* CEIL.L.fmt */ 13407 switch (fmt) { 13408 case 0x10: /* S */ 13409 DIP("ceil.l.s %u, %u", fd, fs); 13410 if (fp_mode64) { 13411 calculateFCSR(fs, 0, CEILLS, True, 1); 13412 t0 = newTemp(Ity_I64); 13413 13414 assign(t0, binop(Iop_F32toI64S, mkU32(0x2), 13415 getLoFromF64(tyF, getFReg(fs)))); 13416 13417 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t0))); 13418 } else { 13419 ILLEGAL_INSTRUCTON; 13420 } 13421 break; 13422 13423 case 0x11: /* D */ 13424 DIP("ceil.l.d %u, %u", fd, fs); 13425 if (fp_mode64) { 13426 calculateFCSR(fs, 0, CEILLD, False, 1); 13427 putDReg(fd, binop(Iop_RoundF64toInt, mkU32(0x2), 13428 getDReg(fs))); 13429 } else { 13430 ILLEGAL_INSTRUCTON; 13431 } 13432 break; 13433 13434 default: 13435 goto decode_failure; 13436 13437 } 13438 break; 13439 13440 case 0x16: /* RSQRT.fmt */ 13441 switch (fmt) { 13442 case 0x10: { /* S */ 13443 DIP("rsqrt.s %u, %u", fd, fs); 13444 IRExpr *rm = get_IR_roundingmode(); 13445 putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm, 13446 unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)), 13447 binop(Iop_SqrtF32, rm, getLoFromF64(tyF, 13448 getFReg(fs)))))); 13449 break; 13450 } 13451 case 0x11: { /* D */ 13452 DIP("rsqrt.d %u, %u", fd, fs); 13453 IRExpr *rm = get_IR_roundingmode(); 13454 putDReg(fd, triop(Iop_DivF64, rm, 13455 unop(Iop_ReinterpI64asF64, 13456 mkU64(ONE_DOUBLE)), 13457 binop(Iop_SqrtF64, rm, getDReg(fs)))); 13458 break; 13459 } 13460 default: 13461 goto decode_failure; 13462 13463 } 13464 break; 13465 13466 default: 13467 if (dis_instr_CCondFmt(cins)) 13468 break; 13469 goto decode_failure; 13470 13471 } 13472 13473 } 13474 } 13475 break; /* COP1 */ 13476 13477 case 0x31: /* LWC1 */ 13478 /* Load Word to Floating Point - LWC1 (MIPS32) */ 13479 DIP("lwc1 f%u, %u(r%u)", ft, imm, rs); 13480 LOAD_STORE_PATTERN; 13481 if (fp_mode64) { 13482 t0 = newTemp(Ity_F32); 13483 t2 = newTemp(Ity_I64); 13484 assign(t0, load(Ity_F32, mkexpr(t1))); 13485 assign(t2, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, 13486 mkexpr(t0)), True)); 13487 putDReg(ft, unop(Iop_ReinterpI64asF64, mkexpr(t2))); 13488 } else { 13489 putFReg(ft, load(Ity_F32, mkexpr(t1))); 13490 } 13491 break; 13492 13493 case 0x39: /* SWC1 */ 13494 DIP("swc1 f%u, %u(r%u)", ft, imm, rs); 13495 if (fp_mode64) { 13496 t0 = newTemp(Ity_I64); 13497 t2 = newTemp(Ity_I32); 13498 LOAD_STORE_PATTERN; 13499 assign(t0, unop(Iop_ReinterpF64asI64, getFReg(ft))); 13500 assign(t2, unop(Iop_64to32, mkexpr(t0))); 13501 store(mkexpr(t1), unop(Iop_ReinterpI32asF32, mkexpr(t2))); 13502 } else { 13503 LOAD_STORE_PATTERN; 13504 store(mkexpr(t1), getFReg(ft)); 13505 } 13506 break; 13507 13508 case 0x33: /* PREF */ 13509 DIP("pref"); 13510 break; 13511 13512 case 0x35: 13513 /* Load Doubleword to Floating Point - LDC1 (MIPS32) */ 13514 DIP("ldc1 f%u, %u(%u)", rt, imm, rs); 13515 LOAD_STORE_PATTERN; 13516 putDReg(ft, load(Ity_F64, mkexpr(t1))); 13517 break; 13518 13519 case 0x3D: 13520 /* Store Doubleword from Floating Point - SDC1 */ 13521 DIP("sdc1 f%u, %u(%u)", ft, imm, rs); 13522 LOAD_STORE_PATTERN; 13523 store(mkexpr(t1), getDReg(ft)); 13524 break; 13525 13526 case 0x23: /* LW */ 13527 DIP("lw r%u, %u(r%u)", rt, imm, rs); 13528 LOAD_STORE_PATTERN; 13529 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True)); 13530 break; 13531 13532 case 0x20: /* LB */ 13533 DIP("lb r%u, %u(r%u)", rt, imm, rs); 13534 LOAD_STORE_PATTERN; 13535 if (mode64) 13536 putIReg(rt, unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 13537 else 13538 putIReg(rt, unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 13539 break; 13540 13541 case 0x24: /* LBU */ 13542 DIP("lbu r%u, %u(r%u)", rt, imm, rs); 13543 LOAD_STORE_PATTERN; 13544 if (mode64) 13545 putIReg(rt, unop(Iop_8Uto64, load(Ity_I8, mkexpr(t1)))); 13546 else 13547 putIReg(rt, unop(Iop_8Uto32, load(Ity_I8, mkexpr(t1)))); 13548 break; 13549 13550 case 0x21: /* LH */ 13551 DIP("lh r%u, %u(r%u)", rt, imm, rs); 13552 LOAD_STORE_PATTERN; 13553 if (mode64) 13554 putIReg(rt, unop(Iop_16Sto64, load(Ity_I16, mkexpr(t1)))); 13555 else 13556 putIReg(rt, unop(Iop_16Sto32, load(Ity_I16, mkexpr(t1)))); 13557 break; 13558 13559 case 0x25: /* LHU */ 13560 DIP("lhu r%u, %u(r%u)", rt, imm, rs); 13561 LOAD_STORE_PATTERN; 13562 if (mode64) 13563 putIReg(rt, unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 13564 else 13565 putIReg(rt, unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 13566 break; 13567 13568 case 0x0F: /* LUI */ 13569 p = (imm << 16); 13570 DIP("lui r%u, imm: 0x%x", rt, imm); 13571 if (mode64) 13572 putIReg(rt, mkU64(extend_s_32to64(p))); 13573 else 13574 putIReg(rt, mkU32(p)); 13575 break; 13576 13577 case 0x13: /* COP1X */ 13578 switch (function) { 13579 case 0x0: { /* LWXC1 */ 13580 /* Load Word Indexed to Floating Point - LWXC1 (MIPS32r2) */ 13581 DIP("lwxc1 f%u, r%u(r%u)", fd, rt, rs); 13582 t2 = newTemp(ty); 13583 assign(t2, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13584 getIReg(rt))); 13585 if (fp_mode64) { 13586 t0 = newTemp(Ity_I64); 13587 t1 = newTemp(Ity_I32); 13588 t3 = newTemp(Ity_F32); 13589 t4 = newTemp(Ity_I64); 13590 assign(t3, load(Ity_F32, mkexpr(t2))); 13591 13592 assign(t4, mkWidenFrom32(Ity_I64, unop(Iop_ReinterpF32asI32, 13593 mkexpr(t3)), True)); 13594 13595 putFReg(fd, unop(Iop_ReinterpI64asF64, mkexpr(t4))); 13596 } else { 13597 putFReg(fd, load(Ity_F32, mkexpr(t2))); 13598 } 13599 break; 13600 } 13601 13602 case 0x1: { /* LDXC1 */ 13603 /* Load Doubleword Indexed to Floating Point 13604 LDXC1 (MIPS32r2 and MIPS64) */ 13605 DIP("ldxc1 f%u, r%u(r%u)", fd, rt, rs); 13606 t0 = newTemp(ty); 13607 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13608 getIReg(rt))); 13609 putDReg(fd, load(Ity_F64, mkexpr(t0))); 13610 break; 13611 } 13612 13613 case 0x5: /* Load Doubleword Indexed Unaligned to Floating Point - LUXC1; 13614 MIPS32r2 and MIPS64 */ 13615 DIP("luxc1 f%u, r%u(r%u)", fd, rt, rs); 13616 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) 13617 && fp_mode64) { 13618 t0 = newTemp(ty); 13619 t1 = newTemp(ty); 13620 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, 13621 getIReg(rs), getIReg(rt))); 13622 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32, 13623 mkexpr(t0), 13624 mode64 ? mkU64(0xfffffffffffffff8ULL) 13625 : mkU32(0xfffffff8ULL))); 13626 putFReg(fd, load(Ity_F64, mkexpr(t1))); 13627 } else { 13628 ILLEGAL_INSTRUCTON; 13629 } 13630 break; 13631 13632 case 0x8: { /* Store Word Indexed from Floating Point - SWXC1 */ 13633 DIP("swxc1 f%u, r%u(r%u)", ft, rt, rs); 13634 t0 = newTemp(ty); 13635 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13636 getIReg(rt))); 13637 if (fp_mode64) { 13638 store(mkexpr(t0), getLoFromF64(tyF, getFReg(fs))); 13639 } else { 13640 store(mkexpr(t0), getFReg(fs)); 13641 } 13642 break; 13643 } 13644 case 0x9: { /* Store Doubleword Indexed from Floating Point - SDXC1 */ 13645 DIP("sdxc1 f%u, r%u(r%u)", fs, rt, rs); 13646 t0 = newTemp(ty); 13647 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, getIReg(rs), 13648 getIReg(rt))); 13649 store(mkexpr(t0), getDReg(fs)); 13650 break; 13651 } 13652 case 0xD: /* Store Doubleword Indexed Unaligned from Floating Point - 13653 SUXC1; MIPS64 MIPS32r2 */ 13654 DIP("suxc1 f%u, r%u(r%u)", fd, rt, rs); 13655 if ((mode64 || VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps)) 13656 && fp_mode64) { 13657 t0 = newTemp(ty); 13658 t1 = newTemp(ty); 13659 assign(t0, binop(mode64 ? Iop_Add64 : Iop_Add32, 13660 getIReg(rs), getIReg(rt))); 13661 assign(t1, binop(mode64 ? Iop_And64 : Iop_And32, 13662 mkexpr(t0), 13663 mode64 ? mkU64(0xfffffffffffffff8ULL) 13664 : mkU32(0xfffffff8ULL))); 13665 store(mkexpr(t1), getFReg(fs)); 13666 } else { 13667 ILLEGAL_INSTRUCTON; 13668 } 13669 break; 13670 13671 case 0x0F: { 13672 DIP("prefx"); 13673 break; 13674 } 13675 case 0x20: { /* MADD.S */ 13676 DIP("madd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13677 IRExpr *rm = get_IR_roundingmode(); 13678 t1 = newTemp(Ity_F32); 13679 assign(t1, qop(Iop_MAddF32, rm, 13680 getLoFromF64(tyF, getFReg(fmt)), 13681 getLoFromF64(tyF, getFReg(fs)), 13682 getLoFromF64(tyF, getFReg(ft)))); 13683 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13684 break; /* MADD.S */ 13685 } 13686 case 0x21: { /* MADD.D */ 13687 DIP("madd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13688 IRExpr *rm = get_IR_roundingmode(); 13689 putDReg(fd, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs), 13690 getDReg(ft))); 13691 break; /* MADD.D */ 13692 } 13693 case 0x28: { /* MSUB.S */ 13694 DIP("msub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13695 IRExpr *rm = get_IR_roundingmode(); 13696 t1 = newTemp(Ity_F32); 13697 assign(t1, qop(Iop_MSubF32, rm, 13698 getLoFromF64(tyF, getFReg(fmt)), 13699 getLoFromF64(tyF, getFReg(fs)), 13700 getLoFromF64(tyF, getFReg(ft)))); 13701 putFReg(fd, mkWidenFromF32(tyF, mkexpr(t1))); 13702 break; /* MSUB.S */ 13703 } 13704 case 0x29: { /* MSUB.D */ 13705 DIP("msub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13706 IRExpr *rm = get_IR_roundingmode(); 13707 putDReg(fd, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs), 13708 getDReg(ft))); 13709 break; /* MSUB.D */ 13710 } 13711 case 0x30: { /* NMADD.S */ 13712 DIP("nmadd.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13713 IRExpr *rm = get_IR_roundingmode(); 13714 t1 = newTemp(Ity_F32); 13715 assign(t1, qop(Iop_MAddF32, rm, 13716 getLoFromF64(tyF, getFReg(fmt)), 13717 getLoFromF64(tyF, getFReg(fs)), 13718 getLoFromF64(tyF, getFReg(ft)))); 13719 13720 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1)))); 13721 break; /* NMADD.S */ 13722 } 13723 case 0x31: { /* NMADD.D */ 13724 DIP("nmadd.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13725 IRExpr *rm = get_IR_roundingmode(); 13726 t1 = newTemp(Ity_F64); 13727 assign(t1, qop(Iop_MAddF64, rm, getDReg(fmt), getDReg(fs), 13728 getDReg(ft))); 13729 putDReg(fd, unop(Iop_NegF64, mkexpr(t1))); 13730 break; /* NMADD.D */ 13731 } 13732 case 0x38: { /* NMSUBB.S */ 13733 DIP("nmsub.s f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13734 IRExpr *rm = get_IR_roundingmode(); 13735 t1 = newTemp(Ity_F32); 13736 assign(t1, qop(Iop_MSubF32, rm, 13737 getLoFromF64(tyF, getFReg(fmt)), 13738 getLoFromF64(tyF, getFReg(fs)), 13739 getLoFromF64(tyF, getFReg(ft)))); 13740 13741 putFReg(fd, mkWidenFromF32(tyF, unop(Iop_NegF32, mkexpr(t1)))); 13742 break; /* NMSUBB.S */ 13743 } 13744 case 0x39: { /* NMSUBB.D */ 13745 DIP("nmsub.d f%u, f%u, f%u, f%u", fd, fmt, fs, ft); 13746 IRExpr *rm = get_IR_roundingmode(); 13747 t1 = newTemp(Ity_F64); 13748 assign(t1, qop(Iop_MSubF64, rm, getDReg(fmt), getDReg(fs), 13749 getDReg(ft))); 13750 putDReg(fd, unop(Iop_NegF64, mkexpr(t1))); 13751 break; /* NMSUBB.D */ 13752 } 13753 13754 default: 13755 goto decode_failure; 13756 } 13757 break; 13758 13759 case 0x22: /* LWL */ 13760 DIP("lwl r%u, %u(r%u)", rt, imm, rs); 13761 if (mode64) { 13762 /* t1 = addr */ 13763 t1 = newTemp(Ity_I64); 13764 #if defined (_MIPSEL) 13765 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13766 #elif defined (_MIPSEB) 13767 assign(t1, binop(Iop_Xor64, 13768 mkU64(0x03), 13769 binop(Iop_Add64, 13770 getIReg(rs), 13771 mkU64(extend_s_16to64(imm))))); 13772 #endif 13773 /* t2 = word addr */ 13774 /* t4 = addr mod 4 */ 13775 LWX_SWX_PATTERN64; 13776 13777 /* t3 = word content - shifted */ 13778 t3 = newTemp(Ity_I32); 13779 assign(t3, binop(Iop_Shl32, 13780 load(Ity_I32, mkexpr(t2)), 13781 narrowTo(Ity_I8, 13782 binop(Iop_Shl32, 13783 binop(Iop_Sub32, 13784 mkU32(0x03), 13785 mkexpr(t4)), 13786 mkU8(3))))); 13787 13788 /* rt content - adjusted */ 13789 t5 = newTemp(Ity_I32); 13790 assign(t5, binop(Iop_And32, 13791 mkNarrowTo32(ty, getIReg(rt)), 13792 binop(Iop_Shr32, 13793 mkU32(0x00FFFFFF), 13794 narrowTo(Ity_I8, binop(Iop_Mul32, 13795 mkU32(0x08), 13796 mkexpr(t4)))))); 13797 13798 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), 13799 mkexpr(t3)), True)); 13800 } else { 13801 /* t1 = addr */ 13802 t1 = newTemp(Ity_I32); 13803 #if defined (_MIPSEL) 13804 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 13805 #elif defined (_MIPSEB) 13806 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 13807 mkU32(extend_s_16to32(imm))))); 13808 #endif 13809 13810 /* t2 = word addr */ 13811 /* t4 = addr mod 4 */ 13812 LWX_SWX_PATTERN; 13813 13814 /* t3 = word content - shifted */ 13815 t3 = newTemp(Ity_I32); 13816 assign(t3, binop(Iop_Shl32, load(Ity_I32, mkexpr(t2)), narrowTo(Ity_I8, 13817 binop(Iop_Shl32, binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), 13818 mkU8(3))))); 13819 13820 /* rt content - adjusted */ 13821 t5 = newTemp(Ity_I32); 13822 assign(t5, binop(Iop_And32, 13823 getIReg(rt), 13824 binop(Iop_Shr32, 13825 mkU32(0x00FFFFFF), 13826 narrowTo(Ity_I8, binop(Iop_Mul32, 13827 mkU32(0x08), 13828 mkexpr(t4)))))); 13829 13830 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 13831 } 13832 break; 13833 13834 case 0x26: /* LWR */ 13835 DIP("lwr r%u, %u(r%u)", rt, imm, rs); 13836 if (mode64) { 13837 /* t1 = addr */ 13838 t1 = newTemp(Ity_I64); 13839 #if defined (_MIPSEL) 13840 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13841 #elif defined (_MIPSEB) 13842 assign(t1, binop(Iop_Xor64, 13843 mkU64(0x3), 13844 binop(Iop_Add64, 13845 getIReg(rs), 13846 mkU64(extend_s_16to64(imm))))); 13847 #endif 13848 /* t2 = word addr */ 13849 /* t4 = addr mod 4 */ 13850 LWX_SWX_PATTERN64; 13851 13852 /* t3 = word content - shifted */ 13853 t3 = newTemp(Ity_I32); 13854 assign(t3, binop(Iop_Shr32, 13855 load(Ity_I32, mkexpr(t2)), 13856 narrowTo(Ity_I8, 13857 binop(Iop_Shl32, mkexpr(t4), mkU8(0x03))))); 13858 13859 /* rt content - adjusted */ 13860 t5 = newTemp(Ity_I32); 13861 assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)), 13862 unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF), 13863 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 13864 13865 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5), 13866 mkexpr(t3)), True)); 13867 13868 } else { 13869 /* t1 = addr */ 13870 t1 = newTemp(Ity_I32); 13871 #if defined (_MIPSEL) 13872 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 13873 #elif defined (_MIPSEB) 13874 assign(t1, binop(Iop_Xor32, mkU32(0x3), binop(Iop_Add32, getIReg(rs), 13875 mkU32(extend_s_16to32(imm))))); 13876 #endif 13877 13878 /* t2 = word addr */ 13879 /* t4 = addr mod 4 */ 13880 LWX_SWX_PATTERN; 13881 13882 /* t3 = word content - shifted */ 13883 t3 = newTemp(Ity_I32); 13884 assign(t3, binop(Iop_Shr32, load(Ity_I32, mkexpr(t2)), 13885 narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), 13886 mkU8(3))))); 13887 13888 /* rt content - adjusted */ 13889 t5 = newTemp(Ity_I32); 13890 assign(t5, binop(Iop_And32, getIReg(rt), unop(Iop_Not32, 13891 binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8, 13892 binop(Iop_Shl32, mkexpr(t4), mkU8(0x3))))))); 13893 13894 putIReg(rt, binop(Iop_Or32, mkexpr(t5), mkexpr(t3))); 13895 } 13896 break; 13897 13898 case 0x2B: /* SW */ 13899 DIP("sw r%u, %u(r%u)", rt, imm, rs); 13900 LOAD_STORE_PATTERN; 13901 store(mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))); 13902 break; 13903 13904 case 0x2C: { /* SDL rt, offset(base) MIPS64 */ 13905 DIP("sdl r%u, %u(r%u)", rt, imm, rs); 13906 vassert(mode64); 13907 IRTemp A_byte = newTemp(Ity_I8); 13908 IRTemp B_byte = newTemp(Ity_I8); 13909 IRTemp C_byte = newTemp(Ity_I8); 13910 IRTemp D_byte = newTemp(Ity_I8); 13911 IRTemp E_byte = newTemp(Ity_I8); 13912 IRTemp F_byte = newTemp(Ity_I8); 13913 IRTemp G_byte = newTemp(Ity_I8); 13914 IRTemp H_byte = newTemp(Ity_I8); 13915 IRTemp B_pos = newTemp(Ity_I64); 13916 IRTemp C_pos = newTemp(Ity_I64); 13917 IRTemp D_pos = newTemp(Ity_I64); 13918 IRTemp E_pos = newTemp(Ity_I64); 13919 IRTemp F_pos = newTemp(Ity_I64); 13920 IRTemp G_pos = newTemp(Ity_I64); 13921 13922 /* H byte */ 13923 assign(H_byte, getByteFromReg(rt, 0)); 13924 /* G byte */ 13925 assign(G_byte, getByteFromReg(rt, 1)); 13926 /* F byte */ 13927 assign(F_byte, getByteFromReg(rt, 2)); 13928 /* E byte */ 13929 assign(E_byte, getByteFromReg(rt, 3)); 13930 /* D byte */ 13931 assign(D_byte, getByteFromReg(rt, 4)); 13932 /* C byte */ 13933 assign(C_byte, getByteFromReg(rt, 5)); 13934 /* B byte */ 13935 assign(B_byte, getByteFromReg(rt, 6)); 13936 /* A byte */ 13937 assign(A_byte, getByteFromReg(rt, 7)); 13938 13939 /* t1 = addr */ 13940 t1 = newTemp(Ity_I64); 13941 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 13942 13943 /* t2 = word addr */ 13944 t2 = newTemp(Ity_I64); 13945 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); 13946 13947 /* t3 = addr mod 7 */ 13948 t3 = newTemp(Ity_I64); 13949 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 13950 13951 #if defined (_MIPSEL) 13952 /* Calculate X_byte position. */ 13953 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x1)), 13954 mkU64(0x0), 13955 mkU64(0x1))); 13956 13957 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x2)), 13958 mkU64(0x0), 13959 mkU64(0x2))); 13960 13961 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)), 13962 mkU64(0x0), 13963 mkU64(0x3))); 13964 13965 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)), 13966 mkU64(0x0), 13967 mkU64(0x4))); 13968 13969 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)), 13970 mkU64(0x0), 13971 mkU64(0x5))); 13972 13973 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 13974 mkU64(0x1), 13975 mkU64(0x0))); 13976 13977 /* Store X_byte on the right place. */ 13978 store(mkexpr(t2), mkexpr(H_byte)); 13979 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 13980 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 13981 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 13982 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 13983 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 13984 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 13985 store(mkexpr(t1), mkexpr(A_byte)); 13986 13987 #else /* _MIPSEB */ 13988 /* Calculate X_byte position. */ 13989 assign(B_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 13990 mkU64(0x0), 13991 mkU64(0x1))); 13992 13993 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x6)), 13994 mkU64(0x2), 13995 mkU64(0x0))); 13996 13997 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x5)), 13998 mkU64(0x3), 13999 mkU64(0x0))); 14000 14001 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x4)), 14002 mkU64(0x4), 14003 mkU64(0x0))); 14004 14005 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkexpr(t3), mkU64(0x3)), 14006 mkU64(0x5), 14007 mkU64(0x0))); 14008 14009 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14010 mkU64(0x6), 14011 mkU64(0x7))); 14012 14013 /* Store X_byte on the right place. */ 14014 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(H_byte)); 14015 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14016 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14017 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14018 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14019 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14020 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14021 store(mkexpr(t1), mkexpr(A_byte)); 14022 #endif 14023 14024 break; 14025 } 14026 14027 case 0x2D: { 14028 /* SDR rt, offset(base) - MIPS64 */ 14029 vassert(mode64); 14030 DIP("sdr r%u, %u(r%u)", rt, imm, rs); 14031 IRTemp A_byte = newTemp(Ity_I8); 14032 IRTemp B_byte = newTemp(Ity_I8); 14033 IRTemp C_byte = newTemp(Ity_I8); 14034 IRTemp D_byte = newTemp(Ity_I8); 14035 IRTemp E_byte = newTemp(Ity_I8); 14036 IRTemp F_byte = newTemp(Ity_I8); 14037 IRTemp G_byte = newTemp(Ity_I8); 14038 IRTemp H_byte = newTemp(Ity_I8); 14039 IRTemp B_pos = newTemp(Ity_I64); 14040 IRTemp C_pos = newTemp(Ity_I64); 14041 IRTemp D_pos = newTemp(Ity_I64); 14042 IRTemp E_pos = newTemp(Ity_I64); 14043 IRTemp F_pos = newTemp(Ity_I64); 14044 IRTemp G_pos = newTemp(Ity_I64); 14045 14046 /* H byte */ 14047 assign(H_byte, getByteFromReg(rt, 0)); 14048 /* G byte */ 14049 assign(G_byte, getByteFromReg(rt, 1)); 14050 /* F byte */ 14051 assign(F_byte, getByteFromReg(rt, 2)); 14052 /* E byte */ 14053 assign(E_byte, getByteFromReg(rt, 3)); 14054 /* D byte */ 14055 assign(D_byte, getByteFromReg(rt, 4)); 14056 /* C byte */ 14057 assign(C_byte, getByteFromReg(rt, 5)); 14058 /* B byte */ 14059 assign(B_byte, getByteFromReg(rt, 6)); 14060 /* A byte */ 14061 assign(A_byte, getByteFromReg(rt, 7)); 14062 14063 /* t1 = addr */ 14064 t1 = newTemp(Ity_I64); 14065 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14066 14067 /* t2 = word addr */ 14068 t2 = newTemp(Ity_I64); 14069 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); 14070 14071 /* t3 = addr mod 7 */ 14072 t3 = newTemp(Ity_I64); 14073 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 14074 14075 #if defined (_MIPSEL) 14076 /* Calculate X_byte position. */ 14077 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)), 14078 mkU64(0x0), 14079 mkU64(0x6))); 14080 14081 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)), 14082 mkU64(0x0), 14083 mkU64(0x5))); 14084 14085 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)), 14086 mkU64(0x0), 14087 mkU64(0x4))); 14088 14089 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)), 14090 mkU64(0x0), 14091 mkU64(0x3))); 14092 14093 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)), 14094 mkU64(0x0), 14095 mkU64(0x2))); 14096 14097 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x7)), 14098 mkU64(0x0), 14099 mkU64(0x1))); 14100 14101 /* Store X_byte on the right place. */ 14102 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x7)), mkexpr(A_byte)); 14103 store(binop(Iop_Add64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14104 store(binop(Iop_Add64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14105 store(binop(Iop_Add64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14106 store(binop(Iop_Add64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14107 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14108 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14109 store(mkexpr(t1), mkexpr(H_byte)); 14110 14111 #else /* _MIPSEB */ 14112 /* Calculate X_byte position. */ 14113 assign(B_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x5), mkexpr(t3)), 14114 mkU64(0x6), 14115 mkU64(0x0))); 14116 14117 assign(C_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x4), mkexpr(t3)), 14118 mkU64(0x5), 14119 mkU64(0x0))); 14120 14121 assign(D_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x3), mkexpr(t3)), 14122 mkU64(0x4), 14123 mkU64(0x0))); 14124 14125 assign(E_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x2), mkexpr(t3)), 14126 mkU64(0x3), 14127 mkU64(0x0))); 14128 14129 assign(F_pos, IRExpr_ITE(binop(Iop_CmpLT64U, mkU64(0x1), mkexpr(t3)), 14130 mkU64(0x2), 14131 mkU64(0x0))); 14132 14133 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14134 mkU64(0x0), 14135 mkU64(0x1))); 14136 14137 /* Store X_byte on the right place. */ 14138 store(mkexpr(t2), mkexpr(A_byte)); 14139 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(B_pos)), mkexpr(B_byte)); 14140 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(C_pos)), mkexpr(C_byte)); 14141 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(D_pos)), mkexpr(D_byte)); 14142 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(E_pos)), mkexpr(E_byte)); 14143 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14144 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14145 store(mkexpr(t1), mkexpr(H_byte)); 14146 #endif 14147 break; 14148 } 14149 14150 case 0x28: /* SB */ 14151 DIP("sb r%u, %u(r%u)", rt, imm, rs); 14152 LOAD_STORE_PATTERN; 14153 store(mkexpr(t1), narrowTo(Ity_I8, getIReg(rt))); 14154 break; 14155 14156 case 0x29: /* SH */ 14157 DIP("sh r%u, %u(r%u)", rt, imm, rs); 14158 LOAD_STORE_PATTERN; 14159 store(mkexpr(t1), narrowTo(Ity_I16, getIReg(rt))); 14160 break; 14161 14162 case 0x2A: /* SWL */ 14163 DIP("swl r%u, %u(r%u)", rt, imm, rs); 14164 if (mode64) { 14165 IRTemp E_byte = newTemp(Ity_I8); 14166 IRTemp F_byte = newTemp(Ity_I8); 14167 IRTemp G_byte = newTemp(Ity_I8); 14168 IRTemp H_byte = newTemp(Ity_I8); 14169 IRTemp F_pos = newTemp(Ity_I64); 14170 IRTemp G_pos = newTemp(Ity_I64); 14171 14172 /* H byte */ 14173 assign(H_byte, getByteFromReg(rt, 0)); 14174 /* G byte */ 14175 assign(G_byte, getByteFromReg(rt, 1)); 14176 /* F byte */ 14177 assign(F_byte, getByteFromReg(rt, 2)); 14178 /* E byte */ 14179 assign(E_byte, getByteFromReg(rt, 3)); 14180 14181 /* t1 = addr */ 14182 t1 = newTemp(Ity_I64); 14183 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14184 14185 /* t2 = word addr */ 14186 t2 = newTemp(Ity_I64); 14187 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); 14188 14189 /* t3 = addr mod 4 */ 14190 t3 = newTemp(Ity_I64); 14191 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3))); 14192 14193 #if defined (_MIPSEL) 14194 /* Calculate X_byte position. */ 14195 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14196 mkU64(0x0), 14197 mkU64(0x1))); 14198 14199 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14200 mkU64(0x1), 14201 mkU64(0x0))); 14202 14203 /* Store X_byte on the right place. */ 14204 store(mkexpr(t2), mkexpr(H_byte)); 14205 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14206 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14207 store(mkexpr(t1), mkexpr(E_byte)); 14208 14209 #else /* _MIPSEB */ 14210 /* Calculate X_byte position. */ 14211 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14212 mkU64(0x0), 14213 mkU64(0x1))); 14214 14215 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14216 mkU64(0x2), 14217 mkU64(0x3))); 14218 14219 store(binop(Iop_Add64, mkexpr(t2), mkU64(3)), mkexpr(H_byte)); 14220 store(binop(Iop_Add64, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14221 store(binop(Iop_Add64, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14222 store(mkexpr(t1), mkexpr(E_byte)); 14223 14224 #endif 14225 } else { 14226 IRTemp E_byte = newTemp(Ity_I8); 14227 IRTemp F_byte = newTemp(Ity_I8); 14228 IRTemp G_byte = newTemp(Ity_I8); 14229 IRTemp H_byte = newTemp(Ity_I8); 14230 IRTemp F_pos = newTemp(Ity_I32); 14231 IRTemp G_pos = newTemp(Ity_I32); 14232 14233 /* H byte */ 14234 assign(H_byte, getByteFromReg(rt, 0)); 14235 /* G byte */ 14236 assign(G_byte, getByteFromReg(rt, 1)); 14237 /* F byte */ 14238 assign(F_byte, getByteFromReg(rt, 2)); 14239 /* E byte */ 14240 assign(E_byte, getByteFromReg(rt, 3)); 14241 14242 /* t1 = addr */ 14243 t1 = newTemp(Ity_I32); 14244 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 14245 14246 /* t2 = word addr */ 14247 t2 = newTemp(Ity_I32); 14248 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL))); 14249 14250 /* t3 = addr mod 4 */ 14251 t3 = newTemp(Ity_I32); 14252 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3))); 14253 14254 #if defined (_MIPSEL) 14255 /* Calculate X_byte position. */ 14256 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14257 mkU32(0x0), 14258 mkU32(0x1))); 14259 14260 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14261 mkU32(0x1), 14262 mkU32(0x0))); 14263 14264 /* Store X_byte on the right place. */ 14265 store(mkexpr(t2), mkexpr(H_byte)); 14266 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14267 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14268 store(mkexpr(t1), mkexpr(E_byte)); 14269 14270 #else /* _MIPSEB */ 14271 /* Calculate X_byte position. */ 14272 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14273 mkU32(0x0), 14274 mkU32(0x1))); 14275 14276 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14277 mkU32(0x2), 14278 mkU32(0x3))); 14279 14280 store(binop(Iop_Add32, mkexpr(t2), mkU32(3)), mkexpr(H_byte)); 14281 store(binop(Iop_Add32, mkexpr(t2), mkexpr(G_pos)), mkexpr(G_byte)); 14282 store(binop(Iop_Add32, mkexpr(t1), mkexpr(F_pos)), mkexpr(F_byte)); 14283 store(mkexpr(t1), mkexpr(E_byte)); 14284 14285 #endif 14286 } 14287 break; 14288 14289 case 0x2E: /* SWR */ 14290 DIP("swr r%u, %u(r%u)", rt, imm, rs); 14291 if (mode64) { 14292 IRTemp E_byte = newTemp(Ity_I8); 14293 IRTemp F_byte = newTemp(Ity_I8); 14294 IRTemp G_byte = newTemp(Ity_I8); 14295 IRTemp H_byte = newTemp(Ity_I8); 14296 IRTemp F_pos = newTemp(Ity_I64); 14297 IRTemp G_pos = newTemp(Ity_I64); 14298 14299 /* H byte */ 14300 assign(H_byte, getByteFromReg(rt, 0)); 14301 /* G byte */ 14302 assign(G_byte, getByteFromReg(rt, 1)); 14303 /* F byte */ 14304 assign(F_byte, getByteFromReg(rt, 2)); 14305 /* E byte */ 14306 assign(E_byte, getByteFromReg(rt, 3)); 14307 14308 /* t1 = addr */ 14309 t1 = newTemp(Ity_I64); 14310 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 14311 14312 /* t2 = word addr */ 14313 t2 = newTemp(Ity_I64); 14314 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); 14315 14316 /* t3 = addr mod 4 */ 14317 t3 = newTemp(Ity_I64); 14318 assign(t3, binop(Iop_And64, mkexpr(t1), mkU64(0x3))); 14319 14320 #if defined (_MIPSEL) 14321 /* Calculate X_byte position. */ 14322 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14323 mkU64(0x2), 14324 mkU64(0x3))); 14325 14326 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14327 mkU64(0x0), 14328 mkU64(0x1))); 14329 14330 /* Store X_byte on the right place. */ 14331 store(binop(Iop_Add64, mkexpr(t2), mkU64(0x3)), mkexpr(E_byte)); 14332 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14333 store(binop(Iop_Add64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14334 store(mkexpr(t1), mkexpr(H_byte)); 14335 14336 #else /* _MIPSEB */ 14337 /* Calculate X_byte position. */ 14338 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x3)), 14339 mkU64(0x1), 14340 mkU64(0x0))); 14341 14342 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ64, mkexpr(t3), mkU64(0x0)), 14343 mkU64(0x0), 14344 mkU64(0x1))); 14345 14346 /* Store X_byte on the right place. */ 14347 store(mkexpr(t2), mkexpr(E_byte)); 14348 store(binop(Iop_Add64, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14349 store(binop(Iop_Sub64, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14350 store(mkexpr(t1), mkexpr(H_byte)); 14351 #endif 14352 } else { 14353 IRTemp E_byte = newTemp(Ity_I8); 14354 IRTemp F_byte = newTemp(Ity_I8); 14355 IRTemp G_byte = newTemp(Ity_I8); 14356 IRTemp H_byte = newTemp(Ity_I8); 14357 IRTemp F_pos = newTemp(Ity_I32); 14358 IRTemp G_pos = newTemp(Ity_I32); 14359 14360 /* H byte */ 14361 assign(H_byte, getByteFromReg(rt, 0)); 14362 /* G byte */ 14363 assign(G_byte, getByteFromReg(rt, 1)); 14364 /* F byte */ 14365 assign(F_byte, getByteFromReg(rt, 2)); 14366 /* E byte */ 14367 assign(E_byte, getByteFromReg(rt, 3)); 14368 14369 /* t1 = addr */ 14370 t1 = newTemp(Ity_I32); 14371 assign(t1, binop(Iop_Add32, getIReg(rs), mkU32(extend_s_16to32(imm)))); 14372 14373 /* t2 = word addr */ 14374 t2 = newTemp(Ity_I32); 14375 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFCULL))); 14376 14377 /* t3 = addr mod 4 */ 14378 t3 = newTemp(Ity_I32); 14379 assign(t3, binop(Iop_And32, mkexpr(t1), mkU32(0x3))); 14380 14381 #if defined (_MIPSEL) 14382 /* Calculate X_byte position. */ 14383 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14384 mkU32(0x2), 14385 mkU32(0x3))); 14386 14387 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14388 mkU32(0x0), 14389 mkU32(0x1))); 14390 14391 /* Store X_byte on the right place. */ 14392 store(binop(Iop_Add32, mkexpr(t2), mkU32(0x3)), mkexpr(E_byte)); 14393 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14394 store(binop(Iop_Add32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14395 store(mkexpr(t1), mkexpr(H_byte)); 14396 14397 #else /* _MIPSEB */ 14398 /* Calculate X_byte position. */ 14399 assign(F_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x3)), 14400 mkU32(0x1), 14401 mkU32(0x0))); 14402 14403 assign(G_pos, IRExpr_ITE(binop(Iop_CmpEQ32, mkexpr(t3), mkU32(0x0)), 14404 mkU32(0x0), 14405 mkU32(0x1))); 14406 14407 /* Store X_byte on the right place. */ 14408 store(mkexpr(t2), mkexpr(E_byte)); 14409 store(binop(Iop_Add32, mkexpr(t2), mkexpr(F_pos)), mkexpr(F_byte)); 14410 store(binop(Iop_Sub32, mkexpr(t1), mkexpr(G_pos)), mkexpr(G_byte)); 14411 store(mkexpr(t1), mkexpr(H_byte)); 14412 #endif 14413 } 14414 break; 14415 14416 case 0x1C: /* Special2 */ 14417 switch (function) { 14418 /* Cavium Specific instructions */ 14419 case 0x03: case 0x32: case 0x33: /* DMUL, CINS , CINS32 */ 14420 case 0x3A: case 0x3B: case 0x2B: /* EXT, EXT32, SNE */ 14421 /* CVM Compare Instructions */ 14422 case 0x2A: case 0x2E: case 0x2F: /* SEQ, SEQI, SNEI */ 14423 /* CPU Load, Store, Memory, and Control Instructions */ 14424 case 0x18: case 0x19: /* SAA, SAAD */ 14425 case 0x1F: /* LAA, LAAD, LAI, LAID */ 14426 case 0x28: case 0x2C: case 0x2D: /* BADDU, POP, DPOP */ 14427 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 14428 if (dis_instr_CVM(cins)) 14429 break; 14430 goto decode_failure; 14431 } else { 14432 goto decode_failure; 14433 } 14434 break; 14435 14436 case 0x02: { /* MUL */ 14437 DIP("mul r%u, r%u, r%u", rd, rs, rt); 14438 if (mode64) { 14439 IRTemp tmpRs32 = newTemp(Ity_I32); 14440 IRTemp tmpRt32 = newTemp(Ity_I32); 14441 IRTemp tmpRes = newTemp(Ity_I32); 14442 14443 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14444 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 14445 assign(tmpRes, binop(Iop_Mul32, 14446 mkexpr(tmpRs32), mkexpr(tmpRt32))); 14447 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpRes), True)); 14448 } else 14449 putIReg(rd, binop(Iop_Mul32, getIReg(rs), getIReg(rt))); 14450 break; 14451 } 14452 14453 case 0x00: { /* MADD */ 14454 if (mode64) { 14455 DIP("madd r%u, r%u", rs, rt); 14456 t1 = newTemp(Ity_I32); 14457 t2 = newTemp(Ity_I32); 14458 t3 = newTemp(Ity_I64); 14459 t4 = newTemp(Ity_I64); 14460 t5 = newTemp(Ity_I64); 14461 t6 = newTemp(Ity_I32); 14462 14463 assign(t1, mkNarrowTo32(ty, getHI())); 14464 assign(t2, mkNarrowTo32(ty, getLO())); 14465 14466 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 14467 mkNarrowTo32(ty, getIReg(rt)))); 14468 14469 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14470 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4))); 14471 14472 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14473 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14474 } else { 14475 if ( (1 <= ac) && ( 3 >= ac) ) { 14476 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14477 /* If DSP is present -> DSP ASE MADD */ 14478 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14479 if (0 != retVal ) { 14480 goto decode_failure_dsp; 14481 } 14482 break; 14483 } else { 14484 goto decode_failure_dsp; 14485 } 14486 } else { 14487 DIP("madd r%u, r%u", rs, rt); 14488 t1 = newTemp(Ity_I32); 14489 t2 = newTemp(Ity_I32); 14490 t3 = newTemp(Ity_I64); 14491 t4 = newTemp(Ity_I32); 14492 t5 = newTemp(Ity_I32); 14493 t6 = newTemp(Ity_I32); 14494 14495 assign(t1, getHI()); 14496 assign(t2, getLO()); 14497 14498 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 14499 14500 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 14501 mkexpr(t3)))); 14502 14503 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 14504 unop(Iop_64to32, mkexpr(t3))))); 14505 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 14506 14507 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, 14508 mkexpr(t3)))); 14509 putLO(mkexpr(t4)); 14510 break; 14511 } 14512 } 14513 break; 14514 } 14515 14516 case 0x01: { /* MADDU */ 14517 if (mode64) { 14518 DIP("maddu r%u, r%u", rs, rt); 14519 t1 = newTemp(Ity_I32); 14520 t2 = newTemp(Ity_I32); 14521 t3 = newTemp(Ity_I64); 14522 t4 = newTemp(Ity_I64); 14523 t5 = newTemp(Ity_I64); 14524 t6 = newTemp(Ity_I32); 14525 14526 assign(t1, mkNarrowTo32(ty, getHI())); 14527 assign(t2, mkNarrowTo32(ty, getLO())); 14528 14529 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 14530 mkNarrowTo32(ty, getIReg(rt)))); 14531 14532 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14533 assign(t5, binop(Iop_Add64, mkexpr(t3), mkexpr(t4))); 14534 14535 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14536 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14537 } else { 14538 if ( (1 <= ac) && ( 3 >= ac) ) { 14539 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14540 /* If DSP is present -> DSP ASE MADDU */ 14541 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14542 if (0 != retVal ) { 14543 goto decode_failure_dsp; 14544 } 14545 break; 14546 } else { 14547 goto decode_failure_dsp; 14548 } 14549 } else { 14550 DIP("maddu r%u, r%u", rs, rt); 14551 t1 = newTemp(Ity_I32); 14552 t2 = newTemp(Ity_I32); 14553 t3 = newTemp(Ity_I64); 14554 t4 = newTemp(Ity_I32); 14555 t5 = newTemp(Ity_I32); 14556 t6 = newTemp(Ity_I32); 14557 14558 assign(t1, getHI()); 14559 assign(t2, getLO()); 14560 14561 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 14562 14563 assign(t4, binop(Iop_Add32, mkexpr(t2), unop(Iop_64to32, 14564 mkexpr(t3)))); 14565 assign(t5, unop(Iop_1Uto32, binop(Iop_CmpLT32U, mkexpr(t4), 14566 unop(Iop_64to32, mkexpr(t3))))); 14567 assign(t6, binop(Iop_Add32, mkexpr(t5), mkexpr(t1))); 14568 14569 putHI(binop(Iop_Add32, mkexpr(t6), unop(Iop_64HIto32, 14570 mkexpr(t3)))); 14571 putLO(mkexpr(t4)); 14572 break; 14573 } 14574 } 14575 break; 14576 } 14577 14578 case 0x04: { /* MSUB */ 14579 if (mode64) { 14580 DIP("msub r%u, r%u", rs, rt); 14581 t1 = newTemp(Ity_I32); 14582 t2 = newTemp(Ity_I32); 14583 t3 = newTemp(Ity_I64); 14584 t4 = newTemp(Ity_I64); 14585 t5 = newTemp(Ity_I64); 14586 t6 = newTemp(Ity_I32); 14587 14588 assign(t1, mkNarrowTo32(ty, getHI())); 14589 assign(t2, mkNarrowTo32(ty, getLO())); 14590 14591 assign(t3, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 14592 mkNarrowTo32(ty, getIReg(rt)))); 14593 14594 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14595 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3))); 14596 14597 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14598 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14599 } else { 14600 if ( (1 <= ac) && ( 3 >= ac) ) { 14601 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14602 /* If DSP is present -> DSP ASE MSUB */ 14603 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14604 if (0 != retVal ) { 14605 goto decode_failure_dsp; 14606 } 14607 break; 14608 } else { 14609 goto decode_failure_dsp; 14610 } 14611 } else { 14612 DIP("msub r%u, r%u", rs, rt); 14613 t1 = newTemp(Ity_I32); 14614 t2 = newTemp(Ity_I32); 14615 t3 = newTemp(Ity_I64); 14616 t4 = newTemp(Ity_I32); 14617 t5 = newTemp(Ity_I1); 14618 t6 = newTemp(Ity_I32); 14619 14620 assign(t1, getHI()); 14621 assign(t2, getLO()); 14622 14623 assign(t3, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 14624 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */ 14625 14626 /* if lo<lo(mul) hi = hi - 1 */ 14627 assign(t5, binop(Iop_CmpLT32U, 14628 mkexpr(t2), 14629 mkexpr(t4))); 14630 14631 assign(t6, IRExpr_ITE(mkexpr(t5), 14632 binop(Iop_Sub32, mkexpr(t1), mkU32(0x1)), 14633 mkexpr(t1))); 14634 14635 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, 14636 mkexpr(t3)))); 14637 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 14638 break; 14639 } 14640 } 14641 break; 14642 } 14643 14644 case 0x05: { /* MSUBU */ 14645 if (mode64) { 14646 DIP("msubu r%u, r%u", rs, rt); 14647 t1 = newTemp(Ity_I32); 14648 t2 = newTemp(Ity_I32); 14649 t3 = newTemp(Ity_I64); 14650 t4 = newTemp(Ity_I64); 14651 t5 = newTemp(Ity_I64); 14652 t6 = newTemp(Ity_I32); 14653 14654 assign(t1, mkNarrowTo32(ty, getHI())); 14655 assign(t2, mkNarrowTo32(ty, getLO())); 14656 14657 assign(t3, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 14658 mkNarrowTo32(ty, getIReg(rt)))); 14659 14660 assign(t4, binop(Iop_32HLto64, mkexpr(t1), mkexpr(t2))); 14661 assign(t5, binop(Iop_Sub64, mkexpr(t4), mkexpr(t3))); 14662 14663 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t5)), True)); 14664 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t5)), True)); 14665 } else { 14666 if ( (1 <= ac) && ( 3 >= ac) ) { 14667 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 14668 /* If DSP is present -> DSP ASE MSUBU */ 14669 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 14670 if (0 != retVal ) { 14671 goto decode_failure_dsp; 14672 } 14673 break; 14674 } else { 14675 goto decode_failure_dsp; 14676 } 14677 } else { 14678 DIP("msubu r%u, r%u", rs, rt); 14679 t1 = newTemp(Ity_I32); 14680 t2 = newTemp(Ity_I32); 14681 t3 = newTemp(Ity_I64); 14682 t4 = newTemp(Ity_I32); 14683 t5 = newTemp(Ity_I1); 14684 t6 = newTemp(Ity_I32); 14685 14686 assign(t1, getHI()); 14687 assign(t2, getLO()); 14688 14689 assign(t3, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 14690 assign(t4, unop(Iop_64to32, mkexpr(t3))); /* new lo */ 14691 14692 /* if lo<lo(mul) hi = hi - 1 */ 14693 assign(t5, binop(Iop_CmpLT32U, 14694 mkexpr(t2), 14695 mkexpr(t4))); 14696 14697 assign(t6, IRExpr_ITE(mkexpr(t5), 14698 binop(Iop_Sub32, 14699 mkexpr(t1), 14700 mkU32(0x1)), 14701 mkexpr(t1))); 14702 14703 putHI(binop(Iop_Sub32, mkexpr(t6), unop(Iop_64HIto32, 14704 mkexpr(t3)))); 14705 putLO(binop(Iop_Sub32, mkexpr(t2), mkexpr(t4))); 14706 break; 14707 } 14708 } 14709 break; 14710 } 14711 14712 case 0x6: /* dmul MIPS64 - Netlogic */ 14713 DIP("dmul r%u, r%u, r%u", rd, rs, rt); 14714 t0 = newTemp(Ity_I128); 14715 14716 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt))); 14717 14718 putIReg(rd, unop(Iop_128to64, mkexpr(t0))); 14719 break; 14720 14721 case 0x10: /* LDADDW - Swap Word - Netlogic */ 14722 DIP("ldaddw r%u, r%u", rt, rs); 14723 t0 = newTemp(Ity_I32); 14724 t1 = newTemp(Ity_I32); 14725 t2 = newTemp(Ity_I32); 14726 t3 = newTemp(Ity_I64); 14727 t4 = newTemp(Ity_I32); 14728 t5 = newTemp(Ity_I32); 14729 t6 = newTemp(Ity_I32); 14730 14731 /* v = GPR[rt] */ 14732 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 14733 14734 /* GPR[rt] = memory[base]; */ 14735 assign(t1, load(Ity_I32, getIReg(rs))); 14736 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 14737 14738 /* memory[base] = memory[base] + v; */ 14739 store(getIReg(rs), binop(Iop_Add32, mkexpr(t0), mkexpr(t1))); 14740 break; 14741 14742 case 0x12: /* LDADDD - Swap Word - Netlogic */ 14743 DIP("ldaddw r%u, r%u", rt, rs); 14744 t0 = newTemp(Ity_I64); 14745 t1 = newTemp(Ity_I64); 14746 14747 /* v = GPR[rt] */ 14748 assign(t0, getIReg(rt)); 14749 14750 /* GPR[rt] = memory[base]; */ 14751 assign(t1, load(Ity_I64, getIReg(rs))); 14752 putIReg(rt, mkexpr(t1)); 14753 14754 /* memory[base] = memory[base] + v; */ 14755 store(getIReg(rs), binop(Iop_Add64, mkexpr(t0), mkexpr(t1))); 14756 break; 14757 14758 case 0x14: /* SWAPW - Swap Word - Netlogic */ 14759 DIP("swapw r%u, r%u", rt, rs); 14760 t0 = newTemp(Ity_I32); 14761 t1 = newTemp(Ity_I32); 14762 assign(t0, mkNarrowTo32(ty, getIReg(rt))); 14763 assign(t1, load(Ity_I32, getIReg(rs))); 14764 putIReg(rt, mkWidenFrom32(ty, mkexpr(t1), True)); 14765 store(getIReg(rs), mkexpr(t0)); 14766 break; 14767 14768 case 0x16: /* SWAPD - Swap Double - Netlogic */ 14769 DIP("swapw r%u, r%u", rt, rs); 14770 t0 = newTemp(Ity_I64); 14771 t1 = newTemp(Ity_I64); 14772 assign(t0, getIReg(rt)); 14773 assign(t1, load(Ity_I64, getIReg(rs))); 14774 putIReg(rt, mkexpr(t1)); 14775 store(getIReg(rs), mkexpr(t0)); 14776 break; 14777 14778 case 0x20: { /* CLZ */ 14779 DIP("clz r%u, r%u", rd, rs); 14780 if (mode64) { 14781 IRTemp tmpClz32 = newTemp(Ity_I32); 14782 IRTemp tmpRs32 = newTemp(Ity_I32); 14783 14784 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14785 assign(tmpClz32, unop(Iop_Clz32, mkexpr(tmpRs32))); 14786 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClz32), True)); 14787 } else { 14788 t1 = newTemp(Ity_I1); 14789 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0))); 14790 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14791 mkU32(0x00000020), 14792 unop(Iop_Clz32, getIReg(rs)))); 14793 } 14794 break; 14795 } 14796 14797 case 0x21: { /* CLO */ 14798 DIP("clo r%u, r%u", rd, rs); 14799 if (mode64) { 14800 IRTemp tmpClo32 = newTemp(Ity_I32); 14801 IRTemp tmpRs32 = newTemp(Ity_I32); 14802 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 14803 14804 t1 = newTemp(Ity_I1); 14805 assign(t1, binop(Iop_CmpEQ32, mkexpr(tmpRs32), mkU32(0xffffffff))); 14806 assign(tmpClo32, IRExpr_ITE(mkexpr(t1), 14807 mkU32(0x00000020), 14808 unop(Iop_Clz32, unop(Iop_Not32, mkexpr(tmpRs32))))); 14809 14810 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpClo32), True)); 14811 break; 14812 } else { 14813 t1 = newTemp(Ity_I1); 14814 assign(t1, binop(Iop_CmpEQ32, getIReg(rs), mkU32(0xffffffff))); 14815 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14816 mkU32(0x00000020), 14817 unop(Iop_Clz32, 14818 unop(Iop_Not32, getIReg(rs))))); 14819 break; 14820 } 14821 } 14822 14823 case 0x24: /* Count Leading Zeros in Doubleword - DCLZ; MIPS64 */ 14824 DIP("dclz r%u, r%u", rd, rs); 14825 t1 = newTemp(Ity_I1); 14826 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), mkU64(0))); 14827 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14828 mkU64(0x00000040), 14829 unop(Iop_Clz64, getIReg(rs)))); 14830 break; 14831 14832 case 0x25: /* Count Leading Ones in Doubleword - DCLO; MIPS64 */ 14833 DIP("dclo r%u, r%u", rd, rs); 14834 t1 = newTemp(Ity_I1); 14835 assign(t1, binop(Iop_CmpEQ64, getIReg(rs), 14836 mkU64(0xffffffffffffffffULL))); 14837 putIReg(rd, IRExpr_ITE(mkexpr(t1), 14838 mkU64(0x40), 14839 unop(Iop_Clz64, unop(Iop_Not64, 14840 getIReg(rs))))); 14841 break; 14842 14843 default: 14844 goto decode_failure; 14845 } 14846 break; 14847 14848 case 0x1F: /* Special3 */ 14849 switch (function) { 14850 case 0x01: { 14851 /* Doubleword Extract Bit Field - DEXTM; MIPS64r2 */ 14852 msb = get_msb(cins); 14853 lsb = get_lsb(cins); 14854 size = msb + 1; 14855 UInt srcPos = lsb; 14856 UInt dstSz = msb + 33; 14857 t1 = newTemp(Ity_I64); 14858 DIP("dextm r%u, r%u, %u, %u", rt, rs, lsb, msb + 1); 14859 14860 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */ 14861 UChar rsAmt = 64 - dstSz; /* right shift amount; */ 14862 14863 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 14864 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 14865 14866 break; 14867 } 14868 case 0x02: { 14869 /* Doubleword Extract Bit Field Upper - DEXTU; MIPS64r2 */ 14870 msb = get_msb(cins); 14871 lsb = get_lsb(cins); 14872 size = msb + 1; 14873 UInt srcPos = lsb + 32; 14874 UInt dstSz = msb + 1; 14875 DIP("dextu r%u, r%u, %u, %u", rt, rs, srcPos, dstSz); 14876 t1 = newTemp(Ity_I64); 14877 14878 vassert(srcPos >= 32 && srcPos < 64); 14879 vassert(dstSz > 0 && dstSz <= 32); 14880 vassert((srcPos + dstSz) > 32 && (srcPos + dstSz) <= 64); 14881 14882 UChar lsAmt = 64 - (srcPos + dstSz); /* left shift amount; */ 14883 UChar rsAmt = 64 - dstSz; /* right shift amount; */ 14884 14885 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 14886 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 14887 break; 14888 } 14889 case 0x05: { 14890 /* Doubleword Insert Bit Field Middle - DINSM; MIPS64r2 */ 14891 msb = get_msb(cins); 14892 lsb = get_lsb(cins); 14893 size = msb + 1; 14894 UInt dstPos = lsb; 14895 UInt srcSz = msb - lsb + 33; 14896 t1 = newTemp(ty); 14897 t2 = newTemp(ty); 14898 t3 = newTemp(ty); 14899 t4 = newTemp(ty); 14900 IRTemp tmpT1 = newTemp(ty); 14901 IRTemp tmpT2 = newTemp(ty); 14902 IRTemp tmpT3 = newTemp(ty); 14903 IRTemp tmpT4 = newTemp(ty); 14904 IRTemp tmpT5 = newTemp(ty); 14905 IRTemp tmpT6 = newTemp(ty); 14906 IRTemp tmpT7 = newTemp(ty); 14907 IRTemp tmpRs = newTemp(ty); 14908 IRTemp tmpRt = newTemp(ty); 14909 IRTemp tmpRd = newTemp(ty); 14910 14911 assign(tmpRs, getIReg(rs)); 14912 assign(tmpRt, getIReg(rt)); 14913 DIP("dinsm r%u, r%u, %u, %u", rt, rs, lsb, msb); 14914 14915 UChar lsAmt = dstPos + srcSz - 1; /* left shift amount; */ 14916 UChar rsAmt = dstPos + srcSz - 1; /* right shift amount; */ 14917 14918 assign(t1, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 14919 assign(tmpT1, binop(Iop_Shr64, mkexpr(t1), mkU8(1))); 14920 assign(t2, binop(Iop_Shl64, mkexpr(tmpT1), mkU8(lsAmt))); 14921 assign(tmpT2, binop(Iop_Shl64, mkexpr(t2), mkU8(1))); 14922 14923 lsAmt = 63 - dstPos; /* left shift amount; */ 14924 rsAmt = 63 - dstPos; /* right shift amount; */ 14925 14926 assign(t3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 14927 assign(tmpT3, binop(Iop_Shl64, mkexpr(t3), mkU8(1))); 14928 assign(t4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt))); 14929 assign(tmpT4, binop(Iop_Shr64, mkexpr(t4), mkU8(1))); 14930 14931 /* extract size from src register */ 14932 lsAmt = 64 - srcSz; /* left shift amount; */ 14933 rsAmt = 64 - (lsb + srcSz); /* right shift amount; */ 14934 14935 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 14936 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(rsAmt))); 14937 14938 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT4))); 14939 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT7))); 14940 putIReg(rt, mkexpr(tmpRd)); 14941 break; 14942 } 14943 case 0x06: { 14944 /* Doubleword Insert Bit Field Upper - DINSU; MIPS64r2 */ 14945 msb = get_msb(cins); 14946 lsb = get_lsb(cins); 14947 size = msb + 1; 14948 UInt dstPos = lsb + 32; 14949 UInt srcSz = msb - lsb + 1; 14950 IRTemp tmpT1 = newTemp(ty); 14951 IRTemp tmpT2 = newTemp(ty); 14952 IRTemp tmpT3 = newTemp(ty); 14953 IRTemp tmpT4 = newTemp(ty); 14954 IRTemp tmpT5 = newTemp(ty); 14955 IRTemp tmpT6 = newTemp(ty); 14956 IRTemp tmpT7 = newTemp(ty); 14957 IRTemp tmpT8 = newTemp(ty); 14958 IRTemp tmpT9 = newTemp(ty); 14959 IRTemp tmpRs = newTemp(ty); 14960 IRTemp tmpRt = newTemp(ty); 14961 IRTemp tmpRd = newTemp(ty); 14962 14963 assign(tmpRs, getIReg(rs)); 14964 assign(tmpRt, getIReg(rt)); 14965 DIP("dinsu r%u, r%u, %u, %u", rt, rs, lsb, msb); 14966 14967 UChar lsAmt = 64 - srcSz; /* left shift amount; */ 14968 UChar rsAmt = 64 - (dstPos + srcSz); /* right shift amount; */ 14969 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 14970 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt))); 14971 14972 lsAmt = 64 - dstPos; /* left shift amount; */ 14973 rsAmt = 64 - dstPos; /* right shift amount; */ 14974 assign(tmpT3, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 14975 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(rsAmt))); 14976 14977 lsAmt = dstPos; /* left shift amount; */ 14978 rsAmt = srcSz; /* right shift amount; */ 14979 assign(tmpT5, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 14980 assign(tmpT6, binop(Iop_Shr64, mkexpr(tmpT5), mkU8(lsAmt))); 14981 14982 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpT6), mkU8(rsAmt))); 14983 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(lsAmt))); 14984 14985 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT4))); 14986 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT9))); 14987 putIReg(rt, mkexpr(tmpRd)); 14988 break; 14989 } 14990 case 0x07: { 14991 /* Doubleword Insert Bit Field - DINS; MIPS64r2 */ 14992 IRTemp tmp1 = newTemp(ty); 14993 IRTemp tmpT1 = newTemp(ty); 14994 IRTemp tmpT2 = newTemp(ty); 14995 IRTemp tmpT3 = newTemp(ty); 14996 IRTemp tmpT4 = newTemp(ty); 14997 IRTemp tmpT5 = newTemp(ty); 14998 IRTemp tmpT6 = newTemp(ty); 14999 IRTemp tmpT7 = newTemp(ty); 15000 IRTemp tmpT8 = newTemp(ty); 15001 IRTemp tmpT9 = newTemp(ty); 15002 IRTemp tmp = newTemp(ty); 15003 IRTemp tmpRs = newTemp(ty); 15004 IRTemp tmpRt = newTemp(ty); 15005 IRTemp tmpRd = newTemp(ty); 15006 15007 assign(tmpRs, getIReg(rs)); 15008 assign(tmpRt, getIReg(rt)); 15009 15010 msb = get_msb(cins); 15011 lsb = get_lsb(cins); 15012 size = msb + 1; 15013 DIP("dins r%u, r%u, %u, %u", rt, rs, lsb, 15014 msb - lsb + 1); 15015 UChar lsAmt = 63 - lsb; /* left shift amount; */ 15016 UChar rsAmt = 63 - lsb; /* right shift amount; */ 15017 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(lsAmt))); 15018 assign(tmpT1, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 15019 assign(tmp1, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(rsAmt))); 15020 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmp1), mkU8(1))); 15021 15022 lsAmt = msb; /* left shift amount; */ 15023 rsAmt = 1; /*right shift amount; */ 15024 assign(tmpT3, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(rsAmt))); 15025 assign(tmpT4, binop(Iop_Shr64, mkexpr(tmpT3), mkU8(lsAmt))); 15026 assign(tmpT5, binop(Iop_Shl64, mkexpr(tmpT4), mkU8(rsAmt))); 15027 assign(tmpT6, binop(Iop_Shl64, mkexpr(tmpT5), mkU8(lsAmt))); 15028 15029 lsAmt = 64 - (msb - lsb + 1); /* left shift amount; */ 15030 rsAmt = 64 - (msb + 1); /* right shift amount; */ 15031 assign(tmpT7, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 15032 assign(tmpT8, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(rsAmt))); 15033 15034 assign(tmpT9, binop(Iop_Or64, mkexpr(tmpT2), mkexpr(tmpT8))); 15035 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT6), mkexpr(tmpT9))); 15036 putIReg(rt, mkexpr(tmpRd)); 15037 break; 15038 } 15039 case 0x24: /* DBSHFL */ 15040 lsb = get_lsb(cins); 15041 IRTemp tmpRs = newTemp(ty); 15042 IRTemp tmpRt = newTemp(ty); 15043 IRTemp tmpRd = newTemp(ty); 15044 assign(tmpRs, getIReg(rs)); 15045 assign(tmpRt, getIReg(rt)); 15046 switch (lsb) { 15047 case 0x02: { /* DSBH */ 15048 DIP("dsbh r%u, r%u", rd, rt); 15049 IRTemp tmpT1 = newTemp(ty); 15050 IRTemp tmpT2 = newTemp(ty); 15051 IRTemp tmpT3 = newTemp(ty); 15052 IRTemp tmpT4 = newTemp(ty); 15053 IRTemp tmpT5 = newTemp(Ity_I64); 15054 IRTemp tmpT6 = newTemp(ty); 15055 assign(tmpT5, mkU64(0xFF00FF00FF00FF00ULL)); 15056 assign(tmpT6, mkU64(0x00FF00FF00FF00FFULL)); 15057 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5))); 15058 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(8))); 15059 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6))); 15060 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(8))); 15061 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2))); 15062 putIReg(rd, mkexpr(tmpRd)); 15063 break; 15064 } 15065 case 0x05: { /* DSHD */ 15066 DIP("dshd r%u, r%u\n", rd, rt); 15067 IRTemp tmpT1 = newTemp(ty); 15068 IRTemp tmpT2 = newTemp(ty); 15069 IRTemp tmpT3 = newTemp(ty); 15070 IRTemp tmpT4 = newTemp(ty); 15071 IRTemp tmpT5 = newTemp(Ity_I64); 15072 IRTemp tmpT6 = newTemp(ty); 15073 IRTemp tmpT7 = newTemp(ty); 15074 IRTemp tmpT8 = newTemp(ty); 15075 IRTemp tmpT9 = newTemp(ty); 15076 assign(tmpT5, mkU64(0xFFFF0000FFFF0000ULL)); 15077 assign(tmpT6, mkU64(0x0000FFFF0000FFFFULL)); 15078 assign(tmpT1, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT5))); 15079 assign(tmpT2, binop(Iop_Shr64, mkexpr(tmpT1), mkU8(16))); 15080 assign(tmpT3, binop(Iop_And64, mkexpr(tmpRt), mkexpr(tmpT6))); 15081 assign(tmpT4, binop(Iop_Shl64, mkexpr(tmpT3), mkU8(16))); 15082 assign(tmpT7, binop(Iop_Or64, mkexpr(tmpT4), mkexpr(tmpT2))); 15083 assign(tmpT8, binop(Iop_Shl64, mkexpr(tmpT7), mkU8(32))); 15084 assign(tmpT9, binop(Iop_Shr64, mkexpr(tmpT7), mkU8(32))); 15085 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpT8), mkexpr(tmpT9))); 15086 putIReg(rd, mkexpr(tmpRd)); 15087 break; 15088 } 15089 default: 15090 vex_printf("\nop6o10 = %u", lsb); 15091 goto decode_failure;; 15092 } 15093 break; 15094 case 0x3B: /* RDHWR */ 15095 DIP("rdhwr r%u, r%u", rt, rd); 15096 if (VEX_MIPS_CPU_HAS_MIPS32R2(archinfo->hwcaps) || 15097 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) { 15098 if (rd == 29) { 15099 putIReg(rt, getULR()); 15100 } else if (rd <= 3 15101 || (rd == 31 15102 && VEX_MIPS_COMP_ID(archinfo->hwcaps) 15103 == VEX_PRID_COMP_CAVIUM)) { 15104 IRExpr** arg = mkIRExprVec_1(mkU32(rd)); 15105 IRTemp val = newTemp(ty); 15106 IRDirty *d = unsafeIRDirty_1_N(val, 15107 0, 15108 "mips_dirtyhelper_rdhwr", 15109 &mips_dirtyhelper_rdhwr, 15110 arg); 15111 stmt(IRStmt_Dirty(d)); 15112 putIReg(rt, mkexpr(val)); 15113 } else 15114 goto decode_failure; 15115 } else { 15116 ILLEGAL_INSTRUCTON; 15117 } 15118 break; 15119 case 0x04: /* INS */ 15120 msb = get_msb(cins); 15121 lsb = get_lsb(cins); 15122 size = msb - lsb + 1; 15123 DIP("ins size:%u msb:%u lsb:%u", size, msb, lsb); 15124 15125 vassert(lsb + size <= 32); 15126 vassert(lsb + size > 0); 15127 15128 /* put size bits from rs at the pos in temporary */ 15129 t0 = newTemp(Ity_I32); 15130 t3 = newTemp(Ity_I32); 15131 /* shift left for 32 - size to clear leading bits and get zeros 15132 at the end */ 15133 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)), 15134 mkU8(32 - size))); 15135 /* now set it at pos */ 15136 t1 = newTemp(Ity_I32); 15137 assign(t1, binop(Iop_Shr32, mkexpr(t0), mkU8(32 - size - lsb))); 15138 15139 if (lsb > 0) { 15140 t2 = newTemp(Ity_I32); 15141 /* clear everything but lower pos bits from rt */ 15142 assign(t2, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rt)), 15143 mkU8(32 - lsb))); 15144 assign(t3, binop(Iop_Shr32, mkexpr(t2), mkU8(32 - lsb))); 15145 } else 15146 assign(t3, mkU32(0)); 15147 15148 if (msb < 31) { 15149 t4 = newTemp(Ity_I32); 15150 /* clear everything but upper msb + 1 bits from rt */ 15151 assign(t4, binop(Iop_Shr32, mkNarrowTo32(ty, getIReg(rt)), 15152 mkU8(msb + 1))); 15153 t5 = newTemp(Ity_I32); 15154 assign(t5, binop(Iop_Shl32, mkexpr(t4), mkU8(msb + 1))); 15155 15156 /* now combine these registers */ 15157 if (lsb > 0) { 15158 t6 = newTemp(Ity_I32); 15159 assign(t6, binop(Iop_Or32, mkexpr(t5), mkexpr(t1))); 15160 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t6), 15161 mkexpr(t3)), True)); 15162 } else { 15163 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1), 15164 mkexpr(t5)), True)); 15165 } 15166 } else { 15167 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t1), 15168 mkexpr(t3)), True)); 15169 } 15170 break; 15171 15172 case 0x00: /* EXT */ 15173 msb = get_msb(cins); 15174 lsb = get_lsb(cins); 15175 size = msb + 1; 15176 DIP("ext size:%u msb:%u lsb:%u", size, msb, lsb); 15177 vassert(lsb + size <= 32); 15178 vassert(lsb + size > 0); 15179 /* put size bits from rs at the top of in temporary */ 15180 if (lsb + size < 32) { 15181 t0 = newTemp(Ity_I32); 15182 assign(t0, binop(Iop_Shl32, mkNarrowTo32(ty, getIReg(rs)), 15183 mkU8(32 - lsb - size))); 15184 15185 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, mkexpr(t0), 15186 mkU8(32 - size)), True)); 15187 } else { 15188 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Shr32, 15189 mkNarrowTo32(ty, getIReg(rs)), 15190 mkU8(32 - size)), True)); 15191 } 15192 break; 15193 15194 case 0x03: /* Doubleword Extract Bit Field - DEXT; MIPS64r2 */ 15195 msb = get_msb(cins); 15196 lsb = get_lsb(cins); 15197 size = msb + 1; 15198 DIP("dext r%u, r%u, %u, %u", rt, rs, lsb, msb + 1); 15199 t1 = newTemp(Ity_I64); 15200 vassert(lsb >= 0 && lsb < 32); 15201 vassert(size > 0 && size <= 32); 15202 vassert((lsb + size) > 0 && (lsb + size) <= 63); 15203 15204 UChar lsAmt = 63 - (lsb + msb); /* left shift amount; */ 15205 UChar rsAmt = 63 - msb; /* right shift amount; */ 15206 15207 assign(t1, binop(Iop_Shl64, getIReg(rs), mkU8(lsAmt))); 15208 putIReg(rt, binop(Iop_Shr64, mkexpr(t1), mkU8(rsAmt))); 15209 15210 break; 15211 15212 case 0x20: /* BSHFL */ 15213 switch (sa) { 15214 case 0x02: /* WSBH */ 15215 DIP("wsbh r%u, r%u", rd, rt); 15216 t0 = newTemp(Ity_I32); 15217 t1 = newTemp(Ity_I32); 15218 t2 = newTemp(Ity_I32); 15219 t3 = newTemp(Ity_I32); 15220 assign(t0, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty, 15221 getIReg(rt)), mkU32(0x00FF0000)), 15222 mkU8(0x8))); 15223 assign(t1, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty, 15224 getIReg(rt)), mkU32(0xFF000000)), mkU8(0x8))); 15225 assign(t2, binop(Iop_Shl32, binop(Iop_And32, mkNarrowTo32(ty, 15226 getIReg(rt)), mkU32(0x000000FF)), mkU8(0x8))); 15227 assign(t3, binop(Iop_Shr32, binop(Iop_And32, mkNarrowTo32(ty, 15228 getIReg(rt)), mkU32(0x0000FF00)), mkU8(0x8))); 15229 putIReg(rd, mkWidenFrom32(ty, binop(Iop_Or32, binop(Iop_Or32, 15230 mkexpr(t0), mkexpr(t1)), 15231 binop(Iop_Or32, mkexpr(t2), 15232 mkexpr(t3))), True)); 15233 break; 15234 15235 case 0x10: /* SEB */ 15236 DIP("seb r%u, r%u", rd, rt); 15237 if (mode64) 15238 putIReg(rd, unop(Iop_8Sto64, unop(Iop_64to8, getIReg(rt)))); 15239 else 15240 putIReg(rd, unop(Iop_8Sto32, unop(Iop_32to8, getIReg(rt)))); 15241 break; 15242 15243 case 0x18: /* SEH */ 15244 DIP("seh r%u, r%u", rd, rt); 15245 if (mode64) 15246 putIReg(rd, unop(Iop_16Sto64, unop(Iop_64to16, getIReg(rt)))); 15247 else 15248 putIReg(rd, unop(Iop_16Sto32, unop(Iop_32to16, getIReg(rt)))); 15249 break; 15250 15251 default: 15252 goto decode_failure; 15253 15254 } 15255 break; /* BSHFL */ 15256 15257 /* --- MIPS32(r2) DSP ASE(r2) / Cavium Specfic (LX) instructions --- */ 15258 case 0xA: /* LX */ 15259 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 15260 if (dis_instr_CVM(cins)) 15261 break; 15262 goto decode_failure; 15263 } 15264 case 0xC: /* INSV */ 15265 case 0x38: { /* EXTR.W */ 15266 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15267 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15268 if (0 != retVal ) { 15269 goto decode_failure_dsp; 15270 } 15271 break; 15272 } else { 15273 goto decode_failure_dsp; 15274 } 15275 break; 15276 } 15277 case 0x10: { /* ADDU.QB */ 15278 switch(sa) { 15279 case 0xC: /* SUBU_S.PH */ 15280 case 0xD: /* ADDU_S.PH */ 15281 case 0x1E: { /* MULQ_S.PH */ 15282 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15283 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15284 if (0 != retVal ) { 15285 goto decode_failure_dsp; 15286 } 15287 break; 15288 } else { 15289 goto decode_failure_dsp; 15290 } 15291 break; 15292 } 15293 default: { 15294 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15295 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15296 if (0 != retVal ) { 15297 goto decode_failure_dsp; 15298 } 15299 break; 15300 } else { 15301 goto decode_failure_dsp; 15302 } 15303 break; 15304 } 15305 } 15306 break; 15307 } 15308 case 0x11: { /* CMPU.EQ.QB */ 15309 switch(sa) { 15310 case 0x18: /* CMPGDU.EQ.QB */ 15311 case 0x19: /* CMPGDU.LT.QB */ 15312 case 0x1A: /* CMPGDU.LE.QB */ 15313 case 0x0D: /* PRECR.QB.PH */ 15314 case 0x1E: /* PRECR_SRA.PH.W */ 15315 case 0x1F: { /* PRECR_SRA_R.PH.W */ 15316 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15317 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15318 if (0 != retVal ) { 15319 goto decode_failure_dsp; 15320 } 15321 break; 15322 } else { 15323 goto decode_failure_dsp; 15324 } 15325 break; 15326 } 15327 default: { 15328 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15329 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15330 if (0 != retVal ) { 15331 goto decode_failure_dsp; 15332 } 15333 break; 15334 } else { 15335 goto decode_failure_dsp; 15336 } 15337 break; 15338 } 15339 } 15340 break; 15341 } 15342 case 0x12: { /* ABSQ_S.PH */ 15343 switch(sa){ 15344 case 0x1: { /* ABSQ_S.QB */ 15345 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15346 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15347 if (0 != retVal ) { 15348 goto decode_failure_dsp; 15349 } 15350 break; 15351 } else { 15352 goto decode_failure_dsp; 15353 } 15354 break; 15355 } 15356 default: { 15357 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15358 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15359 if (0 != retVal ) { 15360 goto decode_failure_dsp; 15361 } 15362 break; 15363 } else { 15364 goto decode_failure_dsp; 15365 } 15366 break; 15367 } 15368 } 15369 break; 15370 } 15371 case 0x13: { /* SHLL.QB */ 15372 switch(sa) { 15373 case 0x04: /* SHRA.QB */ 15374 case 0x05: /* SHRA_R.QB */ 15375 case 0x06: /* SHRAV.QB */ 15376 case 0x07: /* SHRAV_R.QB */ 15377 case 0x19: /* SHLR.PH */ 15378 case 0x1B: { /* SHLRV.PH */ 15379 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15380 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15381 if (0 != retVal ) { 15382 goto decode_failure_dsp; 15383 } 15384 break; 15385 } else { 15386 goto decode_failure_dsp; 15387 } 15388 break; 15389 } 15390 default: { 15391 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15392 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15393 if (0 != retVal ) { 15394 goto decode_failure_dsp; 15395 } 15396 break; 15397 } else { 15398 goto decode_failure_dsp; 15399 } 15400 break; 15401 } 15402 } 15403 break; 15404 } 15405 case 0x30: { /* DPAQ.W.PH */ 15406 switch(sa) { 15407 case 0x0: /* DPA.W.PH */ 15408 case 0x18: /* DPAQX_S.W.PH */ 15409 case 0x1A: /* DPAQX_SA.W.PH */ 15410 case 0x8: /* DPAX.W.PH */ 15411 case 0x1: /* DPS.W.PH */ 15412 case 0x19: /* DPSQX_S.W.PH */ 15413 case 0x1B: /* DPSQX_SA.W.PH */ 15414 case 0x9: /* DPSX.W.PH */ 15415 case 0x2: { /* MULSA.W.PH */ 15416 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15417 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15418 if (0 != retVal ) { 15419 goto decode_failure_dsp; 15420 } 15421 break; 15422 } else { 15423 goto decode_failure_dsp; 15424 } 15425 break; 15426 } 15427 default: { 15428 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15429 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15430 if (0 != retVal ) { 15431 goto decode_failure_dsp; 15432 } 15433 break; 15434 } else { 15435 goto decode_failure_dsp; 15436 } 15437 break; 15438 } 15439 } 15440 break; 15441 } 15442 case 0x18: /* ADDUH.QB/MUL.PH */ 15443 case 0x31: { /* APPEND */ 15444 if (VEX_MIPS_PROC_DSP2(archinfo->hwcaps)) { 15445 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15446 if (0 != retVal ) { 15447 goto decode_failure_dsp; 15448 } 15449 break; 15450 } else { 15451 goto decode_failure_dsp; 15452 } 15453 } 15454 default: 15455 goto decode_failure; 15456 15457 } 15458 break; /* Special3 */ 15459 15460 case 0x3B: 15461 if (0x3B == function && 15462 (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_BROADCOM)) { 15463 /*RDHWR*/ 15464 DIP("rdhwr r%u, r%u", rt, rd); 15465 if (rd == 29) { 15466 putIReg(rt, getULR()); 15467 } else 15468 goto decode_failure; 15469 break; 15470 } else { 15471 goto decode_failure; 15472 } 15473 15474 case 0x00: /* Special */ 15475 15476 switch (function) { 15477 case 0x1: { 15478 UInt mov_cc = get_mov_cc(cins); 15479 if (tf == 0) { /* MOVF */ 15480 DIP("movf r%u, r%u, %u", rd, rs, mov_cc); 15481 t1 = newTemp(Ity_I1); 15482 t2 = newTemp(Ity_I32); 15483 t3 = newTemp(Ity_I1); 15484 15485 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 15486 assign(t2, IRExpr_ITE(mkexpr(t1), 15487 binop(Iop_And32, 15488 binop(Iop_Shr32, getFCSR(), 15489 mkU8(23)), 15490 mkU32(0x1)), 15491 binop(Iop_And32, 15492 binop(Iop_Shr32, getFCSR(), 15493 mkU8(24 + mov_cc)), 15494 mkU32(0x1)) 15495 )); 15496 assign(t3, binop(Iop_CmpEQ32, mkU32(0), mkexpr(t2))); 15497 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd))); 15498 } else if (tf == 1) { /* MOVT */ 15499 DIP("movt r%u, r%u, %u", rd, rs, mov_cc); 15500 t1 = newTemp(Ity_I1); 15501 t2 = newTemp(Ity_I32); 15502 t3 = newTemp(Ity_I1); 15503 15504 assign(t1, binop(Iop_CmpEQ32, mkU32(0), mkU32(mov_cc))); 15505 assign(t2, IRExpr_ITE(mkexpr(t1), 15506 binop(Iop_And32, 15507 binop(Iop_Shr32, getFCSR(), 15508 mkU8(23)), 15509 mkU32(0x1)), 15510 binop(Iop_And32, 15511 binop(Iop_Shr32, getFCSR(), 15512 mkU8(24 + mov_cc)), 15513 mkU32(0x1)) 15514 )); 15515 assign(t3, binop(Iop_CmpEQ32, mkU32(1), mkexpr(t2))); 15516 putIReg(rd, IRExpr_ITE(mkexpr(t3), getIReg(rs), getIReg(rd))); 15517 } 15518 break; 15519 } 15520 case 0x0A: { /* MOVZ */ 15521 DIP("movz r%u, r%u, r%u", rd, rs, rt); 15522 t1 = newTemp(ty); 15523 t2 = newTemp(ty); 15524 if (mode64) { 15525 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64, 15526 getIReg(rt), mkU64(0x0))))); 15527 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64, 15528 getIReg(rt), mkU64(0x0))))); 15529 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs), 15530 mkexpr(t1)), binop(Iop_And64, getIReg(rd),mkexpr(t2)))); 15531 } else { 15532 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 15533 mkU32(0x0)))); 15534 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 15535 mkU32(0x0)))); 15536 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 15537 mkexpr(t1)), binop(Iop_And32, getIReg(rd), 15538 mkexpr(t2)))); 15539 } 15540 break; 15541 } 15542 15543 case 0x0B: { /* MOVN */ 15544 DIP("movn r%u, r%u, r%u", rd, rs, rt); 15545 t1 = newTemp(ty); 15546 t2 = newTemp(ty); 15547 if (mode64) { 15548 assign(t1, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpEQ64, 15549 getIReg(rt), mkU64(0x0))))); 15550 assign(t2, unop(Iop_32Sto64, unop(Iop_1Sto32, binop(Iop_CmpNE64, 15551 getIReg(rt), mkU64(0x0))))); 15552 putIReg(rd, binop(Iop_Add64, binop(Iop_And64, getIReg(rs), 15553 mkexpr(t2)), binop(Iop_And64, getIReg(rd), 15554 mkexpr(t1)))); 15555 } else { 15556 assign(t1, unop(Iop_1Sto32, binop(Iop_CmpEQ32, getIReg(rt), 15557 mkU32(0x0)))); 15558 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpNE32, getIReg(rt), 15559 mkU32(0x0)))); 15560 putIReg(rd, binop(Iop_Add32, binop(Iop_And32, getIReg(rs), 15561 mkexpr(t2)), binop(Iop_And32, getIReg(rd), 15562 mkexpr(t1)))); 15563 } 15564 break; 15565 } 15566 15567 case 0x18: { /* MULT */ 15568 if ( (1 <= ac) && ( 3 >= ac) ) { 15569 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15570 /* If DSP is present -> DSP ASE MULT */ 15571 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15572 if (0 != retVal ) { 15573 goto decode_failure_dsp; 15574 } 15575 break; 15576 } else { 15577 goto decode_failure_dsp; 15578 } 15579 } else { 15580 DIP("mult r%u, r%u", rs, rt); 15581 t2 = newTemp(Ity_I64); 15582 15583 assign(t2, binop(Iop_MullS32, mkNarrowTo32(ty, getIReg(rs)), 15584 mkNarrowTo32(ty, getIReg(rt)))); 15585 15586 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15587 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15588 break; 15589 } 15590 } 15591 case 0x19: { /* MULTU */ 15592 if ( (1 <= ac) && ( 3 >= ac) ) { 15593 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15594 /* If DSP is present -> DSP ASE MULTU */ 15595 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15596 if (0 != retVal ) { 15597 goto decode_failure_dsp; 15598 } 15599 break; 15600 } else { 15601 goto decode_failure_dsp; 15602 } 15603 } else { 15604 DIP("multu r%u, r%u", rs, rt); 15605 t2 = newTemp(Ity_I64); 15606 15607 assign(t2, binop(Iop_MullU32, mkNarrowTo32(ty, getIReg(rs)), 15608 mkNarrowTo32(ty, getIReg(rt)))); 15609 15610 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15611 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15612 break; 15613 } 15614 } 15615 case 0x20: { /* ADD */ 15616 DIP("add r%u, r%u, r%u", rd, rs, rt); 15617 IRTemp tmpRs32 = newTemp(Ity_I32); 15618 IRTemp tmpRt32 = newTemp(Ity_I32); 15619 15620 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 15621 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15622 15623 t0 = newTemp(Ity_I32); 15624 t1 = newTemp(Ity_I32); 15625 t2 = newTemp(Ity_I32); 15626 t3 = newTemp(Ity_I32); 15627 t4 = newTemp(Ity_I32); 15628 /* dst = src0 + src1 15629 if (sign(src0 ) != sign(src1 )) 15630 goto no overflow; 15631 if (sign(dst) == sign(src0 )) 15632 goto no overflow; 15633 we have overflow! */ 15634 15635 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(tmpRt32))); 15636 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(tmpRt32))); 15637 assign(t2, unop(Iop_1Uto32, 15638 binop(Iop_CmpEQ32, 15639 binop(Iop_And32, mkexpr(t1), mkU32(0x80000000)), 15640 mkU32(0x80000000)))); 15641 15642 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 15643 assign(t4, unop(Iop_1Uto32, 15644 binop(Iop_CmpNE32, 15645 binop(Iop_And32, mkexpr(t3), mkU32(0x80000000)), 15646 mkU32(0x80000000)))); 15647 15648 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, 15649 binop(Iop_Or32, mkexpr(t2), mkexpr(t4)), 15650 mkU32(0)), 15651 Ijk_SigFPE_IntOvf, 15652 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 15653 IRConst_U32(guest_PC_curr_instr + 4), 15654 OFFB_PC)); 15655 15656 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True)); 15657 break; 15658 } 15659 case 0x1A: /* DIV */ 15660 DIP("div r%u, r%u", rs, rt); 15661 if (mode64) { 15662 t2 = newTemp(Ity_I64); 15663 15664 assign(t2, binop(Iop_DivModS64to32, 15665 getIReg(rs), mkNarrowTo32(ty, getIReg(rt)))); 15666 15667 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15668 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15669 } else { 15670 t1 = newTemp(Ity_I64); 15671 t2 = newTemp(Ity_I64); 15672 15673 assign(t1, unop(Iop_32Sto64, getIReg(rs))); 15674 assign(t2, binop(Iop_DivModS64to32, mkexpr(t1), getIReg(rt))); 15675 15676 putHI(unop(Iop_64HIto32, mkexpr(t2))); 15677 putLO(unop(Iop_64to32, mkexpr(t2))); 15678 } 15679 break; 15680 15681 case 0x1B: /* DIVU */ 15682 DIP("divu r%u, r%u", rs, rt); 15683 if (mode64) { 15684 t2 = newTemp(Ity_I64); 15685 15686 assign(t2, binop(Iop_DivModU64to32, 15687 getIReg(rs), mkNarrowTo32(ty, getIReg(rt)))); 15688 15689 putHI(mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(t2)), True)); 15690 putLO(mkWidenFrom32(ty, unop(Iop_64to32, mkexpr(t2)), True)); 15691 } else { 15692 t1 = newTemp(Ity_I64); 15693 t2 = newTemp(Ity_I64); 15694 assign(t1, unop(Iop_32Uto64, getIReg(rs))); 15695 assign(t2, binop(Iop_DivModU64to32, mkexpr(t1), getIReg(rt))); 15696 putHI(unop(Iop_64HIto32, mkexpr(t2))); 15697 putLO(unop(Iop_64to32, mkexpr(t2))); 15698 } 15699 break; 15700 15701 case 0x1C: /* Doubleword Multiply - DMULT; MIPS64 */ 15702 DIP("dmult r%u, r%u", rs, rt); 15703 t0 = newTemp(Ity_I128); 15704 15705 assign(t0, binop(Iop_MullS64, getIReg(rs), getIReg(rt))); 15706 15707 putHI(unop(Iop_128HIto64, mkexpr(t0))); 15708 putLO(unop(Iop_128to64, mkexpr(t0))); 15709 break; 15710 15711 case 0x1D: /* Doubleword Multiply Unsigned - DMULTU; MIPS64 */ 15712 DIP("dmultu r%u, r%u", rs, rt); 15713 t0 = newTemp(Ity_I128); 15714 15715 assign(t0, binop(Iop_MullU64, getIReg(rs), getIReg(rt))); 15716 15717 putHI(unop(Iop_128HIto64, mkexpr(t0))); 15718 putLO(unop(Iop_128to64, mkexpr(t0))); 15719 break; 15720 15721 case 0x1E: /* Doubleword Divide DDIV; MIPS64 */ 15722 DIP("ddiv r%u, r%u", rs, rt); 15723 t1 = newTemp(Ity_I128); 15724 15725 assign(t1, binop(Iop_DivModS64to64, getIReg(rs), getIReg(rt))); 15726 15727 putHI(unop(Iop_128HIto64, mkexpr(t1))); 15728 putLO(unop(Iop_128to64, mkexpr(t1))); 15729 break; 15730 15731 case 0x1F: /* Doubleword Divide Unsigned DDIVU; MIPS64 check this */ 15732 DIP("ddivu r%u, r%u", rs, rt); 15733 t1 = newTemp(Ity_I128); 15734 t2 = newTemp(Ity_I128); 15735 15736 assign(t1, binop(Iop_64HLto128, mkU64(0), getIReg(rs))); 15737 15738 assign(t2, binop(Iop_DivModU128to64, mkexpr(t1), getIReg(rt))); 15739 15740 putHI(unop(Iop_128HIto64, mkexpr(t2))); 15741 putLO(unop(Iop_128to64, mkexpr(t2))); 15742 break; 15743 15744 case 0x10: { /* MFHI */ 15745 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15746 /* If DSP is present -> DSP ASE MFHI */ 15747 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15748 if (0 != retVal ) { 15749 goto decode_failure; 15750 } 15751 break; 15752 } else { 15753 DIP("mfhi r%u", rd); 15754 putIReg(rd, getHI()); 15755 break; 15756 } 15757 } 15758 15759 case 0x11: { /* MTHI */ 15760 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15761 /* If DSP is present -> DSP ASE MTHI */ 15762 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15763 if (0 != retVal ) { 15764 goto decode_failure; 15765 } 15766 break; 15767 } else { 15768 DIP("mthi r%u", rs); 15769 putHI(getIReg(rs)); 15770 break; 15771 } 15772 } 15773 15774 case 0x12: { /* MFLO */ 15775 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15776 /* If DSP is present -> DSP ASE MFLO */ 15777 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15778 if (0 != retVal ) { 15779 goto decode_failure; 15780 } 15781 break; 15782 } else { 15783 DIP("mflo r%u", rd); 15784 putIReg(rd, getLO()); 15785 break; 15786 } 15787 } 15788 15789 case 0x13: { /* MTLO */ 15790 if (VEX_MIPS_PROC_DSP(archinfo->hwcaps)) { 15791 /* If DSP is present -> DSP ASE MTLO */ 15792 UInt retVal = disDSPInstr_MIPS_WRK ( cins ); 15793 if (0 != retVal ) { 15794 goto decode_failure; 15795 } 15796 break; 15797 } else { 15798 DIP("mtlo r%u", rs); 15799 putLO(getIReg(rs)); 15800 break; 15801 } 15802 } 15803 15804 case 0x21: /* ADDU */ 15805 DIP("addu r%u, r%u, r%u", rd, rs, rt); 15806 if (mode64) { 15807 ALU_PATTERN64(Iop_Add32); 15808 } else { 15809 ALU_PATTERN(Iop_Add32); 15810 } 15811 break; 15812 15813 case 0x22: { /* SUB */ 15814 DIP("sub r%u, r%u, r%u", rd, rs, rt); 15815 IRTemp tmpRs32 = newTemp(Ity_I32); 15816 IRTemp tmpRt32 = newTemp(Ity_I32); 15817 15818 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 15819 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15820 t0 = newTemp(Ity_I32); 15821 t1 = newTemp(Ity_I32); 15822 t2 = newTemp(Ity_I32); 15823 t3 = newTemp(Ity_I32); 15824 t4 = newTemp(Ity_I32); 15825 t5 = newTemp(Ity_I32); 15826 /* dst = src0 + (-1 * src1) 15827 if(sign(src0 ) != sign((-1 * src1) )) 15828 goto no overflow; 15829 if(sign(dst) == sign(src0 )) 15830 goto no overflow; 15831 we have overflow! */ 15832 15833 assign(t5, binop(Iop_Mul32, mkexpr(tmpRt32), mkU32(-1))); 15834 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), mkexpr(t5))); 15835 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), mkexpr(t5))); 15836 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32, 15837 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000)))); 15838 15839 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 15840 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32, 15841 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000)))); 15842 15843 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2), 15844 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf, 15845 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 15846 IRConst_U32(guest_PC_curr_instr + 4), 15847 OFFB_PC)); 15848 15849 putIReg(rd, mkWidenFrom32(ty, mkexpr(t0), True)); 15850 break; 15851 } 15852 case 0x23: /* SUBU */ 15853 DIP("subu r%u, r%u, r%u", rd, rs, rt); 15854 if (mode64) { 15855 ALU_PATTERN64(Iop_Sub32); 15856 } else { 15857 ALU_PATTERN(Iop_Sub32); 15858 } 15859 break; 15860 15861 case 0x24: /* AND */ 15862 DIP("and r%u, r%u, r%u", rd, rs, rt); 15863 if (mode64) { 15864 ALU_PATTERN(Iop_And64); 15865 } else { 15866 ALU_PATTERN(Iop_And32); 15867 } 15868 break; 15869 15870 case 0x25: /* OR */ 15871 DIP("or r%u, r%u, r%u", rd, rs, rt); 15872 if (mode64) { 15873 ALU_PATTERN(Iop_Or64); 15874 } else { 15875 ALU_PATTERN(Iop_Or32); 15876 } 15877 break; 15878 15879 case 0x26: /* XOR */ 15880 DIP("xor r%u, r%u, r%u", rd, rs, rt); 15881 if (mode64) { 15882 ALU_PATTERN(Iop_Xor64); 15883 } else { 15884 ALU_PATTERN(Iop_Xor32); 15885 } 15886 break; 15887 15888 case 0x27: /* NOR */ 15889 DIP("nor r%u, r%u, r%u", rd, rs, rt); 15890 if (mode64) 15891 putIReg(rd, unop(Iop_Not64, binop(Iop_Or64, getIReg(rs), 15892 getIReg(rt)))); 15893 else 15894 putIReg(rd, unop(Iop_Not32, binop(Iop_Or32, getIReg(rs), 15895 getIReg(rt)))); 15896 break; 15897 15898 case 0x08: /* JR */ 15899 DIP("jr r%u", rs); 15900 t0 = newTemp(ty); 15901 assign(t0, getIReg(rs)); 15902 lastn = mkexpr(t0); 15903 break; 15904 15905 case 0x09: /* JALR */ 15906 DIP("jalr r%u r%u", rd, rs); 15907 if (mode64) { 15908 putIReg(rd, mkU64(guest_PC_curr_instr + 8)); 15909 t0 = newTemp(Ity_I64); 15910 assign(t0, getIReg(rs)); 15911 lastn = mkexpr(t0); 15912 } else { 15913 putIReg(rd, mkU32(guest_PC_curr_instr + 8)); 15914 t0 = newTemp(Ity_I32); 15915 assign(t0, getIReg(rs)); 15916 lastn = mkexpr(t0); 15917 } 15918 break; 15919 15920 case 0x0C: /* SYSCALL */ 15921 DIP("syscall"); 15922 if (mode64) 15923 putPC(mkU64(guest_PC_curr_instr + 4)); 15924 else 15925 putPC(mkU32(guest_PC_curr_instr + 4)); 15926 dres.jk_StopHere = Ijk_Sys_syscall; 15927 dres.whatNext = Dis_StopHere; 15928 break; 15929 15930 case 0x2A: /* SLT */ 15931 DIP("slt r%u, r%u, r%u", rd, rs, rt); 15932 if (mode64) 15933 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs), 15934 getIReg(rt)))); 15935 else 15936 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 15937 getIReg(rt)))); 15938 break; 15939 15940 case 0x2B: /* SLTU */ 15941 DIP("sltu r%u, r%u, r%u", rd, rs, rt); 15942 if (mode64) 15943 putIReg(rd, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs), 15944 getIReg(rt)))); 15945 else 15946 putIReg(rd, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 15947 getIReg(rt)))); 15948 break; 15949 15950 case 0x00: { /* SLL */ 15951 DIP("sll r%u, r%u, %u", rd, rt, sa); 15952 IRTemp tmpRt32 = newTemp(Ity_I32); 15953 IRTemp tmpSh32 = newTemp(Ity_I32); 15954 IRTemp tmpRd = newTemp(Ity_I64); 15955 if (mode64) { 15956 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15957 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkU8(sa))); 15958 assign(tmpRd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 15959 putIReg(rd, mkexpr(tmpRd)); 15960 } else 15961 SXX_PATTERN(Iop_Shl32); 15962 break; 15963 } 15964 15965 case 0x04: { /* SLLV */ 15966 DIP("sllv r%u, r%u, r%u", rd, rt, rs); 15967 if (mode64) { 15968 IRTemp tmpRs8 = newTemp(Ity_I8); 15969 IRTemp tmpRt32 = newTemp(Ity_I32); 15970 IRTemp tmpSh32 = newTemp(Ity_I32); 15971 IRTemp tmp = newTemp(ty); 15972 assign(tmp, binop(mkSzOp(ty, Iop_And8), getIReg(rs), 15973 mkSzImm(ty, 31))); 15974 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 15975 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 15976 assign(tmpSh32, binop(Iop_Shl32, mkexpr(tmpRt32), mkexpr(tmpRs8))); 15977 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 15978 } else { 15979 SXXV_PATTERN(Iop_Shl32); 15980 } 15981 break; 15982 } 15983 15984 case 0x03: /* SRA */ 15985 DIP("sra r%u, r%u, %u", rd, rt, sa); 15986 if (mode64) { 15987 IRTemp tmpRt32 = newTemp(Ity_I32); 15988 IRTemp tmpSh32 = newTemp(Ity_I32); 15989 15990 t1 = newTemp(Ity_I64); 15991 t2 = newTemp(Ity_I64); 15992 t3 = newTemp(Ity_I64); 15993 15994 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */ 15995 mkU64(0xFFFFFFFF00000000ULL))); 15996 15997 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkU8(sa))); 15998 15999 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16000 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkU8(sa))); 16001 16002 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16003 } else { 16004 SXX_PATTERN(Iop_Sar32); 16005 } 16006 break; 16007 16008 case 0x07: /* SRAV */ 16009 DIP("srav r%u, r%u, r%u", rd, rt, rs); 16010 if (mode64) { 16011 IRTemp tmpRt32 = newTemp(Ity_I32); 16012 IRTemp tmpSh32 = newTemp(Ity_I32); 16013 16014 t1 = newTemp(Ity_I64); 16015 t2 = newTemp(Ity_I64); 16016 t3 = newTemp(Ity_I64); 16017 t4 = newTemp(Ity_I8); 16018 16019 assign(t4, unop(Iop_32to8, binop(Iop_And32, 16020 mkNarrowTo32(ty, getIReg(rs)), mkU32(0x0000001F)))); 16021 16022 assign(t1, binop(Iop_And64, getIReg(rt), /* hi */ 16023 mkU64(0xFFFFFFFF00000000ULL))); 16024 16025 assign(t2, binop(Iop_Sar64, mkexpr(t1), mkexpr(t4))); 16026 16027 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16028 assign(tmpSh32, binop(Iop_Sar32, mkexpr(tmpRt32), mkexpr(t4))); 16029 16030 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16031 } else { 16032 SXXV_PATTERN(Iop_Sar32); 16033 } 16034 break; 16035 16036 case 0x02: { /* SRL */ 16037 rot = get_rot(cins); 16038 if (rot) { 16039 DIP("rotr r%u, r%u, %u", rd, rt, sa); 16040 putIReg(rd, mkWidenFrom32(ty, genROR32(mkNarrowTo32(ty, 16041 getIReg(rt)), sa), True)); 16042 } else { 16043 DIP("srl r%u, r%u, %u", rd, rt, sa); 16044 if (mode64) { 16045 IRTemp tmpSh32 = newTemp(Ity_I32); 16046 IRTemp tmpRt32 = newTemp(Ity_I32); 16047 16048 assign(tmpRt32, mkNarrowTo32(ty, getIReg(rt))); 16049 assign(tmpSh32, binop(Iop_Shr32, mkexpr(tmpRt32), mkU8(sa))); 16050 putIReg(rd, mkWidenFrom32(ty, mkexpr(tmpSh32), True)); 16051 } else { 16052 SXX_PATTERN(Iop_Shr32); 16053 } 16054 } 16055 break; 16056 } 16057 16058 case 0x06: { 16059 rot = get_rotv(cins); 16060 if (rot) { 16061 DIP("rotrv r%u, r%u, r%u", rd, rt, rs); 16062 putIReg(rd, mkWidenFrom32(ty, genRORV32(mkNarrowTo32(ty, 16063 getIReg(rt)), mkNarrowTo32(ty, getIReg(rs))), True)); 16064 break; 16065 } else { /* SRLV */ 16066 DIP("srlv r%u, r%u, r%u", rd, rt, rs); 16067 if (mode64) { 16068 SXXV_PATTERN64(Iop_Shr32); 16069 } else { 16070 SXXV_PATTERN(Iop_Shr32); 16071 } 16072 break; 16073 } 16074 } 16075 16076 case 0x0D: /* BREAK */ 16077 DIP("break 0x%x", trap_code); 16078 if (mode64) 16079 jmp_lit64(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4)); 16080 else 16081 jmp_lit32(&dres, Ijk_SigTRAP, (guest_PC_curr_instr + 4)); 16082 vassert(dres.whatNext == Dis_StopHere); 16083 break; 16084 16085 case 0x30: { /* TGE */ 16086 DIP("tge r%u, r%u %u", rs, rt, trap_code); 16087 if (mode64) { 16088 if (trap_code == 7) 16089 stmt (IRStmt_Exit (unop (Iop_Not1, 16090 binop (Iop_CmpLT64S, 16091 getIReg (rs), 16092 getIReg (rt))), 16093 Ijk_SigFPE_IntDiv, 16094 IRConst_U64(guest_PC_curr_instr + 4), 16095 OFFB_PC)); 16096 else if (trap_code == 6) 16097 stmt (IRStmt_Exit (unop (Iop_Not1, 16098 binop (Iop_CmpLT64S, 16099 getIReg (rs), 16100 getIReg (rt))), 16101 Ijk_SigFPE_IntOvf, 16102 IRConst_U64(guest_PC_curr_instr + 4), 16103 OFFB_PC)); 16104 else 16105 stmt (IRStmt_Exit (unop (Iop_Not1, 16106 binop (Iop_CmpLT64S, 16107 getIReg (rs), 16108 getIReg (rt))), 16109 Ijk_SigTRAP, 16110 IRConst_U64(guest_PC_curr_instr + 4), 16111 OFFB_PC)); 16112 } else { 16113 if (trap_code == 7) 16114 stmt (IRStmt_Exit (unop (Iop_Not1, 16115 binop (Iop_CmpLT32S, 16116 getIReg (rs), 16117 getIReg (rt))), 16118 Ijk_SigFPE_IntDiv, 16119 IRConst_U32(guest_PC_curr_instr + 4), 16120 OFFB_PC)); 16121 else if (trap_code == 6) 16122 stmt (IRStmt_Exit (unop (Iop_Not1, 16123 binop (Iop_CmpLT32S, 16124 getIReg (rs), 16125 getIReg (rt))), 16126 Ijk_SigFPE_IntOvf, 16127 IRConst_U32(guest_PC_curr_instr + 4), 16128 OFFB_PC)); 16129 else 16130 stmt (IRStmt_Exit (unop (Iop_Not1, 16131 binop (Iop_CmpLT32S, 16132 getIReg (rs), 16133 getIReg (rt))), 16134 Ijk_SigTRAP, 16135 IRConst_U32(guest_PC_curr_instr + 4), 16136 OFFB_PC)); 16137 } 16138 break; 16139 } 16140 case 0x31: { /* TGEU */ 16141 DIP("tgeu r%u, r%u %u", rs, rt, trap_code); 16142 if (mode64) { 16143 if (trap_code == 7) 16144 stmt (IRStmt_Exit (unop (Iop_Not1, 16145 binop (Iop_CmpLT64U, 16146 getIReg (rs), 16147 getIReg (rt))), 16148 Ijk_SigFPE_IntDiv, 16149 IRConst_U64(guest_PC_curr_instr + 4), 16150 OFFB_PC)); 16151 else if (trap_code == 6) 16152 stmt (IRStmt_Exit (unop (Iop_Not1, 16153 binop (Iop_CmpLT64U, 16154 getIReg (rs), 16155 getIReg (rt))), 16156 Ijk_SigFPE_IntOvf, 16157 IRConst_U64(guest_PC_curr_instr + 4), 16158 OFFB_PC)); 16159 else 16160 stmt (IRStmt_Exit (unop (Iop_Not1, 16161 binop (Iop_CmpLT64U, 16162 getIReg (rs), 16163 getIReg (rt))), 16164 Ijk_SigTRAP, 16165 IRConst_U64(guest_PC_curr_instr + 4), 16166 OFFB_PC)); 16167 } else { 16168 if (trap_code == 7) 16169 stmt (IRStmt_Exit (unop (Iop_Not1, 16170 binop (Iop_CmpLT32U, 16171 getIReg (rs), 16172 getIReg (rt))), 16173 Ijk_SigFPE_IntDiv, 16174 IRConst_U32(guest_PC_curr_instr + 4), 16175 OFFB_PC)); 16176 else if (trap_code == 6) 16177 stmt (IRStmt_Exit (unop (Iop_Not1, 16178 binop (Iop_CmpLT32U, 16179 getIReg (rs), 16180 getIReg (rt))), 16181 Ijk_SigFPE_IntOvf, 16182 IRConst_U32(guest_PC_curr_instr + 4), 16183 OFFB_PC)); 16184 else 16185 stmt (IRStmt_Exit (unop (Iop_Not1, 16186 binop (Iop_CmpLT32U, 16187 getIReg (rs), 16188 getIReg (rt))), 16189 Ijk_SigTRAP, 16190 IRConst_U32(guest_PC_curr_instr + 4), 16191 OFFB_PC)); 16192 } 16193 break; 16194 } 16195 case 0x32: { /* TLT */ 16196 DIP("tlt r%u, r%u %u", rs, rt, trap_code); 16197 if (mode64) { 16198 if (trap_code == 7) 16199 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16200 getIReg(rt)), Ijk_SigFPE_IntDiv, 16201 IRConst_U64(guest_PC_curr_instr + 4), 16202 OFFB_PC)); 16203 else if (trap_code == 6) 16204 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16205 getIReg(rt)), Ijk_SigFPE_IntOvf, 16206 IRConst_U64(guest_PC_curr_instr + 4), 16207 OFFB_PC)); 16208 else 16209 stmt(IRStmt_Exit(binop(Iop_CmpLT64S, getIReg(rs), 16210 getIReg(rt)), Ijk_SigTRAP, 16211 IRConst_U64(guest_PC_curr_instr + 4), 16212 OFFB_PC)); 16213 } else { 16214 if (trap_code == 7) 16215 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16216 getIReg(rt)), Ijk_SigFPE_IntDiv, 16217 IRConst_U32(guest_PC_curr_instr + 4), 16218 OFFB_PC)); 16219 else if (trap_code == 6) 16220 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16221 getIReg(rt)), Ijk_SigFPE_IntOvf, 16222 IRConst_U32(guest_PC_curr_instr + 4), 16223 OFFB_PC)); 16224 else 16225 stmt(IRStmt_Exit(binop(Iop_CmpLT32S, getIReg(rs), 16226 getIReg(rt)), Ijk_SigTRAP, 16227 IRConst_U32(guest_PC_curr_instr + 4), 16228 OFFB_PC)); 16229 } 16230 break; 16231 } 16232 case 0x33: { /* TLTU */ 16233 DIP("tltu r%u, r%u %u", rs, rt, trap_code); 16234 if (mode64) { 16235 if (trap_code == 7) 16236 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16237 getIReg(rt)), Ijk_SigFPE_IntDiv, 16238 IRConst_U64(guest_PC_curr_instr + 4), 16239 OFFB_PC)); 16240 else if (trap_code == 6) 16241 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16242 getIReg(rt)), Ijk_SigFPE_IntOvf, 16243 IRConst_U64(guest_PC_curr_instr + 4), 16244 OFFB_PC)); 16245 else 16246 stmt(IRStmt_Exit(binop(Iop_CmpLT64U, getIReg(rs), 16247 getIReg(rt)), Ijk_SigTRAP, 16248 IRConst_U64(guest_PC_curr_instr + 4), 16249 OFFB_PC)); 16250 } else { 16251 if (trap_code == 7) 16252 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16253 getIReg(rt)), Ijk_SigFPE_IntDiv, 16254 IRConst_U32(guest_PC_curr_instr + 4), 16255 OFFB_PC)); 16256 else if (trap_code == 6) 16257 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16258 getIReg(rt)), Ijk_SigFPE_IntOvf, 16259 IRConst_U32(guest_PC_curr_instr + 4), 16260 OFFB_PC)); 16261 else 16262 stmt(IRStmt_Exit(binop(Iop_CmpLT32U, getIReg(rs), 16263 getIReg (rt)), Ijk_SigTRAP, 16264 IRConst_U32(guest_PC_curr_instr + 4), 16265 OFFB_PC)); 16266 } 16267 break; 16268 } 16269 case 0x34: { /* TEQ */ 16270 DIP("teq r%u, r%u, %u", rs, rt, trap_code); 16271 if (mode64) { 16272 if (trap_code == 7) 16273 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16274 getIReg(rt)), Ijk_SigFPE_IntDiv, 16275 IRConst_U64(guest_PC_curr_instr + 4), 16276 OFFB_PC)); 16277 else if (trap_code == 6) 16278 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16279 getIReg(rt)), Ijk_SigFPE_IntOvf, 16280 IRConst_U64(guest_PC_curr_instr + 4), 16281 OFFB_PC)); 16282 else 16283 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, getIReg(rs), 16284 getIReg(rt)), Ijk_SigTRAP, 16285 IRConst_U64(guest_PC_curr_instr + 4), 16286 OFFB_PC)); 16287 } else { 16288 if (trap_code == 7) 16289 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16290 getIReg(rt)), Ijk_SigFPE_IntDiv, 16291 IRConst_U32(guest_PC_curr_instr + 4), 16292 OFFB_PC)); 16293 else if (trap_code == 6) 16294 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16295 getIReg(rt)), Ijk_SigFPE_IntOvf, 16296 IRConst_U32(guest_PC_curr_instr + 4), 16297 OFFB_PC)); 16298 else 16299 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, getIReg(rs), 16300 getIReg(rt)), Ijk_SigTRAP, 16301 IRConst_U32(guest_PC_curr_instr + 4), 16302 OFFB_PC)); 16303 } 16304 break; 16305 } 16306 case 0x36: { /* TNE */ 16307 DIP("tne r%u, r%u %u", rs, rt, trap_code); 16308 if (mode64) { 16309 if (trap_code == 7) 16310 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16311 getIReg(rt)), Ijk_SigFPE_IntDiv, 16312 IRConst_U64(guest_PC_curr_instr + 4), 16313 OFFB_PC)); 16314 else if (trap_code == 6) 16315 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16316 getIReg(rt)), Ijk_SigFPE_IntOvf, 16317 IRConst_U64(guest_PC_curr_instr + 4), 16318 OFFB_PC)); 16319 else 16320 stmt(IRStmt_Exit(binop(Iop_CmpNE64, getIReg(rs), 16321 getIReg(rt)), Ijk_SigTRAP, 16322 IRConst_U64(guest_PC_curr_instr + 4), 16323 OFFB_PC)); 16324 } else { 16325 if (trap_code == 7) 16326 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16327 getIReg(rt)), Ijk_SigFPE_IntDiv, 16328 IRConst_U32(guest_PC_curr_instr + 4), 16329 OFFB_PC)); 16330 else if (trap_code == 6) 16331 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16332 getIReg(rt)), Ijk_SigFPE_IntOvf, 16333 IRConst_U32(guest_PC_curr_instr + 4), 16334 OFFB_PC)); 16335 else 16336 stmt(IRStmt_Exit(binop(Iop_CmpNE32, getIReg(rs), 16337 getIReg(rt)), Ijk_SigTRAP, 16338 IRConst_U32(guest_PC_curr_instr + 4), 16339 OFFB_PC)); 16340 } 16341 break; 16342 } 16343 case 0x14: 16344 case 0x16: 16345 case 0x17: /* DSLLV, DROTRV:DSRLV, DSRAV */ 16346 case 0x38: 16347 case 0x3A: 16348 case 0x3B: /* DSLL, DROTL:DSRL, DSRA */ 16349 case 0x3C: 16350 case 0x3E: 16351 case 0x3F: /* DSLL32, DROTR32:DSRL32, DSRA32 */ 16352 if (dis_instr_shrt(cins)) 16353 break; 16354 goto decode_failure; 16355 16356 case 0x0F: /* SYNC */ 16357 DIP("sync 0x%x", sel); 16358 /* Just ignore it. */ 16359 break; 16360 16361 case 0x2C: { /* Doubleword Add - DADD; MIPS64 */ 16362 DIP("dadd r%u, r%u, r%u", rd, rs, rt); 16363 IRTemp tmpRs64 = newTemp(Ity_I64); 16364 IRTemp tmpRt64 = newTemp(Ity_I64); 16365 16366 assign(tmpRs64, getIReg(rs)); 16367 assign(tmpRt64, getIReg(rt)); 16368 16369 t0 = newTemp(Ity_I64); 16370 t1 = newTemp(Ity_I64); 16371 t2 = newTemp(Ity_I64); 16372 t3 = newTemp(Ity_I64); 16373 t4 = newTemp(Ity_I64); 16374 /* dst = src0 + src1 16375 if(sign(src0 ) != sign(src1 )) 16376 goto no overflow; 16377 if(sign(dst) == sign(src0 )) 16378 goto no overflow; 16379 we have overflow! */ 16380 16381 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(tmpRt64))); 16382 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(tmpRt64))); 16383 assign(t2, unop(Iop_1Uto64, 16384 binop(Iop_CmpEQ64, 16385 binop(Iop_And64, mkexpr(t1), 16386 mkU64(0x8000000000000000ULL)), 16387 mkU64(0x8000000000000000ULL)))); 16388 16389 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16390 assign(t4, unop(Iop_1Uto64, 16391 binop(Iop_CmpNE64, 16392 binop(Iop_And64, mkexpr(t3), 16393 mkU64(0x8000000000000000ULL)), 16394 mkU64(0x8000000000000000ULL)))); 16395 16396 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, 16397 binop(Iop_Or64, mkexpr(t2), mkexpr(t4)), 16398 mkU64(0)), 16399 Ijk_SigFPE_IntOvf, 16400 IRConst_U64(guest_PC_curr_instr + 4), 16401 OFFB_PC)); 16402 16403 putIReg(rd, mkexpr(t0)); 16404 break; 16405 } 16406 16407 case 0x2D: /* Doubleword Add Unsigned - DADDU; MIPS64 */ 16408 DIP("daddu r%u, r%u, r%u", rd, rs, rt); 16409 ALU_PATTERN(Iop_Add64); 16410 break; 16411 16412 case 0x2E: { /* Doubleword Subtract - DSUB; MIPS64 */ 16413 DIP("dsub r%u, r%u, r%u", rd, rs, rt); 16414 IRTemp tmpRs64 = newTemp(Ity_I64); 16415 IRTemp tmpRt64 = newTemp(Ity_I64); 16416 16417 assign(tmpRs64, getIReg(rs)); 16418 assign(tmpRt64, getIReg(rt)); 16419 t0 = newTemp(Ity_I64); 16420 t1 = newTemp(Ity_I64); 16421 t2 = newTemp(Ity_I64); 16422 t3 = newTemp(Ity_I64); 16423 t4 = newTemp(Ity_I64); 16424 t5 = newTemp(Ity_I64); 16425 /* dst = src0 + (-1 * src1) 16426 if(sign(src0 ) != sign((-1 * src1) )) 16427 goto no overflow; 16428 if(sign(dst) == sign(src0 )) 16429 goto no overflow; 16430 we have overflow! */ 16431 16432 assign(t5, binop(Iop_Mul64, 16433 mkexpr(tmpRt64), 16434 mkU64(0xffffffffffffffffULL))); 16435 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), mkexpr(t5))); 16436 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), mkexpr(t5))); 16437 assign(t2, unop(Iop_1Sto64, 16438 binop(Iop_CmpEQ64, 16439 binop(Iop_And64, 16440 mkexpr(t1), 16441 mkU64(0x8000000000000000ULL)), 16442 mkU64(0x8000000000000000ULL)))); 16443 16444 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16445 assign(t4, unop(Iop_1Sto64, 16446 binop(Iop_CmpNE64, 16447 binop(Iop_And64, 16448 mkexpr(t3), 16449 mkU64(0x8000000000000000ULL)), 16450 mkU64(0x8000000000000000ULL)))); 16451 16452 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2), 16453 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf, 16454 IRConst_U64(guest_PC_curr_instr + 4), 16455 OFFB_PC)); 16456 16457 putIReg(rd, binop(Iop_Sub64, getIReg(rs), getIReg(rt))); 16458 break; 16459 } 16460 16461 case 0x2F: /* Doubleword Subtract Unsigned - DSUBU; MIPS64 */ 16462 DIP("dsub r%u, r%u,r%u", rd, rt, rt); 16463 ALU_PATTERN(Iop_Sub64); 16464 break; 16465 16466 default: 16467 goto decode_failure; 16468 } 16469 break; 16470 16471 case 0x01: /* Regimm */ 16472 16473 switch (rt) { 16474 case 0x00: /* BLTZ */ 16475 DIP("bltz r%u, %u", rs, imm); 16476 if (mode64) { 16477 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16478 callback_opaque, &bstmt)) 16479 goto decode_failure; 16480 } else 16481 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16482 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 16483 break; 16484 16485 case 0x01: /* BGEZ */ 16486 DIP("bgez r%u, %u", rs, imm); 16487 if (mode64) { 16488 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16489 callback_opaque, &bstmt)) 16490 goto decode_failure; 16491 } else 16492 dis_branch(False, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16493 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 16494 break; 16495 16496 case 0x02: /* BLTZL */ 16497 DIP("bltzl r%u, %u", rs, imm); 16498 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16499 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16500 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16501 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16502 imm); 16503 break; 16504 16505 case 0x03: /* BGEZL */ 16506 DIP("bgezl r%u, %u", rs, imm); 16507 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16508 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16509 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16510 mode64 ? mkU64(0x0) : mkU32(0x0)), imm); 16511 break; 16512 16513 case 0x10: /* BLTZAL */ 16514 DIP("bltzal r%u, %u", rs, imm); 16515 if (mode64) { 16516 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16517 callback_opaque, &bstmt)) 16518 goto decode_failure; 16519 } else 16520 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16521 mkU32(0x80000000)), mkU32(0x80000000)), imm, &bstmt); 16522 break; 16523 16524 case 0x12: /* BLTZALL */ 16525 DIP("bltzall r%u, %u", rs, imm); 16526 putIReg(31, mode64 ? mkU64(guest_PC_curr_instr + 8) : 16527 mkU32(guest_PC_curr_instr + 8)); 16528 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16529 binop(mode64 ? Iop_And64 : Iop_And32, getIReg(rs), 16530 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16531 mode64 ? mkU64(0x8000000000000000ULL) : mkU32(0x80000000)), 16532 imm); 16533 break; 16534 16535 case 0x11: /* BGEZAL */ 16536 DIP("bgezal r%u, %u", rs, imm); 16537 if (mode64) { 16538 if (!dis_instr_branch(cins, &dres, resteerOkFn, 16539 callback_opaque, &bstmt)) 16540 goto decode_failure; 16541 } else 16542 dis_branch(True, binop(Iop_CmpEQ32, binop(Iop_And32, getIReg(rs), 16543 mkU32(0x80000000)), mkU32(0x0)), imm, &bstmt); 16544 break; 16545 16546 case 0x13: /* BGEZALL */ 16547 DIP("bgezall r%u, %u", rs, imm); 16548 if (mode64) { 16549 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 16550 lastn = dis_branch_likely(binop(Iop_CmpNE64, 16551 binop(Iop_And64, 16552 getIReg(rs), 16553 mkU64(0x8000000000000000ULL)), 16554 mkU64(0x0)), 16555 imm); 16556 } else { 16557 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 16558 lastn = dis_branch_likely(binop(Iop_CmpNE32, binop(Iop_And32, 16559 getIReg(rs), mkU32(0x80000000)), 16560 mkU32(0x0)), imm); 16561 } 16562 break; 16563 16564 case 0x08: /* TGEI */ 16565 DIP("tgei r%u, %u %u", rs, imm, trap_code); 16566 if (mode64) { 16567 stmt (IRStmt_Exit (unop (Iop_Not1, 16568 binop (Iop_CmpLT64S, 16569 getIReg (rs), 16570 mkU64 (extend_s_16to64 (imm)))), 16571 Ijk_SigTRAP, 16572 IRConst_U64(guest_PC_curr_instr + 4), 16573 OFFB_PC)); 16574 } else { 16575 stmt (IRStmt_Exit (unop (Iop_Not1, 16576 binop (Iop_CmpLT32S, 16577 getIReg (rs), 16578 mkU32 (extend_s_16to32 (imm)))), 16579 Ijk_SigTRAP, 16580 IRConst_U32(guest_PC_curr_instr + 4), 16581 OFFB_PC)); 16582 } 16583 break; 16584 16585 case 0x09: { /* TGEIU */ 16586 DIP("tgeiu r%u, %u %u", rs, imm, trap_code); 16587 if (mode64) { 16588 stmt (IRStmt_Exit (unop (Iop_Not1, 16589 binop (Iop_CmpLT64U, 16590 getIReg (rs), 16591 mkU64 (extend_s_16to64 (imm)))), 16592 Ijk_SigTRAP, 16593 IRConst_U64(guest_PC_curr_instr + 4), 16594 OFFB_PC)); 16595 } else { 16596 stmt (IRStmt_Exit (unop (Iop_Not1, 16597 binop (Iop_CmpLT32U, 16598 getIReg (rs), 16599 mkU32 (extend_s_16to32 (imm)))), 16600 Ijk_SigTRAP, 16601 IRConst_U32(guest_PC_curr_instr + 4), 16602 OFFB_PC)); 16603 } 16604 break; 16605 } 16606 case 0x0A: { /* TLTI */ 16607 DIP("tlti r%u, %u %u", rs, imm, trap_code); 16608 if (mode64) { 16609 stmt (IRStmt_Exit (binop (Iop_CmpLT64S, getIReg (rs), 16610 mkU64 (extend_s_16to64 (imm))), 16611 Ijk_SigTRAP, 16612 IRConst_U64(guest_PC_curr_instr + 4), 16613 OFFB_PC)); 16614 } else { 16615 stmt (IRStmt_Exit (binop (Iop_CmpLT32S, getIReg (rs), 16616 mkU32 (extend_s_16to32 (imm))), 16617 Ijk_SigTRAP, 16618 IRConst_U32(guest_PC_curr_instr + 4), 16619 OFFB_PC)); 16620 } 16621 break; 16622 } 16623 case 0x0B: { /* TLTIU */ 16624 DIP("tltiu r%u, %u %u", rs, imm, trap_code); 16625 if (mode64) { 16626 stmt (IRStmt_Exit (binop (Iop_CmpLT64U, getIReg (rs), 16627 mkU64 (extend_s_16to64 (imm))), 16628 Ijk_SigTRAP, 16629 IRConst_U64(guest_PC_curr_instr + 4), 16630 OFFB_PC)); 16631 } else { 16632 stmt (IRStmt_Exit (binop (Iop_CmpLT32U, getIReg (rs), 16633 mkU32 (extend_s_16to32 (imm))), 16634 Ijk_SigTRAP, 16635 IRConst_U32(guest_PC_curr_instr + 4), 16636 OFFB_PC)); 16637 } 16638 break; 16639 } 16640 case 0x0C: { /* TEQI */ 16641 DIP("teqi r%u, %u %u", rs, imm, trap_code); 16642 if (mode64) { 16643 stmt (IRStmt_Exit (binop (Iop_CmpEQ64, getIReg (rs), 16644 mkU64 (extend_s_16to64 (imm))), 16645 Ijk_SigTRAP, 16646 IRConst_U64(guest_PC_curr_instr + 4), 16647 OFFB_PC)); 16648 } else { 16649 stmt (IRStmt_Exit (binop (Iop_CmpEQ32, getIReg (rs), 16650 mkU32 (extend_s_16to32 (imm))), 16651 Ijk_SigTRAP, 16652 IRConst_U32(guest_PC_curr_instr + 4), 16653 OFFB_PC)); 16654 } 16655 break; 16656 } 16657 case 0x0E: { /* TNEI */ 16658 DIP("tnei r%u, %u %u", rs, imm, trap_code); 16659 if (mode64) { 16660 stmt (IRStmt_Exit (binop (Iop_CmpNE64, getIReg (rs), 16661 mkU64 (extend_s_16to64 (imm))), 16662 Ijk_SigTRAP, 16663 IRConst_U64(guest_PC_curr_instr + 4), 16664 OFFB_PC)); 16665 } else { 16666 stmt (IRStmt_Exit (binop (Iop_CmpNE32, getIReg (rs), 16667 mkU32 (extend_s_16to32 (imm))), 16668 Ijk_SigTRAP, 16669 IRConst_U32(guest_PC_curr_instr + 4), 16670 OFFB_PC)); 16671 } 16672 break; 16673 } 16674 case 0x1C: { /* BPOSGE32 */ 16675 DIP("bposge32 %u", imm); 16676 vassert(!mode64); 16677 t0 = newTemp(Ity_I32); 16678 /* Get pos field from DSPControl register. */ 16679 assign(t0, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 16680 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLT32U, mkexpr(t0), 16681 mkU32(32))), imm, &bstmt); 16682 } 16683 case 0x1F: 16684 /* SYNCI */ 16685 /* Just ignore it */ 16686 break; 16687 16688 default: 16689 goto decode_failure; 16690 } 16691 break; 16692 16693 case 0x04: 16694 DIP("beq r%u, r%u, %u", rs, rt, imm); 16695 if (mode64) 16696 dis_branch(False, binop(Iop_CmpEQ64, getIReg(rs), getIReg(rt)), 16697 imm, &bstmt); 16698 else 16699 dis_branch(False, binop(Iop_CmpEQ32, getIReg(rs), getIReg(rt)), 16700 imm, &bstmt); 16701 break; 16702 16703 case 0x14: 16704 DIP("beql r%u, r%u, %u", rs, rt, imm); 16705 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 16706 getIReg(rs), getIReg(rt)), imm); 16707 break; 16708 16709 case 0x05: 16710 DIP("bne r%u, r%u, %u", rs, rt, imm); 16711 if (mode64) 16712 dis_branch(False, binop(Iop_CmpNE64, getIReg(rs), getIReg(rt)), 16713 imm, &bstmt); 16714 else 16715 dis_branch(False, binop(Iop_CmpNE32, getIReg(rs), getIReg(rt)), 16716 imm, &bstmt); 16717 break; 16718 16719 case 0x15: 16720 DIP("bnel r%u, r%u, %u", rs, rt, imm); 16721 lastn = dis_branch_likely(binop(mode64 ? Iop_CmpEQ64 : Iop_CmpEQ32, 16722 getIReg(rs), getIReg(rt)), imm); 16723 break; 16724 16725 case 0x07: /* BGTZ */ 16726 DIP("bgtz r%u, %u", rs, imm); 16727 if (mode64) 16728 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(rs), 16729 mkU64(0x00))), imm, &bstmt); 16730 else 16731 dis_branch(False, unop(Iop_Not1, binop(Iop_CmpLE32S, getIReg(rs), 16732 mkU32(0x00))), imm, &bstmt); 16733 break; 16734 16735 case 0x17: /* BGTZL */ 16736 DIP("bgtzl r%u, %u", rs, imm); 16737 if (mode64) 16738 lastn = dis_branch_likely(binop(Iop_CmpLE64S, getIReg(rs), 16739 mkU64(0x00)), imm); 16740 else 16741 lastn = dis_branch_likely(binop(Iop_CmpLE32S, getIReg(rs), 16742 mkU32(0x00)), imm); 16743 break; 16744 16745 case 0x06: /* BLEZ */ 16746 DIP("blez r%u, %u", rs, imm); 16747 if (mode64) 16748 dis_branch(False, binop(Iop_CmpLE64S, getIReg(rs), mkU64(0x0)), 16749 imm, &bstmt); 16750 else 16751 dis_branch(False,binop(Iop_CmpLE32S, getIReg(rs), mkU32(0x0)), imm, 16752 &bstmt); 16753 break; 16754 16755 case 0x16: /* BLEZL */ 16756 DIP("blezl r%u, %u", rs, imm); 16757 lastn = dis_branch_likely(unop(Iop_Not1, (binop(mode64 ? Iop_CmpLE64S : 16758 Iop_CmpLE32S, getIReg(rs), mode64 ? 16759 mkU64(0x0) : mkU32(0x0)))), imm); 16760 break; 16761 16762 case 0x08: { /* ADDI */ 16763 DIP("addi r%u, r%u, %u", rt, rs, imm); 16764 IRTemp tmpRs32 = newTemp(Ity_I32); 16765 assign(tmpRs32, mkNarrowTo32(ty, getIReg(rs))); 16766 16767 t0 = newTemp(Ity_I32); 16768 t1 = newTemp(Ity_I32); 16769 t2 = newTemp(Ity_I32); 16770 t3 = newTemp(Ity_I32); 16771 t4 = newTemp(Ity_I32); 16772 /* dst = src0 + sign(imm) 16773 if(sign(src0 ) != sign(imm )) 16774 goto no overflow; 16775 if(sign(dst) == sign(src0 )) 16776 goto no overflow; 16777 we have overflow! */ 16778 16779 assign(t0, binop(Iop_Add32, mkexpr(tmpRs32), 16780 mkU32(extend_s_16to32(imm)))); 16781 assign(t1, binop(Iop_Xor32, mkexpr(tmpRs32), 16782 mkU32(extend_s_16to32(imm)))); 16783 assign(t2, unop(Iop_1Sto32, binop(Iop_CmpEQ32, binop(Iop_And32, 16784 mkexpr(t1), mkU32(0x80000000)), mkU32(0x80000000)))); 16785 16786 assign(t3, binop(Iop_Xor32, mkexpr(t0), mkexpr(tmpRs32))); 16787 assign(t4, unop(Iop_1Sto32, binop(Iop_CmpNE32, binop(Iop_And32, 16788 mkexpr(t3), mkU32(0x80000000)), mkU32(0x80000000)))); 16789 16790 stmt(IRStmt_Exit(binop(Iop_CmpEQ32, binop(Iop_Or32, mkexpr(t2), 16791 mkexpr(t4)), mkU32(0)), Ijk_SigFPE_IntOvf, 16792 mode64 ? IRConst_U64(guest_PC_curr_instr + 4) : 16793 IRConst_U32(guest_PC_curr_instr + 4), 16794 OFFB_PC)); 16795 16796 putIReg(rt, mkWidenFrom32(ty, mkexpr(t0), True)); 16797 break; 16798 } 16799 case 0x09: /* ADDIU */ 16800 DIP("addiu r%u, r%u, %u", rt, rs, imm); 16801 if (mode64) { 16802 putIReg(rt, mkWidenFrom32(ty, binop(Iop_Add32, 16803 mkNarrowTo32(ty, getIReg(rs)),mkU32(extend_s_16to32(imm))), 16804 True)); 16805 } else 16806 putIReg(rt, binop(Iop_Add32, getIReg(rs),mkU32(extend_s_16to32(imm)))); 16807 break; 16808 16809 case 0x0C: /* ANDI */ 16810 DIP("andi r%u, r%u, %u", rt, rs, imm); 16811 if (mode64) { 16812 ALUI_PATTERN64(Iop_And64); 16813 } else { 16814 ALUI_PATTERN(Iop_And32); 16815 } 16816 break; 16817 16818 case 0x0E: /* XORI */ 16819 DIP("xori r%u, r%u, %u", rt, rs, imm); 16820 if (mode64) { 16821 ALUI_PATTERN64(Iop_Xor64); 16822 } else { 16823 ALUI_PATTERN(Iop_Xor32); 16824 } 16825 break; 16826 16827 case 0x0D: /* ORI */ 16828 DIP("ori r%u, r%u, %u", rt, rs, imm); 16829 if (mode64) { 16830 ALUI_PATTERN64(Iop_Or64); 16831 } else { 16832 ALUI_PATTERN(Iop_Or32); 16833 } 16834 break; 16835 16836 case 0x0A: /* SLTI */ 16837 DIP("slti r%u, r%u, %u", rt, rs, imm); 16838 if (mode64) 16839 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(rs), 16840 mkU64(extend_s_16to64(imm))))); 16841 else 16842 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32S, getIReg(rs), 16843 mkU32(extend_s_16to32(imm))))); 16844 break; 16845 16846 case 0x0B: /* SLTIU */ 16847 DIP("sltiu r%u, r%u, %u", rt, rs, imm); 16848 if (mode64) 16849 putIReg(rt, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(rs), 16850 mkU64(extend_s_16to64(imm))))); 16851 else 16852 putIReg(rt, unop(Iop_1Uto32, binop(Iop_CmpLT32U, getIReg(rs), 16853 mkU32(extend_s_16to32(imm))))); 16854 break; 16855 16856 case 0x18: { /* Doubleword Add Immidiate - DADD; MIPS64 */ 16857 DIP("daddi r%u, r%u, %u", rt, rs, imm); 16858 IRTemp tmpRs64 = newTemp(Ity_I64); 16859 assign(tmpRs64, getIReg(rs)); 16860 16861 t0 = newTemp(Ity_I64); 16862 t1 = newTemp(Ity_I64); 16863 t2 = newTemp(Ity_I64); 16864 t3 = newTemp(Ity_I64); 16865 t4 = newTemp(Ity_I64); 16866 /* dst = src0 + sign(imm) 16867 if(sign(src0 ) != sign(imm )) 16868 goto no overflow; 16869 if(sign(dst) == sign(src0 )) 16870 goto no overflow; 16871 we have overflow! */ 16872 16873 assign(t0, binop(Iop_Add64, mkexpr(tmpRs64), 16874 mkU64(extend_s_16to64(imm)))); 16875 assign(t1, binop(Iop_Xor64, mkexpr(tmpRs64), 16876 mkU64(extend_s_16to64(imm)))); 16877 assign(t2, unop(Iop_1Sto64, binop(Iop_CmpEQ64, binop(Iop_And64, 16878 mkexpr(t1), mkU64(0x8000000000000000ULL)), 16879 mkU64(0x8000000000000000ULL)))); 16880 16881 assign(t3, binop(Iop_Xor64, mkexpr(t0), mkexpr(tmpRs64))); 16882 assign(t4, unop(Iop_1Sto64, binop(Iop_CmpNE64, binop(Iop_And64, 16883 mkexpr(t3), mkU64(0x8000000000000000ULL)), 16884 mkU64(0x8000000000000000ULL)))); 16885 16886 stmt(IRStmt_Exit(binop(Iop_CmpEQ64, binop(Iop_Or64, mkexpr(t2), 16887 mkexpr(t4)), mkU64(0)), Ijk_SigFPE_IntOvf, 16888 IRConst_U64(guest_PC_curr_instr + 4), 16889 OFFB_PC)); 16890 16891 putIReg(rt, mkexpr(t0)); 16892 break; 16893 } 16894 16895 case 0x19: /* Doubleword Add Immidiate Unsigned - DADDIU; MIPS64 */ 16896 DIP("daddiu r%u, r%u, %u", rt, rs, imm); 16897 putIReg(rt, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16898 break; 16899 16900 case 0x1A: { 16901 /* Load Doubleword Left - LDL; MIPS64 */ 16902 vassert(mode64); 16903 DIP("ldl r%u, %u(r%u)", rt, imm, rs); 16904 /* t1 = addr */ 16905 #if defined (_MIPSEL) 16906 t1 = newTemp(Ity_I64); 16907 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16908 #elif defined (_MIPSEB) 16909 t1 = newTemp(Ity_I64); 16910 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs), 16911 mkU64(extend_s_16to64(imm))))); 16912 #endif 16913 /* t2 = word addr */ 16914 /* t4 = addr mod 8 */ 16915 LWX_SWX_PATTERN64_1; 16916 16917 /* t3 = word content - shifted */ 16918 t3 = newTemp(Ity_I64); 16919 assign(t3, binop(Iop_Shl64, load(Ity_I64, mkexpr(t2)), 16920 narrowTo(Ity_I8, binop(Iop_Shl64, binop(Iop_Sub64, mkU64(0x07), 16921 mkexpr(t4)), mkU8(3))))); 16922 16923 /* rt content - adjusted */ 16924 t5 = newTemp(Ity_I64); 16925 t6 = newTemp(Ity_I64); 16926 t7 = newTemp(Ity_I64); 16927 16928 assign(t5, binop(Iop_Mul64, mkexpr(t4), mkU64(0x8))); 16929 16930 assign(t6, binop(Iop_Shr64, mkU64(0x00FFFFFFFFFFFFFFULL), 16931 narrowTo(Ity_I8, mkexpr(t5)))); 16932 16933 assign(t7, binop(Iop_And64, getIReg(rt), mkexpr(t6))); 16934 16935 putIReg(rt, binop(Iop_Or64, mkexpr(t7), mkexpr(t3))); 16936 break; 16937 } 16938 16939 case 0x1B: { 16940 /* Load Doubleword Right - LDR; MIPS64 */ 16941 vassert(mode64); 16942 DIP("ldr r%u,%u(r%u)", rt, imm, rs); 16943 /* t1 = addr */ 16944 #if defined (_MIPSEL) 16945 t1 = newTemp(Ity_I64); 16946 assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))); 16947 #elif defined (_MIPSEB) 16948 t1 = newTemp(Ity_I64); 16949 assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs), 16950 mkU64(extend_s_16to64(imm))))); 16951 #endif 16952 /* t2 = word addr */ 16953 /* t4 = addr mod 8 */ 16954 LWX_SWX_PATTERN64_1; 16955 16956 /* t3 = word content - shifted */ 16957 t3 = newTemp(Ity_I64); 16958 assign(t3, binop(Iop_Shr64, load(Ity_I64, mkexpr(t2)), 16959 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(3))))); 16960 16961 /* rt content - adjusted */ 16962 t5 = newTemp(Ity_I64); 16963 assign(t5, binop(Iop_And64, getIReg(rt), unop(Iop_Not64, 16964 binop(Iop_Shr64, mkU64(0xFFFFFFFFFFFFFFFFULL), 16965 narrowTo(Ity_I8, binop(Iop_Shl64, mkexpr(t4), mkU8(0x3))))))); 16966 16967 putIReg(rt, binop(Iop_Or64, mkexpr(t5), mkexpr(t3))); 16968 break; 16969 } 16970 16971 case 0x27: /* Load Word unsigned - LWU; MIPS64 */ 16972 DIP("lwu r%u,%u(r%u)", rt, imm, rs); 16973 LOAD_STORE_PATTERN; 16974 16975 putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False)); 16976 break; 16977 16978 case 0x30: /* LL */ 16979 DIP("ll r%u, %u(r%u)", rt, imm, rs); 16980 LOAD_STORE_PATTERN; 16981 if (abiinfo->guest__use_fallback_LLSC) { 16982 t2 = newTemp(ty); 16983 assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True)); 16984 putLLaddr(mkexpr(t1)); 16985 putLLdata(mkexpr(t2)); 16986 putIReg(rt, mkexpr(t2)); 16987 } else { 16988 t2 = newTemp(Ity_I32); 16989 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL)); 16990 putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True)); 16991 } 16992 break; 16993 16994 case 0x34: /* Load Linked Doubleword - LLD; MIPS64 */ 16995 DIP("lld r%u, %u(r%u)", rt, imm, rs); 16996 if (mode64) { 16997 LOAD_STORE_PATTERN; 16998 t2 = newTemp(Ity_I64); 16999 if (abiinfo->guest__use_fallback_LLSC) { 17000 assign(t2, load(Ity_I64, mkexpr(t1))); 17001 putLLaddr(mkexpr(t1)); 17002 putLLdata(mkexpr(t2)); 17003 } else { 17004 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL)); 17005 } 17006 putIReg(rt, mkexpr(t2)); 17007 } else { 17008 ILLEGAL_INSTRUCTON; 17009 } 17010 break; 17011 17012 case 0x38: /* SC */ 17013 DIP("sc r%u, %u(r%u)", rt, imm, rs); 17014 t2 = newTemp(Ity_I1); 17015 LOAD_STORE_PATTERN; 17016 if (abiinfo->guest__use_fallback_LLSC) { 17017 t3 = newTemp(Ity_I32); 17018 assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32, 17019 mkexpr(t1), getLLaddr())); 17020 assign(t3, mkNarrowTo32(ty, getIReg(rt))); 17021 putLLaddr(LLADDR_INVALID); 17022 putIReg(rt, getIReg(0)); 17023 17024 mips_next_insn_if(mkexpr(t2)); 17025 17026 t4 = newTemp(Ity_I32); 17027 t5 = newTemp(Ity_I32); 17028 17029 assign(t5, mkNarrowTo32(ty, getLLdata())); 17030 17031 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */ 17032 MIPS_IEND, mkexpr(t1), /* addr */ 17033 NULL, mkexpr(t5), /* expected value */ 17034 NULL, mkexpr(t3) /* new value */))); 17035 17036 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, 17037 binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5)))); 17038 } else { 17039 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), 17040 mkNarrowTo32(ty, getIReg(rt)))); 17041 putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2))); 17042 } 17043 break; 17044 17045 case 0x3C: /* Store Conditional Doubleword - SCD; MIPS64 */ 17046 DIP("scd r%u, %u(r%u)", rt, imm, rs); 17047 if (mode64) { 17048 t2 = newTemp(Ity_I1); 17049 LOAD_STORE_PATTERN; 17050 if (abiinfo->guest__use_fallback_LLSC) { 17051 t3 = newTemp(Ity_I64); 17052 assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr())); 17053 assign(t3, getIReg(rt)); 17054 putLLaddr(LLADDR_INVALID); 17055 putIReg(rt, getIReg(0)); 17056 17057 mips_next_insn_if(mkexpr(t2)); 17058 17059 t4 = newTemp(Ity_I64); 17060 t5 = newTemp(Ity_I64); 17061 17062 assign(t5, getLLdata()); 17063 17064 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */ 17065 MIPS_IEND, mkexpr(t1), /* addr */ 17066 NULL, mkexpr(t5), /* expected value */ 17067 NULL, mkexpr(t3) /* new value */))); 17068 17069 putIReg(rt, unop(Iop_1Uto64, 17070 binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5)))); 17071 } else { 17072 stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt))); 17073 putIReg(rt, unop(Iop_1Uto64, mkexpr(t2))); 17074 } 17075 } else { 17076 ILLEGAL_INSTRUCTON; 17077 } 17078 break; 17079 17080 case 0x37: /* Load Doubleword - LD; MIPS64 */ 17081 DIP("ld r%u, %u(r%u)", rt, imm, rs); 17082 LOAD_STORE_PATTERN; 17083 putIReg(rt, load(Ity_I64, mkexpr(t1))); 17084 break; 17085 17086 case 0x3F: /* Store Doubleword - SD; MIPS64 */ 17087 DIP("sd r%u, %u(r%u)", rt, imm, rs); 17088 LOAD_STORE_PATTERN; 17089 store(mkexpr(t1), getIReg(rt)); 17090 break; 17091 17092 case 0x32: /* Branch on Bit Clear - BBIT0; Cavium OCTEON */ 17093 /* Cavium Specific instructions. */ 17094 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17095 DIP("bbit0 r%u, 0x%x, %x", rs, rt, imm); 17096 t0 = newTemp(Ity_I32); 17097 t1 = newTemp(Ity_I32); 17098 assign(t0, mkU32(0x1)); 17099 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt))); 17100 dis_branch(False, binop(Iop_CmpEQ32, 17101 binop(Iop_And32, 17102 mkexpr(t1), 17103 mkNarrowTo32(ty, getIReg(rs))), 17104 mkU32(0x0)), 17105 imm, &bstmt); 17106 break; 17107 } else { 17108 goto decode_failure; 17109 } 17110 17111 case 0x36: /* Branch on Bit Clear Plus 32 - BBIT032; Cavium OCTEON */ 17112 /* Cavium Specific instructions. */ 17113 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17114 DIP("bbit032 r%u, 0x%x, %x", rs, rt, imm); 17115 t0 = newTemp(Ity_I64); 17116 t1 = newTemp(Ity_I8); /* Shift. */ 17117 t2 = newTemp(Ity_I64); 17118 assign(t0, mkU64(0x1)); 17119 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32))); 17120 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1))); 17121 dis_branch(False, binop(Iop_CmpEQ64, 17122 binop(Iop_And64, 17123 mkexpr(t2), 17124 getIReg(rs)), 17125 mkU64(0x0)), 17126 imm, &bstmt); 17127 break; 17128 } else { 17129 goto decode_failure; 17130 } 17131 17132 case 0x3A: /* Branch on Bit Set - BBIT1; Cavium OCTEON */ 17133 /* Cavium Specific instructions. */ 17134 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17135 DIP("bbit1 r%u, 0x%x, %x", rs, rt, imm); 17136 t0 = newTemp(Ity_I32); 17137 t1 = newTemp(Ity_I32); 17138 assign(t0, mkU32(0x1)); 17139 assign(t1, binop(Iop_Shl32, mkexpr(t0), mkU8(rt))); 17140 dis_branch(False, binop(Iop_CmpNE32, 17141 binop(Iop_And32, 17142 mkexpr(t1), 17143 mkNarrowTo32(ty, getIReg(rs))), 17144 mkU32(0x0)), 17145 imm, &bstmt); 17146 break; 17147 } else { 17148 goto decode_failure; 17149 } 17150 17151 case 0x3E: /* Branch on Bit Set Plus 32 - BBIT132; Cavium OCTEON */ 17152 /* Cavium Specific instructions. */ 17153 if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) { 17154 DIP("bbit132 r%u, 0x%x, %x", rs, rt, imm); 17155 t0 = newTemp(Ity_I64); 17156 t1 = newTemp(Ity_I8); /* Shift. */ 17157 t2 = newTemp(Ity_I64); 17158 assign(t0, mkU64(0x1)); 17159 assign(t1, binop(Iop_Add8, mkU8(rt), mkU8(32))); 17160 assign(t2, binop(Iop_Shl64, mkexpr(t0), mkexpr(t1))); 17161 dis_branch(False, binop(Iop_CmpNE64, 17162 binop(Iop_And64, 17163 mkexpr(t2), 17164 getIReg(rs)), 17165 mkU64(0x0)), 17166 imm, &bstmt); 17167 break; 17168 } else { 17169 goto decode_failure; 17170 } 17171 17172 default: 17173 goto decode_failure; 17174 17175 decode_failure_dsp: 17176 vex_printf("Error occured while trying to decode MIPS32 DSP " 17177 "instruction.\nYour platform probably doesn't support " 17178 "MIPS32 DSP ASE.\n"); 17179 decode_failure: 17180 /* All decode failures end up here. */ 17181 if (sigill_diag) 17182 vex_printf("vex mips->IR: unhandled instruction bytes: " 17183 "0x%x 0x%x 0x%x 0x%x\n", 17184 (UInt) getIByte(delta_start + 0), 17185 (UInt) getIByte(delta_start + 1), 17186 (UInt) getIByte(delta_start + 2), 17187 (UInt) getIByte(delta_start + 3)); 17188 17189 /* Tell the dispatcher that this insn cannot be decoded, and so has 17190 not been executed, and (is currently) the next to be executed. 17191 EIP should be up-to-date since it made so at the start bnezof each 17192 insn, but nevertheless be paranoid and update it again right 17193 now. */ 17194 if (mode64) { 17195 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_PC), 17196 mkU64(guest_PC_curr_instr))); 17197 jmp_lit64(&dres, Ijk_NoDecode, guest_PC_curr_instr); 17198 } else { 17199 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_PC), 17200 mkU32(guest_PC_curr_instr))); 17201 jmp_lit32(&dres, Ijk_NoDecode, guest_PC_curr_instr); 17202 } 17203 dres.whatNext = Dis_StopHere; 17204 dres.len = 0; 17205 return dres; 17206 } /* switch (opc) for the main (primary) opcode switch. */ 17207 17208 /* All MIPS insn have 4 bytes */ 17209 17210 if (delay_slot_branch) { 17211 delay_slot_branch = False; 17212 stmt(bstmt); 17213 bstmt = NULL; 17214 if (mode64) 17215 putPC(mkU64(guest_PC_curr_instr + 4)); 17216 else 17217 putPC(mkU32(guest_PC_curr_instr + 4)); 17218 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 17219 Ijk_Call : Ijk_Boring; 17220 } 17221 17222 if (likely_delay_slot) { 17223 dres.jk_StopHere = Ijk_Boring; 17224 dres.whatNext = Dis_StopHere; 17225 putPC(lastn); 17226 lastn = NULL; 17227 } 17228 if (delay_slot_jump) { 17229 putPC(lastn); 17230 lastn = NULL; 17231 dres.jk_StopHere = is_Branch_or_Jump_and_Link(guest_code + delta - 4) ? 17232 Ijk_Call : Ijk_Boring; 17233 } 17234 17235 decode_success: 17236 /* All decode successes end up here. */ 17237 switch (dres.whatNext) { 17238 case Dis_Continue: 17239 if (mode64) 17240 putPC(mkU64(guest_PC_curr_instr + 4)); 17241 else 17242 putPC(mkU32(guest_PC_curr_instr + 4)); 17243 break; 17244 case Dis_ResteerU: 17245 case Dis_ResteerC: 17246 if (mode64) 17247 putPC(mkU64(dres.continueAt)); 17248 else 17249 putPC(mkU32(dres.continueAt)); 17250 break; 17251 case Dis_StopHere: 17252 break; 17253 default: 17254 vassert(0); 17255 break; 17256 } 17257 17258 /* On MIPS we need to check if the last instruction in block is branch or 17259 jump. */ 17260 if (((vex_control.guest_max_insns - 1) == (delta + 4) / 4) 17261 && (dres.whatNext != Dis_StopHere)) 17262 if (branch_or_jump(guest_code + delta + 4)) { 17263 dres.whatNext = Dis_StopHere; 17264 dres.jk_StopHere = Ijk_Boring; 17265 if (mode64) 17266 putPC(mkU64(guest_PC_curr_instr + 4)); 17267 else 17268 putPC(mkU32(guest_PC_curr_instr + 4)); 17269 } 17270 dres.len = 4; 17271 17272 DIP("\n"); 17273 17274 return dres; 17275 17276 } 17277 17278 /*------------------------------------------------------------*/ 17279 /*--- Top-level fn ---*/ 17280 /*------------------------------------------------------------*/ 17281 17282 /* Disassemble a single instruction into IR. The instruction 17283 is located in host memory at &guest_code[delta]. */ 17284 DisResult disInstr_MIPS( IRSB* irsb_IN, 17285 Bool (*resteerOkFn) ( void *, Addr ), 17286 Bool resteerCisOk, 17287 void* callback_opaque, 17288 const UChar* guest_code_IN, 17289 Long delta, 17290 Addr guest_IP, 17291 VexArch guest_arch, 17292 const VexArchInfo* archinfo, 17293 const VexAbiInfo* abiinfo, 17294 VexEndness host_endness_IN, 17295 Bool sigill_diag_IN ) 17296 { 17297 DisResult dres; 17298 /* Set globals (see top of this file) */ 17299 vassert(guest_arch == VexArchMIPS32 || guest_arch == VexArchMIPS64); 17300 17301 mode64 = guest_arch != VexArchMIPS32; 17302 fp_mode64 = abiinfo->guest_mips_fp_mode64; 17303 17304 vassert(VEX_MIPS_HOST_FP_MODE(archinfo->hwcaps) >= fp_mode64); 17305 17306 guest_code = guest_code_IN; 17307 irsb = irsb_IN; 17308 host_endness = host_endness_IN; 17309 #if defined(VGP_mips32_linux) 17310 guest_PC_curr_instr = (Addr32)guest_IP; 17311 #elif defined(VGP_mips64_linux) 17312 guest_PC_curr_instr = (Addr64)guest_IP; 17313 #endif 17314 17315 dres = disInstr_MIPS_WRK(resteerOkFn, resteerCisOk, callback_opaque, 17316 delta, archinfo, abiinfo, sigill_diag_IN); 17317 17318 return dres; 17319 } 17320 17321 /*--------------------------------------------------------------------*/ 17322 /*--- end guest_mips_toIR.c ---*/ 17323 /*--------------------------------------------------------------------*/ 17324