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