}
Condcode;
-
-/*---------------------------------------------------------*/
-/*--- Simulated state offsets ---*/
-/*---------------------------------------------------------*/
-
-/* 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. */
-
-#define OFFB_EAX (0*4)
-#define OFFB_ECX (1*4)
-#define OFFB_EDX (2*4)
-#define OFFB_EBX (3*4)
-#define OFFB_ESP (4*4)
-#define OFFB_EBP (5*4)
-#define OFFB_ESI (6*4)
-#define OFFB_EDI (7*4)
-/* 3-word thunk used to calculate O S Z A C P flags. */
-#define OFFB_CC_OP (8*4)
-#define OFFB_CC_SRC (9*4)
-#define OFFB_CC_DST (10*4)
-/* The D flag is stored here, as either -1 or +1 */
-#define OFFB_DFLAG (11*4)
-/* EIP */
-#define OFFB_EIP (12*4)
-
-/* 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.
-*/
-#define OFFB_FTOP (13*4)
-#define OFFB_F0 (14*4)
-#define OFFB_F1 (16*4)
-#define OFFB_F2 (18*4)
-#define OFFB_F3 (20*4)
-#define OFFB_F4 (22*4)
-#define OFFB_F5 (24*4)
-#define OFFB_F6 (26*4)
-#define OFFB_F7 (28*4)
-#define OFFB_FTAG0 (30*4) // up to 30*4 + 7
-#define OFFB_FPUCW (32*4)
-#define OFFB_FC3210 (33*4)
-
-/* Don't forget to keep this up to date. */
-#define SIZEOF_X86H_STATE (OFFB_FC3210 + 4)
-
-
-
#endif /* ndef __LIBVEX_X86GUEST_DEFS_H */
/*---------------------------------------------------------------*/
/* VISIBLE TO LIBVEX CLIENT */
-void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
+void x87_to_vex ( /*IN*/UChar* x87_state,
+ /*OUT*/VexGuestX86State* vex_state )
{
Int r;
UInt tag;
- Double* vexRegs = (Double*)(vex_state + OFFB_F0);
- UChar* vexTags = (UChar*)(vex_state + OFFB_FTAG0);
+ Double* vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
+ UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
Fpu_State* x87 = (Fpu_State*)x87_state;
UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7;
UInt tagw = x87->env[FP_ENV_TAG];
}
/* stack pointer */
- *(UInt*)(vex_state + OFFB_FTOP) = ftop;
+ vex_state->guest_FTOP = ftop;
/* control word */
- *(UInt*)(vex_state + OFFB_FPUCW) = fpucw;
+ vex_state->guest_FPUCW = fpucw;
/* status word */
- *(UInt*)(vex_state + OFFB_FC3210) = c3210;
+ vex_state->guest_FC3210 = c3210;
}
/* VISIBLE TO LIBVEX CLIENT */
-void vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
+void vex_to_x87 ( /*IN*/VexGuestX86State* vex_state,
+ /*OUT*/UChar* x87_state )
{
Int i, r;
UInt tagw;
- Double* vexRegs = (Double*)(vex_state + OFFB_F0);
- UChar* vexTags = (UChar*)(vex_state + OFFB_FTAG0);
+ Double* vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
+ UChar* vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
Fpu_State* x87 = (Fpu_State*)x87_state;
- UInt ftop = *(UInt*)(vex_state + OFFB_FTOP);
- UInt c3210 = *(UInt*)(vex_state + OFFB_FC3210);
+ UInt ftop = vex_state->guest_FTOP;
+ UInt c3210 = vex_state->guest_FC3210;
for (i = 0; i < 14; i++)
x87->env[i] = 0;
x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
- x87->env[FP_ENV_CTRL] = (UShort)( *(UInt*)(vex_state + OFFB_FPUCW) );
+ x87->env[FP_ENV_CTRL] = (UShort)( vex_state->guest_FPUCW );
x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
tagw = 0;
}
+/* VISIBLE TO LIBVEX CLIENT */
+void eflags_to_vex ( UInt eflags_native,
+ /*OUT*/VexGuestX86State* vex_state )
+{
+ vex_state->guest_DFLAG
+ = (eflags_native & (1<<10)) ? 0xFFFFFFFF : 0x00000001;
+
+ /* Mask out everything except O S Z A C P. */
+ eflags_native
+ &= (CC_MASK_C | CC_MASK_P | CC_MASK_A
+ | CC_MASK_Z | CC_MASK_S | CC_MASK_O);
+
+ vex_state->guest_CC_OP = CC_OP_COPY;
+ vex_state->guest_CC_DST = 0;
+ vex_state->guest_CC_DST = eflags_native;
+}
+
+
+/* VISIBLE TO LIBVEX CLIENT */
+UInt vex_to_eflags ( /*IN*/VexGuestX86State* vex_state )
+{
+ UInt eflags = calculate_eflags_all(
+ vex_state->guest_CC_OP,
+ vex_state->guest_CC_SRC,
+ vex_state->guest_CC_DST
+ );
+ UInt dflag = vex_state->guest_DFLAG;
+ vassert(dflag == 1 || dflag == 0xFFFFFFFF);
+ if (dflag == 0xFFFFFFFF)
+ eflags |= (1<<10);
+
+ return eflags;
+}
+
+
+
/*---------------------------------------------------------------*/
/*--- end guest-x86/ghelpers.c ---*/
/*---------------------------------------------------------------*/
#include "libvex_basictypes.h"
#include "libvex_ir.h"
#include "libvex.h"
+#include "libvex_guest_x86.h"
#include "main/vex_util.h"
#include "main/vex_globals.h"
}
+/*------------------------------------------------------------*/
+/*--- Offsets of various parts of the x86 guest state. ---*/
+/*------------------------------------------------------------*/
+
+#define offsetof(type,memb) ((Int)&((type*)0)->memb)
+
+#define OFFB_FPREGS offsetof(VexGuestX86State,guest_FPREG[0])
+#define OFFB_FPTAGS offsetof(VexGuestX86State,guest_FPTAG[0])
+#define OFFB_EAX offsetof(VexGuestX86State,guest_EAX)
+#define OFFB_CC_OP offsetof(VexGuestX86State,guest_CC_OP)
+#define OFFB_CC_SRC offsetof(VexGuestX86State,guest_CC_SRC)
+#define OFFB_CC_DST offsetof(VexGuestX86State,guest_CC_DST)
+#define OFFB_DFLAG offsetof(VexGuestX86State,guest_DFLAG)
+#define OFFB_FTOP offsetof(VexGuestX86State,guest_FTOP)
+#define OFFB_FC3210 offsetof(VexGuestX86State,guest_FC3210)
+#define OFFB_FPUCW offsetof(VexGuestX86State,guest_FPUCW)
+
+
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- x86 insn stream. ---*/
{
IRArray* descr;
vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
- descr = mkIRArray( OFFB_FTAG0, Ity_I8, 8 );
+ descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
}
static IRExpr* get_ST_TAG ( Int i )
{
- IRArray* descr = mkIRArray( OFFB_FTAG0, Ity_I8, 8 );
+ IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
return IRExpr_GetI( descr, get_ftop(), i );
}
{
IRArray* descr;
vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
- descr = mkIRArray( OFFB_F0, Ity_F64, 8 );
+ descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
/* Mark the register as in-use. */
put_ST_TAG(i, mkU8(1));
static IRExpr* get_ST_UNCHECKED ( Int i )
{
- IRArray* descr = mkIRArray( OFFB_F0, Ity_F64, 8 );
+ IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
return IRExpr_GetI( descr, get_ftop(), i );
}
#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;
+ }
+ VexGuestX86State;
+
+
/*---------------------------------------------------------------*/
/*--- Utility functions for x86 guest stuff. ---*/
/*---------------------------------------------------------------*/
-/* Convert a saved x87 FPU image (as created by fsave) into the
- equivalent vex representation.
+/* 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*/UChar* vex_state );
+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 );
-/* Extract from the vex representation, an x87 FPU image. */
-extern void vex_to_x87 ( /*IN*/UChar* vex_state,
- /*OUT*/UChar* x87_state );
#endif /* ndef __LIBVEX_PUB_GUEST_X86_H */