blob: 72a03e4e5f31b068458464ad99dd427d0f98b1bf [file] [log] [blame]
/*---------------------------------------------------------------*/
/*--- ---*/
/*--- This file (libvex_guest_x86.h) is ---*/
/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
/*--- ---*/
/*---------------------------------------------------------------*/
#ifndef __LIBVEX_PUB_GUEST_X86_H
#define __LIBVEX_PUB_GUEST_X86_H
#include "libvex_basictypes.h"
/*---------------------------------------------------------------*/
/*--- Vex's representation of the x86 CPU state. ---*/
/*---------------------------------------------------------------*/
/* The integer parts should be pretty straightforward. */
/* Hmm, subregisters. The simulated state is stored in memory in the
host's byte ordering, so we can't say here what the offsets of %ax,
%al, %ah etc are since that depends on the host's byte ordering,
which we don't know. */
/* FPU. For now, just simulate 8 64-bit registers, their tags, and
the reg-stack top pointer, of which only the least significant
three bits are relevant.
The model is:
F0 .. F7 are the 8 registers. FTOP[2:0] contains the
index of the current 'stack top' -- pretty meaningless, but
still. FTOP is a 32-bit value. FTOP[31:3] can be anything
(not guaranteed to be zero).
When a value is pushed onto the stack, ftop is first replaced by
(ftop-1) & 7, and then F[ftop] is assigned the value.
When a value is popped off the stack, the value is read from
F[ftop], and then ftop is replaced by (ftop+1) & 7.
In general, a reference to a register ST(i) actually references
F[ (ftop+i) & 7 ].
FTAG0 .. FTAG0+7 are the tags. Each is a byte, zero means empty,
non-zero means non-empty.
The general rule appears to be that a read or modify of a register
gets a stack underflow fault if the register is empty. A write of
a register (only a write, not a modify) gets a stack overflow fault
if the register is full. Note that "over" vs "under" is pretty
meaningless since the FP stack pointer can move around arbitrarily,
so it's really just two different kinds of exceptions:
register-empty and register full.
Naturally Intel (in its infinite wisdom) has seen fit to throw in
some ad-hoc inconsistencies to the fault-generation rules of the
above para, just to complicate everything. Known inconsistencies:
* fxam can read a register in any state without taking an underflow
fault.
* fst from st(0) to st(i) does not take an overflow fault even if the
destination is already full.
FPUCW[15:0] is the FPU's control word. FPUCW[31:16] is unused.
FC3210 contains the C3, C2, C1 and C0 bits in the same place they
are in the FPU's status word. (bits 14, 10, 9, 8 respectively).
All other bits should be zero. The relevant mask to select just
those bits is 0x4700. To select C3, C2 and C0 only, the mask is
0x4500.
*/
typedef
struct {
UInt guest_EAX;
UInt guest_ECX;
UInt guest_EDX;
UInt guest_EBX;
UInt guest_ESP;
UInt guest_EBP;
UInt guest_ESI;
UInt guest_EDI;
/* 3-word thunk used to calculate O S Z A C P flags. */
UInt guest_CC_OP;
UInt guest_CC_SRC;
UInt guest_CC_DST;
/* The D flag is stored here, as either -1 or +1 */
UInt guest_DFLAG;
/* EIP */
UInt guest_EIP;
/* FPU */
UInt guest_FTOP;
ULong guest_FPREG[8];
UChar guest_FPTAG[8];
UInt guest_FPUCW;
UInt guest_FC3210;
/* Segment registers. */
UShort guest_CS;
UShort guest_DS;
UShort guest_ES;
UShort guest_FS;
UShort guest_GS;
UShort guest_SS;
}
VexGuestX86State;
/* This is logically part of the guest state description. */
/* Not visible to library client. */
extern Bool guest_x86_state_requires_precise_mem_exns ( Int, Int );
/*---------------------------------------------------------------*/
/*--- Utility functions for x86 guest stuff. ---*/
/*---------------------------------------------------------------*/
/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
/* Convert a saved x87 FPU image (as created by fsave) and write it
into the supplied VexGuestX86State structure. The non-FP parts of
said structure are left unchanged.
*/
extern
void x87_to_vex ( /*IN*/UChar* x87_state,
/*OUT*/VexGuestX86State* vex_state );
/* Extract from the supplied VexGuestX86State structure, an x87 FPU
image. */
extern
void vex_to_x87 ( /*IN*/VexGuestX86State* vex_state,
/*OUT*/UChar* x87_state );
/* Given a 32-bit word containing native x86 %eflags values, set the
eflag-related fields in the supplied VexGuestX86State accordingly.
All other fields are left unchanged. */
extern
void eflags_to_vex ( UInt eflags_native,
/*OUT*/VexGuestX86State* vex_state );
/* Extract from the supplied VexGuestX86State structure the
corresponding native %eflags value. */
extern
UInt vex_to_eflags ( /*IN*/VexGuestX86State* vex_state );
extern
void vex_initialise_x87 ( /* MOD*/VexGuestX86State* vex_state );
#endif /* ndef __LIBVEX_PUB_GUEST_X86_H */
/*---------------------------------------------------------------*/
/*--- libvex_guest_x86.h ---*/
/*---------------------------------------------------------------*/