/*--------------------------------------------------------------------*/ /*--- begin guest_tilegx_toIR.c ---*/ /*--------------------------------------------------------------------*/ /* This file is part of Valgrind, a dynamic binary instrumentation framework. Copyright (C) 2010-2015 Tilera Corp. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. The GNU General Public License is contained in the file COPYING. */ /* Contributed by Zhi-Gang Liu */ /* Translates TILEGX code to IR. */ #include "libvex_basictypes.h" #include "libvex_ir.h" #include "libvex.h" #include "libvex_guest_tilegx.h" #include "main_util.h" #include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_tilegx_defs.h" #include "tilegx_disasm.h" /*------------------------------------------------------------*/ /*--- Globals ---*/ /*------------------------------------------------------------*/ /* These are set at the start of the translation of a instruction, so that we don't have to pass them around endlessly. CONST means does not change during translation of the instruction. */ /* CONST: is the host bigendian? This has to do with float vs double register accesses on VFP, but it's complex and not properly thought out. */ static VexEndness host_endness; /* Pointer to the guest code area. */ static UChar *guest_code; /* The guest address corresponding to guest_code[0]. */ static Addr64 guest_PC_bbstart; /* CONST: The guest address for the instruction currently being translated. */ static Addr64 guest_PC_curr_instr; /* MOD: The IRSB* into which we're generating code. */ static IRSB *irsb; /*------------------------------------------------------------*/ /*--- Debugging output ---*/ /*------------------------------------------------------------*/ #define DIP(format, args...) \ if (vex_traceflags & VEX_TRACE_FE) \ vex_printf(format, ## args) /*------------------------------------------------------------*/ /*--- Helper bits and pieces for deconstructing the ---*/ /*--- tilegx insn stream. ---*/ /*------------------------------------------------------------*/ static Int integerGuestRegOffset ( UInt iregNo ) { return 8 * (iregNo); } /*------------------------------------------------------------*/ /*--- Field helpers ---*/ /*------------------------------------------------------------*/ /*------------------------------------------------------------*/ /*--- Helper bits and pieces for creating IR fragments. ---*/ /*------------------------------------------------------------*/ static IRExpr *mkU8 ( UInt i ) { return IRExpr_Const(IRConst_U8((UChar) i)); } /* Create an expression node for a 32-bit integer constant */ static IRExpr *mkU32 ( UInt i ) { return IRExpr_Const(IRConst_U32(i)); } /* Create an expression node for a 64-bit integer constant */ static IRExpr *mkU64 ( ULong i ) { return IRExpr_Const(IRConst_U64(i)); } static IRExpr *mkexpr ( IRTemp tmp ) { return IRExpr_RdTmp(tmp); } static IRExpr *unop ( IROp op, IRExpr * a ) { return IRExpr_Unop(op, a); } static IRExpr *binop ( IROp op, IRExpr * a1, IRExpr * a2 ) { return IRExpr_Binop(op, a1, a2); } static IRExpr *load ( IRType ty, IRExpr * addr ) { IRExpr *load1 = NULL; load1 = IRExpr_Load(Iend_LE, ty, addr); return load1; } /* Add a statement to the list held by "irsb". */ static void stmt ( IRStmt * st ) { addStmtToIRSB(irsb, st); } #define OFFB_PC offsetof(VexGuestTILEGXState, guest_pc) static void putPC ( IRExpr * e ) { stmt(IRStmt_Put(OFFB_PC, e)); } static void assign ( IRTemp dst, IRExpr * e ) { stmt(IRStmt_WrTmp(dst, e)); } static void store ( IRExpr * addr, IRExpr * data ) { stmt(IRStmt_Store(Iend_LE, addr, data)); } /* Generate a new temporary of the given type. */ static IRTemp newTemp ( IRType ty ) { vassert(isPlausibleIRType(ty)); return newIRTemp(irsb->tyenv, ty); } static ULong extend_s_16to64 ( UInt x ) { return (ULong) ((((Long) x) << 48) >> 48); } static ULong extend_s_8to64 ( UInt x ) { return (ULong) ((((Long) x) << 56) >> 56); } static IRExpr *getIReg ( UInt iregNo ) { IRType ty = Ity_I64; if(!(iregNo < 56 || iregNo == 63 || (iregNo >= 70 && iregNo <= 73))) { vex_printf("iregNo=%u\n", iregNo); vassert(0); } return IRExpr_Get(integerGuestRegOffset(iregNo), ty); } static void putIReg ( UInt archreg, IRExpr * e ) { IRType ty = Ity_I64; if(!(archreg < 56 || archreg == 63 || archreg == 70 || archreg == 72 || archreg == 73)) { vex_printf("archreg=%u\n", archreg); vassert(0); } vassert(typeOfIRExpr(irsb->tyenv, e) == ty); if (archreg != 63) stmt(IRStmt_Put(integerGuestRegOffset(archreg), e)); } /* Narrow 8/16/32 bit int expr to 8/16/32. Clearly only some of these combinations make sense. */ static IRExpr *narrowTo ( IRType dst_ty, IRExpr * e ) { IRType src_ty = typeOfIRExpr(irsb->tyenv, e); if (src_ty == dst_ty) return e; if (src_ty == Ity_I32 && dst_ty == Ity_I16) return unop(Iop_32to16, e); if (src_ty == Ity_I32 && dst_ty == Ity_I8) return unop(Iop_32to8, e); if (src_ty == Ity_I64 && dst_ty == Ity_I8) { return unop(Iop_64to8, e); } if (src_ty == Ity_I64 && dst_ty == Ity_I16) { return unop(Iop_64to16, e); } if (src_ty == Ity_I64 && dst_ty == Ity_I32) { return unop(Iop_64to32, e); } if (vex_traceflags & VEX_TRACE_FE) { vex_printf("\nsrc, dst tys are: "); ppIRType(src_ty); vex_printf(", "); ppIRType(dst_ty); vex_printf("\n"); } vpanic("narrowTo(tilegx)"); return e; } #define signExtend(_e, _n) \ ((_n == 32) ? \ unop(Iop_32Sto64, _e) : \ ((_n == 16) ? \ unop(Iop_16Sto64, _e) : \ (binop(Iop_Sar64, binop(Iop_Shl64, _e, mkU8(63 - (_n))), mkU8(63 - (_n)))))) static IRStmt* dis_branch ( IRExpr* guard, ULong imm ) { IRTemp t0; t0 = newTemp(Ity_I1); assign(t0, guard); return IRStmt_Exit(mkexpr(t0), Ijk_Boring, IRConst_U64(imm), OFFB_PC); } #define MARK_REG_WB(_rd, _td) \ do { \ vassert(rd_wb_index < 6); \ rd_wb_temp[rd_wb_index] = _td; \ rd_wb_reg[rd_wb_index] = _rd; \ rd_wb_index++; \ } while(0) /* Expand/repeat byte _X 8 times to a 64-bit value */ #define V1EXP(_X) \ ({ \ _X = ((((UChar)(_X)) << 8) | ((UChar)(_X))); \ _X = (((_X) << 16) | (_X)); \ (((_X) << 32) | (_X)); \ }) /* Expand/repeat byte _X 4 times to a 64-bit value */ #define V2EXP(_X) \ ({ \ _X = ((((UChar)(_X)) << 16) | ((UChar)(_X))); \ (((_X) << 32) | (_X)); \ }) /*------------------------------------------------------------*/ /*--- Disassemble a single instruction ---*/ /*------------------------------------------------------------*/ /* Disassemble a single instruction bundle into IR. The bundle is located in host memory at guest_instr, and has guest IP of guest_PC_curr_instr, which will have been set before the call here. */ static DisResult disInstr_TILEGX_WRK ( Bool(*resteerOkFn) (void *, Addr), Bool resteerCisOk, void *callback_opaque, Long delta64, const VexArchInfo * archinfo, const VexAbiInfo * abiinfo, Bool sigill_diag ) { struct tilegx_decoded_instruction decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; ULong cins, opcode = -1, rd, ra, rb, imm = 0; ULong opd[4]; ULong opd_src_map, opd_dst_map, opd_imm_map; Int use_dirty_helper; IRTemp t0, t1, t2, t3, t4; IRTemp tb[4]; IRTemp rd_wb_temp[6]; ULong rd_wb_reg[6]; /* Tilegx is a VLIW processor, we have to commit register write after read.*/ Int rd_wb_index; Int n = 0, nr_insn; DisResult dres; /* The running delta */ Long delta = delta64; /* Holds pc at the start of the insn, so that we can print consistent error messages for unimplemented insns. */ //Long delta_start = delta; UChar *code = (UChar *) (guest_code + delta); IRStmt *bstmt = NULL; /* Branch statement. */ IRExpr *next = NULL; /* Next bundle expr. */ ULong jumpkind = Ijk_Boring; ULong steering_pc; /* Set result defaults. */ dres.whatNext = Dis_Continue; dres.len = 0; dres.continueAt = 0; dres.jk_StopHere = Ijk_INVALID; /* Verify the code addr is 8-byte aligned. */ vassert((((Addr)code) & 7) == 0); /* Get the instruction bundle. */ cins = *((ULong *)(Addr) code); /* "Special" instructions. */ /* Spot the 16-byte preamble: ****tilegx**** 0:02b3c7ff91234fff { moveli zero, 4660 ; moveli zero, 22136 } 8:0091a7ff95678fff { moveli zero, 22136 ; moveli zero, 4660 } */ #define CL_W0 0x02b3c7ff91234fffULL #define CL_W1 0x0091a7ff95678fffULL if (*((ULong*)(Addr)(code)) == CL_W0 && *((ULong*)(Addr)(code + 8)) == CL_W1) { /* Got a "Special" instruction preamble. Which one is it? */ if (*((ULong*)(Addr)(code + 16)) == 0x283a69a6d1483000ULL /* or r13, r13, r13 */ ) { /* r0 = client_request ( r12 ) */ DIP("r0 = client_request ( r12 )\n"); putPC(mkU64(guest_PC_curr_instr + 24)); dres.jk_StopHere = Ijk_ClientReq; dres.whatNext = Dis_StopHere; dres.len = 24; goto decode_success; } else if (*((ULong*)(Addr)(code + 16)) == 0x283a71c751483000ULL /* or r14, r14, r14 */ ) { /* r11 = guest_NRADDR */ DIP("r11 = guest_NRADDR\n"); dres.len = 24; putIReg(11, IRExpr_Get(offsetof(VexGuestTILEGXState, guest_NRADDR), Ity_I64)); putPC(mkU64(guest_PC_curr_instr + 8)); goto decode_success; } else if (*((ULong*)(Addr)(code + 16)) == 0x283a79e7d1483000ULL /* or r15, r15, r15 */ ) { /* branch-and-link-to-noredir r12 */ DIP("branch-and-link-to-noredir r12\n"); dres.len = 24; putIReg(55, mkU64(guest_PC_curr_instr + 24)); putPC(getIReg(12)); dres.jk_StopHere = Ijk_NoRedir; dres.whatNext = Dis_StopHere; goto decode_success; } else if (*((ULong*)(Addr)(code + 16)) == 0x283a5965d1483000ULL /* or r11, r11, r11 */ ) { /* vex-inject-ir */ DIP("vex-inject-ir\n"); dres.len = 24; vex_inject_ir(irsb, Iend_LE); stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_CMSTART), mkU64(guest_PC_curr_instr))); stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_CMLEN), mkU64(24))); /* 2 + 1 = 3 bundles. 24 bytes. */ putPC(mkU64(guest_PC_curr_instr + 24)); dres.jk_StopHere = Ijk_InvalICache; dres.whatNext = Dis_StopHere; goto decode_success; } /* We don't expect this. */ vex_printf("%s: unexpect special bundles at %lx\n", __func__, (Addr)guest_PC_curr_instr); delta += 16; goto decode_failure; /*NOTREACHED*/ } /* To decode the given instruction bundle. */ nr_insn = parse_insn_tilegx((tilegx_bundle_bits)cins, (ULong)(Addr)code, decoded); if (vex_traceflags & VEX_TRACE_FE) decode_and_display(&cins, 1, (ULong)(Addr)code); /* Init. rb_wb_index */ rd_wb_index = 0; steering_pc = -1ULL; for (n = 0; n < nr_insn; n++) { opcode = decoded[n].opcode->mnemonic; Int opi; rd = ra = rb = -1; opd[0] = opd[1] = opd[2] = opd[3] = -1; opd_dst_map = 0; opd_src_map = 0; opd_imm_map = 0; for (opi = 0; opi < decoded[n].opcode->num_operands; opi++) { const struct tilegx_operand *op = decoded[n].operands[opi]; opd[opi] = decoded[n].operand_values[opi]; /* Set the operands. rd, ra, rb and imm. */ if (opi < 3) { if (op->is_dest_reg) { if (rd == -1) rd = decoded[n].operand_values[opi]; else if (ra == -1) ra = decoded[n].operand_values[opi]; } else if (op->is_src_reg) { if (ra == -1) { ra = decoded[n].operand_values[opi]; } else if(rb == -1) { rb = decoded[n].operand_values[opi]; } else { vassert(0); } } else { imm = decoded[n].operand_values[opi]; } } /* Build bit maps of used dest, source registers and immediate. */ if (op->is_dest_reg) { opd_dst_map |= 1ULL << opi; if(op->is_src_reg) opd_src_map |= 1ULL << opi; } else if(op->is_src_reg) { opd_src_map |= 1ULL << opi; } else { opd_imm_map |= 1ULL << opi; } } use_dirty_helper = 0; switch (opcode) { case 0: /* "bpt" */ /* "raise" */ /* "bpt" pseudo instruction is an illegal instruction */ opd_imm_map |= (1 << 0); opd[0] = cins; use_dirty_helper = 1; break; case 1: /* "info" */ /* Ignore this instruction. */ break; case 2: /* "infol" */ /* Ignore this instruction. */ break; case 3: /* "ld4s_tls" */ /* Ignore this instruction. */ break; case 4: /* "ld_tls" */ /* Ignore this instruction. */ break; case 5: /* "move" */ t2 = newTemp(Ity_I64); assign(t2, getIReg(ra)); MARK_REG_WB(rd, t2); break; case 6: /* "movei" */ t2 = newTemp(Ity_I64); assign(t2, mkU64(extend_s_8to64(imm))); MARK_REG_WB(rd, t2); break; case 7: /* "moveli" */ t2 = newTemp(Ity_I64); assign(t2, mkU64(extend_s_16to64(imm))); MARK_REG_WB(rd, t2); break; case 8: /* "prefetch" */ /* Ignore. */ break; case 9: /* "prefetch_add_l1" */ /* Ignore. */ break; case 10: /* "prefetch_add_l1_fault" */ /* Ignore. */ break; case 11: /* "prefetch_add_l2" */ /* Ignore. */ break; case 12: /* "prefetch_add_l2_fault" */ /* Ignore. */ break; case 13: /* "prefetch_add_l3" */ /* Ignore. */ break; case 14: /* "prefetch_add_l3_fault" */ /* Ignore. */ break; case 15: /* "prefetch_l1" */ /* Ignore. */ break; case 16: /* "prefetch_l1_fault" */ /* Ignore. */ break; case 17: /* "prefetch_l2" */ /* Ignore. */ break; case 18: /* "prefetch_l2_fault" */ /* Ignore. */ break; case 19: /* "prefetch_l3" */ /* Ignore. */ break; case 20: /* "prefetch_l3_fault" */ /* Ignore. */ break; case 21: /* "raise" */ /* "raise" pseudo instruction is an illegal instruction plusing a "moveli zero, ", so we need save whole bundle in the opd[0], which will be used in the dirty helper. */ opd_imm_map |= (1 << 0); opd[0] = cins; use_dirty_helper = 1; break; case 22: /* "add" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 23: /* "addi" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, getIReg(ra), mkU64(extend_s_8to64(imm)))); MARK_REG_WB(rd, t2); break; case 24: /* "addli" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, getIReg(ra), mkU64(extend_s_16to64(imm)))); MARK_REG_WB(rd, t2); break; case 25: /* "addx" */ t2 = newTemp(Ity_I64); assign(t2, signExtend(binop(Iop_Add32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I32, getIReg(rb))), 32)); MARK_REG_WB(rd, t2); break; case 26: /* "addxi" */ t2 = newTemp(Ity_I64); assign(t2, signExtend(binop(Iop_Add32, narrowTo(Ity_I32, getIReg(ra)), mkU32(imm)), 32)); MARK_REG_WB(rd, t2); break; case 27: /* "addxli" */ t2 = newTemp(Ity_I64); assign(t2, signExtend(binop(Iop_Add32, narrowTo(Ity_I32, getIReg(ra)), mkU32(imm)), 32)); MARK_REG_WB(rd, t2); break; case 28: /* "addxsc" */ use_dirty_helper = 1; break; case 29: /* "and" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_And64, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 30: /* "andi" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_And64, getIReg(ra), mkU64(extend_s_8to64(imm)))); MARK_REG_WB(rd, t2); break; case 31: /* "beqz" */ /* Fall-through */ case 32: /* "beqzt" */ bstmt = dis_branch(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)), imm); break; case 33: /* "bfexts" */ { ULong imm0 = decoded[n].operand_values[3]; ULong mask = ((-1ULL) ^ ((-1ULL << ((imm0 - imm) & 63)) << 1)); t0 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t0, binop(Iop_Xor64, binop(Iop_Sub64, binop(Iop_And64, binop(Iop_Shr64, getIReg(ra), mkU8(imm0)), mkU64(1)), mkU64(1)), mkU64(-1ULL))); assign(t2, binop(Iop_Or64, binop(Iop_And64, binop(Iop_Or64, binop(Iop_Shr64, getIReg(ra), mkU8(imm)), binop(Iop_Shl64, getIReg(ra), mkU8(64 - imm))), mkU64(mask)), binop(Iop_And64, mkexpr(t0), mkU64(~mask)))); MARK_REG_WB(rd, t2); } break; case 34: /* "bfextu" */ { ULong imm0 = decoded[n].operand_values[3]; ULong mask = 0; t2 = newTemp(Ity_I64); mask = ((-1ULL) ^ ((-1ULL << ((imm0 - imm) & 63)) << 1)); assign(t2, binop(Iop_And64, binop(Iop_Or64, binop(Iop_Shr64, getIReg(ra), mkU8(imm)), binop(Iop_Shl64, getIReg(ra), mkU8(64 - imm))), mkU64(mask))); MARK_REG_WB(rd, t2); } break; case 35: /* "bfins" */ { ULong mask; ULong imm0 = decoded[n].operand_values[3]; t0 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); if (imm <= imm0) { mask = ((-1ULL << imm) ^ ((-1ULL << imm0) << 1)); } else { mask = ((-1ULL << imm) | (-1ULL >> (63 - imm0))); } assign(t0, binop(Iop_Or64, binop(Iop_Shl64, getIReg(ra), mkU8(imm)), binop(Iop_Shr64, getIReg(ra), mkU8(64 - imm)))); assign(t2, binop(Iop_Or64, binop(Iop_And64, mkexpr(t0), mkU64(mask)), binop(Iop_And64, getIReg(rd), mkU64(~mask)))); MARK_REG_WB(rd, t2); } break; case 36: /* "bgez" */ /* Fall-through */ case 37: /* "bgezt" */ bstmt = dis_branch(binop(Iop_CmpEQ64, binop(Iop_And64, getIReg(ra), mkU64(0x8000000000000000ULL)), mkU64(0x0)), imm); break; case 38: /* "bgtz" */ /* Fall-through */ case 39: /* "bgtzt" */ bstmt = dis_branch(unop(Iop_Not1, binop(Iop_CmpLE64S, getIReg(ra), mkU64(0))), imm); break; case 40: /* "blbc" */ /* Fall-through */ case 41: /* "blbct" */ bstmt = dis_branch(unop(Iop_64to1, unop(Iop_Not64, getIReg(ra))), imm); break; case 42: /* "blbs" */ /* Fall-through */ case 43: /* "blbst" */ bstmt = dis_branch(unop(Iop_64to1, getIReg(ra)), imm); break; case 44: /* "blez" */ bstmt = dis_branch(binop(Iop_CmpLE64S, getIReg(ra), mkU64(0)), imm); break; case 45: /* "blezt" */ bstmt = dis_branch(binop(Iop_CmpLE64S, getIReg(ra), mkU64(0)), imm); break; case 46: /* "bltz" */ bstmt = dis_branch(binop(Iop_CmpLT64S, getIReg(ra), mkU64(0)), imm); break; case 47: /* "bltzt" */ bstmt = dis_branch(binop(Iop_CmpLT64S, getIReg(ra), mkU64(0)), imm); break; case 48: /* "bnez" */ /* Fall-through */ case 49: /* "bnezt" */ bstmt = dis_branch(binop(Iop_CmpNE64, getIReg(ra), mkU64(0)), imm); break; case 50: /* "clz" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_Clz64, getIReg(ra))); MARK_REG_WB(rd, t2); break; case 51: /* "cmoveqz rd, ra, rb" */ t2 = newTemp(Ity_I64); assign(t2, IRExpr_ITE(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)), getIReg(rb), getIReg(rd))); MARK_REG_WB(rd, t2); break; case 52: /* "cmovnez" */ t2 = newTemp(Ity_I64); assign(t2, IRExpr_ITE(binop(Iop_CmpEQ64, getIReg(ra), mkU64(0)), getIReg(rd), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 53: /* "cmpeq" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpEQ64, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 54: /* "cmpeqi" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpEQ64, getIReg(ra), mkU64(extend_s_8to64(imm))))); MARK_REG_WB(rd, t2); break; case 55: /* "cmpexch" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, getIReg(rb)); stmt( IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, binop(Iop_Add64, getIReg(70), getIReg(71)), NULL, mkexpr(t1)))); MARK_REG_WB(rd, t2); break; case 56: /* "cmpexch4" */ t1 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I32); assign(t1, narrowTo(Ity_I32, getIReg(rb))); stmt( IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t3, Iend_LE, getIReg(ra), NULL, narrowTo(Ity_I32, binop(Iop_Add64, getIReg(70), getIReg(71))), NULL, mkexpr(t1)))); assign(t2, unop(Iop_32Uto64, mkexpr(t3))); MARK_REG_WB(rd, t2); break; case 57: /* "cmples" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLE64S, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 58: /* "cmpleu" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLE64U, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 59: /* "cmplts" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 60: /* "cmpltsi" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLT64S, getIReg(ra), mkU64(extend_s_8to64(imm))))); MARK_REG_WB(rd, t2); break; case 61: /* "cmpltu" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 62: /* "cmpltui" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpLT64U, getIReg(ra), mkU64(imm)))); MARK_REG_WB(rd, t2); break; case 63: /* "cmpne" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_1Uto64, binop(Iop_CmpNE64, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 64: /* Fall-through */ case 65: /* Fall-through */ case 66: /* Fall-through */ case 67: /* Fall-through */ case 68: /* Fall-through */ case 69: /* Fall-through */ case 70: /* Fall-through */ case 71: /* Fall-through */ case 72: use_dirty_helper = 1; break; case 73: /* "ctz" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_Ctz64, getIReg(ra))); MARK_REG_WB(rd, t2); break; case 74: /* "dblalign" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); /* t0 is the bit shift amount */ assign(t0, binop(Iop_Shl64, binop(Iop_And64, getIReg(rb), mkU64(7)), mkU8(3))); assign(t1, binop(Iop_Sub64, mkU64(64), mkexpr(t0))); assign(t2, binop(Iop_Or64, binop(Iop_Shl64, getIReg(ra), unop(Iop_64to8, mkexpr(t1))), binop(Iop_Shr64, getIReg(rd), unop(Iop_64to8, mkexpr(t0))))); MARK_REG_WB(rd, t2); break; case 75: /* Fall-through */ case 76: /* Fall-through */ case 77: /* Fall-through */ case 78: /* Fall-through */ case 79: use_dirty_helper = 1; break; case 80: /* "exch" */ t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, mkU64(0x0), NULL, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 81: /* "exch4 rd, ra, rb" */ t0 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t0, Iend_LE, getIReg(ra), NULL, mkU32(0x0), NULL, narrowTo(Ity_I32, getIReg(rb))))); assign(t2, unop(Iop_32Sto64, mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 82: /* Fall-through */ case 83: /* Fall-through */ case 84: /* Fall-through */ case 85: /* Fall-through */ case 86: /* Fall-through */ case 87: /* Fall-through */ case 88: /* Fall-through */ case 89: use_dirty_helper = 1; break; case 90: /* "fetchadd" */ t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, // fetchadd=3 mkU64(0x3), NULL, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 91: /* "fetchadd4" */ t0 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t0, Iend_LE, getIReg(ra), NULL, // fetchadd=3 mkU32(0x3), NULL, narrowTo(Ity_I32, getIReg(rb))))); assign(t2, unop(Iop_32Sto64, mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 92: /* "fetchaddgez" */ t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, // fetchaddgez=5 mkU64(0x5), NULL, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 93: /* "fetchaddgez4" */ t0 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t0, Iend_LE, getIReg(ra), NULL, // fetchaddgez=5 mkU32(0x5), NULL, narrowTo(Ity_I32, getIReg(rb))))); assign(t2, unop(Iop_32Sto64, mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 94: /* "fetchand\n") */ t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, mkU64(0x2), NULL, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 95: /* mkIRCAS. 0: xch### 1: cmpexch###, 2: fetchand## 3: fetchadd## 4: fetchor## 5: fetchaddgez */ /* "fetchand4" */ t0 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t0, Iend_LE, getIReg(ra), NULL, mkU32(0x2), NULL, narrowTo(Ity_I32, getIReg(rb))))); assign(t2, unop(Iop_32Sto64, mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 96: /* "fetchor" */ t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t2, Iend_LE, getIReg(ra), NULL, mkU64(0x4), NULL, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 97: /* "fetchor4" */ t0 = newTemp(Ity_I32); t2 = newTemp(Ity_I64); stmt( IRStmt_CAS( mkIRCAS(IRTemp_INVALID, t0, Iend_LE, getIReg(ra), NULL, mkU32(0x4), NULL, narrowTo(Ity_I32, getIReg(rb))))); assign(t2, unop(Iop_32Sto64, mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 98: /* Fall-through */ case 99: /* Fall-through */ case 100: use_dirty_helper = 1; break; case 101: /* "fnop" Ignore */ break; case 102: /* Fall-through */ case 103: /* Fall-through */ case 104: /* Fall-through */ case 105: /* Fall-through */ case 106: /* Fall-through */ case 107: /* Fall-through */ case 108: use_dirty_helper = 1; break; case 109: /* Fall-through */ case 110: /* Fall-through */ case 111: use_dirty_helper = 1; break; case 112: /* "iret" */ next = mkU64(guest_PC_curr_instr + 8); jumpkind = Ijk_Ret; break; case 113: /* "j" */ next = mkU64(imm); /* set steering address. */ steering_pc = imm; jumpkind = Ijk_Boring; break; case 114: t2 = newTemp(Ity_I64); assign(t2, mkU64(guest_PC_curr_instr + 8)); /* set steering address. */ steering_pc = imm; next = mkU64(imm); jumpkind = Ijk_Call; MARK_REG_WB(55, t2); break; case 115: /* "jalr" */ /* Fall-through */ case 116: /* "jalrp" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, getIReg(ra)); assign(t2, mkU64(guest_PC_curr_instr + 8)); next = mkexpr(t1); jumpkind = Ijk_Call; MARK_REG_WB(55, t2); break; case 117: /* "jr" */ /* Fall-through */ case 118: /* "jrp" */ next = getIReg(ra); jumpkind = Ijk_Boring; break; case 119: /* "ld" */ t2 = newTemp(Ity_I64); assign(t2, load(Ity_I64, (getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 120: /* "ld1s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_8Sto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 121: /* "ld1s_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_8Sto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 122: /* "ld1u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_8Uto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 123: /* "ld1u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_8Uto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 124: /* "ld2s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Sto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 125: /* "ld2s_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_16Sto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); MARK_REG_WB(ra, t1); break; case 126: /* "ld2u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Uto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 127: /* "ld2u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_16Uto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); MARK_REG_WB(ra, t1); break; case 128: /* "ld4s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, load(Ity_I32, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 129: /* "ld4s_add" */ t2 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_32Sto64, load(Ity_I32, (getIReg(ra))))); MARK_REG_WB(rd, t2); MARK_REG_WB(ra, t1); break; case 130: /* "ld4u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Uto64, load(Ity_I32, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 131: /* "ld4u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_32Uto64, load(Ity_I32, getIReg(ra)))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 132: /* "ld_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, load(Ity_I64, getIReg(ra))); assign(t2, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(ra, t2); MARK_REG_WB(rd, t1); break; case 133: /* "ldna" */ t2 = newTemp(Ity_I64); assign(t2, load(Ity_I64, binop(Iop_And64, getIReg(ra), unop(Iop_Not64, mkU64(7))))); MARK_REG_WB(rd, t2); break; case 134: /* "ldna_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, load(Ity_I64, binop(Iop_And64, getIReg(ra), unop(Iop_Not64, mkU64(7))))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 135: /* "ldnt" */ /* Valgrind IR has no Non-Temp load. Use normal load. */ t2 = newTemp(Ity_I64); assign(t2, load(Ity_I64, (getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 136: /* "ldnt1s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_8Sto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 137: /* "ldnt1s_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t2, unop(Iop_8Sto64, load(Ity_I8, (getIReg(ra))))); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 138: /* "ldnt1u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_8Uto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 139: /* "ldnt1u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); assign(t2, unop(Iop_8Uto64, load(Ity_I8, (getIReg(ra))))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 140: /* "ldnt2s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Sto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 141: /* "ldnt2s_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Sto64, load(Ity_I16, getIReg(ra)))); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 142: /* "ldnt2u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Uto64, load(Ity_I16, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 143: /* "ldnt2u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t2, unop(Iop_16Uto64, load(Ity_I16, getIReg(ra)))); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(ra, t1); MARK_REG_WB(rd, t2); break; case 144: /* "ldnt4s" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, load(Ity_I32, (getIReg(ra))))); MARK_REG_WB(rd, t2); break; case 145: /* "ldnt4s_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, load(Ity_I32, (getIReg(ra))))); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); MARK_REG_WB(ra, t1); break; case 146: /* "ldnt4u" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Uto64, load(Ity_I32, getIReg(ra)))); MARK_REG_WB(rd, t2); break; case 147: /* "ldnt4u_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Uto64, load(Ity_I32, getIReg(ra)))); assign(t1, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); MARK_REG_WB(ra, t1); break; case 148: /* "ldnt_add" */ t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t1, load(Ity_I64, getIReg(ra))); assign(t2, binop(Iop_Add64, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t1); MARK_REG_WB(ra, t2); break; case 149: /* "lnk" */ t2 = newTemp(Ity_I64); assign(t2, mkU64(guest_PC_curr_instr + 8)); MARK_REG_WB(rd, t2); break; case 150: /* "mf" */ use_dirty_helper = 1; break; case 151: /* "mfspr" */ t2 = newTemp(Ity_I64); if (imm == 0x2780) { // Get Cmpexch value assign(t2, getIReg(70)); MARK_REG_WB(rd, t2); } else if (imm == 0x2580) { // Get EX_CONTEXT_0_0 assign(t2, getIReg(576 / 8)); MARK_REG_WB(rd, t2); } else if (imm == 0x2581) { // Get EX_CONTEXT_0_1 assign(t2, getIReg(584 / 8)); MARK_REG_WB(rd, t2); } else use_dirty_helper = 1; break; case 152: /* "mm" */ use_dirty_helper = 1; break; case 153: /* "mnz" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_And64, unop(Iop_1Sto64, binop(Iop_CmpNE64, getIReg(ra), mkU64(0))), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 154: /* "mtspr imm, ra" */ if (imm == 0x2780) // Set Cmpexch value putIReg(70, getIReg(ra)); else if (imm == 0x2580) // set EX_CONTEXT_0_0 putIReg(576/8, getIReg(ra)); else if (imm == 0x2581) // set EX_CONTEXT_0_1 putIReg(584/8, getIReg(ra)); else use_dirty_helper = 1; break; case 155: /* "mul_hs_hs" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullS32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); MARK_REG_WB(rd, t2); break; case 156: /* "mul_hs_hu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); MARK_REG_WB(rd, t2); break; case 157: /* "mul_hs_ls" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullS32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 158: /* "mul_hs_lu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, getIReg(rb)))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); MARK_REG_WB(rd, t2); break; case 159: /* "mul_hu_hu" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); MARK_REG_WB(rd, t2); break; case 160: /* "mul_hu_ls" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, getIReg(ra)))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); MARK_REG_WB(rd, t2); break; case 161: /* "mul_hu_lu" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 162: /* "mul_ls_ls" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullS32, unop(Iop_64to32, getIReg(ra)), unop(Iop_64to32, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 163: /* "mul_ls_lu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, getIReg(ra)))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, getIReg(rb)))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); MARK_REG_WB(rd, t2); break; case 164: /* "mul_lu_lu" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_MullU32, unop(Iop_64to32, getIReg(ra)), unop(Iop_64to32, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 165: /* "mula_hs_hs" */ t0 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t0, binop(Iop_MullS32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t2, binop(Iop_Add64, getIReg(rd), mkexpr(t0))); MARK_REG_WB(rd, t2); break; case 166: /* "mula_hs_hu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); t4 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, binop(Iop_Shr64, getIReg(rb), mkU8(32))))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); assign(t4, binop(Iop_Add64, getIReg(rd), mkexpr(t2))); MARK_REG_WB(rd, t4); break; case 167: /* "mula_hs_ls" */ t2 = newTemp(Ity_I64); t4 = newTemp(Ity_I64); assign(t2, binop(Iop_MullS32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); assign(t4, binop(Iop_Add64, getIReg(rd), mkexpr(t2))); MARK_REG_WB(rd, t4); break; case 168: /* "mula_hs_lu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); t4 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, getIReg(rb)))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); assign(t2, binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32)))); assign(t4, binop(Iop_Add64, getIReg(rd), mkexpr(t2))); MARK_REG_WB(rd, t4); break; case 169: /* "mula_hu_hu" */ use_dirty_helper = 1; break; case 170: /* "mula_hu_ls" */ use_dirty_helper = 1; break; case 171: /* "mula_hu_lu" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, getIReg(ra), mkU8(32))), unop(Iop_64to32, getIReg(rb))), getIReg(rd))); MARK_REG_WB(rd, t2); break; case 172: /* "mula_ls_ls" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, getIReg(rd), binop(Iop_MullS32, unop(Iop_64to32, getIReg(ra)), unop(Iop_64to32, getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 173: /* "mula_ls_lu" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t0, unop(Iop_32Sto64, unop(Iop_64to32, getIReg(ra)))); assign(t1, binop(Iop_MullU32, unop(Iop_64to32, mkexpr(t0)), unop(Iop_64to32, getIReg(rb)))); assign(t3, binop(Iop_MullU32, unop(Iop_64to32, binop(Iop_Shr64, mkexpr(t0), mkU8(32))), unop(Iop_64to32, getIReg(rb)))); assign(t2, binop(Iop_Add64, getIReg(rd), binop(Iop_Add64, mkexpr(t1), binop(Iop_Shl64, mkexpr(t3), mkU8(32))))); MARK_REG_WB(rd, t2); break; case 174: /* "mula_lu_lu" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, binop(Iop_MullU32, unop(Iop_64to32, getIReg(ra)), unop(Iop_64to32, getIReg(rb))), getIReg(rd))); MARK_REG_WB(rd, t2); break; case 175: /* "mulax" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Add64, getIReg(rd), binop(Iop_MullU32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I32, getIReg(rb))))))); MARK_REG_WB(rd, t2); break; case 176: /* "mulx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_MullU32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I32, getIReg(rb)))))); MARK_REG_WB(rd, t2); break; case 177: /* "mz" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_And64, unop(Iop_1Sto64, binop(Iop_CmpEQ64, getIReg(ra), mkU64(0))), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 178: /* "nap" */ break; case 179: /* "nop" */ break; case 180: /* "nor" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_Not64, binop(Iop_Or64, getIReg(ra), getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 181: /* "or" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Or64, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 182: /* "ori" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Or64, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); break; case 183: /* Fall-through */ case 184: /* Fall-through */ case 185: use_dirty_helper = 1; break; case 186: /* "rotl" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t0, binop(Iop_Shl64, getIReg(ra), unop(Iop_64to8, getIReg(rb)))); assign(t1, binop(Iop_Shr64, getIReg(ra), unop(Iop_64to8, binop(Iop_Sub64, mkU64(0), getIReg(rb))))); assign(t2, binop(Iop_Or64, mkexpr(t0), mkexpr(t1))); MARK_REG_WB(rd, t2); break; case 187: /* "rotli" */ t0 = newTemp(Ity_I64); t1 = newTemp(Ity_I64); t2 = newTemp(Ity_I64); assign(t0, binop(Iop_Shl64, getIReg(ra), mkU8(imm))); assign(t1, binop(Iop_Shr64, getIReg(ra), mkU8(0 - imm))); assign(t2, binop(Iop_Or64, mkexpr(t0), mkexpr(t1))); MARK_REG_WB(rd, t2); break; case 188: /* "shl" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Shl64, getIReg(ra), unop(Iop_64to8, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 189: /* "shl16insli" */ t2 = newTemp(Ity_I64); t3 = newTemp(Ity_I64); assign(t3, binop(Iop_Shl64, getIReg(ra), mkU8(16))); imm &= 0xFFFFULL; if (imm & 0x8000) { t4 = newTemp(Ity_I64); assign(t4, mkU64(imm)); assign(t2, binop(Iop_Add64, mkexpr(t3), mkexpr(t4))); } else { assign(t2, binop(Iop_Add64, mkexpr(t3), mkU64(imm))); } MARK_REG_WB(rd, t2); break; case 190: /* "shl1add" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(1)), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 191: /* "shl1addx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(1)), getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 192: /* "shl2add" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(2)), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 193: /* "shl2addx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(2)), getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 194: /* "shl3add" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(3)), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 195: /* "shl3addx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, unop(Iop_64to32, binop(Iop_Add64, binop(Iop_Shl64, getIReg(ra), mkU8(3)), getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 196: /* "shli" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Shl64, getIReg(ra), mkU8(imm))); MARK_REG_WB(rd, t2); break; case 197: /* "shlx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, binop(Iop_Shl32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I8, getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 198: /* "shlxi" */ t2 = newTemp(Ity_I64); assign(t2, signExtend(binop(Iop_Shl32, narrowTo(Ity_I32, getIReg(ra)), mkU8(imm)), 32)); MARK_REG_WB(rd, t2); break; case 199: /* "shrs" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Sar64, getIReg(ra), narrowTo(Ity_I8, getIReg(rb)))); MARK_REG_WB(rd, t2); break; case 200: /* "shrsi" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Sar64, getIReg(ra), mkU8(imm))); MARK_REG_WB(rd, t2); break; case 201: /* "shru" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Shr64, getIReg(ra), narrowTo(Ity_I8, (getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 202: /* "shrui" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Shr64, getIReg(ra), mkU8(imm))); MARK_REG_WB(rd, t2); break; case 203: /* "shrux" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, (binop(Iop_Shr32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I8, getIReg(rb)))))); MARK_REG_WB(rd, t2); break; case 204: /* "shruxi" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, (binop(Iop_Shr32, narrowTo(Ity_I32, getIReg(ra)), mkU8(imm))))); MARK_REG_WB(rd, t2); break; case 205: /* "shufflebytes" */ use_dirty_helper = 1; break; case 206: /* "st" */ store(getIReg(ra), getIReg(rb)); break; case 207: /* "st1" */ store(getIReg(ra), narrowTo(Ity_I8, getIReg(rb))); break; case 208: /* "st1_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I8, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 209: /* "st2" */ store(getIReg(ra), narrowTo(Ity_I16, getIReg(rb))); break; case 210: /* "st2_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I16, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 211: /* "st4" */ store(getIReg(ra), narrowTo(Ity_I32, getIReg(rb))); break; case 212: /* "st4_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I32, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 213: /* "st_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), getIReg(opd[1])); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 214: /* "stnt" */ store(getIReg(ra), getIReg(rb)); break; case 215: /* "stnt1" */ store(getIReg(ra), narrowTo(Ity_I8, getIReg(rb))); break; case 216: /* "stnt1_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I8, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 217: /* "stnt2" */ store(getIReg(ra), narrowTo(Ity_I16, getIReg(rb))); break; case 218: /* "stnt2_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I16, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 219: /* "stnt4" */ store(getIReg(ra), narrowTo(Ity_I32, getIReg(rb))); break; case 220: /* "stnt4_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), narrowTo(Ity_I32, getIReg(opd[1]))); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 221: /* "stnt_add" */ t2 = newTemp(Ity_I64); store(getIReg(opd[0]), getIReg(opd[1])); assign(t2, binop(Iop_Add64, getIReg(opd[0]), mkU64(opd[2]))); MARK_REG_WB(opd[0], t2); break; case 222: /* "sub" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Sub64, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 223: /* "subx" */ t2 = newTemp(Ity_I64); assign(t2, unop(Iop_32Sto64, binop(Iop_Sub32, narrowTo(Ity_I32, getIReg(ra)), narrowTo(Ity_I32, getIReg(rb))))); MARK_REG_WB(rd, t2); break; case 224: /* "subxsc" */ use_dirty_helper = 1; break; case 225: /* "swint0" */ vex_printf( "\n *** swint0 ***\n"); vassert(0); break; case 226: /* "swint1" */ next = mkU64(guest_PC_curr_instr + 8); jumpkind = Ijk_Sys_syscall; break; case 227: /* "swint2" */ vex_printf( "\n *** swint2 ***\n"); vassert(0); break; case 228: /* "swint3" */ vex_printf( "\n *** swint3 ***\n"); vassert(0); break; case 229: /* Fall-through */ case 230: /* Fall-through */ case 231: /* Fall-through */ case 232: /* Fall-through */ case 233: use_dirty_helper = 1; break; case 234: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 235: /* Fall-through */ case 236: /* Fall-through */ case 237: use_dirty_helper = 1; break; case 238: /* "v1cmpeq" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_CmpEQ8x8, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 239: /* "v1cmpeqi" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_CmpEQ8x8, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); break; case 240: /* Fall-through */ case 241: /* Fall-through */ case 242: use_dirty_helper = 1; break; case 243: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; /* Fall-through */ case 244: use_dirty_helper = 1; break; case 245: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 246: /* "v1cmpne" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_CmpEQ8x8, binop(Iop_CmpEQ8x8, getIReg(ra), getIReg(rb)), getIReg(63))); MARK_REG_WB(rd, t2); break; case 247: /* Fall-through */ case 248: /* Fall-through */ case 249: /* Fall-through */ case 250: /* Fall-through */ case 251: /* Fall-through */ case 252: /* Fall-through */ case 253: /* Fall-through */ case 254: /* Fall-through */ case 255: /* Fall-through */ case 256: /* Fall-through */ case 257: /* Fall-through */ case 258: /* Fall-through */ case 259: use_dirty_helper = 1; break; case 260: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 261: use_dirty_helper = 1; break; case 262: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 263: /* Fall-through */ case 264: /* Fall-through */ case 265: /* Fall-through */ case 266: /* Fall-through */ case 267: /* Fall-through */ case 268: /* Fall-through */ case 269: /* Fall-through */ case 270: use_dirty_helper = 1; break; case 271: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 272: use_dirty_helper = 1; break; case 273: opd[3] = V1EXP(opd[3]); use_dirty_helper = 1; break; case 274: use_dirty_helper = 1; break; case 275: /* "v1shrui" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Shr8x8, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); break; case 276: /* Fall-through */ case 277: /* Fall-through */ case 278: use_dirty_helper = 1; break; case 279: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 280: /* Fall-through */ case 281: /* Fall-through */ case 282: /* Fall-through */ case 283: use_dirty_helper = 1; break; case 284: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 285: /* Fall-through */ case 286: /* Fall-through */ case 287: use_dirty_helper = 1; break; case 288: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 289: use_dirty_helper = 1; break; case 290: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 291: /* Fall-through */ case 292: /* Fall-through */ case 293: /* Fall-through */ case 294: /* Fall-through */ case 295: /* Fall-through */ case 296: use_dirty_helper = 1; break; case 297: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 298: use_dirty_helper = 1; break; case 299: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 300: /* Fall-through */ case 301: /* Fall-through */ case 302: /* Fall-through */ case 303: /* Fall-through */ case 304: /* Fall-through */ case 305: /* Fall-through */ case 306: /* Fall-through */ case 307: /* Fall-through */ case 308: /* Fall-through */ case 309: /* Fall-through */ case 310: /* Fall-through */ case 311: /* Fall-through */ case 312: use_dirty_helper = 1; break; case 313: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 314: /* Fall-through */ case 315: use_dirty_helper = 1; break; case 316: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 317: use_dirty_helper = 1; break; case 318: opd[3] = V2EXP(opd[3]); use_dirty_helper = 1; break; case 319: /* Fall-through */ case 320: /* Fall-through */ case 321: /* Fall-through */ case 322: /* Fall-through */ case 323: use_dirty_helper = 1; break; case 324: /* "v4int_l" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Or64, binop(Iop_Shl64, getIReg(ra), mkU8(32)), binop(Iop_And64, getIReg(rb), mkU64(0xFFFFFFFF)))); MARK_REG_WB(rd, t2); break; case 325: /* Fall-through */ case 326: /* Fall-through */ case 327: /* Fall-through */ case 328: /* Fall-through */ case 329: /* Fall-through */ case 330: /* Fall-through */ case 331: use_dirty_helper = 1; break; case 332: /* "wh64" */ /* Ignore store hint */ break; case 333: /* "xor" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Xor64, getIReg(ra), getIReg(rb))); MARK_REG_WB(rd, t2); break; case 334: /* "xori" */ t2 = newTemp(Ity_I64); assign(t2, binop(Iop_Xor64, getIReg(ra), mkU64(imm))); MARK_REG_WB(rd, t2); break; case 335: /* "(null)" */ /* ignore */ break; default: decode_failure: vex_printf("error: %d\n", (Int)opcode); /* All decode failures end up here. */ vex_printf("vex tilegx->IR: unhandled instruction: " "%s 0x%llx 0x%llx 0x%llx 0x%llx\n", decoded[n].opcode->name, opd[0], opd[1], opd[2], opd[3]); /* Tell the dispatcher that this insn cannot be decoded, and so has not been executed, and (is currently) the next to be executed. */ stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), mkU64(guest_PC_curr_instr))); dres.whatNext = Dis_StopHere; dres.len = 0; return dres; } /* Hook the dirty helper for rare instruxtions. */ if (use_dirty_helper) { Int i = 0; Int wbc = 0; IRExpr *opc_oprand[5]; opc_oprand[0] = mkU64(opcode); /* Get the operand registers or immediate. */ for (i = 0 ; i < 4; i++) { opc_oprand[i + 1] = NULL; if (opd_dst_map & (1ULL << i)) { tb[wbc] = newTemp(Ity_I64); wbc++; opc_oprand[i + 1] = getIReg(opd[i]); } else if (opd_imm_map & (1ULL << i)) opc_oprand[i + 1] = mkU64(opd[i]); else if (opd_src_map & (1ULL << i)) opc_oprand[i + 1] = getIReg(opd[i]); else opc_oprand[i + 1] = mkU64(0xfeee); } IRExpr **args = mkIRExprVec_5(opc_oprand[0], opc_oprand[1], opc_oprand[2], opc_oprand[3], opc_oprand[4]); IRDirty *genIR = NULL; switch (wbc) { case 0: { genIR = unsafeIRDirty_0_N (0/*regparms*/, "tilegx_dirtyhelper_gen", &tilegx_dirtyhelper_gen, args); } break; case 1: { genIR = unsafeIRDirty_1_N (tb[0], 0/*regparms*/, "tilegx_dirtyhelper_gen", &tilegx_dirtyhelper_gen, args); } break; default: vex_printf("opc = %d\n", (Int)opcode); vassert(0); } stmt(IRStmt_Dirty(genIR)); wbc = 0; for (i = 0 ; i < 4; i++) { if(opd_dst_map & (1 << i)) { /* Queue the writeback destination registers. */ MARK_REG_WB(opd[i], tb[wbc]); wbc++; } } } } /* Write back registers for a bundle. Note have to get all source registers for all instructions in a bundle before write the destinations b/c this is an VLIW processor. */ for (n = 0; n < rd_wb_index; n++) putIReg(rd_wb_reg[n], mkexpr(rd_wb_temp[n])); /* Add branch IR if apply finally, only upto one branch per bundle. */ if (bstmt) { stmt(bstmt); dres.whatNext = Dis_StopHere; dres.jk_StopHere = jumpkind; stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), mkU64(guest_PC_curr_instr + 8))); } else if (next) { if (steering_pc != -1ULL) { if (resteerOkFn(callback_opaque, steering_pc)) { dres.whatNext = Dis_ResteerU; dres.continueAt = steering_pc; stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), mkU64(steering_pc))); } else { dres.whatNext = Dis_StopHere; dres.jk_StopHere = jumpkind; stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), mkU64(steering_pc))); } } else { dres.whatNext = Dis_StopHere; dres.jk_StopHere = jumpkind; stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), next)); } } else { /* As dafault dres.whatNext = Dis_Continue. */ stmt(IRStmt_Put(offsetof(VexGuestTILEGXState, guest_pc), mkU64(guest_PC_curr_instr + 8))); } irsb->jumpkind = Ijk_Boring; irsb->next = NULL; dres.len = 8; decode_success: return dres; } /*------------------------------------------------------------*/ /*--- Top-level fn ---*/ /*------------------------------------------------------------*/ /* Disassemble a single instruction into IR. The instruction is located in host memory at &guest_code[delta]. */ DisResult disInstr_TILEGX ( IRSB* irsb_IN, Bool (*resteerOkFn) (void *, Addr), Bool resteerCisOk, void* callback_opaque, const UChar* guest_code_IN, Long delta, Addr guest_IP, VexArch guest_arch, const VexArchInfo* archinfo, const VexAbiInfo* abiinfo, VexEndness host_endness_IN, Bool sigill_diag_IN ) { DisResult dres; /* Set globals (see top of this file) */ vassert(guest_arch == VexArchTILEGX); guest_code = (UChar*)(Addr)guest_code_IN; irsb = irsb_IN; host_endness = host_endness_IN; guest_PC_curr_instr = (Addr64) guest_IP; guest_PC_bbstart = (Addr64) toUInt(guest_IP - delta); dres = disInstr_TILEGX_WRK(resteerOkFn, resteerCisOk, callback_opaque, delta, archinfo, abiinfo, sigill_diag_IN); return dres; } /*--------------------------------------------------------------------*/ /*--- end guest_tilegx_toIR.c ---*/ /*--------------------------------------------------------------------*/