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
|
---|
19 | */
|
---|
20 | #ifndef CPU_I386_H
|
---|
21 | #define CPU_I386_H
|
---|
22 |
|
---|
23 | #include "config.h"
|
---|
24 |
|
---|
25 | #ifdef TARGET_X86_64
|
---|
26 | #define TARGET_LONG_BITS 64
|
---|
27 | #else
|
---|
28 | #define TARGET_LONG_BITS 32
|
---|
29 | #endif
|
---|
30 |
|
---|
31 | /* target supports implicit self modifying code */
|
---|
32 | #define TARGET_HAS_SMC
|
---|
33 | /* support for self modifying code even if the modified instruction is
|
---|
34 | close to the modifying instruction */
|
---|
35 | #define TARGET_HAS_PRECISE_SMC
|
---|
36 |
|
---|
37 | #define TARGET_HAS_ICE 1
|
---|
38 |
|
---|
39 | #ifdef TARGET_X86_64
|
---|
40 | #define ELF_MACHINE EM_X86_64
|
---|
41 | #else
|
---|
42 | #define ELF_MACHINE EM_386
|
---|
43 | #endif
|
---|
44 |
|
---|
45 | #include "cpu-defs.h"
|
---|
46 |
|
---|
47 | #include "softfloat.h"
|
---|
48 |
|
---|
49 | #if defined(VBOX)
|
---|
50 | # include <iprt/critsect.h>
|
---|
51 | # include <iprt/thread.h>
|
---|
52 | # include <iprt/assert.h>
|
---|
53 | # include <iprt/asm.h>
|
---|
54 | # include <VBox/vmm.h>
|
---|
55 | #endif /* VBOX */
|
---|
56 |
|
---|
57 | #if defined(__i386__) && !defined(CONFIG_SOFTMMU)
|
---|
58 | #define USE_CODE_COPY
|
---|
59 | #endif
|
---|
60 |
|
---|
61 | #define R_EAX 0
|
---|
62 | #define R_ECX 1
|
---|
63 | #define R_EDX 2
|
---|
64 | #define R_EBX 3
|
---|
65 | #define R_ESP 4
|
---|
66 | #define R_EBP 5
|
---|
67 | #define R_ESI 6
|
---|
68 | #define R_EDI 7
|
---|
69 |
|
---|
70 | #define R_AL 0
|
---|
71 | #define R_CL 1
|
---|
72 | #define R_DL 2
|
---|
73 | #define R_BL 3
|
---|
74 | #define R_AH 4
|
---|
75 | #define R_CH 5
|
---|
76 | #define R_DH 6
|
---|
77 | #define R_BH 7
|
---|
78 |
|
---|
79 | #define R_ES 0
|
---|
80 | #define R_CS 1
|
---|
81 | #define R_SS 2
|
---|
82 | #define R_DS 3
|
---|
83 | #define R_FS 4
|
---|
84 | #define R_GS 5
|
---|
85 |
|
---|
86 | /* segment descriptor fields */
|
---|
87 | #define DESC_G_MASK (1 << 23)
|
---|
88 | #define DESC_B_SHIFT 22
|
---|
89 | #define DESC_B_MASK (1 << DESC_B_SHIFT)
|
---|
90 | #define DESC_L_SHIFT 21 /* x86_64 only : 64 bit code segment */
|
---|
91 | #define DESC_L_MASK (1 << DESC_L_SHIFT)
|
---|
92 | #define DESC_AVL_MASK (1 << 20)
|
---|
93 | #define DESC_P_MASK (1 << 15)
|
---|
94 | #define DESC_DPL_SHIFT 13
|
---|
95 | #define DESC_S_MASK (1 << 12)
|
---|
96 | #define DESC_TYPE_SHIFT 8
|
---|
97 | #define DESC_A_MASK (1 << 8)
|
---|
98 |
|
---|
99 | #define DESC_CS_MASK (1 << 11) /* 1=code segment 0=data segment */
|
---|
100 | #define DESC_C_MASK (1 << 10) /* code: conforming */
|
---|
101 | #define DESC_R_MASK (1 << 9) /* code: readable */
|
---|
102 |
|
---|
103 | #define DESC_E_MASK (1 << 10) /* data: expansion direction */
|
---|
104 | #define DESC_W_MASK (1 << 9) /* data: writable */
|
---|
105 |
|
---|
106 | #define DESC_TSS_BUSY_MASK (1 << 9)
|
---|
107 |
|
---|
108 | /* eflags masks */
|
---|
109 | #define CC_C 0x0001
|
---|
110 | #define CC_P 0x0004
|
---|
111 | #define CC_A 0x0010
|
---|
112 | #define CC_Z 0x0040
|
---|
113 | #define CC_S 0x0080
|
---|
114 | #define CC_O 0x0800
|
---|
115 |
|
---|
116 | #define TF_SHIFT 8
|
---|
117 | #define IOPL_SHIFT 12
|
---|
118 | #define VM_SHIFT 17
|
---|
119 |
|
---|
120 | #define TF_MASK 0x00000100
|
---|
121 | #define IF_MASK 0x00000200
|
---|
122 | #define DF_MASK 0x00000400
|
---|
123 | #define IOPL_MASK 0x00003000
|
---|
124 | #define NT_MASK 0x00004000
|
---|
125 | #define RF_MASK 0x00010000
|
---|
126 | #define VM_MASK 0x00020000
|
---|
127 | #define AC_MASK 0x00040000
|
---|
128 | #define VIF_MASK 0x00080000
|
---|
129 | #define VIP_MASK 0x00100000
|
---|
130 | #define ID_MASK 0x00200000
|
---|
131 |
|
---|
132 | /* hidden flags - used internally by qemu to represent additionnal cpu
|
---|
133 | states. Only the CPL, INHIBIT_IRQ and HALTED are not redundant. We avoid
|
---|
134 | using the IOPL_MASK, TF_MASK and VM_MASK bit position to ease oring
|
---|
135 | with eflags. */
|
---|
136 | /* current cpl */
|
---|
137 | #define HF_CPL_SHIFT 0
|
---|
138 | /* true if soft mmu is being used */
|
---|
139 | #define HF_SOFTMMU_SHIFT 2
|
---|
140 | /* true if hardware interrupts must be disabled for next instruction */
|
---|
141 | #define HF_INHIBIT_IRQ_SHIFT 3
|
---|
142 | /* 16 or 32 segments */
|
---|
143 | #define HF_CS32_SHIFT 4
|
---|
144 | #define HF_SS32_SHIFT 5
|
---|
145 | /* zero base for DS, ES and SS : can be '0' only in 32 bit CS segment */
|
---|
146 | #define HF_ADDSEG_SHIFT 6
|
---|
147 | /* copy of CR0.PE (protected mode) */
|
---|
148 | #define HF_PE_SHIFT 7
|
---|
149 | #define HF_TF_SHIFT 8 /* must be same as eflags */
|
---|
150 | #define HF_MP_SHIFT 9 /* the order must be MP, EM, TS */
|
---|
151 | #define HF_EM_SHIFT 10
|
---|
152 | #define HF_TS_SHIFT 11
|
---|
153 | #define HF_IOPL_SHIFT 12 /* must be same as eflags */
|
---|
154 | #define HF_LMA_SHIFT 14 /* only used on x86_64: long mode active */
|
---|
155 | #define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment */
|
---|
156 | #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */
|
---|
157 | #define HF_VM_SHIFT 17 /* must be same as eflags */
|
---|
158 | #define HF_HALTED_SHIFT 18 /* CPU halted */
|
---|
159 | #define HF_SMM_SHIFT 19 /* CPU in SMM mode */
|
---|
160 |
|
---|
161 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT)
|
---|
162 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
|
---|
163 | #define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT)
|
---|
164 | #define HF_CS32_MASK (1 << HF_CS32_SHIFT)
|
---|
165 | #define HF_SS32_MASK (1 << HF_SS32_SHIFT)
|
---|
166 | #define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT)
|
---|
167 | #define HF_PE_MASK (1 << HF_PE_SHIFT)
|
---|
168 | #define HF_TF_MASK (1 << HF_TF_SHIFT)
|
---|
169 | #define HF_MP_MASK (1 << HF_MP_SHIFT)
|
---|
170 | #define HF_EM_MASK (1 << HF_EM_SHIFT)
|
---|
171 | #define HF_TS_MASK (1 << HF_TS_SHIFT)
|
---|
172 | #define HF_LMA_MASK (1 << HF_LMA_SHIFT)
|
---|
173 | #define HF_CS64_MASK (1 << HF_CS64_SHIFT)
|
---|
174 | #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
|
---|
175 | #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT)
|
---|
176 | #define HF_SMM_MASK (1 << HF_SMM_SHIFT)
|
---|
177 |
|
---|
178 | #define CR0_PE_MASK (1 << 0)
|
---|
179 | #define CR0_MP_MASK (1 << 1)
|
---|
180 | #define CR0_EM_MASK (1 << 2)
|
---|
181 | #define CR0_TS_MASK (1 << 3)
|
---|
182 | #define CR0_ET_MASK (1 << 4)
|
---|
183 | #define CR0_NE_MASK (1 << 5)
|
---|
184 | #define CR0_WP_MASK (1 << 16)
|
---|
185 | #define CR0_AM_MASK (1 << 18)
|
---|
186 | #define CR0_PG_MASK (1 << 31)
|
---|
187 |
|
---|
188 | #define CR4_VME_MASK (1 << 0)
|
---|
189 | #define CR4_PVI_MASK (1 << 1)
|
---|
190 | #define CR4_TSD_MASK (1 << 2)
|
---|
191 | #define CR4_DE_MASK (1 << 3)
|
---|
192 | #define CR4_PSE_MASK (1 << 4)
|
---|
193 | #define CR4_PAE_MASK (1 << 5)
|
---|
194 | #define CR4_PGE_MASK (1 << 7)
|
---|
195 | #define CR4_PCE_MASK (1 << 8)
|
---|
196 | #define CR4_OSFXSR_MASK (1 << 9)
|
---|
197 | #define CR4_OSXMMEXCPT_MASK (1 << 10)
|
---|
198 |
|
---|
199 | #define PG_PRESENT_BIT 0
|
---|
200 | #define PG_RW_BIT 1
|
---|
201 | #define PG_USER_BIT 2
|
---|
202 | #define PG_PWT_BIT 3
|
---|
203 | #define PG_PCD_BIT 4
|
---|
204 | #define PG_ACCESSED_BIT 5
|
---|
205 | #define PG_DIRTY_BIT 6
|
---|
206 | #define PG_PSE_BIT 7
|
---|
207 | #define PG_GLOBAL_BIT 8
|
---|
208 | #define PG_NX_BIT 63
|
---|
209 |
|
---|
210 | #define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
|
---|
211 | #define PG_RW_MASK (1 << PG_RW_BIT)
|
---|
212 | #define PG_USER_MASK (1 << PG_USER_BIT)
|
---|
213 | #define PG_PWT_MASK (1 << PG_PWT_BIT)
|
---|
214 | #define PG_PCD_MASK (1 << PG_PCD_BIT)
|
---|
215 | #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
|
---|
216 | #define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
|
---|
217 | #define PG_PSE_MASK (1 << PG_PSE_BIT)
|
---|
218 | #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
|
---|
219 | #define PG_NX_MASK (1LL << PG_NX_BIT)
|
---|
220 |
|
---|
221 | #define PG_ERROR_W_BIT 1
|
---|
222 |
|
---|
223 | #define PG_ERROR_P_MASK 0x01
|
---|
224 | #define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT)
|
---|
225 | #define PG_ERROR_U_MASK 0x04
|
---|
226 | #define PG_ERROR_RSVD_MASK 0x08
|
---|
227 | #define PG_ERROR_I_D_MASK 0x10
|
---|
228 |
|
---|
229 | #define MSR_IA32_APICBASE 0x1b
|
---|
230 | #define MSR_IA32_APICBASE_BSP (1<<8)
|
---|
231 | #define MSR_IA32_APICBASE_ENABLE (1<<11)
|
---|
232 | #define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
---|
233 |
|
---|
234 | #ifndef MSR_IA32_SYSENTER_CS /* VBox x86.h klugde */
|
---|
235 | #define MSR_IA32_SYSENTER_CS 0x174
|
---|
236 | #define MSR_IA32_SYSENTER_ESP 0x175
|
---|
237 | #define MSR_IA32_SYSENTER_EIP 0x176
|
---|
238 | #endif
|
---|
239 |
|
---|
240 | #define MSR_MCG_CAP 0x179
|
---|
241 | #define MSR_MCG_STATUS 0x17a
|
---|
242 | #define MSR_MCG_CTL 0x17b
|
---|
243 |
|
---|
244 | #define MSR_PAT 0x277
|
---|
245 |
|
---|
246 | #define MSR_EFER 0xc0000080
|
---|
247 |
|
---|
248 | #define MSR_EFER_SCE (1 << 0)
|
---|
249 | #define MSR_EFER_LME (1 << 8)
|
---|
250 | #define MSR_EFER_LMA (1 << 10)
|
---|
251 | #define MSR_EFER_NXE (1 << 11)
|
---|
252 | #define MSR_EFER_FFXSR (1 << 14)
|
---|
253 |
|
---|
254 | #define MSR_STAR 0xc0000081
|
---|
255 | #define MSR_LSTAR 0xc0000082
|
---|
256 | #define MSR_CSTAR 0xc0000083
|
---|
257 | #define MSR_FMASK 0xc0000084
|
---|
258 | #define MSR_FSBASE 0xc0000100
|
---|
259 | #define MSR_GSBASE 0xc0000101
|
---|
260 | #define MSR_KERNELGSBASE 0xc0000102
|
---|
261 |
|
---|
262 | /* cpuid_features bits */
|
---|
263 | #define CPUID_FP87 (1 << 0)
|
---|
264 | #define CPUID_VME (1 << 1)
|
---|
265 | #define CPUID_DE (1 << 2)
|
---|
266 | #define CPUID_PSE (1 << 3)
|
---|
267 | #define CPUID_TSC (1 << 4)
|
---|
268 | #define CPUID_MSR (1 << 5)
|
---|
269 | #define CPUID_PAE (1 << 6)
|
---|
270 | #define CPUID_MCE (1 << 7)
|
---|
271 | #define CPUID_CX8 (1 << 8)
|
---|
272 | #define CPUID_APIC (1 << 9)
|
---|
273 | #define CPUID_SEP (1 << 11) /* sysenter/sysexit */
|
---|
274 | #define CPUID_MTRR (1 << 12)
|
---|
275 | #define CPUID_PGE (1 << 13)
|
---|
276 | #define CPUID_MCA (1 << 14)
|
---|
277 | #define CPUID_CMOV (1 << 15)
|
---|
278 | #define CPUID_PAT (1 << 16)
|
---|
279 | #define CPUID_PSE36 (1 << 17)
|
---|
280 | #define CPUID_CLFLUSH (1 << 19)
|
---|
281 | /* ... */
|
---|
282 | #define CPUID_MMX (1 << 23)
|
---|
283 | #define CPUID_FXSR (1 << 24)
|
---|
284 | #define CPUID_SSE (1 << 25)
|
---|
285 | #define CPUID_SSE2 (1 << 26)
|
---|
286 |
|
---|
287 | #ifdef VBOX
|
---|
288 | #define CPUID_HTT (1 << 28)
|
---|
289 | #endif
|
---|
290 |
|
---|
291 | #define CPUID_EXT_SSE3 (1 << 0)
|
---|
292 | #define CPUID_EXT_MONITOR (1 << 3)
|
---|
293 | #define CPUID_EXT_DSCPL (1 << 4)
|
---|
294 | #define CPUID_EXT_VMX (1 << 5)
|
---|
295 | #define CPUID_EXT_SMX (1 << 6)
|
---|
296 | #define CPUID_EXT_EST (1 << 7)
|
---|
297 | #define CPUID_EXT_TM2 (1 << 8)
|
---|
298 | #define CPUID_EXT_SSSE3 (1 << 9)
|
---|
299 | #define CPUID_EXT_CID (1 << 10)
|
---|
300 | #define CPUID_EXT_CX16 (1 << 13)
|
---|
301 | #define CPUID_EXT_XTPR (1 << 14)
|
---|
302 | #define CPUID_EXT_DCA (1 << 17)
|
---|
303 | #define CPUID_EXT_POPCNT (1 << 22)
|
---|
304 |
|
---|
305 | #define CPUID_EXT2_SYSCALL (1 << 11)
|
---|
306 | #define CPUID_EXT2_MP (1 << 19)
|
---|
307 | #define CPUID_EXT2_NX (1 << 20)
|
---|
308 | #define CPUID_EXT2_MMXEXT (1 << 22)
|
---|
309 | #define CPUID_EXT2_FFXSR (1 << 25)
|
---|
310 | #define CPUID_EXT2_PDPE1GB (1 << 26)
|
---|
311 | #define CPUID_EXT2_RDTSCP (1 << 27)
|
---|
312 | #define CPUID_EXT2_LM (1 << 29)
|
---|
313 | #define CPUID_EXT2_3DNOWEXT (1 << 30)
|
---|
314 | #define CPUID_EXT2_3DNOW (1 << 31)
|
---|
315 |
|
---|
316 | #define CPUID_EXT3_LAHF_LM (1 << 0)
|
---|
317 | #define CPUID_EXT3_CMP_LEG (1 << 1)
|
---|
318 | #define CPUID_EXT3_SVM (1 << 2)
|
---|
319 | #define CPUID_EXT3_EXTAPIC (1 << 3)
|
---|
320 | #define CPUID_EXT3_CR8LEG (1 << 4)
|
---|
321 | #define CPUID_EXT3_ABM (1 << 5)
|
---|
322 | #define CPUID_EXT3_SSE4A (1 << 6)
|
---|
323 | #define CPUID_EXT3_MISALIGNSSE (1 << 7)
|
---|
324 | #define CPUID_EXT3_3DNOWPREFETCH (1 << 8)
|
---|
325 | #define CPUID_EXT3_OSVW (1 << 9)
|
---|
326 | #define CPUID_EXT3_IBS (1 << 10)
|
---|
327 |
|
---|
328 | #define EXCP00_DIVZ 0
|
---|
329 | #define EXCP01_SSTP 1
|
---|
330 | #define EXCP02_NMI 2
|
---|
331 | #define EXCP03_INT3 3
|
---|
332 | #define EXCP04_INTO 4
|
---|
333 | #define EXCP05_BOUND 5
|
---|
334 | #define EXCP06_ILLOP 6
|
---|
335 | #define EXCP07_PREX 7
|
---|
336 | #define EXCP08_DBLE 8
|
---|
337 | #define EXCP09_XERR 9
|
---|
338 | #define EXCP0A_TSS 10
|
---|
339 | #define EXCP0B_NOSEG 11
|
---|
340 | #define EXCP0C_STACK 12
|
---|
341 | #define EXCP0D_GPF 13
|
---|
342 | #define EXCP0E_PAGE 14
|
---|
343 | #define EXCP10_COPR 16
|
---|
344 | #define EXCP11_ALGN 17
|
---|
345 | #define EXCP12_MCHK 18
|
---|
346 |
|
---|
347 | enum {
|
---|
348 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
---|
349 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
|
---|
350 |
|
---|
351 | CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */
|
---|
352 | CC_OP_MULW,
|
---|
353 | CC_OP_MULL,
|
---|
354 | CC_OP_MULQ,
|
---|
355 |
|
---|
356 | CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
357 | CC_OP_ADDW,
|
---|
358 | CC_OP_ADDL,
|
---|
359 | CC_OP_ADDQ,
|
---|
360 |
|
---|
361 | CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
362 | CC_OP_ADCW,
|
---|
363 | CC_OP_ADCL,
|
---|
364 | CC_OP_ADCQ,
|
---|
365 |
|
---|
366 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
367 | CC_OP_SUBW,
|
---|
368 | CC_OP_SUBL,
|
---|
369 | CC_OP_SUBQ,
|
---|
370 |
|
---|
371 | CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
372 | CC_OP_SBBW,
|
---|
373 | CC_OP_SBBL,
|
---|
374 | CC_OP_SBBQ,
|
---|
375 |
|
---|
376 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */
|
---|
377 | CC_OP_LOGICW,
|
---|
378 | CC_OP_LOGICL,
|
---|
379 | CC_OP_LOGICQ,
|
---|
380 |
|
---|
381 | CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
---|
382 | CC_OP_INCW,
|
---|
383 | CC_OP_INCL,
|
---|
384 | CC_OP_INCQ,
|
---|
385 |
|
---|
386 | CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
---|
387 | CC_OP_DECW,
|
---|
388 | CC_OP_DECL,
|
---|
389 | CC_OP_DECQ,
|
---|
390 |
|
---|
391 | CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.msb = C */
|
---|
392 | CC_OP_SHLW,
|
---|
393 | CC_OP_SHLL,
|
---|
394 | CC_OP_SHLQ,
|
---|
395 |
|
---|
396 | CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
|
---|
397 | CC_OP_SARW,
|
---|
398 | CC_OP_SARL,
|
---|
399 | CC_OP_SARQ,
|
---|
400 |
|
---|
401 | CC_OP_NB,
|
---|
402 | };
|
---|
403 |
|
---|
404 | #ifdef FLOATX80
|
---|
405 | #define USE_X86LDOUBLE
|
---|
406 | #endif
|
---|
407 |
|
---|
408 | #ifdef USE_X86LDOUBLE
|
---|
409 | typedef floatx80 CPU86_LDouble;
|
---|
410 | #else
|
---|
411 | typedef float64 CPU86_LDouble;
|
---|
412 | #endif
|
---|
413 |
|
---|
414 | typedef struct SegmentCache {
|
---|
415 | uint32_t selector;
|
---|
416 | target_ulong base;
|
---|
417 | uint32_t limit;
|
---|
418 | uint32_t flags;
|
---|
419 | #ifdef VBOX
|
---|
420 | /** The new selector is saved here when we are unable to sync it before invoking the recompiled code. */
|
---|
421 | uint32_t newselector;
|
---|
422 | #endif
|
---|
423 | } SegmentCache;
|
---|
424 |
|
---|
425 | typedef union {
|
---|
426 | uint8_t _b[16];
|
---|
427 | uint16_t _w[8];
|
---|
428 | uint32_t _l[4];
|
---|
429 | uint64_t _q[2];
|
---|
430 | float32 _s[4];
|
---|
431 | float64 _d[2];
|
---|
432 | } XMMReg;
|
---|
433 |
|
---|
434 | typedef union {
|
---|
435 | uint8_t _b[8];
|
---|
436 | uint16_t _w[2];
|
---|
437 | uint32_t _l[1];
|
---|
438 | uint64_t q;
|
---|
439 | } MMXReg;
|
---|
440 |
|
---|
441 | #ifdef WORDS_BIGENDIAN
|
---|
442 | #define XMM_B(n) _b[15 - (n)]
|
---|
443 | #define XMM_W(n) _w[7 - (n)]
|
---|
444 | #define XMM_L(n) _l[3 - (n)]
|
---|
445 | #define XMM_S(n) _s[3 - (n)]
|
---|
446 | #define XMM_Q(n) _q[1 - (n)]
|
---|
447 | #define XMM_D(n) _d[1 - (n)]
|
---|
448 |
|
---|
449 | #define MMX_B(n) _b[7 - (n)]
|
---|
450 | #define MMX_W(n) _w[3 - (n)]
|
---|
451 | #define MMX_L(n) _l[1 - (n)]
|
---|
452 | #else
|
---|
453 | #define XMM_B(n) _b[n]
|
---|
454 | #define XMM_W(n) _w[n]
|
---|
455 | #define XMM_L(n) _l[n]
|
---|
456 | #define XMM_S(n) _s[n]
|
---|
457 | #define XMM_Q(n) _q[n]
|
---|
458 | #define XMM_D(n) _d[n]
|
---|
459 |
|
---|
460 | #define MMX_B(n) _b[n]
|
---|
461 | #define MMX_W(n) _w[n]
|
---|
462 | #define MMX_L(n) _l[n]
|
---|
463 | #endif
|
---|
464 | #define MMX_Q(n) q
|
---|
465 |
|
---|
466 | #ifdef TARGET_X86_64
|
---|
467 | #define CPU_NB_REGS 16
|
---|
468 | #else
|
---|
469 | #define CPU_NB_REGS 8
|
---|
470 | #endif
|
---|
471 |
|
---|
472 | typedef struct CPUX86State {
|
---|
473 | #if TARGET_LONG_BITS > HOST_LONG_BITS
|
---|
474 | /* temporaries if we cannot store them in host registers */
|
---|
475 | target_ulong t0, t1, t2;
|
---|
476 | #endif
|
---|
477 |
|
---|
478 | /* standard registers */
|
---|
479 | target_ulong regs[CPU_NB_REGS];
|
---|
480 | target_ulong eip;
|
---|
481 | target_ulong eflags; /* eflags register. During CPU emulation, CC
|
---|
482 | flags and DF are set to zero because they are
|
---|
483 | stored elsewhere */
|
---|
484 |
|
---|
485 | /* emulator internal eflags handling */
|
---|
486 | target_ulong cc_src;
|
---|
487 | target_ulong cc_dst;
|
---|
488 | uint32_t cc_op;
|
---|
489 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
|
---|
490 | uint32_t hflags; /* hidden flags, see HF_xxx constants */
|
---|
491 |
|
---|
492 | /* segments */
|
---|
493 | SegmentCache segs[6]; /* selector values */
|
---|
494 | SegmentCache ldt;
|
---|
495 | SegmentCache tr;
|
---|
496 | SegmentCache gdt; /* only base and limit are used */
|
---|
497 | SegmentCache idt; /* only base and limit are used */
|
---|
498 |
|
---|
499 | target_ulong cr[5]; /* NOTE: cr1 is unused */
|
---|
500 | uint32_t a20_mask;
|
---|
501 |
|
---|
502 | /* FPU state */
|
---|
503 | unsigned int fpstt; /* top of stack index */
|
---|
504 | unsigned int fpus;
|
---|
505 | unsigned int fpuc;
|
---|
506 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */
|
---|
507 | union {
|
---|
508 | #ifdef USE_X86LDOUBLE
|
---|
509 | CPU86_LDouble d __attribute__((aligned(16)));
|
---|
510 | #else
|
---|
511 | CPU86_LDouble d;
|
---|
512 | #endif
|
---|
513 | MMXReg mmx;
|
---|
514 | } fpregs[8];
|
---|
515 |
|
---|
516 | /* emulator internal variables */
|
---|
517 | float_status fp_status;
|
---|
518 | #ifdef VBOX
|
---|
519 | uint32_t alignment3[3]; /* force the long double to start a 16 byte line. */
|
---|
520 | #endif
|
---|
521 | CPU86_LDouble ft0;
|
---|
522 | #if defined(VBOX) && defined(RT_ARCH_X86) && !defined(RT_OS_DARWIN)
|
---|
523 | uint32_t alignment4; /* long double is 12 byte, pad it to 16. */
|
---|
524 | #endif
|
---|
525 | union {
|
---|
526 | float f;
|
---|
527 | double d;
|
---|
528 | int i32;
|
---|
529 | int64_t i64;
|
---|
530 | } fp_convert;
|
---|
531 |
|
---|
532 | float_status sse_status;
|
---|
533 | uint32_t mxcsr;
|
---|
534 | XMMReg xmm_regs[CPU_NB_REGS];
|
---|
535 | XMMReg xmm_t0;
|
---|
536 | MMXReg mmx_t0;
|
---|
537 |
|
---|
538 | /* sysenter registers */
|
---|
539 | uint32_t sysenter_cs;
|
---|
540 | uint32_t sysenter_esp;
|
---|
541 | uint32_t sysenter_eip;
|
---|
542 | #ifdef VBOX
|
---|
543 | uint32_t alignment0;
|
---|
544 | #endif
|
---|
545 | uint64_t efer;
|
---|
546 | uint64_t star;
|
---|
547 | #ifdef TARGET_X86_64
|
---|
548 | target_ulong lstar;
|
---|
549 | target_ulong cstar;
|
---|
550 | target_ulong fmask;
|
---|
551 | target_ulong kernelgsbase;
|
---|
552 | #endif
|
---|
553 |
|
---|
554 | uint64_t pat;
|
---|
555 |
|
---|
556 | /* temporary data for USE_CODE_COPY mode */
|
---|
557 | #ifdef USE_CODE_COPY
|
---|
558 | uint32_t tmp0;
|
---|
559 | uint32_t saved_esp;
|
---|
560 | int native_fp_regs; /* if true, the FPU state is in the native CPU regs */
|
---|
561 | #endif
|
---|
562 |
|
---|
563 | /* exception/interrupt handling */
|
---|
564 | jmp_buf jmp_env;
|
---|
565 | #if defined(VBOX) && defined(RT_OS_WINDOWS) && defined(RT_ARCH_X86)
|
---|
566 | /* This will be removed when switching to the no-crt code everywhere. */
|
---|
567 | uint32_t alignment1[23];
|
---|
568 | #endif
|
---|
569 | int exception_index;
|
---|
570 | int error_code;
|
---|
571 | int exception_is_int;
|
---|
572 | target_ulong exception_next_eip;
|
---|
573 | target_ulong dr[8]; /* debug registers */
|
---|
574 | uint32_t smbase;
|
---|
575 | int interrupt_request;
|
---|
576 | int user_mode_only; /* user mode only simulation */
|
---|
577 |
|
---|
578 | CPU_COMMON
|
---|
579 |
|
---|
580 | #ifdef VBOX
|
---|
581 | /** cpu state flags. (see defines below) */
|
---|
582 | uint32_t state;
|
---|
583 | /** The VM handle. */
|
---|
584 | PVM pVM;
|
---|
585 | /** code buffer for instruction emulation */
|
---|
586 | void *pvCodeBuffer;
|
---|
587 | /** code buffer size */
|
---|
588 | uint32_t cbCodeBuffer;
|
---|
589 | #endif /* VBOX */
|
---|
590 |
|
---|
591 | /* processor features (e.g. for CPUID insn) */
|
---|
592 | #ifndef VBOX /* remR3CpuId deals with these */
|
---|
593 | uint32_t cpuid_level;
|
---|
594 | uint32_t cpuid_vendor1;
|
---|
595 | uint32_t cpuid_vendor2;
|
---|
596 | uint32_t cpuid_vendor3;
|
---|
597 | uint32_t cpuid_version;
|
---|
598 | #endif /* !VBOX */
|
---|
599 | uint32_t cpuid_features;
|
---|
600 | uint32_t cpuid_ext_features;
|
---|
601 | #ifndef VBOX
|
---|
602 | uint32_t cpuid_xlevel;
|
---|
603 | uint32_t cpuid_model[12];
|
---|
604 | #endif /* !VBOX */
|
---|
605 | uint32_t cpuid_ext2_features;
|
---|
606 | uint32_t cpuid_ext3_features;
|
---|
607 |
|
---|
608 | #ifndef VBOX
|
---|
609 | #ifdef USE_KQEMU
|
---|
610 | int kqemu_enabled;
|
---|
611 | int last_io_time;
|
---|
612 | #endif
|
---|
613 | /* in order to simplify APIC support, we leave this pointer to the
|
---|
614 | user */
|
---|
615 | struct APICState *apic_state;
|
---|
616 | #else
|
---|
617 | uint32_t alignment2[3];
|
---|
618 | #endif
|
---|
619 | } CPUX86State;
|
---|
620 |
|
---|
621 | #ifdef VBOX
|
---|
622 | /** CPUX86State state flags
|
---|
623 | * @{ */
|
---|
624 | #define CPU_RAW_RING0 0x0002 /* Set after first time RawR0 is executed, never cleared. */
|
---|
625 | #define CPU_EMULATE_SINGLE_INSTR 0x0040 /* Execute a single instruction in emulation mode */
|
---|
626 | #define CPU_EMULATE_SINGLE_STEP 0x0080 /* go into single step mode */
|
---|
627 | #define CPU_RAW_HWACC 0x0100 /* Set after first time HWACC is executed, never cleared. */
|
---|
628 | /** @} */
|
---|
629 | #endif /* !VBOX */
|
---|
630 |
|
---|
631 | #ifdef VBOX
|
---|
632 | CPUX86State *cpu_x86_init(CPUX86State *env);
|
---|
633 | #else /* !VBOX */
|
---|
634 | CPUX86State *cpu_x86_init(void);
|
---|
635 | #endif /* !VBOX */
|
---|
636 | int cpu_x86_exec(CPUX86State *s);
|
---|
637 | void cpu_x86_close(CPUX86State *s);
|
---|
638 | int cpu_get_pic_interrupt(CPUX86State *s);
|
---|
639 | /* MSDOS compatibility mode FPU exception support */
|
---|
640 | void cpu_set_ferr(CPUX86State *s);
|
---|
641 |
|
---|
642 | /* this function must always be used to load data in the segment
|
---|
643 | cache: it synchronizes the hflags with the segment cache values */
|
---|
644 | static inline void cpu_x86_load_seg_cache(CPUX86State *env,
|
---|
645 | int seg_reg, unsigned int selector,
|
---|
646 | target_ulong base,
|
---|
647 | unsigned int limit,
|
---|
648 | unsigned int flags)
|
---|
649 | {
|
---|
650 | SegmentCache *sc;
|
---|
651 | unsigned int new_hflags;
|
---|
652 |
|
---|
653 | sc = &env->segs[seg_reg];
|
---|
654 | sc->selector = selector;
|
---|
655 | sc->base = base;
|
---|
656 | sc->limit = limit;
|
---|
657 | sc->flags = flags;
|
---|
658 | #ifdef VBOX
|
---|
659 | sc->newselector = 0;
|
---|
660 | #endif
|
---|
661 |
|
---|
662 | /* update the hidden flags */
|
---|
663 | {
|
---|
664 | if (seg_reg == R_CS) {
|
---|
665 | #ifdef TARGET_X86_64
|
---|
666 | if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) {
|
---|
667 | /* long mode */
|
---|
668 | env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
|
---|
669 | env->hflags &= ~(HF_ADDSEG_MASK);
|
---|
670 | } else
|
---|
671 | #endif
|
---|
672 | {
|
---|
673 | /* legacy / compatibility case */
|
---|
674 | new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
|
---|
675 | >> (DESC_B_SHIFT - HF_CS32_SHIFT);
|
---|
676 | env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) |
|
---|
677 | new_hflags;
|
---|
678 | }
|
---|
679 | }
|
---|
680 | new_hflags = (env->segs[R_SS].flags & DESC_B_MASK)
|
---|
681 | >> (DESC_B_SHIFT - HF_SS32_SHIFT);
|
---|
682 | if (env->hflags & HF_CS64_MASK) {
|
---|
683 | /* zero base assumed for DS, ES and SS in long mode */
|
---|
684 | } else if (!(env->cr[0] & CR0_PE_MASK) ||
|
---|
685 | (env->eflags & VM_MASK) ||
|
---|
686 | !(env->hflags & HF_CS32_MASK)) {
|
---|
687 | /* XXX: try to avoid this test. The problem comes from the
|
---|
688 | fact that is real mode or vm86 mode we only modify the
|
---|
689 | 'base' and 'selector' fields of the segment cache to go
|
---|
690 | faster. A solution may be to force addseg to one in
|
---|
691 | translate-i386.c. */
|
---|
692 | new_hflags |= HF_ADDSEG_MASK;
|
---|
693 | } else {
|
---|
694 | new_hflags |= ((env->segs[R_DS].base |
|
---|
695 | env->segs[R_ES].base |
|
---|
696 | env->segs[R_SS].base) != 0) <<
|
---|
697 | HF_ADDSEG_SHIFT;
|
---|
698 | }
|
---|
699 | env->hflags = (env->hflags &
|
---|
700 | ~(HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags;
|
---|
701 | }
|
---|
702 | }
|
---|
703 |
|
---|
704 | /* wrapper, just in case memory mappings must be changed */
|
---|
705 | static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
|
---|
706 | {
|
---|
707 | #if HF_CPL_MASK == 3
|
---|
708 | s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl;
|
---|
709 | #else
|
---|
710 | #error HF_CPL_MASK is hardcoded
|
---|
711 | #endif
|
---|
712 | }
|
---|
713 |
|
---|
714 | /* used for debug or cpu save/restore */
|
---|
715 | void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f);
|
---|
716 | CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper);
|
---|
717 |
|
---|
718 | /* the following helpers are only usable in user mode simulation as
|
---|
719 | they can trigger unexpected exceptions */
|
---|
720 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
|
---|
721 | void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
|
---|
722 | void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
|
---|
723 |
|
---|
724 | /* you can call this signal handler from your SIGBUS and SIGSEGV
|
---|
725 | signal handlers to inform the virtual CPU of exceptions. non zero
|
---|
726 | is returned if the signal was handled by the virtual CPU. */
|
---|
727 | int cpu_x86_signal_handler(int host_signum, void *pinfo,
|
---|
728 | void *puc);
|
---|
729 | void cpu_x86_set_a20(CPUX86State *env, int a20_state);
|
---|
730 |
|
---|
731 | uint64_t cpu_get_tsc(CPUX86State *env);
|
---|
732 |
|
---|
733 | void cpu_set_apic_base(CPUX86State *env, uint64_t val);
|
---|
734 | uint64_t cpu_get_apic_base(CPUX86State *env);
|
---|
735 | void cpu_set_apic_tpr(CPUX86State *env, uint8_t val);
|
---|
736 | #ifndef NO_CPU_IO_DEFS
|
---|
737 | uint8_t cpu_get_apic_tpr(CPUX86State *env);
|
---|
738 | #endif
|
---|
739 | void cpu_smm_update(CPUX86State *env);
|
---|
740 |
|
---|
741 | /* will be suppressed */
|
---|
742 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
|
---|
743 |
|
---|
744 | /* used to debug */
|
---|
745 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */
|
---|
746 | #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
|
---|
747 |
|
---|
748 | #ifdef USE_KQEMU
|
---|
749 | static inline int cpu_get_time_fast(void)
|
---|
750 | {
|
---|
751 | int low, high;
|
---|
752 | asm volatile("rdtsc" : "=a" (low), "=d" (high));
|
---|
753 | return low;
|
---|
754 | }
|
---|
755 | #endif
|
---|
756 |
|
---|
757 | #ifdef VBOX
|
---|
758 | void cpu_trap_raw(CPUX86State *env1);
|
---|
759 |
|
---|
760 | /* in helper.c */
|
---|
761 | uint8_t read_byte(CPUX86State *env1, target_ulong addr);
|
---|
762 | uint16_t read_word(CPUX86State *env1, target_ulong addr);
|
---|
763 | void write_byte(CPUX86State *env1, target_ulong addr, uint8_t val);
|
---|
764 | uint32_t read_dword(CPUX86State *env1, target_ulong addr);
|
---|
765 | void write_word(CPUX86State *env1, target_ulong addr, uint16_t val);
|
---|
766 | void write_dword(CPUX86State *env1, target_ulong addr, uint32_t val);
|
---|
767 | /* in helper.c */
|
---|
768 | int emulate_single_instr(CPUX86State *env1);
|
---|
769 | int get_ss_esp_from_tss_raw(CPUX86State *env1, uint32_t *ss_ptr, uint32_t *esp_ptr, int dpl);
|
---|
770 |
|
---|
771 | void restore_raw_fp_state(CPUX86State *env, uint8_t *ptr);
|
---|
772 | void save_raw_fp_state(CPUX86State *env, uint8_t *ptr);
|
---|
773 |
|
---|
774 | #endif
|
---|
775 |
|
---|
776 | #define TARGET_PAGE_BITS 12
|
---|
777 | #include "cpu-all.h"
|
---|
778 |
|
---|
779 | #endif /* CPU_I386_H */
|
---|