2 * i386 virtual CPU header
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 /* segment descriptor fields */
52 #define DESC_G_MASK (1 << 23)
53 #define DESC_B_MASK (1 << 22)
54 #define DESC_AVL_MASK (1 << 20)
55 #define DESC_P_MASK (1 << 15)
56 #define DESC_DPL_SHIFT 13
57 #define DESC_S_MASK (1 << 12)
58 #define DESC_TYPE_SHIFT 8
59 #define DESC_A_MASK (1 << 8)
61 #define DESC_CS_MASK (1 << 11)
62 #define DESC_C_MASK (1 << 10)
63 #define DESC_R_MASK (1 << 9)
65 #define DESC_E_MASK (1 << 10)
66 #define DESC_W_MASK (1 << 9)
76 #define TF_MASK 0x00000100
77 #define IF_MASK 0x00000200
78 #define DF_MASK 0x00000400
79 #define IOPL_MASK 0x00003000
80 #define NT_MASK 0x00004000
81 #define RF_MASK 0x00010000
82 #define VM_MASK 0x00020000
83 #define AC_MASK 0x00040000
84 #define VIF_MASK 0x00080000
85 #define VIP_MASK 0x00100000
86 #define ID_MASK 0x00200000
93 #define EXCP05_BOUND 5
94 #define EXCP06_ILLOP 6
99 #define EXCP0B_NOSEG 11
100 #define EXCP0C_STACK 12
101 #define EXCP0D_GPF 13
102 #define EXCP0E_PAGE 14
103 #define EXCP10_COPR 16
104 #define EXCP11_ALGN 17
105 #define EXCP12_MCHK 18
107 #define EXCP_INTERRUPT 256 /* async interruption */
110 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
111 CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
112 CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
114 CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
118 CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
122 CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
126 CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
130 CC_OP_LOGICB, /* modify all flags, CC_DST = res */
134 CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
138 CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
142 CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
146 CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
154 #define USE_X86LDOUBLE
157 #ifdef USE_X86LDOUBLE
158 typedef long double CPU86_LDouble;
160 typedef double CPU86_LDouble;
163 typedef struct SegmentCache {
169 typedef struct SegmentDescriptorTable {
172 /* this is the returned base when reading the register, just to
173 avoid that the emulated program modifies it */
174 unsigned long emu_base;
175 } SegmentDescriptorTable;
177 typedef struct CPUX86State {
178 /* standard registers */
181 uint32_t eflags; /* eflags register. During CPU emulation, CC
182 flags and DF are set to zero because they are
185 /* emulator internal eflags handling */
189 int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
192 unsigned int fpstt; /* top of stack index */
195 uint8_t fptags[8]; /* 0 = valid, 1 = empty */
196 CPU86_LDouble fpregs[8];
198 /* emulator internal variables */
208 uint32_t segs[6]; /* selector values */
209 SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
210 SegmentDescriptorTable gdt;
211 SegmentDescriptorTable ldt;
212 SegmentDescriptorTable idt;
214 /* exception/interrupt handling */
219 int interrupt_request;
225 /* all CPU memory access use these macros */
226 static inline int ldub(void *ptr)
228 return *(uint8_t *)ptr;
231 static inline int ldsb(void *ptr)
233 return *(int8_t *)ptr;
236 static inline void stb(void *ptr, int v)
241 #ifdef WORDS_BIGENDIAN
243 /* conservative code for little endian unaligned accesses */
244 static inline int lduw(void *ptr)
248 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
252 return p[0] | (p[1] << 8);
256 static inline int ldsw(void *ptr)
260 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
264 return (int16_t)(p[0] | (p[1] << 8));
268 static inline int ldl(void *ptr)
272 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
276 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
280 static inline uint64_t ldq(void *ptr)
286 return v1 | ((uint64_t)v2 << 32);
289 static inline void stw(void *ptr, int v)
292 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
300 static inline void stl(void *ptr, int v)
303 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
313 static inline void stq(void *ptr, uint64_t v)
322 static inline float ldfl(void *ptr)
332 static inline double ldfq(void *ptr)
342 static inline void stfl(void *ptr, float v)
352 static inline void stfq(void *ptr, double v)
364 static inline int lduw(void *ptr)
366 return *(uint16_t *)ptr;
369 static inline int ldsw(void *ptr)
371 return *(int16_t *)ptr;
374 static inline int ldl(void *ptr)
376 return *(uint32_t *)ptr;
379 static inline uint64_t ldq(void *ptr)
381 return *(uint64_t *)ptr;
384 static inline void stw(void *ptr, int v)
386 *(uint16_t *)ptr = v;
389 static inline void stl(void *ptr, int v)
391 *(uint32_t *)ptr = v;
394 static inline void stq(void *ptr, uint64_t v)
396 *(uint64_t *)ptr = v;
401 static inline float ldfl(void *ptr)
403 return *(float *)ptr;
406 static inline double ldfq(void *ptr)
408 return *(double *)ptr;
411 static inline void stfl(void *ptr, float v)
416 static inline void stfq(void *ptr, double v)
423 void cpu_x86_outb(CPUX86State *env, int addr, int val);
424 void cpu_x86_outw(CPUX86State *env, int addr, int val);
425 void cpu_x86_outl(CPUX86State *env, int addr, int val);
426 int cpu_x86_inb(CPUX86State *env, int addr);
427 int cpu_x86_inw(CPUX86State *env, int addr);
428 int cpu_x86_inl(CPUX86State *env, int addr);
431 CPUX86State *cpu_x86_init(void);
432 int cpu_x86_exec(CPUX86State *s);
433 void cpu_x86_interrupt(CPUX86State *s);
434 void cpu_x86_close(CPUX86State *s);
436 /* needed to load some predefinied segment registers */
437 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
439 /* simulate fsave/frstor */
440 void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
441 void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
443 /* you can call this signal handler from your SIGBUS and SIGSEGV
444 signal handlers to inform the virtual CPU of exceptions. non zero
445 is returned if the signal was handled by the virtual CPU. */
447 int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
451 #define X86_DUMP_FPU 0x0001 /* dump FPU state too */
452 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
453 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
455 /* page related stuff */
456 #define TARGET_PAGE_BITS 12
457 #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
458 #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
459 #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
461 extern unsigned long real_host_page_size;
462 extern unsigned long host_page_bits;
463 extern unsigned long host_page_size;
464 extern unsigned long host_page_mask;
466 #define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
468 /* same as PROT_xxx */
469 #define PAGE_READ 0x0001
470 #define PAGE_WRITE 0x0002
471 #define PAGE_EXEC 0x0004
472 #define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
473 #define PAGE_VALID 0x0008
474 /* original state of the write flag (used when tracking self-modifying
476 #define PAGE_WRITE_ORG 0x0010
478 void page_dump(FILE *f);
479 int page_get_flags(unsigned long address);
480 void page_set_flags(unsigned long start, unsigned long end, int flags);
481 void page_unprotect_range(uint8_t *data, unsigned long data_size);
483 #endif /* CPU_I386_H */