blob: ac95b045aa479c50fbfddf806aba7ae9f848805f [file] [log] [blame]
sewardj0c2cb622004-09-06 23:21:21 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (libvex_guest_x86.h) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
sewardjf8ed9d82004-11-12 17:40:23 +00009/*
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
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"
sewardj893aada2004-11-29 19:57:54 +000040#include "libvex_emwarn.h"
41
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
123 (denormals-are-zeroes) to 1. */
sewardjf6dc3ce2004-10-19 01:03:46 +0000124
125typedef
126 struct {
sewardj70f676d2004-12-10 14:59:57 +0000127 UInt guest_EAX; /* 0 */
sewardjf6dc3ce2004-10-19 01:03:46 +0000128 UInt guest_ECX;
129 UInt guest_EDX;
130 UInt guest_EBX;
131 UInt guest_ESP;
132 UInt guest_EBP;
133 UInt guest_ESI;
sewardj70f676d2004-12-10 14:59:57 +0000134 UInt guest_EDI; /* 28 */
sewardj2a2ba8b2004-11-08 13:14:06 +0000135 /* 4-word thunk used to calculate O S Z A C P flags. */
sewardj70f676d2004-12-10 14:59:57 +0000136 UInt guest_CC_OP; /* 32 */
sewardj2a2ba8b2004-11-08 13:14:06 +0000137 UInt guest_CC_DEP1;
138 UInt guest_CC_DEP2;
sewardj70f676d2004-12-10 14:59:57 +0000139 UInt guest_CC_NDEP; /* 44 */
sewardj2a2ba8b2004-11-08 13:14:06 +0000140 /* The D flag is stored here, encoded as either -1 or +1 */
sewardj70f676d2004-12-10 14:59:57 +0000141 UInt guest_DFLAG; /* 48 */
sewardj006a6a22004-10-26 00:50:52 +0000142 /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */
sewardj70f676d2004-12-10 14:59:57 +0000143 UInt guest_IDFLAG; /* 52 */
sewardjf6dc3ce2004-10-19 01:03:46 +0000144 /* EIP */
sewardj70f676d2004-12-10 14:59:57 +0000145 UInt guest_EIP; /* 56 */
sewardjf6dc3ce2004-10-19 01:03:46 +0000146 /* FPU */
sewardj70f676d2004-12-10 14:59:57 +0000147 UInt guest_FTOP; /* 60 */
148 ULong guest_FPREG[8]; /* 64 */
149 UChar guest_FPTAG[8]; /* 128 */
150 UInt guest_FPROUND; /* 136 */
151 UInt guest_FC3210; /* 140 */
sewardjc9a43662004-11-30 18:51:59 +0000152 /* SSE */
sewardj70f676d2004-12-10 14:59:57 +0000153 UInt guest_SSEROUND; /* 144 */
154 U128 guest_XMM0; /* 148 */
sewardjc9a43662004-11-30 18:51:59 +0000155 U128 guest_XMM1;
156 U128 guest_XMM2;
157 U128 guest_XMM3;
158 U128 guest_XMM4;
159 U128 guest_XMM5;
160 U128 guest_XMM6;
161 U128 guest_XMM7;
sewardj063f02f2004-10-20 12:36:12 +0000162 /* Segment registers. */
163 UShort guest_CS;
164 UShort guest_DS;
165 UShort guest_ES;
166 UShort guest_FS;
167 UShort guest_GS;
168 UShort guest_SS;
sewardj893aada2004-11-29 19:57:54 +0000169 /* Emulation warnings */
170 UInt guest_EMWARN;
sewardj81ec4182004-10-25 23:15:52 +0000171 /* Padding to make it have an 8-aligned size */
sewardjc9a43662004-11-30 18:51:59 +0000172 UInt padding;
sewardjf6dc3ce2004-10-19 01:03:46 +0000173 }
174 VexGuestX86State;
175
176
sewardj8d2291c2004-10-25 14:50:21 +0000177
sewardjf6dc3ce2004-10-19 01:03:46 +0000178/*---------------------------------------------------------------*/
sewardj0c2cb622004-09-06 23:21:21 +0000179/*--- Utility functions for x86 guest stuff. ---*/
180/*---------------------------------------------------------------*/
181
sewardj8d2291c2004-10-25 14:50:21 +0000182
sewardj8d2291c2004-10-25 14:50:21 +0000183/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
184
sewardj76bdc802004-10-25 15:33:26 +0000185
186/* Initialise all guest x86 state. The FPU is put in default mode. */
187extern
188void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state );
189
190
sewardjf6dc3ce2004-10-19 01:03:46 +0000191/* Convert a saved x87 FPU image (as created by fsave) and write it
192 into the supplied VexGuestX86State structure. The non-FP parts of
sewardj893aada2004-11-29 19:57:54 +0000193 said structure are left unchanged. May return an emulation warning
194 value.
sewardj0c2cb622004-09-06 23:21:21 +0000195*/
sewardjf6dc3ce2004-10-19 01:03:46 +0000196extern
sewardj893aada2004-11-29 19:57:54 +0000197VexEmWarn
198 LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state,
sewardj76bdc802004-10-25 15:33:26 +0000199 /*OUT*/VexGuestX86State* vex_state );
sewardj0c2cb622004-09-06 23:21:21 +0000200
sewardjf6dc3ce2004-10-19 01:03:46 +0000201/* Extract from the supplied VexGuestX86State structure, an x87 FPU
202 image. */
203extern
sewardj76bdc802004-10-25 15:33:26 +0000204void LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state,
205 /*OUT*/UChar* x87_state );
sewardjf6dc3ce2004-10-19 01:03:46 +0000206
207
208/* Given a 32-bit word containing native x86 %eflags values, set the
209 eflag-related fields in the supplied VexGuestX86State accordingly.
210 All other fields are left unchanged. */
211
212extern
sewardj76bdc802004-10-25 15:33:26 +0000213void LibVEX_GuestX86_put_eflags ( UInt eflags_native,
214 /*OUT*/VexGuestX86State* vex_state );
sewardjf6dc3ce2004-10-19 01:03:46 +0000215
216/* Extract from the supplied VexGuestX86State structure the
217 corresponding native %eflags value. */
218
219extern
sewardj76bdc802004-10-25 15:33:26 +0000220UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state );
sewardjf6dc3ce2004-10-19 01:03:46 +0000221
sewardj0c2cb622004-09-06 23:21:21 +0000222
223#endif /* ndef __LIBVEX_PUB_GUEST_X86_H */
224
225/*---------------------------------------------------------------*/
226/*--- libvex_guest_x86.h ---*/
227/*---------------------------------------------------------------*/