blob: 166c63e6bc8ee1083823627a6d80a1f501d591ac [file] [log] [blame]
sewardj0c2cb622004-09-06 23:21:21 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin libvex_guest_x86.h ---*/
sewardj0c2cb622004-09-06 23:21:21 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardj25e54732012-08-05 15:36:51 +000010 Copyright (C) 2004-2012 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardj0c2cb622004-09-06 23:21:21 +000036#ifndef __LIBVEX_PUB_GUEST_X86_H
37#define __LIBVEX_PUB_GUEST_X86_H
38
39#include "libvex_basictypes.h"
florian33b02432012-08-25 21:48:04 +000040#include "libvex_emnote.h"
sewardj893aada2004-11-29 19:57:54 +000041
sewardj0c2cb622004-09-06 23:21:21 +000042
43/*---------------------------------------------------------------*/
sewardjf6dc3ce2004-10-19 01:03:46 +000044/*--- Vex's representation of the x86 CPU state. ---*/
45/*---------------------------------------------------------------*/
46
47/* The integer parts should be pretty straightforward. */
48
49/* Hmm, subregisters. The simulated state is stored in memory in the
50 host's byte ordering, so we can't say here what the offsets of %ax,
51 %al, %ah etc are since that depends on the host's byte ordering,
52 which we don't know. */
53
54/* FPU. For now, just simulate 8 64-bit registers, their tags, and
55 the reg-stack top pointer, of which only the least significant
56 three bits are relevant.
57
58 The model is:
59 F0 .. F7 are the 8 registers. FTOP[2:0] contains the
60 index of the current 'stack top' -- pretty meaningless, but
61 still. FTOP is a 32-bit value. FTOP[31:3] can be anything
62 (not guaranteed to be zero).
63
64 When a value is pushed onto the stack, ftop is first replaced by
65 (ftop-1) & 7, and then F[ftop] is assigned the value.
66
67 When a value is popped off the stack, the value is read from
68 F[ftop], and then ftop is replaced by (ftop+1) & 7.
69
70 In general, a reference to a register ST(i) actually references
71 F[ (ftop+i) & 7 ].
72
73 FTAG0 .. FTAG0+7 are the tags. Each is a byte, zero means empty,
74 non-zero means non-empty.
75
76 The general rule appears to be that a read or modify of a register
77 gets a stack underflow fault if the register is empty. A write of
78 a register (only a write, not a modify) gets a stack overflow fault
79 if the register is full. Note that "over" vs "under" is pretty
80 meaningless since the FP stack pointer can move around arbitrarily,
81 so it's really just two different kinds of exceptions:
82 register-empty and register full.
83
84 Naturally Intel (in its infinite wisdom) has seen fit to throw in
85 some ad-hoc inconsistencies to the fault-generation rules of the
86 above para, just to complicate everything. Known inconsistencies:
87
88 * fxam can read a register in any state without taking an underflow
89 fault.
90
91 * fst from st(0) to st(i) does not take an overflow fault even if the
92 destination is already full.
93
sewardjd01a9632004-11-30 13:18:37 +000094 FPROUND[1:0] is the FPU's notional rounding mode, encoded as per
95 the IRRoundingMode type (see libvex_ir.h). This just happens to be
96 the Intel encoding. Note carefully, the rounding mode is only
sewardj7df596b2004-12-06 14:29:12 +000097 observed on float-to-int conversions, and on float-to-float
98 rounding, but not for general float-to-float operations, which are
99 always rounded-to-nearest.
100
101 Loads/stores of the FPU control word are faked accordingly -- on
102 loads, everything except the rounding mode is ignored, and on
103 stores, you get a vanilla control world (0x037F) with the rounding
104 mode patched in. Hence the only values you can get are 0x037F,
105 0x077F, 0x0B7F or 0x0F7F. Vex will emit an emulation warning if
106 you try and load a control word which either (1) unmasks FP
107 exceptions, or (2) changes the default (80-bit) precision.
sewardjf6dc3ce2004-10-19 01:03:46 +0000108
109 FC3210 contains the C3, C2, C1 and C0 bits in the same place they
110 are in the FPU's status word. (bits 14, 10, 9, 8 respectively).
111 All other bits should be zero. The relevant mask to select just
112 those bits is 0x4700. To select C3, C2 and C0 only, the mask is
sewardj7df596b2004-12-06 14:29:12 +0000113 0x4500.
114
115 SSEROUND[1:0] is the SSE unit's notional rounding mode, encoded as
116 per the IRRoundingMode type. As with the FPU control word, the
117 rounding mode is the only part of %MXCSR that Vex observes. On
118 storing %MXCSR, you will get a vanilla word (0x1F80) with the
119 rounding mode patched in. Hence the only values you will get are
120 0x1F80, 0x3F80, 0x5F80 or 0x7F80. Vex will emit an emulation
121 warning if you try and load a control word which either (1) unmasks
122 any exceptions, (2) sets FZ (flush-to-zero) to 1, or (3) sets DAZ
sewardj3bd6f3e2004-12-13 10:48:19 +0000123 (denormals-are-zeroes) to 1.
sewardjf6dc3ce2004-10-19 01:03:46 +0000124
sewardj3bd6f3e2004-12-13 10:48:19 +0000125 Segments: initial prefixes of local and global segment descriptor
126 tables are modelled. guest_LDT is either zero (NULL) or points in
127 the host address space to an array of VEX_GUEST_X86_LDT_NENT
128 descriptors, which have the type VexGuestX86SegDescr, defined
129 below. Similarly, guest_GDT is either zero or points in the host
130 address space to an array of VEX_GUEST_X86_GDT_NENT descriptors.
131 The only place where these are used are in the helper function
132 x86g_use_seg(). LibVEX's client is responsible for pointing
133 guest_LDT and guest_GDT at suitable tables. The contents of these
134 tables are expected not to change during the execution of any given
135 superblock, but they may validly be changed by LibVEX's client in
136 between superblock executions.
137
138 Since x86g_use_seg() only expects these tables to have
139 VEX_GUEST_X86_{LDT,GDT}_NENT entries, LibVEX's client should not
140 attempt to write entries beyond those limits.
141*/
sewardjf6dc3ce2004-10-19 01:03:46 +0000142typedef
143 struct {
sewardjc6f970f2012-04-02 21:54:49 +0000144 /* Event check fail addr and counter. */
145 UInt host_EvC_FAILADDR; /* 0 */
146 UInt host_EvC_COUNTER; /* 4 */
147 UInt guest_EAX; /* 8 */
sewardjf6dc3ce2004-10-19 01:03:46 +0000148 UInt guest_ECX;
149 UInt guest_EDX;
150 UInt guest_EBX;
151 UInt guest_ESP;
152 UInt guest_EBP;
153 UInt guest_ESI;
sewardjc6f970f2012-04-02 21:54:49 +0000154 UInt guest_EDI; /* 36 */
sewardj6d269842005-08-06 11:45:02 +0000155
sewardj2a2ba8b2004-11-08 13:14:06 +0000156 /* 4-word thunk used to calculate O S Z A C P flags. */
sewardjc6f970f2012-04-02 21:54:49 +0000157 UInt guest_CC_OP; /* 40 */
sewardj2a2ba8b2004-11-08 13:14:06 +0000158 UInt guest_CC_DEP1;
159 UInt guest_CC_DEP2;
sewardjc6f970f2012-04-02 21:54:49 +0000160 UInt guest_CC_NDEP; /* 52 */
sewardj2a2ba8b2004-11-08 13:14:06 +0000161 /* The D flag is stored here, encoded as either -1 or +1 */
sewardjc6f970f2012-04-02 21:54:49 +0000162 UInt guest_DFLAG; /* 56 */
sewardj006a6a22004-10-26 00:50:52 +0000163 /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */
sewardjc6f970f2012-04-02 21:54:49 +0000164 UInt guest_IDFLAG; /* 60 */
sewardj6d269842005-08-06 11:45:02 +0000165 /* Bit 18 (AC) of eflags stored here, as either 0 or 1. */
sewardjc6f970f2012-04-02 21:54:49 +0000166 UInt guest_ACFLAG; /* 64 */
sewardj6d269842005-08-06 11:45:02 +0000167
sewardjf6dc3ce2004-10-19 01:03:46 +0000168 /* EIP */
sewardjc6f970f2012-04-02 21:54:49 +0000169 UInt guest_EIP; /* 68 */
sewardj6d269842005-08-06 11:45:02 +0000170
sewardjf6dc3ce2004-10-19 01:03:46 +0000171 /* FPU */
sewardjc6f970f2012-04-02 21:54:49 +0000172 ULong guest_FPREG[8]; /* 72 */
173 UChar guest_FPTAG[8]; /* 136 */
174 UInt guest_FPROUND; /* 144 */
175 UInt guest_FC3210; /* 148 */
176 UInt guest_FTOP; /* 152 */
sewardj6d269842005-08-06 11:45:02 +0000177
sewardjc9a43662004-11-30 18:51:59 +0000178 /* SSE */
sewardjc6f970f2012-04-02 21:54:49 +0000179 UInt guest_SSEROUND; /* 156 */
180 U128 guest_XMM0; /* 160 */
sewardjc9a43662004-11-30 18:51:59 +0000181 U128 guest_XMM1;
182 U128 guest_XMM2;
183 U128 guest_XMM3;
184 U128 guest_XMM4;
185 U128 guest_XMM5;
186 U128 guest_XMM6;
187 U128 guest_XMM7;
sewardj6d269842005-08-06 11:45:02 +0000188
sewardj063f02f2004-10-20 12:36:12 +0000189 /* Segment registers. */
190 UShort guest_CS;
191 UShort guest_DS;
192 UShort guest_ES;
193 UShort guest_FS;
194 UShort guest_GS;
195 UShort guest_SS;
sewardj3bd6f3e2004-12-13 10:48:19 +0000196 /* LDT/GDT stuff. */
197 HWord guest_LDT; /* host addr, a VexGuestX86SegDescr* */
198 HWord guest_GDT; /* host addr, a VexGuestX86SegDescr* */
sewardj1f126c52005-03-16 13:57:58 +0000199
sewardj893aada2004-11-29 19:57:54 +0000200 /* Emulation warnings */
201 UInt guest_EMWARN;
sewardj1f126c52005-03-16 13:57:58 +0000202
sewardjce02aa72006-01-12 12:27:58 +0000203 /* For clflush: record start and length of area to invalidate */
sewardj1f126c52005-03-16 13:57:58 +0000204 UInt guest_TISTART;
205 UInt guest_TILEN;
206
sewardjce02aa72006-01-12 12:27:58 +0000207 /* Used to record the unredirected guest address at the start of
208 a translation whose start has been redirected. By reading
209 this pseudo-register shortly afterwards, the translation can
210 find out what the corresponding no-redirection address was.
211 Note, this is only set for wrap-style redirects, not for
212 replace-style ones. */
213 UInt guest_NRADDR;
214
sewardjd660d412008-12-03 21:29:59 +0000215 /* Used for Darwin syscall dispatching. */
216 UInt guest_SC_CLASS;
217
sewardje86310f2009-03-19 22:21:40 +0000218 /* Needed for Darwin (but mandated for all guest architectures):
219 EIP at the last syscall insn (int 0x80/81/82, sysenter,
220 syscall). Used when backing up to restart a syscall that has
221 been interrupted by a signal. */
222 UInt guest_IP_AT_SYSCALL;
223
sewardjc4530ae2012-05-21 10:18:49 +0000224 /* Padding to make it have an 32-aligned size */
225 UInt padding[5];
sewardjf6dc3ce2004-10-19 01:03:46 +0000226 }
227 VexGuestX86State;
228
sewardj3f46a012005-11-05 15:46:22 +0000229#define VEX_GUEST_X86_LDT_NENT /*64*/ 8192 /* use complete LDT */
230#define VEX_GUEST_X86_GDT_NENT /*16*/ 8192 /* use complete GDT */
sewardj3bd6f3e2004-12-13 10:48:19 +0000231
232
233/*---------------------------------------------------------------*/
234/*--- Types for x86 guest stuff. ---*/
235/*---------------------------------------------------------------*/
236
237/* VISIBLE TO LIBRARY CLIENT */
238
239/* This is the hardware-format for a segment descriptor, ie what the
240 x86 actually deals with. It is 8 bytes long. It's ugly. */
241
242typedef struct {
243 union {
244 struct {
245 UShort LimitLow;
246 UShort BaseLow;
247 UInt BaseMid : 8;
248 UInt Type : 5;
249 UInt Dpl : 2;
250 UInt Pres : 1;
251 UInt LimitHi : 4;
252 UInt Sys : 1;
253 UInt Reserved_0 : 1;
254 UInt Default_Big : 1;
255 UInt Granularity : 1;
256 UInt BaseHi : 8;
257 } Bits;
258 struct {
259 UInt word1;
260 UInt word2;
261 } Words;
262 }
263 LdtEnt;
264} VexGuestX86SegDescr;
sewardjf6dc3ce2004-10-19 01:03:46 +0000265
sewardj8d2291c2004-10-25 14:50:21 +0000266
sewardjf6dc3ce2004-10-19 01:03:46 +0000267/*---------------------------------------------------------------*/
sewardj0c2cb622004-09-06 23:21:21 +0000268/*--- Utility functions for x86 guest stuff. ---*/
269/*---------------------------------------------------------------*/
270
sewardj8d2291c2004-10-25 14:50:21 +0000271/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
272
sewardj76bdc802004-10-25 15:33:26 +0000273/* Initialise all guest x86 state. The FPU is put in default mode. */
274extern
275void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state );
276
277
sewardjf6dc3ce2004-10-19 01:03:46 +0000278/* Extract from the supplied VexGuestX86State structure the
279 corresponding native %eflags value. */
sewardjf6dc3ce2004-10-19 01:03:46 +0000280extern
sewardj76bdc802004-10-25 15:33:26 +0000281UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state );
sewardjf6dc3ce2004-10-19 01:03:46 +0000282
sewardjf32d5a52006-03-20 12:05:42 +0000283/* Set the carry flag in the given state to 'new_carry_flag', which
284 should be zero or one. */
285extern
286void
287LibVEX_GuestX86_put_eflag_c ( UInt new_carry_flag,
288 /*MOD*/VexGuestX86State* vex_state );
sewardj38a3f862005-01-13 15:06:51 +0000289
sewardj0c2cb622004-09-06 23:21:21 +0000290#endif /* ndef __LIBVEX_PUB_GUEST_X86_H */
291
292/*---------------------------------------------------------------*/
293/*--- libvex_guest_x86.h ---*/
294/*---------------------------------------------------------------*/