#define R_FS 4
#define R_GS 5
+/* segment descriptor fields */
+#define DESC_G_MASK (1 << 23)
+#define DESC_B_SHIFT 22
+#define DESC_B_MASK (1 << DESC_B_SHIFT)
+#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 CR4_PSE_MASK (1 << 4)
+
+#define PG_PRESENT_BIT 0
+#define PG_RW_BIT 1
+#define PG_USER_BIT 2
+#define PG_PWT_BIT 3
+#define PG_PCD_BIT 4
+#define PG_ACCESSED_BIT 5
+#define PG_DIRTY_BIT 6
+#define PG_PSE_BIT 7
+#define PG_GLOBAL_BIT 8
+
+#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
+#define PG_RW_MASK (1 << PG_RW_BIT)
+#define PG_USER_MASK (1 << PG_USER_BIT)
+#define PG_PWT_MASK (1 << PG_PWT_BIT)
+#define PG_PCD_MASK (1 << PG_PCD_BIT)
+#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
+#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
+#define PG_PSE_MASK (1 << PG_PSE_BIT)
+#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
+
+#define PG_ERROR_W_BIT 1
+
+#define PG_ERROR_P_MASK 0x01
+#define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT)
+#define PG_ERROR_U_MASK 0x04
+#define PG_ERROR_RSVD_MASK 0x08
+
#define EXCP00_DIVZ 0
#define EXCP01_SSTP 1
#define EXCP02_NMI 2
#define EXCP12_MCHK 18
#define EXCP_INTERRUPT 256 /* async interruption */
+#define EXCP_HLT 257 /* hlt instruction reached */
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
#endif
typedef struct SegmentCache {
+ uint32_t selector;
uint8_t *base;
- unsigned long limit;
- uint8_t seg_32bit;
+ uint32_t limit;
+ uint32_t flags;
} 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;
- int interrupt_request;
+ int exception_is_int;
+ int exception_next_eip;
+
+ uint32_t cr[5]; /* NOTE: cr1 is unused */
+ uint32_t dr[8]; /* debug registers */
+ int interrupt_request; /* if true, will exit from cpu_exec() ASAP */
+ /* if true, will call cpu_x86_get_pic_interrupt() ASAP to get the
+ request interrupt number */
+ int hard_interrupt_request;
+ int user_mode_only; /* user mode only simulation */
/* 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);
int cpu_x86_exec(CPUX86State *s);
void cpu_x86_interrupt(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
+int cpu_x86_get_pic_interrupt(CPUX86State *s);
/* 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. */
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc);
+/* MMU defines */
+void cpu_x86_init_mmu(CPUX86State *env);
+extern CPUX86State *global_env;
+extern int phys_ram_size;
+extern int phys_ram_fd;
+extern uint8_t *phys_ram_base;
+
/* used to debug */
#define X86_DUMP_FPU 0x0001 /* dump FPU state too */
#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 */