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