guest_generic_bb_to_IR.c revision db4738ab05bf88fabe7fd931a24fab2fa2060e73
19e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 29e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--------------------------------------------------------------------*/ 39e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- ---*/ 49e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- This file (guest-generic/bb_to_IR.c) is ---*/ 59e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- Copyright (c) OpenWorks LLP. All rights reserved. ---*/ 69e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- ---*/ 79e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--------------------------------------------------------------------*/ 89e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 99e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/* 109e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj This file is part of LibVEX, a library for dynamic binary 119e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj instrumentation and translation. 129e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 139e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Copyright (C) 2004-2005 OpenWorks LLP. 149e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 159e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj This program is free software; you can redistribute it and/or modify 169e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj it under the terms of the GNU General Public License as published by 179e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj the Free Software Foundation; Version 2 dated June 1991 of the 189e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj license. 199e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 209e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj This program is distributed in the hope that it will be useful, 219e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj but WITHOUT ANY WARRANTY; without even the implied warranty of 229e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability 239e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj for damages. See the GNU General Public License for more details. 249e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 259e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Neither the names of the U.S. Department of Energy nor the 269e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj University of California nor the names of its contributors may be 279e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj used to endorse or promote products derived from this software 289e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj without prior written permission. 299e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 309e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj You should have received a copy of the GNU General Public License 319e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj along with this program; if not, write to the Free Software 329e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 339e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj USA. 349e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj*/ 359e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 369e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "libvex_basictypes.h" 379e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "libvex_ir.h" 389e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "libvex.h" 399e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "main/vex_util.h" 409e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "main/vex_globals.h" 419e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj#include "guest-generic/bb_to_IR.h" 429e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 439e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 44db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj/* Forwards .. */ 45db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardjstatic UInt genericg_compute_adler32 ( HWord addr, UInt len ); 46db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 47db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 489e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/* Disassemble a complete basic block, starting at guest_IP_start, 499e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj returning a new IRBB. The disassembler may chase across basic 509e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj block boundaries if it wishes and if chase_into_ok allows it. 519e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj The precise guest address ranges from which code has been taken 529e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj are written into vge. guest_IP_start is taken to be the IP in 539e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj the guest's address space corresponding to the instruction at 549e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj &guest_code[0]. 559e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 569e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj dis_instr_fn is the arch-specific fn to disassemble on function; it 579e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj is this that does the real work. 58db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 59db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj do_self_check indicates that the caller needs a self-checking 60db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj translation. 61db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 62db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj offB_TIADDR and offB_TILEN are the offsets of guest_TIADDR and 63db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj guest_TILEN. Since this routine has to work for any guest state, 64db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj without knowing what it is, those offsets have to passed in. 659e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj*/ 669e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 679e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardjstatic Bool const_False ( Addr64 a ) { return False; } 689e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 699e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardjIRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, 709e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ DisOneInstrFn dis_instr_fn, 719e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ UChar* guest_code, 729e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ Addr64 guest_IP_bbstart, 739e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ Bool (*chase_into_ok)(Addr64), 749e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ Bool host_bigendian, 759e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /*IN*/ VexArchInfo* archinfo_guest, 76db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /*IN*/ IRType guest_word_type, 77db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /*IN*/ Bool do_self_check, 78db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /*IN*/ Int offB_TISTART, 79db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /*IN*/ Int offB_TILEN ) 809e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj{ 819e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Long delta; 829e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Int i, n_instrs, first_stmt_idx; 839e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Bool resteerOK, need_to_put_IP, debug_print; 849e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj DisResult dres; 859e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj IRStmt* imark; 869e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj static Int n_resteers = 0; 879e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Int d_resteers = 0; 88db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj Int selfcheck_idx = 0; 899e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj IRBB* irbb; 909e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Addr64 guest_IP_curr_instr; 919e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 929e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj Bool (*resteerOKfn)(Addr64) = NULL; 939e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 949e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj debug_print = toBool(vex_traceflags & VEX_TRACE_FE); 959e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 96db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* Note: for adler32 to work without % operation for the self 97db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj check, need to limit length of stuff it scans to 5552 bytes. 98db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj Therefore limiting the max bb len to 100 insns seems generously 99db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj conservative. */ 100db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 1019e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* check sanity .. */ 102db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj vassert(sizeof(HWord) == sizeof(void*)); 1039e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(vex_control.guest_max_insns >= 1); 104db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj vassert(vex_control.guest_max_insns < 100); 1059e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(vex_control.guest_chase_thresh >= 0); 1069e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns); 1079e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64); 1089e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1099e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Start a new, empty extent. */ 1109e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->n_used = 1; 1119e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->base[0] = guest_IP_bbstart; 1129e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->len[0] = 0; 1139e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1149e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* And a new IR BB to dump the result into. */ 1159e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj irbb = emptyIRBB(); 1169e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1179e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Delta keeps track of how far along the guest_code array we have 1189e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj so far gone. */ 1199e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj delta = 0; 1209e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj n_instrs = 0; 1219e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 122db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* If asked to make a self-checking translation, leave a 3 spaces 123db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj in which to put the check statements. We'll fill them in later 124db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj when we know the length and adler32 of the area to check. */ 125db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj if (do_self_check) { 126db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj selfcheck_idx = irbb->stmts_used; 127db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj addStmtToIRBB( irbb, IRStmt_NoOp() ); 128db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj addStmtToIRBB( irbb, IRStmt_NoOp() ); 129db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj addStmtToIRBB( irbb, IRStmt_NoOp() ); 130db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj } 131db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 132db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* Process instructions. */ 1339e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj while (True) { 1349e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(n_instrs < vex_control.guest_max_insns); 1359e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1369e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Regardless of what chase_into_ok says, is chasing permissible 1379e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj at all right now? Set resteerOKfn accordingly. */ 1389e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj resteerOK 1399e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj = toBool( 1409e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj n_instrs < vex_control.guest_chase_thresh 141db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* If making self-checking translations, don't chase 142db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj .. it makes the checks too complicated. We only want 143db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj to scan just one sequence of bytes in the check, not 144db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj a whole bunch. */ 145db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj && !do_self_check 1469e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* we can't afford to have a resteer once we're on the 1479e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj last extent slot. */ 1489e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj && vge->n_used < 3 1499e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ); 1509e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1519e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj resteerOKfn 1529e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj = resteerOK ? chase_into_ok : const_False; 1539e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1549e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* This is the IP of the instruction we're just about to deal 1559e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj with. */ 1569e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj guest_IP_curr_instr = guest_IP_bbstart + delta; 1579e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1589e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* This is the irbb statement array index of the first stmt in 1599e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj this insn. That will always be the instruction-mark 1609e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj descriptor. */ 1619e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj first_stmt_idx = irbb->stmts_used; 1629e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1639e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Add an instruction-mark statement. We won't know until after 1649e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj disassembling the instruction how long it instruction is, so 1659e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj just put in a zero length and we'll fix it up later. */ 1669e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj addStmtToIRBB( irbb, IRStmt_IMark( guest_IP_curr_instr, 0 )); 1679e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1689e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* for the first insn, the dispatch loop will have set 1699e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj %IP, but for all the others we have to do it ourselves. */ 1709e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj need_to_put_IP = toBool(n_instrs > 0); 1719e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1729e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Finally, actually disassemble an instruction. */ 1739e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj dres = dis_instr_fn ( irbb, 1749e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj need_to_put_IP, 1759e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj resteerOKfn, 1769e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj guest_code, 1779e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj delta, 1789e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj guest_IP_curr_instr, 1799e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj archinfo_guest, 1809e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj host_bigendian ); 1819e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1829e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* stay sane ... */ 1839e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(dres.whatNext == Dis_StopHere 1849e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj || dres.whatNext == Dis_Continue 1859e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj || dres.whatNext == Dis_Resteer); 1869e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(dres.len >= 0 && dres.len <= 18); 1879e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (dres.whatNext != Dis_Resteer) 1889e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(dres.continueAt == 0); 1899e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1909e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Fill in the insn-mark length field. */ 1919e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used); 1929e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj imark = irbb->stmts[first_stmt_idx]; 1939e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(imark); 1949e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(imark->tag == Ist_IMark); 1959e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(imark->Ist.IMark.len == 0); 1969e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj imark->Ist.IMark.len = toUInt(dres.len); 1979e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 1989e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Print the resulting IR, if needed. */ 1999e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (vex_traceflags & VEX_TRACE_FE) { 2009e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj for (i = first_stmt_idx; i < irbb->stmts_used; i++) { 2019e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf(" "); 2029e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ppIRStmt(irbb->stmts[i]); 2039e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf("\n"); 2049e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2059e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2069e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 2079e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* If dis_instr_fn terminated the BB at this point, check it 2089e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj also filled in the irbb->next field. */ 2099e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (dres.whatNext == Dis_StopHere) { 2109e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(irbb->next != NULL); 2119e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (debug_print) { 2129e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf(" "); 2139e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf( "goto {"); 2149e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ppIRJumpKind(irbb->jumpkind); 2159e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf( "} "); 2169e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ppIRExpr( irbb->next ); 2179e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf( "\n"); 2189e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2199e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2209e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 2219e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Update the VexGuestExtents we are constructing. */ 222db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* If vex_control.guest_max_insns is required to be < 100 and 223db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj each insn is at max 20 bytes long, this limit of 5000 then 2249e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj seems reasonable since the max possible extent length will be 225db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 100 * 20 == 2000. */ 226db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj vassert(vge->len[vge->n_used-1] < 5000); 2279e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->len[vge->n_used-1] 2289e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len )); 2299e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj n_instrs++; 2309e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (debug_print) 2319e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf("\n"); 2329e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 2339e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Advance delta (inconspicuous but very important :-) */ 2349e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj delta += (Long)dres.len; 2359e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 2369e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj switch (dres.whatNext) { 2379e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj case Dis_Continue: 2389e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(irbb->next == NULL); 2399e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (n_instrs < vex_control.guest_max_insns) { 2409e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* keep going */ 2419e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } else { 2429e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* We have to stop. */ 2439e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj irbb->next 2449e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj = IRExpr_Const( 2459e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj guest_word_type == Ity_I32 2469e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ? IRConst_U32(toUInt(guest_IP_bbstart+delta)) 2479e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj : IRConst_U64(guest_IP_bbstart+delta) 2489e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj ); 249db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj goto done; 2509e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2519e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj break; 2529e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj case Dis_StopHere: 2539e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(irbb->next != NULL); 254db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj goto done; 2559e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj case Dis_Resteer: 2569e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* Check that we actually allowed a resteer .. */ 2579e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(resteerOK); 2589e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(irbb->next == NULL); 2599e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* figure out a new delta to continue at. */ 2609e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(resteerOKfn(dres.continueAt)); 2619e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj delta = dres.continueAt - guest_IP_bbstart; 2629e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj /* we now have to start a new extent slot. */ 2639e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->n_used++; 2649e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vassert(vge->n_used <= 3); 2659e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->base[vge->n_used-1] = dres.continueAt; 2669e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vge->len[vge->n_used-1] = 0; 2679e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj n_resteers++; 2689e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj d_resteers++; 2699e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj if (0 && (n_resteers & 0xFF) == 0) 2709e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n", 2719e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj n_resteers, d_resteers, 2729e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj dres.continueAt, delta); 2739e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj break; 2749e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj default: 2759e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj vpanic("bb_to_IR"); 2769e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 2779e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj } 278db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /*NOTREACHED*/ 279db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj vassert(0); 280db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 281db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj done: 282db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* We're done. The only thing that might need attending to is that 283db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj a self-checking preamble may need to be created. */ 284db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj if (do_self_check) { 285db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 286db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj UInt len2check, adler32; 287db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj IRConst* guest_IP_bbstart_IRConst; 288db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 289db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj vassert(vge->n_used == 1); 290db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj len2check = vge->len[0]; 291db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj if (len2check == 0) 292db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj len2check = 1; 293db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 294db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj adler32 = genericg_compute_adler32( (HWord)guest_code, len2check ); 295db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 296db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj guest_IP_bbstart_IRConst 297db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj = guest_word_type==Ity_I32 298db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ? IRConst_U32(guest_IP_bbstart) 299db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj : IRConst_U64(guest_IP_bbstart); 300db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 301db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj /* Set TISTART and TILEN. These will describe to the despatcher 302db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj the area of guest code to invalidate should we exit with a 303db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj self-check failure. */ 304db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 305db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj irbb->stmts[selfcheck_idx+0] 306db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj = IRStmt_Put( offB_TILEN, 307db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj guest_word_type==Ity_I32 308db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ? IRExpr_Const(IRConst_U32(len2check)) 309db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj : IRExpr_Const(IRConst_U64(len2check)) ); 310db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 311db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj irbb->stmts[selfcheck_idx+1] 312db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj = IRStmt_Put( offB_TISTART, IRExpr_Const(guest_IP_bbstart_IRConst) ); 313db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 314db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj irbb->stmts[selfcheck_idx+2] 315db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj = IRStmt_Exit( 316db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj IRExpr_Binop( 317db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj Iop_CmpNE32, 318db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj mkIRExprCCall( 319db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj Ity_I32, 320db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 0/*regparms*/, 321db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj "genericg_compute_adler32", 322db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj &genericg_compute_adler32, 323db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj mkIRExprVec_2( 324db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj mkIRExpr_HWord( (HWord)guest_code ), 325db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj IRExpr_Const(IRConst_U32(len2check)) 326db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ) 327db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ), 328db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj IRExpr_Const(IRConst_U32(adler32)) 329db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ), 330db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj Ijk_TInval, 331db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj guest_IP_bbstart_IRConst 332db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj ); 333db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj } 334db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 335db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj return irbb; 3369e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj} 3379e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 3389e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 339db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj/*------------------------------------------------------------- 340db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj A support routine for doing self-checking translations. 341db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj -------------------------------------------------------------*/ 342db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 343db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj/* CLEAN HELPER */ 344db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj/* CALLED FROM GENERATED CODE */ 345db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 346db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj/* Compute the Adler32 checksum of host memory at [addr 347db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj .. addr+len-1]. This presumably holds guest code. Note this is 348db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj not a proper implementation of Adler32 in that it fails to mod the 349db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj counts with 65521 every 5552 bytes, but we really never expect to 350db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj get anywhere near that many bytes to deal with. This fn is called 351db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj once for every use of a self-checking translation, so it needs to 352db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj be as fast as possible. */ 353db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardjstatic UInt genericg_compute_adler32 ( HWord addr, UInt len ) 354db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj{ 355db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj UInt i; 356db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj UInt s1 = 1; 357db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj UInt s2 = 0; 358db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj UChar* buf = (UChar*)addr; 359db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj for (i = 0; i < len; i++) { 360db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += (UInt)buf[i]; 361db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 362db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj } 363db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj#if 0 364db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj while (len >= 4) { 365db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += buf[0]; 366db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 367db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += buf[1]; 368db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 369db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += buf[2]; 370db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 371db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += buf[3]; 372db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 373db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj buf += 4; 374db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj len -= 4; 375db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj } 376db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj while (len > 0) { 377db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s1 += buf[0]; 378db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj s2 += s1; 379db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj len--; 380db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj buf++; 381db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj } 382db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj#endif 383db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj return (s2 << 16) + s1; 384db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj} 385db4738ab05bf88fabe7fd931a24fab2fa2060e73sewardj 3869e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj 3879e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--------------------------------------------------------------------*/ 3889e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- end guest-generic/bb_to_IR.c ---*/ 3899e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--------------------------------------------------------------------*/ 390