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 /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
242 kernel handles unaligned load/stores may give better results, but
243 it is a system wide setting : bad */
244 #if defined(WORDS_BIGENDIAN) || defined(__arm__)
246 /* conservative code for little endian unaligned accesses */
247 static inline int lduw(void *ptr)
251 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
255 return p[0] | (p[1] << 8);
259 static inline int ldsw(void *ptr)
263 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
267 return (int16_t)(p[0] | (p[1] << 8));
271 static inline int ldl(void *ptr)
275 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
279 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
283 static inline uint64_t ldq(void *ptr)
289 return v1 | ((uint64_t)v2 << 32);
292 static inline void stw(void *ptr, int v)
295 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
303 static inline void stl(void *ptr, int v)
306 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
316 static inline void stq(void *ptr, uint64_t v)
325 static inline float ldfl(void *ptr)
335 static inline void stfl(void *ptr, float v)
345 #if defined(__arm__) && !defined(WORDS_BIGENDIAN)
347 /* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
348 static inline double ldfq(void *ptr)
355 u.tab[0] = ldl(ptr + 4);
359 static inline void stfq(void *ptr, double v)
367 stl(ptr + 4, u.tab[0]);
371 static inline double ldfq(void *ptr)
381 static inline void stfq(void *ptr, double v)
394 static inline int lduw(void *ptr)
396 return *(uint16_t *)ptr;
399 static inline int ldsw(void *ptr)
401 return *(int16_t *)ptr;
404 static inline int ldl(void *ptr)
406 return *(uint32_t *)ptr;
409 static inline uint64_t ldq(void *ptr)
411 return *(uint64_t *)ptr;
414 static inline void stw(void *ptr, int v)
416 *(uint16_t *)ptr = v;
419 static inline void stl(void *ptr, int v)
421 *(uint32_t *)ptr = v;
424 static inline void stq(void *ptr, uint64_t v)
426 *(uint64_t *)ptr = v;
431 static inline float ldfl(void *ptr)
433 return *(float *)ptr;
436 static inline double ldfq(void *ptr)
438 return *(double *)ptr;
441 static inline void stfl(void *ptr, float v)
446 static inline void stfq(void *ptr, double v)
453 void cpu_x86_outb(CPUX86State *env, int addr, int val);
454 void cpu_x86_outw(CPUX86State *env, int addr, int val);
455 void cpu_x86_outl(CPUX86State *env, int addr, int val);
456 int cpu_x86_inb(CPUX86State *env, int addr);
457 int cpu_x86_inw(CPUX86State *env, int addr);
458 int cpu_x86_inl(CPUX86State *env, int addr);
461 CPUX86State *cpu_x86_init(void);
462 int cpu_x86_exec(CPUX86State *s);
463 void cpu_x86_interrupt(CPUX86State *s);
464 void cpu_x86_close(CPUX86State *s);
466 /* needed to load some predefinied segment registers */
467 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
469 /* simulate fsave/frstor */
470 void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
471 void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
473 /* you can call this signal handler from your SIGBUS and SIGSEGV
474 signal handlers to inform the virtual CPU of exceptions. non zero
475 is returned if the signal was handled by the virtual CPU. */
477 int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
481 #define X86_DUMP_FPU 0x0001 /* dump FPU state too */
482 #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
483 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
485 /* page related stuff */
486 #define TARGET_PAGE_BITS 12
487 #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
488 #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
489 #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
491 extern unsigned long real_host_page_size;
492 extern unsigned long host_page_bits;
493 extern unsigned long host_page_size;
494 extern unsigned long host_page_mask;
496 #define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
498 /* same as PROT_xxx */
499 #define PAGE_READ 0x0001
500 #define PAGE_WRITE 0x0002
501 #define PAGE_EXEC 0x0004
502 #define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
503 #define PAGE_VALID 0x0008
504 /* original state of the write flag (used when tracking self-modifying
506 #define PAGE_WRITE_ORG 0x0010
508 void page_dump(FILE *f);
509 int page_get_flags(unsigned long address);
510 void page_set_flags(unsigned long start, unsigned long end, int flags);
511 void page_unprotect_range(uint8_t *data, unsigned long data_size);
513 #endif /* CPU_I386_H */