blob: 38681207c1ebc56ca5ef6d3561c8a08ab91e7a4f [file] [log] [blame]
sewardj9e6491a2005-07-02 19:24:10 +00001
2/*--------------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin guest_generic_bb_to_IR.c ---*/
sewardj9e6491a2005-07-02 19:24:10 +00004/*--------------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardj9e6491a2005-07-02 19:24:10 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardj9e6491a2005-07-02 19:24:10 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardj9e6491a2005-07-02 19:24:10 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardj9e6491a2005-07-02 19:24:10 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardj9e6491a2005-07-02 19:24:10 +000034*/
35
36#include "libvex_basictypes.h"
37#include "libvex_ir.h"
38#include "libvex.h"
sewardjcef7d3e2009-07-02 12:21:59 +000039#include "main_util.h"
40#include "main_globals.h"
41#include "guest_generic_bb_to_IR.h"
sewardj9e6491a2005-07-02 19:24:10 +000042
43
sewardjdb4738a2005-07-07 01:32:16 +000044/* Forwards .. */
sewardj03d91142011-03-14 12:35:18 +000045VEX_REGPARM(2)
sewardj95819062010-02-18 23:01:26 +000046static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s );
sewardj03d91142011-03-14 12:35:18 +000047VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000048static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000049VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000050static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000051VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000052static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000053VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000054static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000055VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000056static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000057VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000058static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000059VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000060static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000061VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000062static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000063VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000064static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000065VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000066static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000067VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000068static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 );
sewardj03d91142011-03-14 12:35:18 +000069VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +000070static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 );
sewardjdb4738a2005-07-07 01:32:16 +000071
sewardj03d91142011-03-14 12:35:18 +000072VEX_REGPARM(2)
sewardjd6c17252011-01-10 15:08:41 +000073static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s );
sewardj03d91142011-03-14 12:35:18 +000074VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000075static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000076VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000077static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000078VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000079static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000080VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000081static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000082VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000083static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000084VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000085static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000086VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000087static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000088VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000089static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000090VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000091static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000092VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000093static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000094VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000095static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 );
sewardj03d91142011-03-14 12:35:18 +000096VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +000097static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 );
98
sewardjce02aa72006-01-12 12:27:58 +000099/* Small helpers */
sewardjc716aea2006-01-17 01:48:46 +0000100static Bool const_False ( void* callback_opaque, Addr64 a ) {
101 return False;
102}
sewardjdb4738a2005-07-07 01:32:16 +0000103
sewardjce02aa72006-01-12 12:27:58 +0000104/* Disassemble a complete basic block, starting at guest_IP_start,
sewardjf6c8ebf2007-02-06 01:52:52 +0000105 returning a new IRSB. The disassembler may chase across basic
sewardj9e6491a2005-07-02 19:24:10 +0000106 block boundaries if it wishes and if chase_into_ok allows it.
107 The precise guest address ranges from which code has been taken
cerion36d982b2006-01-02 14:09:16 +0000108 are written into vge. guest_IP_bbstart is taken to be the IP in
sewardj9e6491a2005-07-02 19:24:10 +0000109 the guest's address space corresponding to the instruction at
110 &guest_code[0].
111
112 dis_instr_fn is the arch-specific fn to disassemble on function; it
113 is this that does the real work.
sewardjdb4738a2005-07-07 01:32:16 +0000114
sewardjbc161a42011-06-07 21:28:38 +0000115 needs_self_check is a callback used to ask the caller which of the
116 extents, if any, a self check is required for. The returned value
117 is a bitmask with a 1 in position i indicating that the i'th extent
118 needs a check. Since there can be at most 3 extents, the returned
119 values must be between 0 and 7.
120
121 The number of extents which did get a self check (0 to 3) is put in
122 n_sc_extents. The caller already knows this because it told us
123 which extents to add checks for, via the needs_self_check callback,
124 but we ship the number back out here for the caller's convenience.
sewardjdb4738a2005-07-07 01:32:16 +0000125
sewardjc716aea2006-01-17 01:48:46 +0000126 preamble_function is a callback which allows the caller to add
127 its own IR preamble (following the self-check, if any). May be
sewardjf6c8ebf2007-02-06 01:52:52 +0000128 NULL. If non-NULL, the IRSB under construction is handed to
sewardjc716aea2006-01-17 01:48:46 +0000129 this function, which presumably adds IR statements to it. The
130 callback may optionally complete the block and direct bb_to_IR
131 not to disassemble any instructions into it; this is indicated
132 by the callback returning True.
sewardj9e6491a2005-07-02 19:24:10 +0000133
sewardj05f5e012014-05-04 10:52:11 +0000134 offB_CMADDR and offB_CMLEN are the offsets of guest_CMADDR and
135 guest_CMLEN. Since this routine has to work for any guest state,
sewardjc716aea2006-01-17 01:48:46 +0000136 without knowing what it is, those offsets have to passed in.
137
138 callback_opaque is a caller-supplied pointer to data which the
139 callbacks may want to see. Vex has no idea what it is.
140 (In fact it's a VgInstrumentClosure.)
sewardjce02aa72006-01-12 12:27:58 +0000141*/
sewardj9e6491a2005-07-02 19:24:10 +0000142
sewardjc6f970f2012-04-02 21:54:49 +0000143/* Regarding IP updating. dis_instr_fn (that does the guest specific
144 work of disassembling an individual instruction) must finish the
145 resulting IR with "PUT(guest_IP) = ". Hence in all cases it must
146 state the next instruction address.
147
148 If the block is to be ended at that point, then this routine
149 (bb_to_IR) will set up the next/jumpkind/offsIP fields so as to
150 make a transfer (of the right kind) to "GET(guest_IP)". Hence if
151 dis_instr_fn generates incorrect IP updates we will see it
152 immediately (due to jumping to the wrong next guest address).
153
154 However it is also necessary to set this up so it can be optimised
155 nicely. The IRSB exit is defined to update the guest IP, so that
156 chaining works -- since the chain_me stubs expect the chain-to
157 address to be in the guest state. Hence what the IRSB next fields
158 will contain initially is (implicitly)
159
160 PUT(guest_IP) [implicitly] = GET(guest_IP) [explicit expr on ::next]
161
162 which looks pretty strange at first. Eg so unconditional branch
163 to some address 0x123456 looks like this:
164
165 PUT(guest_IP) = 0x123456; // dis_instr_fn generates this
166 // the exit
167 PUT(guest_IP) [implicitly] = GET(guest_IP); exit-Boring
168
169 after redundant-GET and -PUT removal by iropt, we get what we want:
170
171 // the exit
172 PUT(guest_IP) [implicitly] = 0x123456; exit-Boring
173
174 This makes the IRSB-end case the same as the side-exit case: update
175 IP, then transfer. There is no redundancy of representation for
176 the destination, and we use the destination specified by
177 dis_instr_fn, so any errors it makes show up sooner.
178*/
179
sewardjbc161a42011-06-07 21:28:38 +0000180IRSB* bb_to_IR (
181 /*OUT*/VexGuestExtents* vge,
182 /*OUT*/UInt* n_sc_extents,
sewardjfadbbe22012-04-24 11:49:03 +0000183 /*OUT*/UInt* n_guest_instrs, /* stats only */
sewardjbc161a42011-06-07 21:28:38 +0000184 /*IN*/ void* callback_opaque,
185 /*IN*/ DisOneInstrFn dis_instr_fn,
florian8462d112014-09-24 15:18:09 +0000186 /*IN*/ const UChar* guest_code,
sewardjbc161a42011-06-07 21:28:38 +0000187 /*IN*/ Addr64 guest_IP_bbstart,
188 /*IN*/ Bool (*chase_into_ok)(void*,Addr64),
sewardj9b769162014-07-24 12:42:03 +0000189 /*IN*/ VexEndness host_endness,
sewardj442e51a2012-12-06 18:08:04 +0000190 /*IN*/ Bool sigill_diag,
sewardjbc161a42011-06-07 21:28:38 +0000191 /*IN*/ VexArch arch_guest,
192 /*IN*/ VexArchInfo* archinfo_guest,
193 /*IN*/ VexAbiInfo* abiinfo_both,
194 /*IN*/ IRType guest_word_type,
florian0a5494e2014-09-24 12:00:49 +0000195 /*IN*/ UInt (*needs_self_check)(void*,const VexGuestExtents*),
sewardjbc161a42011-06-07 21:28:38 +0000196 /*IN*/ Bool (*preamble_function)(void*,IRSB*),
sewardj05f5e012014-05-04 10:52:11 +0000197 /*IN*/ Int offB_GUEST_CMSTART,
198 /*IN*/ Int offB_GUEST_CMLEN,
sewardjc6f970f2012-04-02 21:54:49 +0000199 /*IN*/ Int offB_GUEST_IP,
200 /*IN*/ Int szB_GUEST_IP
sewardjbc161a42011-06-07 21:28:38 +0000201 )
sewardj9e6491a2005-07-02 19:24:10 +0000202{
203 Long delta;
204 Int i, n_instrs, first_stmt_idx;
sewardjc6f970f2012-04-02 21:54:49 +0000205 Bool resteerOK, debug_print;
sewardj9e6491a2005-07-02 19:24:10 +0000206 DisResult dres;
207 IRStmt* imark;
sewardjbc161a42011-06-07 21:28:38 +0000208 IRStmt* nop;
sewardj9e6491a2005-07-02 19:24:10 +0000209 static Int n_resteers = 0;
210 Int d_resteers = 0;
sewardjdb4738a2005-07-07 01:32:16 +0000211 Int selfcheck_idx = 0;
sewardjdd40fdf2006-12-24 02:20:24 +0000212 IRSB* irsb;
sewardj9e6491a2005-07-02 19:24:10 +0000213 Addr64 guest_IP_curr_instr;
sewardjce02aa72006-01-12 12:27:58 +0000214 IRConst* guest_IP_bbstart_IRConst = NULL;
sewardj984d9b12010-01-15 10:53:21 +0000215 Int n_cond_resteers_allowed = 2;
sewardj9e6491a2005-07-02 19:24:10 +0000216
sewardjc716aea2006-01-17 01:48:46 +0000217 Bool (*resteerOKfn)(void*,Addr64) = NULL;
sewardj9e6491a2005-07-02 19:24:10 +0000218
219 debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
220
221 /* check sanity .. */
sewardjdb4738a2005-07-07 01:32:16 +0000222 vassert(sizeof(HWord) == sizeof(void*));
sewardj9e6491a2005-07-02 19:24:10 +0000223 vassert(vex_control.guest_max_insns >= 1);
sewardjdb4738a2005-07-07 01:32:16 +0000224 vassert(vex_control.guest_max_insns < 100);
sewardj9e6491a2005-07-02 19:24:10 +0000225 vassert(vex_control.guest_chase_thresh >= 0);
226 vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
227 vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);
228
sewardjc6f970f2012-04-02 21:54:49 +0000229 if (guest_word_type == Ity_I32) {
230 vassert(szB_GUEST_IP == 4);
231 vassert((offB_GUEST_IP % 4) == 0);
232 } else {
233 vassert(szB_GUEST_IP == 8);
234 vassert((offB_GUEST_IP % 8) == 0);
235 }
236
sewardj9e6491a2005-07-02 19:24:10 +0000237 /* Start a new, empty extent. */
238 vge->n_used = 1;
239 vge->base[0] = guest_IP_bbstart;
240 vge->len[0] = 0;
sewardjbc161a42011-06-07 21:28:38 +0000241 *n_sc_extents = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000242
sewardjdd40fdf2006-12-24 02:20:24 +0000243 /* And a new IR superblock to dump the result into. */
244 irsb = emptyIRSB();
sewardj9e6491a2005-07-02 19:24:10 +0000245
246 /* Delta keeps track of how far along the guest_code array we have
247 so far gone. */
248 delta = 0;
249 n_instrs = 0;
sewardjfadbbe22012-04-24 11:49:03 +0000250 *n_guest_instrs = 0;
sewardj9e6491a2005-07-02 19:24:10 +0000251
sewardjbc161a42011-06-07 21:28:38 +0000252 /* Guest addresses as IRConsts. Used in self-checks to specify the
253 restart-after-discard point. */
254 guest_IP_bbstart_IRConst
255 = guest_word_type==Ity_I32
256 ? IRConst_U32(toUInt(guest_IP_bbstart))
257 : IRConst_U64(guest_IP_bbstart);
sewardjce02aa72006-01-12 12:27:58 +0000258
sewardjbc161a42011-06-07 21:28:38 +0000259 /* Leave 15 spaces in which to put the check statements for a self
260 checking translation (up to 3 extents, and 5 stmts required for
261 each). We won't know until later the extents and checksums of
262 the areas, if any, that need to be checked. */
263 nop = IRStmt_NoOp();
264 selfcheck_idx = irsb->stmts_used;
265 for (i = 0; i < 3 * 5; i++)
266 addStmtToIRSB( irsb, nop );
sewardjdb4738a2005-07-07 01:32:16 +0000267
sewardjc716aea2006-01-17 01:48:46 +0000268 /* If the caller supplied a function to add its own preamble, use
269 it now. */
270 if (preamble_function) {
sewardjdd40fdf2006-12-24 02:20:24 +0000271 Bool stopNow = preamble_function( callback_opaque, irsb );
sewardjc716aea2006-01-17 01:48:46 +0000272 if (stopNow) {
273 /* The callback has completed the IR block without any guest
274 insns being disassembled into it, so just return it at
275 this point, even if a self-check was requested - as there
sewardjbc161a42011-06-07 21:28:38 +0000276 is nothing to self-check. The 15 self-check no-ops will
sewardjc716aea2006-01-17 01:48:46 +0000277 still be in place, but they are harmless. */
sewardjdd40fdf2006-12-24 02:20:24 +0000278 return irsb;
sewardjc716aea2006-01-17 01:48:46 +0000279 }
sewardjce02aa72006-01-12 12:27:58 +0000280 }
281
sewardjdb4738a2005-07-07 01:32:16 +0000282 /* Process instructions. */
sewardj9e6491a2005-07-02 19:24:10 +0000283 while (True) {
284 vassert(n_instrs < vex_control.guest_max_insns);
285
286 /* Regardless of what chase_into_ok says, is chasing permissible
287 at all right now? Set resteerOKfn accordingly. */
288 resteerOK
289 = toBool(
290 n_instrs < vex_control.guest_chase_thresh
291 /* we can't afford to have a resteer once we're on the
292 last extent slot. */
293 && vge->n_used < 3
294 );
295
296 resteerOKfn
297 = resteerOK ? chase_into_ok : const_False;
298
sewardj984d9b12010-01-15 10:53:21 +0000299 /* n_cond_resteers_allowed keeps track of whether we're still
300 allowing dis_instr_fn to chase conditional branches. It
301 starts (at 2) and gets decremented each time dis_instr_fn
302 tells us it has chased a conditional branch. We then
303 decrement it, and use it to tell later calls to dis_instr_fn
304 whether or not it is allowed to chase conditional
305 branches. */
306 vassert(n_cond_resteers_allowed >= 0 && n_cond_resteers_allowed <= 2);
307
sewardj9e6491a2005-07-02 19:24:10 +0000308 /* This is the IP of the instruction we're just about to deal
309 with. */
310 guest_IP_curr_instr = guest_IP_bbstart + delta;
311
sewardjdd40fdf2006-12-24 02:20:24 +0000312 /* This is the irsb statement array index of the first stmt in
sewardj9e6491a2005-07-02 19:24:10 +0000313 this insn. That will always be the instruction-mark
314 descriptor. */
sewardjdd40fdf2006-12-24 02:20:24 +0000315 first_stmt_idx = irsb->stmts_used;
sewardj9e6491a2005-07-02 19:24:10 +0000316
317 /* Add an instruction-mark statement. We won't know until after
318 disassembling the instruction how long it instruction is, so
sewardj31763862011-05-11 14:17:35 +0000319 just put in a zero length and we'll fix it up later.
320
321 On ARM, the least significant bit of the instr address
322 distinguishes ARM vs Thumb instructions. All instructions
323 actually start on at least 2-aligned addresses. So we need
324 to ignore the bottom bit of the insn address when forming the
sewardj2f10aa62011-05-27 13:20:56 +0000325 IMark's address field, but put that bottom bit in the delta
326 field, so that comparisons against guest_R15T for Thumb can
327 be done correctly. By inspecting the delta field,
328 instruction processors can determine whether the instruction
329 was originally Thumb or ARM. For more details of this
330 convention, see comments on definition of guest_R15T in
331 libvex_guest_arm.h. */
332 if (arch_guest == VexArchARM && (guest_IP_curr_instr & (Addr64)1)) {
333 /* Thumb insn => mask out the T bit, but put it in delta */
334 addStmtToIRSB( irsb,
335 IRStmt_IMark(guest_IP_curr_instr & ~(Addr64)1,
336 0, /* len */
337 1 /* delta */
338 )
339 );
340 } else {
341 /* All other targets: store IP as-is, and set delta to zero. */
342 addStmtToIRSB( irsb,
343 IRStmt_IMark(guest_IP_curr_instr,
344 0, /* len */
345 0 /* delta */
346 )
347 );
348 }
sewardj9e6491a2005-07-02 19:24:10 +0000349
sewardjc6f970f2012-04-02 21:54:49 +0000350 if (debug_print && n_instrs > 0)
351 vex_printf("\n");
sewardj9e6491a2005-07-02 19:24:10 +0000352
353 /* Finally, actually disassemble an instruction. */
sewardjc6f970f2012-04-02 21:54:49 +0000354 vassert(irsb->next == NULL);
sewardjdd40fdf2006-12-24 02:20:24 +0000355 dres = dis_instr_fn ( irsb,
sewardj9e6491a2005-07-02 19:24:10 +0000356 resteerOKfn,
sewardj984d9b12010-01-15 10:53:21 +0000357 toBool(n_cond_resteers_allowed > 0),
sewardjc716aea2006-01-17 01:48:46 +0000358 callback_opaque,
sewardj9e6491a2005-07-02 19:24:10 +0000359 guest_code,
360 delta,
361 guest_IP_curr_instr,
sewardja5f55da2006-04-30 23:37:32 +0000362 arch_guest,
sewardj9e6491a2005-07-02 19:24:10 +0000363 archinfo_guest,
sewardjdd40fdf2006-12-24 02:20:24 +0000364 abiinfo_both,
sewardj9b769162014-07-24 12:42:03 +0000365 host_endness,
sewardj442e51a2012-12-06 18:08:04 +0000366 sigill_diag );
sewardj9e6491a2005-07-02 19:24:10 +0000367
368 /* stay sane ... */
369 vassert(dres.whatNext == Dis_StopHere
370 || dres.whatNext == Dis_Continue
sewardj984d9b12010-01-15 10:53:21 +0000371 || dres.whatNext == Dis_ResteerU
372 || dres.whatNext == Dis_ResteerC);
373 /* ... disassembled insn length is sane ... */
sewardjce02aa72006-01-12 12:27:58 +0000374 vassert(dres.len >= 0 && dres.len <= 20);
sewardj984d9b12010-01-15 10:53:21 +0000375 /* ... continueAt is zero if no resteer requested ... */
376 if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC)
sewardj9e6491a2005-07-02 19:24:10 +0000377 vassert(dres.continueAt == 0);
sewardj984d9b12010-01-15 10:53:21 +0000378 /* ... if we disallowed conditional resteers, check that one
379 didn't actually happen anyway ... */
380 if (n_cond_resteers_allowed == 0)
381 vassert(dres.whatNext != Dis_ResteerC);
sewardj9e6491a2005-07-02 19:24:10 +0000382
383 /* Fill in the insn-mark length field. */
sewardjdd40fdf2006-12-24 02:20:24 +0000384 vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
385 imark = irsb->stmts[first_stmt_idx];
sewardj9e6491a2005-07-02 19:24:10 +0000386 vassert(imark);
387 vassert(imark->tag == Ist_IMark);
388 vassert(imark->Ist.IMark.len == 0);
389 imark->Ist.IMark.len = toUInt(dres.len);
390
391 /* Print the resulting IR, if needed. */
392 if (vex_traceflags & VEX_TRACE_FE) {
sewardjdd40fdf2006-12-24 02:20:24 +0000393 for (i = first_stmt_idx; i < irsb->stmts_used; i++) {
sewardj9e6491a2005-07-02 19:24:10 +0000394 vex_printf(" ");
sewardjdd40fdf2006-12-24 02:20:24 +0000395 ppIRStmt(irsb->stmts[i]);
sewardj9e6491a2005-07-02 19:24:10 +0000396 vex_printf("\n");
397 }
398 }
399
sewardjc6f970f2012-04-02 21:54:49 +0000400 /* Individual insn disassembly may not mess with irsb->next.
401 This function is the only place where it can be set. */
402 vassert(irsb->next == NULL);
403 vassert(irsb->jumpkind == Ijk_Boring);
404 vassert(irsb->offsIP == 0);
405
406 /* Individual insn disassembly must finish the IR for each
407 instruction with an assignment to the guest PC. */
408 vassert(first_stmt_idx < irsb->stmts_used);
409 /* it follows that irsb->stmts_used must be > 0 */
410 { IRStmt* st = irsb->stmts[irsb->stmts_used-1];
411 vassert(st);
412 vassert(st->tag == Ist_Put);
413 vassert(st->Ist.Put.offset == offB_GUEST_IP);
414 /* Really we should also check that the type of the Put'd data
415 == guest_word_type, but that's a bit expensive. */
sewardj9e6491a2005-07-02 19:24:10 +0000416 }
417
418 /* Update the VexGuestExtents we are constructing. */
sewardjdb4738a2005-07-07 01:32:16 +0000419 /* If vex_control.guest_max_insns is required to be < 100 and
sewardj5eaf82b2009-09-05 00:03:07 +0000420 each insn is at max 20 bytes long, this limit of 5000 then
421 seems reasonable since the max possible extent length will be
422 100 * 20 == 2000. */
sewardjdb4738a2005-07-07 01:32:16 +0000423 vassert(vge->len[vge->n_used-1] < 5000);
sewardj9e6491a2005-07-02 19:24:10 +0000424 vge->len[vge->n_used-1]
425 = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
426 n_instrs++;
sewardj9e6491a2005-07-02 19:24:10 +0000427
428 /* Advance delta (inconspicuous but very important :-) */
429 delta += (Long)dres.len;
430
431 switch (dres.whatNext) {
432 case Dis_Continue:
sewardjc6f970f2012-04-02 21:54:49 +0000433 vassert(dres.continueAt == 0);
434 vassert(dres.jk_StopHere == Ijk_INVALID);
sewardj9e6491a2005-07-02 19:24:10 +0000435 if (n_instrs < vex_control.guest_max_insns) {
436 /* keep going */
437 } else {
sewardjc6f970f2012-04-02 21:54:49 +0000438 /* We have to stop. See comment above re irsb field
439 settings here. */
440 irsb->next = IRExpr_Get(offB_GUEST_IP, guest_word_type);
441 /* irsb->jumpkind must already by Ijk_Boring */
442 irsb->offsIP = offB_GUEST_IP;
sewardjdb4738a2005-07-07 01:32:16 +0000443 goto done;
sewardj9e6491a2005-07-02 19:24:10 +0000444 }
445 break;
446 case Dis_StopHere:
sewardjc6f970f2012-04-02 21:54:49 +0000447 vassert(dres.continueAt == 0);
448 vassert(dres.jk_StopHere != Ijk_INVALID);
449 /* See comment above re irsb field settings here. */
450 irsb->next = IRExpr_Get(offB_GUEST_IP, guest_word_type);
451 irsb->jumpkind = dres.jk_StopHere;
452 irsb->offsIP = offB_GUEST_IP;
sewardjdb4738a2005-07-07 01:32:16 +0000453 goto done;
sewardjc6f970f2012-04-02 21:54:49 +0000454
sewardj984d9b12010-01-15 10:53:21 +0000455 case Dis_ResteerU:
456 case Dis_ResteerC:
sewardj9e6491a2005-07-02 19:24:10 +0000457 /* Check that we actually allowed a resteer .. */
458 vassert(resteerOK);
sewardj984d9b12010-01-15 10:53:21 +0000459 if (dres.whatNext == Dis_ResteerC) {
460 vassert(n_cond_resteers_allowed > 0);
461 n_cond_resteers_allowed--;
462 }
sewardj9e6491a2005-07-02 19:24:10 +0000463 /* figure out a new delta to continue at. */
sewardjc716aea2006-01-17 01:48:46 +0000464 vassert(resteerOKfn(callback_opaque,dres.continueAt));
sewardj9e6491a2005-07-02 19:24:10 +0000465 delta = dres.continueAt - guest_IP_bbstart;
466 /* we now have to start a new extent slot. */
cerion92b64362005-12-13 12:02:26 +0000467 vge->n_used++;
468 vassert(vge->n_used <= 3);
sewardj9e6491a2005-07-02 19:24:10 +0000469 vge->base[vge->n_used-1] = dres.continueAt;
470 vge->len[vge->n_used-1] = 0;
471 n_resteers++;
472 d_resteers++;
473 if (0 && (n_resteers & 0xFF) == 0)
474 vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
475 n_resteers, d_resteers,
476 dres.continueAt, delta);
477 break;
478 default:
479 vpanic("bb_to_IR");
480 }
481 }
sewardjdb4738a2005-07-07 01:32:16 +0000482 /*NOTREACHED*/
483 vassert(0);
484
485 done:
486 /* We're done. The only thing that might need attending to is that
sewardjbc161a42011-06-07 21:28:38 +0000487 a self-checking preamble may need to be created. If so it gets
488 placed in the 15 slots reserved above.
sewardj95819062010-02-18 23:01:26 +0000489
490 The scheme is to compute a rather crude checksum of the code
491 we're making a translation of, and add to the IR a call to a
492 helper routine which recomputes the checksum every time the
493 translation is run, and requests a retranslation if it doesn't
494 match. This is obviously very expensive and considerable
495 efforts are made to speed it up:
496
sewardjbc161a42011-06-07 21:28:38 +0000497 * the checksum is computed from all the naturally aligned
498 host-sized words that overlap the translated code. That means
499 it could depend on up to 7 bytes before and 7 bytes after
500 which aren't part of the translated area, and so if those
501 change then we'll unnecessarily have to discard and
502 retranslate. This seems like a pretty remote possibility and
503 it seems as if the benefit of not having to deal with the ends
504 of the range at byte precision far outweigh any possible extra
505 translations needed.
sewardj95819062010-02-18 23:01:26 +0000506
507 * there's a generic routine and 12 specialised cases, which
508 handle the cases of 1 through 12-word lengths respectively.
509 They seem to cover about 90% of the cases that occur in
510 practice.
sewardjdb4738a2005-07-07 01:32:16 +0000511
sewardjbc161a42011-06-07 21:28:38 +0000512 We ask the caller, via needs_self_check, which of the 3 vge
513 extents needs a check, and only generate check code for those
514 that do.
515 */
516 {
sewardjd6c17252011-01-10 15:08:41 +0000517 Addr64 base2check;
518 UInt len2check;
519 HWord expectedhW;
sewardj16a403b2005-07-07 12:26:36 +0000520 IRTemp tistart_tmp, tilen_tmp;
sewardj03d91142011-03-14 12:35:18 +0000521 HWord VEX_REGPARM(2) (*fn_generic)(HWord, HWord);
522 HWord VEX_REGPARM(1) (*fn_spec)(HWord);
florian55085f82012-11-21 00:36:55 +0000523 const HChar* nm_generic;
524 const HChar* nm_spec;
sewardj95819062010-02-18 23:01:26 +0000525 HWord fn_generic_entry = 0;
526 HWord fn_spec_entry = 0;
sewardjd6c17252011-01-10 15:08:41 +0000527 UInt host_word_szB = sizeof(HWord);
528 IRType host_word_type = Ity_INVALID;
sewardjdb4738a2005-07-07 01:32:16 +0000529
sewardjbc161a42011-06-07 21:28:38 +0000530 VexGuestExtents vge_tmp = *vge;
531 UInt extents_needing_check
532 = needs_self_check(callback_opaque, &vge_tmp);
533
sewardjd6c17252011-01-10 15:08:41 +0000534 if (host_word_szB == 4) host_word_type = Ity_I32;
535 if (host_word_szB == 8) host_word_type = Ity_I64;
536 vassert(host_word_type != Ity_INVALID);
sewardjdb4738a2005-07-07 01:32:16 +0000537
sewardjd6c17252011-01-10 15:08:41 +0000538 vassert(vge->n_used >= 1 && vge->n_used <= 3);
sewardjbc161a42011-06-07 21:28:38 +0000539
540 /* Caller shouldn't claim that nonexistent extents need a
541 check. */
542 vassert((extents_needing_check >> vge->n_used) == 0);
543
sewardjd6c17252011-01-10 15:08:41 +0000544 for (i = 0; i < vge->n_used; i++) {
sewardjdb4738a2005-07-07 01:32:16 +0000545
sewardjbc161a42011-06-07 21:28:38 +0000546 /* Do we need to generate a check for this extent? */
547 if ((extents_needing_check & (1 << i)) == 0)
548 continue;
549
550 /* Tell the caller */
551 (*n_sc_extents)++;
552
sewardjd6c17252011-01-10 15:08:41 +0000553 /* the extent we're generating a check for */
554 base2check = vge->base[i];
555 len2check = vge->len[i];
556
557 /* stay sane */
558 vassert(len2check >= 0 && len2check < 1000/*arbitrary*/);
559
560 /* Skip the check if the translation involved zero bytes */
561 if (len2check == 0)
562 continue;
563
564 HWord first_hW = ((HWord)base2check)
565 & ~(HWord)(host_word_szB-1);
566 HWord last_hW = (((HWord)base2check) + len2check - 1)
567 & ~(HWord)(host_word_szB-1);
568 vassert(first_hW <= last_hW);
569 HWord hW_diff = last_hW - first_hW;
570 vassert(0 == (hW_diff & (host_word_szB-1)));
571 HWord hWs_to_check = (hW_diff + host_word_szB) / host_word_szB;
572 vassert(hWs_to_check > 0
573 && hWs_to_check < 1004/*arbitrary*/ / host_word_szB);
sewardjdb4738a2005-07-07 01:32:16 +0000574
sewardjbc161a42011-06-07 21:28:38 +0000575 /* vex_printf("%lx %lx %ld\n", first_hW, last_hW, hWs_to_check); */
sewardj16a403b2005-07-07 12:26:36 +0000576
sewardjd6c17252011-01-10 15:08:41 +0000577 if (host_word_szB == 8) {
sewardj03d91142011-03-14 12:35:18 +0000578 fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord))
sewardjd6c17252011-01-10 15:08:41 +0000579 genericg_compute_checksum_8al;
580 nm_generic = "genericg_compute_checksum_8al";
581 } else {
sewardj03d91142011-03-14 12:35:18 +0000582 fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord))
sewardjd6c17252011-01-10 15:08:41 +0000583 genericg_compute_checksum_4al;
584 nm_generic = "genericg_compute_checksum_4al";
585 }
586
sewardj95819062010-02-18 23:01:26 +0000587 fn_spec = NULL;
588 nm_spec = NULL;
sewardjdb4738a2005-07-07 01:32:16 +0000589
sewardjd6c17252011-01-10 15:08:41 +0000590 if (host_word_szB == 8) {
florian55085f82012-11-21 00:36:55 +0000591 const HChar* nm = NULL;
sewardj03d91142011-03-14 12:35:18 +0000592 ULong VEX_REGPARM(1) (*fn)(HWord) = NULL;
sewardjd6c17252011-01-10 15:08:41 +0000593 switch (hWs_to_check) {
594 case 1: fn = genericg_compute_checksum_8al_1;
595 nm = "genericg_compute_checksum_8al_1"; break;
596 case 2: fn = genericg_compute_checksum_8al_2;
597 nm = "genericg_compute_checksum_8al_2"; break;
598 case 3: fn = genericg_compute_checksum_8al_3;
599 nm = "genericg_compute_checksum_8al_3"; break;
600 case 4: fn = genericg_compute_checksum_8al_4;
601 nm = "genericg_compute_checksum_8al_4"; break;
602 case 5: fn = genericg_compute_checksum_8al_5;
603 nm = "genericg_compute_checksum_8al_5"; break;
604 case 6: fn = genericg_compute_checksum_8al_6;
605 nm = "genericg_compute_checksum_8al_6"; break;
606 case 7: fn = genericg_compute_checksum_8al_7;
607 nm = "genericg_compute_checksum_8al_7"; break;
608 case 8: fn = genericg_compute_checksum_8al_8;
609 nm = "genericg_compute_checksum_8al_8"; break;
610 case 9: fn = genericg_compute_checksum_8al_9;
611 nm = "genericg_compute_checksum_8al_9"; break;
612 case 10: fn = genericg_compute_checksum_8al_10;
613 nm = "genericg_compute_checksum_8al_10"; break;
614 case 11: fn = genericg_compute_checksum_8al_11;
615 nm = "genericg_compute_checksum_8al_11"; break;
616 case 12: fn = genericg_compute_checksum_8al_12;
617 nm = "genericg_compute_checksum_8al_12"; break;
618 default: break;
619 }
sewardj03d91142011-03-14 12:35:18 +0000620 fn_spec = (VEX_REGPARM(1) HWord(*)(HWord)) fn;
sewardjd6c17252011-01-10 15:08:41 +0000621 nm_spec = nm;
622 } else {
florian55085f82012-11-21 00:36:55 +0000623 const HChar* nm = NULL;
sewardj03d91142011-03-14 12:35:18 +0000624 UInt VEX_REGPARM(1) (*fn)(HWord) = NULL;
sewardjd6c17252011-01-10 15:08:41 +0000625 switch (hWs_to_check) {
626 case 1: fn = genericg_compute_checksum_4al_1;
627 nm = "genericg_compute_checksum_4al_1"; break;
628 case 2: fn = genericg_compute_checksum_4al_2;
629 nm = "genericg_compute_checksum_4al_2"; break;
630 case 3: fn = genericg_compute_checksum_4al_3;
631 nm = "genericg_compute_checksum_4al_3"; break;
632 case 4: fn = genericg_compute_checksum_4al_4;
633 nm = "genericg_compute_checksum_4al_4"; break;
634 case 5: fn = genericg_compute_checksum_4al_5;
635 nm = "genericg_compute_checksum_4al_5"; break;
636 case 6: fn = genericg_compute_checksum_4al_6;
637 nm = "genericg_compute_checksum_4al_6"; break;
638 case 7: fn = genericg_compute_checksum_4al_7;
639 nm = "genericg_compute_checksum_4al_7"; break;
640 case 8: fn = genericg_compute_checksum_4al_8;
641 nm = "genericg_compute_checksum_4al_8"; break;
642 case 9: fn = genericg_compute_checksum_4al_9;
643 nm = "genericg_compute_checksum_4al_9"; break;
644 case 10: fn = genericg_compute_checksum_4al_10;
645 nm = "genericg_compute_checksum_4al_10"; break;
646 case 11: fn = genericg_compute_checksum_4al_11;
647 nm = "genericg_compute_checksum_4al_11"; break;
648 case 12: fn = genericg_compute_checksum_4al_12;
649 nm = "genericg_compute_checksum_4al_12"; break;
650 default: break;
651 }
sewardj03d91142011-03-14 12:35:18 +0000652 fn_spec = (VEX_REGPARM(1) HWord(*)(HWord))fn;
sewardjd6c17252011-01-10 15:08:41 +0000653 nm_spec = nm;
sewardj95819062010-02-18 23:01:26 +0000654 }
sewardjdb4738a2005-07-07 01:32:16 +0000655
sewardjd6c17252011-01-10 15:08:41 +0000656 expectedhW = fn_generic( first_hW, hWs_to_check );
sewardj95819062010-02-18 23:01:26 +0000657 /* If we got a specialised version, check it produces the same
658 result as the generic version! */
659 if (fn_spec) {
660 vassert(nm_spec);
sewardjd6c17252011-01-10 15:08:41 +0000661 vassert(expectedhW == fn_spec( first_hW ));
sewardj95819062010-02-18 23:01:26 +0000662 } else {
663 vassert(!nm_spec);
664 }
sewardj16a403b2005-07-07 12:26:36 +0000665
sewardj05f5e012014-05-04 10:52:11 +0000666 /* Set CMSTART and CMLEN. These will describe to the despatcher
sewardj95819062010-02-18 23:01:26 +0000667 the area of guest code to invalidate should we exit with a
668 self-check failure. */
sewardj16a403b2005-07-07 12:26:36 +0000669
sewardj95819062010-02-18 23:01:26 +0000670 tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
671 tilen_tmp = newIRTemp(irsb->tyenv, guest_word_type);
sewardjaca070a2006-10-17 00:28:22 +0000672
sewardjd6c17252011-01-10 15:08:41 +0000673 IRConst* base2check_IRConst
674 = guest_word_type==Ity_I32 ? IRConst_U32(toUInt(base2check))
675 : IRConst_U64(base2check);
676 IRConst* len2check_IRConst
677 = guest_word_type==Ity_I32 ? IRConst_U32(len2check)
678 : IRConst_U64(len2check);
sewardj5eaf82b2009-09-05 00:03:07 +0000679
sewardjd6c17252011-01-10 15:08:41 +0000680 irsb->stmts[selfcheck_idx + i * 5 + 0]
681 = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) );
sewardj5eaf82b2009-09-05 00:03:07 +0000682
sewardjd6c17252011-01-10 15:08:41 +0000683 irsb->stmts[selfcheck_idx + i * 5 + 1]
684 = IRStmt_WrTmp(tilen_tmp, IRExpr_Const(len2check_IRConst) );
685
686 irsb->stmts[selfcheck_idx + i * 5 + 2]
sewardj05f5e012014-05-04 10:52:11 +0000687 = IRStmt_Put( offB_GUEST_CMSTART, IRExpr_RdTmp(tistart_tmp) );
sewardj95819062010-02-18 23:01:26 +0000688
sewardjd6c17252011-01-10 15:08:41 +0000689 irsb->stmts[selfcheck_idx + i * 5 + 3]
sewardj05f5e012014-05-04 10:52:11 +0000690 = IRStmt_Put( offB_GUEST_CMLEN, IRExpr_RdTmp(tilen_tmp) );
sewardj95819062010-02-18 23:01:26 +0000691
692 /* Generate the entry point descriptors */
693 if (abiinfo_both->host_ppc_calls_use_fndescrs) {
694 HWord* descr = (HWord*)fn_generic;
695 fn_generic_entry = descr[0];
696 if (fn_spec) {
697 descr = (HWord*)fn_spec;
698 fn_spec_entry = descr[0];
699 } else {
700 fn_spec_entry = (HWord)NULL;
701 }
702 } else {
703 fn_generic_entry = (HWord)fn_generic;
704 if (fn_spec) {
705 fn_spec_entry = (HWord)fn_spec;
706 } else {
707 fn_spec_entry = (HWord)NULL;
708 }
709 }
710
711 IRExpr* callexpr = NULL;
712 if (fn_spec) {
713 callexpr = mkIRExprCCall(
sewardjd6c17252011-01-10 15:08:41 +0000714 host_word_type, 1/*regparms*/,
sewardj95819062010-02-18 23:01:26 +0000715 nm_spec, (void*)fn_spec_entry,
716 mkIRExprVec_1(
sewardjd6c17252011-01-10 15:08:41 +0000717 mkIRExpr_HWord( (HWord)first_hW )
sewardj95819062010-02-18 23:01:26 +0000718 )
719 );
720 } else {
721 callexpr = mkIRExprCCall(
sewardjd6c17252011-01-10 15:08:41 +0000722 host_word_type, 2/*regparms*/,
sewardj95819062010-02-18 23:01:26 +0000723 nm_generic, (void*)fn_generic_entry,
724 mkIRExprVec_2(
sewardjd6c17252011-01-10 15:08:41 +0000725 mkIRExpr_HWord( (HWord)first_hW ),
726 mkIRExpr_HWord( (HWord)hWs_to_check )
sewardj95819062010-02-18 23:01:26 +0000727 )
728 );
729 }
730
sewardjd6c17252011-01-10 15:08:41 +0000731 irsb->stmts[selfcheck_idx + i * 5 + 4]
sewardj95819062010-02-18 23:01:26 +0000732 = IRStmt_Exit(
733 IRExpr_Binop(
sewardjd6c17252011-01-10 15:08:41 +0000734 host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32,
sewardj95819062010-02-18 23:01:26 +0000735 callexpr,
sewardjd6c17252011-01-10 15:08:41 +0000736 host_word_type==Ity_I64
737 ? IRExpr_Const(IRConst_U64(expectedhW))
738 : IRExpr_Const(IRConst_U32(expectedhW))
sewardj5eaf82b2009-09-05 00:03:07 +0000739 ),
sewardj05f5e012014-05-04 10:52:11 +0000740 Ijk_InvalICache,
sewardjd6c17252011-01-10 15:08:41 +0000741 /* Where we must restart if there's a failure: at the
742 first extent, regardless of which extent the
743 failure actually happened in. */
sewardjc6f970f2012-04-02 21:54:49 +0000744 guest_IP_bbstart_IRConst,
745 offB_GUEST_IP
sewardj95819062010-02-18 23:01:26 +0000746 );
sewardjbc161a42011-06-07 21:28:38 +0000747 } /* for (i = 0; i < vge->n_used; i++) */
sewardjdb4738a2005-07-07 01:32:16 +0000748 }
749
sewardjc6f970f2012-04-02 21:54:49 +0000750 /* irsb->next must now be set, since we've finished the block.
751 Print it if necessary.*/
752 vassert(irsb->next != NULL);
753 if (debug_print) {
754 vex_printf(" ");
755 vex_printf( "PUT(%d) = ", irsb->offsIP);
756 ppIRExpr( irsb->next );
757 vex_printf( "; exit-");
758 ppIRJumpKind(irsb->jumpkind);
759 vex_printf( "\n");
760 vex_printf( "\n");
761 }
762
sewardjfadbbe22012-04-24 11:49:03 +0000763 *n_guest_instrs = n_instrs;
sewardjdd40fdf2006-12-24 02:20:24 +0000764 return irsb;
sewardj9e6491a2005-07-02 19:24:10 +0000765}
766
767
sewardjdb4738a2005-07-07 01:32:16 +0000768/*-------------------------------------------------------------
769 A support routine for doing self-checking translations.
770 -------------------------------------------------------------*/
771
772/* CLEAN HELPER */
773/* CALLED FROM GENERATED CODE */
774
sewardj5eaf82b2009-09-05 00:03:07 +0000775/* Compute a checksum of host memory at [addr .. addr+len-1], as fast
sewardjd6c17252011-01-10 15:08:41 +0000776 as possible. All _4al versions assume that the supplied address is
777 4 aligned. All length values are in 4-byte chunks. These fns
778 arecalled once for every use of a self-checking translation, so
779 they needs to be as fast as possible. */
780
781/* --- 32-bit versions, used only on 32-bit hosts --- */
sewardj5eaf82b2009-09-05 00:03:07 +0000782
783static inline UInt ROL32 ( UInt w, Int n ) {
784 w = (w << n) | (w >> (32-n));
785 return w;
sewardjdb4738a2005-07-07 01:32:16 +0000786}
787
sewardj03d91142011-03-14 12:35:18 +0000788VEX_REGPARM(2)
sewardj95819062010-02-18 23:01:26 +0000789static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s )
sewardj5eaf82b2009-09-05 00:03:07 +0000790{
sewardj95819062010-02-18 23:01:26 +0000791 UInt sum1 = 0, sum2 = 0;
792 UInt* p = (UInt*)first_w32;
793 /* unrolled */
794 while (n_w32s >= 4) {
sewardj5eaf82b2009-09-05 00:03:07 +0000795 UInt w;
796 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
797 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
798 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
799 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
sewardj95819062010-02-18 23:01:26 +0000800 p += 4;
801 n_w32s -= 4;
sewardj5eaf82b2009-09-05 00:03:07 +0000802 sum1 ^= sum2;
803 }
sewardj95819062010-02-18 23:01:26 +0000804 while (n_w32s >= 1) {
805 UInt w;
806 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
807 p += 1;
808 n_w32s -= 1;
sewardj5eaf82b2009-09-05 00:03:07 +0000809 sum1 ^= sum2;
810 }
sewardj5eaf82b2009-09-05 00:03:07 +0000811 return sum1 + sum2;
812}
813
sewardj95819062010-02-18 23:01:26 +0000814/* Specialised versions of the above function */
815
sewardj03d91142011-03-14 12:35:18 +0000816VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000817static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 )
sewardj5eaf82b2009-09-05 00:03:07 +0000818{
sewardj95819062010-02-18 23:01:26 +0000819 UInt sum1 = 0, sum2 = 0;
820 UInt* p = (UInt*)first_w32;
821 UInt w;
822 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
823 sum1 ^= sum2;
824 return sum1 + sum2;
825}
826
sewardj03d91142011-03-14 12:35:18 +0000827VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000828static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 )
829{
830 UInt sum1 = 0, sum2 = 0;
831 UInt* p = (UInt*)first_w32;
832 UInt w;
833 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
834 sum1 ^= sum2;
835 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
836 sum1 ^= sum2;
837 return sum1 + sum2;
838}
839
sewardj03d91142011-03-14 12:35:18 +0000840VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000841static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 )
842{
843 UInt sum1 = 0, sum2 = 0;
844 UInt* p = (UInt*)first_w32;
845 UInt w;
846 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
847 sum1 ^= sum2;
848 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
849 sum1 ^= sum2;
850 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
851 sum1 ^= sum2;
852 return sum1 + sum2;
853}
854
sewardj03d91142011-03-14 12:35:18 +0000855VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000856static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 )
857{
858 UInt sum1 = 0, sum2 = 0;
859 UInt* p = (UInt*)first_w32;
860 UInt w;
861 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
862 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
863 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
864 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
865 sum1 ^= sum2;
866 return sum1 + sum2;
867}
868
sewardj03d91142011-03-14 12:35:18 +0000869VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000870static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 )
871{
872 UInt sum1 = 0, sum2 = 0;
873 UInt* p = (UInt*)first_w32;
874 UInt w;
875 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
876 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
877 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
878 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
879 sum1 ^= sum2;
880 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
881 sum1 ^= sum2;
882 return sum1 + sum2;
883}
884
sewardj03d91142011-03-14 12:35:18 +0000885VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000886static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 )
887{
888 UInt sum1 = 0, sum2 = 0;
889 UInt* p = (UInt*)first_w32;
890 UInt w;
891 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
892 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
893 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
894 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
895 sum1 ^= sum2;
896 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
897 sum1 ^= sum2;
898 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
899 sum1 ^= sum2;
900 return sum1 + sum2;
901}
902
sewardj03d91142011-03-14 12:35:18 +0000903VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000904static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 )
905{
906 UInt sum1 = 0, sum2 = 0;
907 UInt* p = (UInt*)first_w32;
908 UInt w;
909 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
910 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
911 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
912 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
913 sum1 ^= sum2;
914 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
915 sum1 ^= sum2;
916 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
917 sum1 ^= sum2;
918 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
919 sum1 ^= sum2;
920 return sum1 + sum2;
921}
922
sewardj03d91142011-03-14 12:35:18 +0000923VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000924static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 )
925{
926 UInt sum1 = 0, sum2 = 0;
927 UInt* p = (UInt*)first_w32;
928 UInt w;
929 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
930 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
931 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
932 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
933 sum1 ^= sum2;
934 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
935 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
936 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
937 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
938 sum1 ^= sum2;
939 return sum1 + sum2;
940}
941
sewardj03d91142011-03-14 12:35:18 +0000942VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000943static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 )
944{
945 UInt sum1 = 0, sum2 = 0;
946 UInt* p = (UInt*)first_w32;
947 UInt w;
948 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
949 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
950 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
951 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
952 sum1 ^= sum2;
953 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
954 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
955 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
956 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
957 sum1 ^= sum2;
958 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
959 sum1 ^= sum2;
960 return sum1 + sum2;
961}
962
sewardj03d91142011-03-14 12:35:18 +0000963VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000964static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 )
965{
966 UInt sum1 = 0, sum2 = 0;
967 UInt* p = (UInt*)first_w32;
968 UInt w;
969 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
970 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
971 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
972 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
973 sum1 ^= sum2;
974 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
975 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
976 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
977 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
978 sum1 ^= sum2;
979 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
980 sum1 ^= sum2;
981 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
982 sum1 ^= sum2;
983 return sum1 + sum2;
984}
985
sewardj03d91142011-03-14 12:35:18 +0000986VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +0000987static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 )
988{
989 UInt sum1 = 0, sum2 = 0;
990 UInt* p = (UInt*)first_w32;
991 UInt w;
992 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
993 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
994 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
995 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
996 sum1 ^= sum2;
997 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
998 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
999 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1000 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1001 sum1 ^= sum2;
1002 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1003 sum1 ^= sum2;
1004 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1005 sum1 ^= sum2;
1006 w = p[10]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1007 sum1 ^= sum2;
1008 return sum1 + sum2;
1009}
1010
sewardj03d91142011-03-14 12:35:18 +00001011VEX_REGPARM(1)
sewardj95819062010-02-18 23:01:26 +00001012static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 )
1013{
1014 UInt sum1 = 0, sum2 = 0;
1015 UInt* p = (UInt*)first_w32;
1016 UInt w;
1017 w = p[0]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1018 w = p[1]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1019 w = p[2]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1020 w = p[3]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1021 sum1 ^= sum2;
1022 w = p[4]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1023 w = p[5]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1024 w = p[6]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1025 w = p[7]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1026 sum1 ^= sum2;
1027 w = p[8]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1028 w = p[9]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1029 w = p[10]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1030 w = p[11]; sum1 = ROL32(sum1 ^ w, 31); sum2 += w;
1031 sum1 ^= sum2;
sewardj5eaf82b2009-09-05 00:03:07 +00001032 return sum1 + sum2;
1033}
sewardj9e6491a2005-07-02 19:24:10 +00001034
sewardjd6c17252011-01-10 15:08:41 +00001035
1036/* --- 64-bit versions, used only on 64-bit hosts --- */
1037
1038static inline ULong ROL64 ( ULong w, Int n ) {
1039 w = (w << n) | (w >> (64-n));
1040 return w;
1041}
1042
sewardj03d91142011-03-14 12:35:18 +00001043VEX_REGPARM(2)
sewardjd6c17252011-01-10 15:08:41 +00001044static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s )
1045{
1046 ULong sum1 = 0, sum2 = 0;
1047 ULong* p = (ULong*)first_w64;
1048 /* unrolled */
1049 while (n_w64s >= 4) {
1050 ULong w;
1051 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1052 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1053 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1054 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1055 p += 4;
1056 n_w64s -= 4;
1057 sum1 ^= sum2;
1058 }
1059 while (n_w64s >= 1) {
1060 ULong w;
1061 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1062 p += 1;
1063 n_w64s -= 1;
1064 sum1 ^= sum2;
1065 }
1066 return sum1 + sum2;
1067}
1068
1069/* Specialised versions of the above function */
1070
sewardj03d91142011-03-14 12:35:18 +00001071VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001072static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 )
1073{
1074 ULong sum1 = 0, sum2 = 0;
1075 ULong* p = (ULong*)first_w64;
1076 ULong w;
1077 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1078 sum1 ^= sum2;
1079 return sum1 + sum2;
1080}
1081
sewardj03d91142011-03-14 12:35:18 +00001082VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001083static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 )
1084{
1085 ULong sum1 = 0, sum2 = 0;
1086 ULong* p = (ULong*)first_w64;
1087 ULong w;
1088 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1089 sum1 ^= sum2;
1090 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1091 sum1 ^= sum2;
1092 return sum1 + sum2;
1093}
1094
sewardj03d91142011-03-14 12:35:18 +00001095VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001096static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 )
1097{
1098 ULong sum1 = 0, sum2 = 0;
1099 ULong* p = (ULong*)first_w64;
1100 ULong w;
1101 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1102 sum1 ^= sum2;
1103 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1104 sum1 ^= sum2;
1105 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1106 sum1 ^= sum2;
1107 return sum1 + sum2;
1108}
1109
sewardj03d91142011-03-14 12:35:18 +00001110VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001111static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 )
1112{
1113 ULong sum1 = 0, sum2 = 0;
1114 ULong* p = (ULong*)first_w64;
1115 ULong w;
1116 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1117 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1118 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1119 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1120 sum1 ^= sum2;
1121 return sum1 + sum2;
1122}
1123
sewardj03d91142011-03-14 12:35:18 +00001124VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001125static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 )
1126{
1127 ULong sum1 = 0, sum2 = 0;
1128 ULong* p = (ULong*)first_w64;
1129 ULong w;
1130 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1131 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1132 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1133 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1134 sum1 ^= sum2;
1135 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1136 sum1 ^= sum2;
1137 return sum1 + sum2;
1138}
1139
sewardj03d91142011-03-14 12:35:18 +00001140VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001141static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 )
1142{
1143 ULong sum1 = 0, sum2 = 0;
1144 ULong* p = (ULong*)first_w64;
1145 ULong w;
1146 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1147 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1148 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1149 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1150 sum1 ^= sum2;
1151 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1152 sum1 ^= sum2;
1153 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1154 sum1 ^= sum2;
1155 return sum1 + sum2;
1156}
1157
sewardj03d91142011-03-14 12:35:18 +00001158VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001159static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 )
1160{
1161 ULong sum1 = 0, sum2 = 0;
1162 ULong* p = (ULong*)first_w64;
1163 ULong w;
1164 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1165 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1166 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1167 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1168 sum1 ^= sum2;
1169 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1170 sum1 ^= sum2;
1171 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1172 sum1 ^= sum2;
1173 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1174 sum1 ^= sum2;
1175 return sum1 + sum2;
1176}
1177
sewardj03d91142011-03-14 12:35:18 +00001178VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001179static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 )
1180{
1181 ULong sum1 = 0, sum2 = 0;
1182 ULong* p = (ULong*)first_w64;
1183 ULong w;
1184 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1185 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1186 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1187 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1188 sum1 ^= sum2;
1189 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1190 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1191 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1192 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1193 sum1 ^= sum2;
1194 return sum1 + sum2;
1195}
1196
sewardj03d91142011-03-14 12:35:18 +00001197VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001198static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 )
1199{
1200 ULong sum1 = 0, sum2 = 0;
1201 ULong* p = (ULong*)first_w64;
1202 ULong w;
1203 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1204 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1205 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1206 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1207 sum1 ^= sum2;
1208 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1209 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1210 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1211 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1212 sum1 ^= sum2;
1213 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1214 sum1 ^= sum2;
1215 return sum1 + sum2;
1216}
1217
sewardj03d91142011-03-14 12:35:18 +00001218VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001219static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 )
1220{
1221 ULong sum1 = 0, sum2 = 0;
1222 ULong* p = (ULong*)first_w64;
1223 ULong w;
1224 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1225 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1226 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1227 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1228 sum1 ^= sum2;
1229 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1230 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1231 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1232 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1233 sum1 ^= sum2;
1234 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1235 sum1 ^= sum2;
1236 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1237 sum1 ^= sum2;
1238 return sum1 + sum2;
1239}
1240
sewardj03d91142011-03-14 12:35:18 +00001241VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001242static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 )
1243{
1244 ULong sum1 = 0, sum2 = 0;
1245 ULong* p = (ULong*)first_w64;
1246 ULong w;
1247 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1248 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1249 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1250 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1251 sum1 ^= sum2;
1252 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1253 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1254 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1255 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1256 sum1 ^= sum2;
1257 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1258 sum1 ^= sum2;
1259 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1260 sum1 ^= sum2;
1261 w = p[10]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1262 sum1 ^= sum2;
1263 return sum1 + sum2;
1264}
1265
sewardj03d91142011-03-14 12:35:18 +00001266VEX_REGPARM(1)
sewardjd6c17252011-01-10 15:08:41 +00001267static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 )
1268{
1269 ULong sum1 = 0, sum2 = 0;
1270 ULong* p = (ULong*)first_w64;
1271 ULong w;
1272 w = p[0]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1273 w = p[1]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1274 w = p[2]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1275 w = p[3]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1276 sum1 ^= sum2;
1277 w = p[4]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1278 w = p[5]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1279 w = p[6]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1280 w = p[7]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1281 sum1 ^= sum2;
1282 w = p[8]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1283 w = p[9]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1284 w = p[10]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1285 w = p[11]; sum1 = ROL64(sum1 ^ w, 63); sum2 += w;
1286 sum1 ^= sum2;
1287 return sum1 + sum2;
1288}
1289
sewardj9e6491a2005-07-02 19:24:10 +00001290/*--------------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00001291/*--- end guest_generic_bb_to_IR.c ---*/
sewardj9e6491a2005-07-02 19:24:10 +00001292/*--------------------------------------------------------------------*/