sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 1 | |
| 2 | /*---------------------------------------------------------------*/ |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 3 | /*--- begin guest_x86_defs.h ---*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 4 | /*---------------------------------------------------------------*/ |
| 5 | |
sewardj | f8ed9d8 | 2004-11-12 17:40:23 +0000 | [diff] [blame] | 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 | f8ed9d8 | 2004-11-12 17:40:23 +0000 | [diff] [blame] | 9 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 10 | Copyright (C) 2004-2017 OpenWorks LLP |
sewardj | 752f906 | 2010-05-03 21:38:49 +0000 | [diff] [blame] | 11 | info@open-works.net |
sewardj | f8ed9d8 | 2004-11-12 17:40:23 +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 | f8ed9d8 | 2004-11-12 17:40:23 +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 | f8ed9d8 | 2004-11-12 17:40:23 +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 | f8ed9d8 | 2004-11-12 17:40:23 +0000 | [diff] [blame] | 34 | */ |
| 35 | |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 36 | /* Only to be used within the guest-x86 directory. */ |
| 37 | |
sewardj | cef7d3e | 2009-07-02 12:21:59 +0000 | [diff] [blame] | 38 | #ifndef __VEX_GUEST_X86_DEFS_H |
| 39 | #define __VEX_GUEST_X86_DEFS_H |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 40 | |
florian | 58a637b | 2012-09-30 20:30:17 +0000 | [diff] [blame] | 41 | #include "libvex_basictypes.h" |
| 42 | #include "libvex_guest_x86.h" // VexGuestX86State |
| 43 | #include "libvex_emnote.h" // VexEmNote |
| 44 | #include "guest_generic_bb_to_IR.h" // DisResult |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 45 | |
| 46 | /*---------------------------------------------------------*/ |
| 47 | /*--- x86 to IR conversion ---*/ |
| 48 | /*---------------------------------------------------------*/ |
| 49 | |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 50 | /* Convert one x86 insn to IR. See the type DisOneInstrFn in |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 51 | guest_generic_bb_to_IR.h. */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 52 | extern |
sewardj | dd40fdf | 2006-12-24 02:20:24 +0000 | [diff] [blame] | 53 | DisResult disInstr_X86 ( IRSB* irbb, |
florian | beac530 | 2014-12-31 12:09:38 +0000 | [diff] [blame] | 54 | Bool (*resteerOkFn) ( void*, Addr ), |
sewardj | 984d9b1 | 2010-01-15 10:53:21 +0000 | [diff] [blame] | 55 | Bool resteerCisOk, |
sewardj | c716aea | 2006-01-17 01:48:46 +0000 | [diff] [blame] | 56 | void* callback_opaque, |
florian | 8462d11 | 2014-09-24 15:18:09 +0000 | [diff] [blame] | 57 | const UChar* guest_code, |
sewardj | 9e6491a | 2005-07-02 19:24:10 +0000 | [diff] [blame] | 58 | Long delta, |
florian | d4cc0de | 2015-01-02 11:44:12 +0000 | [diff] [blame] | 59 | Addr guest_IP, |
sewardj | a5f55da | 2006-04-30 23:37:32 +0000 | [diff] [blame] | 60 | VexArch guest_arch, |
florian | cacba8e | 2014-12-15 18:58:07 +0000 | [diff] [blame] | 61 | const VexArchInfo* archinfo, |
| 62 | const VexAbiInfo* abiinfo, |
sewardj | 9b76916 | 2014-07-24 12:42:03 +0000 | [diff] [blame] | 63 | VexEndness host_endness, |
sewardj | 442e51a | 2012-12-06 18:08:04 +0000 | [diff] [blame] | 64 | Bool sigill_diag ); |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 65 | |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 66 | /* Used by the optimiser to specialise calls to helpers. */ |
| 67 | extern |
florian | 1ff4756 | 2012-10-21 02:09:51 +0000 | [diff] [blame] | 68 | IRExpr* guest_x86_spechelper ( const HChar* function_name, |
sewardj | be91791 | 2010-08-22 12:38:53 +0000 | [diff] [blame] | 69 | IRExpr** args, |
| 70 | IRStmt** precedingStmts, |
| 71 | Int n_precedingStmts ); |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 72 | |
sewardj | b122d42 | 2005-03-10 19:40:41 +0000 | [diff] [blame] | 73 | /* Describes to the optimiser which part of the guest state require |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 74 | precise memory exceptions. This is logically part of the guest |
| 75 | state description. */ |
| 76 | extern |
sewardj | ca2c3c7 | 2015-02-05 12:53:20 +0000 | [diff] [blame] | 77 | Bool guest_x86_state_requires_precise_mem_exns ( Int, Int, |
| 78 | VexRegisterUpdates ); |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 79 | |
sewardj | 49651f4 | 2004-10-28 22:11:04 +0000 | [diff] [blame] | 80 | extern |
sewardj | eeac841 | 2004-11-02 00:26:55 +0000 | [diff] [blame] | 81 | VexGuestLayout x86guest_layout; |
sewardj | 49651f4 | 2004-10-28 22:11:04 +0000 | [diff] [blame] | 82 | |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 83 | |
| 84 | /*---------------------------------------------------------*/ |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 85 | /*--- x86 guest helpers ---*/ |
| 86 | /*---------------------------------------------------------*/ |
| 87 | |
| 88 | /* --- CLEAN HELPERS --- */ |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 89 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 90 | extern UInt x86g_calculate_eflags_all ( |
| 91 | UInt cc_op, UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 92 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 93 | |
sewardj | 03d9114 | 2011-03-14 12:35:18 +0000 | [diff] [blame] | 94 | VEX_REGPARM(3) |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 95 | extern UInt x86g_calculate_eflags_c ( |
| 96 | UInt cc_op, UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 97 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 98 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 99 | extern UInt x86g_calculate_condition ( |
| 100 | UInt/*X86Condcode*/ cond, |
| 101 | UInt cc_op, |
| 102 | UInt cc_dep1, UInt cc_dep2, UInt cc_ndep |
| 103 | ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 104 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 105 | extern UInt x86g_calculate_FXAM ( UInt tag, ULong dbl ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 106 | |
sewardj | 2eef773 | 2005-08-23 15:41:14 +0000 | [diff] [blame] | 107 | extern ULong x86g_calculate_RCR ( |
| 108 | UInt arg, UInt rot_amt, UInt eflags_in, UInt sz |
| 109 | ); |
| 110 | extern ULong x86g_calculate_RCL ( |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 111 | UInt arg, UInt rot_amt, UInt eflags_in, UInt sz |
| 112 | ); |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 113 | |
sewardj | 8edc36b | 2007-11-23 02:46:29 +0000 | [diff] [blame] | 114 | extern UInt x86g_calculate_daa_das_aaa_aas ( UInt AX_and_flags, UInt opcode ); |
| 115 | |
sewardj | 321bbbf | 2011-01-17 12:32:25 +0000 | [diff] [blame] | 116 | extern UInt x86g_calculate_aad_aam ( UInt AX_and_flags, UInt opcode ); |
| 117 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame] | 118 | extern ULong x86g_check_fldcw ( UInt fpucw ); |
sewardj | 893aada | 2004-11-29 19:57:54 +0000 | [diff] [blame] | 119 | |
sewardj | 38a3f86 | 2005-01-13 15:06:51 +0000 | [diff] [blame] | 120 | extern UInt x86g_create_fpucw ( UInt fpround ); |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 121 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame] | 122 | extern ULong x86g_check_ldmxcsr ( UInt mxcsr ); |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 123 | |
sewardj | 38a3f86 | 2005-01-13 15:06:51 +0000 | [diff] [blame] | 124 | extern UInt x86g_create_mxcsr ( UInt sseround ); |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame] | 125 | |
sewardj | fda10af | 2005-10-03 01:02:40 +0000 | [diff] [blame] | 126 | |
sewardj | 3bd6f3e | 2004-12-13 10:48:19 +0000 | [diff] [blame] | 127 | /* Translate a guest virtual_addr into a guest linear address by |
| 128 | consulting the supplied LDT/GDT structures. Their representation |
| 129 | must be as specified in pub/libvex_guest_x86.h. To indicate a |
| 130 | translation failure, 1<<32 is returned. On success, the lower 32 |
| 131 | bits of the returned result indicate the linear address. |
| 132 | */ |
| 133 | extern |
| 134 | ULong x86g_use_seg_selector ( HWord ldt, HWord gdt, |
| 135 | UInt seg_selector, UInt virtual_addr ); |
sewardj | 893aada | 2004-11-29 19:57:54 +0000 | [diff] [blame] | 136 | |
sewardj | 38a3f86 | 2005-01-13 15:06:51 +0000 | [diff] [blame] | 137 | extern ULong x86g_calculate_mmx_pmaddwd ( ULong, ULong ); |
| 138 | extern ULong x86g_calculate_mmx_psadbw ( ULong, ULong ); |
sewardj | 4340dac | 2004-11-20 13:17:04 +0000 | [diff] [blame] | 139 | |
sewardj | 38a3f86 | 2005-01-13 15:06:51 +0000 | [diff] [blame] | 140 | |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 141 | /* --- DIRTY HELPERS --- */ |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 142 | |
florian | bdf99f0 | 2015-01-04 17:20:19 +0000 | [diff] [blame] | 143 | extern ULong x86g_dirtyhelper_loadF80le ( Addr ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 144 | |
florian | bdf99f0 | 2015-01-04 17:20:19 +0000 | [diff] [blame] | 145 | extern void x86g_dirtyhelper_storeF80le ( Addr, ULong ); |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 146 | |
sewardj | 9df271d | 2004-12-31 22:37:42 +0000 | [diff] [blame] | 147 | extern void x86g_dirtyhelper_CPUID_sse0 ( VexGuestX86State* ); |
mjw | 6c65c12 | 2013-08-27 10:19:03 +0000 | [diff] [blame] | 148 | extern void x86g_dirtyhelper_CPUID_mmxext ( VexGuestX86State* ); |
sewardj | 9df271d | 2004-12-31 22:37:42 +0000 | [diff] [blame] | 149 | extern void x86g_dirtyhelper_CPUID_sse1 ( VexGuestX86State* ); |
philippe | 7ffce01 | 2015-06-18 21:31:32 +0000 | [diff] [blame] | 150 | extern void x86g_dirtyhelper_CPUID_sse2 ( VexGuestX86State* ); |
philippe | 6d7c8e4 | 2015-06-17 21:33:19 +0000 | [diff] [blame] | 151 | extern void x86g_dirtyhelper_CPUID_sse3 ( VexGuestX86State* ); |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 152 | |
sewardj | a0e83b0 | 2005-01-06 12:36:38 +0000 | [diff] [blame] | 153 | extern void x86g_dirtyhelper_FINIT ( VexGuestX86State* ); |
| 154 | |
sewardj | d24931d | 2005-03-20 12:51:39 +0000 | [diff] [blame] | 155 | extern void x86g_dirtyhelper_FXSAVE ( VexGuestX86State*, HWord ); |
| 156 | extern void x86g_dirtyhelper_FSAVE ( VexGuestX86State*, HWord ); |
| 157 | extern void x86g_dirtyhelper_FSTENV ( VexGuestX86State*, HWord ); |
| 158 | |
sewardj | 4ed6429 | 2005-08-23 19:24:29 +0000 | [diff] [blame] | 159 | extern ULong x86g_dirtyhelper_RDTSC ( void ); |
| 160 | |
sewardj | d14c570 | 2005-10-29 19:19:51 +0000 | [diff] [blame] | 161 | extern UInt x86g_dirtyhelper_IN ( UInt portno, UInt sz/*1,2 or 4*/ ); |
| 162 | extern void x86g_dirtyhelper_OUT ( UInt portno, UInt data, |
| 163 | UInt sz/*1,2 or 4*/ ); |
| 164 | |
sewardj | b9dc243 | 2010-06-07 16:22:22 +0000 | [diff] [blame] | 165 | extern void x86g_dirtyhelper_SxDT ( void* address, |
| 166 | UInt op /* 0 or 1 */ ); |
| 167 | |
florian | 6ef84be | 2012-08-26 03:20:07 +0000 | [diff] [blame] | 168 | extern VexEmNote |
sewardj | 3800e2d | 2008-05-09 13:24:43 +0000 | [diff] [blame] | 169 | x86g_dirtyhelper_FXRSTOR ( VexGuestX86State*, HWord ); |
| 170 | |
florian | 6ef84be | 2012-08-26 03:20:07 +0000 | [diff] [blame] | 171 | extern VexEmNote |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 172 | x86g_dirtyhelper_FRSTOR ( VexGuestX86State*, HWord ); |
| 173 | |
florian | 6ef84be | 2012-08-26 03:20:07 +0000 | [diff] [blame] | 174 | extern VexEmNote |
sewardj | 7df596b | 2004-12-06 14:29:12 +0000 | [diff] [blame] | 175 | x86g_dirtyhelper_FLDENV ( VexGuestX86State*, HWord ); |
sewardj | 9fc9e78 | 2004-11-26 17:57:40 +0000 | [diff] [blame] | 176 | |
sewardj | 8ea867b | 2004-10-30 19:03:02 +0000 | [diff] [blame] | 177 | |
| 178 | /*---------------------------------------------------------*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 179 | /*--- Condition code stuff ---*/ |
| 180 | /*---------------------------------------------------------*/ |
| 181 | |
| 182 | /* eflags masks */ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 183 | #define X86G_CC_SHIFT_O 11 |
| 184 | #define X86G_CC_SHIFT_S 7 |
| 185 | #define X86G_CC_SHIFT_Z 6 |
| 186 | #define X86G_CC_SHIFT_A 4 |
| 187 | #define X86G_CC_SHIFT_C 0 |
| 188 | #define X86G_CC_SHIFT_P 2 |
sewardj | 9aebb0c | 2004-10-24 19:20:43 +0000 | [diff] [blame] | 189 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 190 | #define X86G_CC_MASK_O (1 << X86G_CC_SHIFT_O) |
| 191 | #define X86G_CC_MASK_S (1 << X86G_CC_SHIFT_S) |
| 192 | #define X86G_CC_MASK_Z (1 << X86G_CC_SHIFT_Z) |
| 193 | #define X86G_CC_MASK_A (1 << X86G_CC_SHIFT_A) |
| 194 | #define X86G_CC_MASK_C (1 << X86G_CC_SHIFT_C) |
| 195 | #define X86G_CC_MASK_P (1 << X86G_CC_SHIFT_P) |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 196 | |
sewardj | 3e5d82d | 2015-07-21 14:43:23 +0000 | [diff] [blame] | 197 | /* additional eflags masks */ |
| 198 | #define X86G_CC_SHIFT_ID 21 |
| 199 | #define X86G_CC_SHIFT_AC 18 |
| 200 | #define X86G_CC_SHIFT_D 10 |
| 201 | |
| 202 | #define X86G_CC_MASK_ID (1 << X86G_CC_SHIFT_ID) |
| 203 | #define X86G_CC_MASK_AC (1 << X86G_CC_SHIFT_AC) |
| 204 | #define X86G_CC_MASK_D (1 << X86G_CC_SHIFT_D) |
| 205 | |
sewardj | c4be80c | 2004-09-10 16:17:45 +0000 | [diff] [blame] | 206 | /* FPU flag masks */ |
sewardj | e128ea1 | 2005-03-25 22:33:54 +0000 | [diff] [blame] | 207 | #define X86G_FC_SHIFT_C3 14 |
| 208 | #define X86G_FC_SHIFT_C2 10 |
| 209 | #define X86G_FC_SHIFT_C1 9 |
| 210 | #define X86G_FC_SHIFT_C0 8 |
| 211 | |
| 212 | #define X86G_FC_MASK_C3 (1 << X86G_FC_SHIFT_C3) |
| 213 | #define X86G_FC_MASK_C2 (1 << X86G_FC_SHIFT_C2) |
| 214 | #define X86G_FC_MASK_C1 (1 << X86G_FC_SHIFT_C1) |
| 215 | #define X86G_FC_MASK_C0 (1 << X86G_FC_SHIFT_C0) |
| 216 | |
sewardj | c4be80c | 2004-09-10 16:17:45 +0000 | [diff] [blame] | 217 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 218 | /* %EFLAGS thunk descriptors. A four-word thunk is used to record |
| 219 | details of the most recent flag-setting operation, so the flags can |
| 220 | be computed later if needed. It is possible to do this a little |
| 221 | more efficiently using a 3-word thunk, but that makes it impossible |
| 222 | to describe the flag data dependencies sufficiently accurately for |
| 223 | Memcheck. Hence 4 words are used, with minimal loss of efficiency. |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 224 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 225 | The four words are: |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 226 | |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 227 | CC_OP, which describes the operation. |
| 228 | |
| 229 | CC_DEP1 and CC_DEP2. These are arguments to the operation. |
| 230 | We want Memcheck to believe that the resulting flags are |
| 231 | data-dependent on both CC_DEP1 and CC_DEP2, hence the |
| 232 | name DEP. |
| 233 | |
| 234 | CC_NDEP. This is a 3rd argument to the operation which is |
| 235 | sometimes needed. We arrange things so that Memcheck does |
| 236 | not believe the resulting flags are data-dependent on CC_NDEP |
| 237 | ("not dependent"). |
| 238 | |
| 239 | To make Memcheck believe that (the definedness of) the encoded |
| 240 | flags depends only on (the definedness of) CC_DEP1 and CC_DEP2 |
| 241 | requires two things: |
| 242 | |
| 243 | (1) In the guest state layout info (x86guest_layout), CC_OP and |
| 244 | CC_NDEP are marked as always defined. |
| 245 | |
| 246 | (2) When passing the thunk components to an evaluation function |
| 247 | (calculate_condition, calculate_eflags, calculate_eflags_c) the |
| 248 | IRCallee's mcx_mask must be set so as to exclude from |
| 249 | consideration all passed args except CC_DEP1 and CC_DEP2. |
| 250 | |
| 251 | Strictly speaking only (2) is necessary for correctness. However, |
| 252 | (1) helps efficiency in that since (2) means we never ask about the |
| 253 | definedness of CC_OP or CC_NDEP, we may as well not even bother to |
| 254 | track their definedness. |
| 255 | |
| 256 | When building the thunk, it is always necessary to write words into |
| 257 | CC_DEP1 and CC_DEP2, even if those args are not used given the |
| 258 | CC_OP field (eg, CC_DEP2 is not used if CC_OP is CC_LOGIC1/2/4). |
| 259 | This is important because otherwise Memcheck could give false |
| 260 | positives as it does not understand the relationship between the |
| 261 | CC_OP field and CC_DEP1 and CC_DEP2, and so believes that the |
| 262 | definedness of the stored flags always depends on both CC_DEP1 and |
| 263 | CC_DEP2. |
| 264 | |
| 265 | However, it is only necessary to set CC_NDEP when the CC_OP value |
| 266 | requires it, because Memcheck ignores CC_NDEP, and the evaluation |
| 267 | functions do understand the CC_OP fields and will only examine |
| 268 | CC_NDEP for suitable values of CC_OP. |
| 269 | |
| 270 | A summary of the field usages is: |
| 271 | |
| 272 | Operation DEP1 DEP2 NDEP |
| 273 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 274 | |
| 275 | add/sub/mul first arg second arg unused |
| 276 | |
| 277 | adc/sbb first arg (second arg) |
| 278 | XOR old_carry old_carry |
| 279 | |
| 280 | and/or/xor result zero unused |
| 281 | |
| 282 | inc/dec result zero old_carry |
| 283 | |
| 284 | shl/shr/sar result subshifted- unused |
| 285 | result |
| 286 | |
| 287 | rol/ror result zero old_flags |
| 288 | |
| 289 | copy old_flags zero unused. |
| 290 | |
| 291 | |
| 292 | Therefore Memcheck will believe the following: |
| 293 | |
| 294 | * add/sub/mul -- definedness of result flags depends on definedness |
| 295 | of both args. |
| 296 | |
| 297 | * adc/sbb -- definedness of result flags depends on definedness of |
| 298 | both args and definedness of the old C flag. Because only two |
| 299 | DEP fields are available, the old C flag is XOR'd into the second |
| 300 | arg so that Memcheck sees the data dependency on it. That means |
| 301 | the NDEP field must contain a second copy of the old C flag |
| 302 | so that the evaluation functions can correctly recover the second |
| 303 | arg. |
| 304 | |
| 305 | * and/or/xor are straightforward -- definedness of result flags |
| 306 | depends on definedness of result value. |
| 307 | |
| 308 | * inc/dec -- definedness of result flags depends only on |
| 309 | definedness of result. This isn't really true -- it also depends |
| 310 | on the old C flag. However, we don't want Memcheck to see that, |
| 311 | and so the old C flag must be passed in NDEP and not in DEP2. |
| 312 | It's inconceivable that a compiler would generate code that puts |
| 313 | the C flag in an undefined state, then does an inc/dec, which |
| 314 | leaves C unchanged, and then makes a conditional jump/move based |
| 315 | on C. So our fiction seems a good approximation. |
| 316 | |
| 317 | * shl/shr/sar -- straightforward, again, definedness of result |
| 318 | flags depends on definedness of result value. The subshifted |
| 319 | value (value shifted one less) is also needed, but its |
| 320 | definedness is the same as the definedness of the shifted value. |
| 321 | |
| 322 | * rol/ror -- these only set O and C, and leave A Z C P alone. |
| 323 | However it seems prudent (as per inc/dec) to say the definedness |
| 324 | of all resulting flags depends on the definedness of the result, |
| 325 | hence the old flags must go in as NDEP and not DEP2. |
| 326 | |
| 327 | * rcl/rcr are too difficult to do in-line, and so are done by a |
| 328 | helper function. They are not part of this scheme. The helper |
| 329 | function takes the value to be rotated, the rotate amount and the |
| 330 | old flags, and returns the new flags and the rotated value. |
| 331 | Since the helper's mcx_mask does not have any set bits, Memcheck |
| 332 | will lazily propagate undefinedness from any of the 3 args into |
| 333 | both results (flags and actual value). |
sewardj | 948d48b | 2004-11-05 19:49:09 +0000 | [diff] [blame] | 334 | */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 335 | enum { |
sewardj | 63663e3 | 2005-01-22 11:00:07 +0000 | [diff] [blame] | 336 | X86G_CC_OP_COPY=0, /* DEP1 = current flags, DEP2 = 0, NDEP = unused */ |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 337 | /* just copy DEP1 to output */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 338 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 339 | X86G_CC_OP_ADDB, /* 1 */ |
| 340 | X86G_CC_OP_ADDW, /* 2 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 341 | X86G_CC_OP_ADDL, /* 3 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 342 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 343 | X86G_CC_OP_SUBB, /* 4 */ |
| 344 | X86G_CC_OP_SUBW, /* 5 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 345 | X86G_CC_OP_SUBL, /* 6 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 346 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 347 | X86G_CC_OP_ADCB, /* 7 */ |
| 348 | X86G_CC_OP_ADCW, /* 8 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ |
| 349 | X86G_CC_OP_ADCL, /* 9 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 350 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 351 | X86G_CC_OP_SBBB, /* 10 */ |
| 352 | X86G_CC_OP_SBBW, /* 11 DEP1 = argL, DEP2 = argR ^ oldCarry, NDEP = oldCarry */ |
| 353 | X86G_CC_OP_SBBL, /* 12 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 354 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 355 | X86G_CC_OP_LOGICB, /* 13 */ |
| 356 | X86G_CC_OP_LOGICW, /* 14 DEP1 = result, DEP2 = 0, NDEP = unused */ |
| 357 | X86G_CC_OP_LOGICL, /* 15 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 358 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 359 | X86G_CC_OP_INCB, /* 16 */ |
| 360 | X86G_CC_OP_INCW, /* 17 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ |
| 361 | X86G_CC_OP_INCL, /* 18 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 362 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 363 | X86G_CC_OP_DECB, /* 19 */ |
| 364 | X86G_CC_OP_DECW, /* 20 DEP1 = result, DEP2 = 0, NDEP = oldCarry (0 or 1) */ |
| 365 | X86G_CC_OP_DECL, /* 21 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 366 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 367 | X86G_CC_OP_SHLB, /* 22 DEP1 = res, DEP2 = res', NDEP = unused */ |
| 368 | X86G_CC_OP_SHLW, /* 23 where res' is like res but shifted one bit less */ |
| 369 | X86G_CC_OP_SHLL, /* 24 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 370 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 371 | X86G_CC_OP_SHRB, /* 25 DEP1 = res, DEP2 = res', NDEP = unused */ |
| 372 | X86G_CC_OP_SHRW, /* 26 where res' is like res but shifted one bit less */ |
| 373 | X86G_CC_OP_SHRL, /* 27 */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 374 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 375 | X86G_CC_OP_ROLB, /* 28 */ |
| 376 | X86G_CC_OP_ROLW, /* 29 DEP1 = res, DEP2 = 0, NDEP = old flags */ |
| 377 | X86G_CC_OP_ROLL, /* 30 */ |
sewardj | 1813dbe | 2004-07-28 17:09:04 +0000 | [diff] [blame] | 378 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 379 | X86G_CC_OP_RORB, /* 31 */ |
| 380 | X86G_CC_OP_RORW, /* 32 DEP1 = res, DEP2 = 0, NDEP = old flags */ |
| 381 | X86G_CC_OP_RORL, /* 33 */ |
sewardj | 1813dbe | 2004-07-28 17:09:04 +0000 | [diff] [blame] | 382 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 383 | X86G_CC_OP_UMULB, /* 34 */ |
| 384 | X86G_CC_OP_UMULW, /* 35 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 385 | X86G_CC_OP_UMULL, /* 36 */ |
sewardj | cf780b4 | 2004-07-13 18:42:17 +0000 | [diff] [blame] | 386 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 387 | X86G_CC_OP_SMULB, /* 37 */ |
| 388 | X86G_CC_OP_SMULW, /* 38 DEP1 = argL, DEP2 = argR, NDEP = unused */ |
| 389 | X86G_CC_OP_SMULL, /* 39 */ |
sewardj | cf780b4 | 2004-07-13 18:42:17 +0000 | [diff] [blame] | 390 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 391 | X86G_CC_OP_NUMBER |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 392 | }; |
| 393 | |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 394 | typedef |
| 395 | enum { |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 396 | X86CondO = 0, /* overflow */ |
| 397 | X86CondNO = 1, /* no overflow */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 398 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 399 | X86CondB = 2, /* below */ |
| 400 | X86CondNB = 3, /* not below */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 401 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 402 | X86CondZ = 4, /* zero */ |
| 403 | X86CondNZ = 5, /* not zero */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 404 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 405 | X86CondBE = 6, /* below or equal */ |
| 406 | X86CondNBE = 7, /* not below or equal */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 407 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 408 | X86CondS = 8, /* negative */ |
| 409 | X86CondNS = 9, /* not negative */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 410 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 411 | X86CondP = 10, /* parity even */ |
| 412 | X86CondNP = 11, /* not parity even */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 413 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 414 | X86CondL = 12, /* jump less */ |
| 415 | X86CondNL = 13, /* not less */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 416 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 417 | X86CondLE = 14, /* less or equal */ |
| 418 | X86CondNLE = 15, /* not less or equal */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 419 | |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 420 | X86CondAlways = 16 /* HACK */ |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 421 | } |
sewardj | 2a9ad02 | 2004-11-25 02:46:58 +0000 | [diff] [blame] | 422 | X86Condcode; |
sewardj | 84ff065 | 2004-08-23 16:16:08 +0000 | [diff] [blame] | 423 | |
sewardj | cef7d3e | 2009-07-02 12:21:59 +0000 | [diff] [blame] | 424 | #endif /* ndef __VEX_GUEST_X86_DEFS_H */ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 425 | |
| 426 | /*---------------------------------------------------------------*/ |
sewardj | cef7d3e | 2009-07-02 12:21:59 +0000 | [diff] [blame] | 427 | /*--- end guest_x86_defs.h ---*/ |
sewardj | c9a6570 | 2004-07-07 16:32:57 +0000 | [diff] [blame] | 428 | /*---------------------------------------------------------------*/ |