]>
Commit | Line | Data |
---|---|---|
3ef693a0 FB |
1 | /* |
2 | * i386 virtual CPU header | |
3 | * | |
4 | * Copyright (c) 2003 Fabrice Bellard | |
5 | * | |
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. | |
10 | * | |
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. | |
15 | * | |
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 | |
0ecfa993 | 19 | */ |
367e86e8 FB |
20 | #ifndef CPU_I386_H |
21 | #define CPU_I386_H | |
22 | ||
04369ff2 | 23 | #include "config.h" |
0ecfa993 FB |
24 | #include <setjmp.h> |
25 | ||
367e86e8 FB |
26 | #define R_EAX 0 |
27 | #define R_ECX 1 | |
28 | #define R_EDX 2 | |
29 | #define R_EBX 3 | |
30 | #define R_ESP 4 | |
31 | #define R_EBP 5 | |
32 | #define R_ESI 6 | |
33 | #define R_EDI 7 | |
34 | ||
35 | #define R_AL 0 | |
36 | #define R_CL 1 | |
37 | #define R_DL 2 | |
38 | #define R_BL 3 | |
39 | #define R_AH 4 | |
40 | #define R_CH 5 | |
41 | #define R_DH 6 | |
42 | #define R_BH 7 | |
43 | ||
44 | #define R_ES 0 | |
45 | #define R_CS 1 | |
46 | #define R_SS 2 | |
47 | #define R_DS 3 | |
48 | #define R_FS 4 | |
49 | #define R_GS 5 | |
50 | ||
aad13cd1 FB |
51 | /* segment descriptor fields */ |
52 | #define DESC_G_MASK (1 << 23) | |
66e85a21 FB |
53 | #define DESC_B_SHIFT 22 |
54 | #define DESC_B_MASK (1 << DESC_B_SHIFT) | |
aad13cd1 FB |
55 | #define DESC_AVL_MASK (1 << 20) |
56 | #define DESC_P_MASK (1 << 15) | |
57 | #define DESC_DPL_SHIFT 13 | |
58 | #define DESC_S_MASK (1 << 12) | |
59 | #define DESC_TYPE_SHIFT 8 | |
60 | #define DESC_A_MASK (1 << 8) | |
61 | ||
62 | #define DESC_CS_MASK (1 << 11) | |
63 | #define DESC_C_MASK (1 << 10) | |
64 | #define DESC_R_MASK (1 << 9) | |
65 | ||
66 | #define DESC_E_MASK (1 << 10) | |
67 | #define DESC_W_MASK (1 << 9) | |
68 | ||
fc2b4c48 | 69 | /* eflags masks */ |
367e86e8 FB |
70 | #define CC_C 0x0001 |
71 | #define CC_P 0x0004 | |
72 | #define CC_A 0x0010 | |
73 | #define CC_Z 0x0040 | |
74 | #define CC_S 0x0080 | |
75 | #define CC_O 0x0800 | |
76 | ||
fc2b4c48 FB |
77 | #define TF_MASK 0x00000100 |
78 | #define IF_MASK 0x00000200 | |
79 | #define DF_MASK 0x00000400 | |
80 | #define IOPL_MASK 0x00003000 | |
81 | #define NT_MASK 0x00004000 | |
82 | #define RF_MASK 0x00010000 | |
83 | #define VM_MASK 0x00020000 | |
84 | #define AC_MASK 0x00040000 | |
85 | #define VIF_MASK 0x00080000 | |
86 | #define VIP_MASK 0x00100000 | |
87 | #define ID_MASK 0x00200000 | |
367e86e8 | 88 | |
13b55754 FB |
89 | #define CR0_PE_MASK (1 << 0) |
90 | #define CR0_TS_MASK (1 << 3) | |
91 | #define CR0_WP_MASK (1 << 16) | |
92 | #define CR0_AM_MASK (1 << 18) | |
93 | #define CR0_PG_MASK (1 << 31) | |
94 | ||
95 | #define CR4_VME_MASK (1 << 0) | |
96 | #define CR4_PVI_MASK (1 << 1) | |
97 | #define CR4_TSD_MASK (1 << 2) | |
98 | #define CR4_DE_MASK (1 << 3) | |
66e85a21 FB |
99 | #define CR4_PSE_MASK (1 << 4) |
100 | ||
101 | #define PG_PRESENT_BIT 0 | |
102 | #define PG_RW_BIT 1 | |
103 | #define PG_USER_BIT 2 | |
104 | #define PG_PWT_BIT 3 | |
105 | #define PG_PCD_BIT 4 | |
106 | #define PG_ACCESSED_BIT 5 | |
107 | #define PG_DIRTY_BIT 6 | |
108 | #define PG_PSE_BIT 7 | |
109 | #define PG_GLOBAL_BIT 8 | |
110 | ||
111 | #define PG_PRESENT_MASK (1 << PG_PRESENT_BIT) | |
112 | #define PG_RW_MASK (1 << PG_RW_BIT) | |
113 | #define PG_USER_MASK (1 << PG_USER_BIT) | |
114 | #define PG_PWT_MASK (1 << PG_PWT_BIT) | |
115 | #define PG_PCD_MASK (1 << PG_PCD_BIT) | |
116 | #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT) | |
117 | #define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) | |
118 | #define PG_PSE_MASK (1 << PG_PSE_BIT) | |
119 | #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) | |
120 | ||
121 | #define PG_ERROR_W_BIT 1 | |
122 | ||
123 | #define PG_ERROR_P_MASK 0x01 | |
124 | #define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT) | |
125 | #define PG_ERROR_U_MASK 0x04 | |
126 | #define PG_ERROR_RSVD_MASK 0x08 | |
13b55754 | 127 | |
3c1cf9fa FB |
128 | #define MSR_IA32_APICBASE 0x1b |
129 | #define MSR_IA32_APICBASE_BSP (1<<8) | |
130 | #define MSR_IA32_APICBASE_ENABLE (1<<11) | |
131 | #define MSR_IA32_APICBASE_BASE (0xfffff<<12) | |
132 | ||
133 | #define MSR_IA32_SYSENTER_CS 0x174 | |
134 | #define MSR_IA32_SYSENTER_ESP 0x175 | |
135 | #define MSR_IA32_SYSENTER_EIP 0x176 | |
136 | ||
bc8a22cc FB |
137 | #define EXCP00_DIVZ 0 |
138 | #define EXCP01_SSTP 1 | |
139 | #define EXCP02_NMI 2 | |
140 | #define EXCP03_INT3 3 | |
141 | #define EXCP04_INTO 4 | |
142 | #define EXCP05_BOUND 5 | |
143 | #define EXCP06_ILLOP 6 | |
144 | #define EXCP07_PREX 7 | |
145 | #define EXCP08_DBLE 8 | |
146 | #define EXCP09_XERR 9 | |
147 | #define EXCP0A_TSS 10 | |
148 | #define EXCP0B_NOSEG 11 | |
149 | #define EXCP0C_STACK 12 | |
150 | #define EXCP0D_GPF 13 | |
151 | #define EXCP0E_PAGE 14 | |
152 | #define EXCP10_COPR 16 | |
153 | #define EXCP11_ALGN 17 | |
154 | #define EXCP12_MCHK 18 | |
0ecfa993 | 155 | |
9de5e440 | 156 | #define EXCP_INTERRUPT 256 /* async interruption */ |
66e85a21 | 157 | #define EXCP_HLT 257 /* hlt instruction reached */ |
0ecfa993 | 158 | |
367e86e8 FB |
159 | enum { |
160 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ | |
161 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ | |
162 | CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */ | |
163 | ||
164 | CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | |
165 | CC_OP_ADDW, | |
166 | CC_OP_ADDL, | |
167 | ||
4b74fe1f FB |
168 | CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
169 | CC_OP_ADCW, | |
170 | CC_OP_ADCL, | |
171 | ||
367e86e8 FB |
172 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
173 | CC_OP_SUBW, | |
174 | CC_OP_SUBL, | |
175 | ||
4b74fe1f FB |
176 | CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
177 | CC_OP_SBBW, | |
178 | CC_OP_SBBL, | |
179 | ||
367e86e8 FB |
180 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */ |
181 | CC_OP_LOGICW, | |
182 | CC_OP_LOGICL, | |
183 | ||
4b74fe1f | 184 | CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
367e86e8 FB |
185 | CC_OP_INCW, |
186 | CC_OP_INCL, | |
187 | ||
4b74fe1f | 188 | CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
367e86e8 FB |
189 | CC_OP_DECW, |
190 | CC_OP_DECL, | |
191 | ||
192 | CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ | |
193 | CC_OP_SHLW, | |
194 | CC_OP_SHLL, | |
195 | ||
4b74fe1f FB |
196 | CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ |
197 | CC_OP_SARW, | |
198 | CC_OP_SARL, | |
199 | ||
367e86e8 FB |
200 | CC_OP_NB, |
201 | }; | |
202 | ||
927f621e | 203 | #ifdef __i386__ |
27362c82 | 204 | #define USE_X86LDOUBLE |
927f621e FB |
205 | #endif |
206 | ||
207 | #ifdef USE_X86LDOUBLE | |
208 | typedef long double CPU86_LDouble; | |
209 | #else | |
210 | typedef double CPU86_LDouble; | |
211 | #endif | |
212 | ||
6dbad63e | 213 | typedef struct SegmentCache { |
13b55754 | 214 | uint32_t selector; |
6dbad63e | 215 | uint8_t *base; |
66e85a21 FB |
216 | uint32_t limit; |
217 | uint32_t flags; | |
6dbad63e FB |
218 | } SegmentCache; |
219 | ||
ba1c6e37 | 220 | typedef struct CPUX86State { |
367e86e8 FB |
221 | /* standard registers */ |
222 | uint32_t regs[8]; | |
dab2ed99 | 223 | uint32_t eip; |
fc2b4c48 FB |
224 | uint32_t eflags; /* eflags register. During CPU emulation, CC |
225 | flags and DF are set to zero because they are | |
d34720fd | 226 | stored elsewhere */ |
0ecfa993 FB |
227 | |
228 | /* emulator internal eflags handling */ | |
367e86e8 FB |
229 | uint32_t cc_src; |
230 | uint32_t cc_dst; | |
231 | uint32_t cc_op; | |
232 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ | |
0ecfa993 | 233 | |
927f621e | 234 | /* FPU state */ |
927f621e FB |
235 | unsigned int fpstt; /* top of stack index */ |
236 | unsigned int fpus; | |
237 | unsigned int fpuc; | |
0ecfa993 FB |
238 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */ |
239 | CPU86_LDouble fpregs[8]; | |
240 | ||
367e86e8 | 241 | /* emulator internal variables */ |
927f621e | 242 | CPU86_LDouble ft0; |
d014c98c FB |
243 | union { |
244 | float f; | |
245 | double d; | |
246 | int i32; | |
247 | int64_t i64; | |
248 | } fp_convert; | |
d57c4e01 | 249 | |
6dbad63e | 250 | /* segments */ |
13b55754 FB |
251 | SegmentCache segs[6]; /* selector values */ |
252 | SegmentCache ldt; | |
253 | SegmentCache tr; | |
254 | SegmentCache gdt; /* only base and limit are used */ | |
255 | SegmentCache idt; /* only base and limit are used */ | |
3c1cf9fa FB |
256 | |
257 | /* sysenter registers */ | |
258 | uint32_t sysenter_cs; | |
259 | uint32_t sysenter_esp; | |
260 | uint32_t sysenter_eip; | |
6dbad63e | 261 | |
9de5e440 | 262 | /* exception/interrupt handling */ |
0ecfa993 FB |
263 | jmp_buf jmp_env; |
264 | int exception_index; | |
9ba5695c | 265 | int error_code; |
66e85a21 FB |
266 | int exception_is_int; |
267 | int exception_next_eip; | |
ea041c0e | 268 | struct TranslationBlock *current_tb; /* currently executing TB */ |
13b55754 FB |
269 | uint32_t cr[5]; /* NOTE: cr1 is unused */ |
270 | uint32_t dr[8]; /* debug registers */ | |
68a79315 | 271 | int interrupt_request; |
66e85a21 | 272 | int user_mode_only; /* user mode only simulation */ |
ea041c0e | 273 | |
fc2b4c48 FB |
274 | /* user data */ |
275 | void *opaque; | |
ba1c6e37 | 276 | } CPUX86State; |
367e86e8 | 277 | |
927f621e | 278 | #ifndef IN_OP_I386 |
9ba5695c FB |
279 | void cpu_x86_outb(CPUX86State *env, int addr, int val); |
280 | void cpu_x86_outw(CPUX86State *env, int addr, int val); | |
281 | void cpu_x86_outl(CPUX86State *env, int addr, int val); | |
282 | int cpu_x86_inb(CPUX86State *env, int addr); | |
283 | int cpu_x86_inw(CPUX86State *env, int addr); | |
284 | int cpu_x86_inl(CPUX86State *env, int addr); | |
927f621e | 285 | #endif |
367e86e8 | 286 | |
ba1c6e37 FB |
287 | CPUX86State *cpu_x86_init(void); |
288 | int cpu_x86_exec(CPUX86State *s); | |
289 | void cpu_x86_close(CPUX86State *s); | |
66e85a21 | 290 | int cpu_x86_get_pic_interrupt(CPUX86State *s); |
ba1c6e37 | 291 | |
6dbad63e FB |
292 | /* needed to load some predefinied segment registers */ |
293 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); | |
294 | ||
d0a1ffc9 FB |
295 | /* simulate fsave/frstor */ |
296 | void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32); | |
297 | void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32); | |
298 | ||
d691f669 | 299 | /* you can call this signal handler from your SIGBUS and SIGSEGV |
9de5e440 FB |
300 | signal handlers to inform the virtual CPU of exceptions. non zero |
301 | is returned if the signal was handled by the virtual CPU. */ | |
302 | struct siginfo; | |
303 | int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | |
304 | void *puc); | |
305 | ||
66e85a21 FB |
306 | /* MMU defines */ |
307 | void cpu_x86_init_mmu(CPUX86State *env); | |
66e85a21 FB |
308 | extern int phys_ram_size; |
309 | extern int phys_ram_fd; | |
310 | extern uint8_t *phys_ram_base; | |
311 | ||
f351077e FB |
312 | /* used to debug */ |
313 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */ | |
314 | #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */ | |
315 | void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags); | |
316 | ||
54936004 | 317 | #define TARGET_PAGE_BITS 12 |
5a9fdfec | 318 | #include "cpu-all.h" |
54936004 | 319 | |
367e86e8 | 320 | #endif /* CPU_I386_H */ |