X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;ds=sidebyside;f=cpu-i386.h;h=e6318fb7f2ddcd177f4526d8afce6cfd1a4c7bfb;hb=4690764bba3a489d5180106d08970ced59113e22;hp=8d7e1d612e942d908a6593c2dc8b8fcbbae7d913;hpb=a95c67907cce5b03269581b77f014ec51b98da36;p=qemu diff --git a/cpu-i386.h b/cpu-i386.h index 8d7e1d6..e6318fb 100644 --- a/cpu-i386.h +++ b/cpu-i386.h @@ -50,7 +50,8 @@ /* segment descriptor fields */ #define DESC_G_MASK (1 << 23) -#define DESC_B_MASK (1 << 22) +#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 @@ -85,6 +86,54 @@ #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 @@ -105,6 +154,7 @@ #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 */ @@ -161,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]; @@ -205,250 +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; -} - -/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the - kernel handles unaligned load/stores may give better results, but - it is a system wide setting : bad */ -#if defined(WORDS_BIGENDIAN) || defined(__arm__) - -/* 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 void stfl(void *ptr, float v) -{ - union { - float f; - uint32_t i; - } u; - u.f = v; - stl(ptr, u.i); -} - -#if defined(__arm__) && !defined(WORDS_BIGENDIAN) - -/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ -static inline double ldfq(void *ptr) -{ - union { - double d; - uint32_t tab[2]; - } u; - u.tab[1] = ldl(ptr); - u.tab[0] = ldl(ptr + 4); - return u.d; -} - -static inline void stfq(void *ptr, double v) -{ - union { - double d; - uint32_t tab[2]; - } u; - u.d = v; - stl(ptr, u.tab[1]); - stl(ptr + 4, u.tab[0]); -} - -#else -static inline double ldfq(void *ptr) -{ - union { - double d; - uint64_t i; - } u; - u.i = ldq(ptr); - return u.d; -} - -static inline void stfq(void *ptr, double v) -{ - union { - double d; - uint64_t i; - } u; - u.d = v; - stq(ptr, u.i); -} -#endif - -#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); @@ -460,8 +286,8 @@ 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); @@ -477,37 +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); +#include "cpu-all.h" #endif /* CPU_I386_H */