update
[qemu] / cpu-i386.h
index 44411b0..e6318fb 100644 (file)
 #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 MSR_IA32_APICBASE               0x1b
+#define MSR_IA32_APICBASE_BSP           (1<<8)
+#define MSR_IA32_APICBASE_ENABLE        (1<<11)
+#define MSR_IA32_APICBASE_BASE          (0xfffff<<12)
+
+#define MSR_IA32_SYSENTER_CS            0x174
+#define MSR_IA32_SYSENTER_ESP           0x175
+#define MSR_IA32_SYSENTER_EIP           0x176
+
 #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 */
@@ -144,19 +211,12 @@ typedef double CPU86_LDouble;
 #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];
@@ -188,220 +248,33 @@ typedef struct CPUX86State {
     } 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 */
+
+    /* sysenter registers */
+    uint32_t sysenter_cs;
+    uint32_t sysenter_esp;
+    uint32_t sysenter_eip;
     
     /* 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;
+    struct TranslationBlock *current_tb; /* currently executing TB */
+    uint32_t cr[5]; /* NOTE: cr1 is unused */
+    uint32_t dr[8]; /* debug registers */
+    int 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);
@@ -413,12 +286,16 @@ int cpu_x86_inl(CPUX86State *env, int addr);
 
 CPUX86State *cpu_x86_init(void);
 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.  */
@@ -426,120 +303,18 @@ struct siginfo;
 int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
                            void *puc);
 
+/* MMU defines */
+void cpu_x86_init_mmu(CPUX86State *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);
-
-/***************************************************/
-/* internal functions */
-
-#define GEN_FLAG_CODE32_SHIFT 0
-#define GEN_FLAG_ADDSEG_SHIFT 1
-#define GEN_FLAG_SS32_SHIFT   2
-#define GEN_FLAG_VM_SHIFT     3
-#define GEN_FLAG_ST_SHIFT     4
-#define GEN_FLAG_CPL_SHIFT    7
-#define GEN_FLAG_IOPL_SHIFT   9
-#define GEN_FLAG_TF_SHIFT     11
-
-int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
-                     int *gen_code_size_ptr,
-                     uint8_t *pc_start,  uint8_t *cs_base, int flags,
-                     int *code_size_ptr);
-void cpu_x86_tblocks_init(void);
-void page_init(void);
-int page_unprotect(unsigned long address);
-
-#define CODE_GEN_MAX_SIZE        65536
-#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
-
-#define CODE_GEN_HASH_BITS     15
-#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)
-
-/* maximum total translate dcode allocated */
-#define CODE_GEN_BUFFER_SIZE     (2048 * 1024)
-//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
-
-typedef struct TranslationBlock {
-    unsigned long pc;   /* simulated PC corresponding to this block (EIP + CS base) */
-    unsigned long cs_base; /* CS base for this block */
-    unsigned int flags; /* flags defining in which context the code was generated */
-    uint16_t size;      /* size of target code for this block (1 <=
-                           size <= TARGET_PAGE_SIZE) */
-    uint8_t *tc_ptr;    /* pointer to the translated code */
-    struct TranslationBlock *hash_next; /* next matching block */
-    struct TranslationBlock *page_next[2]; /* next blocks in even/odd page */
-} TranslationBlock;
-
-static inline unsigned int tb_hash_func(unsigned long pc)
-{
-    return pc & (CODE_GEN_HASH_SIZE - 1);
-}
-
-void tb_flush(void);
-TranslationBlock *tb_alloc(unsigned long pc, 
-                           unsigned long size);
-
-extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
-
-extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
-extern uint8_t *code_gen_ptr;
-
-/* find a translation block in the translation cache. If not found,
-   return NULL and the pointer to the last element of the list in pptb */
-static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
-                                        unsigned long pc, 
-                                        unsigned long cs_base,
-                                        unsigned int flags)
-{
-    TranslationBlock **ptb, *tb;
-    unsigned int h;
-    h = tb_hash_func(pc);
-    ptb = &tb_hash[h];
-    for(;;) {
-        tb = *ptb;
-        if (!tb)
-            break;
-        if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
-            return tb;
-        ptb = &tb->hash_next;
-    }
-    *pptb = ptb;
-    return NULL;
-}
-
-#ifndef offsetof
-#define offsetof(type, field) ((size_t) &((type *)0)->field)
-#endif
+#include "cpu-all.h"
 
 #endif /* CPU_I386_H */