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 |
|
---|
21 | /*
|
---|
22 | * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
23 | * other than GPL or LGPL is available it will apply instead, Sun elects to use only
|
---|
24 | * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
25 | * a choice of LGPL license versions is made available with the language indicating
|
---|
26 | * that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
27 | * of the LGPL is applied is otherwise unspecified.
|
---|
28 | */
|
---|
29 | #ifndef CPU_I386_H
|
---|
30 | #define CPU_I386_H
|
---|
31 |
|
---|
32 | #include "config.h"
|
---|
33 |
|
---|
34 | #ifdef TARGET_X86_64
|
---|
35 | #define TARGET_LONG_BITS 64
|
---|
36 | #else
|
---|
37 | #define TARGET_LONG_BITS 32
|
---|
38 | #endif
|
---|
39 |
|
---|
40 | /* target supports implicit self modifying code */
|
---|
41 | #define TARGET_HAS_SMC
|
---|
42 | /* support for self modifying code even if the modified instruction is
|
---|
43 | close to the modifying instruction */
|
---|
44 | #define TARGET_HAS_PRECISE_SMC
|
---|
45 |
|
---|
46 | #define TARGET_HAS_ICE 1
|
---|
47 |
|
---|
48 | #ifdef TARGET_X86_64
|
---|
49 | #define ELF_MACHINE EM_X86_64
|
---|
50 | #else
|
---|
51 | #define ELF_MACHINE EM_386
|
---|
52 | #endif
|
---|
53 |
|
---|
54 | #include "cpu-defs.h"
|
---|
55 |
|
---|
56 | #include "softfloat.h"
|
---|
57 |
|
---|
58 | #if defined(VBOX)
|
---|
59 | # include <iprt/critsect.h>
|
---|
60 | # include <iprt/thread.h>
|
---|
61 | # include <iprt/assert.h>
|
---|
62 | # include <iprt/asm.h>
|
---|
63 | # include <VBox/vmm.h>
|
---|
64 | #endif /* VBOX */
|
---|
65 |
|
---|
66 | #define R_EAX 0
|
---|
67 | #define R_ECX 1
|
---|
68 | #define R_EDX 2
|
---|
69 | #define R_EBX 3
|
---|
70 | #define R_ESP 4
|
---|
71 | #define R_EBP 5
|
---|
72 | #define R_ESI 6
|
---|
73 | #define R_EDI 7
|
---|
74 |
|
---|
75 | #define R_AL 0
|
---|
76 | #define R_CL 1
|
---|
77 | #define R_DL 2
|
---|
78 | #define R_BL 3
|
---|
79 | #define R_AH 4
|
---|
80 | #define R_CH 5
|
---|
81 | #define R_DH 6
|
---|
82 | #define R_BH 7
|
---|
83 |
|
---|
84 | #define R_ES 0
|
---|
85 | #define R_CS 1
|
---|
86 | #define R_SS 2
|
---|
87 | #define R_DS 3
|
---|
88 | #define R_FS 4
|
---|
89 | #define R_GS 5
|
---|
90 |
|
---|
91 | /* segment descriptor fields */
|
---|
92 | #define DESC_G_MASK (1 << 23)
|
---|
93 | #define DESC_B_SHIFT 22
|
---|
94 | #define DESC_B_MASK (1 << DESC_B_SHIFT)
|
---|
95 | #define DESC_L_SHIFT 21 /* x86_64 only : 64 bit code segment */
|
---|
96 | #define DESC_L_MASK (1 << DESC_L_SHIFT)
|
---|
97 | #define DESC_AVL_MASK (1 << 20)
|
---|
98 | #define DESC_P_MASK (1 << 15)
|
---|
99 | #define DESC_DPL_SHIFT 13
|
---|
100 | #define DESC_S_MASK (1 << 12)
|
---|
101 | #define DESC_TYPE_SHIFT 8
|
---|
102 | #define DESC_A_MASK (1 << 8)
|
---|
103 |
|
---|
104 | #define DESC_CS_MASK (1 << 11) /* 1=code segment 0=data segment */
|
---|
105 | #define DESC_C_MASK (1 << 10) /* code: conforming */
|
---|
106 | #define DESC_R_MASK (1 << 9) /* code: readable */
|
---|
107 |
|
---|
108 | #define DESC_E_MASK (1 << 10) /* data: expansion direction */
|
---|
109 | #define DESC_W_MASK (1 << 9) /* data: writable */
|
---|
110 |
|
---|
111 | #define DESC_TSS_BUSY_MASK (1 << 9)
|
---|
112 |
|
---|
113 | /* eflags masks */
|
---|
114 | #define CC_C 0x0001
|
---|
115 | #define CC_P 0x0004
|
---|
116 | #define CC_A 0x0010
|
---|
117 | #define CC_Z 0x0040
|
---|
118 | #define CC_S 0x0080
|
---|
119 | #define CC_O 0x0800
|
---|
120 |
|
---|
121 | #define TF_SHIFT 8
|
---|
122 | #define IOPL_SHIFT 12
|
---|
123 | #define VM_SHIFT 17
|
---|
124 |
|
---|
125 | #define TF_MASK 0x00000100
|
---|
126 | #define IF_MASK 0x00000200
|
---|
127 | #define DF_MASK 0x00000400
|
---|
128 | #define IOPL_MASK 0x00003000
|
---|
129 | #define NT_MASK 0x00004000
|
---|
130 | #define RF_MASK 0x00010000
|
---|
131 | #define VM_MASK 0x00020000
|
---|
132 | #define AC_MASK 0x00040000
|
---|
133 | #define VIF_MASK 0x00080000
|
---|
134 | #define VIP_MASK 0x00100000
|
---|
135 | #define ID_MASK 0x00200000
|
---|
136 |
|
---|
137 | /* hidden flags - used internally by qemu to represent additionnal cpu
|
---|
138 | states. Only the CPL, INHIBIT_IRQ, SMM and SVMI are not redundant. We avoid
|
---|
139 | using the IOPL_MASK, TF_MASK and VM_MASK bit position to ease oring
|
---|
140 | with eflags. */
|
---|
141 | /* current cpl */
|
---|
142 | #define HF_CPL_SHIFT 0
|
---|
143 | /* true if soft mmu is being used */
|
---|
144 | #define HF_SOFTMMU_SHIFT 2
|
---|
145 | /* true if hardware interrupts must be disabled for next instruction */
|
---|
146 | #define HF_INHIBIT_IRQ_SHIFT 3
|
---|
147 | /* 16 or 32 segments */
|
---|
148 | #define HF_CS32_SHIFT 4
|
---|
149 | #define HF_SS32_SHIFT 5
|
---|
150 | /* zero base for DS, ES and SS : can be '0' only in 32 bit CS segment */
|
---|
151 | #define HF_ADDSEG_SHIFT 6
|
---|
152 | /* copy of CR0.PE (protected mode) */
|
---|
153 | #define HF_PE_SHIFT 7
|
---|
154 | #define HF_TF_SHIFT 8 /* must be same as eflags */
|
---|
155 | #define HF_MP_SHIFT 9 /* the order must be MP, EM, TS */
|
---|
156 | #define HF_EM_SHIFT 10
|
---|
157 | #define HF_TS_SHIFT 11
|
---|
158 | #define HF_IOPL_SHIFT 12 /* must be same as eflags */
|
---|
159 | #define HF_LMA_SHIFT 14 /* only used on x86_64: long mode active */
|
---|
160 | #define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment */
|
---|
161 | #define HF_OSFXSR_SHIFT 16 /* CR4.OSFXSR */
|
---|
162 | #define HF_VM_SHIFT 17 /* must be same as eflags */
|
---|
163 | #define HF_HALTED_SHIFT 18 /* CPU halted */
|
---|
164 | #define HF_SMM_SHIFT 19 /* CPU in SMM mode */
|
---|
165 | #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */
|
---|
166 | #define HF_SVMI_SHIFT 21 /* SVM intercepts are active */
|
---|
167 |
|
---|
168 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT)
|
---|
169 | #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT)
|
---|
170 | #define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT)
|
---|
171 | #define HF_CS32_MASK (1 << HF_CS32_SHIFT)
|
---|
172 | #define HF_SS32_MASK (1 << HF_SS32_SHIFT)
|
---|
173 | #define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT)
|
---|
174 | #define HF_PE_MASK (1 << HF_PE_SHIFT)
|
---|
175 | #define HF_TF_MASK (1 << HF_TF_SHIFT)
|
---|
176 | #define HF_MP_MASK (1 << HF_MP_SHIFT)
|
---|
177 | #define HF_EM_MASK (1 << HF_EM_SHIFT)
|
---|
178 | #define HF_TS_MASK (1 << HF_TS_SHIFT)
|
---|
179 | #define HF_LMA_MASK (1 << HF_LMA_SHIFT)
|
---|
180 | #define HF_CS64_MASK (1 << HF_CS64_SHIFT)
|
---|
181 | #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT)
|
---|
182 | #define HF_HALTED_MASK (1 << HF_HALTED_SHIFT)
|
---|
183 | #define HF_SMM_MASK (1 << HF_SMM_SHIFT)
|
---|
184 | #define HF_SVME_MASK (1 << HF_SVME_SHIFT)
|
---|
185 | #define HF_SVMI_MASK (1 << HF_SVMI_SHIFT)
|
---|
186 |
|
---|
187 | /* hflags2 */
|
---|
188 |
|
---|
189 | #define HF2_GIF_SHIFT 0 /* if set CPU takes interrupts */
|
---|
190 | #define HF2_HIF_SHIFT 1 /* value of IF_MASK when entering SVM */
|
---|
191 | #define HF2_NMI_SHIFT 2 /* CPU serving NMI */
|
---|
192 | #define HF2_VINTR_SHIFT 3 /* value of V_INTR_MASKING bit */
|
---|
193 |
|
---|
194 | #define HF2_GIF_MASK (1 << HF2_GIF_SHIFT)
|
---|
195 | #define HF2_HIF_MASK (1 << HF2_HIF_SHIFT)
|
---|
196 | #define HF2_NMI_MASK (1 << HF2_NMI_SHIFT)
|
---|
197 | #define HF2_VINTR_MASK (1 << HF2_VINTR_SHIFT)
|
---|
198 |
|
---|
199 | #define CR0_PE_MASK (1 << 0)
|
---|
200 | #define CR0_MP_MASK (1 << 1)
|
---|
201 | #define CR0_EM_MASK (1 << 2)
|
---|
202 | #define CR0_TS_MASK (1 << 3)
|
---|
203 | #define CR0_ET_MASK (1 << 4)
|
---|
204 | #define CR0_NE_MASK (1 << 5)
|
---|
205 | #define CR0_WP_MASK (1 << 16)
|
---|
206 | #define CR0_AM_MASK (1 << 18)
|
---|
207 | #define CR0_PG_MASK (1 << 31)
|
---|
208 |
|
---|
209 | #define CR4_VME_MASK (1 << 0)
|
---|
210 | #define CR4_PVI_MASK (1 << 1)
|
---|
211 | #define CR4_TSD_MASK (1 << 2)
|
---|
212 | #define CR4_DE_MASK (1 << 3)
|
---|
213 | #define CR4_PSE_MASK (1 << 4)
|
---|
214 | #define CR4_PAE_MASK (1 << 5)
|
---|
215 | #define CR4_PGE_MASK (1 << 7)
|
---|
216 | #define CR4_PCE_MASK (1 << 8)
|
---|
217 | #define CR4_OSFXSR_MASK (1 << 9)
|
---|
218 | #define CR4_OSXMMEXCPT_MASK (1 << 10)
|
---|
219 |
|
---|
220 | #define PG_PRESENT_BIT 0
|
---|
221 | #define PG_RW_BIT 1
|
---|
222 | #define PG_USER_BIT 2
|
---|
223 | #define PG_PWT_BIT 3
|
---|
224 | #define PG_PCD_BIT 4
|
---|
225 | #define PG_ACCESSED_BIT 5
|
---|
226 | #define PG_DIRTY_BIT 6
|
---|
227 | #define PG_PSE_BIT 7
|
---|
228 | #define PG_GLOBAL_BIT 8
|
---|
229 | #define PG_NX_BIT 63
|
---|
230 |
|
---|
231 | #define PG_PRESENT_MASK (1 << PG_PRESENT_BIT)
|
---|
232 | #define PG_RW_MASK (1 << PG_RW_BIT)
|
---|
233 | #define PG_USER_MASK (1 << PG_USER_BIT)
|
---|
234 | #define PG_PWT_MASK (1 << PG_PWT_BIT)
|
---|
235 | #define PG_PCD_MASK (1 << PG_PCD_BIT)
|
---|
236 | #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
|
---|
237 | #define PG_DIRTY_MASK (1 << PG_DIRTY_BIT)
|
---|
238 | #define PG_PSE_MASK (1 << PG_PSE_BIT)
|
---|
239 | #define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT)
|
---|
240 | #define PG_NX_MASK (1LL << PG_NX_BIT)
|
---|
241 |
|
---|
242 | #define PG_ERROR_W_BIT 1
|
---|
243 |
|
---|
244 | #define PG_ERROR_P_MASK 0x01
|
---|
245 | #define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT)
|
---|
246 | #define PG_ERROR_U_MASK 0x04
|
---|
247 | #define PG_ERROR_RSVD_MASK 0x08
|
---|
248 | #define PG_ERROR_I_D_MASK 0x10
|
---|
249 |
|
---|
250 | #define MSR_IA32_APICBASE 0x1b
|
---|
251 | #define MSR_IA32_APICBASE_BSP (1<<8)
|
---|
252 | #define MSR_IA32_APICBASE_ENABLE (1<<11)
|
---|
253 | #define MSR_IA32_APICBASE_BASE (0xfffff<<12)
|
---|
254 |
|
---|
255 | #ifndef MSR_IA32_SYSENTER_CS /* VBox x86.h klugde */
|
---|
256 | #define MSR_IA32_SYSENTER_CS 0x174
|
---|
257 | #define MSR_IA32_SYSENTER_ESP 0x175
|
---|
258 | #define MSR_IA32_SYSENTER_EIP 0x176
|
---|
259 | #endif
|
---|
260 |
|
---|
261 | #define MSR_IA32_SYSENTER_CS 0x174
|
---|
262 | #define MSR_IA32_SYSENTER_ESP 0x175
|
---|
263 | #define MSR_IA32_SYSENTER_EIP 0x176
|
---|
264 |
|
---|
265 | #define MSR_MCG_CAP 0x179
|
---|
266 | #define MSR_MCG_STATUS 0x17a
|
---|
267 | #define MSR_MCG_CTL 0x17b
|
---|
268 |
|
---|
269 | #define MSR_IA32_PERF_STATUS 0x198
|
---|
270 |
|
---|
271 | #define MSR_PAT 0x277
|
---|
272 |
|
---|
273 | #define MSR_EFER 0xc0000080
|
---|
274 |
|
---|
275 | #define MSR_EFER_SCE (1 << 0)
|
---|
276 | #define MSR_EFER_LME (1 << 8)
|
---|
277 | #define MSR_EFER_LMA (1 << 10)
|
---|
278 | #define MSR_EFER_NXE (1 << 11)
|
---|
279 | #define MSR_EFER_SVME (1 << 12)
|
---|
280 | #define MSR_EFER_FFXSR (1 << 14)
|
---|
281 |
|
---|
282 | #ifdef VBOX
|
---|
283 | #define MSR_APIC_RANGE_START 0x800
|
---|
284 | #define MSR_APIC_RANGE_END 0x900
|
---|
285 | #endif
|
---|
286 |
|
---|
287 | #define MSR_STAR 0xc0000081
|
---|
288 | #define MSR_LSTAR 0xc0000082
|
---|
289 | #define MSR_CSTAR 0xc0000083
|
---|
290 | #define MSR_FMASK 0xc0000084
|
---|
291 | #define MSR_FSBASE 0xc0000100
|
---|
292 | #define MSR_GSBASE 0xc0000101
|
---|
293 | #define MSR_KERNELGSBASE 0xc0000102
|
---|
294 |
|
---|
295 | #define MSR_VM_HSAVE_PA 0xc0010117
|
---|
296 |
|
---|
297 | /* cpuid_features bits */
|
---|
298 | #define CPUID_FP87 (1 << 0)
|
---|
299 | #define CPUID_VME (1 << 1)
|
---|
300 | #define CPUID_DE (1 << 2)
|
---|
301 | #define CPUID_PSE (1 << 3)
|
---|
302 | #define CPUID_TSC (1 << 4)
|
---|
303 | #define CPUID_MSR (1 << 5)
|
---|
304 | #define CPUID_PAE (1 << 6)
|
---|
305 | #define CPUID_MCE (1 << 7)
|
---|
306 | #define CPUID_CX8 (1 << 8)
|
---|
307 | #define CPUID_APIC (1 << 9)
|
---|
308 | #define CPUID_SEP (1 << 11) /* sysenter/sysexit */
|
---|
309 | #define CPUID_MTRR (1 << 12)
|
---|
310 | #define CPUID_PGE (1 << 13)
|
---|
311 | #define CPUID_MCA (1 << 14)
|
---|
312 | #define CPUID_CMOV (1 << 15)
|
---|
313 | #define CPUID_PAT (1 << 16)
|
---|
314 | #define CPUID_PSE36 (1 << 17)
|
---|
315 | #define CPUID_CLFLUSH (1 << 19)
|
---|
316 | #define CPUID_DTS (1 << 21)
|
---|
317 | #define CPUID_ACPI (1 << 22)
|
---|
318 | #define CPUID_MMX (1 << 23)
|
---|
319 | #define CPUID_FXSR (1 << 24)
|
---|
320 | #define CPUID_SSE (1 << 25)
|
---|
321 | #define CPUID_SSE2 (1 << 26)
|
---|
322 | #define CPUID_SS (1 << 27)
|
---|
323 | #define CPUID_HT (1 << 28)
|
---|
324 | #define CPUID_TM (1 << 29)
|
---|
325 | #define CPUID_IA64 (1 << 30)
|
---|
326 | #define CPUID_PBE (1 << 31)
|
---|
327 |
|
---|
328 | #define CPUID_EXT_SSE3 (1 << 0)
|
---|
329 | #define CPUID_EXT_DTES64 (1 << 2)
|
---|
330 | #define CPUID_EXT_MONITOR (1 << 3)
|
---|
331 | #define CPUID_EXT_DSCPL (1 << 4)
|
---|
332 | #define CPUID_EXT_VMX (1 << 5)
|
---|
333 | #define CPUID_EXT_SMX (1 << 6)
|
---|
334 | #define CPUID_EXT_EST (1 << 7)
|
---|
335 | #define CPUID_EXT_TM2 (1 << 8)
|
---|
336 | #define CPUID_EXT_SSSE3 (1 << 9)
|
---|
337 | #define CPUID_EXT_CID (1 << 10)
|
---|
338 | #define CPUID_EXT_CX16 (1 << 13)
|
---|
339 | #define CPUID_EXT_XTPR (1 << 14)
|
---|
340 | #define CPUID_EXT_PDCM (1 << 15)
|
---|
341 | #define CPUID_EXT_DCA (1 << 18)
|
---|
342 | #define CPUID_EXT_SSE41 (1 << 19)
|
---|
343 | #define CPUID_EXT_SSE42 (1 << 20)
|
---|
344 | #define CPUID_EXT_X2APIC (1 << 21)
|
---|
345 | #define CPUID_EXT_MOVBE (1 << 22)
|
---|
346 | #define CPUID_EXT_POPCNT (1 << 23)
|
---|
347 | #define CPUID_EXT_XSAVE (1 << 26)
|
---|
348 | #define CPUID_EXT_OSXSAVE (1 << 27)
|
---|
349 |
|
---|
350 | #define CPUID_EXT2_SYSCALL (1 << 11)
|
---|
351 | #define CPUID_EXT2_MP (1 << 19)
|
---|
352 | #define CPUID_EXT2_NX (1 << 20)
|
---|
353 | #define CPUID_EXT2_MMXEXT (1 << 22)
|
---|
354 | #define CPUID_EXT2_FFXSR (1 << 25)
|
---|
355 | #define CPUID_EXT2_PDPE1GB (1 << 26)
|
---|
356 | #define CPUID_EXT2_RDTSCP (1 << 27)
|
---|
357 | #define CPUID_EXT2_LM (1 << 29)
|
---|
358 | #define CPUID_EXT2_3DNOWEXT (1 << 30)
|
---|
359 | #define CPUID_EXT2_3DNOW (1 << 31)
|
---|
360 |
|
---|
361 | #define CPUID_EXT3_LAHF_LM (1 << 0)
|
---|
362 | #define CPUID_EXT3_CMP_LEG (1 << 1)
|
---|
363 | #define CPUID_EXT3_SVM (1 << 2)
|
---|
364 | #define CPUID_EXT3_EXTAPIC (1 << 3)
|
---|
365 | #define CPUID_EXT3_CR8LEG (1 << 4)
|
---|
366 | #define CPUID_EXT3_ABM (1 << 5)
|
---|
367 | #define CPUID_EXT3_SSE4A (1 << 6)
|
---|
368 | #define CPUID_EXT3_MISALIGNSSE (1 << 7)
|
---|
369 | #define CPUID_EXT3_3DNOWPREFETCH (1 << 8)
|
---|
370 | #define CPUID_EXT3_OSVW (1 << 9)
|
---|
371 | #define CPUID_EXT3_IBS (1 << 10)
|
---|
372 | #define CPUID_EXT3_SKINIT (1 << 12)
|
---|
373 |
|
---|
374 | #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
|
---|
375 | #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
|
---|
376 | #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
|
---|
377 |
|
---|
378 | #define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */
|
---|
379 | #define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */
|
---|
380 | #define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */
|
---|
381 |
|
---|
382 | #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */
|
---|
383 | #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */
|
---|
384 |
|
---|
385 | #define EXCP00_DIVZ 0
|
---|
386 | #define EXCP01_SSTP 1
|
---|
387 | #define EXCP02_NMI 2
|
---|
388 | #define EXCP03_INT3 3
|
---|
389 | #define EXCP04_INTO 4
|
---|
390 | #define EXCP05_BOUND 5
|
---|
391 | #define EXCP06_ILLOP 6
|
---|
392 | #define EXCP07_PREX 7
|
---|
393 | #define EXCP08_DBLE 8
|
---|
394 | #define EXCP09_XERR 9
|
---|
395 | #define EXCP0A_TSS 10
|
---|
396 | #define EXCP0B_NOSEG 11
|
---|
397 | #define EXCP0C_STACK 12
|
---|
398 | #define EXCP0D_GPF 13
|
---|
399 | #define EXCP0E_PAGE 14
|
---|
400 | #define EXCP10_COPR 16
|
---|
401 | #define EXCP11_ALGN 17
|
---|
402 | #define EXCP12_MCHK 18
|
---|
403 |
|
---|
404 | #define EXCP_SYSCALL 0x100 /* only happens in user only emulation
|
---|
405 | for syscall instruction */
|
---|
406 |
|
---|
407 | enum {
|
---|
408 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
|
---|
409 | CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
|
---|
410 |
|
---|
411 | CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */
|
---|
412 | CC_OP_MULW,
|
---|
413 | CC_OP_MULL,
|
---|
414 | CC_OP_MULQ,
|
---|
415 |
|
---|
416 | CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
417 | CC_OP_ADDW,
|
---|
418 | CC_OP_ADDL,
|
---|
419 | CC_OP_ADDQ,
|
---|
420 |
|
---|
421 | CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
422 | CC_OP_ADCW,
|
---|
423 | CC_OP_ADCL,
|
---|
424 | CC_OP_ADCQ,
|
---|
425 |
|
---|
426 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
427 | CC_OP_SUBW,
|
---|
428 | CC_OP_SUBL,
|
---|
429 | CC_OP_SUBQ,
|
---|
430 |
|
---|
431 | CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
|
---|
432 | CC_OP_SBBW,
|
---|
433 | CC_OP_SBBL,
|
---|
434 | CC_OP_SBBQ,
|
---|
435 |
|
---|
436 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */
|
---|
437 | CC_OP_LOGICW,
|
---|
438 | CC_OP_LOGICL,
|
---|
439 | CC_OP_LOGICQ,
|
---|
440 |
|
---|
441 | CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
---|
442 | CC_OP_INCW,
|
---|
443 | CC_OP_INCL,
|
---|
444 | CC_OP_INCQ,
|
---|
445 |
|
---|
446 | CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */
|
---|
447 | CC_OP_DECW,
|
---|
448 | CC_OP_DECL,
|
---|
449 | CC_OP_DECQ,
|
---|
450 |
|
---|
451 | CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.msb = C */
|
---|
452 | CC_OP_SHLW,
|
---|
453 | CC_OP_SHLL,
|
---|
454 | CC_OP_SHLQ,
|
---|
455 |
|
---|
456 | CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
|
---|
457 | CC_OP_SARW,
|
---|
458 | CC_OP_SARL,
|
---|
459 | CC_OP_SARQ,
|
---|
460 |
|
---|
461 | CC_OP_NB
|
---|
462 | };
|
---|
463 |
|
---|
464 | #ifdef FLOATX80
|
---|
465 | #define USE_X86LDOUBLE
|
---|
466 | #endif
|
---|
467 |
|
---|
468 | #ifdef USE_X86LDOUBLE
|
---|
469 | typedef floatx80 CPU86_LDouble;
|
---|
470 | #else
|
---|
471 | typedef float64 CPU86_LDouble;
|
---|
472 | #endif
|
---|
473 |
|
---|
474 | typedef struct SegmentCache {
|
---|
475 | uint32_t selector;
|
---|
476 | target_ulong base;
|
---|
477 | uint32_t limit;
|
---|
478 | uint32_t flags;
|
---|
479 | #ifdef VBOX
|
---|
480 | /** The new selector is saved here when we are unable to sync it before invoking the recompiled code. */
|
---|
481 | uint32_t newselector;
|
---|
482 | #endif
|
---|
483 | } SegmentCache;
|
---|
484 |
|
---|
485 | typedef union {
|
---|
486 | uint8_t _b[16];
|
---|
487 | uint16_t _w[8];
|
---|
488 | uint32_t _l[4];
|
---|
489 | uint64_t _q[2];
|
---|
490 | float32 _s[4];
|
---|
491 | float64 _d[2];
|
---|
492 | } XMMReg;
|
---|
493 |
|
---|
494 | typedef union {
|
---|
495 | uint8_t _b[8];
|
---|
496 | uint16_t _w[2];
|
---|
497 | uint32_t _l[1];
|
---|
498 | float32 _s[2];
|
---|
499 | uint64_t q;
|
---|
500 | } MMXReg;
|
---|
501 |
|
---|
502 | #ifdef WORDS_BIGENDIAN
|
---|
503 | #define XMM_B(n) _b[15 - (n)]
|
---|
504 | #define XMM_W(n) _w[7 - (n)]
|
---|
505 | #define XMM_L(n) _l[3 - (n)]
|
---|
506 | #define XMM_S(n) _s[3 - (n)]
|
---|
507 | #define XMM_Q(n) _q[1 - (n)]
|
---|
508 | #define XMM_D(n) _d[1 - (n)]
|
---|
509 |
|
---|
510 | #define MMX_B(n) _b[7 - (n)]
|
---|
511 | #define MMX_W(n) _w[3 - (n)]
|
---|
512 | #define MMX_L(n) _l[1 - (n)]
|
---|
513 | #define MMX_S(n) _s[1 - (n)]
|
---|
514 | #else
|
---|
515 | #define XMM_B(n) _b[n]
|
---|
516 | #define XMM_W(n) _w[n]
|
---|
517 | #define XMM_L(n) _l[n]
|
---|
518 | #define XMM_S(n) _s[n]
|
---|
519 | #define XMM_Q(n) _q[n]
|
---|
520 | #define XMM_D(n) _d[n]
|
---|
521 |
|
---|
522 | #define MMX_B(n) _b[n]
|
---|
523 | #define MMX_W(n) _w[n]
|
---|
524 | #define MMX_L(n) _l[n]
|
---|
525 | #define MMX_S(n) _s[n]
|
---|
526 | #endif
|
---|
527 | #define MMX_Q(n) q
|
---|
528 |
|
---|
529 | #ifdef TARGET_X86_64
|
---|
530 | #define CPU_NB_REGS 16
|
---|
531 | #else
|
---|
532 | #define CPU_NB_REGS 8
|
---|
533 | #endif
|
---|
534 |
|
---|
535 | #define NB_MMU_MODES 2
|
---|
536 |
|
---|
537 | typedef struct CPUX86State {
|
---|
538 | /* standard registers */
|
---|
539 | target_ulong regs[CPU_NB_REGS];
|
---|
540 | target_ulong eip;
|
---|
541 | target_ulong eflags; /* eflags register. During CPU emulation, CC
|
---|
542 | flags and DF are set to zero because they are
|
---|
543 | stored elsewhere */
|
---|
544 |
|
---|
545 | /* emulator internal eflags handling */
|
---|
546 | target_ulong cc_src;
|
---|
547 | target_ulong cc_dst;
|
---|
548 | uint32_t cc_op;
|
---|
549 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
|
---|
550 | uint32_t hflags; /* TB flags, see HF_xxx constants. These flags
|
---|
551 | are known at translation time. */
|
---|
552 | uint32_t hflags2; /* various other flags, see HF2_xxx constants. */
|
---|
553 |
|
---|
554 | /* segments */
|
---|
555 | SegmentCache segs[6]; /* selector values */
|
---|
556 | SegmentCache ldt;
|
---|
557 | SegmentCache tr;
|
---|
558 | SegmentCache gdt; /* only base and limit are used */
|
---|
559 | SegmentCache idt; /* only base and limit are used */
|
---|
560 |
|
---|
561 | target_ulong cr[5]; /* NOTE: cr1 is unused */
|
---|
562 | uint64_t a20_mask;
|
---|
563 |
|
---|
564 | /* FPU state */
|
---|
565 | unsigned int fpstt; /* top of stack index */
|
---|
566 | unsigned int fpus;
|
---|
567 | unsigned int fpuc;
|
---|
568 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */
|
---|
569 | union {
|
---|
570 | #ifdef USE_X86LDOUBLE
|
---|
571 | #ifndef VBOX
|
---|
572 | CPU86_LDouble d __attribute__((aligned(16)));
|
---|
573 | #else
|
---|
574 | ALIGNED_MEMBER(CPU86_LDouble, d, 16);
|
---|
575 | #endif
|
---|
576 | #else
|
---|
577 | CPU86_LDouble d;
|
---|
578 | #endif
|
---|
579 | MMXReg mmx;
|
---|
580 | } fpregs[8];
|
---|
581 |
|
---|
582 | /* emulator internal variables */
|
---|
583 | float_status fp_status;
|
---|
584 | #ifdef VBOX
|
---|
585 | uint32_t alignment3[3]; /* force the long double to start a 16 byte line. */
|
---|
586 | #endif
|
---|
587 | CPU86_LDouble ft0;
|
---|
588 | #if defined(VBOX) && defined(RT_ARCH_X86) && !defined(RT_OS_DARWIN)
|
---|
589 | uint32_t alignment4; /* long double is 12 byte, pad it to 16. */
|
---|
590 | #endif
|
---|
591 |
|
---|
592 | float_status mmx_status; /* for 3DNow! float ops */
|
---|
593 | float_status sse_status;
|
---|
594 | uint32_t mxcsr;
|
---|
595 | XMMReg xmm_regs[CPU_NB_REGS];
|
---|
596 | XMMReg xmm_t0;
|
---|
597 | MMXReg mmx_t0;
|
---|
598 | target_ulong cc_tmp; /* temporary for rcr/rcl */
|
---|
599 |
|
---|
600 | /* sysenter registers */
|
---|
601 | uint32_t sysenter_cs;
|
---|
602 | uint64_t sysenter_esp;
|
---|
603 | uint64_t sysenter_eip;
|
---|
604 | #ifdef VBOX
|
---|
605 | uint32_t alignment0;
|
---|
606 | #endif
|
---|
607 | uint64_t efer;
|
---|
608 | uint64_t star;
|
---|
609 |
|
---|
610 | uint64_t vm_hsave;
|
---|
611 | uint64_t vm_vmcb;
|
---|
612 | uint64_t tsc_offset;
|
---|
613 | uint64_t intercept;
|
---|
614 | uint16_t intercept_cr_read;
|
---|
615 | uint16_t intercept_cr_write;
|
---|
616 | uint16_t intercept_dr_read;
|
---|
617 | uint16_t intercept_dr_write;
|
---|
618 | uint32_t intercept_exceptions;
|
---|
619 | uint8_t v_tpr;
|
---|
620 |
|
---|
621 | #ifdef TARGET_X86_64
|
---|
622 | target_ulong lstar;
|
---|
623 | target_ulong cstar;
|
---|
624 | target_ulong fmask;
|
---|
625 | target_ulong kernelgsbase;
|
---|
626 | #endif
|
---|
627 |
|
---|
628 | uint64_t pat;
|
---|
629 |
|
---|
630 | /* exception/interrupt handling */
|
---|
631 | int error_code;
|
---|
632 | int exception_is_int;
|
---|
633 | target_ulong exception_next_eip;
|
---|
634 | target_ulong dr[8]; /* debug registers */
|
---|
635 | uint32_t smbase;
|
---|
636 | int old_exception; /* exception in flight */
|
---|
637 |
|
---|
638 | CPU_COMMON
|
---|
639 |
|
---|
640 | #ifdef VBOX
|
---|
641 | /** cpu state flags. (see defines below) */
|
---|
642 | uint32_t state;
|
---|
643 | /** The VM handle. */
|
---|
644 | PVM pVM;
|
---|
645 | /** code buffer for instruction emulation */
|
---|
646 | void *pvCodeBuffer;
|
---|
647 | /** code buffer size */
|
---|
648 | uint32_t cbCodeBuffer;
|
---|
649 | #endif /* VBOX */
|
---|
650 |
|
---|
651 | /* processor features (e.g. for CPUID insn) */
|
---|
652 | #ifndef VBOX /* remR3CpuId deals with these */
|
---|
653 | uint32_t cpuid_level;
|
---|
654 | uint32_t cpuid_vendor1;
|
---|
655 | uint32_t cpuid_vendor2;
|
---|
656 | uint32_t cpuid_vendor3;
|
---|
657 | uint32_t cpuid_version;
|
---|
658 | #endif /* !VBOX */
|
---|
659 | uint32_t cpuid_features;
|
---|
660 | uint32_t cpuid_ext_features;
|
---|
661 | #ifndef VBOX
|
---|
662 | uint32_t cpuid_xlevel;
|
---|
663 | uint32_t cpuid_model[12];
|
---|
664 | #endif /* !VBOX */
|
---|
665 | uint32_t cpuid_ext2_features;
|
---|
666 | uint32_t cpuid_ext3_features;
|
---|
667 | uint32_t cpuid_apic_id;
|
---|
668 |
|
---|
669 | #ifndef VBOX
|
---|
670 | #ifdef USE_KQEMU
|
---|
671 | int kqemu_enabled;
|
---|
672 | int last_io_time;
|
---|
673 | #endif
|
---|
674 | /* in order to simplify APIC support, we leave this pointer to the
|
---|
675 | user */
|
---|
676 | struct APICState *apic_state;
|
---|
677 | #else
|
---|
678 | uint32_t alignment2[3];
|
---|
679 | #endif
|
---|
680 | } CPUX86State;
|
---|
681 |
|
---|
682 | #ifdef VBOX
|
---|
683 |
|
---|
684 | /* Version 1.6 structure; just for loading the old saved state */
|
---|
685 | typedef struct SegmentCache_Ver16 {
|
---|
686 | uint32_t selector;
|
---|
687 | uint32_t base;
|
---|
688 | uint32_t limit;
|
---|
689 | uint32_t flags;
|
---|
690 | /** The new selector is saved here when we are unable to sync it before invoking the recompiled code. */
|
---|
691 | uint32_t newselector;
|
---|
692 | } SegmentCache_Ver16;
|
---|
693 |
|
---|
694 | #define CPU_NB_REGS_VER16 8
|
---|
695 |
|
---|
696 | /* Version 1.6 structure; just for loading the old saved state */
|
---|
697 | typedef struct CPUX86State_Ver16 {
|
---|
698 | #if TARGET_LONG_BITS > HOST_LONG_BITS
|
---|
699 | /* temporaries if we cannot store them in host registers */
|
---|
700 | uint32_t t0, t1, t2;
|
---|
701 | #endif
|
---|
702 |
|
---|
703 | /* standard registers */
|
---|
704 | uint32_t regs[CPU_NB_REGS_VER16];
|
---|
705 | uint32_t eip;
|
---|
706 | uint32_t eflags; /* eflags register. During CPU emulation, CC
|
---|
707 | flags and DF are set to zero because they are
|
---|
708 | stored elsewhere */
|
---|
709 |
|
---|
710 | /* emulator internal eflags handling */
|
---|
711 | uint32_t cc_src;
|
---|
712 | uint32_t cc_dst;
|
---|
713 | uint32_t cc_op;
|
---|
714 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
|
---|
715 | uint32_t hflags; /* hidden flags, see HF_xxx constants */
|
---|
716 |
|
---|
717 | /* segments */
|
---|
718 | SegmentCache_Ver16 segs[6]; /* selector values */
|
---|
719 | SegmentCache_Ver16 ldt;
|
---|
720 | SegmentCache_Ver16 tr;
|
---|
721 | SegmentCache_Ver16 gdt; /* only base and limit are used */
|
---|
722 | SegmentCache_Ver16 idt; /* only base and limit are used */
|
---|
723 |
|
---|
724 | uint32_t cr[5]; /* NOTE: cr1 is unused */
|
---|
725 | uint32_t a20_mask;
|
---|
726 |
|
---|
727 | /* FPU state */
|
---|
728 | unsigned int fpstt; /* top of stack index */
|
---|
729 | unsigned int fpus;
|
---|
730 | unsigned int fpuc;
|
---|
731 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */
|
---|
732 | union {
|
---|
733 | #ifdef USE_X86LDOUBLE
|
---|
734 | #ifndef VBOX
|
---|
735 | CPU86_LDouble d __attribute__((aligned(16)));
|
---|
736 | #else
|
---|
737 | ALIGNED_MEMBER(CPU86_LDouble, d, 16);
|
---|
738 | #endif
|
---|
739 | #else
|
---|
740 | CPU86_LDouble d;
|
---|
741 | #endif
|
---|
742 | MMXReg mmx;
|
---|
743 | } fpregs[8];
|
---|
744 |
|
---|
745 | /* emulator internal variables */
|
---|
746 | float_status fp_status;
|
---|
747 | #ifdef VBOX
|
---|
748 | uint32_t alignment3[3]; /* force the long double to start a 16 byte line. */
|
---|
749 | #endif
|
---|
750 | CPU86_LDouble ft0;
|
---|
751 | #if defined(VBOX) && defined(RT_ARCH_X86) && !defined(RT_OS_DARWIN)
|
---|
752 | uint32_t alignment4; /* long double is 12 byte, pad it to 16. */
|
---|
753 | #endif
|
---|
754 | union {
|
---|
755 | float f;
|
---|
756 | double d;
|
---|
757 | int i32;
|
---|
758 | int64_t i64;
|
---|
759 | } fp_convert;
|
---|
760 |
|
---|
761 | float_status sse_status;
|
---|
762 | uint32_t mxcsr;
|
---|
763 | XMMReg xmm_regs[CPU_NB_REGS_VER16];
|
---|
764 | XMMReg xmm_t0;
|
---|
765 | MMXReg mmx_t0;
|
---|
766 |
|
---|
767 | /* sysenter registers */
|
---|
768 | uint32_t sysenter_cs;
|
---|
769 | uint32_t sysenter_esp;
|
---|
770 | uint32_t sysenter_eip;
|
---|
771 | #ifdef VBOX
|
---|
772 | uint32_t alignment0;
|
---|
773 | #endif
|
---|
774 | uint64_t efer;
|
---|
775 | uint64_t star;
|
---|
776 |
|
---|
777 | uint64_t pat;
|
---|
778 |
|
---|
779 | /* temporary data for USE_CODE_COPY mode */
|
---|
780 | #ifdef USE_CODE_COPY
|
---|
781 | uint32_t tmp0;
|
---|
782 | uint32_t saved_esp;
|
---|
783 | int native_fp_regs; /* if true, the FPU state is in the native CPU regs */
|
---|
784 | #endif
|
---|
785 |
|
---|
786 | /* exception/interrupt handling */
|
---|
787 | jmp_buf jmp_env;
|
---|
788 | } CPUX86State_Ver16;
|
---|
789 |
|
---|
790 | /** CPUX86State state flags
|
---|
791 | * @{ */
|
---|
792 | #define CPU_RAW_RING0 0x0002 /* Set after first time RawR0 is executed, never cleared. */
|
---|
793 | #define CPU_EMULATE_SINGLE_INSTR 0x0040 /* Execute a single instruction in emulation mode */
|
---|
794 | #define CPU_EMULATE_SINGLE_STEP 0x0080 /* go into single step mode */
|
---|
795 | #define CPU_RAW_HWACC 0x0100 /* Set after first time HWACC is executed, never cleared. */
|
---|
796 | /** @} */
|
---|
797 | #endif /* !VBOX */
|
---|
798 |
|
---|
799 | #ifdef VBOX
|
---|
800 | CPUX86State *cpu_x86_init(CPUX86State *env, const char *cpu_model);
|
---|
801 | #else /* !VBOX */
|
---|
802 | CPUX86State *cpu_x86_init(const char *cpu_model);
|
---|
803 | #endif /* !VBOX */
|
---|
804 | int cpu_x86_exec(CPUX86State *s);
|
---|
805 | void cpu_x86_close(CPUX86State *s);
|
---|
806 | void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
|
---|
807 | ...));
|
---|
808 | int cpu_get_pic_interrupt(CPUX86State *s);
|
---|
809 | /* MSDOS compatibility mode FPU exception support */
|
---|
810 | void cpu_set_ferr(CPUX86State *s);
|
---|
811 |
|
---|
812 | /* this function must always be used to load data in the segment
|
---|
813 | cache: it synchronizes the hflags with the segment cache values */
|
---|
814 | #ifndef VBOX
|
---|
815 | static inline void cpu_x86_load_seg_cache(CPUX86State *env,
|
---|
816 | int seg_reg, unsigned int selector,
|
---|
817 | target_ulong base,
|
---|
818 | unsigned int limit,
|
---|
819 | unsigned int flags)
|
---|
820 | #else
|
---|
821 | DECLINLINE(void) cpu_x86_load_seg_cache(CPUX86State *env,
|
---|
822 | int seg_reg, unsigned int selector,
|
---|
823 | target_ulong base,
|
---|
824 | unsigned int limit,
|
---|
825 | unsigned int flags)
|
---|
826 |
|
---|
827 | #endif
|
---|
828 | {
|
---|
829 | SegmentCache *sc;
|
---|
830 | unsigned int new_hflags;
|
---|
831 |
|
---|
832 | sc = &env->segs[seg_reg];
|
---|
833 | sc->selector = selector;
|
---|
834 | sc->base = base;
|
---|
835 | sc->limit = limit;
|
---|
836 | sc->flags = flags;
|
---|
837 | #ifdef VBOX
|
---|
838 | sc->newselector = 0;
|
---|
839 | #endif
|
---|
840 |
|
---|
841 | /* update the hidden flags */
|
---|
842 | {
|
---|
843 | if (seg_reg == R_CS) {
|
---|
844 | #ifdef TARGET_X86_64
|
---|
845 | if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) {
|
---|
846 | /* long mode */
|
---|
847 | env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
|
---|
848 | env->hflags &= ~(HF_ADDSEG_MASK);
|
---|
849 | } else
|
---|
850 | #endif
|
---|
851 | {
|
---|
852 | /* legacy / compatibility case */
|
---|
853 | new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
|
---|
854 | >> (DESC_B_SHIFT - HF_CS32_SHIFT);
|
---|
855 | env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) |
|
---|
856 | new_hflags;
|
---|
857 | }
|
---|
858 | }
|
---|
859 | new_hflags = (env->segs[R_SS].flags & DESC_B_MASK)
|
---|
860 | >> (DESC_B_SHIFT - HF_SS32_SHIFT);
|
---|
861 | if (env->hflags & HF_CS64_MASK) {
|
---|
862 | /* zero base assumed for DS, ES and SS in long mode */
|
---|
863 | } else if (!(env->cr[0] & CR0_PE_MASK) ||
|
---|
864 | (env->eflags & VM_MASK) ||
|
---|
865 | !(env->hflags & HF_CS32_MASK)) {
|
---|
866 | /* XXX: try to avoid this test. The problem comes from the
|
---|
867 | fact that is real mode or vm86 mode we only modify the
|
---|
868 | 'base' and 'selector' fields of the segment cache to go
|
---|
869 | faster. A solution may be to force addseg to one in
|
---|
870 | translate-i386.c. */
|
---|
871 | new_hflags |= HF_ADDSEG_MASK;
|
---|
872 | } else {
|
---|
873 | new_hflags |= ((env->segs[R_DS].base |
|
---|
874 | env->segs[R_ES].base |
|
---|
875 | env->segs[R_SS].base) != 0) <<
|
---|
876 | HF_ADDSEG_SHIFT;
|
---|
877 | }
|
---|
878 | env->hflags = (env->hflags &
|
---|
879 | ~(HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags;
|
---|
880 | }
|
---|
881 | }
|
---|
882 |
|
---|
883 | /* wrapper, just in case memory mappings must be changed */
|
---|
884 | #ifndef VBOX
|
---|
885 | static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
|
---|
886 | #else
|
---|
887 | DECLINLINE(void) cpu_x86_set_cpl(CPUX86State *s, int cpl)
|
---|
888 | #endif
|
---|
889 | {
|
---|
890 | #if HF_CPL_MASK == 3
|
---|
891 | s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl;
|
---|
892 | #else
|
---|
893 | #error HF_CPL_MASK is hardcoded
|
---|
894 | #endif
|
---|
895 | }
|
---|
896 |
|
---|
897 | /* used for debug or cpu save/restore */
|
---|
898 | void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, CPU86_LDouble f);
|
---|
899 | CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper);
|
---|
900 |
|
---|
901 | /* the following helpers are only usable in user mode simulation as
|
---|
902 | they can trigger unexpected exceptions */
|
---|
903 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
|
---|
904 | void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
|
---|
905 | void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
|
---|
906 |
|
---|
907 | /* you can call this signal handler from your SIGBUS and SIGSEGV
|
---|
908 | signal handlers to inform the virtual CPU of exceptions. non zero
|
---|
909 | is returned if the signal was handled by the virtual CPU. */
|
---|
910 | int cpu_x86_signal_handler(int host_signum, void *pinfo,
|
---|
911 | void *puc);
|
---|
912 | void cpu_x86_set_a20(CPUX86State *env, int a20_state);
|
---|
913 |
|
---|
914 | uint64_t cpu_get_tsc(CPUX86State *env);
|
---|
915 |
|
---|
916 | void cpu_set_apic_base(CPUX86State *env, uint64_t val);
|
---|
917 | uint64_t cpu_get_apic_base(CPUX86State *env);
|
---|
918 | void cpu_set_apic_tpr(CPUX86State *env, uint8_t val);
|
---|
919 | #ifndef NO_CPU_IO_DEFS
|
---|
920 | uint8_t cpu_get_apic_tpr(CPUX86State *env);
|
---|
921 | #endif
|
---|
922 | #ifdef VBOX
|
---|
923 | uint64_t cpu_apic_rdmsr(CPUX86State *env, uint32_t reg);
|
---|
924 | void cpu_apic_wrmsr(CPUX86State *env, uint32_t reg, uint64_t value);
|
---|
925 | uint64_t cpu_rdmsr(CPUX86State *env, uint32_t msr);
|
---|
926 | void cpu_wrmsr(CPUX86State *env, uint32_t msr, uint64_t val);
|
---|
927 | #endif
|
---|
928 | void cpu_smm_update(CPUX86State *env);
|
---|
929 |
|
---|
930 | /* will be suppressed */
|
---|
931 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0);
|
---|
932 |
|
---|
933 | /* used to debug */
|
---|
934 | #define X86_DUMP_FPU 0x0001 /* dump FPU state too */
|
---|
935 | #define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
|
---|
936 |
|
---|
937 | #ifdef USE_KQEMU
|
---|
938 | static inline int cpu_get_time_fast(void)
|
---|
939 | {
|
---|
940 | int low, high;
|
---|
941 | asm volatile("rdtsc" : "=a" (low), "=d" (high));
|
---|
942 | return low;
|
---|
943 | }
|
---|
944 | #endif
|
---|
945 |
|
---|
946 | #ifdef VBOX
|
---|
947 | void cpu_trap_raw(CPUX86State *env1);
|
---|
948 |
|
---|
949 | /* in helper.c */
|
---|
950 | uint8_t read_byte(CPUX86State *env1, target_ulong addr);
|
---|
951 | uint16_t read_word(CPUX86State *env1, target_ulong addr);
|
---|
952 | void write_byte(CPUX86State *env1, target_ulong addr, uint8_t val);
|
---|
953 | uint32_t read_dword(CPUX86State *env1, target_ulong addr);
|
---|
954 | void write_word(CPUX86State *env1, target_ulong addr, uint16_t val);
|
---|
955 | void write_dword(CPUX86State *env1, target_ulong addr, uint32_t val);
|
---|
956 | /* in helper.c */
|
---|
957 | int emulate_single_instr(CPUX86State *env1);
|
---|
958 | int get_ss_esp_from_tss_raw(CPUX86State *env1, uint32_t *ss_ptr, uint32_t *esp_ptr, int dpl);
|
---|
959 |
|
---|
960 | void restore_raw_fp_state(CPUX86State *env, uint8_t *ptr);
|
---|
961 | void save_raw_fp_state(CPUX86State *env, uint8_t *ptr);
|
---|
962 |
|
---|
963 | #endif
|
---|
964 |
|
---|
965 | #define TARGET_PAGE_BITS 12
|
---|
966 |
|
---|
967 | #define CPUState CPUX86State
|
---|
968 | #define cpu_init cpu_x86_init
|
---|
969 | #define cpu_exec cpu_x86_exec
|
---|
970 | #define cpu_gen_code cpu_x86_gen_code
|
---|
971 | #define cpu_signal_handler cpu_x86_signal_handler
|
---|
972 | #define cpu_list x86_cpu_list
|
---|
973 |
|
---|
974 | #define CPU_SAVE_VERSION 7
|
---|
975 |
|
---|
976 | /* MMU modes definitions */
|
---|
977 | #define MMU_MODE0_SUFFIX _kernel
|
---|
978 | #define MMU_MODE1_SUFFIX _user
|
---|
979 | #define MMU_USER_IDX 1
|
---|
980 | #ifndef VBOX
|
---|
981 | static inline int cpu_mmu_index (CPUState *env)
|
---|
982 | #else
|
---|
983 | DECLINLINE(int) cpu_mmu_index (CPUState *env)
|
---|
984 | #endif
|
---|
985 | {
|
---|
986 | return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
|
---|
987 | }
|
---|
988 |
|
---|
989 | void optimize_flags_init(void);
|
---|
990 |
|
---|
991 | typedef struct CCTable {
|
---|
992 | int (*compute_all)(void); /* return all the flags */
|
---|
993 | int (*compute_c)(void); /* return the C flag */
|
---|
994 | } CCTable;
|
---|
995 |
|
---|
996 | extern CCTable cc_table[];
|
---|
997 |
|
---|
998 | #if defined(CONFIG_USER_ONLY)
|
---|
999 | static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
|
---|
1000 | {
|
---|
1001 | if (newsp)
|
---|
1002 | env->regs[R_ESP] = newsp;
|
---|
1003 | env->regs[R_EAX] = 0;
|
---|
1004 | }
|
---|
1005 | #endif
|
---|
1006 |
|
---|
1007 | #define CPU_PC_FROM_TB(env, tb) env->eip = tb->pc - tb->cs_base
|
---|
1008 |
|
---|
1009 | #include "cpu-all.h"
|
---|
1010 |
|
---|
1011 | #include "svm.h"
|
---|
1012 |
|
---|
1013 | #endif /* CPU_I386_H */
|
---|