1 2 /*--------------------------------------------------------------------*/ 3 /*--- begin guest_mips_toIR.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2010-2015 RT-RK 11 mips-valgrind (at) rt-rk.com 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 /* Translates MIPS code to IR. */ 32 33 #include "libvex_basictypes.h" 34 #include "libvex_ir.h" 35 #include "libvex.h" 36 #include "libvex_guest_mips32.h" 37 #include "libvex_guest_mips64.h" 38 39 #include "main_util.h" 40 #include "main_globals.h" 41 #include "guest_generic_bb_to_IR.h" 42 #include "guest_mips_defs.h" 43 44 /*------------------------------------------------------------*/ 45 /*--- Globals ---*/ 46 /*------------------------------------------------------------*/ 47 48 /* These are set at the start of the translation of a instruction, so 49 that we don't have to pass them around endlessly. CONST means does 50 not change during translation of the instruction. */ 51 52 /* CONST: what is the host's endianness? This has to do with float vs 53 double register accesses on VFP, but it's complex and not properly 54 thought out. */ 55 static VexEndness host_endness; 56 57 /* Pointer to the guest code area. */ 58 static const UChar *guest_code; 59 60 /* CONST: The guest address for the instruction currently being 61 translated. */ 62 #if defined(VGP_mips32_linux) 63 static Addr32 guest_PC_curr_instr; 64 #else 65 static Addr64 guest_PC_curr_instr; 66 #endif 67 68 /* MOD: The IRSB* into which we're generating code. */ 69 static IRSB *irsb; 70 71 /* Is our guest binary 32 or 64bit? Set at each call to 72 disInstr_MIPS below. */ 73 static Bool mode64 = False; 74 75 /* CPU has FPU and 32 dbl. prec. FP registers. */ 76 static Bool fp_mode64 = False; 77 78 /* Define 1.0 in single and double precision. */ 79 #define ONE_SINGLE 0x3F800000 80 #define ONE_DOUBLE 0x3FF0000000000000ULL 81 82 /*------------------------------------------------------------*/ 83 /*--- Debugging output ---*/ 84 /*------------------------------------------------------------*/ 85 86 #define DIP(format, args...) \ 87 if (vex_traceflags & VEX_TRACE_FE) \ 88 vex_printf(format, ## args) 89 90 /*------------------------------------------------------------*/ 91 /*--- Helper bits and pieces for deconstructing the ---*/ 92 /*--- mips insn stream. ---*/ 93 /*------------------------------------------------------------*/ 94 95 /* ---------------- Integer registers ---------------- */ 96 97 static UInt integerGuestRegOffset(UInt iregNo) 98 { 99 /* Do we care about endianness here? We do if sub-parts of integer 100 registers are accessed, but I don't think that ever happens on 101 MIPS. */ 102 UInt ret; 103 if (!mode64) 104 switch (iregNo) { 105 case 0: 106 ret = offsetof(VexGuestMIPS32State, guest_r0); break; 107 case 1: 108 ret = offsetof(VexGuestMIPS32State, guest_r1); break; 109 case 2: 110 ret = offsetof(VexGuestMIPS32State, guest_r2); break; 111 case 3: 112 ret = offsetof(VexGuestMIPS32State, guest_r3); break; 113 case 4: 114 ret = offsetof(VexGuestMIPS32State, guest_r4); break; 115 case 5: 116 ret = offsetof(VexGuestMIPS32State, guest_r5); break; 117 case 6: 118 ret = offsetof(VexGuestMIPS32State, guest_r6); break; 119 case 7: 120 ret = offsetof(VexGuestMIPS32State, guest_r7); break; 121 case 8: 122 ret = offsetof(VexGuestMIPS32State, guest_r8); break; 123 case 9: 124 ret = offsetof(VexGuestMIPS32State, guest_r9); break; 125 case 10: 126 ret = offsetof(VexGuestMIPS32State, guest_r10); break; 127 case 11: 128 ret = offsetof(VexGuestMIPS32State, guest_r11); break; 129 case 12: 130 ret = offsetof(VexGuestMIPS32State, guest_r12); break; 131 case 13: 132 ret = offsetof(VexGuestMIPS32State, guest_r13); break; 133 case 14: 134 ret = offsetof(VexGuestMIPS32State, guest_r14); break; 135 case 15: 136 ret = offsetof(VexGuestMIPS32State, guest_r15); break; 137 case 16: 138 ret = offsetof(VexGuestMIPS32State, guest_r16); break; 139 case 17: 140 ret = offsetof(VexGuestMIPS32State, guest_r17); break; 141 case 18: 142 ret = offsetof(VexGuestMIPS32State, guest_r18); break; 143 case 19: 144 ret = offsetof(VexGuestMIPS32State, guest_r19); break; 145 case 20: 146 ret = offsetof(VexGuestMIPS32State, guest_r20); break; 147 case 21: 148 ret = offsetof(VexGuestMIPS32State, guest_r21); break; 149 case 22: 150 ret = offsetof(VexGuestMIPS32State, guest_r22); break; 151 case 23: 152 ret = offsetof(VexGuestMIPS32State, guest_r23); break; 153 case 24: 154 ret = offsetof(VexGuestMIPS32State, guest_r24); break; 155 case 25: 156 ret = offsetof(VexGuestMIPS32State, guest_r25); break; 157 case 26: 158 ret = offsetof(VexGuestMIPS32State, guest_r26); break; 159 case 27: 160 ret = offsetof(VexGuestMIPS32State, guest_r27); break; 161 case 28: 162 ret = offsetof(VexGuestMIPS32State, guest_r28); break; 163 case 29: 164 ret = offsetof(VexGuestMIPS32State, guest_r29); break; 165 case 30: 166 ret = offsetof(VexGuestMIPS32State, guest_r30); break; 167 case 31: 168 ret = offsetof(VexGuestMIPS32State, guest_r31); break; 169 default: 170 vassert(0); 171 break; 172 } 173 else 174 switch (iregNo) { 175 case 0: 176 ret = offsetof(VexGuestMIPS64State, guest_r0); break; 177 case 1: 178 ret = offsetof(VexGuestMIPS64State, guest_r1); break; 179 case 2: 180 ret = offsetof(VexGuestMIPS64State, guest_r2); break; 181 case 3: 182 ret = offsetof(VexGuestMIPS64State, guest_r3); break; 183 case 4: 184 ret = offsetof(VexGuestMIPS64State, guest_r4); break; 185 case 5: 186 ret = offsetof(VexGuestMIPS64State, guest_r5); break; 187 case 6: 188 ret = offsetof(VexGuestMIPS64State, guest_r6); break; 189 case 7: 190 ret = offsetof(VexGuestMIPS64State, guest_r7); break; 191 case 8: 192 ret = offsetof(VexGuestMIPS64State, guest_r8); break; 193 case 9: 194 ret = offsetof(VexGuestMIPS64State, guest_r9); break; 195 case 10: 196 ret = offsetof(VexGuestMIPS64State, guest_r10); break; 197 case 11: 198 ret = offsetof(VexGuestMIPS64State, guest_r11); break; 199 case 12: 200 ret = offsetof(VexGuestMIPS64State, guest_r12); break; 201 case 13: 202 ret = offsetof(VexGuestMIPS64State, guest_r13); break; 203 case 14: 204 ret = offsetof(VexGuestMIPS64State, guest_r14); break; 205 case 15: 206 ret = offsetof(VexGuestMIPS64State, guest_r15); break; 207 case 16: 208 ret = offsetof(VexGuestMIPS64State, guest_r16); break; 209 case 17: 210 ret = offsetof(VexGuestMIPS64State, guest_r17); break; 211 case 18: 212 ret = offsetof(VexGuestMIPS64State, guest_r18); break; 213 case 19: 214 ret = offsetof(VexGuestMIPS64State, guest_r19); break; 215 case 20: 216 ret = offsetof(VexGuestMIPS64State, guest_r20); break; 217 case 21: 218 ret = offsetof(VexGuestMIPS64State, guest_r21); break; 219 case 22: 220 ret = offsetof(VexGuestMIPS64State, guest_r22); break; 221 case 23: 222 ret = offsetof(VexGuestMIPS64State, guest_r23); break; 223 case 24: 224 ret = offsetof(VexGuestMIPS64State, guest_r24); break; 225 case 25: 226 ret = offsetof(VexGuestMIPS64State, guest_r25); break; 227 case 26: 228 ret = offsetof(VexGuestMIPS64State, guest_r26); break; 229 case 27: 230 ret = offsetof(VexGuestMIPS64State, guest_r27); break; 231 case 28: 232 ret = offsetof(VexGuestMIPS64State, guest_r28); break; 233 case 29: 234 ret = offsetof(VexGuestMIPS64State, guest_r29); break; 235 case 30: 236 ret = offsetof(VexGuestMIPS64State, guest_r30); break; 237 case 31: 238 ret = offsetof(VexGuestMIPS64State, guest_r31); break; 239 default: 240 vassert(0); 241 break; 242 } 243 return ret; 244 } 245 246 #if defined(VGP_mips32_linux) 247 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC) 248 #else 249 #define OFFB_PC offsetof(VexGuestMIPS64State, guest_PC) 250 #endif 251 252 /* ---------------- Floating point registers ---------------- */ 253 254 static UInt floatGuestRegOffset(UInt fregNo) 255 { 256 vassert(fregNo < 32); 257 UInt ret; 258 if (!mode64) 259 switch (fregNo) { 260 case 0: 261 ret = offsetof(VexGuestMIPS32State, guest_f0); break; 262 case 1: 263 ret = offsetof(VexGuestMIPS32State, guest_f1); break; 264 case 2: 265 ret = offsetof(VexGuestMIPS32State, guest_f2); break; 266 case 3: 267 ret = offsetof(VexGuestMIPS32State, guest_f3); break; 268 case 4: 269 ret = offsetof(VexGuestMIPS32State, guest_f4); break; 270 case 5: 271 ret = offsetof(VexGuestMIPS32State, guest_f5); break; 272 case 6: 273 ret = offsetof(VexGuestMIPS32State, guest_f6); break; 274 case 7: 275 ret = offsetof(VexGuestMIPS32State, guest_f7); break; 276 case 8: 277 ret = offsetof(VexGuestMIPS32State, guest_f8); break; 278 case 9: 279 ret = offsetof(VexGuestMIPS32State, guest_f9); break; 280 case 10: 281 ret = offsetof(VexGuestMIPS32State, guest_f10); break; 282 case 11: 283 ret = offsetof(VexGuestMIPS32State, guest_f11); break; 284 case 12: 285 ret = offsetof(VexGuestMIPS32State, guest_f12); break; 286 case 13: 287 ret = offsetof(VexGuestMIPS32State, guest_f13); break; 288 case 14: 289 ret = offsetof(VexGuestMIPS32State, guest_f14); break; 290 case 15: 291 ret = offsetof(VexGuestMIPS32State, guest_f15); break; 292 case 16: 293 ret = offsetof(VexGuestMIPS32State, guest_f16); break; 294 case 17: 295 ret = offsetof(VexGuestMIPS32State, guest_f17); break; 296 case 18: 297 ret = offsetof(VexGuestMIPS32State, guest_f18); break; 298 case 19: 299 ret = offsetof(VexGuestMIPS32State, guest_f19); break; 300 case 20: 301 ret = offsetof(VexGuestMIPS32State, guest_f20); break; 302 case 21: 303 ret = offsetof(VexGuestMIPS32State, guest_f21); break; 304 case 22: 305 ret = offsetof(VexGuestMIPS32State, guest_f22); break; 306 case 23: 307 ret = offsetof(VexGuestMIPS32State, guest_f23); break; 308 case 24: 309 ret = offsetof(VexGuestMIPS32State, guest_f24); break; 310 case 25: 311 ret = offsetof(VexGuestMIPS32State, guest_f25); break; 312 case 26: 313 ret = offsetof(VexGuestMIPS32State, guest_f26); break; 314 case 27: 315 ret = offsetof(VexGuestMIPS32State, guest_f27); break; 316 case 28: 317 ret = offsetof(VexGuestMIPS32State, guest_f28); break; 318 case 29: 319 ret = offsetof(VexGuestMIPS32State, guest_f29); break; 320 case 30: 321 ret = offsetof(VexGuestMIPS32State, guest_f30); break; 322 case 31: 323 ret = offsetof(VexGuestMIPS32State, guest_f31); break; 324 default: 325 vassert(0); 326 break; 327 } 328 else 329 switch (fregNo) { 330 case 0: 331 ret = offsetof(VexGuestMIPS64State, guest_f0); break; 332 case 1: 333 ret = offsetof(VexGuestMIPS64State, guest_f1); break; 334 case 2: 335 ret = offsetof(VexGuestMIPS64State, guest_f2); break; 336 case 3: 337 ret = offsetof(VexGuestMIPS64State, guest_f3); break; 338 case 4: 339 ret = offsetof(VexGuestMIPS64State, guest_f4); break; 340 case 5: 341 ret = offsetof(VexGuestMIPS64State, guest_f5); break; 342 case 6: 343 ret = offsetof(VexGuestMIPS64State, guest_f6); break; 344 case 7: 345 ret = offsetof(VexGuestMIPS64State, guest_f7); break; 346 case 8: 347 ret = offsetof(VexGuestMIPS64State, guest_f8); break; 348 case 9: 349 ret = offsetof(VexGuestMIPS64State, guest_f9); break; 350 case 10: 351 ret = offsetof(VexGuestMIPS64State, guest_f10); break; 352 case 11: 353 ret = offsetof(VexGuestMIPS64State, guest_f11); break; 354 case 12: 355 ret = offsetof(VexGuestMIPS64State, guest_f12); break; 356 case 13: 357 ret = offsetof(VexGuestMIPS64State, guest_f13); break; 358 case 14: 359 ret = offsetof(VexGuestMIPS64State, guest_f14); break; 360 case 15: 361 ret = offsetof(VexGuestMIPS64State, guest_f15); break; 362 case 16: 363 ret = offsetof(VexGuestMIPS64State, guest_f16); break; 364 case 17: 365 ret = offsetof(VexGuestMIPS64State, guest_f17); break; 366 case 18: 367 ret = offsetof(VexGuestMIPS64State, guest_f18); break; 368 case 19: 369 ret = offsetof(VexGuestMIPS64State, guest_f19); break; 370 case 20: 371 ret = offsetof(VexGuestMIPS64State, guest_f20); break; 372 case 21: 373 ret = offsetof(VexGuestMIPS64State, guest_f21); break; 374 case 22: 375 ret = offsetof(VexGuestMIPS64State, guest_f22); break; 376 case 23: 377 ret = offsetof(VexGuestMIPS64State, guest_f23); break; 378 case 24: 379 ret = offsetof(VexGuestMIPS64State, guest_f24); break; 380 case 25: 381 ret = offsetof(VexGuestMIPS64State, guest_f25); break; 382 case 26: 383 ret = offsetof(VexGuestMIPS64State, guest_f26); break; 384 case 27: 385 ret = offsetof(VexGuestMIPS64State, guest_f27); break; 386 case 28: 387 ret = offsetof(VexGuestMIPS64State, guest_f28); break; 388 case 29: 389 ret = offsetof(VexGuestMIPS64State, guest_f29); break; 390 case 30: 391 ret = offsetof(VexGuestMIPS64State, guest_f30); break; 392 case 31: 393 ret = offsetof(VexGuestMIPS64State, guest_f31); break; 394 default: 395 vassert(0); 396 break; 397 } 398 return ret; 399 } 400 401 /* ---------------- MIPS32 DSP ASE(r2) accumulators ---------------- */ 402 403 static UInt accumulatorGuestRegOffset(UInt acNo) 404 { 405 vassert(!mode64); 406 vassert(acNo <= 3); 407 UInt ret; 408 switch (acNo) { 409 case 0: 410 ret = offsetof(VexGuestMIPS32State, guest_ac0); break; 411 case 1: 412 ret = offsetof(VexGuestMIPS32State, guest_ac1); break; 413 case 2: 414 ret = offsetof(VexGuestMIPS32State, guest_ac2); break; 415 case 3: 416 ret = offsetof(VexGuestMIPS32State, guest_ac3); break; 417 default: 418 vassert(0); 419 break; 420 } 421 return ret; 422 } 423 424 /* Do a endian load of a 32-bit word, regardless of the endianness of the 425 underlying host. */ 426 static inline UInt getUInt(const UChar * p) 427 { 428 UInt w = 0; 429 #if defined (_MIPSEL) 430 w = (w << 8) | p[3]; 431 w = (w << 8) | p[2]; 432 w = (w << 8) | p[1]; 433 w = (w << 8) | p[0]; 434 #elif defined (_MIPSEB) 435 w = (w << 8) | p[0]; 436 w = (w << 8) | p[1]; 437 w = (w << 8) | p[2]; 438 w = (w << 8) | p[3]; 439 #endif 440 return w; 441 } 442 443 #define BITS2(_b1,_b0) \ 444 (((_b1) << 1) | (_b0)) 445 446 #define BITS3(_b2,_b1,_b0) \ 447 (((_b2) << 2) | ((_b1) << 1) | (_b0)) 448 449 #define BITS4(_b3,_b2,_b1,_b0) \ 450 (((_b3) << 3) | ((_b2) << 2) | ((_b1) << 1) | (_b0)) 451 452 #define BITS5(_b4,_b3,_b2,_b1,_b0) \ 453 (((_b4) << 4) | BITS4((_b3),(_b2),(_b1),(_b0))) 454 455 #define BITS6(_b5,_b4,_b3,_b2,_b1,_b0) \ 456 ((BITS2((_b5),(_b4)) << 4) \ 457 | BITS4((_b3),(_b2),(_b1),(_b0))) 458 459 #define BITS8(_b7,_b6,_b5,_b4,_b3,_b2,_b1,_b0) \ 460 ((BITS4((_b7),(_b6),(_b5),(_b4)) << 4) \ 461 | BITS4((_b3),(_b2),(_b1),(_b0))) 462 463 #define LOAD_STORE_PATTERN \ 464 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \ 465 if(!mode64) \ 466 assign(t1, binop(Iop_Add32, getIReg(rs), \ 467 mkU32(extend_s_16to32(imm)))); \ 468 else \ 469 assign(t1, binop(Iop_Add64, getIReg(rs), \ 470 mkU64(extend_s_16to64(imm)))); \ 471 472 #define LOADX_STORE_PATTERN \ 473 t1 = newTemp(mode64 ? Ity_I64 : Ity_I32); \ 474 if(!mode64) \ 475 assign(t1, binop(Iop_Add32, getIReg(regRs), getIReg(regRt))); \ 476 else \ 477 assign(t1, binop(Iop_Add64, getIReg(regRs), getIReg(regRt))); 478 479 #define LWX_SWX_PATTERN64 \ 480 t2 = newTemp(Ity_I64); \ 481 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFFCULL))); \ 482 t4 = newTemp(Ity_I32); \ 483 assign(t4, mkNarrowTo32( ty, binop(Iop_And64, \ 484 mkexpr(t1), mkU64(0x3)))); 485 486 #define LWX_SWX_PATTERN64_1 \ 487 t2 = newTemp(Ity_I64); \ 488 assign(t2, binop(Iop_And64, mkexpr(t1), mkU64(0xFFFFFFFFFFFFFFF8ULL))); \ 489 t4 = newTemp(Ity_I64); \ 490 assign(t4, binop(Iop_And64, mkexpr(t1), mkU64(0x7))); 491 492 #define LWX_SWX_PATTERN \ 493 t2 = newTemp(Ity_I32); \ 494 assign(t2, binop(Iop_And32, mkexpr(t1), mkU32(0xFFFFFFFC))); \ 495 t4 = newTemp(Ity_I32); \ 496 assign(t4, binop(Iop_And32, mkexpr(t1), mkU32(0x00000003))) 497 498 #define SXXV_PATTERN(op) \ 499 putIReg(rd, binop(op, \ 500 getIReg(rt), \ 501 unop(Iop_32to8, \ 502 binop(Iop_And32, \ 503 getIReg(rs), \ 504 mkU32(0x0000001F) \ 505 ) \ 506 ) \ 507 ) \ 508 ) 509 510 #define SXXV_PATTERN64(op) \ 511 putIReg(rd, mkWidenFrom32(ty, binop(op, \ 512 mkNarrowTo32(ty, getIReg(rt)), \ 513 unop(Iop_32to8, \ 514 binop(Iop_And32, \ 515 mkNarrowTo32(ty, getIReg(rs)), \ 516 mkU32(0x0000001F) \ 517 ) \ 518 ) \ 519 ), True \ 520 )) 521 522 #define SXX_PATTERN(op) \ 523 putIReg(rd, binop(op, getIReg(rt), mkU8(sa))); 524 525 #define ALU_PATTERN(op) \ 526 putIReg(rd, binop(op, getIReg(rs), getIReg(rt))); 527 528 #define ALUI_PATTERN(op) \ 529 putIReg(rt, binop(op, getIReg(rs), mkU32(imm))); 530 531 #define ALUI_PATTERN64(op) \ 532 putIReg(rt, binop(op, getIReg(rs), mkU64(imm))); 533 534 #define ALU_PATTERN64(op) \ 535 putIReg(rd, mkWidenFrom32(ty, binop(op, \ 536 mkNarrowTo32(ty, getIReg(rs)), \ 537 mkNarrowTo32(ty, getIReg(rt))), True)); 538 539 #define FP_CONDITIONAL_CODE \ 540 t3 = newTemp(Ity_I32); \ 541 assign(t3, binop(Iop_And32, \ 542 IRExpr_ITE( binop(Iop_CmpEQ32, mkU32(cc), mkU32(0)), \ 543 binop(Iop_Shr32, getFCSR(), mkU8(23)), \ 544 binop(Iop_Shr32, getFCSR(), mkU8(24+cc))), \ 545 mkU32(0x1))); 546 547 #define ILLEGAL_INSTRUCTON \ 548 putPC(mkU32(guest_PC_curr_instr + 4)); \ 549 dres.jk_StopHere = Ijk_SigILL; \ 550 dres.whatNext = Dis_StopHere; 551 552 /*------------------------------------------------------------*/ 553 /*--- Field helpers ---*/ 554 /*------------------------------------------------------------*/ 555 556 static UInt get_opcode(UInt mipsins) 557 { 558 return (0xFC000000 & mipsins) >> 26; 559 } 560 561 static UInt get_rs(UInt mipsins) 562 { 563 return (0x03E00000 & mipsins) >> 21; 564 } 565 566 static UInt get_rt(UInt mipsins) 567 { 568 return (0x001F0000 & mipsins) >> 16; 569 } 570 571 static UInt get_imm(UInt mipsins) 572 { 573 return (0x0000FFFF & mipsins); 574 } 575 576 static UInt get_instr_index(UInt mipsins) 577 { 578 return (0x03FFFFFF & mipsins); 579 } 580 581 static UInt get_rd(UInt mipsins) 582 { 583 return (0x0000F800 & mipsins) >> 11; 584 } 585 586 static UInt get_sa(UInt mipsins) 587 { 588 return (0x000007C0 & mipsins) >> 6; 589 } 590 591 static UInt get_function(UInt mipsins) 592 { 593 return (0x0000003F & mipsins); 594 } 595 596 static UInt get_ft(UInt mipsins) 597 { 598 return (0x001F0000 & mipsins) >> 16; 599 } 600 601 static UInt get_fs(UInt mipsins) 602 { 603 return (0x0000F800 & mipsins) >> 11; 604 } 605 606 static UInt get_fd(UInt mipsins) 607 { 608 return (0x000007C0 & mipsins) >> 6; 609 } 610 611 static UInt get_mov_cc(UInt mipsins) 612 { 613 return (0x001C0000 & mipsins) >> 18; 614 } 615 616 static UInt get_bc1_cc(UInt mipsins) 617 { 618 return (0x001C0000 & mipsins) >> 18; 619 } 620 621 static UInt get_fpc_cc(UInt mipsins) 622 { 623 return (0x00000700 & mipsins) >> 8; 624 } 625 626 static UInt get_tf(UInt mipsins) 627 { 628 return (0x00010000 & mipsins) >> 16; 629 } 630 631 static UInt get_nd(UInt mipsins) 632 { 633 return (0x00020000 & mipsins) >> 17; 634 } 635 636 static UInt get_fmt(UInt mipsins) 637 { 638 return (0x03E00000 & mipsins) >> 21; 639 } 640 641 static UInt get_FC(UInt mipsins) 642 { 643 return (0x000000F0 & mipsins) >> 4; 644 } 645 646 static UInt get_cond(UInt mipsins) 647 { 648 return (0x0000000F & mipsins); 649 } 650 651 /* for break & syscall */ 652 static UInt get_code(UInt mipsins) 653 { 654 return (0xFFC0 & mipsins) >> 6; 655 } 656 657 static UInt get_lsb(UInt mipsins) 658 { 659 return (0x7C0 & mipsins) >> 6; 660 } 661 662 static UInt get_msb(UInt mipsins) 663 { 664 return (0x0000F800 & mipsins) >> 11; 665 } 666 667 static UInt get_rot(UInt mipsins) 668 { 669 return (0x00200000 & mipsins) >> 21; 670 } 671 672 static UInt get_rotv(UInt mipsins) 673 { 674 return (0x00000040 & mipsins) >> 6; 675 } 676 677 static UInt get_sel(UInt mipsins) 678 { 679 return (0x00000007 & mipsins); 680 } 681 682 /* Get acc number for all MIPS32 DSP ASE(r2) instructions that use them, 683 except for MFHI and MFLO. */ 684 static UInt get_acNo(UInt mipsins) 685 { 686 return (0x00001800 & mipsins) >> 11; 687 } 688 689 /* Get accumulator number for MIPS32 DSP ASEr2 MFHI and MFLO instructions. */ 690 static UInt get_acNo_mfhilo(UInt mipsins) 691 { 692 return (0x00600000 & mipsins) >> 21; 693 } 694 695 /* Get mask field (helper function for wrdsp instruction). */ 696 static UInt get_wrdspMask(UInt mipsins) 697 { 698 return (0x001ff800 & mipsins) >> 11; 699 } 700 701 /* Get mask field (helper function for rddsp instruction). */ 702 static UInt get_rddspMask(UInt mipsins) 703 { 704 return (0x03ff0000 & mipsins) >> 16; 705 } 706 707 /* Get shift field (helper function for DSP ASE instructions). */ 708 static UInt get_shift(UInt mipsins) 709 { 710 return (0x03f00000 & mipsins) >> 20; 711 } 712 713 /* Get immediate field for DSP ASE instructions. */ 714 static UInt get_dspImm(UInt mipsins) 715 { 716 return (0x03ff0000 & mipsins) >> 16; 717 } 718 719 static Bool branch_or_jump(const UChar * addr) 720 { 721 UInt fmt; 722 UInt cins = getUInt(addr); 723 724 UInt opcode = get_opcode(cins); 725 UInt rt = get_rt(cins); 726 UInt function = get_function(cins); 727 728 /* bgtz, blez, bne, beq, jal */ 729 if (opcode == 0x07 || opcode == 0x06 || opcode == 0x05 || opcode == 0x04 730 || opcode == 0x03 || opcode == 0x02) { 731 return True; 732 } 733 734 /* bgez */ 735 if (opcode == 0x01 && rt == 0x01) { 736 return True; 737 } 738 739 /* bgezal */ 740 if (opcode == 0x01 && rt == 0x11) { 741 return True; 742 } 743 744 /* bltzal */ 745 if (opcode == 0x01 && rt == 0x10) { 746 return True; 747 } 748 749 /* bltz */ 750 if (opcode == 0x01 && rt == 0x00) { 751 return True; 752 } 753 754 /* jalr */ 755 if (opcode == 0x00 && function == 0x09) { 756 return True; 757 } 758 759 /* jr */ 760 if (opcode == 0x00 && function == 0x08) { 761 return True; 762 } 763 764 if (opcode == 0x11) { 765 /*bc1f & bc1t */ 766 fmt = get_fmt(cins); 767 if (fmt == 0x08) { 768 return True; 769 } 770 } 771 772 /* bposge32 */ 773 if (opcode == 0x01 && rt == 0x1c) { 774 return True; 775 } 776 777 /* Cavium Specific instructions. */ 778 if (opcode == 0x32 || opcode == 0x3A || opcode == 0x36 || opcode == 0x3E) { 779 /* BBIT0, BBIT1, BBIT032, BBIT132 */ 780 return True; 781 } 782 783 return False; 784 } 785 786 static Bool is_Branch_or_Jump_and_Link(const UChar * addr) 787 { 788 UInt cins = getUInt(addr); 789 790 UInt opcode = get_opcode(cins); 791 UInt rt = get_rt(cins); 792 UInt function = get_function(cins); 793 794 /* jal */ 795 if (opcode == 0x02) { 796 return True; 797 } 798 799 /* bgezal */ 800 if (opcode == 0x01 && rt == 0x11) { 801 return True; 802 } 803 804 /* bltzal */ 805 if (opcode == 0x01 && rt == 0x10) { 806 return True; 807 } 808 809 /* jalr */ 810 if (opcode == 0x00 && function == 0x09) { 811 return True; 812 } 813 814 return False; 815 } 816 817 static Bool branch_or_link_likely(const UChar * addr) 818 { 819 UInt cins = getUInt(addr); 820 UInt opcode = get_opcode(cins); 821 UInt rt = get_rt(cins); 822 823 /* bgtzl, blezl, bnel, beql */ 824 if (opcode == 0x17 || opcode == 0x16 || opcode == 0x15 || opcode == 0x14) 825 return True; 826 827 /* bgezl */ 828 if (opcode == 0x01 && rt == 0x03) 829 return True; 830 831 /* bgezall */ 832 if (opcode == 0x01 && rt == 0x13) 833 return True; 834 835 /* bltzall */ 836 if (opcode == 0x01 && rt == 0x12) 837 return True; 838 839 /* bltzl */ 840 if (opcode == 0x01 && rt == 0x02) 841 return True; 842 843 return False; 844 } 845 846 /*------------------------------------------------------------*/ 847 /*--- Helper bits and pieces for creating IR fragments. ---*/ 848 /*------------------------------------------------------------*/ 849 850 static IRExpr *mkU8(UInt i) 851 { 852 vassert(i < 256); 853 return IRExpr_Const(IRConst_U8((UChar) i)); 854 } 855 856 /* Create an expression node for a 16-bit integer constant. */ 857 static IRExpr *mkU16(UInt i) 858 { 859 return IRExpr_Const(IRConst_U16(i)); 860 } 861 862 /* Create an expression node for a 32-bit integer constant. */ 863 static IRExpr *mkU32(UInt i) 864 { 865 return IRExpr_Const(IRConst_U32(i)); 866 } 867 868 /* Create an expression node for a 64-bit integer constant. */ 869 static IRExpr *mkU64(ULong i) 870 { 871 return IRExpr_Const(IRConst_U64(i)); 872 } 873 874 static IRExpr *mkexpr(IRTemp tmp) 875 { 876 return IRExpr_RdTmp(tmp); 877 } 878 879 static IRExpr *unop(IROp op, IRExpr * a) 880 { 881 return IRExpr_Unop(op, a); 882 } 883 884 static IRExpr *binop(IROp op, IRExpr * a1, IRExpr * a2) 885 { 886 return IRExpr_Binop(op, a1, a2); 887 } 888 889 static IRExpr *triop(IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3) 890 { 891 return IRExpr_Triop(op, a1, a2, a3); 892 } 893 894 static IRExpr *qop ( IROp op, IRExpr * a1, IRExpr * a2, IRExpr * a3, 895 IRExpr * a4 ) 896 { 897 return IRExpr_Qop(op, a1, a2, a3, a4); 898 } 899 900 static IRExpr *load(IRType ty, IRExpr * addr) 901 { 902 IRExpr *load1 = NULL; 903 #if defined (_MIPSEL) 904 load1 = IRExpr_Load(Iend_LE, ty, addr); 905 #elif defined (_MIPSEB) 906 load1 = IRExpr_Load(Iend_BE, ty, addr); 907 #endif 908 return load1; 909 } 910 911 /* Add a statement to the list held by "irsb". */ 912 static void stmt(IRStmt * st) 913 { 914 addStmtToIRSB(irsb, st); 915 } 916 917 static void assign(IRTemp dst, IRExpr * e) 918 { 919 stmt(IRStmt_WrTmp(dst, e)); 920 } 921 922 static void store(IRExpr * addr, IRExpr * data) 923 { 924 #if defined (_MIPSEL) 925 stmt(IRStmt_Store(Iend_LE, addr, data)); 926 #elif defined (_MIPSEB) 927 stmt(IRStmt_Store(Iend_BE, addr, data)); 928 #endif 929 } 930 931 /* Generate a new temporary of the given type. */ 932 static IRTemp newTemp(IRType ty) 933 { 934 vassert(isPlausibleIRType(ty)); 935 return newIRTemp(irsb->tyenv, ty); 936 } 937 938 /* Generate an expression for SRC rotated right by ROT. */ 939 static IRExpr *genROR32(IRExpr * src, Int rot) 940 { 941 vassert(rot >= 0 && rot < 32); 942 if (rot == 0) 943 return src; 944 return binop(Iop_Or32, binop(Iop_Shl32, src, mkU8(32 - rot)), 945 binop(Iop_Shr32, src, mkU8(rot))); 946 } 947 948 static IRExpr *genRORV32(IRExpr * src, IRExpr * rs) 949 { 950 IRTemp t0 = newTemp(Ity_I8); 951 IRTemp t1 = newTemp(Ity_I8); 952 953 assign(t0, unop(Iop_32to8, binop(Iop_And32, rs, mkU32(0x0000001F)))); 954 assign(t1, binop(Iop_Sub8, mkU8(32), mkexpr(t0))); 955 return binop(Iop_Or32, binop(Iop_Shl32, src, mkexpr(t1)), 956 binop(Iop_Shr32, src, mkexpr(t0))); 957 } 958 959 static UShort extend_s_10to16(UInt x) 960 { 961 return (UShort) ((((Int) x) << 22) >> 22); 962 } 963 964 static ULong extend_s_10to32(UInt x) 965 { 966 return (ULong)((((Long) x) << 22) >> 22); 967 } 968 969 static ULong extend_s_10to64(UInt x) 970 { 971 return (ULong)((((Long) x) << 54) >> 54); 972 } 973 974 static UInt extend_s_16to32(UInt x) 975 { 976 return (UInt) ((((Int) x) << 16) >> 16); 977 } 978 979 static UInt extend_s_18to32(UInt x) 980 { 981 return (UInt) ((((Int) x) << 14) >> 14); 982 } 983 984 static ULong extend_s_16to64 ( UInt x ) 985 { 986 return (ULong) ((((Long) x) << 48) >> 48); 987 } 988 989 static ULong extend_s_18to64 ( UInt x ) 990 { 991 return (ULong) ((((Long) x) << 46) >> 46); 992 } 993 994 static ULong extend_s_32to64 ( UInt x ) 995 { 996 return (ULong) ((((Long) x) << 32) >> 32); 997 } 998 999 static void jmp_lit32 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr32 d32 ) 1000 { 1001 vassert(dres->whatNext == Dis_Continue); 1002 vassert(dres->len == 0); 1003 vassert(dres->continueAt == 0); 1004 vassert(dres->jk_StopHere == Ijk_INVALID); 1005 dres->whatNext = Dis_StopHere; 1006 dres->jk_StopHere = kind; 1007 stmt( IRStmt_Put( OFFB_PC, mkU32(d32) ) ); 1008 } 1009 1010 static void jmp_lit64 ( /*MOD*/ DisResult* dres, IRJumpKind kind, Addr64 d64 ) 1011 { 1012 vassert(dres->whatNext == Dis_Continue); 1013 vassert(dres->len == 0); 1014 vassert(dres->continueAt == 0); 1015 vassert(dres->jk_StopHere == Ijk_INVALID); 1016 dres->whatNext = Dis_StopHere; 1017 dres->jk_StopHere = kind; 1018 stmt(IRStmt_Put(OFFB_PC, mkU64(d64))); 1019 } 1020 1021 /* Get value from accumulator (helper function for MIPS32 DSP ASE instructions). 1022 This function should be called before any other operation if widening 1023 multiplications are used. */ 1024 static IRExpr *getAcc(UInt acNo) 1025 { 1026 vassert(!mode64); 1027 vassert(acNo <= 3); 1028 return IRExpr_Get(accumulatorGuestRegOffset(acNo), Ity_I64); 1029 } 1030 1031 /* Get value from DSPControl register (helper function for MIPS32 DSP ASE 1032 instructions). */ 1033 static IRExpr *getDSPControl(void) 1034 { 1035 vassert(!mode64); 1036 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_DSPControl), Ity_I32); 1037 } 1038 1039 /* Put value to DSPControl register. Expression e is written to DSPControl as 1040 is. If only certain bits of DSPControl need to be changed, it should be done 1041 before calling putDSPControl(). It could be done by reading DSPControl and 1042 ORing it with appropriate mask. */ 1043 static void putDSPControl(IRExpr * e) 1044 { 1045 vassert(!mode64); 1046 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_DSPControl), e)); 1047 } 1048 1049 /* Fetch a byte from the guest insn stream. */ 1050 static UChar getIByte(Int delta) 1051 { 1052 return guest_code[delta]; 1053 } 1054 1055 static IRExpr *getIReg(UInt iregNo) 1056 { 1057 if (0 == iregNo) { 1058 return mode64 ? mkU64(0x0) : mkU32(0x0); 1059 } else { 1060 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1061 vassert(iregNo < 32); 1062 return IRExpr_Get(integerGuestRegOffset(iregNo), ty); 1063 } 1064 } 1065 1066 static IRExpr *getHI(void) 1067 { 1068 if (mode64) 1069 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_HI), Ity_I64); 1070 else 1071 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_HI), Ity_I32); 1072 } 1073 1074 static IRExpr *getLO(void) 1075 { 1076 if (mode64) 1077 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LO), Ity_I64); 1078 else 1079 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LO), Ity_I32); 1080 } 1081 1082 static IRExpr *getFCSR(void) 1083 { 1084 if (mode64) 1085 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_FCSR), Ity_I32); 1086 else 1087 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32); 1088 } 1089 1090 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */ 1091 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos) 1092 { 1093 UInt pos = byte_pos * 8; 1094 if (mode64) 1095 return unop(Iop_64to8, binop(Iop_And64, 1096 binop(Iop_Shr64, getIReg(reg), mkU8(pos)), 1097 mkU64(0xFF))); 1098 else 1099 return unop(Iop_32to8, binop(Iop_And32, 1100 binop(Iop_Shr32, getIReg(reg), mkU8(pos)), 1101 mkU32(0xFF))); 1102 } 1103 1104 static void putFCSR(IRExpr * e) 1105 { 1106 if (mode64) 1107 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_FCSR), e)); 1108 else 1109 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e)); 1110 } 1111 1112 /* fs - fpu source register number. 1113 inst - fpu instruction that needs to be executed. 1114 sz32 - size of source register. 1115 opN - number of operads: 1116 1 - unary operation. 1117 2 - binary operation. */ 1118 static void calculateFCSR(UInt fs, UInt ft, UInt inst, Bool sz32, UInt opN) 1119 { 1120 IRDirty *d; 1121 IRTemp fcsr = newTemp(Ity_I32); 1122 /* IRExpr_BBPTR() => Need to pass pointer to guest state to helper. */ 1123 if (fp_mode64) 1124 d = unsafeIRDirty_1_N(fcsr, 0, 1125 "mips_dirtyhelper_calculate_FCSR_fp64", 1126 &mips_dirtyhelper_calculate_FCSR_fp64, 1127 mkIRExprVec_4(IRExpr_BBPTR(), 1128 mkU32(fs), 1129 mkU32(ft), 1130 mkU32(inst))); 1131 else 1132 d = unsafeIRDirty_1_N(fcsr, 0, 1133 "mips_dirtyhelper_calculate_FCSR_fp32", 1134 &mips_dirtyhelper_calculate_FCSR_fp32, 1135 mkIRExprVec_4(IRExpr_BBPTR(), 1136 mkU32(fs), 1137 mkU32(ft), 1138 mkU32(inst))); 1139 1140 if (opN == 1) { /* Unary operation. */ 1141 /* Declare we're reading guest state. */ 1142 if (sz32 || fp_mode64) 1143 d->nFxState = 2; 1144 else 1145 d->nFxState = 3; 1146 vex_bzero(&d->fxState, sizeof(d->fxState)); 1147 1148 d->fxState[0].fx = Ifx_Read; /* read */ 1149 if (mode64) 1150 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1151 else 1152 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1153 d->fxState[0].size = sizeof(UInt); 1154 d->fxState[1].fx = Ifx_Read; /* read */ 1155 d->fxState[1].offset = floatGuestRegOffset(fs); 1156 d->fxState[1].size = sizeof(ULong); 1157 1158 if (!(sz32 || fp_mode64)) { 1159 d->fxState[2].fx = Ifx_Read; /* read */ 1160 d->fxState[2].offset = floatGuestRegOffset(fs+1); 1161 d->fxState[2].size = sizeof(ULong); 1162 } 1163 } else if (opN == 2) { /* Binary operation. */ 1164 /* Declare we're reading guest state. */ 1165 if (sz32 || fp_mode64) 1166 d->nFxState = 3; 1167 else 1168 d->nFxState = 5; 1169 vex_bzero(&d->fxState, sizeof(d->fxState)); 1170 1171 d->fxState[0].fx = Ifx_Read; /* read */ 1172 if (mode64) 1173 d->fxState[0].offset = offsetof(VexGuestMIPS64State, guest_FCSR); 1174 else 1175 d->fxState[0].offset = offsetof(VexGuestMIPS32State, guest_FCSR); 1176 d->fxState[0].size = sizeof(UInt); 1177 d->fxState[1].fx = Ifx_Read; /* read */ 1178 d->fxState[1].offset = floatGuestRegOffset(fs); 1179 d->fxState[1].size = sizeof(ULong); 1180 d->fxState[2].fx = Ifx_Read; /* read */ 1181 d->fxState[2].offset = floatGuestRegOffset(ft); 1182 d->fxState[2].size = sizeof(ULong); 1183 1184 if (!(sz32 || fp_mode64)) { 1185 d->fxState[3].fx = Ifx_Read; /* read */ 1186 d->fxState[3].offset = floatGuestRegOffset(fs+1); 1187 d->fxState[3].size = sizeof(ULong); 1188 d->fxState[4].fx = Ifx_Read; /* read */ 1189 d->fxState[4].offset = floatGuestRegOffset(ft+1); 1190 d->fxState[4].size = sizeof(ULong); 1191 } 1192 } 1193 1194 stmt(IRStmt_Dirty(d)); 1195 1196 putFCSR(mkexpr(fcsr)); 1197 } 1198 1199 static IRExpr *getULR(void) 1200 { 1201 if (mode64) 1202 return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_ULR), Ity_I64); 1203 else 1204 return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_ULR), Ity_I32); 1205 } 1206 1207 static void putIReg(UInt archreg, IRExpr * e) 1208 { 1209 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1210 vassert(archreg < 32); 1211 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1212 if (archreg != 0) 1213 stmt(IRStmt_Put(integerGuestRegOffset(archreg), e)); 1214 } 1215 1216 static IRExpr *mkNarrowTo32(IRType ty, IRExpr * src) 1217 { 1218 vassert(ty == Ity_I32 || ty == Ity_I64); 1219 return ty == Ity_I64 ? unop(Iop_64to32, src) : src; 1220 } 1221 1222 static void putLO(IRExpr * e) 1223 { 1224 if (mode64) { 1225 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LO), e)); 1226 } else { 1227 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LO), e)); 1228 /* Add value to lower 32 bits of ac0 to maintain compatibility between 1229 regular MIPS32 instruction set and MIPS DSP ASE. Keep higher 32bits 1230 unchanged. */ 1231 IRTemp t_lo = newTemp(Ity_I32); 1232 IRTemp t_hi = newTemp(Ity_I32); 1233 assign(t_lo, e); 1234 assign(t_hi, unop(Iop_64HIto32, getAcc(0))); 1235 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1236 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1237 } 1238 } 1239 1240 static void putHI(IRExpr * e) 1241 { 1242 if (mode64) { 1243 stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_HI), e)); 1244 } else { 1245 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_HI), e)); 1246 /* Add value to higher 32 bits of ac0 to maintain compatibility between 1247 regular MIPS32 instruction set and MIPS DSP ASE. Keep lower 32bits 1248 unchanged. */ 1249 IRTemp t_lo = newTemp(Ity_I32); 1250 IRTemp t_hi = newTemp(Ity_I32); 1251 assign(t_hi, e); 1252 assign(t_lo, unop(Iop_64to32, getAcc(0))); 1253 stmt(IRStmt_Put(accumulatorGuestRegOffset(0), 1254 binop(Iop_32HLto64, mkexpr(t_hi), mkexpr(t_lo)))); 1255 } 1256 } 1257 1258 /* Put value to accumulator(helper function for MIPS32 DSP ASE instructions). */ 1259 static void putAcc(UInt acNo, IRExpr * e) 1260 { 1261 vassert(!mode64); 1262 vassert(acNo <= 3); 1263 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I64); 1264 stmt(IRStmt_Put(accumulatorGuestRegOffset(acNo), e)); 1265 /* If acNo = 0, split value to HI and LO regs in order to maintain compatibility 1266 between MIPS32 and MIPS DSP ASE insn sets. */ 1267 if (0 == acNo) { 1268 putLO(unop(Iop_64to32, e)); 1269 putHI(unop(Iop_64HIto32, e)); 1270 } 1271 } 1272 1273 static IRExpr *mkNarrowTo8 ( IRType ty, IRExpr * src ) 1274 { 1275 vassert(ty == Ity_I32 || ty == Ity_I64); 1276 return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src); 1277 } 1278 1279 static void putPC(IRExpr * e) 1280 { 1281 stmt(IRStmt_Put(OFFB_PC, e)); 1282 } 1283 1284 static IRExpr *mkWidenFrom32(IRType ty, IRExpr * src, Bool sined) 1285 { 1286 vassert(ty == Ity_I32 || ty == Ity_I64); 1287 if (ty == Ity_I32) 1288 return src; 1289 return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src); 1290 } 1291 1292 /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some 1293 of these combinations make sense. */ 1294 static IRExpr *narrowTo(IRType dst_ty, IRExpr * e) 1295 { 1296 IRType src_ty = typeOfIRExpr(irsb->tyenv, e); 1297 if (src_ty == dst_ty) 1298 return e; 1299 if (src_ty == Ity_I32 && dst_ty == Ity_I16) 1300 return unop(Iop_32to16, e); 1301 if (src_ty == Ity_I32 && dst_ty == Ity_I8) 1302 return unop(Iop_32to8, e); 1303 if (src_ty == Ity_I64 && dst_ty == Ity_I8) { 1304 vassert(mode64); 1305 return unop(Iop_64to8, e); 1306 } 1307 if (src_ty == Ity_I64 && dst_ty == Ity_I16) { 1308 vassert(mode64); 1309 return unop(Iop_64to16, e); 1310 } 1311 vpanic("narrowTo(mips)"); 1312 return 0; 1313 } 1314 1315 static IRExpr *getLoFromF64(IRType ty, IRExpr * src) 1316 { 1317 vassert(ty == Ity_F32 || ty == Ity_F64); 1318 if (ty == Ity_F64) { 1319 IRTemp t0, t1; 1320 t0 = newTemp(Ity_I64); 1321 t1 = newTemp(Ity_I32); 1322 assign(t0, unop(Iop_ReinterpF64asI64, src)); 1323 assign(t1, unop(Iop_64to32, mkexpr(t0))); 1324 return unop(Iop_ReinterpI32asF32, mkexpr(t1)); 1325 } else 1326 return src; 1327 } 1328 1329 static IRExpr *mkWidenFromF32(IRType ty, IRExpr * src) 1330 { 1331 vassert(ty == Ity_F32 || ty == Ity_F64); 1332 if (ty == Ity_F64) { 1333 IRTemp t0 = newTemp(Ity_I32); 1334 IRTemp t1 = newTemp(Ity_I64); 1335 assign(t0, unop(Iop_ReinterpF32asI32, src)); 1336 assign(t1, binop(Iop_32HLto64, mkU32(0x0), mkexpr(t0))); 1337 return unop(Iop_ReinterpI64asF64, mkexpr(t1)); 1338 } else 1339 return src; 1340 } 1341 1342 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm) 1343 { 1344 ULong branch_offset; 1345 IRTemp t0; 1346 1347 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1348 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1349 is added to the address of the instruction following 1350 the branch (not the branch itself), in the branch delay slot, to form 1351 a PC-relative effective target address. */ 1352 if (mode64) 1353 branch_offset = extend_s_18to64(imm << 2); 1354 else 1355 branch_offset = extend_s_18to32(imm << 2); 1356 1357 t0 = newTemp(Ity_I1); 1358 assign(t0, guard); 1359 1360 if (mode64) 1361 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1362 IRConst_U64(guest_PC_curr_instr + 8), OFFB_PC)); 1363 else 1364 stmt(IRStmt_Exit(mkexpr(t0), Ijk_Boring, 1365 IRConst_U32(guest_PC_curr_instr + 8), OFFB_PC)); 1366 1367 irsb->jumpkind = Ijk_Boring; 1368 1369 if (mode64) 1370 return mkU64(guest_PC_curr_instr + 4 + branch_offset); 1371 else 1372 return mkU32(guest_PC_curr_instr + 4 + branch_offset); 1373 } 1374 1375 static void dis_branch(Bool link, IRExpr * guard, UInt imm, IRStmt ** set) 1376 { 1377 ULong branch_offset; 1378 IRTemp t0; 1379 1380 if (link) { /* LR (GPR31) = addr of the 2nd instr after branch instr */ 1381 if (mode64) 1382 putIReg(31, mkU64(guest_PC_curr_instr + 8)); 1383 else 1384 putIReg(31, mkU32(guest_PC_curr_instr + 8)); 1385 } 1386 1387 /* PC = PC + (SignExtend(signed_immed_24) << 2) 1388 An 18-bit signed offset (the 16-bit offset field shifted left 2 bits) 1389 is added to the address of the instruction following 1390 the branch (not the branch itself), in the branch delay slot, to form 1391 a PC-relative effective target address. */ 1392 1393 if (mode64) 1394 branch_offset = extend_s_18to64(imm << 2); 1395 else 1396 branch_offset = extend_s_18to32(imm << 2); 1397 1398 t0 = newTemp(Ity_I1); 1399 assign(t0, guard); 1400 if (mode64) 1401 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1402 IRConst_U64(guest_PC_curr_instr + 4 + branch_offset), 1403 OFFB_PC); 1404 else 1405 *set = IRStmt_Exit(mkexpr(t0), link ? Ijk_Call : Ijk_Boring, 1406 IRConst_U32(guest_PC_curr_instr + 4 + 1407 (UInt) branch_offset), OFFB_PC); 1408 } 1409 1410 static IRExpr *getFReg(UInt fregNo) 1411 { 1412 vassert(fregNo < 32); 1413 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1414 return IRExpr_Get(floatGuestRegOffset(fregNo), ty); 1415 } 1416 1417 static IRExpr *getDReg(UInt dregNo) 1418 { 1419 vassert(dregNo < 32); 1420 if (fp_mode64) { 1421 return IRExpr_Get(floatGuestRegOffset(dregNo), Ity_F64); 1422 } else { 1423 /* Read a floating point register pair and combine their contents into a 1424 64-bit value */ 1425 IRTemp t0 = newTemp(Ity_F32); 1426 IRTemp t1 = newTemp(Ity_F32); 1427 IRTemp t2 = newTemp(Ity_F64); 1428 IRTemp t3 = newTemp(Ity_I32); 1429 IRTemp t4 = newTemp(Ity_I32); 1430 IRTemp t5 = newTemp(Ity_I64); 1431 1432 assign(t0, getFReg(dregNo)); 1433 assign(t1, getFReg(dregNo + 1)); 1434 1435 assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0))); 1436 assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1))); 1437 assign(t5, binop(Iop_32HLto64, mkexpr(t4), mkexpr(t3))); 1438 assign(t2, unop(Iop_ReinterpI64asF64, mkexpr(t5))); 1439 1440 return mkexpr(t2); 1441 } 1442 } 1443 1444 static void putFReg(UInt dregNo, IRExpr * e) 1445 { 1446 vassert(dregNo < 32); 1447 IRType ty = fp_mode64 ? Ity_F64 : Ity_F32; 1448 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1449 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1450 } 1451 1452 static void putDReg(UInt dregNo, IRExpr * e) 1453 { 1454 if (fp_mode64) { 1455 vassert(dregNo < 32); 1456 IRType ty = Ity_F64; 1457 vassert(typeOfIRExpr(irsb->tyenv, e) == ty); 1458 stmt(IRStmt_Put(floatGuestRegOffset(dregNo), e)); 1459 } else { 1460 vassert(dregNo < 32); 1461 vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64); 1462 IRTemp t1 = newTemp(Ity_F64); 1463 IRTemp t4 = newTemp(Ity_I32); 1464 IRTemp t5 = newTemp(Ity_I32); 1465 IRTemp t6 = newTemp(Ity_I64); 1466 assign(t1, e); 1467 assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1))); 1468 assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */ 1469 assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */ 1470 putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5))); 1471 putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4))); 1472 } 1473 } 1474 1475 static void setFPUCondCode(IRExpr * e, UInt cc) 1476 { 1477 if (cc == 0) { 1478 putFCSR(binop(Iop_And32, getFCSR(), mkU32(0xFF7FFFFF))); 1479 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(23)))); 1480 } else { 1481 putFCSR(binop(Iop_And32, getFCSR(), unop(Iop_Not32, 1482 binop(Iop_Shl32, mkU32(0x01000000), mkU8(cc))))); 1483 putFCSR(binop(Iop_Or32, getFCSR(), binop(Iop_Shl32, e, mkU8(24 + cc)))); 1484 } 1485 } 1486 1487 static IRExpr* get_IR_roundingmode ( void ) 1488 { 1489 /* 1490 rounding mode | MIPS | IR 1491 ------------------------ 1492 to nearest | 00 | 00 1493 to zero | 01 | 11 1494 to +infinity | 10 | 10 1495 to -infinity | 11 | 01 1496 */ 1497 IRTemp rm_MIPS = newTemp(Ity_I32); 1498 /* Last two bits in FCSR are rounding mode. */ 1499 1500 if (mode64) 1501 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS64State, 1502 guest_FCSR), Ity_I32), mkU32(3))); 1503 else 1504 assign(rm_MIPS, binop(Iop_And32, IRExpr_Get(offsetof(VexGuestMIPS32State, 1505 guest_FCSR), Ity_I32), mkU32(3))); 1506 1507 /* rm_IR = XOR( rm_MIPS32, (rm_MIPS32 << 1) & 2) */ 1508 1509 return binop(Iop_Xor32, mkexpr(rm_MIPS), binop(Iop_And32, 1510 binop(Iop_Shl32, mkexpr(rm_MIPS), mkU8(1)), mkU32(2))); 1511 } 1512 1513 /* sz, ULong -> IRExpr */ 1514 static IRExpr *mkSzImm ( IRType ty, ULong imm64 ) 1515 { 1516 vassert(ty == Ity_I32 || ty == Ity_I64); 1517 return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt) imm64); 1518 } 1519 1520 static IRConst *mkSzConst ( IRType ty, ULong imm64 ) 1521 { 1522 vassert(ty == Ity_I32 || ty == Ity_I64); 1523 return (ty == Ity_I64 ? IRConst_U64(imm64) : IRConst_U32((UInt) imm64)); 1524 } 1525 1526 /* Make sure we get valid 32 and 64bit addresses */ 1527 static Addr64 mkSzAddr ( IRType ty, Addr64 addr ) 1528 { 1529 vassert(ty == Ity_I32 || ty == Ity_I64); 1530 return (ty == Ity_I64 ? (Addr64) addr : 1531 (Addr64) extend_s_32to64(toUInt(addr))); 1532 } 1533 1534 /* Shift and Rotate instructions for MIPS64 */ 1535 static Bool dis_instr_shrt ( UInt theInstr ) 1536 { 1537 UInt opc2 = get_function(theInstr); 1538 UChar regRs = get_rs(theInstr); 1539 UChar regRt = get_rt(theInstr); 1540 UChar regRd = get_rd(theInstr); 1541 UChar uImmsa = get_sa(theInstr); 1542 Long sImmsa = extend_s_16to64(uImmsa); 1543 IRType ty = mode64 ? Ity_I64 : Ity_I32; 1544 IRTemp tmp = newTemp(ty); 1545 IRTemp tmpOr = newTemp(ty); 1546 IRTemp tmpRt = newTemp(ty); 1547 IRTemp tmpRs = newTemp(ty); 1548 IRTemp tmpRd = newTemp(ty); 1549 1550 assign(tmpRs, getIReg(regRs)); 1551 assign(tmpRt, getIReg(regRt)); 1552 1553 switch (opc2) { 1554 case 0x3A: 1555 if ((regRs & 0x01) == 0) { 1556 /* Doubleword Shift Right Logical - DSRL; MIPS64 */ 1557 DIP("dsrl r%u, r%u, %lld", regRd, regRt, sImmsa); 1558 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1559 putIReg(regRd, mkexpr(tmpRd)); 1560 } else if ((regRs & 0x01) == 1) { 1561 /* Doubleword Rotate Right - DROTR; MIPS64r2 */ 1562 vassert(mode64); 1563 DIP("drotr r%u, r%u, %lld", regRd, regRt, sImmsa); 1564 IRTemp tmpL = newTemp(ty); 1565 IRTemp tmpR = newTemp(ty); 1566 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa))); 1567 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(63 - uImmsa))); 1568 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1569 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1570 putIReg(regRd, mkexpr(tmpRd)); 1571 } else 1572 return False; 1573 break; 1574 1575 case 0x3E: 1576 if ((regRs & 0x01) == 0) { 1577 /* Doubleword Shift Right Logical Plus 32 - DSRL32; MIPS64 */ 1578 DIP("dsrl32 r%u, r%u, %lld", regRd, regRt, sImmsa + 32); 1579 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1580 putIReg(regRd, mkexpr(tmpRd)); 1581 } else if ((regRs & 0x01) == 1) { 1582 /* Doubleword Rotate Right Plus 32 - DROTR32; MIPS64r2 */ 1583 DIP("drotr32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1584 vassert(mode64); 1585 IRTemp tmpL = newTemp(ty); 1586 IRTemp tmpR = newTemp(ty); 1587 /* (tmpRt >> sa) | (tmpRt << (64 - sa)) */ 1588 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1589 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRt), 1590 mkU8(63 - (uImmsa + 32)))); 1591 assign(tmpL, binop(Iop_Shl64, mkexpr(tmp), mkU8(1))); 1592 assign(tmpRd, binop(Iop_Or64, mkexpr(tmpL), mkexpr(tmpR))); 1593 putIReg(regRd, mkexpr(tmpRd)); 1594 } else 1595 return False; 1596 break; 1597 1598 case 0x16: 1599 if ((uImmsa & 0x01) == 0) { 1600 /* Doubleword Shift Right Logical Variable - DSRLV; MIPS64 */ 1601 DIP("dsrlv r%u, r%u, r%u", regRd, regRt, regRs); 1602 IRTemp tmpRs8 = newTemp(Ity_I8); 1603 /* s = tmpRs[5..0] */ 1604 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkU64(63))); 1605 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1606 assign(tmpRd, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1607 putIReg(regRd, mkexpr(tmpRd)); 1608 } else if ((uImmsa & 0x01) == 1) { 1609 /* Doubleword Rotate Right Variable - DROTRV; MIPS64r2 */ 1610 DIP("drotrv r%u, r%u, r%u", regRd, regRt, regRs); 1611 IRTemp tmpL = newTemp(ty); 1612 IRTemp tmpR = newTemp(ty); 1613 IRTemp tmpRs8 = newTemp(Ity_I8); 1614 IRTemp tmpLs8 = newTemp(Ity_I8); 1615 IRTemp tmp64 = newTemp(ty); 1616 /* s = tmpRs[5...0] 1617 m = 64 - s 1618 (tmpRt << s) | (tmpRt >> m) */ 1619 1620 assign(tmp64, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1621 assign(tmp, binop(Iop_Sub64, mkU64(63), mkexpr(tmp64))); 1622 1623 assign(tmpLs8, mkNarrowTo8(ty, mkexpr(tmp))); 1624 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp64))); 1625 1626 assign(tmpR, binop(Iop_Shr64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1627 assign(tmpL, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpLs8))); 1628 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpL), mkU8(1))); 1629 assign(tmpOr, binop(Iop_Or64, mkexpr(tmpRd), mkexpr(tmpR))); 1630 1631 putIReg(regRd, mkexpr(tmpOr)); 1632 } else 1633 return False; 1634 break; 1635 1636 case 0x38: /* Doubleword Shift Left Logical - DSLL; MIPS64 */ 1637 DIP("dsll r%u, r%u, %lld", regRd, regRt, sImmsa); 1638 vassert(mode64); 1639 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa))); 1640 putIReg(regRd, mkexpr(tmpRd)); 1641 break; 1642 1643 case 0x3C: /* Doubleword Shift Left Logical Plus 32 - DSLL32; MIPS64 */ 1644 DIP("dsll32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1645 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1646 putIReg(regRd, mkexpr(tmpRd)); 1647 break; 1648 1649 case 0x14: { /* Doubleword Shift Left Logical Variable - DSLLV; MIPS64 */ 1650 DIP("dsllv r%u, r%u, r%u", regRd, regRt, regRs); 1651 IRTemp tmpRs8 = newTemp(Ity_I8); 1652 1653 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1654 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1655 assign(tmpRd, binop(Iop_Shl64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1656 putIReg(regRd, mkexpr(tmpRd)); 1657 break; 1658 } 1659 1660 case 0x3B: /* Doubleword Shift Right Arithmetic - DSRA; MIPS64 */ 1661 DIP("dsra r%u, r%u, %lld", regRd, regRt, sImmsa); 1662 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa))); 1663 putIReg(regRd, mkexpr(tmpRd)); 1664 break; 1665 1666 case 0x3F: /* Doubleword Shift Right Arithmetic Plus 32 - DSRA32; 1667 MIPS64 */ 1668 DIP("dsra32 r%u, r%u, %lld", regRd, regRt, sImmsa); 1669 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkU8(uImmsa + 32))); 1670 putIReg(regRd, mkexpr(tmpRd)); 1671 break; 1672 1673 case 0x17: { /* Doubleword Shift Right Arithmetic Variable - DSRAV; 1674 MIPS64 */ 1675 DIP("dsrav r%u, r%u, r%u", regRd, regRt, regRs); 1676 IRTemp tmpRs8 = newTemp(Ity_I8); 1677 assign(tmp, binop(Iop_And64, mkexpr(tmpRs), mkSzImm(ty, 63))); 1678 assign(tmpRs8, mkNarrowTo8(ty, mkexpr(tmp))); 1679 assign(tmpRd, binop(Iop_Sar64, mkexpr(tmpRt), mkexpr(tmpRs8))); 1680 putIReg(regRd, mkexpr(tmpRd)); 1681 break; 1682 1683 } 1684 1685 default: 1686 return False; 1687 1688 } 1689 return True; 1690 } 1691 1692 static IROp mkSzOp ( IRType ty, IROp op8 ) 1693 { 1694 Int adj; 1695 vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64); 1696 vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 || op8 == Iop_Mul8 1697 || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8 1698 || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8 1699 || op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 || op8 == Iop_Not8); 1700 adj = ty == Ity_I8 ? 0 : (ty == Ity_I16 ? 1 : (ty == Ity_I32 ? 2 : 3)); 1701 return adj + op8; 1702 } 1703 1704 /*********************************************************/ 1705 /*--- Floating Point Compare ---*/ 1706 /*********************************************************/ 1707 /* Function that returns a string that represent mips cond 1708 mnemonic for the input code. */ 1709 static const HChar* showCondCode(UInt code) { 1710 const HChar* ret; 1711 switch (code) { 1712 case 0: ret = "f"; break; 1713 case 1: ret = "un"; break; 1714 case 2: ret = "eq"; break; 1715 case 3: ret = "ueq"; break; 1716 case 4: ret = "olt"; break; 1717 case 5: ret = "ult"; break; 1718 case 6: ret = "ole"; break; 1719 case 7: ret = "ule"; break; 1720 case 8: ret = "sf"; break; 1721 case 9: ret = "ngle"; break; 1722 case 10: ret = "seq"; break; 1723 case 11: ret = "ngl"; break; 1724 case 12: ret = "lt"; break; 1725 case 13: ret = "nge"; break; 1726 case 14: ret = "le"; break; 1727 case 15: ret = "ngt"; break; 1728 default: vpanic("showCondCode"); break; 1729 } 1730 return ret; 1731 } 1732 1733 static Bool dis_instr_CCondFmt ( UInt cins ) 1734 { 1735 IRTemp t0, t1, t2, t3, tmp5, tmp6; 1736 IRTemp ccIR = newTemp(Ity_I32); 1737 IRTemp ccMIPS = newTemp(Ity_I32); 1738 UInt FC = get_FC(cins); 1739 UInt fmt = get_fmt(cins); 1740 UInt fs = get_fs(cins); 1741 UInt ft = get_ft(cins); 1742 UInt cond = get_cond(cins); 1743 1744 if (FC == 0x3) { /* C.cond.fmt */ 1745 UInt fpc_cc = get_fpc_cc(cins); 1746 switch (fmt) { 1747 case 0x10: { /* C.cond.S */ 1748 DIP("c.%s.s %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft); 1749 if (fp_mode64) { 1750 t0 = newTemp(Ity_I32); 1751 t1 = newTemp(Ity_I32); 1752 t2 = newTemp(Ity_I32); 1753 t3 = newTemp(Ity_I32); 1754 1755 tmp5 = newTemp(Ity_F64); 1756 tmp6 = newTemp(Ity_F64); 1757 1758 assign(tmp5, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1759 getFReg(fs)))); 1760 assign(tmp6, unop(Iop_F32toF64, getLoFromF64(Ity_F64, 1761 getFReg(ft)))); 1762 1763 assign(ccIR, binop(Iop_CmpF64, mkexpr(tmp5), mkexpr(tmp6))); 1764 putHI(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1765 mkexpr(ccIR), True)); 1766 /* Map compare result from IR to MIPS 1767 FP cmp result | MIPS | IR 1768 -------------------------- 1769 UN | 0x1 | 0x45 1770 EQ | 0x2 | 0x40 1771 GT | 0x4 | 0x00 1772 LT | 0x8 | 0x01 1773 */ 1774 1775 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1776 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1777 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1778 binop(Iop_Shr32, mkexpr(ccIR),mkU8(5))),mkU32(2)), 1779 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1780 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1781 mkU32(1)))))); 1782 putLO(mkWidenFrom32(mode64 ? Ity_I64: Ity_I32, 1783 mkexpr(ccMIPS), True)); 1784 1785 /* UN */ 1786 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1787 /* EQ */ 1788 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1789 mkU8(0x1)), mkU32(0x1))); 1790 /* NGT */ 1791 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1792 mkexpr(ccMIPS), mkU8(0x2))),mkU32(0x1))); 1793 /* LT */ 1794 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1795 mkU8(0x3)), mkU32(0x1))); 1796 switch (cond) { 1797 case 0x0: 1798 setFPUCondCode(mkU32(0), fpc_cc); 1799 break; 1800 case 0x1: 1801 setFPUCondCode(mkexpr(t0), fpc_cc); 1802 break; 1803 case 0x2: 1804 setFPUCondCode(mkexpr(t1), fpc_cc); 1805 break; 1806 case 0x3: 1807 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1808 fpc_cc); 1809 break; 1810 case 0x4: 1811 setFPUCondCode(mkexpr(t3), fpc_cc); 1812 break; 1813 case 0x5: 1814 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1815 fpc_cc); 1816 break; 1817 case 0x6: 1818 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1819 fpc_cc); 1820 break; 1821 case 0x7: 1822 setFPUCondCode(mkexpr(t2), fpc_cc); 1823 break; 1824 case 0x8: 1825 setFPUCondCode(mkU32(0), fpc_cc); 1826 break; 1827 case 0x9: 1828 setFPUCondCode(mkexpr(t0), fpc_cc); 1829 break; 1830 case 0xA: 1831 setFPUCondCode(mkexpr(t1), fpc_cc); 1832 break; 1833 case 0xB: 1834 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1835 fpc_cc); 1836 break; 1837 case 0xC: 1838 setFPUCondCode(mkexpr(t3), fpc_cc); 1839 break; 1840 case 0xD: 1841 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1842 fpc_cc); 1843 break; 1844 case 0xE: 1845 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1846 fpc_cc); 1847 break; 1848 case 0xF: 1849 setFPUCondCode(mkexpr(t2), fpc_cc); 1850 break; 1851 1852 default: 1853 return False; 1854 } 1855 1856 } else { 1857 t0 = newTemp(Ity_I32); 1858 t1 = newTemp(Ity_I32); 1859 t2 = newTemp(Ity_I32); 1860 t3 = newTemp(Ity_I32); 1861 1862 assign(ccIR, binop(Iop_CmpF64, unop(Iop_F32toF64, getFReg(fs)), 1863 unop(Iop_F32toF64, getFReg(ft)))); 1864 /* Map compare result from IR to MIPS 1865 FP cmp result | MIPS | IR 1866 -------------------------- 1867 UN | 0x1 | 0x45 1868 EQ | 0x2 | 0x40 1869 GT | 0x4 | 0x00 1870 LT | 0x8 | 0x01 1871 */ 1872 1873 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1874 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1875 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1876 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), 1877 mkU32(2)), binop(Iop_And32, 1878 binop(Iop_Xor32, mkexpr(ccIR), 1879 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1880 mkU32(1)))))); 1881 /* UN */ 1882 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1883 /* EQ */ 1884 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1885 mkU8(0x1)), mkU32(0x1))); 1886 /* NGT */ 1887 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1888 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 1889 /* LT */ 1890 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1891 mkU8(0x3)), mkU32(0x1))); 1892 1893 switch (cond) { 1894 case 0x0: 1895 setFPUCondCode(mkU32(0), fpc_cc); 1896 break; 1897 case 0x1: 1898 setFPUCondCode(mkexpr(t0), fpc_cc); 1899 break; 1900 case 0x2: 1901 setFPUCondCode(mkexpr(t1), fpc_cc); 1902 break; 1903 case 0x3: 1904 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1905 fpc_cc); 1906 break; 1907 case 0x4: 1908 setFPUCondCode(mkexpr(t3), fpc_cc); 1909 break; 1910 case 0x5: 1911 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1912 fpc_cc); 1913 break; 1914 case 0x6: 1915 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1916 fpc_cc); 1917 break; 1918 case 0x7: 1919 setFPUCondCode(mkexpr(t2), fpc_cc); 1920 break; 1921 case 0x8: 1922 setFPUCondCode(mkU32(0), fpc_cc); 1923 break; 1924 case 0x9: 1925 setFPUCondCode(mkexpr(t0), fpc_cc); 1926 break; 1927 case 0xA: 1928 setFPUCondCode(mkexpr(t1), fpc_cc); 1929 break; 1930 case 0xB: 1931 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 1932 fpc_cc); 1933 break; 1934 case 0xC: 1935 setFPUCondCode(mkexpr(t3), fpc_cc); 1936 break; 1937 case 0xD: 1938 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 1939 fpc_cc); 1940 break; 1941 case 0xE: 1942 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 1943 fpc_cc); 1944 break; 1945 case 0xF: 1946 setFPUCondCode(mkexpr(t2), fpc_cc); 1947 break; 1948 1949 default: 1950 return False; 1951 } 1952 } 1953 } 1954 break; 1955 1956 case 0x11: { /* C.cond.D */ 1957 DIP("c.%s.d %u, f%u, f%u", showCondCode(cond), fpc_cc, fs, ft); 1958 t0 = newTemp(Ity_I32); 1959 t1 = newTemp(Ity_I32); 1960 t2 = newTemp(Ity_I32); 1961 t3 = newTemp(Ity_I32); 1962 assign(ccIR, binop(Iop_CmpF64, getDReg(fs), getDReg(ft))); 1963 /* Map compare result from IR to MIPS 1964 FP cmp result | MIPS | IR 1965 -------------------------- 1966 UN | 0x1 | 0x45 1967 EQ | 0x2 | 0x40 1968 GT | 0x4 | 0x00 1969 LT | 0x8 | 0x01 1970 */ 1971 1972 /* ccMIPS = Shl(1, (~(ccIR>>5) & 2) | ((ccIR ^ (ccIR>>6)) & 1) */ 1973 assign(ccMIPS, binop(Iop_Shl32, mkU32(1), unop(Iop_32to8, 1974 binop(Iop_Or32, binop(Iop_And32, unop(Iop_Not32, 1975 binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))), mkU32(2)), 1976 binop(Iop_And32, binop(Iop_Xor32, mkexpr(ccIR), 1977 binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))), 1978 mkU32(1)))))); 1979 1980 /* UN */ 1981 assign(t0, binop(Iop_And32, mkexpr(ccMIPS), mkU32(0x1))); 1982 /* EQ */ 1983 assign(t1, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1984 mkU8(0x1)), mkU32(0x1))); 1985 /* NGT */ 1986 assign(t2, binop(Iop_And32, unop(Iop_Not32, binop(Iop_Shr32, 1987 mkexpr(ccMIPS), mkU8(0x2))), mkU32(0x1))); 1988 /* LT */ 1989 assign(t3, binop(Iop_And32, binop(Iop_Shr32, mkexpr(ccMIPS), 1990 mkU8(0x3)), mkU32(0x1))); 1991 1992 switch (cond) { 1993 case 0x0: 1994 setFPUCondCode(mkU32(0), fpc_cc); 1995 break; 1996 case 0x1: 1997 setFPUCondCode(mkexpr(t0), fpc_cc); 1998 break; 1999 case 0x2: 2000 setFPUCondCode(mkexpr(t1), fpc_cc); 2001 break; 2002 case 0x3: 2003 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2004 fpc_cc); 2005 break; 2006 case 0x4: 2007 setFPUCondCode(mkexpr(t3), fpc_cc); 2008 break; 2009 case 0x5: 2010 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2011 fpc_cc); 2012 break; 2013 case 0x6: 2014 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2015 fpc_cc); 2016 break; 2017 case 0x7: 2018 setFPUCondCode(mkexpr(t2), fpc_cc); 2019 break; 2020 case 0x8: 2021 setFPUCondCode(mkU32(0), fpc_cc); 2022 break; 2023 case 0x9: 2024 setFPUCondCode(mkexpr(t0), fpc_cc); 2025 break; 2026 case 0xA: 2027 setFPUCondCode(mkexpr(t1), fpc_cc); 2028 break; 2029 case 0xB: 2030 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t1)), 2031 fpc_cc); 2032 break; 2033 case 0xC: 2034 setFPUCondCode(mkexpr(t3), fpc_cc); 2035 break; 2036 case 0xD: 2037 setFPUCondCode(binop(Iop_Or32, mkexpr(t0), mkexpr(t3)), 2038 fpc_cc); 2039 break; 2040 case 0xE: 2041 setFPUCondCode(binop(Iop_Or32, mkexpr(t3), mkexpr(t1)), 2042 fpc_cc); 2043 break; 2044 case 0xF: 2045 setFPUCondCode(mkexpr(t2), fpc_cc); 2046 break; 2047 default: 2048 return False; 2049 } 2050 } 2051 break; 2052 2053 default: 2054 return False; 2055 } 2056 } else { 2057 return False; 2058 } 2059 2060 return True; 2061 } 2062 2063 /*********************************************************/ 2064 /*--- Branch Instructions for mips64 ---*/ 2065 /*********************************************************/ 2066 static Bool dis_instr_branch ( UInt theInstr, DisResult * dres, 2067 Bool(*resteerOkFn) (void *, Addr), 2068 void *callback_opaque, IRStmt ** set ) 2069 { 2070 UInt jmpKind = 0; 2071 UChar opc1 = get_opcode(theInstr); 2072 UChar regRs = get_rs(theInstr); 2073 UChar regRt = get_rt(theInstr); 2074 UInt offset = get_imm(theInstr); 2075 Long sOffset = extend_s_16to64(offset); 2076 IRType ty = mode64 ? Ity_I64 : Ity_I32; 2077 IROp opSlt = mode64 ? Iop_CmpLT64S : Iop_CmpLT32S; 2078 2079 IRTemp tmp = newTemp(ty); 2080 IRTemp tmpRs = newTemp(ty); 2081 IRTemp tmpRt = newTemp(ty); 2082 IRTemp tmpLt = newTemp(ty); 2083 IRTemp tmpReg0 = newTemp(ty); 2084 2085 UChar regLnk = 31; /* reg 31 is link reg in MIPS */ 2086 Addr64 addrTgt = 0; 2087 Addr64 cia = guest_PC_curr_instr; 2088 2089 IRExpr *eConst0 = mkSzImm(ty, (UInt) 0); 2090 IRExpr *eNia = mkSzImm(ty, cia + 8); 2091 IRExpr *eCond = NULL; 2092 2093 assign(tmpRs, getIReg(regRs)); 2094 assign(tmpRt, getIReg(regRt)); 2095 assign(tmpReg0, getIReg(0)); 2096 2097 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpReg0), mkexpr(tmpReg0)); 2098 2099 switch (opc1) { 2100 case 0x01: 2101 switch (regRt) { 2102 case 0x00: { /* BLTZ rs, offset */ 2103 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2104 IRTemp tmpLtRes = newTemp(Ity_I1); 2105 2106 assign(tmp, eConst0); 2107 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2108 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2109 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2110 2111 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpLt), 2112 mkexpr(tmpReg0)); 2113 2114 jmpKind = Ijk_Boring; 2115 break; 2116 } 2117 2118 case 0x01: { /* BGEZ rs, offset */ 2119 IRTemp tmpLtRes = newTemp(Ity_I1); 2120 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2121 2122 assign(tmp, eConst0); 2123 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2124 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2125 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2126 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2127 mkexpr(tmpReg0)); 2128 2129 jmpKind = Ijk_Boring; 2130 break; 2131 } 2132 2133 case 0x11: { /* BGEZAL rs, offset */ 2134 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2135 putIReg(regLnk, eNia); 2136 IRTemp tmpLtRes = newTemp(Ity_I1); 2137 2138 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), eConst0)); 2139 assign(tmpLt, mode64 ? unop(Iop_1Uto64, mkexpr(tmpLtRes)) : 2140 unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2141 2142 eCond = binop(mkSzOp(ty, Iop_CmpEQ8), mkexpr(tmpLt), 2143 mkexpr(tmpReg0)); 2144 2145 jmpKind = Ijk_Call; 2146 break; 2147 } 2148 2149 case 0x10: { /* BLTZAL rs, offset */ 2150 IRTemp tmpLtRes = newTemp(Ity_I1); 2151 IRTemp tmpRes = newTemp(ty); 2152 2153 addrTgt = mkSzAddr(ty, cia + 4 + (sOffset << 2)); 2154 putIReg(regLnk, eNia); 2155 2156 assign(tmp, eConst0); 2157 assign(tmpLtRes, binop(opSlt, mkexpr(tmpRs), mkexpr(tmp))); 2158 assign(tmpRes, mode64 ? unop(Iop_1Uto64, 2159 mkexpr(tmpLtRes)) : unop(Iop_1Uto32, mkexpr(tmpLtRes))); 2160 eCond = binop(mkSzOp(ty, Iop_CmpNE8), mkexpr(tmpRes), 2161 mkexpr(tmpReg0)); 2162 2163 jmpKind = Ijk_Call; 2164 break; 2165 } 2166 2167 } 2168 break; 2169 default: 2170 return False; 2171 } 2172 *set = IRStmt_Exit(eCond, jmpKind, mkSzConst(ty, addrTgt), OFFB_PC); 2173 return True; 2174 } 2175 2176 /*********************************************************/ 2177 /*--- Cavium Specific Instructions ---*/ 2178 /*********************************************************/ 2179 2180 /* Convenience function to yield to thread scheduler */ 2181 static void jump_back(IRExpr *condition) 2182 { 2183 stmt( IRStmt_Exit(condition, 2184 Ijk_Yield, 2185 IRConst_U64( guest_PC_curr_instr ), 2186 OFFB_PC) ); 2187 } 2188 2189 /* Based on s390_irgen_load_and_add32. */ 2190 static void mips_irgen_load_and_add32(IRTemp op1addr, IRTemp new_val, 2191 UChar rd, Bool putIntoRd) 2192 { 2193 IRCAS *cas; 2194 IRTemp old_mem = newTemp(Ity_I32); 2195 IRTemp expd = newTemp(Ity_I32); 2196 2197 assign(expd, load(Ity_I32, mkexpr(op1addr))); 2198 2199 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2200 Iend_LE, mkexpr(op1addr), 2201 NULL, mkexpr(expd), /* expected value */ 2202 NULL, mkexpr(new_val) /* new value */); 2203 stmt(IRStmt_CAS(cas)); 2204 2205 /* If old_mem contains the expected value, then the CAS succeeded. 2206 Otherwise, it did not */ 2207 jump_back(binop(Iop_CmpNE32, mkexpr(old_mem), mkexpr(expd))); 2208 if (putIntoRd) 2209 putIReg(rd, mkWidenFrom32(Ity_I64, mkexpr(old_mem), True)); 2210 } 2211 2212 /* Based on s390_irgen_load_and_add64. */ 2213 static void mips_irgen_load_and_add64(IRTemp op1addr, IRTemp new_val, 2214 UChar rd, Bool putIntoRd) 2215 { 2216 IRCAS *cas; 2217 IRTemp old_mem = newTemp(Ity_I64); 2218 IRTemp expd = newTemp(Ity_I64); 2219 2220 assign(expd, load(Ity_I64, mkexpr(op1addr))); 2221 2222 cas = mkIRCAS(IRTemp_INVALID, old_mem, 2223 Iend_LE, mkexpr(op1addr), 2224 NULL, mkexpr(expd), /* expected value */ 2225 NULL, mkexpr(new_val) /* new value */); 2226 stmt(IRStmt_CAS(cas)); 2227 2228 /* If old_mem contains the expected value, then the CAS succeeded. 2229 Otherwise, it did not */ 2230 jump_back(binop(Iop_CmpNE64, mkexpr(old_mem), mkexpr(expd))); 2231 if (putIntoRd) 2232 putIReg(rd, mkexpr(old_mem)); 2233 } 2234 2235 static Bool dis_instr_CVM ( UInt theInstr ) 2236 { 2237 UChar opc2 = get_function(theInstr); 2238 UChar opc1 = get_opcode(theInstr); 2239 UChar regRs = get_rs(theInstr); 2240 UChar regRt = get_rt(theInstr); 2241 UChar regRd = get_rd(theInstr); 2242 /* MIPS trap instructions extract code from theInstr[15:6]. 2243 Cavium OCTEON instructions SNEI, SEQI extract immediate operands 2244 from the same bit field [15:6]. */ 2245 UInt imm = get_code(theInstr); 2246 UChar lenM1 = get_msb(theInstr); 2247 UChar p = get_lsb(theInstr); 2248 IRType ty = mode64? Ity_I64 : Ity_I32; 2249 IRTemp tmp = newTemp(ty); 2250 IRTemp tmpRs = newTemp(ty); 2251 IRTemp tmpRt = newTemp(ty); 2252 IRTemp t1 = newTemp(ty); 2253 UInt size; 2254 assign(tmpRs, getIReg(regRs)); 2255 2256 switch(opc1) { 2257 case 0x1C: { 2258 switch(opc2) { 2259 case 0x03: { /* DMUL rd, rs, rt */ 2260 DIP("dmul r%u, r%u, r%u", regRd, regRs, regRt); 2261 IRTemp t0 = newTemp(Ity_I128); 2262 assign(t0, binop(Iop_MullU64, getIReg(regRs), getIReg(regRt))); 2263 putIReg(regRd, unop(Iop_128to64, mkexpr(t0))); 2264 break; 2265 } 2266 2267 case 0x18: { /* Store Atomic Add Word - SAA; Cavium OCTEON */ 2268 DIP("saa r%u, (r%u)", regRt, regRs); 2269 IRTemp addr = newTemp(Ity_I64); 2270 IRTemp new = newTemp(Ity_I32); 2271 assign (addr, getIReg(regRs)); 2272 assign(new, binop(Iop_Add32, 2273 load(Ity_I32, mkexpr(addr)), 2274 mkNarrowTo32(ty, getIReg(regRt)))); 2275 mips_irgen_load_and_add32(addr, new, 0, False); 2276 break; 2277 } 2278 2279 /* Store Atomic Add Doubleword - SAAD; Cavium OCTEON */ 2280 case 0x19: { 2281 DIP( "saad r%u, (r%u)", regRt, regRs); 2282 IRTemp addr = newTemp(Ity_I64); 2283 IRTemp new = newTemp(Ity_I64); 2284 assign (addr, getIReg(regRs)); 2285 assign(new, binop(Iop_Add64, 2286 load(Ity_I64, mkexpr(addr)), 2287 getIReg(regRt))); 2288 mips_irgen_load_and_add64(addr, new, 0, False); 2289 break; 2290 } 2291 2292 /* LAI, LAID, LAD, LADD, LAS, LASD, 2293 LAC, LACD, LAA, LAAD, LAW, LAWD */ 2294 case 0x1f: { 2295 UInt opc3 = get_sa(theInstr); 2296 IRTemp addr = newTemp(Ity_I64); 2297 switch (opc3) { 2298 /* Load Atomic Increment Word - LAI; Cavium OCTEON2 */ 2299 case 0x02: { 2300 DIP("lai r%u,(r%u)\n", regRd, regRs); 2301 IRTemp new = newTemp(Ity_I32); 2302 assign(addr, getIReg(regRs)); 2303 assign(new, binop(Iop_Add32, 2304 load(Ity_I32, mkexpr(addr)), 2305 mkU32(1))); 2306 mips_irgen_load_and_add32(addr, new, regRd, True); 2307 break; 2308 } 2309 /* Load Atomic Increment Doubleword - LAID; Cavium OCTEON2 */ 2310 case 0x03: { 2311 DIP("laid r%u,(r%u)\n", regRd, regRs); 2312 IRTemp new = newTemp(Ity_I64); 2313 assign(addr, getIReg(regRs)); 2314 assign(new, binop(Iop_Add64, 2315 load(Ity_I64, mkexpr(addr)), 2316 mkU64(1))); 2317 mips_irgen_load_and_add64(addr, new, regRd, True); 2318 break; 2319 } 2320 /* Load Atomic Decrement Word - LAD; Cavium OCTEON2 */ 2321 case 0x06: { 2322 DIP("lad r%u,(r%u)\n", regRd, regRs); 2323 IRTemp new = newTemp(Ity_I32); 2324 assign(addr, getIReg(regRs)); 2325 assign(new, binop(Iop_Sub32, 2326 load(Ity_I32, mkexpr(addr)), 2327 mkU32(1))); 2328 mips_irgen_load_and_add32(addr, new, regRd, True); 2329 break; 2330 } 2331 /* Load Atomic Decrement Doubleword - LADD; Cavium OCTEON2 */ 2332 case 0x07: { 2333 DIP("ladd r%u,(r%u)\n", regRd, regRs); 2334 IRTemp new = newTemp(Ity_I64); 2335 assign (addr, getIReg(regRs)); 2336 assign(new, binop(Iop_Sub64, 2337 load(Ity_I64, mkexpr(addr)), 2338 mkU64(1))); 2339 mips_irgen_load_and_add64(addr, new, regRd, True); 2340 break; 2341 } 2342 /* Load Atomic Set Word - LAS; Cavium OCTEON2 */ 2343 case 0x0a: { 2344 DIP("las r%u,(r%u)\n", regRd, regRs); 2345 IRTemp new = newTemp(Ity_I32); 2346 assign(addr, getIReg(regRs)); 2347 assign(new, mkU32(0xffffffff)); 2348 mips_irgen_load_and_add32(addr, new, regRd, True); 2349 break; 2350 } 2351 /* Load Atomic Set Doubleword - LASD; Cavium OCTEON2 */ 2352 case 0x0b: { 2353 DIP("lasd r%u,(r%u)\n", regRd, regRs); 2354 IRTemp new = newTemp(Ity_I64); 2355 assign (addr, getIReg(regRs)); 2356 assign(new, mkU64(0xffffffffffffffffULL)); 2357 mips_irgen_load_and_add64(addr, new, regRd, True); 2358 break; 2359 } 2360 /* Load Atomic Clear Word - LAC; Cavium OCTEON2 */ 2361 case 0x0e: { 2362 DIP("lac r%u,(r%u)\n", regRd, regRs); 2363 IRTemp new = newTemp(Ity_I32); 2364 assign (addr, getIReg(regRs)); 2365 assign(new, mkU32(0)); 2366 mips_irgen_load_and_add32(addr, new, regRd, True); 2367 break; 2368 } 2369 /* Load Atomic Clear Doubleword - LACD; Cavium OCTEON2 */ 2370 case 0x0f: { 2371 DIP("lacd r%u,(r%u)\n", regRd, regRs); 2372 IRTemp new = newTemp(Ity_I64); 2373 assign(addr, getIReg(regRs)); 2374 assign(new, mkU64(0)); 2375 mips_irgen_load_and_add64(addr, new, regRd, True); 2376 break; 2377 } 2378 /* Load Atomic Add Word - LAA; Cavium OCTEON2 */ 2379 case 0x12: { 2380 DIP("laa r%u,(r%u),r%u\n", regRd, regRs, regRt); 2381 IRTemp new = newTemp(Ity_I32); 2382 assign(addr, getIReg(regRs)); 2383 assign(new, binop(Iop_Add32, 2384 load(Ity_I32, mkexpr(addr)), 2385 mkNarrowTo32(ty, getIReg(regRt)))); 2386 mips_irgen_load_and_add32(addr, new, regRd, True); 2387 break; 2388 } 2389 /* Load Atomic Add Doubleword - LAAD; Cavium OCTEON2 */ 2390 case 0x13: { 2391 DIP("laad r%u,(r%u),r%u\n", regRd, regRs, regRt); 2392 IRTemp new = newTemp(Ity_I64); 2393 assign (addr, getIReg(regRs)); 2394 assign(new, binop(Iop_Add64, 2395 load(Ity_I64, mkexpr(addr)), 2396 getIReg(regRt))); 2397 mips_irgen_load_and_add64(addr, new, regRd, True); 2398 break; 2399 } 2400 /* Load Atomic Swap Word - LAW; Cavium OCTEON2 */ 2401 case 0x16: { 2402 DIP("law r%u,(r%u)\n", regRd, regRs); 2403 IRTemp new = newTemp(Ity_I32); 2404 assign(addr, getIReg(regRs)); 2405 assign(new, mkNarrowTo32(ty, getIReg(regRt))); 2406 mips_irgen_load_and_add32(addr, new, regRd, True); 2407 break; 2408 } 2409 /* Load Atomic Swap Doubleword - LAWD; Cavium OCTEON2 */ 2410 case 0x17: { 2411 DIP("lawd r%u,(r%u)\n", regRd, regRs); 2412 IRTemp new = newTemp(Ity_I64); 2413 assign(addr, getIReg(regRs)); 2414 assign(new, getIReg(regRt)); 2415 mips_irgen_load_and_add64(addr, new, regRd, True); 2416 break; 2417 } 2418 default: 2419 vex_printf("Unknown laxx instruction, opc3=0x%x\n", opc3); 2420 vex_printf("Instruction=0x%08x\n", theInstr); 2421 return False; 2422 } 2423 break; 2424 } 2425 2426 /* Unsigned Byte Add - BADDU rd, rs, rt; Cavium OCTEON */ 2427 case 0x28: { 2428 DIP("BADDU r%u, r%u, r%u", regRs, regRt, regRd); 2429 IRTemp t0 = newTemp(Ity_I8); 2430 2431 assign(t0, binop(Iop_Add8, 2432 mkNarrowTo8(ty, getIReg(regRs)), 2433 mkNarrowTo8(ty, getIReg(regRt)))); 2434 2435 if (mode64) 2436 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2437 unop(Iop_8Uto64, mkexpr(t0)), 2438 mkSzImm(ty, 0xFF))); 2439 else 2440 putIReg(regRd, binop(mkSzOp(ty, Iop_And8), 2441 unop(Iop_8Uto32, mkexpr(t0)), 2442 mkSzImm(ty, 0xFF))); 2443 break; 2444 } 2445 2446 case 0x2c: { /* Count Ones in a Word - POP; Cavium OCTEON */ 2447 int i, shift[5]; 2448 IRTemp mask[5]; 2449 IRTemp old = newTemp(ty); 2450 IRTemp nyu = IRTemp_INVALID; 2451 assign(old, getIReg(regRs)); 2452 DIP("pop r%u, r%u", regRd, regRs); 2453 2454 for (i = 0; i < 5; i++) { 2455 mask[i] = newTemp(ty); 2456 shift[i] = 1 << i; 2457 } 2458 if(mode64) { 2459 assign(mask[0], mkU64(0x0000000055555555)); 2460 assign(mask[1], mkU64(0x0000000033333333)); 2461 assign(mask[2], mkU64(0x000000000F0F0F0F)); 2462 assign(mask[3], mkU64(0x0000000000FF00FF)); 2463 assign(mask[4], mkU64(0x000000000000FFFF)); 2464 2465 for (i = 0; i < 5; i++) { 2466 nyu = newTemp(ty); 2467 assign(nyu, 2468 binop(Iop_Add64, 2469 binop(Iop_And64, 2470 mkexpr(old), mkexpr(mask[i])), 2471 binop(Iop_And64, 2472 binop(Iop_Shr64, 2473 mkexpr(old), mkU8(shift[i])), 2474 mkexpr(mask[i])))); 2475 old = nyu; 2476 } 2477 } else { 2478 assign(mask[0], mkU32(0x55555555)); 2479 assign(mask[1], mkU32(0x33333333)); 2480 assign(mask[2], mkU32(0x0F0F0F0F)); 2481 assign(mask[3], mkU32(0x00FF00FF)); 2482 assign(mask[4], mkU32(0x0000FFFF)); 2483 assign(old, getIReg(regRs)); 2484 2485 for (i = 0; i < 5; i++) { 2486 nyu = newTemp(ty); 2487 assign(nyu, 2488 binop(Iop_Add32, 2489 binop(Iop_And32, 2490 mkexpr(old), mkexpr(mask[i])), 2491 binop(Iop_And32, 2492 binop(Iop_Shr32, 2493 mkexpr(old), mkU8(shift[i])), 2494 mkexpr(mask[i])))); 2495 old = nyu; 2496 } 2497 } 2498 putIReg(regRd, mkexpr(nyu)); 2499 break; 2500 } 2501 2502 /* Count Ones in a Doubleword - DPOP; Cavium OCTEON */ 2503 case 0x2d: { 2504 int i, shift[6]; 2505 IRTemp mask[6]; 2506 IRTemp old = newTemp(ty); 2507 IRTemp nyu = IRTemp_INVALID; 2508 DIP("dpop r%u, r%u", regRd, regRs); 2509 2510 for (i = 0; i < 6; i++) { 2511 mask[i] = newTemp(ty); 2512 shift[i] = 1 << i; 2513 } 2514 vassert(mode64); /*Caution! Only for Mode 64*/ 2515 assign(mask[0], mkU64(0x5555555555555555ULL)); 2516 assign(mask[1], mkU64(0x3333333333333333ULL)); 2517 assign(mask[2], mkU64(0x0F0F0F0F0F0F0F0FULL)); 2518 assign(mask[3], mkU64(0x00FF00FF00FF00FFULL)); 2519 assign(mask[4], mkU64(0x0000FFFF0000FFFFULL)); 2520 assign(mask[5], mkU64(0x00000000FFFFFFFFULL)); 2521 assign(old, getIReg(regRs)); 2522 for (i = 0; i < 6; i++) { 2523 nyu = newTemp(Ity_I64); 2524 assign(nyu, 2525 binop(Iop_Add64, 2526 binop(Iop_And64, 2527 mkexpr(old), mkexpr(mask[i])), 2528 binop(Iop_And64, 2529 binop(Iop_Shr64, 2530 mkexpr(old), mkU8(shift[i])), 2531 mkexpr(mask[i])))); 2532 old = nyu; 2533 } 2534 putIReg(regRd, mkexpr(nyu)); 2535 break; 2536 } 2537 2538 case 0x32: /* 5. CINS rd, rs, p, lenm1 */ 2539 DIP("cins r%u, r%u, %u, %u\n", regRt, regRs, p, lenM1); 2540 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2541 mkU8(64-( lenM1+1 )))); 2542 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2543 mkU8(64-(p+lenM1+1)))); 2544 putIReg( regRt, mkexpr(tmpRt)); 2545 break; 2546 2547 case 0x33: /* 6. CINS32 rd, rs, p+32, lenm1 */ 2548 DIP("cins32 r%u, r%u, %d, %d\n", regRt, regRs, p+32, lenM1); 2549 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2550 mkU8(64-( lenM1+1 )))); 2551 assign ( tmpRt, binop(Iop_Shr64, mkexpr( tmp ), 2552 mkU8(32-(p+lenM1+1)))); 2553 putIReg( regRt, mkexpr(tmpRt)); 2554 break; 2555 2556 case 0x3A: /* 3. EXTS rt, rs, p len */ 2557 DIP("exts r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2558 size = lenM1 + 1; /* lenm1+1 */ 2559 UChar lsAmt = 64 - (p + size); /* p+lenm1+1 */ 2560 UChar rsAmt = 64 - size; /* lenm1+1 */ 2561 tmp = newTemp(Ity_I64); 2562 assign(tmp, binop(Iop_Shl64, mkexpr(tmpRs), mkU8(lsAmt))); 2563 putIReg(regRt, binop(Iop_Sar64, mkexpr(tmp), mkU8(rsAmt))); 2564 break; 2565 2566 case 0x3B: /* 4. EXTS32 rt, rs, p len */ 2567 DIP("exts32 r%u, r%u, %d, %d\n", regRt, regRs, p, lenM1); 2568 assign ( tmp , binop(Iop_Shl64, mkexpr(tmpRs), 2569 mkU8(32-(p+lenM1+1)))); 2570 assign ( tmpRt, binop(Iop_Sar64, mkexpr(tmp), 2571 mkU8(64-(lenM1+1))) ); 2572 putIReg( regRt, mkexpr(tmpRt)); 2573 break; 2574 2575 case 0x2B: /* 20. SNE rd, rs, rt */ 2576 DIP("sne r%u, r%u, r%u", regRd,regRs, regRt); 2577 if (mode64) 2578 putIReg(regRd, unop(Iop_1Uto64, binop(Iop_CmpNE64, 2579 getIReg(regRs), 2580 getIReg(regRt)))); 2581 else 2582 putIReg(regRd,unop(Iop_1Uto32, binop(Iop_CmpNE32, 2583 getIReg(regRs), 2584 getIReg(regRt)))); 2585 break; 2586 2587 case 0x2A: /* Set Equals - SEQ; Cavium OCTEON */ 2588 DIP("seq r%u, r%u, %d", regRd, regRs, regRt); 2589 if (mode64) 2590 putIReg(regRd, unop(Iop_1Uto64, 2591 binop(Iop_CmpEQ64, getIReg(regRs), 2592 getIReg(regRt)))); 2593 else 2594 putIReg(regRd, unop(Iop_1Uto32, 2595 binop(Iop_CmpEQ32, getIReg(regRs), 2596 getIReg(regRt)))); 2597 break; 2598 2599 case 0x2E: /* Set Equals Immediate - SEQI; Cavium OCTEON */ 2600 DIP("seqi r%u, r%u, %u", regRt, regRs, imm); 2601 if (mode64) 2602 putIReg(regRt, unop(Iop_1Uto64, 2603 binop(Iop_CmpEQ64, getIReg(regRs), 2604 mkU64(extend_s_10to64(imm))))); 2605 else 2606 putIReg(regRt, unop(Iop_1Uto32, 2607 binop(Iop_CmpEQ32, getIReg(regRs), 2608 mkU32(extend_s_10to32(imm))))); 2609 break; 2610 2611 case 0x2F: /* Set Not Equals Immediate - SNEI; Cavium OCTEON */ 2612 DIP("snei r%u, r%u, %u", regRt, regRs, imm); 2613 if (mode64) 2614 putIReg(regRt, unop(Iop_1Uto64, 2615 binop(Iop_CmpNE64, 2616 getIReg(regRs), 2617 mkU64(extend_s_10to64(imm))))); 2618 else 2619 putIReg(regRt, unop(Iop_1Uto32, 2620 binop(Iop_CmpNE32, 2621 getIReg(regRs), 2622 mkU32(extend_s_10to32(imm))))); 2623 break; 2624 2625 default: 2626 return False; 2627 } 2628 break; 2629 } /* opc1 0x1C ends here*/ 2630 case 0x1F: { 2631 switch(opc2) { 2632 case 0x0A: { // lx - Load indexed instructions 2633 switch (get_sa(theInstr)) { 2634 case 0x00: { // LWX rd, index(base) 2635 DIP("lwx r%u, r%u(r%u)", regRd, regRt, regRs); 2636 LOADX_STORE_PATTERN; 2637 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2638 True)); 2639 break; 2640 } 2641 case 0x04: // LHX rd, index(base) 2642 DIP("lhx r%u, r%u(r%u)", regRd, regRt, regRs); 2643 LOADX_STORE_PATTERN; 2644 if (mode64) 2645 putIReg(regRd, unop(Iop_16Sto64, load(Ity_I16, 2646 mkexpr(t1)))); 2647 else 2648 putIReg(regRd, unop(Iop_16Sto32, load(Ity_I16, 2649 mkexpr(t1)))); 2650 break; 2651 case 0x08: { // LDX rd, index(base) 2652 DIP("ldx r%u, r%u(r%u)", regRd, regRt, regRs); 2653 vassert(mode64); /* Currently Implemented only for n64 */ 2654 LOADX_STORE_PATTERN; 2655 putIReg(regRd, load(Ity_I64, mkexpr(t1))); 2656 break; 2657 } 2658 case 0x06: { // LBUX rd, index(base) 2659 DIP("lbux r%u, r%u(r%u)", regRd, regRt, regRs); 2660 LOADX_STORE_PATTERN; 2661 if (mode64) 2662 putIReg(regRd, unop(Iop_8Uto64, load(Ity_I8, 2663 mkexpr(t1)))); 2664 else 2665 putIReg(regRd, unop(Iop_8Uto32, load(Ity_I8, 2666 mkexpr(t1)))); 2667 break; 2668 } 2669 case 0x10: { // LWUX rd, index(base) (Cavium OCTEON) 2670 DIP("lwux r%u, r%u(r%u)", regRd, regRt, regRs); 2671 LOADX_STORE_PATTERN; /* same for both 32 and 64 modes*/ 2672 putIReg(regRd, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), 2673 False)); 2674 break; 2675 } 2676 case 0x14: { // LHUX rd, index(base) (Cavium OCTEON) 2677 DIP("lhux r%u, r%u(r%u)", regRd, regRt, regRs); 2678 LOADX_STORE_PATTERN; 2679 if (mode64) 2680 putIReg(regRd, 2681 unop(Iop_16Uto64, load(Ity_I16, mkexpr(t1)))); 2682 else 2683 putIReg(regRd, 2684 unop(Iop_16Uto32, load(Ity_I16, mkexpr(t1)))); 2685 break; 2686 } 2687 case 0x16: { // LBX rd, index(base) (Cavium OCTEON) 2688 DIP("lbx r%u, r%u(r%u)", regRd, regRs, regRt); 2689 LOADX_STORE_PATTERN; 2690 if (mode64) 2691 putIReg(regRd, 2692 unop(Iop_8Sto64, load(Ity_I8, mkexpr(t1)))); 2693 else 2694 putIReg(regRd, 2695 unop(Iop_8Sto32, load(Ity_I8, mkexpr(t1)))); 2696 break; 2697 } 2698 default: 2699 vex_printf("\nUnhandled LX instruction opc3 = %x\n", 2700 get_sa(theInstr)); 2701 return False; 2702 } 2703 break; 2704 } 2705 } /* opc1 = 0x1F & opc2 = 0xA (LX) ends here*/ 2706 break; 2707 } /* opc1 = 0x1F ends here*/ 2708 default: 2709 return False; 2710 } /* main opc1 switch ends here */ 2711 return True; 2712 } 2713 2714 /*------------------------------------------------------------*/ 2715 /*--- Disassemble a single DSP ASE instruction ---*/ 2716 /*------------------------------------------------------------*/ 2717 2718 static UInt disDSPInstr_MIPS_WRK ( UInt cins ) 2719 { 2720 IRTemp t0, t1 = 0, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, 2721 t15, t16, t17; 2722 UInt opcode, rs, rt, rd, sa, function, ac, ac_mfhilo, rddsp_mask, 2723 wrdsp_mask, dsp_imm, shift; 2724 2725 opcode = get_opcode(cins); 2726 rs = get_rs(cins); 2727 rt = get_rt(cins); 2728 rd = get_rd(cins); 2729 sa = get_sa(cins); 2730 function = get_function(cins); 2731 ac = get_acNo(cins); 2732 ac_mfhilo = get_acNo_mfhilo(cins); 2733 rddsp_mask = get_rddspMask(cins); 2734 wrdsp_mask = get_wrdspMask(cins); 2735 dsp_imm = get_dspImm(cins); 2736 shift = get_shift(cins); 2737 2738 switch (opcode) { 2739 case 0x00: { /* Special */ 2740 switch (function) { 2741 case 0x10: { /* MFHI */ 2742 DIP("mfhi ac%u r%u", ac_mfhilo, rd); 2743 putIReg(rd, unop(Iop_64HIto32, getAcc(ac_mfhilo))); 2744 break; 2745 } 2746 2747 case 0x11: { /* MTHI */ 2748 DIP("mthi ac%u r%u", ac, rs); 2749 t1 = newTemp(Ity_I32); 2750 assign(t1, unop(Iop_64to32, getAcc(ac))); 2751 putAcc(ac, binop(Iop_32HLto64, getIReg(rs), mkexpr(t1))); 2752 break; 2753 } 2754 2755 case 0x12: { /* MFLO */ 2756 DIP("mflo ac%u r%u", ac_mfhilo, rd); 2757 putIReg(rd, unop(Iop_64to32, getAcc(ac_mfhilo))); 2758 break; 2759 } 2760 2761 case 0x13: { /* MTLO */ 2762 DIP("mtlo ac%u r%u", ac, rs); 2763 t1 = newTemp(Ity_I32); 2764 assign(t1, unop(Iop_64HIto32, getAcc(ac))); 2765 putAcc(ac, binop(Iop_32HLto64, mkexpr(t1), getIReg(rs))); 2766 break; 2767 } 2768 2769 case 0x18: { /* MULT */ 2770 DIP("mult ac%u r%u, r%u", ac, rs, rt); 2771 t1 = newTemp(Ity_I64); 2772 assign(t1, binop(Iop_MullS32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2773 mkNarrowTo32(Ity_I32, getIReg(rt)))); 2774 putAcc(ac, mkexpr(t1)); 2775 break; 2776 } 2777 2778 case 0x19: { /* MULTU */ 2779 DIP("multu ac%u r%u, r%u", ac, rs, rt); 2780 t1 = newTemp(Ity_I64); 2781 assign(t1, binop(Iop_MullU32, mkNarrowTo32(Ity_I32, getIReg(rs)), 2782 mkNarrowTo32(Ity_I32, 2783 getIReg(rt)))); 2784 putAcc(ac, mkexpr(t1)); 2785 break; 2786 } 2787 } 2788 break; 2789 } 2790 case 0x1C: { /* Special2 */ 2791 switch (function) { 2792 case 0x00: { /* MADD */ 2793 DIP("madd ac%u, r%u, r%u", ac, rs, rt); 2794 t1 = newTemp(Ity_I64); 2795 t2 = newTemp(Ity_I64); 2796 t3 = newTemp(Ity_I64); 2797 2798 assign(t1, getAcc(ac)); 2799 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2800 assign(t3, binop(Iop_Add64, mkexpr(t1), mkexpr(t2))); 2801 2802 putAcc(ac, mkexpr(t3)); 2803 break; 2804 } 2805 case 0x01: { /* MADDU */ 2806 DIP("maddu ac%u r%u, r%u", ac, rs, rt); 2807 t1 = newTemp(Ity_I64); 2808 t2 = newTemp(Ity_I64); 2809 t3 = newTemp(Ity_I64); 2810 2811 assign(t1, getAcc(ac)); 2812 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2813 assign(t3, binop(Iop_Add64, mkexpr(t2), mkexpr(t1))); 2814 2815 putAcc(ac, mkexpr(t3)); 2816 break; 2817 } 2818 case 0x04: { /* MSUB */ 2819 DIP("msub ac%u r%u, r%u", ac, rs, rt); 2820 t1 = newTemp(Ity_I64); 2821 t2 = newTemp(Ity_I64); 2822 t3 = newTemp(Ity_I64); 2823 2824 assign(t1, getAcc(ac)); 2825 assign(t2, binop(Iop_MullS32, getIReg(rs), getIReg(rt))); 2826 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2827 2828 putAcc(ac, mkexpr(t3)); 2829 break; 2830 } 2831 case 0x05: { /* MSUBU */ 2832 DIP("msubu ac%u r%u, r%u", ac, rs, rt); 2833 t1 = newTemp(Ity_I64); 2834 t2 = newTemp(Ity_I64); 2835 t3 = newTemp(Ity_I64); 2836 2837 assign(t1, getAcc(ac)); 2838 assign(t2, binop(Iop_MullU32, getIReg(rs), getIReg(rt))); 2839 assign(t3, binop(Iop_Sub64, mkexpr(t1), mkexpr(t2))); 2840 2841 putAcc(ac, mkexpr(t3)); 2842 break; 2843 } 2844 } 2845 break; 2846 } 2847 case 0x1F: { /* Special3 */ 2848 switch (function) { 2849 case 0x12: { /* ABSQ_S.PH */ 2850 switch (sa) { 2851 case 0x1: { /* ABSQ_S.QB */ 2852 DIP("absq_s.qb r%u, r%u", rd, rt); 2853 vassert(!mode64); 2854 t0 = newTemp(Ity_I8); 2855 t1 = newTemp(Ity_I1); 2856 t2 = newTemp(Ity_I1); 2857 t3 = newTemp(Ity_I8); 2858 t4 = newTemp(Ity_I8); 2859 t5 = newTemp(Ity_I1); 2860 t6 = newTemp(Ity_I1); 2861 t7 = newTemp(Ity_I8); 2862 t8 = newTemp(Ity_I8); 2863 t9 = newTemp(Ity_I1); 2864 t10 = newTemp(Ity_I1); 2865 t11 = newTemp(Ity_I8); 2866 t12 = newTemp(Ity_I8); 2867 t13 = newTemp(Ity_I1); 2868 t14 = newTemp(Ity_I1); 2869 t15 = newTemp(Ity_I8); 2870 t16 = newTemp(Ity_I32); 2871 t17 = newTemp(Ity_I32); 2872 2873 /* Absolute value of the rightmost byte (bits 7-0). */ 2874 /* t0 - rightmost byte. */ 2875 assign(t0, unop(Iop_16to8, unop(Iop_32to16, getIReg(rt)))); 2876 /* t1 holds 1 if t0 is equal to 0x80, or 0 otherwise. */ 2877 assign(t1, binop(Iop_CmpEQ32, 2878 unop(Iop_8Uto32, mkexpr(t0)), 2879 mkU32(0x00000080))); 2880 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 2881 assign(t2, unop(Iop_32to1, 2882 binop(Iop_Shr32, 2883 binop(Iop_And32, 2884 getIReg(rt), 2885 mkU32(0x00000080)), 2886 mkU8(0x7)))); 2887 /* t3 holds abs(t0). */ 2888 assign(t3, IRExpr_ITE(mkexpr(t1), 2889 mkU8(0x7F), 2890 IRExpr_ITE(mkexpr(t2), 2891 binop(Iop_Add8, 2892 unop(Iop_Not8, 2893 mkexpr(t0)), 2894 mkU8(0x1)), 2895 mkexpr(t0)))); 2896 2897 /* Absolute value of bits 15-8. */ 2898 /* t4 - input byte. */ 2899 assign(t4, 2900 unop(Iop_16HIto8, unop(Iop_32to16, getIReg(rt)))); 2901 /* t5 holds 1 if t4 is equal to 0x80, or 0 otherwise. */ 2902 assign(t5, binop(Iop_CmpEQ32, 2903 unop(Iop_8Uto32, mkexpr(t4)), 2904 mkU32(0x00000080))); 2905 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 2906 assign(t6, unop(Iop_32to1, 2907 binop(Iop_Shr32, 2908 binop(Iop_And32, 2909 getIReg(rt), 2910 mkU32(0x00008000)), 2911 mkU8(15)))); 2912 /* t3 holds abs(t4). */ 2913 assign(t7, IRExpr_ITE(mkexpr(t5), 2914 mkU8(0x7F), 2915 IRExpr_ITE(mkexpr(t6), 2916 binop(Iop_Add8, 2917 unop(Iop_Not8, 2918 mkexpr(t4)), 2919 mkU8(0x1)), 2920 mkexpr(t4)))); 2921 2922 /* Absolute value of bits 23-15. */ 2923 /* t8 - input byte. */ 2924 assign(t8, 2925 unop(Iop_16to8, unop(Iop_32HIto16, getIReg(rt)))); 2926 /* t9 holds 1 if t8 is equal to 0x80, or 0 otherwise. */ 2927 assign(t9, binop(Iop_CmpEQ32, 2928 unop(Iop_8Uto32, mkexpr(t8)), 2929 mkU32(0x00000080))); 2930 /* t6 holds 1 if value in t8 is negative, 0 otherwise. */ 2931 assign(t10, unop(Iop_32to1, 2932 binop(Iop_Shr32, 2933 binop(Iop_And32, 2934 getIReg(rt), 2935 mkU32(0x00800000)), 2936 mkU8(23)))); 2937 /* t3 holds abs(t8). */ 2938 assign(t11, IRExpr_ITE(mkexpr(t9), 2939 mkU8(0x7F), 2940 IRExpr_ITE(mkexpr(t10), 2941 binop(Iop_Add8, 2942 unop(Iop_Not8, 2943 mkexpr(t8)), 2944 mkU8(0x1)), 2945 mkexpr(t8)))); 2946 2947 /* Absolute value of bits 31-24. */ 2948 /* t12 - input byte. */ 2949 assign(t12, 2950 unop(Iop_16HIto8, unop(Iop_32HIto16, getIReg(rt)))); 2951 /* t13 holds 1 if t12 is equal to 0x80, or 0 otherwise. */ 2952 assign(t13, binop(Iop_CmpEQ32, 2953 unop(Iop_8Uto32, mkexpr(t12)), 2954 mkU32(0x00000080))); 2955 /* t14 holds 1 if value in t12 is negative, 0 otherwise. */ 2956 assign(t14, unop(Iop_32to1, 2957 binop(Iop_Shr32, 2958 binop(Iop_And32, 2959 getIReg(rt), 2960 mkU32(0x80000000)), 2961 mkU8(31)))); 2962 /* t15 holds abs(t12). */ 2963 assign(t15, IRExpr_ITE(mkexpr(t13), 2964 mkU8(0x7F), 2965 IRExpr_ITE(mkexpr(t14), 2966 binop(Iop_Add8, 2967 unop(Iop_Not8, 2968 mkexpr(t12)), 2969 mkU8(0x1)), 2970 mkexpr(t12)))); 2971 2972 /* t16 holds !0 if any of input bytes is 0x80 or 0 2973 otherwise. */ 2974 assign(t16, 2975 binop(Iop_Or32, 2976 binop(Iop_Or32, 2977 binop(Iop_Or32, 2978 unop(Iop_1Sto32, mkexpr(t13)), 2979 unop(Iop_1Sto32, mkexpr(t9))), 2980 unop(Iop_1Sto32, mkexpr(t5))), 2981 unop(Iop_1Sto32, mkexpr(t1)))); 2982 2983 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 2984 mkexpr(t16), 2985 mkU32(0x0)), 2986 getDSPControl(), 2987 binop(Iop_Or32, 2988 getDSPControl(), 2989 mkU32(0x00100000)))); 2990 2991 /* t17 = t15|t11|t7|t3 */ 2992 assign(t17, 2993 binop(Iop_16HLto32, 2994 binop(Iop_8HLto16, mkexpr(t15), mkexpr(t11)), 2995 binop(Iop_8HLto16, mkexpr(t7), mkexpr(t3)))); 2996 2997 putIReg(rd, mkexpr(t17)); 2998 break; 2999 } 3000 case 0x2: { /* REPL.QB */ 3001 DIP("repl.qb r%u, %u", rd, dsp_imm); 3002 vassert(!mode64); 3003 3004 putIReg(rd, mkU32((dsp_imm << 24) | (dsp_imm << 16) | 3005 (dsp_imm << 8) | (dsp_imm))); 3006 break; 3007 } 3008 case 0x3: { /* REPLV.QB */ 3009 DIP("replv.qb r%u, r%u", rd, rt); 3010 vassert(!mode64); 3011 t0 = newTemp(Ity_I8); 3012 3013 assign(t0, unop(Iop_32to8, 3014 binop(Iop_And32, getIReg(rt), mkU32(0xff)))); 3015 putIReg(rd, 3016 binop(Iop_16HLto32, 3017 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)), 3018 binop(Iop_8HLto16, mkexpr(t0), mkexpr(t0)))); 3019 break; 3020 } 3021 case 0x4: { /* PRECEQU.PH.QBL */ 3022 DIP("precequ.ph.qbl r%u, r%u", rd, rt); 3023 vassert(!mode64); 3024 3025 putIReg(rd, binop(Iop_Or32, 3026 binop(Iop_Shr32, 3027 binop(Iop_And32, 3028 getIReg(rt), 3029 mkU32(0xff000000)), 3030 mkU8(1)), 3031 binop(Iop_Shr32, 3032 binop(Iop_And32, 3033 getIReg(rt), 3034 mkU32(0x00ff0000)), 3035 mkU8(9)))); 3036 break; 3037 } 3038 case 0x5: { /* PRECEQU.PH.QBR */ 3039 DIP("precequ.ph.qbr r%u, r%u", rd, rt); 3040 vassert(!mode64); 3041 3042 putIReg(rd, binop(Iop_Or32, 3043 binop(Iop_Shl32, 3044 binop(Iop_And32, 3045 getIReg(rt), 3046 mkU32(0x0000ff00)), 3047 mkU8(15)), 3048 binop(Iop_Shl32, 3049 binop(Iop_And32, 3050 getIReg(rt), 3051 mkU32(0x000000ff)), 3052 mkU8(7)))); 3053 break; 3054 } 3055 case 0x6: { /* PRECEQU.PH.QBLA */ 3056 DIP("precequ.ph.qbla r%u, r%u", rd, rt); 3057 vassert(!mode64); 3058 3059 putIReg(rd, binop(Iop_Or32, 3060 binop(Iop_Shr32, 3061 binop(Iop_And32, 3062 getIReg(rt), 3063 mkU32(0xff000000)), 3064 mkU8(1)), 3065 binop(Iop_Shr32, 3066 binop(Iop_And32, 3067 getIReg(rt), 3068 mkU32(0x0000ff00)), 3069 mkU8(1)))); 3070 break; 3071 } 3072 case 0x7: { /* PRECEQU.PH.QBRA */ 3073 DIP("precequ.ph.qbra r%u, r%u", rd, rt); 3074 vassert(!mode64); 3075 3076 putIReg(rd, binop(Iop_Or32, 3077 binop(Iop_Shl32, 3078 binop(Iop_And32, 3079 getIReg(rt), 3080 mkU32(0x00ff0000)), 3081 mkU8(7)), 3082 binop(Iop_Shl32, 3083 binop(Iop_And32, 3084 getIReg(rt), 3085 mkU32(0x000000ff)), 3086 mkU8(7)))); 3087 break; 3088 } 3089 case 0x9: { /* ABSQ_S.PH */ 3090 DIP("absq_s.ph r%u, r%u", rd, rt); 3091 vassert(!mode64); 3092 t0 = newTemp(Ity_I16); 3093 t1 = newTemp(Ity_I1); 3094 t2 = newTemp(Ity_I1); 3095 t3 = newTemp(Ity_I16); 3096 t4 = newTemp(Ity_I16); 3097 t5 = newTemp(Ity_I1); 3098 t6 = newTemp(Ity_I1); 3099 t7 = newTemp(Ity_I16); 3100 t8 = newTemp(Ity_I32); 3101 t9 = newTemp(Ity_I32); 3102 3103 /* t0 holds lower 16 bits of value in rt. */ 3104 assign(t0, unop(Iop_32to16, getIReg(rt))); 3105 /* t1 holds 1 if t0 is equal to 0x8000. */ 3106 assign(t1, binop(Iop_CmpEQ32, 3107 unop(Iop_16Uto32, mkexpr(t0)), 3108 mkU32(0x00008000))); 3109 /* t2 holds 1 if value in t0 is negative, 0 otherwise. */ 3110 assign(t2, unop(Iop_32to1, 3111 binop(Iop_Shr32, 3112 binop(Iop_And32, 3113 getIReg(rt), 3114 mkU32(0x00008000)), 3115 mkU8(15)))); 3116 /* t3 holds abs(t0). */ 3117 assign(t3, IRExpr_ITE(mkexpr(t1), 3118 mkU16(0x7FFF), 3119 IRExpr_ITE(mkexpr(t2), 3120 binop(Iop_Add16, 3121 unop(Iop_Not16, 3122 mkexpr(t0)), 3123 mkU16(0x1)), 3124 mkexpr(t0)))); 3125 3126 /* t4 holds lower 16 bits of value in rt. */ 3127 assign(t4, unop(Iop_32HIto16, getIReg(rt))); 3128 /* t5 holds 1 if t4 is equal to 0x8000. */ 3129 assign(t5, binop(Iop_CmpEQ32, 3130 unop(Iop_16Uto32, mkexpr(t4)), 3131 mkU32(0x00008000))); 3132 /* t6 holds 1 if value in t4 is negative, 0 otherwise. */ 3133 assign(t6, unop(Iop_32to1, 3134 binop(Iop_Shr32, 3135 binop(Iop_And32, 3136 getIReg(rt), 3137 mkU32(0x80000000)), 3138 mkU8(31)))); 3139 /* t7 holds abs(t4). */ 3140 assign(t7, IRExpr_ITE(mkexpr(t5), 3141 mkU16(0x7FFF), 3142 IRExpr_ITE(mkexpr(t6), 3143 binop(Iop_Add16, 3144 unop(Iop_Not16, 3145 mkexpr(t4)), 3146 mkU16(0x1)), 3147 mkexpr(t4)))); 3148 /* If any of the two input halfwords is equal 0x8000, 3149 set bit 20 in DSPControl register. */ 3150 assign(t8, binop(Iop_Or32, 3151 unop(Iop_1Sto32, mkexpr(t5)), 3152 unop(Iop_1Sto32, mkexpr(t1)))); 3153 3154 putDSPControl(IRExpr_ITE(binop(Iop_CmpEQ32, 3155 mkexpr(t8), 3156 mkU32(0x0)), 3157 getDSPControl(), 3158 binop(Iop_Or32, 3159 getDSPControl(), 3160 mkU32(0x00100000)))); 3161 3162 /* t9 = t7|t3 */ 3163 assign(t9, binop(Iop_16HLto32, mkexpr(t7), mkexpr(t3))); 3164 3165 putIReg(rd, mkexpr(t9)); 3166 break; 3167 } 3168 case 0xA: { /* REPL.PH */ 3169 DIP("repl.ph r%u, %u", rd, dsp_imm); 3170 vassert(!mode64); 3171 UShort immediate = extend_s_10to16(dsp_imm); 3172 3173 putIReg(rd, mkU32(immediate << 16 | immediate)); 3174 break; 3175 } 3176 case 0xB: { /* REPLV.PH */ 3177 DIP("replv.ph r%u, r%u", rd, rt); 3178 vassert(!mode64); 3179 3180 putIReg(rd, binop(Iop_16HLto32, 3181 unop(Iop_32to16, getIReg(rt)), 3182 unop(Iop_32to16, getIReg(rt)))); 3183 break; 3184 } 3185 case 0xC: { /* PRECEQ.W.PHL */ 3186 DIP("preceq.w.phl r%u, r%u", rd, rt); 3187 vassert(!mode64); 3188 putIReg(rd, binop(Iop_And32, 3189 getIReg(rt), 3190 mkU32(0xffff0000))); 3191 break; 3192 } 3193 case 0xD: { /* PRECEQ.W.PHR */ 3194 DIP("preceq.w.phr r%u, r%u", rd, rt); 3195 vassert(!mode64); 3196 putIReg(rd, binop(Iop_16HLto32, 3197 unop(Iop_32to16, getIReg(rt)), 3198 mkU16(0x0))); 3199 break; 3200 } 3201 case 0x11: { /* ABSQ_S.W */ 3202 DIP("absq_s.w r%u, r%u", rd, rt); 3203 vassert(!mode64); 3204 t0 = newTemp(Ity_I1); 3205 t1 = newTemp(Ity_I1); 3206 t2 = newTemp(Ity_I32); 3207 3208 assign(t0, 3209 binop(Iop_CmpEQ32, getIReg(rt), mkU32(0x80000000))); 3210 3211 putDSPControl(IRExpr_ITE(mkexpr(t0), 3212 binop(Iop_Or32, 3213 getDSPControl(), 3214 mkU32(0x00100000)), 3215 getDSPControl())); 3216 3217 assign(t1, binop(Iop_CmpLT32S, getIReg(rt), mkU32(0x0))); 3218 3219 assign(t2, IRExpr_ITE(mkexpr(t0), 3220 mkU32(0x7FFFFFFF), 3221 IRExpr_ITE(mkexpr(t1), 3222 binop(Iop_Add32, 3223 unop(Iop_Not32, 3224 getIReg(rt)), 3225 mkU32(0x1)), 3226 getIReg(rt)))); 3227 putIReg(rd, mkexpr(t2)); 3228 break; 3229 } 3230 case 0x1B: { /* BITREV */ 3231 DIP("bitrev r%u, r%u", rd, rt); 3232 vassert(!mode64); 3233 /* 32bit reversal as seen on Bit Twiddling Hacks site 3234 http://graphics.stanford.edu/~seander/bithacks.html 3235 section ReverseParallel */ 3236 t1 = newTemp(Ity_I32); 3237 t2 = newTemp(Ity_I32); 3238 t3 = newTemp(Ity_I32); 3239 t4 = newTemp(Ity_I32); 3240 t5 = newTemp(Ity_I32); 3241 3242 assign(t1, binop(Iop_Or32, 3243 binop(Iop_Shr32, 3244 binop(Iop_And32, 3245 getIReg(rt), 3246 mkU32(0xaaaaaaaa)), 3247 mkU8(0x1)), 3248 binop(Iop_Shl32, 3249 binop(Iop_And32, 3250 getIReg(rt), 3251 mkU32(0x55555555)), 3252 mkU8(0x1)))); 3253 assign(t2, binop(Iop_Or32, 3254 binop(Iop_Shr32, 3255 binop(Iop_And32, 3256 mkexpr(t1), 3257 mkU32(0xcccccccc)), 3258 mkU8(0x2)), 3259 binop(Iop_Shl32, 3260 binop(Iop_And32, 3261 mkexpr(t1), 3262 mkU32(0x33333333)), 3263 mkU8(0x2)))); 3264 assign(t3, binop(Iop_Or32, 3265 binop(Iop_Shr32, 3266 binop(Iop_And32, 3267 mkexpr(t2), 3268 mkU32(0xf0f0f0f0)), 3269 mkU8(0x4)), 3270 binop(Iop_Shl32, 3271 binop(Iop_And32, 3272 mkexpr(t2), 3273 mkU32(0x0f0f0f0f)), 3274 mkU8(0x4)))); 3275 assign(t4, binop(Iop_Or32, 3276 binop(Iop_Shr32, 3277 binop(Iop_And32, 3278 mkexpr(t3), 3279 mkU32(0xff00ff00)), 3280 mkU8(0x8)), 3281 binop(Iop_Shl32, 3282 binop(Iop_And32, 3283 mkexpr(t3), 3284 mkU32(0x00ff00ff)), 3285 mkU8(0x8)))); 3286 assign(t5, binop(Iop_Or32, 3287 binop(Iop_Shr32, 3288 mkexpr(t4), 3289 mkU8(0x10)), 3290 binop(Iop_Shl32, 3291 mkexpr(t4), 3292 mkU8(0x10)))); 3293 putIReg(rd, binop(Iop_Shr32, 3294 mkexpr(t5), 3295 mkU8(16))); 3296 break; 3297 } 3298 case 0x1C: { /* PRECEU.PH.QBL */ 3299 DIP("preceu.ph.qbl r%u, r%u", rd, rt); 3300 vassert(!mode64); 3301 3302 putIReg(rd, binop(Iop_Or32, 3303 binop(Iop_Shr32, 3304 binop(Iop_And32, 3305 getIReg(rt), 3306 mkU32(0xff000000)), 3307 mkU8(8)), 3308 binop(Iop_Shr32, 3309 binop(Iop_And32, 3310 getIReg(rt), 3311 mkU32(0x00ff0000)), 3312 mkU8(16)))); 3313 break; 3314 } 3315 case 0x1E: { /* PRECEU.PH.QBLA */ 3316 DIP("preceu.ph.qbla r%u, r%u", rd, rt); 3317 vassert(!mode64); 3318 3319 putIReg(rd, binop(Iop_Or32, 3320 binop(Iop_Shr32, 3321 binop(Iop_And32, 3322 getIReg(rt), 3323 mkU32(0xff000000)), 3324 mkU8(8)), 3325 binop(Iop_Shr32, 3326 binop(Iop_And32, 3327 getIReg(rt), 3328 mkU32(0x0000ff00)), 3329 mkU8(8)))); 3330 break; 3331 } 3332 case 0x1D: { /* PRECEU.PH.QBR */ 3333 DIP("preceu.ph.qbr r%u, r%u", rd, rt); 3334 vassert(!mode64); 3335 3336 putIReg(rd, binop(Iop_Or32, 3337 binop(Iop_Shl32, 3338 binop(Iop_And32, 3339 getIReg(rt), 3340 mkU32(0x0000ff00)), 3341 mkU8(8)), 3342 binop(Iop_And32, 3343 getIReg(rt), 3344 mkU32(0x000000ff)))); 3345 break; 3346 } 3347 case 0x1F: { /* PRECEU.PH.QBRA */ 3348 DIP("preceu.ph.qbra r%u, r%u", rd, rt); 3349 vassert(!mode64); 3350 3351 putIReg(rd, binop(Iop_Or32, 3352 binop(Iop_And32, 3353 getIReg(rt), 3354 mkU32(0x00ff0000)), 3355 binop(Iop_And32, 3356 getIReg(rt), 3357 mkU32(0x000000ff)))); 3358 break; 3359 } 3360 default: 3361 return -1; 3362 } 3363 break; /* end of ABSQ_S.PH */ 3364 } 3365 case 0x38: { /* EXTR.W */ 3366 switch(sa) { 3367 case 0x0: { /* EXTR.W */ 3368 DIP("extr.w r%u, ac%u, %u", rt, ac, rs); 3369 vassert(!mode64); 3370 t0 = newTemp(Ity_I64); 3371 t1 = newTemp(Ity_I64); 3372 t2 = newTemp(Ity_I32); 3373 t3 = newTemp(Ity_I1); 3374 t4 = newTemp(Ity_I1); 3375 t5 = newTemp(Ity_I1); 3376 t6 = newTemp(Ity_I1); 3377 t7 = newTemp(Ity_I32); 3378 t8 = newTemp(Ity_I64); 3379 t9 = newTemp(Ity_I64); 3380 t10 = newTemp(Ity_I1); 3381 t11 = newTemp(Ity_I1); 3382 t12 = newTemp(Ity_I1); 3383 t13 = newTemp(Ity_I1); 3384 t14 = newTemp(Ity_I32); 3385 3386 assign(t0, getAcc(ac)); 3387 if (0 == rs) { 3388 assign(t1, mkexpr(t0)); 3389 } else { 3390 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 3391 } 3392 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3393 assign(t3, binop(Iop_CmpNE32, 3394 unop(Iop_64HIto32, 3395 mkexpr(t1)), 3396 mkU32(0))); 3397 assign(t4, binop(Iop_CmpNE32, 3398 binop(Iop_And32, 3399 unop(Iop_64to32, 3400 mkexpr(t1)), 3401 mkU32(0x80000000)), 3402 mkU32(0))); 3403 /* Check if bits 63..31 of the result in t1 aren't 3404 0x1ffffffff. */ 3405 assign(t5, binop(Iop_CmpNE32, 3406 unop(Iop_64HIto32, 3407 mkexpr(t1)), 3408 mkU32(0xffffffff))); 3409 assign(t6, binop(Iop_CmpNE32, 3410 binop(Iop_And32, 3411 unop(Iop_64to32, 3412 mkexpr(t1)), 3413 mkU32(0x80000000)), 3414 mkU32(0x80000000))); 3415 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3416 control register. */ 3417 assign(t7, binop(Iop_And32, 3418 binop(Iop_Or32, 3419 unop(Iop_1Sto32, mkexpr(t3)), 3420 unop(Iop_1Sto32, mkexpr(t4))), 3421 binop(Iop_Or32, 3422 unop(Iop_1Sto32, mkexpr(t5)), 3423 unop(Iop_1Sto32, mkexpr(t6))))); 3424 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3425 mkexpr(t7), 3426 mkU32(0)), 3427 binop(Iop_Or32, 3428 getDSPControl(), 3429 mkU32(0x00800000)), 3430 getDSPControl())); 3431 3432 /* If the last discarded bit is 1, there would be carry 3433 when rounding, otherwise there wouldn't. We use that 3434 fact and just add the value of the last discarded bit 3435 to the least sifgnificant bit of the shifted value 3436 from acc. */ 3437 if (0 == rs) { 3438 assign(t8, mkU64(0x0ULL)); 3439 } else { 3440 assign(t8, binop(Iop_And64, 3441 binop(Iop_Shr64, 3442 mkexpr(t0), 3443 mkU8(rs-1)), 3444 mkU64(0x1ULL))); 3445 } 3446 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3447 3448 /* Repeat previous steps for the rounded value. */ 3449 assign(t10, binop(Iop_CmpNE32, 3450 unop(Iop_64HIto32, 3451 mkexpr(t9)), 3452 mkU32(0))); 3453 assign(t11, binop(Iop_CmpNE32, 3454 binop(Iop_And32, 3455 unop(Iop_64to32, 3456 mkexpr(t9)), 3457 mkU32(0x80000000)), 3458 mkU32(0))); 3459 3460 assign(t12, binop(Iop_CmpNE32, 3461 unop(Iop_64HIto32, 3462 mkexpr(t9)), 3463 mkU32(0xffffffff))); 3464 assign(t13, binop(Iop_CmpNE32, 3465 binop(Iop_And32, 3466 unop(Iop_64to32, 3467 mkexpr(t9)), 3468 mkU32(0x80000000)), 3469 mkU32(0x80000000))); 3470 3471 assign(t14, binop(Iop_And32, 3472 binop(Iop_Or32, 3473 unop(Iop_1Sto32, mkexpr(t10)), 3474 unop(Iop_1Sto32, mkexpr(t11))), 3475 binop(Iop_Or32, 3476 unop(Iop_1Sto32, mkexpr(t12)), 3477 unop(Iop_1Sto32, mkexpr(t13))))); 3478 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3479 mkexpr(t14), 3480 mkU32(0)), 3481 binop(Iop_Or32, 3482 getDSPControl(), 3483 mkU32(0x00800000)), 3484 getDSPControl())); 3485 if (0 == rs) { 3486 putIReg(rt, unop(Iop_64to32, mkexpr(t0))); 3487 } else { 3488 putIReg(rt, unop(Iop_64to32, mkexpr(t1))); 3489 } 3490 break; 3491 } 3492 case 0x1: { /* EXTRV.W */ 3493 DIP("extrv.w r%u, ac%u, r%u", rt, ac, rs); 3494 vassert(!mode64); 3495 t0 = newTemp(Ity_I64); 3496 t1 = newTemp(Ity_I64); 3497 t2 = newTemp(Ity_I32); 3498 t3 = newTemp(Ity_I1); 3499 t4 = newTemp(Ity_I1); 3500 t5 = newTemp(Ity_I1); 3501 t6 = newTemp(Ity_I1); 3502 t7 = newTemp(Ity_I32); 3503 t8 = newTemp(Ity_I64); 3504 t9 = newTemp(Ity_I64); 3505 t10 = newTemp(Ity_I1); 3506 t11 = newTemp(Ity_I1); 3507 t12 = newTemp(Ity_I1); 3508 t13 = newTemp(Ity_I1); 3509 t14 = newTemp(Ity_I32); 3510 t15 = newTemp(Ity_I8); 3511 3512 assign(t15, unop(Iop_32to8, 3513 binop(Iop_And32, 3514 getIReg(rs), 3515 mkU32(0x1f)))); 3516 assign(t0, getAcc(ac)); 3517 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3518 putIReg(rt, IRExpr_ITE(binop(Iop_CmpEQ32, 3519 unop(Iop_8Uto32, 3520 mkexpr(t15)), 3521 mkU32(0)), 3522 unop(Iop_64to32, mkexpr(t0)), 3523 unop(Iop_64to32, mkexpr(t1)))); 3524 3525 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3526 assign(t3, binop(Iop_CmpNE32, 3527 unop(Iop_64HIto32, 3528 mkexpr(t1)), 3529 mkU32(0))); 3530 assign(t4, binop(Iop_CmpNE32, 3531 binop(Iop_And32, 3532 unop(Iop_64to32, 3533 mkexpr(t1)), 3534 mkU32(0x80000000)), 3535 mkU32(0))); 3536 /* Check if bits 63..31 of the result in t1 aren't 3537 0x1ffffffff. */ 3538 assign(t5, binop(Iop_CmpNE32, 3539 unop(Iop_64HIto32, 3540 mkexpr(t1)), 3541 mkU32(0xffffffff))); 3542 assign(t6, binop(Iop_CmpNE32, 3543 binop(Iop_And32, 3544 unop(Iop_64to32, 3545 mkexpr(t1)), 3546 mkU32(0x80000000)), 3547 mkU32(0x80000000))); 3548 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3549 control register. */ 3550 assign(t7, binop(Iop_And32, 3551 binop(Iop_Or32, 3552 unop(Iop_1Sto32, mkexpr(t3)), 3553 unop(Iop_1Sto32, mkexpr(t4))), 3554 binop(Iop_Or32, 3555 unop(Iop_1Sto32, mkexpr(t5)), 3556 unop(Iop_1Sto32, mkexpr(t6))))); 3557 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3558 mkexpr(t7), 3559 mkU32(0)), 3560 binop(Iop_Or32, 3561 getDSPControl(), 3562 mkU32(0x00800000)), 3563 getDSPControl())); 3564 3565 /* If the last discarded bit is 1, there would be carry 3566 when rounding, otherwise there wouldn't. We use that 3567 fact and just add the value of the last discarded bit 3568 to the least sifgnificant bit of the shifted value 3569 from acc. */ 3570 assign(t8, 3571 IRExpr_ITE(binop(Iop_CmpEQ32, 3572 unop(Iop_8Uto32, 3573 mkexpr(t15)), 3574 mkU32(0)), 3575 mkU64(0x0ULL), 3576 binop(Iop_And64, 3577 binop(Iop_Shr64, 3578 mkexpr(t0), 3579 unop(Iop_32to8, 3580 binop(Iop_Sub32, 3581 unop(Iop_8Uto32, 3582 mkexpr(t15)), 3583 mkU32(1)))), 3584 mkU64(0x1ULL)))); 3585 3586 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3587 3588 /* Repeat previous steps for the rounded value. */ 3589 assign(t10, binop(Iop_CmpNE32, 3590 unop(Iop_64HIto32, 3591 mkexpr(t9)), 3592 mkU32(0))); 3593 assign(t11, binop(Iop_CmpNE32, 3594 binop(Iop_And32, 3595 unop(Iop_64to32, 3596 mkexpr(t9)), 3597 mkU32(0x80000000)), 3598 mkU32(0))); 3599 3600 assign(t12, binop(Iop_CmpNE32, 3601 unop(Iop_64HIto32, 3602 mkexpr(t9)), 3603 mkU32(0xffffffff))); 3604 assign(t13, binop(Iop_CmpNE32, 3605 binop(Iop_And32, 3606 unop(Iop_64to32, 3607 mkexpr(t9)), 3608 mkU32(0x80000000)), 3609 mkU32(0x80000000))); 3610 3611 assign(t14, binop(Iop_And32, 3612 binop(Iop_Or32, 3613 unop(Iop_1Sto32, mkexpr(t10)), 3614 unop(Iop_1Sto32, mkexpr(t11))), 3615 binop(Iop_Or32, 3616 unop(Iop_1Sto32, mkexpr(t12)), 3617 unop(Iop_1Sto32, mkexpr(t13))))); 3618 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3619 mkexpr(t14), 3620 mkU32(0)), 3621 binop(Iop_Or32, 3622 getDSPControl(), 3623 mkU32(0x00800000)), 3624 getDSPControl())); 3625 break; 3626 } 3627 case 0x2: { /* EXTP */ 3628 DIP("extp r%u, ac%u, %u", rt, ac, rs); 3629 vassert(!mode64); 3630 t0 = newTemp(Ity_I64); 3631 t1 = newTemp(Ity_I32); 3632 t2 = newTemp(Ity_I1); 3633 t3 = newTemp(Ity_I1); 3634 t4 = newTemp(Ity_I8); 3635 t5 = newTemp(Ity_I64); 3636 t6 = newTemp(Ity_I64); 3637 t7 = newTemp(Ity_I32); 3638 3639 assign(t0, getAcc(ac)); 3640 /* Extract pos field of DSPControl register. */ 3641 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3642 3643 /* Check if (pos - size) >= 0 [size <= pos] 3644 if (pos < size) 3645 put 1 to EFI field of DSPControl register 3646 else 3647 extract bits from acc and put 0 to EFI field of 3648 DSPCtrl */ 3649 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 3650 3651 putDSPControl(IRExpr_ITE(mkexpr(t2), 3652 binop(Iop_Or32, 3653 binop(Iop_And32, 3654 getDSPControl(), 3655 mkU32(0xffffbfff)), 3656 mkU32(0x4000)), 3657 binop(Iop_And32, 3658 getDSPControl(), 3659 mkU32(0xffffbfff)))); 3660 3661 /* If pos <= 31, shift right the value from the acc 3662 (pos-size) times and take (size+1) bits from the least 3663 significant positions. Otherwise, shift left the value 3664 (63-pos) times, take (size+1) bits from the most 3665 significant positions and shift right (31-size) times.*/ 3666 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3667 3668 assign(t4, 3669 IRExpr_ITE(mkexpr(t3), 3670 unop(Iop_32to8, 3671 binop(Iop_Sub32, 3672 mkexpr(t1), mkU32(rs))), 3673 unop(Iop_32to8, 3674 binop(Iop_Sub32, 3675 mkU32(63), mkexpr(t1))))); 3676 3677 assign(t5, IRExpr_ITE(mkexpr(t3), 3678 binop(Iop_Shr64, 3679 mkexpr(t0), mkexpr(t4)), 3680 binop(Iop_Shl64, 3681 mkexpr(t0), mkexpr(t4)))); 3682 3683 /* t6 holds a mask for bit extraction */ 3684 assign(t6, 3685 IRExpr_ITE(mkexpr(t3), 3686 unop(Iop_Not64, 3687 binop(Iop_Shl64, 3688 mkU64(0xffffffffffffffffULL), 3689 mkU8(rs+1))), 3690 unop(Iop_Not64, 3691 binop(Iop_Shr64, 3692 mkU64(0xffffffffffffffffULL), 3693 mkU8(rs+1))))); 3694 3695 assign(t7, IRExpr_ITE(mkexpr(t3), 3696 unop(Iop_64to32, 3697 binop(Iop_And64, 3698 mkexpr(t5), 3699 mkexpr(t6))), 3700 binop(Iop_Shr32, 3701 unop(Iop_64HIto32, 3702 binop(Iop_And64, 3703 mkexpr(t5), 3704 mkexpr(t6))), 3705 mkU8(31-rs)))); 3706 3707 putIReg(rt, mkexpr(t7)); 3708 break; 3709 } 3710 case 0x3: { /* EXTPV */ 3711 DIP("extpv r%u, ac%u, r%u", rt, ac, rs); 3712 vassert(!mode64); 3713 t0 = newTemp(Ity_I64); 3714 t1 = newTemp(Ity_I32); 3715 t2 = newTemp(Ity_I1); 3716 t3 = newTemp(Ity_I1); 3717 t4 = newTemp(Ity_I8); 3718 t5 = newTemp(Ity_I64); 3719 t6 = newTemp(Ity_I64); 3720 t7 = newTemp(Ity_I32); 3721 t8 = newTemp(Ity_I32); 3722 3723 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 3724 assign(t0, getAcc(ac)); 3725 /* Extract pos field of DSPControl register. */ 3726 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 3727 3728 /* Check if (pos - size) >= 0 [size <= pos] 3729 if (pos < size) 3730 put 1 to EFI field of DSPControl register 3731 else 3732 extract bits from acc and put 0 to EFI field of 3733 DSPCtrl */ 3734 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 3735 3736 putDSPControl(IRExpr_ITE(mkexpr(t2), 3737 binop(Iop_Or32, 3738 binop(Iop_And32, 3739 getDSPControl(), 3740 mkU32(0xffffbfff)), 3741 mkU32(0x4000)), 3742 binop(Iop_And32, 3743 getDSPControl(), 3744 mkU32(0xffffbfff)))); 3745 3746 /* If pos <= 31, shift right the value from the acc 3747 (pos-size) times and take (size+1) bits from the least 3748 significant positions. Otherwise, shift left the value 3749 (63-pos) times, take (size+1) bits from the most 3750 significant positions and shift right (31-size) 3751 times. */ 3752 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 3753 3754 assign(t4, 3755 IRExpr_ITE(mkexpr(t3), 3756 unop(Iop_32to8, 3757 binop(Iop_Sub32, 3758 mkexpr(t1), mkexpr(t8))), 3759 unop(Iop_32to8, 3760 binop(Iop_Sub32, 3761 mkU32(63), mkexpr(t1))))); 3762 3763 assign(t5, IRExpr_ITE(mkexpr(t3), 3764 binop(Iop_Shr64, 3765 mkexpr(t0), mkexpr(t4)), 3766 binop(Iop_Shl64, 3767 mkexpr(t0), mkexpr(t4)))); 3768 3769 /* t6 holds a mask for bit extraction. */ 3770 assign(t6, 3771 IRExpr_ITE(mkexpr(t3), 3772 unop(Iop_Not64, 3773 binop(Iop_Shl64, 3774 mkU64(0xffffffffffffffffULL), 3775 unop(Iop_32to8, 3776 binop(Iop_Add32, 3777 mkexpr(t8), 3778 mkU32(1))))), 3779 unop(Iop_Not64, 3780 binop(Iop_Shr64, 3781 mkU64(0xffffffffffffffffULL), 3782 unop(Iop_32to8, 3783 binop(Iop_Add32, 3784 mkexpr(t8), 3785 mkU32(1))))))); 3786 3787 assign(t7, IRExpr_ITE(mkexpr(t3), 3788 unop(Iop_64to32, 3789 binop(Iop_And64, 3790 mkexpr(t5), 3791 mkexpr(t6))), 3792 binop(Iop_Shr32, 3793 unop(Iop_64HIto32, 3794 binop(Iop_And64, 3795 mkexpr(t5), 3796 mkexpr(t6))), 3797 unop(Iop_32to8, 3798 binop(Iop_Sub32, 3799 mkU32(31), 3800 mkexpr(t8)))))); 3801 3802 putIReg(rt, mkexpr(t7)); 3803 break; 3804 } 3805 case 0x4: { /* EXTR_R.W */ 3806 DIP("extr_r.w r%u, ac%u, %u", rt, ac, rs); 3807 vassert(!mode64); 3808 t0 = newTemp(Ity_I64); 3809 t1 = newTemp(Ity_I64); 3810 t2 = newTemp(Ity_I32); 3811 t3 = newTemp(Ity_I1); 3812 t4 = newTemp(Ity_I1); 3813 t5 = newTemp(Ity_I1); 3814 t6 = newTemp(Ity_I1); 3815 t7 = newTemp(Ity_I32); 3816 t8 = newTemp(Ity_I64); 3817 t9 = newTemp(Ity_I64); 3818 t10 = newTemp(Ity_I1); 3819 t11 = newTemp(Ity_I1); 3820 t12 = newTemp(Ity_I1); 3821 t13 = newTemp(Ity_I1); 3822 t14 = newTemp(Ity_I32); 3823 t15 = newTemp(Ity_I64); 3824 t16 = newTemp(Ity_I1); 3825 3826 assign(t0, getAcc(ac)); 3827 assign(t16, binop(Iop_CmpEQ32, 3828 mkU32(rs), 3829 mkU32(0))); 3830 assign(t1, IRExpr_ITE(mkexpr(t16), 3831 mkexpr(t0), 3832 binop(Iop_Sar64, 3833 mkexpr(t0), 3834 mkU8(rs)))); 3835 /* If the last discarded bit is 1, there would be carry 3836 when rounding, otherwise there wouldn't. We use that 3837 fact and just add the value of the last discarded bit 3838 to the least significant bit of the shifted value 3839 from acc. */ 3840 assign(t15, binop(Iop_Shr64, 3841 mkexpr(t0), 3842 unop(Iop_32to8, 3843 binop(Iop_Sub32, 3844 binop(Iop_And32, 3845 mkU32(rs), 3846 mkU32(0x1f)), 3847 mkU32(1))))); 3848 3849 assign(t8, 3850 IRExpr_ITE(mkexpr(t16), 3851 mkU64(0x0ULL), 3852 binop(Iop_And64, 3853 mkexpr(t15), 3854 mkU64(0x0000000000000001ULL)))); 3855 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 3856 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 3857 3858 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3859 assign(t3, binop(Iop_CmpNE32, 3860 unop(Iop_64HIto32, 3861 mkexpr(t1)), 3862 mkU32(0))); 3863 assign(t4, binop(Iop_CmpNE32, 3864 binop(Iop_And32, 3865 unop(Iop_64to32, 3866 mkexpr(t1)), 3867 mkU32(0x80000000)), 3868 mkU32(0))); 3869 3870 /* Check if bits 63..31 of the result in t1 aren't 3871 0x1ffffffff. */ 3872 assign(t5, binop(Iop_CmpNE32, 3873 unop(Iop_64HIto32, 3874 mkexpr(t1)), 3875 mkU32(0xffffffff))); 3876 assign(t6, binop(Iop_CmpNE32, 3877 binop(Iop_And32, 3878 unop(Iop_64to32, 3879 mkexpr(t1)), 3880 mkU32(0x80000000)), 3881 mkU32(0x80000000))); 3882 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3883 control register. */ 3884 assign(t7, binop(Iop_And32, 3885 binop(Iop_Or32, 3886 unop(Iop_1Sto32, mkexpr(t3)), 3887 unop(Iop_1Sto32, mkexpr(t4))), 3888 binop(Iop_Or32, 3889 unop(Iop_1Sto32, mkexpr(t5)), 3890 unop(Iop_1Sto32, mkexpr(t6))))); 3891 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3892 mkexpr(t7), 3893 mkU32(0)), 3894 binop(Iop_Or32, 3895 getDSPControl(), 3896 mkU32(0x00800000)), 3897 getDSPControl())); 3898 3899 /* Repeat previous steps for the rounded value. */ 3900 assign(t10, binop(Iop_CmpNE32, 3901 unop(Iop_64HIto32, 3902 mkexpr(t9)), 3903 mkU32(0))); 3904 assign(t11, binop(Iop_CmpNE32, 3905 binop(Iop_And32, 3906 unop(Iop_64to32, 3907 mkexpr(t9)), 3908 mkU32(0x80000000)), 3909 mkU32(0))); 3910 3911 assign(t12, binop(Iop_CmpNE32, 3912 unop(Iop_64HIto32, 3913 mkexpr(t9)), 3914 mkU32(0xffffffff))); 3915 assign(t13, binop(Iop_CmpNE32, 3916 binop(Iop_And32, 3917 unop(Iop_64to32, 3918 mkexpr(t9)), 3919 mkU32(0x80000000)), 3920 mkU32(0x80000000))); 3921 3922 assign(t14, binop(Iop_And32, 3923 binop(Iop_Or32, 3924 unop(Iop_1Sto32, mkexpr(t10)), 3925 unop(Iop_1Sto32, mkexpr(t11))), 3926 binop(Iop_Or32, 3927 unop(Iop_1Sto32, mkexpr(t12)), 3928 unop(Iop_1Sto32, mkexpr(t13))))); 3929 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3930 mkexpr(t14), 3931 mkU32(0)), 3932 binop(Iop_Or32, 3933 getDSPControl(), 3934 mkU32(0x00800000)), 3935 getDSPControl())); 3936 break; 3937 } 3938 case 0x5: { /* EXTRV_R.W */ 3939 DIP("extrv_r.w r%u, ac%u, r%u", rt, ac, rs); 3940 vassert(!mode64); 3941 t0 = newTemp(Ity_I64); 3942 t1 = newTemp(Ity_I64); 3943 t2 = newTemp(Ity_I32); 3944 t3 = newTemp(Ity_I1); 3945 t4 = newTemp(Ity_I1); 3946 t5 = newTemp(Ity_I1); 3947 t6 = newTemp(Ity_I1); 3948 t7 = newTemp(Ity_I32); 3949 t8 = newTemp(Ity_I64); 3950 t9 = newTemp(Ity_I64); 3951 t10 = newTemp(Ity_I1); 3952 t11 = newTemp(Ity_I1); 3953 t12 = newTemp(Ity_I1); 3954 t13 = newTemp(Ity_I1); 3955 t14 = newTemp(Ity_I32); 3956 t15 = newTemp(Ity_I8); 3957 3958 assign(t15, unop(Iop_32to8, 3959 binop(Iop_And32, 3960 getIReg(rs), 3961 mkU32(0x1f)))); 3962 assign(t0, getAcc(ac)); 3963 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkexpr(t15))); 3964 3965 /* Check if bits 63..31 of the result in t1 aren't 0. */ 3966 assign(t3, binop(Iop_CmpNE32, 3967 unop(Iop_64HIto32, 3968 mkexpr(t1)), 3969 mkU32(0))); 3970 assign(t4, binop(Iop_CmpNE32, 3971 binop(Iop_And32, 3972 unop(Iop_64to32, 3973 mkexpr(t1)), 3974 mkU32(0x80000000)), 3975 mkU32(0))); 3976 /* Check if bits 63..31 of the result in t1 aren't 3977 0x1ffffffff. */ 3978 assign(t5, binop(Iop_CmpNE32, 3979 unop(Iop_64HIto32, 3980 mkexpr(t1)), 3981 mkU32(0xffffffff))); 3982 assign(t6, binop(Iop_CmpNE32, 3983 binop(Iop_And32, 3984 unop(Iop_64to32, 3985 mkexpr(t1)), 3986 mkU32(0x80000000)), 3987 mkU32(0x80000000))); 3988 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 3989 control register. */ 3990 assign(t7, binop(Iop_And32, 3991 binop(Iop_Or32, 3992 unop(Iop_1Sto32, mkexpr(t3)), 3993 unop(Iop_1Sto32, mkexpr(t4))), 3994 binop(Iop_Or32, 3995 unop(Iop_1Sto32, mkexpr(t5)), 3996 unop(Iop_1Sto32, mkexpr(t6))))); 3997 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 3998 mkexpr(t7), 3999 mkU32(0)), 4000 binop(Iop_Or32, 4001 getDSPControl(), 4002 mkU32(0x00800000)), 4003 getDSPControl())); 4004 4005 /* If the last discarded bit is 1, there would be carry 4006 when rounding, otherwise there wouldn't. We use that 4007 fact and just add the value of the last discarded bit 4008 to the least sifgnificant bit of the shifted value 4009 from acc. */ 4010 assign(t8, 4011 IRExpr_ITE(binop(Iop_CmpEQ32, 4012 unop(Iop_8Uto32, 4013 mkexpr(t15)), 4014 mkU32(0)), 4015 mkU64(0x0ULL), 4016 binop(Iop_And64, 4017 binop(Iop_Shr64, 4018 mkexpr(t0), 4019 unop(Iop_32to8, 4020 binop(Iop_Sub32, 4021 unop(Iop_8Uto32, 4022 mkexpr(t15)), 4023 mkU32(1)))), 4024 mkU64(0x1ULL)))); 4025 4026 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4027 /* Put rounded value in destination register. */ 4028 putIReg(rt, unop(Iop_64to32, mkexpr(t9))); 4029 4030 /* Repeat previous steps for the rounded value. */ 4031 assign(t10, binop(Iop_CmpNE32, 4032 unop(Iop_64HIto32, 4033 mkexpr(t9)), 4034 mkU32(0))); 4035 assign(t11, binop(Iop_CmpNE32, 4036 binop(Iop_And32, 4037 unop(Iop_64to32, 4038 mkexpr(t9)), 4039 mkU32(0x80000000)), 4040 mkU32(0))); 4041 4042 assign(t12, binop(Iop_CmpNE32, 4043 unop(Iop_64HIto32, 4044 mkexpr(t9)), 4045 mkU32(0xffffffff))); 4046 assign(t13, binop(Iop_CmpNE32, 4047 binop(Iop_And32, 4048 unop(Iop_64to32, 4049 mkexpr(t9)), 4050 mkU32(0x80000000)), 4051 mkU32(0x80000000))); 4052 4053 assign(t14, binop(Iop_And32, 4054 binop(Iop_Or32, 4055 unop(Iop_1Sto32, mkexpr(t10)), 4056 unop(Iop_1Sto32, mkexpr(t11))), 4057 binop(Iop_Or32, 4058 unop(Iop_1Sto32, mkexpr(t12)), 4059 unop(Iop_1Sto32, mkexpr(t13))))); 4060 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4061 mkexpr(t14), 4062 mkU32(0)), 4063 binop(Iop_Or32, 4064 getDSPControl(), 4065 mkU32(0x00800000)), 4066 getDSPControl())); 4067 break; 4068 } 4069 case 0x6: { /* EXTR_RS.W */ 4070 DIP("extr_rs.w r%u, ac%u, %u", rt, ac, rs); 4071 vassert(!mode64); 4072 t0 = newTemp(Ity_I64); 4073 t1 = newTemp(Ity_I64); 4074 t2 = newTemp(Ity_I32); 4075 t3 = newTemp(Ity_I1); 4076 t4 = newTemp(Ity_I1); 4077 t5 = newTemp(Ity_I1); 4078 t6 = newTemp(Ity_I1); 4079 t7 = newTemp(Ity_I32); 4080 t8 = newTemp(Ity_I64); 4081 t9 = newTemp(Ity_I64); 4082 t10 = newTemp(Ity_I1); 4083 t11 = newTemp(Ity_I1); 4084 t12 = newTemp(Ity_I1); 4085 t13 = newTemp(Ity_I1); 4086 t14 = newTemp(Ity_I32); 4087 t16 = newTemp(Ity_I32); 4088 4089 assign(t0, getAcc(ac)); 4090 if (0 == rs) { 4091 assign(t1, mkexpr(t0)); 4092 } else { 4093 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4094 } 4095 4096 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4097 assign(t3, binop(Iop_CmpNE32, 4098 unop(Iop_64HIto32, 4099 mkexpr(t1)), 4100 mkU32(0))); 4101 assign(t4, binop(Iop_CmpNE32, 4102 binop(Iop_And32, 4103 unop(Iop_64to32, 4104 mkexpr(t1)), 4105 mkU32(0x80000000)), 4106 mkU32(0))); 4107 /* Check if bits 63..31 of the result in t1 aren't 4108 0x1ffffffff. */ 4109 assign(t5, binop(Iop_CmpNE32, 4110 unop(Iop_64HIto32, 4111 mkexpr(t1)), 4112 mkU32(0xffffffff))); 4113 assign(t6, binop(Iop_CmpNE32, 4114 binop(Iop_And32, 4115 unop(Iop_64to32, 4116 mkexpr(t1)), 4117 mkU32(0x80000000)), 4118 mkU32(0x80000000))); 4119 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4120 control register. */ 4121 assign(t7, binop(Iop_And32, 4122 binop(Iop_Or32, 4123 unop(Iop_1Sto32, mkexpr(t3)), 4124 unop(Iop_1Sto32, mkexpr(t4))), 4125 binop(Iop_Or32, 4126 unop(Iop_1Sto32, mkexpr(t5)), 4127 unop(Iop_1Sto32, mkexpr(t6))))); 4128 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4129 mkexpr(t7), 4130 mkU32(0)), 4131 binop(Iop_Or32, 4132 getDSPControl(), 4133 mkU32(0x00800000)), 4134 getDSPControl())); 4135 4136 /* If the last discarded bit is 1, there would be carry 4137 when rounding, otherwise there wouldn't. We use that 4138 fact and just add the value of the last discarded bit 4139 to the least sifgnificant bit of the shifted value 4140 from acc. */ 4141 if (0 == rs) { 4142 assign(t8, mkU64(0x0ULL)); 4143 } else { 4144 assign(t8, binop(Iop_And64, 4145 binop(Iop_Shr64, 4146 mkexpr(t0), 4147 mkU8(rs-1)), 4148 mkU64(0x1ULL))); 4149 } 4150 4151 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4152 4153 /* Repeat previous steps for the rounded value. */ 4154 assign(t10, binop(Iop_CmpNE32, 4155 unop(Iop_64HIto32, 4156 mkexpr(t9)), 4157 mkU32(0))); 4158 assign(t11, binop(Iop_CmpNE32, 4159 binop(Iop_And32, 4160 unop(Iop_64to32, 4161 mkexpr(t9)), 4162 mkU32(0x80000000)), 4163 mkU32(0))); 4164 4165 assign(t12, binop(Iop_CmpNE32, 4166 unop(Iop_64HIto32, 4167 mkexpr(t9)), 4168 mkU32(0xffffffff))); 4169 assign(t13, binop(Iop_CmpNE32, 4170 binop(Iop_And32, 4171 unop(Iop_64to32, 4172 mkexpr(t9)), 4173 mkU32(0x80000000)), 4174 mkU32(0x80000000))); 4175 4176 assign(t14, binop(Iop_And32, 4177 binop(Iop_Or32, 4178 unop(Iop_1Sto32, mkexpr(t10)), 4179 unop(Iop_1Sto32, mkexpr(t11))), 4180 binop(Iop_Or32, 4181 unop(Iop_1Sto32, mkexpr(t12)), 4182 unop(Iop_1Sto32, mkexpr(t13))))); 4183 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4184 mkexpr(t14), 4185 mkU32(0)), 4186 binop(Iop_Or32, 4187 getDSPControl(), 4188 mkU32(0x00800000)), 4189 getDSPControl())); 4190 4191 assign(t16, binop(Iop_And32, 4192 unop(Iop_64HIto32, 4193 mkexpr(t9)), 4194 mkU32(0x80000000))); 4195 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4196 mkexpr(t14), 4197 mkU32(0)), 4198 IRExpr_ITE(binop(Iop_CmpEQ32, 4199 mkexpr(t16), 4200 mkU32(0)), 4201 mkU32(0x7fffffff), 4202 mkU32(0x80000000)), 4203 unop(Iop_64to32, mkexpr(t9)))); 4204 break; 4205 } 4206 case 0x7: { /* EXTRV_RS.W */ 4207 DIP("extrv_rs.w r%u, ac%u, r%u", rt, ac, rs); 4208 vassert(!mode64); 4209 t0 = newTemp(Ity_I64); 4210 t1 = newTemp(Ity_I64); 4211 t2 = newTemp(Ity_I32); 4212 t3 = newTemp(Ity_I1); 4213 t4 = newTemp(Ity_I1); 4214 t5 = newTemp(Ity_I1); 4215 t6 = newTemp(Ity_I1); 4216 t7 = newTemp(Ity_I32); 4217 t8 = newTemp(Ity_I64); 4218 t9 = newTemp(Ity_I64); 4219 t10 = newTemp(Ity_I1); 4220 t11 = newTemp(Ity_I1); 4221 t12 = newTemp(Ity_I1); 4222 t13 = newTemp(Ity_I1); 4223 t14 = newTemp(Ity_I32); 4224 t15 = newTemp(Ity_I32); 4225 t16 = newTemp(Ity_I32); 4226 t17 = newTemp(Ity_I1); 4227 4228 assign(t15, binop(Iop_And32, 4229 getIReg(rs), 4230 mkU32(0x1f))); 4231 assign(t17, binop(Iop_CmpEQ32, 4232 mkexpr(t15), 4233 mkU32(0))); 4234 assign(t0, getAcc(ac)); 4235 assign(t1, IRExpr_ITE(mkexpr(t17), 4236 mkexpr(t0), 4237 binop(Iop_Sar64, 4238 mkexpr(t0), 4239 unop(Iop_32to8, 4240 mkexpr(t15))))); 4241 4242 /* Check if bits 63..31 of the result in t1 aren't 0. */ 4243 assign(t3, binop(Iop_CmpNE32, 4244 unop(Iop_64HIto32, 4245 mkexpr(t1)), 4246 mkU32(0))); 4247 assign(t4, binop(Iop_CmpNE32, 4248 binop(Iop_And32, 4249 unop(Iop_64to32, 4250 mkexpr(t1)), 4251 mkU32(0x80000000)), 4252 mkU32(0))); 4253 /* Check if bits 63..31 of the result in t1 aren't 4254 0x1ffffffff. */ 4255 assign(t5, binop(Iop_CmpNE32, 4256 unop(Iop_64HIto32, 4257 mkexpr(t1)), 4258 mkU32(0xffffffff))); 4259 assign(t6, binop(Iop_CmpNE32, 4260 binop(Iop_And32, 4261 unop(Iop_64to32, 4262 mkexpr(t1)), 4263 mkU32(0x80000000)), 4264 mkU32(0x80000000))); 4265 /* If bits 63..31 aren't 0 nor 0x1ffffffff, set DSP 4266 control register. */ 4267 assign(t7, binop(Iop_And32, 4268 binop(Iop_Or32, 4269 unop(Iop_1Sto32, mkexpr(t3)), 4270 unop(Iop_1Sto32, mkexpr(t4))), 4271 binop(Iop_Or32, 4272 unop(Iop_1Sto32, mkexpr(t5)), 4273 unop(Iop_1Sto32, mkexpr(t6))))); 4274 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4275 mkexpr(t7), 4276 mkU32(0)), 4277 binop(Iop_Or32, 4278 getDSPControl(), 4279 mkU32(0x00800000)), 4280 getDSPControl())); 4281 4282 /* If the last discarded bit is 1, there would be carry 4283 when rounding, otherwise there wouldn't. We use that 4284 fact and just add the value of the last discarded bit 4285 to the least sifgnificant bit of the shifted value 4286 from acc. */ 4287 assign(t8, 4288 IRExpr_ITE(mkexpr(t17), 4289 mkU64(0x0ULL), 4290 binop(Iop_And64, 4291 binop(Iop_Shr64, 4292 mkexpr(t0), 4293 unop(Iop_32to8, 4294 binop(Iop_Sub32, 4295 mkexpr(t15), 4296 mkU32(1)))), 4297 mkU64(0x1ULL)))); 4298 4299 assign(t9, binop(Iop_Add64, mkexpr(t1), mkexpr(t8))); 4300 4301 /* Repeat previous steps for the rounded value. */ 4302 assign(t10, binop(Iop_CmpNE32, 4303 unop(Iop_64HIto32, 4304 mkexpr(t9)), 4305 mkU32(0))); 4306 assign(t11, binop(Iop_CmpNE32, 4307 binop(Iop_And32, 4308 unop(Iop_64to32, 4309 mkexpr(t9)), 4310 mkU32(0x80000000)), 4311 mkU32(0))); 4312 4313 assign(t12, binop(Iop_CmpNE32, 4314 unop(Iop_64HIto32, 4315 mkexpr(t9)), 4316 mkU32(0xffffffff))); 4317 assign(t13, binop(Iop_CmpNE32, 4318 binop(Iop_And32, 4319 unop(Iop_64to32, 4320 mkexpr(t9)), 4321 mkU32(0x80000000)), 4322 mkU32(0x80000000))); 4323 4324 assign(t14, binop(Iop_And32, 4325 binop(Iop_Or32, 4326 unop(Iop_1Sto32, mkexpr(t10)), 4327 unop(Iop_1Sto32, mkexpr(t11))), 4328 binop(Iop_Or32, 4329 unop(Iop_1Sto32, mkexpr(t12)), 4330 unop(Iop_1Sto32, mkexpr(t13))))); 4331 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4332 mkexpr(t14), 4333 mkU32(0)), 4334 binop(Iop_Or32, 4335 getDSPControl(), 4336 mkU32(0x00800000)), 4337 getDSPControl())); 4338 4339 assign(t16, binop(Iop_And32, 4340 unop(Iop_64HIto32, 4341 mkexpr(t9)), 4342 mkU32(0x80000000))); 4343 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4344 mkexpr(t14), 4345 mkU32(0)), 4346 IRExpr_ITE(binop(Iop_CmpEQ32, 4347 mkexpr(t16), 4348 mkU32(0)), 4349 mkU32(0x7fffffff), 4350 mkU32(0x80000000)), 4351 unop(Iop_64to32, mkexpr(t9)))); 4352 break; 4353 } 4354 case 0xA: { /* EXTPDP */ 4355 DIP("extpdp r%u, ac%u, %u", rt, ac, rs); 4356 vassert(!mode64); 4357 t0 = newTemp(Ity_I64); 4358 t1 = newTemp(Ity_I32); 4359 t2 = newTemp(Ity_I1); 4360 t3 = newTemp(Ity_I1); 4361 t4 = newTemp(Ity_I8); 4362 t5 = newTemp(Ity_I64); 4363 t6 = newTemp(Ity_I64); 4364 t7 = newTemp(Ity_I32); 4365 t8 = newTemp(Ity_I32); 4366 4367 assign(t0, getAcc(ac)); 4368 /* Extract pos field of DSPControl register. */ 4369 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4370 4371 /* Check if (pos - size) >= 0 [size <= pos] 4372 if (pos < size) 4373 put 1 to EFI field of DSPControl register 4374 else 4375 extract bits from acc and put 0 to EFI field of 4376 DSPCtrl */ 4377 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkU32(rs))); 4378 4379 assign(t8, binop(Iop_Or32, 4380 binop(Iop_And32, 4381 getDSPControl(), 4382 mkU32(0xffffbfc0)), 4383 binop(Iop_And32, 4384 binop(Iop_Sub32, 4385 binop(Iop_And32, 4386 getDSPControl(), 4387 mkU32(0x3f)), 4388 mkU32(rs+1)), 4389 mkU32(0x3f)))); 4390 putDSPControl(IRExpr_ITE(mkexpr(t2), 4391 binop(Iop_Or32, 4392 binop(Iop_And32, 4393 getDSPControl(), 4394 mkU32(0xffffbfff)), 4395 mkU32(0x4000)), 4396 mkexpr(t8))); 4397 4398 /* If pos <= 31, shift right the value from the acc 4399 (pos-size) times and take (size+1) bits from the least 4400 significant positions. Otherwise, shift left the value 4401 (63-pos) times, take (size+1) bits from the most 4402 significant positions and shift right (31-size) times. 4403 */ 4404 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4405 4406 assign(t4, 4407 IRExpr_ITE(mkexpr(t3), 4408 unop(Iop_32to8, 4409 binop(Iop_Sub32, 4410 mkexpr(t1), mkU32(rs))), 4411 unop(Iop_32to8, 4412 binop(Iop_Sub32, 4413 mkU32(63), mkexpr(t1))))); 4414 4415 assign(t5, IRExpr_ITE(mkexpr(t3), 4416 binop(Iop_Shr64, 4417 mkexpr(t0), mkexpr(t4)), 4418 binop(Iop_Shl64, 4419 mkexpr(t0), mkexpr(t4)))); 4420 4421 /* t6 holds a mask for bit extraction. */ 4422 assign(t6, 4423 IRExpr_ITE(mkexpr(t3), 4424 unop(Iop_Not64, 4425 binop(Iop_Shl64, 4426 mkU64(0xffffffffffffffffULL), 4427 mkU8(rs+1))), 4428 unop(Iop_Not64, 4429 binop(Iop_Shr64, 4430 mkU64(0xffffffffffffffffULL), 4431 mkU8(rs+1))))); 4432 4433 assign(t7, IRExpr_ITE(mkexpr(t3), 4434 unop(Iop_64to32, 4435 binop(Iop_And64, 4436 mkexpr(t5), 4437 mkexpr(t6))), 4438 binop(Iop_Shr32, 4439 unop(Iop_64HIto32, 4440 binop(Iop_And64, 4441 mkexpr(t5), 4442 mkexpr(t6))), 4443 mkU8(31-rs)))); 4444 4445 putIReg(rt, mkexpr(t7)); 4446 break; 4447 } 4448 case 0xB: { /* EXTPDPV */ 4449 DIP("extpdpv r%u, ac%u, r%u", rt, ac, rs); 4450 vassert(!mode64); 4451 t0 = newTemp(Ity_I64); 4452 t1 = newTemp(Ity_I32); 4453 t2 = newTemp(Ity_I1); 4454 t3 = newTemp(Ity_I1); 4455 t4 = newTemp(Ity_I8); 4456 t5 = newTemp(Ity_I64); 4457 t6 = newTemp(Ity_I64); 4458 t7 = newTemp(Ity_I32); 4459 t8 = newTemp(Ity_I32); 4460 t9 = newTemp(Ity_I32); 4461 4462 assign(t8, binop(Iop_And32, getIReg(rs), mkU32(0x1f))); 4463 assign(t0, getAcc(ac)); 4464 /* Extract pos field of DSPControl register. */ 4465 assign(t1, binop(Iop_And32, getDSPControl(), mkU32(0x3f))); 4466 4467 /* Check if (pos - size) >= 0 [size <= pos] 4468 if (pos < size) 4469 put 1 to EFI field of DSPControl register 4470 else 4471 extract bits from acc and put 0 to EFI field of 4472 DSPCtrl */ 4473 assign(t2, binop(Iop_CmpLT32U, mkexpr(t1), mkexpr(t8))); 4474 4475 assign(t9, binop(Iop_Or32, 4476 binop(Iop_And32, 4477 getDSPControl(), 4478 mkU32(0xffffbfc0)), 4479 binop(Iop_And32, 4480 binop(Iop_Sub32, 4481 binop(Iop_And32, 4482 getDSPControl(), 4483 mkU32(0x3f)), 4484 binop(Iop_Add32, 4485 mkexpr(t8), 4486 mkU32(0x1))), 4487 mkU32(0x3f)))); 4488 putDSPControl(IRExpr_ITE(mkexpr(t2), 4489 binop(Iop_Or32, 4490 binop(Iop_And32, 4491 getDSPControl(), 4492 mkU32(0xffffbfff)), 4493 mkU32(0x4000)), 4494 mkexpr(t9))); 4495 4496 /* If pos <= 31, shift right the value from the acc 4497 (pos-size) times and take (size+1) bits from the least 4498 significant positions. Otherwise, shift left the value 4499 (63-pos) times, take (size+1) bits from the most 4500 significant positions and shift right (31-size) times. 4501 */ 4502 assign(t3, binop(Iop_CmpLE32U, mkexpr(t1), mkU32(31))); 4503 4504 assign(t4, 4505 IRExpr_ITE(mkexpr(t3), 4506 unop(Iop_32to8, 4507 binop(Iop_Sub32, 4508 mkexpr(t1), mkexpr(t8))), 4509 unop(Iop_32to8, 4510 binop(Iop_Sub32, 4511 mkU32(63), mkexpr(t1))))); 4512 4513 assign(t5, IRExpr_ITE(mkexpr(t3), 4514 binop(Iop_Shr64, 4515 mkexpr(t0), mkexpr(t4)), 4516 binop(Iop_Shl64, 4517 mkexpr(t0), mkexpr(t4)))); 4518 4519 /* t6 holds a mask for bit extraction. */ 4520 assign(t6, 4521 IRExpr_ITE(mkexpr(t3), 4522 unop(Iop_Not64, 4523 binop(Iop_Shl64, 4524 mkU64(0xffffffffffffffffULL), 4525 unop(Iop_32to8, 4526 binop(Iop_Add32, 4527 mkexpr(t8), 4528 mkU32(1))))), 4529 unop(Iop_Not64, 4530 binop(Iop_Shr64, 4531 mkU64(0xffffffffffffffffULL), 4532 unop(Iop_32to8, 4533 binop(Iop_Add32, 4534 mkexpr(t8), 4535 mkU32(1))))))); 4536 4537 assign(t7, IRExpr_ITE(mkexpr(t3), 4538 unop(Iop_64to32, 4539 binop(Iop_And64, 4540 mkexpr(t5), 4541 mkexpr(t6))), 4542 binop(Iop_Shr32, 4543 unop(Iop_64HIto32, 4544 binop(Iop_And64, 4545 mkexpr(t5), 4546 mkexpr(t6))), 4547 unop(Iop_32to8, 4548 binop(Iop_Sub32, 4549 mkU32(31), 4550 mkexpr(t8)))))); 4551 4552 putIReg(rt, mkexpr(t7)); 4553 break; 4554 } 4555 case 0xE: { /* EXTR_S.H */ 4556 DIP("extr_s.h r%u, ac%u, %u", rt, ac, rs); 4557 vassert(!mode64); 4558 t0 = newTemp(Ity_I64); 4559 t1 = newTemp(Ity_I64); 4560 t2 = newTemp(Ity_I32); 4561 t3 = newTemp(Ity_I64); 4562 t4 = newTemp(Ity_I32); 4563 t5 = newTemp(Ity_I32); 4564 t6 = newTemp(Ity_I64); 4565 t7 = newTemp(Ity_I32); 4566 t9 = newTemp(Ity_I32); 4567 4568 assign(t0, getAcc(ac)); 4569 4570 assign(t1, binop(Iop_Sar64, mkexpr(t0), mkU8(rs))); 4571 4572 assign(t2, binop(Iop_Or32, 4573 getDSPControl(), mkU32(0x00800000))); 4574 4575 assign(t9, binop(Iop_And32, 4576 unop(Iop_64to32, 4577 mkexpr(t1)), 4578 mkU32(0x80000000))); 4579 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4580 mkexpr(t9), 4581 binop(Iop_And32, 4582 unop(Iop_64HIto32, 4583 mkexpr(t0)), 4584 mkU32(0x80000000))), 4585 mkexpr(t2), 4586 getDSPControl())); 4587 4588 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4589 1. subtract 0x7fff from t1 4590 2. if the resulting number is positive (sign bit = 0) 4591 and any of the other bits is 1, the value is > 0. */ 4592 assign(t3, binop(Iop_Sub64, 4593 mkexpr(t1), 4594 mkU64(0x0000000000007fffULL))); 4595 assign(t4, binop(Iop_And32, 4596 binop(Iop_Or32, 4597 unop(Iop_1Sto32, 4598 binop(Iop_CmpNE32, 4599 mkU32(0), 4600 binop(Iop_And32, 4601 unop(Iop_64HIto32, 4602 mkexpr(t3)), 4603 mkU32(0x7fffffff)))), 4604 unop(Iop_1Sto32, 4605 binop(Iop_CmpNE32, 4606 mkU32(0), 4607 unop(Iop_64to32, 4608 mkexpr(t3))))), 4609 unop(Iop_1Sto32, 4610 binop(Iop_CmpEQ32, 4611 binop(Iop_And32, 4612 unop(Iop_64HIto32, 4613 mkexpr(t3)), 4614 mkU32(0x80000000)), 4615 mkU32(0))))); 4616 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4617 mkU32(0), 4618 mkexpr(t4)), 4619 binop(Iop_Or32, 4620 getDSPControl(), 4621 mkU32(0x00800000)), 4622 getDSPControl())); 4623 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4624 1. subtract t1 from 0xffffffffffff8000 4625 2. if the resulting number is positive (sign bit = 0) 4626 and any of the other bits is 1, the value is > 0 */ 4627 assign(t6, binop(Iop_Sub64, 4628 mkU64(0xffffffffffff8000ULL), 4629 mkexpr(t1))); 4630 assign(t7, binop(Iop_And32, 4631 binop(Iop_Or32, 4632 unop(Iop_1Sto32, 4633 binop(Iop_CmpNE32, 4634 mkU32(0), 4635 binop(Iop_And32, 4636 unop(Iop_64HIto32, 4637 mkexpr(t6)), 4638 mkU32(0x7fffffff)))), 4639 unop(Iop_1Sto32, 4640 binop(Iop_CmpNE32, 4641 mkU32(0), 4642 unop(Iop_64to32, 4643 mkexpr(t6))))), 4644 unop(Iop_1Sto32, 4645 binop(Iop_CmpEQ32, 4646 binop(Iop_And32, 4647 unop(Iop_64HIto32, 4648 mkexpr(t6)), 4649 mkU32(0x80000000)), 4650 mkU32(0))))); 4651 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4652 mkU32(0), 4653 mkexpr(t7)), 4654 binop(Iop_Or32, 4655 getDSPControl(), 4656 mkU32(0x00800000)), 4657 getDSPControl())); 4658 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4659 mkU32(0), 4660 mkexpr(t4)), 4661 mkU32(0x00007fff), 4662 IRExpr_ITE(binop(Iop_CmpNE32, 4663 mkU32(0), 4664 mkexpr(t7)), 4665 mkU32(0xffff8000), 4666 unop(Iop_64to32, 4667 mkexpr(t1))))); 4668 break; 4669 } 4670 case 0xF: { /* EXTRV_S.H */ 4671 DIP("extrv_s.h r%u, ac%u, %u", rt, ac, rs); 4672 vassert(!mode64); 4673 t0 = newTemp(Ity_I64); 4674 t1 = newTemp(Ity_I64); 4675 t2 = newTemp(Ity_I32); 4676 t3 = newTemp(Ity_I64); 4677 t4 = newTemp(Ity_I32); 4678 t5 = newTemp(Ity_I32); 4679 t6 = newTemp(Ity_I64); 4680 t7 = newTemp(Ity_I32); 4681 t9 = newTemp(Ity_I32); 4682 4683 assign(t0, getAcc(ac)); 4684 4685 assign(t1, binop(Iop_Sar64, 4686 mkexpr(t0), 4687 unop(Iop_32to8, 4688 binop(Iop_And32, 4689 getIReg(rs), 4690 mkU32(0x1f))))); 4691 4692 assign(t2, binop(Iop_Or32, 4693 getDSPControl(), mkU32(0x00800000))); 4694 4695 assign(t9, binop(Iop_And32, 4696 unop(Iop_64to32, 4697 mkexpr(t1)), 4698 mkU32(0x80000000))); 4699 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4700 mkexpr(t9), 4701 binop(Iop_And32, 4702 unop(Iop_64HIto32, 4703 mkexpr(t0)), 4704 mkU32(0x80000000))), 4705 mkexpr(t2), 4706 getDSPControl())); 4707 4708 /* Check if t1 > 0x7fff ((t1 - 0x7fff) > 0) 4709 1. subtract 0x7fff from t1 4710 2. if the resulting number is positive (sign bit = 0) 4711 and any of the other bits is 1, the value is > 0. */ 4712 assign(t3, binop(Iop_Sub64, 4713 mkexpr(t1), 4714 mkU64(0x0000000000007fffULL))); 4715 assign(t4, binop(Iop_And32, 4716 binop(Iop_Or32, 4717 unop(Iop_1Sto32, 4718 binop(Iop_CmpNE32, 4719 mkU32(0), 4720 binop(Iop_And32, 4721 unop(Iop_64HIto32, 4722 mkexpr(t3)), 4723 mkU32(0x7fffffff)))), 4724 unop(Iop_1Sto32, 4725 binop(Iop_CmpNE32, 4726 mkU32(0), 4727 unop(Iop_64to32, 4728 mkexpr(t3))))), 4729 unop(Iop_1Sto32, 4730 binop(Iop_CmpEQ32, 4731 binop(Iop_And32, 4732 unop(Iop_64HIto32, 4733 mkexpr(t3)), 4734 mkU32(0x80000000)), 4735 mkU32(0))))); 4736 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4737 mkU32(0), 4738 mkexpr(t4)), 4739 binop(Iop_Or32, 4740 getDSPControl(), 4741 mkU32(0x00800000)), 4742 getDSPControl())); 4743 /* Check if t1<0xffffffffffff8000 (0xffffffffffff8000-t1)>0 4744 1. subtract t1 from 0xffffffffffff8000 4745 2. if the resulting number is positive (sign bit = 0) 4746 and any of the other bits is 1, the value is > 0 */ 4747 assign(t6, binop(Iop_Sub64, 4748 mkU64(0xffffffffffff8000ULL), 4749 mkexpr(t1))); 4750 assign(t7, binop(Iop_And32, 4751 binop(Iop_Or32, 4752 unop(Iop_1Sto32, 4753 binop(Iop_CmpNE32, 4754 mkU32(0), 4755 binop(Iop_And32, 4756 unop(Iop_64HIto32, 4757 mkexpr(t6)), 4758 mkU32(0x7fffffff)))), 4759 unop(Iop_1Sto32, 4760 binop(Iop_CmpNE32, 4761 mkU32(0), 4762 unop(Iop_64to32, 4763 mkexpr(t6))))), 4764 unop(Iop_1Sto32, 4765 binop(Iop_CmpEQ32, 4766 binop(Iop_And32, 4767 unop(Iop_64HIto32, 4768 mkexpr(t6)), 4769 mkU32(0x80000000)), 4770 mkU32(0))))); 4771 putDSPControl(IRExpr_ITE(binop(Iop_CmpNE32, 4772 mkU32(0), 4773 mkexpr(t7)), 4774 binop(Iop_Or32, 4775 getDSPControl(), 4776 mkU32(0x00800000)), 4777 getDSPControl())); 4778 putIReg(rt, IRExpr_ITE(binop(Iop_CmpNE32, 4779 mkU32(0), 4780 mkexpr(t4)), 4781 mkU32(0x00007fff), 4782 IRExpr_ITE(binop(Iop_CmpNE32, 4783 mkU32(0), 4784 mkexpr(t7)), 4785 mkU32(0xffff8000), 4786 unop(Iop_64to32, 4787 mkexpr(t1))))); 4788 break; 4789 } 4790 case 0x12: { /* RDDSP*/ 4791 DIP("rddsp r%u, mask 0x%x", rd, rddsp_mask); 4792 vassert(!mode64); 4793 4794 putIReg(rd, mkU32(0x0)); 4795 4796 if ((rddsp_mask & 0x1) == 0x1) { 4797 /* Read pos field (bits 5-0) of DSPControl register. */ 4798 putIReg(rd, binop(Iop_Or32, 4799 getIReg(rd), 4800 binop(Iop_And32, 4801 getDSPControl(), 4802 mkU32(0x0000003F)))); 4803 } 4804 4805 if ((rddsp_mask & 0x2) == 0x2) { 4806 /* Read scount field (bits 12-7) of DSPControl 4807 register. */ 4808 putIReg(rd, binop(Iop_Or32, 4809 getIReg(rd), 4810 binop(Iop_And32, 4811 getDSPControl(), 4812 mkU32(0x00001F80)))); 4813 } 4814 4815 if ((rddsp_mask & 0x4) == 0x4) { 4816 /* Read C field (bit 13) of DSPControl register. */ 4817 putIReg(rd, binop(Iop_Or32, 4818 getIReg(rd), 4819 binop(Iop_And32, 4820 getDSPControl(), 4821 mkU32(0x00002000)))); 4822 } 4823 4824 if ((rddsp_mask & 0x8) == 0x8) { 4825 /* Read outflag field (bit s 23-16) of DSPControl 4826 register. */ 4827 putIReg(rd, binop(Iop_Or32, 4828 getIReg(rd), 4829 binop(Iop_And32, 4830 getDSPControl(), 4831 mkU32(0x00FF0000)))); 4832 } 4833 4834 if ((rddsp_mask & 0x10) == 0x10) { 4835 /* Read ccond field (bits 31-24) of DSPControl 4836 register. */ 4837 putIReg(rd, binop(Iop_Or32, 4838 getIReg(rd), 4839 binop(Iop_And32, 4840 getDSPControl(), 4841 mkU32(0xFF000000)))); 4842 } 4843 4844 if ((rddsp_mask & 0x20) == 0x20) { 4845 /* Read EFI field (bit 14) of DSPControl register. */ 4846 putIReg(rd, binop(Iop_Or32, 4847 getIReg(rd), 4848 binop(Iop_And32, 4849 getDSPControl(), 4850 mkU32(0x00004000)))); 4851 } 4852 4853 if ((rddsp_mask & 0x3f) == 0x3f) { 4854 /* Read all fields of DSPControl register. */ 4855 putIReg(rd, getDSPControl()); 4856 } 4857 break; 4858 } 4859 case 0x13: { /* WRDSP */ 4860 DIP("wrdsp r%u, mask 0x%x", rs, wrdsp_mask); 4861