#define R_FS 4
#define R_GS 5
+/* segment descriptor fields */
+#define DESC_G_MASK (1 << 23)
+#define DESC_B_MASK (1 << 22)
+#define DESC_AVL_MASK (1 << 20)
+#define DESC_P_MASK (1 << 15)
+#define DESC_DPL_SHIFT 13
+#define DESC_S_MASK (1 << 12)
+#define DESC_TYPE_SHIFT 8
+#define DESC_A_MASK (1 << 8)
+
+#define DESC_CS_MASK (1 << 11)
+#define DESC_C_MASK (1 << 10)
+#define DESC_R_MASK (1 << 9)
+
+#define DESC_E_MASK (1 << 10)
+#define DESC_W_MASK (1 << 9)
+
/* eflags masks */
#define CC_C 0x0001
#define CC_P 0x0004
#define VIP_MASK 0x00100000
#define ID_MASK 0x00200000
+#define CR0_PE_MASK (1 << 0)
+#define CR0_TS_MASK (1 << 3)
+#define CR0_WP_MASK (1 << 16)
+#define CR0_AM_MASK (1 << 18)
+#define CR0_PG_MASK (1 << 31)
+
+#define CR4_VME_MASK (1 << 0)
+#define CR4_PVI_MASK (1 << 1)
+#define CR4_TSD_MASK (1 << 2)
+#define CR4_DE_MASK (1 << 3)
+
#define EXCP00_DIVZ 0
#define EXCP01_SSTP 1
#define EXCP02_NMI 2
#endif
typedef struct SegmentCache {
+ uint32_t selector;
uint8_t *base;
unsigned long limit;
uint8_t seg_32bit;
} SegmentCache;
-typedef struct SegmentDescriptorTable {
- uint8_t *base;
- unsigned long limit;
- /* this is the returned base when reading the register, just to
- avoid that the emulated program modifies it */
- unsigned long emu_base;
-} SegmentDescriptorTable;
-
typedef struct CPUX86State {
/* standard registers */
uint32_t regs[8];
} fp_convert;
/* segments */
- uint32_t segs[6]; /* selector values */
- SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
- SegmentDescriptorTable gdt;
- SegmentDescriptorTable ldt;
- SegmentDescriptorTable idt;
+ SegmentCache segs[6]; /* selector values */
+ SegmentCache ldt;
+ SegmentCache tr;
+ SegmentCache gdt; /* only base and limit are used */
+ SegmentCache idt; /* only base and limit are used */
/* exception/interrupt handling */
jmp_buf jmp_env;
int exception_index;
int error_code;
- uint32_t cr2;
+ uint32_t cr[5]; /* NOTE: cr1 is unused */
+ uint32_t dr[8]; /* debug registers */
int interrupt_request;
/* user data */
void *opaque;
} CPUX86State;
-/* all CPU memory access use these macros */
-static inline int ldub(void *ptr)
-{
- return *(uint8_t *)ptr;
-}
-
-static inline int ldsb(void *ptr)
-{
- return *(int8_t *)ptr;
-}
-
-static inline void stb(void *ptr, int v)
-{
- *(uint8_t *)ptr = v;
-}
-
-#ifdef WORDS_BIGENDIAN
-
-/* conservative code for little endian unaligned accesses */
-static inline int lduw(void *ptr)
-{
-#ifdef __powerpc__
- int val;
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return val;
-#else
- uint8_t *p = ptr;
- return p[0] | (p[1] << 8);
-#endif
-}
-
-static inline int ldsw(void *ptr)
-{
-#ifdef __powerpc__
- int val;
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return (int16_t)val;
-#else
- uint8_t *p = ptr;
- return (int16_t)(p[0] | (p[1] << 8));
-#endif
-}
-
-static inline int ldl(void *ptr)
-{
-#ifdef __powerpc__
- int val;
- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return val;
-#else
- uint8_t *p = ptr;
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-#endif
-}
-
-static inline uint64_t ldq(void *ptr)
-{
- uint8_t *p = ptr;
- uint32_t v1, v2;
- v1 = ldl(p);
- v2 = ldl(p + 4);
- return v1 | ((uint64_t)v2 << 32);
-}
-
-static inline void stw(void *ptr, int v)
-{
-#ifdef __powerpc__
- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
-#else
- uint8_t *p = ptr;
- p[0] = v;
- p[1] = v >> 8;
-#endif
-}
-
-static inline void stl(void *ptr, int v)
-{
-#ifdef __powerpc__
- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
-#else
- uint8_t *p = ptr;
- p[0] = v;
- p[1] = v >> 8;
- p[2] = v >> 16;
- p[3] = v >> 24;
-#endif
-}
-
-static inline void stq(void *ptr, uint64_t v)
-{
- uint8_t *p = ptr;
- stl(p, (uint32_t)v);
- stl(p + 4, v >> 32);
-}
-
-/* float access */
-
-static inline float ldfl(void *ptr)
-{
- union {
- float f;
- uint32_t i;
- } u;
- u.i = ldl(ptr);
- return u.f;
-}
-
-static inline double ldfq(void *ptr)
-{
- union {
- double d;
- uint64_t i;
- } u;
- u.i = ldq(ptr);
- return u.d;
-}
-
-static inline void stfl(void *ptr, float v)
-{
- union {
- float f;
- uint32_t i;
- } u;
- u.f = v;
- stl(ptr, u.i);
-}
-
-static inline void stfq(void *ptr, double v)
-{
- union {
- double d;
- uint64_t i;
- } u;
- u.d = v;
- stq(ptr, u.i);
-}
-
-#else
-
-static inline int lduw(void *ptr)
-{
- return *(uint16_t *)ptr;
-}
-
-static inline int ldsw(void *ptr)
-{
- return *(int16_t *)ptr;
-}
-
-static inline int ldl(void *ptr)
-{
- return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq(void *ptr)
-{
- return *(uint64_t *)ptr;
-}
-
-static inline void stw(void *ptr, int v)
-{
- *(uint16_t *)ptr = v;
-}
-
-static inline void stl(void *ptr, int v)
-{
- *(uint32_t *)ptr = v;
-}
-
-static inline void stq(void *ptr, uint64_t v)
-{
- *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float ldfl(void *ptr)
-{
- return *(float *)ptr;
-}
-
-static inline double ldfq(void *ptr)
-{
- return *(double *)ptr;
-}
-
-static inline void stfl(void *ptr, float v)
-{
- *(float *)ptr = v;
-}
-
-static inline void stfq(void *ptr, double v)
-{
- *(double *)ptr = v;
-}
-#endif
-
#ifndef IN_OP_I386
void cpu_x86_outb(CPUX86State *env, int addr, int val);
void cpu_x86_outw(CPUX86State *env, int addr, int val);
/* needed to load some predefinied segment registers */
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
+/* simulate fsave/frstor */
+void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
+void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
+
/* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */
#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
-/* page related stuff */
#define TARGET_PAGE_BITS 12
-#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
-#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
-#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
-
-extern unsigned long real_host_page_size;
-extern unsigned long host_page_bits;
-extern unsigned long host_page_size;
-extern unsigned long host_page_mask;
-
-#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
-
-/* same as PROT_xxx */
-#define PAGE_READ 0x0001
-#define PAGE_WRITE 0x0002
-#define PAGE_EXEC 0x0004
-#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
-#define PAGE_VALID 0x0008
-/* original state of the write flag (used when tracking self-modifying
- code */
-#define PAGE_WRITE_ORG 0x0010
-
-void page_dump(FILE *f);
-int page_get_flags(unsigned long address);
-void page_set_flags(unsigned long start, unsigned long end, int flags);
-void page_unprotect_range(uint8_t *data, unsigned long data_size);
+#include "cpu-all.h"
#endif /* CPU_I386_H */