sewardj | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 1 | |
| 2 | /*---------------------------------------------------------------*/ |
| 3 | /*--- ---*/ |
| 4 | /*--- This file (libvex_guest_x86.h) is ---*/ |
| 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 | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 36 | #ifndef __LIBVEX_PUB_GUEST_X86_H |
| 37 | #define __LIBVEX_PUB_GUEST_X86_H |
| 38 | |
| 39 | #include "libvex_basictypes.h" |
| 40 | |
| 41 | /*---------------------------------------------------------------*/ |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 42 | /*--- Vex's representation of the x86 CPU state. ---*/ |
| 43 | /*---------------------------------------------------------------*/ |
| 44 | |
| 45 | /* The integer parts should be pretty straightforward. */ |
| 46 | |
| 47 | /* Hmm, subregisters. The simulated state is stored in memory in the |
| 48 | host's byte ordering, so we can't say here what the offsets of %ax, |
| 49 | %al, %ah etc are since that depends on the host's byte ordering, |
| 50 | which we don't know. */ |
| 51 | |
| 52 | /* FPU. For now, just simulate 8 64-bit registers, their tags, and |
| 53 | the reg-stack top pointer, of which only the least significant |
| 54 | three bits are relevant. |
| 55 | |
| 56 | The model is: |
| 57 | F0 .. F7 are the 8 registers. FTOP[2:0] contains the |
| 58 | index of the current 'stack top' -- pretty meaningless, but |
| 59 | still. FTOP is a 32-bit value. FTOP[31:3] can be anything |
| 60 | (not guaranteed to be zero). |
| 61 | |
| 62 | When a value is pushed onto the stack, ftop is first replaced by |
| 63 | (ftop-1) & 7, and then F[ftop] is assigned the value. |
| 64 | |
| 65 | When a value is popped off the stack, the value is read from |
| 66 | F[ftop], and then ftop is replaced by (ftop+1) & 7. |
| 67 | |
| 68 | In general, a reference to a register ST(i) actually references |
| 69 | F[ (ftop+i) & 7 ]. |
| 70 | |
| 71 | FTAG0 .. FTAG0+7 are the tags. Each is a byte, zero means empty, |
| 72 | non-zero means non-empty. |
| 73 | |
| 74 | The general rule appears to be that a read or modify of a register |
| 75 | gets a stack underflow fault if the register is empty. A write of |
| 76 | a register (only a write, not a modify) gets a stack overflow fault |
| 77 | if the register is full. Note that "over" vs "under" is pretty |
| 78 | meaningless since the FP stack pointer can move around arbitrarily, |
| 79 | so it's really just two different kinds of exceptions: |
| 80 | register-empty and register full. |
| 81 | |
| 82 | Naturally Intel (in its infinite wisdom) has seen fit to throw in |
| 83 | some ad-hoc inconsistencies to the fault-generation rules of the |
| 84 | above para, just to complicate everything. Known inconsistencies: |
| 85 | |
| 86 | * fxam can read a register in any state without taking an underflow |
| 87 | fault. |
| 88 | |
| 89 | * fst from st(0) to st(i) does not take an overflow fault even if the |
| 90 | destination is already full. |
| 91 | |
| 92 | FPUCW[15:0] is the FPU's control word. FPUCW[31:16] is unused. |
| 93 | |
| 94 | FC3210 contains the C3, C2, C1 and C0 bits in the same place they |
| 95 | are in the FPU's status word. (bits 14, 10, 9, 8 respectively). |
| 96 | All other bits should be zero. The relevant mask to select just |
| 97 | those bits is 0x4700. To select C3, C2 and C0 only, the mask is |
| 98 | 0x4500. |
| 99 | */ |
| 100 | |
| 101 | typedef |
| 102 | struct { |
| 103 | UInt guest_EAX; |
| 104 | UInt guest_ECX; |
| 105 | UInt guest_EDX; |
| 106 | UInt guest_EBX; |
| 107 | UInt guest_ESP; |
| 108 | UInt guest_EBP; |
| 109 | UInt guest_ESI; |
| 110 | UInt guest_EDI; |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 111 | /* 4-word thunk used to calculate O S Z A C P flags. */ |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 112 | UInt guest_CC_OP; |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 113 | UInt guest_CC_DEP1; |
| 114 | UInt guest_CC_DEP2; |
| 115 | UInt guest_CC_NDEP; |
| 116 | /* The D flag is stored here, encoded as either -1 or +1 */ |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 117 | UInt guest_DFLAG; |
sewardj | 006a6a2 | 2004-10-26 00:50:52 +0000 | [diff] [blame] | 118 | /* Bit 21 (ID) of eflags stored here, as either 0 or 1. */ |
| 119 | UInt guest_IDFLAG; |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 120 | /* EIP */ |
| 121 | UInt guest_EIP; |
| 122 | /* FPU */ |
| 123 | UInt guest_FTOP; |
| 124 | ULong guest_FPREG[8]; |
| 125 | UChar guest_FPTAG[8]; |
| 126 | UInt guest_FPUCW; |
| 127 | UInt guest_FC3210; |
sewardj | 063f02f | 2004-10-20 12:36:12 +0000 | [diff] [blame] | 128 | /* Segment registers. */ |
| 129 | UShort guest_CS; |
| 130 | UShort guest_DS; |
| 131 | UShort guest_ES; |
| 132 | UShort guest_FS; |
| 133 | UShort guest_GS; |
| 134 | UShort guest_SS; |
sewardj | 81ec418 | 2004-10-25 23:15:52 +0000 | [diff] [blame] | 135 | /* Padding to make it have an 8-aligned size */ |
sewardj | 2a2ba8b | 2004-11-08 13:14:06 +0000 | [diff] [blame] | 136 | UInt padding; |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 137 | } |
| 138 | VexGuestX86State; |
| 139 | |
| 140 | |
sewardj | 8d2291c | 2004-10-25 14:50:21 +0000 | [diff] [blame] | 141 | |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 142 | /*---------------------------------------------------------------*/ |
sewardj | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 143 | /*--- Utility functions for x86 guest stuff. ---*/ |
| 144 | /*---------------------------------------------------------------*/ |
| 145 | |
sewardj | 8d2291c | 2004-10-25 14:50:21 +0000 | [diff] [blame] | 146 | |
sewardj | 8d2291c | 2004-10-25 14:50:21 +0000 | [diff] [blame] | 147 | /* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */ |
| 148 | |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 149 | |
| 150 | /* Initialise all guest x86 state. The FPU is put in default mode. */ |
| 151 | extern |
| 152 | void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ); |
| 153 | |
| 154 | |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 155 | /* Convert a saved x87 FPU image (as created by fsave) and write it |
| 156 | into the supplied VexGuestX86State structure. The non-FP parts of |
| 157 | said structure are left unchanged. |
sewardj | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 158 | */ |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 159 | extern |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 160 | void LibVEX_GuestX86_put_x87 ( /*IN*/UChar* x87_state, |
| 161 | /*OUT*/VexGuestX86State* vex_state ); |
sewardj | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 162 | |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 163 | /* Extract from the supplied VexGuestX86State structure, an x87 FPU |
| 164 | image. */ |
| 165 | extern |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 166 | void LibVEX_GuestX86_get_x87 ( /*IN*/VexGuestX86State* vex_state, |
| 167 | /*OUT*/UChar* x87_state ); |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 168 | |
| 169 | |
| 170 | /* Given a 32-bit word containing native x86 %eflags values, set the |
| 171 | eflag-related fields in the supplied VexGuestX86State accordingly. |
| 172 | All other fields are left unchanged. */ |
| 173 | |
| 174 | extern |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 175 | void LibVEX_GuestX86_put_eflags ( UInt eflags_native, |
| 176 | /*OUT*/VexGuestX86State* vex_state ); |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 177 | |
| 178 | /* Extract from the supplied VexGuestX86State structure the |
| 179 | corresponding native %eflags value. */ |
| 180 | |
| 181 | extern |
sewardj | 76bdc80 | 2004-10-25 15:33:26 +0000 | [diff] [blame] | 182 | UInt LibVEX_GuestX86_get_eflags ( /*IN*/VexGuestX86State* vex_state ); |
sewardj | f6dc3ce | 2004-10-19 01:03:46 +0000 | [diff] [blame] | 183 | |
sewardj | 0c2cb62 | 2004-09-06 23:21:21 +0000 | [diff] [blame] | 184 | |
| 185 | #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */ |
| 186 | |
| 187 | /*---------------------------------------------------------------*/ |
| 188 | /*--- libvex_guest_x86.h ---*/ |
| 189 | /*---------------------------------------------------------------*/ |