1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                               guest_generic_bb_to_IR.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copyright (C) 2004-2010 OpenWorks LLP
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forwards .. */
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(2)))
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s );
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_1 ( HWord first_w32 );
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_2 ( HWord first_w32 );
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_3 ( HWord first_w32 );
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_4 ( HWord first_w32 );
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_5 ( HWord first_w32 );
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_6 ( HWord first_w32 );
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_7 ( HWord first_w32 );
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_8 ( HWord first_w32 );
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_9 ( HWord first_w32 );
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_10 ( HWord first_w32 );
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_11 ( HWord first_w32 );
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_12 ( HWord first_w32 );
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Small helpers */
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool const_False ( void* callback_opaque, Addr64 a ) {
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a complete basic block, starting at guest_IP_start,
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   returning a new IRSB.  The disassembler may chase across basic
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   block boundaries if it wishes and if chase_into_ok allows it.
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The precise guest address ranges from which code has been taken
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are written into vge.  guest_IP_bbstart is taken to be the IP in
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the guest's address space corresponding to the instruction at
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   &guest_code[0].
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dis_instr_fn is the arch-specific fn to disassemble on function; it
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is this that does the real work.
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do_self_check indicates that the caller needs a self-checking
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translation.
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   preamble_function is a callback which allows the caller to add
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   its own IR preamble (following the self-check, if any).  May be
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NULL.  If non-NULL, the IRSB under construction is handed to
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this function, which presumably adds IR statements to it.  The
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   callback may optionally complete the block and direct bb_to_IR
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   not to disassemble any instructions into it; this is indicated
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by the callback returning True.
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   offB_TIADDR and offB_TILEN are the offsets of guest_TIADDR and
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_TILEN.  Since this routine has to work for any guest state,
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without knowing what it is, those offsets have to passed in.
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   callback_opaque is a caller-supplied pointer to data which the
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   callbacks may want to see.  Vex has no idea what it is.
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (In fact it's a VgInstrumentClosure.)
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ void*            callback_opaque,
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ DisOneInstrFn    dis_instr_fn,
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ UChar*           guest_code,
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Addr64           guest_IP_bbstart,
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Bool             (*chase_into_ok)(void*,Addr64),
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Bool             host_bigendian,
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ VexArch          arch_guest,
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ VexArchInfo*     archinfo_guest,
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ VexAbiInfo*      abiinfo_both,
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ IRType           guest_word_type,
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Bool             do_self_check,
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Bool             (*preamble_function)(void*,IRSB*),
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Int              offB_TISTART,
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 /*IN*/ Int              offB_TILEN )
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long       delta;
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, n_instrs, first_stmt_idx;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool       resteerOK, need_to_put_IP, debug_print;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult  dres;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    imark;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static Int n_resteers = 0;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        d_resteers = 0;
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        selfcheck_idx = 0;
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRSB*      irsb;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64     guest_IP_curr_instr;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst*   guest_IP_bbstart_IRConst = NULL;
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        n_cond_resteers_allowed = 2;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool (*resteerOKfn)(void*,Addr64) = NULL;
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: for adler32 to work without % operation for the self
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      check, need to limit length of stuff it scans to 5552 bytes.
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Therefore limiting the max bb len to 100 insns seems generously
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      conservative. */
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* check sanity .. */
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(sizeof(HWord) == sizeof(void*));
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vex_control.guest_max_insns >= 1);
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vex_control.guest_max_insns < 100);
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vex_control.guest_chase_thresh >= 0);
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Start a new, empty extent. */
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vge->n_used  = 1;
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vge->base[0] = guest_IP_bbstart;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vge->len[0]  = 0;
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* And a new IR superblock to dump the result into. */
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb = emptyIRSB();
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Delta keeps track of how far along the guest_code array we have
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      so far gone. */
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta    = 0;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_instrs = 0;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Guest addresses as IRConsts.  Used in the two self-checks
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      generated. */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_self_check) {
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest_IP_bbstart_IRConst
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = guest_word_type==Ity_I32
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ? IRConst_U32(toUInt(guest_IP_bbstart))
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              : IRConst_U64(guest_IP_bbstart);
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If asked to make a self-checking translation, leave 5 spaces
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in which to put the check statements.  We'll fill them in later
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      when we know the length and adler32 of the area to check. */
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_self_check) {
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      selfcheck_idx = irsb->stmts_used;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_NoOp() );
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_NoOp() );
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_NoOp() );
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_NoOp() );
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_NoOp() );
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the caller supplied a function to add its own preamble, use
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it now. */
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (preamble_function) {
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool stopNow = preamble_function( callback_opaque, irsb );
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (stopNow) {
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The callback has completed the IR block without any guest
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            insns being disassembled into it, so just return it at
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            this point, even if a self-check was requested - as there
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is nothing to self-check.  The five self-check no-ops will
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            still be in place, but they are harmless. */
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return irsb;
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Process instructions. */
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (True) {
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(n_instrs < vex_control.guest_max_insns);
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Regardless of what chase_into_ok says, is chasing permissible
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         at all right now?  Set resteerOKfn accordingly. */
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      resteerOK
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toBool(
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              n_instrs < vex_control.guest_chase_thresh
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* If making self-checking translations, don't chase
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 .. it makes the checks too complicated.  We only want
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 to scan just one sequence of bytes in the check, not
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 a whole bunch. */
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && !do_self_check
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* we can't afford to have a resteer once we're on the
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 last extent slot. */
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              && vge->n_used < 3
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      resteerOKfn
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = resteerOK ? chase_into_ok : const_False;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* n_cond_resteers_allowed keeps track of whether we're still
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         allowing dis_instr_fn to chase conditional branches.  It
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         starts (at 2) and gets decremented each time dis_instr_fn
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tells us it has chased a conditional branch.  We then
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         decrement it, and use it to tell later calls to dis_instr_fn
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         whether or not it is allowed to chase conditional
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         branches. */
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(n_cond_resteers_allowed >= 0 && n_cond_resteers_allowed <= 2);
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the IP of the instruction we're just about to deal
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         with. */
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      guest_IP_curr_instr = guest_IP_bbstart + delta;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the irsb statement array index of the first stmt in
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         this insn.  That will always be the instruction-mark
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         descriptor. */
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      first_stmt_idx = irsb->stmts_used;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add an instruction-mark statement.  We won't know until after
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         disassembling the instruction how long it instruction is, so
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         just put in a zero length and we'll fix it up later. */
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( irsb, IRStmt_IMark( guest_IP_curr_instr, 0 ));
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* for the first insn, the dispatch loop will have set
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         %IP, but for all the others we have to do it ourselves. */
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      need_to_put_IP = toBool(n_instrs > 0);
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Finally, actually disassemble an instruction. */
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dres = dis_instr_fn ( irsb,
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            need_to_put_IP,
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            resteerOKfn,
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            toBool(n_cond_resteers_allowed > 0),
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            callback_opaque,
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            guest_code,
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            delta,
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            guest_IP_curr_instr,
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            arch_guest,
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            archinfo_guest,
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            abiinfo_both,
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            host_bigendian );
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* stay sane ... */
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(dres.whatNext == Dis_StopHere
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || dres.whatNext == Dis_Continue
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || dres.whatNext == Dis_ResteerU
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || dres.whatNext == Dis_ResteerC);
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ... disassembled insn length is sane ... */
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(dres.len >= 0 && dres.len <= 20);
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ... continueAt is zero if no resteer requested ... */
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC)
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(dres.continueAt == 0);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ... if we disallowed conditional resteers, check that one
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             didn't actually happen anyway ... */
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (n_cond_resteers_allowed == 0)
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(dres.whatNext != Dis_ResteerC);
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fill in the insn-mark length field. */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imark = irsb->stmts[first_stmt_idx];
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(imark);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(imark->tag == Ist_IMark);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(imark->Ist.IMark.len == 0);
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      imark->Ist.IMark.len = toUInt(dres.len);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Print the resulting IR, if needed. */
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vex_traceflags & VEX_TRACE_FE) {
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = first_stmt_idx; i < irsb->stmts_used; i++) {
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("              ");
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRStmt(irsb->stmts[i]);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("\n");
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If dis_instr_fn terminated the BB at this point, check it
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         also filled in the irsb->next field. */
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dres.whatNext == Dis_StopHere) {
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(irsb->next != NULL);
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (debug_print) {
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("              ");
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf( "goto {");
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRJumpKind(irsb->jumpkind);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf( "} ");
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppIRExpr( irsb->next );
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf( "\n");
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Update the VexGuestExtents we are constructing. */
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If vex_control.guest_max_insns is required to be < 100 and
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         each insn is at max 20 bytes long, this limit of 5000 then
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         seems reasonable since the max possible extent length will be
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         100 * 20 == 2000. */
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(vge->len[vge->n_used-1] < 5000);
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vge->len[vge->n_used-1]
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_instrs++;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (debug_print)
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("\n");
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Advance delta (inconspicuous but very important :-) */
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delta += (Long)dres.len;
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (dres.whatNext) {
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Dis_Continue:
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(irsb->next == NULL);
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (n_instrs < vex_control.guest_max_insns) {
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* keep going */
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* We have to stop. */
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               irsb->next
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  = IRExpr_Const(
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       guest_word_type == Ity_I32
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          ? IRConst_U32(toUInt(guest_IP_bbstart+delta))
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          : IRConst_U64(guest_IP_bbstart+delta)
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    );
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               goto done;
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Dis_StopHere:
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(irsb->next != NULL);
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto done;
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Dis_ResteerU:
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Dis_ResteerC:
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Check that we actually allowed a resteer .. */
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(resteerOK);
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(irsb->next == NULL);
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (dres.whatNext == Dis_ResteerC) {
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               vassert(n_cond_resteers_allowed > 0);
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               n_cond_resteers_allowed--;
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* figure out a new delta to continue at. */
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(resteerOKfn(callback_opaque,dres.continueAt));
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta = dres.continueAt - guest_IP_bbstart;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* we now have to start a new extent slot. */
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vge->n_used++;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(vge->n_used <= 3);
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vge->base[vge->n_used-1] = dres.continueAt;
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vge->len[vge->n_used-1] = 0;
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            n_resteers++;
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            d_resteers++;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0 && (n_resteers & 0xFF) == 0)
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       n_resteers, d_resteers,
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       dres.continueAt, delta);
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vpanic("bb_to_IR");
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(0);
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  done:
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We're done.  The only thing that might need attending to is that
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a self-checking preamble may need to be created.
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The scheme is to compute a rather crude checksum of the code
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we're making a translation of, and add to the IR a call to a
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helper routine which recomputes the checksum every time the
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      translation is run, and requests a retranslation if it doesn't
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      match.  This is obviously very expensive and considerable
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      efforts are made to speed it up:
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * the checksum is computed from all the 32-bit words that
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        overlap the translated code.  That means it could depend on up
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        to 3 bytes before and 3 bytes after which aren't part of the
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        translated area, and so if those change then we'll
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        unnecessarily have to discard and retranslate.  This seems
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        like a pretty remote possibility and it seems as if the
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        benefit of not having to deal with the ends of the range at
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        byte precision far outweigh any possible extra translations
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        needed.
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      * there's a generic routine and 12 specialised cases, which
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        handle the cases of 1 through 12-word lengths respectively.
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        They seem to cover about 90% of the cases that occur in
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        practice.
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_self_check) {
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt     len2check, expected32;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   tistart_tmp, tilen_tmp;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt     (*fn_generic)(HWord, HWord) __attribute__((regparm(2)));
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt     (*fn_spec)(HWord) __attribute__((regparm(1)));
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar*   nm_generic;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar*   nm_spec;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord    fn_generic_entry = 0;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord    fn_spec_entry = 0;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(vge->n_used == 1);
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      len2check = vge->len[0];
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* stay sane */
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Skip the check if the translation involved zero bytes */
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (len2check > 0) {
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HWord first_w32 = ((HWord)guest_code) & ~(HWord)3;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HWord last_w32  = (((HWord)guest_code) + len2check - 1) & ~(HWord)3;
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(first_w32 <= last_w32);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HWord w32_diff = last_w32 - first_w32;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(0 == (w32_diff & 3));
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HWord w32s_to_check = (w32_diff + 4) / 4;
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(w32s_to_check > 0 && w32s_to_check < 1004/*arbitrary*//4);
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* vex_printf("%lx %lx  %ld\n", first_w32, last_w32, w32s_to_check); */
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fn_generic =  genericg_compute_checksum_4al;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nm_generic = "genericg_compute_checksum_4al";
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         fn_spec = NULL;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nm_spec = NULL;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (w32s_to_check) {
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 1:  fn_spec =  genericg_compute_checksum_4al_1;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_1"; break;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 2:  fn_spec =  genericg_compute_checksum_4al_2;
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_2"; break;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 3:  fn_spec =  genericg_compute_checksum_4al_3;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_3"; break;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 4:  fn_spec =  genericg_compute_checksum_4al_4;
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_4"; break;
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 5:  fn_spec =  genericg_compute_checksum_4al_5;
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_5"; break;
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 6:  fn_spec =  genericg_compute_checksum_4al_6;
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_6"; break;
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 7:  fn_spec =  genericg_compute_checksum_4al_7;
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_7"; break;
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 8:  fn_spec =  genericg_compute_checksum_4al_8;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_8"; break;
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 9:  fn_spec =  genericg_compute_checksum_4al_9;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_9"; break;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 10: fn_spec =  genericg_compute_checksum_4al_10;
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_10"; break;
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 11: fn_spec =  genericg_compute_checksum_4al_11;
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_11"; break;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             case 12: fn_spec =  genericg_compute_checksum_4al_12;
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      nm_spec = "genericg_compute_checksum_4al_12"; break;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             default: break;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         expected32 = fn_generic( first_w32, w32s_to_check );
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If we got a specialised version, check it produces the same
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            result as the generic version! */
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fn_spec) {
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(nm_spec);
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(expected32 == fn_spec( first_w32 ));
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vassert(!nm_spec);
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Set TISTART and TILEN.  These will describe to the despatcher
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the area of guest code to invalidate should we exit with a
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            self-check failure. */
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tilen_tmp   = newIRTemp(irsb->tyenv, guest_word_type);
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->stmts[selfcheck_idx+0]
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(guest_IP_bbstart_IRConst) );
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->stmts[selfcheck_idx+1]
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_WrTmp(tilen_tmp,
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           guest_word_type==Ity_I32
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ? IRExpr_Const(IRConst_U32(len2check))
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              : IRExpr_Const(IRConst_U64(len2check))
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->stmts[selfcheck_idx+2]
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_Put( offB_TISTART, IRExpr_RdTmp(tistart_tmp) );
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->stmts[selfcheck_idx+3]
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_Put( offB_TILEN, IRExpr_RdTmp(tilen_tmp) );
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Generate the entry point descriptors */
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (abiinfo_both->host_ppc_calls_use_fndescrs) {
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            HWord* descr = (HWord*)fn_generic;
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn_generic_entry = descr[0];
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fn_spec) {
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               descr = (HWord*)fn_spec;
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fn_spec_entry = descr[0];
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fn_spec_entry = (HWord)NULL;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            fn_generic_entry = (HWord)fn_generic;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (fn_spec) {
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fn_spec_entry = (HWord)fn_spec;
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               fn_spec_entry = (HWord)NULL;
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* callexpr = NULL;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (fn_spec) {
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            callexpr = mkIRExprCCall(
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Ity_I32, 1/*regparms*/,
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nm_spec, (void*)fn_spec_entry,
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkIRExprVec_1(
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkIRExpr_HWord( (HWord)first_w32 )
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       );
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            callexpr = mkIRExprCCall(
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Ity_I32, 2/*regparms*/,
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          nm_generic, (void*)fn_generic_entry,
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkIRExprVec_2(
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkIRExpr_HWord( (HWord)first_w32 ),
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkIRExpr_HWord( (HWord)w32s_to_check )
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          )
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       );
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->stmts[selfcheck_idx+4]
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            = IRStmt_Exit(
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Binop(
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    Iop_CmpNE32,
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    callexpr,
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    IRExpr_Const(IRConst_U32(expected32))
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 ),
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 Ijk_TInval,
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 guest_IP_bbstart_IRConst
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return irsb;
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*-------------------------------------------------------------
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A support routine for doing self-checking translations.
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  -------------------------------------------------------------*/
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CLEAN HELPER */
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CALLED FROM GENERATED CODE */
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Compute a checksum of host memory at [addr .. addr+len-1], as fast
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as possible.  The _4al_4plus version is assured that the request is
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for 4-aligned memory and for a block of 4 or more long, whilst the
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   _generic version must be able to handle any alignment, and lengths
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   down to zero too.  This fn is called once for every use of a
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   self-checking translation, so it needs to be as fast as
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   possible. */
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline UInt ROL32 ( UInt w, Int n ) {
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << n) | (w >> (32-n));
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute((regparm(2)))
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* unrolled */
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (n_w32s >= 4) {
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  w;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p += 4;
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_w32s -= 4;
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sum1 ^= sum2;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (n_w32s >= 1) {
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  w;
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p += 1;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n_w32s -= 1;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sum1 ^= sum2;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Specialised versions of the above function */
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_4 ( HWord first_w32 )
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[10]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((regparm(1)))
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  sum1 = 0, sum2 = 0;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt* p = (UInt*)first_w32;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  w;
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[0];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[1];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[2];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[3];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[4];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[5];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[6];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[7];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[8];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[9];  sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[10]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = p[11]; sum1 = ROL32(sum1 ^ w, 31);  sum2 += w;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sum1 ^= sum2;
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sum1 + sum2;
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                 guest_generic_bb_to_IR.c ---*/
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
823