sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 1 | |
| 2 | /*---------------------------------------------------------------*/ |
| 3 | /*--- ---*/ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 4 | /*--- This file (guest-x86/gdefs.h) is ---*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 5 | /*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/ |
| 6 | /*--- ---*/ |
| 7 | /*---------------------------------------------------------------*/ |
| 8 | |
sewardj | f8ed9d8 | 2004-11-12 17:40:23 +0000 | [diff] [blame] | 9 | /* |
| 10 | This file is part of LibVEX, a library for dynamic binary |
| 11 | instrumentation and translation. |
| 12 | |
| 13 | Copyright (C) 2004 OpenWorks, LLP. |
| 14 | |
| 15 | This program is free software; you can redistribute it and/or modify |
| 16 | it under the terms of the GNU General Public License as published by |
| 17 | the Free Software Foundation; Version 2 dated June 1991 of the |
| 18 | license. |
| 19 | |
| 20 | This program is distributed in the hope that it will be useful, |
| 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability |
| 23 | for damages. See the GNU General Public License for more details. |
| 24 | |
| 25 | Neither the names of the U.S. Department of Energy nor the |
| 26 | University of California nor the names of its contributors may be |
| 27 | used to endorse or promote products derived from this software |
| 28 | without prior written permission. |
| 29 | |
| 30 | You should have received a copy of the GNU General Public License |
| 31 | along with this program; if not, write to the Free Software |
| 32 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
| 33 | USA. |
| 34 | */ |
| 35 | |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 36 | /* Only to be used within the guest-x86 directory. */ |
| 37 | |
| 38 | /* Some of this stuff is taken from QEMU, which is Copyright (c) 2003 |
| 39 | Fabrice Bellard, and licensed under the LGPL. */ |
| 40 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 41 | #ifndef __LIBVEX_GUEST_X86_DEFS_H |
| 42 | #define __LIBVEX_GUEST_X86_DEFS_H |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 43 | |
| 44 | |
| 45 | /*---------------------------------------------------------*/ |
| 46 | /*--- x86 to IR conversion ---*/ |
| 47 | /*---------------------------------------------------------*/ |
| 48 | |
| 49 | extern |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 50 | IRBB* bbToIR_X86 ( UChar* x86code, |
| 51 | Addr64 eip, |
| 52 | Int* guest_bytes_read, |
| 53 | Bool (*byte_accessible)(Addr64), |
| 54 | Bool (*resteerOkFn)(Addr64), |
| 55 | Bool host_bigendian ); |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 56 | |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 57 | /* Used by the optimiser to specialise calls to helpers. */ |
| 58 | extern |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 59 | IRExpr* guest_x86_spechelper ( Char* function_name, |
| 60 | IRExpr** args ); |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 61 | |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 62 | /* Describes to the optimser which part of the guest state require |
| 63 | precise memory exceptions. This is logically part of the guest |
| 64 | state description. */ |
| 65 | extern |
| 66 | Bool guest_x86_state_requires_precise_mem_exns ( Int, Int ); |
| 67 | |
sewardj | 49651f4 | 2004-10-28 22:11:04 +0000 | [diff] [blame] | 68 | extern |
sewardj | eeac841 | 2004-11-02 00:26:55 +0000 | [diff] [blame] | 69 | VexGuestLayout x86guest_layout; |
sewardj | 49651f4 | 2004-10-28 22:11:04 +0000 | [diff] [blame] | 70 | |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 71 | |
| 72 | /*---------------------------------------------------------*/ |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 73 | /*--- x86 guest helpers ---*/ |
| 74 | /*---------------------------------------------------------*/ |
| 75 | |
| 76 | /* --- CLEAN HELPERS --- */ |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 77 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 78 | extern UInt x86g_calculate_eflags_all ( |
| 79 | UInt cc_op, UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 80 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 81 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 82 | extern UInt x86g_calculate_eflags_c ( |
| 83 | UInt cc_op, UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 84 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 85 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 86 | extern UInt x86g_calculate_condition ( |
| 87 | UInt/*X86Condcode*/ cond, |
| 88 | UInt cc_op, |
| 89 | UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 90 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 91 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 92 | extern UInt x86g_calculate_FXAM ( UInt tag, ULong dbl ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 93 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 94 | extern ULong x86g_calculate_RCR ( |
| 95 | UInt arg, UInt rot_amt, UInt eflags_in, UInt sz |
| 96 | ); |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 97 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame^] | 98 | extern ULong x86g_check_fldcw ( UInt fpucw ); |
sewardj | 893aada | 2004-11-29 19:57:54 +0000 | [diff] [blame] | 99 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame^] | 100 | extern UInt x86g_create_fpucw ( UInt fpround ); |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 101 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame^] | 102 | extern ULong x86g_check_ldmxcsr ( UInt mxcsr ); |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 103 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame^] | 104 | extern UInt x86g_create_mxcsr ( UInt sseround ); |
| 105 | |
| 106 | /* Translate a guest virtual_addr into a guest linear address by |
| 107 | consulting the supplied LDT/GDT structures. Their representation |
| 108 | must be as specified in pub/libvex_guest_x86.h. To indicate a |
| 109 | translation failure, 1<<32 is returned. On success, the lower 32 |
| 110 | bits of the returned result indicate the linear address. |
| 111 | */ |
| 112 | extern |
| 113 | ULong x86g_use_seg_selector ( HWord ldt, HWord gdt, |
| 114 | UInt seg_selector, UInt virtual_addr ); |
sewardj | 893aada | 2004-11-29 19:57:54 +0000 | [diff] [blame] | 115 | |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 116 | /* --- Clean helpers for MMX --- */ |
| 117 | |
sewardj | 164f927 | 2004-12-09 00:39:32 +0000 | [diff] [blame] | 118 | extern ULong x86g_calculate_add64x1 ( ULong, ULong ); |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 119 | extern ULong x86g_calculate_add32x2 ( ULong, ULong ); |
| 120 | extern ULong x86g_calculate_add16x4 ( ULong, ULong ); |
| 121 | extern ULong x86g_calculate_add8x8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 122 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 123 | extern ULong x86g_calculate_qadd16Sx4 ( ULong, ULong ); |
| 124 | extern ULong x86g_calculate_qadd8Sx8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 125 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 126 | extern ULong x86g_calculate_qadd16Ux4 ( ULong, ULong ); |
| 127 | extern ULong x86g_calculate_qadd8Ux8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 128 | |
sewardj | b9fa69b | 2004-12-09 23:25:14 +0000 | [diff] [blame] | 129 | extern ULong x86g_calculate_sub64x1 ( ULong, ULong ); |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 130 | extern ULong x86g_calculate_sub32x2 ( ULong, ULong ); |
| 131 | extern ULong x86g_calculate_sub16x4 ( ULong, ULong ); |
| 132 | extern ULong x86g_calculate_sub8x8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 133 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 134 | extern ULong x86g_calculate_qsub16Sx4 ( ULong, ULong ); |
| 135 | extern ULong x86g_calculate_qsub8Sx8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 136 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 137 | extern ULong x86g_calculate_qsub16Ux4 ( ULong, ULong ); |
| 138 | extern ULong x86g_calculate_qsub8Ux8 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 139 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 140 | extern ULong x86g_calculate_mulhi16x4 ( ULong, ULong ); |
| 141 | extern ULong x86g_calculate_mullo16x4 ( ULong, ULong ); |
sewardj | 464efa4 | 2004-11-19 22:17:29 +0000 | [diff] [blame] | 142 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 143 | extern ULong x86g_calculate_pmaddwd ( ULong, ULong ); |
sewardj | 4340dac | 2004-11-20 13:17:04 +0000 | [diff] [blame] | 144 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 145 | extern ULong x86g_calculate_cmpeq32x2 ( ULong, ULong ); |
| 146 | extern ULong x86g_calculate_cmpeq16x4 ( ULong, ULong ); |
| 147 | extern ULong x86g_calculate_cmpeq8x8 ( ULong, ULong ); |
| 148 | extern ULong x86g_calculate_cmpge32Sx2 ( ULong, ULong ); |
| 149 | extern ULong x86g_calculate_cmpge16Sx4 ( ULong, ULong ); |
| 150 | extern ULong x86g_calculate_cmpge8Sx8 ( ULong, ULong ); |
sewardj | 63ba409 | 2004-11-21 12:30:18 +0000 | [diff] [blame] | 151 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 152 | extern ULong x86g_calculate_packssdw ( ULong, ULong ); |
| 153 | extern ULong x86g_calculate_packsswb ( ULong, ULong ); |
| 154 | extern ULong x86g_calculate_packuswb ( ULong, ULong ); |
sewardj | 63ba409 | 2004-11-21 12:30:18 +0000 | [diff] [blame] | 155 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 156 | extern ULong x86g_calculate_punpckhbw ( ULong, ULong ); |
| 157 | extern ULong x86g_calculate_punpcklbw ( ULong, ULong ); |
| 158 | extern ULong x86g_calculate_punpckhwd ( ULong, ULong ); |
| 159 | extern ULong x86g_calculate_punpcklwd ( ULong, ULong ); |
| 160 | extern ULong x86g_calculate_punpckhdq ( ULong, ULong ); |
| 161 | extern ULong x86g_calculate_punpckldq ( ULong, ULong ); |
sewardj | 4340dac | 2004-11-20 13:17:04 +0000 | [diff] [blame] | 162 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 163 | extern ULong x86g_calculate_shl16x4 ( ULong, ULong ); |
| 164 | extern ULong x86g_calculate_shl32x2 ( ULong, ULong ); |
| 165 | extern ULong x86g_calculate_shl64x1 ( ULong, ULong ); |
sewardj | 8d14a59 | 2004-11-21 17:04:50 +0000 | [diff] [blame] | 166 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 167 | extern ULong x86g_calculate_shr16Ux4 ( ULong, ULong ); |
| 168 | extern ULong x86g_calculate_shr32Ux2 ( ULong, ULong ); |
| 169 | extern ULong x86g_calculate_shr64Ux1 ( ULong, ULong ); |
sewardj | 8d14a59 | 2004-11-21 17:04:50 +0000 | [diff] [blame] | 170 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 171 | extern ULong x86g_calculate_shr16Sx4 ( ULong, ULong ); |
| 172 | extern ULong x86g_calculate_shr32Sx2 ( ULong, ULong ); |
sewardj | 8d14a59 | 2004-11-21 17:04:50 +0000 | [diff] [blame] | 173 | |
sewardj | b545208 | 2004-12-04 20:33:02 +0000 | [diff] [blame] | 174 | extern ULong x86g_calculate_avg8Ux8 ( ULong, ULong ); |
| 175 | extern ULong x86g_calculate_avg16Ux4 ( ULong, ULong ); |
| 176 | |
| 177 | extern ULong x86g_calculate_max16Sx4 ( ULong, ULong ); |
| 178 | extern ULong x86g_calculate_max8Ux8 ( ULong, ULong ); |
| 179 | extern ULong x86g_calculate_min16Sx4 ( ULong, ULong ); |
| 180 | extern ULong x86g_calculate_min8Ux8 ( ULong, ULong ); |
| 181 | |
sewardj | 0bd7ce6 | 2004-12-05 02:47:40 +0000 | [diff] [blame] | 182 | extern UInt x86g_calculate_pmovmskb ( ULong xx ); |
| 183 | extern ULong x86g_calculate_psadbw ( ULong, ULong ); |
| 184 | |
| 185 | extern ULong x86g_calculate_mull16uHIx4 ( ULong, ULong ); |
sewardj | b545208 | 2004-12-04 20:33:02 +0000 | [diff] [blame] | 186 | |
sewardj | e5854d6 | 2004-12-09 03:44:34 +0000 | [diff] [blame] | 187 | extern UInt x86g_calculate_sse_pmovmskb ( ULong w64hi, ULong w64lo ); |
sewardj | 4340dac | 2004-11-20 13:17:04 +0000 | [diff] [blame] | 188 | |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 189 | /* --- DIRTY HELPERS --- */ |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 190 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 191 | extern ULong x86g_loadF80le ( UInt ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 192 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 193 | extern void x86g_storeF80le ( UInt, ULong ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 194 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 195 | extern void x86g_dirtyhelper_CPUID ( VexGuestX86State* ); |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 196 | |
sewardj | 9fc9e78 | 2004-11-26 17:57:40 +0000 | [diff] [blame] | 197 | extern void x86g_dirtyhelper_FSAVE ( VexGuestX86State*, HWord ); |
| 198 | |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 199 | extern VexEmWarn |
| 200 | x86g_dirtyhelper_FRSTOR ( VexGuestX86State*, HWord ); |
| 201 | |
| 202 | extern void x86g_dirtyhelper_FSTENV ( VexGuestX86State*, HWord ); |
| 203 | |
| 204 | extern VexEmWarn |
| 205 | x86g_dirtyhelper_FLDENV ( VexGuestX86State*, HWord ); |
sewardj | 9fc9e78 | 2004-11-26 17:57:40 +0000 | [diff] [blame] | 206 | |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 207 | |
| 208 | /*---------------------------------------------------------*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 209 | /*--- Condition code stuff ---*/ |
| 210 | /*---------------------------------------------------------*/ |
| 211 | |
| 212 | /* eflags masks */ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 213 | #define X86G_CC_SHIFT_O 11 |
| 214 | #define X86G_CC_SHIFT_S 7 |
| 215 | #define X86G_CC_SHIFT_Z 6 |
| 216 | #define X86G_CC_SHIFT_A 4 |
| 217 | #define X86G_CC_SHIFT_C 0 |
| 218 | #define X86G_CC_SHIFT_P 2 |
sewardj | 9aebb0c | 2004-10-24 19:20:43 +0000 | [diff] [blame] | 219 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 220 | #define X86G_CC_MASK_O (1 << X86G_CC_SHIFT_O) |
| 221 | #define X86G_CC_MASK_S (1 << X86G_CC_SHIFT_S) |
| 222 | #define X86G_CC_MASK_Z (1 << X86G_CC_SHIFT_Z) |
| 223 | #define X86G_CC_MASK_A (1 << X86G_CC_SHIFT_A) |
| 224 | #define X86G_CC_MASK_C (1 << X86G_CC_SHIFT_C) |
| 225 | #define X86G_CC_MASK_P (1 << X86G_CC_SHIFT_P) |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 226 | |
sewardj | c4be80c | 2004-09-10 16:17:45 +0000 | [diff] [blame] | 227 | /* FPU flag masks */ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 228 | #define X86G_FC_MASK_C3 (1 << 14) |
| 229 | #define X86G_FC_MASK_C2 (1 << 10) |
| 230 | #define X86G_FC_MASK_C1 (1 << 9) |
| 231 | #define X86G_FC_MASK_C0 (1 << 8) |
sewardj | c4be80c | 2004-09-10 16:17:45 +0000 | [diff] [blame] | 232 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 233 | /* %EFLAGS thunk descriptors. A four-word thunk is used to record |
| 234 | details of the most recent flag-setting operation, so the flags can |
| 235 | be computed later if needed. It is possible to do this a little |
| 236 | more efficiently using a 3-word thunk, but that makes it impossible |
| 237 | to describe the flag data dependencies sufficiently accurately for |
| 238 | Memcheck. Hence 4 words are used, with minimal loss of efficiency. |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 239 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 240 | The four words are: |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 241 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 242 | CC_OP, which describes the operation. |
| 243 | |
| 244 | CC_DEP1 and CC_DEP2. These are arguments to the operation. |
| 245 | We want Memcheck to believe that the resulting flags are |
| 246 | data-dependent on both CC_DEP1 and CC_DEP2, hence the |
| 247 | name DEP. |
| 248 | |
| 249 | CC_NDEP. This is a 3rd argument to the operation which is |
| 250 | sometimes needed. We arrange things so that Memcheck does |
| 251 | not believe the resulting flags are data-dependent on CC_NDEP |
| 252 | ("not dependent"). |
| 253 | |
| 254 | To make Memcheck believe that (the definedness of) the encoded |
| 255 | flags depends only on (the definedness of) CC_DEP1 and CC_DEP2 |
| 256 | requires two things: |
| 257 | |
| 258 | (1) In the guest state layout info (x86guest_layout), CC_OP and |
| 259 | CC_NDEP are marked as always defined. |
| 260 | |
| 261 | (2) When passing the thunk components to an evaluation function |
| 262 | (calculate_condition, calculate_eflags, calculate_eflags_c) the |
| 263 | IRCallee's mcx_mask must be set so as to exclude from |
| 264 | consideration all passed args except CC_DEP1 and CC_DEP2. |
| 265 | |
| 266 | Strictly speaking only (2) is necessary for correctness. However, |
| 267 | (1) helps efficiency in that since (2) means we never ask about the |
| 268 | definedness of CC_OP or CC_NDEP, we may as well not even bother to |
| 269 | track their definedness. |
| 270 | |
| 271 | When building the thunk, it is always necessary to write words into |
| 272 | CC_DEP1 and CC_DEP2, even if those args are not used given the |
| 273 | CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4). |
| 274 | This is important because otherwise Memcheck could give false |
| 275 | positives as it does not understand the relationship between the |
| 276 | CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the |
| 277 | definedness of the stored flags always depends on both CC_DEP1 and |
| 278 | CC_DEP2. |
| 279 | |
| 280 | However, it is only necessary to set CC_NDEP when the CC_OP value |
| 281 | requires it, because Memcheck ignores CC_NDEP, and the evaluation |
| 282 | functions do understand the CC_OP fields and will only examine |
| 283 | CC_NDEP for suitable values of CC_OP. |
| 284 | |
| 285 | A summary of the field usages is: |
| 286 | |
| 287 | Operation DEP1 DEP2 NDEP |
| 288 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 289 | |
| 290 | add/sub/mul first arg second arg unused |
| 291 | |
| 292 | adc/sbb first arg (second arg) |
| 293 | XOR old_carry old_carry |
| 294 | |
| 295 | and/or/xor result zero unused |
| 296 | |
| 297 | inc/dec result zero old_carry |
| 298 | |
| 299 | shl/shr/sar result subshifted- unused |
| 300 | result |
| 301 | |
| 302 | rol/ror result zero old_flags |
| 303 | |
| 304 | copy old_flags zero unused. |
| 305 | |
| 306 | |
| 307 | Therefore Memcheck will believe the following: |
| 308 | |
| 309 | * add/sub/mul -- definedness of result flags depends on definedness |
| 310 | of both args. |
| 311 | |
| 312 | * adc/sbb -- definedness of result flags depends on definedness of |
| 313 | both args and definedness of the old C flag. Because only two |
| 314 | DEP fields are available, the old C flag is XOR'd into the second |
| 315 | arg so that Memcheck sees the data dependency on it. That means |
| 316 | the NDEP field must contain a second copy of the old C flag |
| 317 | so that the evaluation functions can correctly recover the second |
| 318 | arg. |
| 319 | |
| 320 | * and/or/xor are straightforward -- definedness of result flags |
| 321 | depends on definedness of result value. |
| 322 | |
| 323 | * inc/dec -- definedness of result flags depends only on |
| 324 | definedness of result. This isn't really true -- it also depends |
| 325 | on the old C flag. However, we don't want Memcheck to see that, |
| 326 | and so the old C flag must be passed in NDEP and not in DEP2. |
| 327 | It's inconceivable that a compiler would generate code that puts |
| 328 | the C flag in an undefined state, then does an inc/dec, which |
| 329 | leaves C unchanged, and then makes a conditional jump/move based |
| 330 | on C. So our fiction seems a good approximation. |
| 331 | |
| 332 | * shl/shr/sar -- straightforward, again, definedness of result |
| 333 | flags depends on definedness of result value. The subshifted |
| 334 | value (value shifted one less) is also needed, but its |
| 335 | definedness is the same as the definedness of the shifted value. |
| 336 | |
| 337 | * rol/ror -- these only set O and C, and leave A Z C P alone. |
| 338 | However it seems prudent (as per inc/dec) to say the definedness |
| 339 | of all resulting flags depends on the definedness of the result, |
| 340 | hence the old flags must go in as NDEP and not DEP2. |
| 341 | |
| 342 | * rcl/rcr are too difficult to do in-line, and so are done by a |
| 343 | helper function. They are not part of this scheme. The helper |
| 344 | function takes the value to be rotated, the rotate amount and the |
| 345 | old flags, and returns the new flags and the rotated value. |
| 346 | Since the helper's mcx_mask does not have any set bits, Memcheck |
| 347 | will lazily propagate undefinedness from any of the 3 args into |
| 348 | both results (flags and actual value). |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 349 | */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 350 | enum { |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 351 | X86G_CC_OP_COPY, /* DEP1 = current flags, DEP2 = 0, NDEP = unused */ |
| 352 | /* just copy DEP1 to output */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 353 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 354 | X86G_CC_OP_ADDB, /* 1 */ |
| 355 | X86G_CC_OP_ADDW, /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 356 | X86G_CC_OP_ADDL, /* 3 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 357 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 358 | X86G_CC_OP_SUBB, /* 4 */ |
| 359 | X86G_CC_OP_SUBW, /* 5 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 360 | X86G_CC_OP_SUBL, /* 6 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 361 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 362 | X86G_CC_OP_ADCB, /* 7 */ |
| 363 | X86G_CC_OP_ADCW, /* 8 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ |
| 364 | X86G_CC_OP_ADCL, /* 9 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 365 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 366 | X86G_CC_OP_SBBB, /* 10 */ |
| 367 | X86G_CC_OP_SBBW, /* 11 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ |
| 368 | X86G_CC_OP_SBBL, /* 12 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 369 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 370 | X86G_CC_OP_LOGICB, /* 13 */ |
| 371 | X86G_CC_OP_LOGICW, /* 14 DEP1 = result, DEP2 = 0, NDEP = unused */ |
| 372 | X86G_CC_OP_LOGICL, /* 15 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 373 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 374 | X86G_CC_OP_INCB, /* 16 */ |
| 375 | X86G_CC_OP_INCW, /* 17 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ |
| 376 | X86G_CC_OP_INCL, /* 18 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 377 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 378 | X86G_CC_OP_DECB, /* 19 */ |
| 379 | X86G_CC_OP_DECW, /* 20 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ |
| 380 | X86G_CC_OP_DECL, /* 21 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 381 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 382 | X86G_CC_OP_SHLB, /* 22 DEP1 = res, DEP2 = res', NDEP = unused */ |
| 383 | X86G_CC_OP_SHLW, /* 23 where res' is like res but shifted one bit less */ |
| 384 | X86G_CC_OP_SHLL, /* 24 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 385 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 386 | X86G_CC_OP_SHRB, /* 25 DEP1 = res, DEP2 = res', NDEP = unused */ |
| 387 | X86G_CC_OP_SHRW, /* 26 where res' is like res but shifted one bit less */ |
| 388 | X86G_CC_OP_SHRL, /* 27 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 389 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 390 | X86G_CC_OP_ROLB, /* 28 */ |
| 391 | X86G_CC_OP_ROLW, /* 29 DEP1 = res, DEP2 = 0, NDEP = old flags */ |
| 392 | X86G_CC_OP_ROLL, /* 30 */ |
sewardj | 1813dbe | 2004-07-28 17:09:04 +0000 | [diff] [blame] | 393 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 394 | X86G_CC_OP_RORB, /* 31 */ |
| 395 | X86G_CC_OP_RORW, /* 32 DEP1 = res, DEP2 = 0, NDEP = old flags */ |
| 396 | X86G_CC_OP_RORL, /* 33 */ |
sewardj | 1813dbe | 2004-07-28 17:09:04 +0000 | [diff] [blame] | 397 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 398 | X86G_CC_OP_UMULB, /* 34 */ |
| 399 | X86G_CC_OP_UMULW, /* 35 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 400 | X86G_CC_OP_UMULL, /* 36 */ |
sewardj | cf780b4 | 2004-07-13 18:42:17 +0000 | [diff] [blame] | 401 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 402 | X86G_CC_OP_SMULB, /* 37 */ |
| 403 | X86G_CC_OP_SMULW, /* 38 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 404 | X86G_CC_OP_SMULL, /* 39 */ |
sewardj | cf780b4 | 2004-07-13 18:42:17 +0000 | [diff] [blame] | 405 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 406 | X86G_CC_OP_NUMBER |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 407 | }; |
| 408 | |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 409 | typedef |
| 410 | enum { |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 411 | X86CondO = 0, /* overflow */ |
| 412 | X86CondNO = 1, /* no overflow */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 413 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 414 | X86CondB = 2, /* below */ |
| 415 | X86CondNB = 3, /* not below */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 416 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 417 | X86CondZ = 4, /* zero */ |
| 418 | X86CondNZ = 5, /* not zero */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 419 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 420 | X86CondBE = 6, /* below or equal */ |
| 421 | X86CondNBE = 7, /* not below or equal */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 422 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 423 | X86CondS = 8, /* negative */ |
| 424 | X86CondNS = 9, /* not negative */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 425 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 426 | X86CondP = 10, /* parity even */ |
| 427 | X86CondNP = 11, /* not parity even */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 428 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 429 | X86CondL = 12, /* jump less */ |
| 430 | X86CondNL = 13, /* not less */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 431 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 432 | X86CondLE = 14, /* less or equal */ |
| 433 | X86CondNLE = 15, /* not less or equal */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 434 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 435 | X86CondAlways = 16 /* HACK */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 436 | } |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 437 | X86Condcode; |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 438 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 439 | #endif /* ndef __LIBVEX_GUEST_X86_DEFS_H */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 440 | |
| 441 | /*---------------------------------------------------------------*/ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 442 | /*--- end guest-x86/gdefs.h ---*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 443 | /*---------------------------------------------------------------*/ |