sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 3 | /*--- begin guest_generic_bb_to_IR.c ---*/ |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 9 | |
sewardj | 89ae847 | 2013-10-18 14:12:58 +0000 | [diff] [blame] | 10 | Copyright (C) 2004-2013 OpenWorks LLP |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 11 | info@open-works.net |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 12 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 13 | 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. |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 17 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 18 | 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 |
sewardj | 7bd6ffe | 2005-08-03 16:07:36 +0000 | [diff] [blame] | 26 | 02110-1301, USA. |
| 27 | |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 28 | The GNU General Public License is contained in the file COPYING. |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 29 | |
| 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. |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 34 | */ |
| 35 | |
| 36 | #include "libvex_basictypes.h" |
| 37 | #include "libvex_ir.h" |
| 38 | #include "libvex.h" |
sewardj | cef7d3e | 2009-07-02 12:21:59 +0000 | [diff] [blame] | 39 | #include "main_util.h" |
| 40 | #include "main_globals.h" |
| 41 | #include "guest_generic_bb_to_IR.h" |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 42 | |
| 43 | |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 44 | /* Forwards .. */ |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 45 | VEX_REGPARM(2) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 46 | static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 47 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 48 | static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 49 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 50 | static UInt genericg_compute_checksum_4al_2 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 51 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 52 | static UInt genericg_compute_checksum_4al_3 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 53 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 54 | static UInt genericg_compute_checksum_4al_4 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 55 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 56 | static UInt genericg_compute_checksum_4al_5 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 57 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 58 | static UInt genericg_compute_checksum_4al_6 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 59 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 60 | static UInt genericg_compute_checksum_4al_7 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 61 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 62 | static UInt genericg_compute_checksum_4al_8 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 63 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 64 | static UInt genericg_compute_checksum_4al_9 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 65 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 66 | static UInt genericg_compute_checksum_4al_10 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 67 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 68 | static UInt genericg_compute_checksum_4al_11 ( HWord first_w32 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 69 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 70 | static UInt genericg_compute_checksum_4al_12 ( HWord first_w32 ); |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 71 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 72 | VEX_REGPARM(2) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 73 | static ULong genericg_compute_checksum_8al ( HWord first_w64, HWord n_w64s ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 74 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 75 | static ULong genericg_compute_checksum_8al_1 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 76 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 77 | static ULong genericg_compute_checksum_8al_2 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 78 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 79 | static ULong genericg_compute_checksum_8al_3 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 80 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 81 | static ULong genericg_compute_checksum_8al_4 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 82 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 83 | static ULong genericg_compute_checksum_8al_5 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 84 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 85 | static ULong genericg_compute_checksum_8al_6 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 86 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 87 | static ULong genericg_compute_checksum_8al_7 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 88 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 89 | static ULong genericg_compute_checksum_8al_8 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 90 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 91 | static ULong genericg_compute_checksum_8al_9 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 92 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 93 | static ULong genericg_compute_checksum_8al_10 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 94 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 95 | static ULong genericg_compute_checksum_8al_11 ( HWord first_w64 ); |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 96 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 97 | static ULong genericg_compute_checksum_8al_12 ( HWord first_w64 ); |
| 98 | |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 99 | /* Small helpers */ |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 100 | static Bool const_False ( void* callback_opaque, Addr64 a ) { |
| 101 | return False; |
| 102 | } |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 103 | |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 104 | /* Disassemble a complete basic block, starting at guest_IP_start, |
sewardj | f6c8ebf | 2007-02-06 01:52:52 +0000 | [diff] [blame] | 105 | returning a new IRSB. The disassembler may chase across basic |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 106 | block boundaries if it wishes and if chase_into_ok allows it. |
| 107 | The precise guest address ranges from which code has been taken |
cerion | 36d982b | 2006-01-02 14:09:16 +0000 | [diff] [blame] | 108 | are written into vge. guest_IP_bbstart is taken to be the IP in |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 109 | 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. |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 114 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 115 | 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. |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 125 | |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 126 | preamble_function is a callback which allows the caller to add |
| 127 | its own IR preamble (following the self-check, if any). May be |
sewardj | f6c8ebf | 2007-02-06 01:52:52 +0000 | [diff] [blame] | 128 | NULL. If non-NULL, the IRSB under construction is handed to |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 129 | 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. |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 133 | |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 134 | 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, |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 136 | 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.) |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 141 | */ |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 142 | |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 143 | /* 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 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 180 | IRSB* bb_to_IR ( |
| 181 | /*OUT*/VexGuestExtents* vge, |
| 182 | /*OUT*/UInt* n_sc_extents, |
sewardj | fadbbe2 | 2012-04-24 11:49:03 +0000 | [diff] [blame] | 183 | /*OUT*/UInt* n_guest_instrs, /* stats only */ |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 184 | /*IN*/ void* callback_opaque, |
| 185 | /*IN*/ DisOneInstrFn dis_instr_fn, |
florian | 8462d11 | 2014-09-24 15:18:09 +0000 | [diff] [blame] | 186 | /*IN*/ const UChar* guest_code, |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 187 | /*IN*/ Addr64 guest_IP_bbstart, |
| 188 | /*IN*/ Bool (*chase_into_ok)(void*,Addr64), |
sewardj | 9b76916 | 2014-07-24 12:42:03 +0000 | [diff] [blame] | 189 | /*IN*/ VexEndness host_endness, |
sewardj | 442e51a | 2012-12-06 18:08:04 +0000 | [diff] [blame] | 190 | /*IN*/ Bool sigill_diag, |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 191 | /*IN*/ VexArch arch_guest, |
| 192 | /*IN*/ VexArchInfo* archinfo_guest, |
| 193 | /*IN*/ VexAbiInfo* abiinfo_both, |
| 194 | /*IN*/ IRType guest_word_type, |
florian | 0a5494e | 2014-09-24 12:00:49 +0000 | [diff] [blame] | 195 | /*IN*/ UInt (*needs_self_check)(void*,const VexGuestExtents*), |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 196 | /*IN*/ Bool (*preamble_function)(void*,IRSB*), |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 197 | /*IN*/ Int offB_GUEST_CMSTART, |
| 198 | /*IN*/ Int offB_GUEST_CMLEN, |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 199 | /*IN*/ Int offB_GUEST_IP, |
| 200 | /*IN*/ Int szB_GUEST_IP |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 201 | ) |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 202 | { |
| 203 | Long delta; |
| 204 | Int i, n_instrs, first_stmt_idx; |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 205 | Bool resteerOK, debug_print; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 206 | DisResult dres; |
| 207 | IRStmt* imark; |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 208 | IRStmt* nop; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 209 | static Int n_resteers = 0; |
| 210 | Int d_resteers = 0; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 211 | Int selfcheck_idx = 0; |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 212 | IRSB* irsb; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 213 | Addr64 guest_IP_curr_instr; |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 214 | IRConst* guest_IP_bbstart_IRConst = NULL; |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 215 | Int n_cond_resteers_allowed = 2; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 216 | |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 217 | Bool (*resteerOKfn)(void*,Addr64) = NULL; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 218 | |
| 219 | debug_print = toBool(vex_traceflags & VEX_TRACE_FE); |
| 220 | |
| 221 | /* check sanity .. */ |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 222 | vassert(sizeof(HWord) == sizeof(void*)); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 223 | vassert(vex_control.guest_max_insns >= 1); |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 224 | vassert(vex_control.guest_max_insns < 100); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 225 | 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 | |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 229 | 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 | |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 237 | /* Start a new, empty extent. */ |
| 238 | vge->n_used = 1; |
| 239 | vge->base[0] = guest_IP_bbstart; |
| 240 | vge->len[0] = 0; |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 241 | *n_sc_extents = 0; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 242 | |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 243 | /* And a new IR superblock to dump the result into. */ |
| 244 | irsb = emptyIRSB(); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 245 | |
| 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; |
sewardj | fadbbe2 | 2012-04-24 11:49:03 +0000 | [diff] [blame] | 250 | *n_guest_instrs = 0; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 251 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 252 | /* 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); |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 258 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 259 | /* 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 ); |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 267 | |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 268 | /* If the caller supplied a function to add its own preamble, use |
| 269 | it now. */ |
| 270 | if (preamble_function) { |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 271 | Bool stopNow = preamble_function( callback_opaque, irsb ); |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 272 | 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 |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 276 | is nothing to self-check. The 15 self-check no-ops will |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 277 | still be in place, but they are harmless. */ |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 278 | return irsb; |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 279 | } |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 280 | } |
| 281 | |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 282 | /* Process instructions. */ |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 283 | 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 | |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 299 | /* 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 | |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 308 | /* 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 | |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 312 | /* This is the irsb statement array index of the first stmt in |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 313 | this insn. That will always be the instruction-mark |
| 314 | descriptor. */ |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 315 | first_stmt_idx = irsb->stmts_used; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 316 | |
| 317 | /* Add an instruction-mark statement. We won't know until after |
| 318 | disassembling the instruction how long it instruction is, so |
sewardj | 3176386 | 2011-05-11 14:17:35 +0000 | [diff] [blame] | 319 | 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 |
sewardj | 2f10aa6 | 2011-05-27 13:20:56 +0000 | [diff] [blame] | 325 | 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 | } |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 349 | |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 350 | if (debug_print && n_instrs > 0) |
| 351 | vex_printf("\n"); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 352 | |
| 353 | /* Finally, actually disassemble an instruction. */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 354 | vassert(irsb->next == NULL); |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 355 | dres = dis_instr_fn ( irsb, |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 356 | resteerOKfn, |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 357 | toBool(n_cond_resteers_allowed > 0), |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 358 | callback_opaque, |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 359 | guest_code, |
| 360 | delta, |
| 361 | guest_IP_curr_instr, |
sewardj | a5f55da | 2006-04-30 23:37:32 +0000 | [diff] [blame] | 362 | arch_guest, |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 363 | archinfo_guest, |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 364 | abiinfo_both, |
sewardj | 9b76916 | 2014-07-24 12:42:03 +0000 | [diff] [blame] | 365 | host_endness, |
sewardj | 442e51a | 2012-12-06 18:08:04 +0000 | [diff] [blame] | 366 | sigill_diag ); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 367 | |
| 368 | /* stay sane ... */ |
| 369 | vassert(dres.whatNext == Dis_StopHere |
| 370 | || dres.whatNext == Dis_Continue |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 371 | || dres.whatNext == Dis_ResteerU |
| 372 | || dres.whatNext == Dis_ResteerC); |
| 373 | /* ... disassembled insn length is sane ... */ |
sewardj | ce02aa7 | 2006-01-12 12:27:58 +0000 | [diff] [blame] | 374 | vassert(dres.len >= 0 && dres.len <= 20); |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 375 | /* ... continueAt is zero if no resteer requested ... */ |
| 376 | if (dres.whatNext != Dis_ResteerU && dres.whatNext != Dis_ResteerC) |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 377 | vassert(dres.continueAt == 0); |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 378 | /* ... 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); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 382 | |
| 383 | /* Fill in the insn-mark length field. */ |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 384 | vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used); |
| 385 | imark = irsb->stmts[first_stmt_idx]; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 386 | 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) { |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 393 | for (i = first_stmt_idx; i < irsb->stmts_used; i++) { |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 394 | vex_printf(" "); |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 395 | ppIRStmt(irsb->stmts[i]); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 396 | vex_printf("\n"); |
| 397 | } |
| 398 | } |
| 399 | |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 400 | /* 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. */ |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 416 | } |
| 417 | |
| 418 | /* Update the VexGuestExtents we are constructing. */ |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 419 | /* If vex_control.guest_max_insns is required to be < 100 and |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 420 | 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. */ |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 423 | vassert(vge->len[vge->n_used-1] < 5000); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 424 | vge->len[vge->n_used-1] |
| 425 | = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len )); |
| 426 | n_instrs++; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 427 | |
| 428 | /* Advance delta (inconspicuous but very important :-) */ |
| 429 | delta += (Long)dres.len; |
| 430 | |
| 431 | switch (dres.whatNext) { |
| 432 | case Dis_Continue: |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 433 | vassert(dres.continueAt == 0); |
| 434 | vassert(dres.jk_StopHere == Ijk_INVALID); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 435 | if (n_instrs < vex_control.guest_max_insns) { |
| 436 | /* keep going */ |
| 437 | } else { |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 438 | /* 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; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 443 | goto done; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 444 | } |
| 445 | break; |
| 446 | case Dis_StopHere: |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 447 | 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; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 453 | goto done; |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 454 | |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 455 | case Dis_ResteerU: |
| 456 | case Dis_ResteerC: |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 457 | /* Check that we actually allowed a resteer .. */ |
| 458 | vassert(resteerOK); |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 459 | if (dres.whatNext == Dis_ResteerC) { |
| 460 | vassert(n_cond_resteers_allowed > 0); |
| 461 | n_cond_resteers_allowed--; |
| 462 | } |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 463 | /* figure out a new delta to continue at. */ |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 464 | vassert(resteerOKfn(callback_opaque,dres.continueAt)); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 465 | delta = dres.continueAt - guest_IP_bbstart; |
| 466 | /* we now have to start a new extent slot. */ |
cerion | 92b6436 | 2005-12-13 12:02:26 +0000 | [diff] [blame] | 467 | vge->n_used++; |
| 468 | vassert(vge->n_used <= 3); |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 469 | 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 | } |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 482 | /*NOTREACHED*/ |
| 483 | vassert(0); |
| 484 | |
| 485 | done: |
| 486 | /* We're done. The only thing that might need attending to is that |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 487 | a self-checking preamble may need to be created. If so it gets |
| 488 | placed in the 15 slots reserved above. |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 489 | |
| 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 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 497 | * 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. |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 506 | |
| 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. |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 511 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 512 | 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 | { |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 517 | Addr64 base2check; |
| 518 | UInt len2check; |
| 519 | HWord expectedhW; |
sewardj | 16a403b | 2005-07-07 12:26:36 +0000 | [diff] [blame] | 520 | IRTemp tistart_tmp, tilen_tmp; |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 521 | HWord VEX_REGPARM(2) (*fn_generic)(HWord, HWord); |
| 522 | HWord VEX_REGPARM(1) (*fn_spec)(HWord); |
florian | 55085f8 | 2012-11-21 00:36:55 +0000 | [diff] [blame] | 523 | const HChar* nm_generic; |
| 524 | const HChar* nm_spec; |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 525 | HWord fn_generic_entry = 0; |
| 526 | HWord fn_spec_entry = 0; |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 527 | UInt host_word_szB = sizeof(HWord); |
| 528 | IRType host_word_type = Ity_INVALID; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 529 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 530 | VexGuestExtents vge_tmp = *vge; |
| 531 | UInt extents_needing_check |
| 532 | = needs_self_check(callback_opaque, &vge_tmp); |
| 533 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 534 | 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); |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 537 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 538 | vassert(vge->n_used >= 1 && vge->n_used <= 3); |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 539 | |
| 540 | /* Caller shouldn't claim that nonexistent extents need a |
| 541 | check. */ |
| 542 | vassert((extents_needing_check >> vge->n_used) == 0); |
| 543 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 544 | for (i = 0; i < vge->n_used; i++) { |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 545 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 546 | /* 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 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 553 | /* 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); |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 574 | |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 575 | /* vex_printf("%lx %lx %ld\n", first_hW, last_hW, hWs_to_check); */ |
sewardj | 16a403b | 2005-07-07 12:26:36 +0000 | [diff] [blame] | 576 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 577 | if (host_word_szB == 8) { |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 578 | fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord)) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 579 | genericg_compute_checksum_8al; |
| 580 | nm_generic = "genericg_compute_checksum_8al"; |
| 581 | } else { |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 582 | fn_generic = (VEX_REGPARM(2) HWord(*)(HWord, HWord)) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 583 | genericg_compute_checksum_4al; |
| 584 | nm_generic = "genericg_compute_checksum_4al"; |
| 585 | } |
| 586 | |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 587 | fn_spec = NULL; |
| 588 | nm_spec = NULL; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 589 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 590 | if (host_word_szB == 8) { |
florian | 55085f8 | 2012-11-21 00:36:55 +0000 | [diff] [blame] | 591 | const HChar* nm = NULL; |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 592 | ULong VEX_REGPARM(1) (*fn)(HWord) = NULL; |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 593 | 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 | } |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 620 | fn_spec = (VEX_REGPARM(1) HWord(*)(HWord)) fn; |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 621 | nm_spec = nm; |
| 622 | } else { |
florian | 55085f8 | 2012-11-21 00:36:55 +0000 | [diff] [blame] | 623 | const HChar* nm = NULL; |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 624 | UInt VEX_REGPARM(1) (*fn)(HWord) = NULL; |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 625 | 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 | } |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 652 | fn_spec = (VEX_REGPARM(1) HWord(*)(HWord))fn; |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 653 | nm_spec = nm; |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 654 | } |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 655 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 656 | expectedhW = fn_generic( first_hW, hWs_to_check ); |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 657 | /* 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); |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 661 | vassert(expectedhW == fn_spec( first_hW )); |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 662 | } else { |
| 663 | vassert(!nm_spec); |
| 664 | } |
sewardj | 16a403b | 2005-07-07 12:26:36 +0000 | [diff] [blame] | 665 | |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 666 | /* Set CMSTART and CMLEN. These will describe to the despatcher |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 667 | the area of guest code to invalidate should we exit with a |
| 668 | self-check failure. */ |
sewardj | 16a403b | 2005-07-07 12:26:36 +0000 | [diff] [blame] | 669 | |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 670 | tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type); |
| 671 | tilen_tmp = newIRTemp(irsb->tyenv, guest_word_type); |
sewardj | aca070a | 2006-10-17 00:28:22 +0000 | [diff] [blame] | 672 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 673 | 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); |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 679 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 680 | irsb->stmts[selfcheck_idx + i * 5 + 0] |
| 681 | = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(base2check_IRConst) ); |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 682 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 683 | 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] |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 687 | = IRStmt_Put( offB_GUEST_CMSTART, IRExpr_RdTmp(tistart_tmp) ); |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 688 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 689 | irsb->stmts[selfcheck_idx + i * 5 + 3] |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 690 | = IRStmt_Put( offB_GUEST_CMLEN, IRExpr_RdTmp(tilen_tmp) ); |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 691 | |
| 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( |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 714 | host_word_type, 1/*regparms*/, |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 715 | nm_spec, (void*)fn_spec_entry, |
| 716 | mkIRExprVec_1( |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 717 | mkIRExpr_HWord( (HWord)first_hW ) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 718 | ) |
| 719 | ); |
| 720 | } else { |
| 721 | callexpr = mkIRExprCCall( |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 722 | host_word_type, 2/*regparms*/, |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 723 | nm_generic, (void*)fn_generic_entry, |
| 724 | mkIRExprVec_2( |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 725 | mkIRExpr_HWord( (HWord)first_hW ), |
| 726 | mkIRExpr_HWord( (HWord)hWs_to_check ) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 727 | ) |
| 728 | ); |
| 729 | } |
| 730 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 731 | irsb->stmts[selfcheck_idx + i * 5 + 4] |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 732 | = IRStmt_Exit( |
| 733 | IRExpr_Binop( |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 734 | host_word_type==Ity_I64 ? Iop_CmpNE64 : Iop_CmpNE32, |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 735 | callexpr, |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 736 | host_word_type==Ity_I64 |
| 737 | ? IRExpr_Const(IRConst_U64(expectedhW)) |
| 738 | : IRExpr_Const(IRConst_U32(expectedhW)) |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 739 | ), |
sewardj | 05f5e01 | 2014-05-04 10:52:11 +0000 | [diff] [blame] | 740 | Ijk_InvalICache, |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 741 | /* Where we must restart if there's a failure: at the |
| 742 | first extent, regardless of which extent the |
| 743 | failure actually happened in. */ |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 744 | guest_IP_bbstart_IRConst, |
| 745 | offB_GUEST_IP |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 746 | ); |
sewardj | bc161a4 | 2011-06-07 21:28:38 +0000 | [diff] [blame] | 747 | } /* for (i = 0; i < vge->n_used; i++) */ |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 748 | } |
| 749 | |
sewardj | c6f970f | 2012-04-02 21:54:49 +0000 | [diff] [blame] | 750 | /* 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 | |
sewardj | fadbbe2 | 2012-04-24 11:49:03 +0000 | [diff] [blame] | 763 | *n_guest_instrs = n_instrs; |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 764 | return irsb; |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 765 | } |
| 766 | |
| 767 | |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 768 | /*------------------------------------------------------------- |
| 769 | A support routine for doing self-checking translations. |
| 770 | -------------------------------------------------------------*/ |
| 771 | |
| 772 | /* CLEAN HELPER */ |
| 773 | /* CALLED FROM GENERATED CODE */ |
| 774 | |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 775 | /* Compute a checksum of host memory at [addr .. addr+len-1], as fast |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 776 | 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 --- */ |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 782 | |
| 783 | static inline UInt ROL32 ( UInt w, Int n ) { |
| 784 | w = (w << n) | (w >> (32-n)); |
| 785 | return w; |
sewardj | db4738a | 2005-07-07 01:32:16 +0000 | [diff] [blame] | 786 | } |
| 787 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 788 | VEX_REGPARM(2) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 789 | static UInt genericg_compute_checksum_4al ( HWord first_w32, HWord n_w32s ) |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 790 | { |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 791 | UInt sum1 = 0, sum2 = 0; |
| 792 | UInt* p = (UInt*)first_w32; |
| 793 | /* unrolled */ |
| 794 | while (n_w32s >= 4) { |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 795 | 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; |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 800 | p += 4; |
| 801 | n_w32s -= 4; |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 802 | sum1 ^= sum2; |
| 803 | } |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 804 | 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; |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 809 | sum1 ^= sum2; |
| 810 | } |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 811 | return sum1 + sum2; |
| 812 | } |
| 813 | |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 814 | /* Specialised versions of the above function */ |
| 815 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 816 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 817 | static UInt genericg_compute_checksum_4al_1 ( HWord first_w32 ) |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 818 | { |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 819 | 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 827 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 828 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 840 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 841 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 855 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 856 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 869 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 870 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 885 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 886 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 903 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 904 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 923 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 924 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 942 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 943 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 963 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 964 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 986 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 987 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1011 | VEX_REGPARM(1) |
sewardj | 9581906 | 2010-02-18 23:01:26 +0000 | [diff] [blame] | 1012 | static 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; |
sewardj | 5eaf82b | 2009-09-05 00:03:07 +0000 | [diff] [blame] | 1032 | return sum1 + sum2; |
| 1033 | } |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 1034 | |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1035 | |
| 1036 | /* --- 64-bit versions, used only on 64-bit hosts --- */ |
| 1037 | |
| 1038 | static inline ULong ROL64 ( ULong w, Int n ) { |
| 1039 | w = (w << n) | (w >> (64-n)); |
| 1040 | return w; |
| 1041 | } |
| 1042 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1043 | VEX_REGPARM(2) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1044 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1071 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1072 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1082 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1083 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1095 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1096 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1110 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1111 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1124 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1125 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1140 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1141 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1158 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1159 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1178 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1179 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1197 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1198 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1218 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1219 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1241 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1242 | static 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 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 1266 | VEX_REGPARM(1) |
sewardj | d6c1725 | 2011-01-10 15:08:41 +0000 | [diff] [blame] | 1267 | static 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 | |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 1290 | /*--------------------------------------------------------------------*/ |
sewardj | cef7d3e | 2009-07-02 12:21:59 +0000 | [diff] [blame] | 1291 | /*--- end guest_generic_bb_to_IR.c ---*/ |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 1292 | /*--------------------------------------------------------------------*/ |