Commit d3eead2eec2f74fded2bed2cb8c21fd8404aeeb9
1 parent
853d6f7a
new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@390 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
0 additions
and
3834 deletions
Too many changes to show.
To preserve performance only 9 of 20 files are displayed.
cpu-arm.h deleted
100644 → 0
1 | -/* | ||
2 | - * ARM 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_ARM_H | ||
21 | -#define CPU_ARM_H | ||
22 | - | ||
23 | -#include "cpu-defs.h" | ||
24 | - | ||
25 | -#define EXCP_UDEF 1 /* undefined instruction */ | ||
26 | -#define EXCP_SWI 2 /* software interrupt */ | ||
27 | - | ||
28 | -typedef struct CPUARMState { | ||
29 | - uint32_t regs[16]; | ||
30 | - uint32_t cpsr; | ||
31 | - | ||
32 | - /* cpsr flag cache for faster execution */ | ||
33 | - uint32_t CF; /* 0 or 1 */ | ||
34 | - uint32_t VF; /* V is the bit 31. All other bits are undefined */ | ||
35 | - uint32_t NZF; /* N is bit 31. Z is computed from NZF */ | ||
36 | - | ||
37 | - /* exception/interrupt handling */ | ||
38 | - jmp_buf jmp_env; | ||
39 | - int exception_index; | ||
40 | - int interrupt_request; | ||
41 | - struct TranslationBlock *current_tb; | ||
42 | - int user_mode_only; | ||
43 | - | ||
44 | - /* user data */ | ||
45 | - void *opaque; | ||
46 | -} CPUARMState; | ||
47 | - | ||
48 | -CPUARMState *cpu_arm_init(void); | ||
49 | -int cpu_arm_exec(CPUARMState *s); | ||
50 | -void cpu_arm_close(CPUARMState *s); | ||
51 | -/* you can call this signal handler from your SIGBUS and SIGSEGV | ||
52 | - signal handlers to inform the virtual CPU of exceptions. non zero | ||
53 | - is returned if the signal was handled by the virtual CPU. */ | ||
54 | -struct siginfo; | ||
55 | -int cpu_arm_signal_handler(int host_signum, struct siginfo *info, | ||
56 | - void *puc); | ||
57 | - | ||
58 | -void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags); | ||
59 | - | ||
60 | -#define TARGET_PAGE_BITS 12 | ||
61 | -#include "cpu-all.h" | ||
62 | - | ||
63 | -#endif |
cpu-i386.h deleted
100644 → 0
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 "cpu-defs.h" | ||
24 | - | ||
25 | -#define R_EAX 0 | ||
26 | -#define R_ECX 1 | ||
27 | -#define R_EDX 2 | ||
28 | -#define R_EBX 3 | ||
29 | -#define R_ESP 4 | ||
30 | -#define R_EBP 5 | ||
31 | -#define R_ESI 6 | ||
32 | -#define R_EDI 7 | ||
33 | - | ||
34 | -#define R_AL 0 | ||
35 | -#define R_CL 1 | ||
36 | -#define R_DL 2 | ||
37 | -#define R_BL 3 | ||
38 | -#define R_AH 4 | ||
39 | -#define R_CH 5 | ||
40 | -#define R_DH 6 | ||
41 | -#define R_BH 7 | ||
42 | - | ||
43 | -#define R_ES 0 | ||
44 | -#define R_CS 1 | ||
45 | -#define R_SS 2 | ||
46 | -#define R_DS 3 | ||
47 | -#define R_FS 4 | ||
48 | -#define R_GS 5 | ||
49 | - | ||
50 | -/* segment descriptor fields */ | ||
51 | -#define DESC_G_MASK (1 << 23) | ||
52 | -#define DESC_B_SHIFT 22 | ||
53 | -#define DESC_B_MASK (1 << DESC_B_SHIFT) | ||
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) | ||
60 | - | ||
61 | -#define DESC_CS_MASK (1 << 11) | ||
62 | -#define DESC_C_MASK (1 << 10) | ||
63 | -#define DESC_R_MASK (1 << 9) | ||
64 | - | ||
65 | -#define DESC_E_MASK (1 << 10) | ||
66 | -#define DESC_W_MASK (1 << 9) | ||
67 | - | ||
68 | -/* eflags masks */ | ||
69 | -#define CC_C 0x0001 | ||
70 | -#define CC_P 0x0004 | ||
71 | -#define CC_A 0x0010 | ||
72 | -#define CC_Z 0x0040 | ||
73 | -#define CC_S 0x0080 | ||
74 | -#define CC_O 0x0800 | ||
75 | - | ||
76 | -#define TF_SHIFT 8 | ||
77 | -#define IOPL_SHIFT 12 | ||
78 | -#define VM_SHIFT 17 | ||
79 | - | ||
80 | -#define TF_MASK 0x00000100 | ||
81 | -#define IF_MASK 0x00000200 | ||
82 | -#define DF_MASK 0x00000400 | ||
83 | -#define IOPL_MASK 0x00003000 | ||
84 | -#define NT_MASK 0x00004000 | ||
85 | -#define RF_MASK 0x00010000 | ||
86 | -#define VM_MASK 0x00020000 | ||
87 | -#define AC_MASK 0x00040000 | ||
88 | -#define VIF_MASK 0x00080000 | ||
89 | -#define VIP_MASK 0x00100000 | ||
90 | -#define ID_MASK 0x00200000 | ||
91 | - | ||
92 | -/* hidden flags - used internally by qemu to represent additionnal cpu | ||
93 | - states. Only the CPL and INHIBIT_IRQ are not redundant. We avoid | ||
94 | - using the IOPL_MASK, TF_MASK and VM_MASK bit position to ease oring | ||
95 | - with eflags. */ | ||
96 | -/* current cpl */ | ||
97 | -#define HF_CPL_SHIFT 0 | ||
98 | -/* true if soft mmu is being used */ | ||
99 | -#define HF_SOFTMMU_SHIFT 2 | ||
100 | -/* true if hardware interrupts must be disabled for next instruction */ | ||
101 | -#define HF_INHIBIT_IRQ_SHIFT 3 | ||
102 | -/* 16 or 32 segments */ | ||
103 | -#define HF_CS32_SHIFT 4 | ||
104 | -#define HF_SS32_SHIFT 5 | ||
105 | -/* zero base for DS, ES and SS */ | ||
106 | -#define HF_ADDSEG_SHIFT 6 | ||
107 | - | ||
108 | -#define HF_CPL_MASK (3 << HF_CPL_SHIFT) | ||
109 | -#define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) | ||
110 | -#define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT) | ||
111 | -#define HF_CS32_MASK (1 << HF_CS32_SHIFT) | ||
112 | -#define HF_SS32_MASK (1 << HF_SS32_SHIFT) | ||
113 | -#define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT) | ||
114 | - | ||
115 | -#define CR0_PE_MASK (1 << 0) | ||
116 | -#define CR0_TS_MASK (1 << 3) | ||
117 | -#define CR0_WP_MASK (1 << 16) | ||
118 | -#define CR0_AM_MASK (1 << 18) | ||
119 | -#define CR0_PG_MASK (1 << 31) | ||
120 | - | ||
121 | -#define CR4_VME_MASK (1 << 0) | ||
122 | -#define CR4_PVI_MASK (1 << 1) | ||
123 | -#define CR4_TSD_MASK (1 << 2) | ||
124 | -#define CR4_DE_MASK (1 << 3) | ||
125 | -#define CR4_PSE_MASK (1 << 4) | ||
126 | - | ||
127 | -#define PG_PRESENT_BIT 0 | ||
128 | -#define PG_RW_BIT 1 | ||
129 | -#define PG_USER_BIT 2 | ||
130 | -#define PG_PWT_BIT 3 | ||
131 | -#define PG_PCD_BIT 4 | ||
132 | -#define PG_ACCESSED_BIT 5 | ||
133 | -#define PG_DIRTY_BIT 6 | ||
134 | -#define PG_PSE_BIT 7 | ||
135 | -#define PG_GLOBAL_BIT 8 | ||
136 | - | ||
137 | -#define PG_PRESENT_MASK (1 << PG_PRESENT_BIT) | ||
138 | -#define PG_RW_MASK (1 << PG_RW_BIT) | ||
139 | -#define PG_USER_MASK (1 << PG_USER_BIT) | ||
140 | -#define PG_PWT_MASK (1 << PG_PWT_BIT) | ||
141 | -#define PG_PCD_MASK (1 << PG_PCD_BIT) | ||
142 | -#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT) | ||
143 | -#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) | ||
144 | -#define PG_PSE_MASK (1 << PG_PSE_BIT) | ||
145 | -#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) | ||
146 | - | ||
147 | -#define PG_ERROR_W_BIT 1 | ||
148 | - | ||
149 | -#define PG_ERROR_P_MASK 0x01 | ||
150 | -#define PG_ERROR_W_MASK (1 << PG_ERROR_W_BIT) | ||
151 | -#define PG_ERROR_U_MASK 0x04 | ||
152 | -#define PG_ERROR_RSVD_MASK 0x08 | ||
153 | - | ||
154 | -#define MSR_IA32_APICBASE 0x1b | ||
155 | -#define MSR_IA32_APICBASE_BSP (1<<8) | ||
156 | -#define MSR_IA32_APICBASE_ENABLE (1<<11) | ||
157 | -#define MSR_IA32_APICBASE_BASE (0xfffff<<12) | ||
158 | - | ||
159 | -#define MSR_IA32_SYSENTER_CS 0x174 | ||
160 | -#define MSR_IA32_SYSENTER_ESP 0x175 | ||
161 | -#define MSR_IA32_SYSENTER_EIP 0x176 | ||
162 | - | ||
163 | -#define EXCP00_DIVZ 0 | ||
164 | -#define EXCP01_SSTP 1 | ||
165 | -#define EXCP02_NMI 2 | ||
166 | -#define EXCP03_INT3 3 | ||
167 | -#define EXCP04_INTO 4 | ||
168 | -#define EXCP05_BOUND 5 | ||
169 | -#define EXCP06_ILLOP 6 | ||
170 | -#define EXCP07_PREX 7 | ||
171 | -#define EXCP08_DBLE 8 | ||
172 | -#define EXCP09_XERR 9 | ||
173 | -#define EXCP0A_TSS 10 | ||
174 | -#define EXCP0B_NOSEG 11 | ||
175 | -#define EXCP0C_STACK 12 | ||
176 | -#define EXCP0D_GPF 13 | ||
177 | -#define EXCP0E_PAGE 14 | ||
178 | -#define EXCP10_COPR 16 | ||
179 | -#define EXCP11_ALGN 17 | ||
180 | -#define EXCP12_MCHK 18 | ||
181 | - | ||
182 | -enum { | ||
183 | - CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ | ||
184 | - CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ | ||
185 | - CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */ | ||
186 | - | ||
187 | - CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
188 | - CC_OP_ADDW, | ||
189 | - CC_OP_ADDL, | ||
190 | - | ||
191 | - CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
192 | - CC_OP_ADCW, | ||
193 | - CC_OP_ADCL, | ||
194 | - | ||
195 | - CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
196 | - CC_OP_SUBW, | ||
197 | - CC_OP_SUBL, | ||
198 | - | ||
199 | - CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ | ||
200 | - CC_OP_SBBW, | ||
201 | - CC_OP_SBBL, | ||
202 | - | ||
203 | - CC_OP_LOGICB, /* modify all flags, CC_DST = res */ | ||
204 | - CC_OP_LOGICW, | ||
205 | - CC_OP_LOGICL, | ||
206 | - | ||
207 | - CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */ | ||
208 | - CC_OP_INCW, | ||
209 | - CC_OP_INCL, | ||
210 | - | ||
211 | - CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */ | ||
212 | - CC_OP_DECW, | ||
213 | - CC_OP_DECL, | ||
214 | - | ||
215 | - CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ | ||
216 | - CC_OP_SHLW, | ||
217 | - CC_OP_SHLL, | ||
218 | - | ||
219 | - CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ | ||
220 | - CC_OP_SARW, | ||
221 | - CC_OP_SARL, | ||
222 | - | ||
223 | - CC_OP_NB, | ||
224 | -}; | ||
225 | - | ||
226 | -#ifdef __i386__ | ||
227 | -#define USE_X86LDOUBLE | ||
228 | -#endif | ||
229 | - | ||
230 | -#ifdef USE_X86LDOUBLE | ||
231 | -typedef long double CPU86_LDouble; | ||
232 | -#else | ||
233 | -typedef double CPU86_LDouble; | ||
234 | -#endif | ||
235 | - | ||
236 | -typedef struct SegmentCache { | ||
237 | - uint32_t selector; | ||
238 | - uint8_t *base; | ||
239 | - uint32_t limit; | ||
240 | - uint32_t flags; | ||
241 | -} SegmentCache; | ||
242 | - | ||
243 | -typedef struct CPUX86State { | ||
244 | - /* standard registers */ | ||
245 | - uint32_t regs[8]; | ||
246 | - uint32_t eip; | ||
247 | - uint32_t eflags; /* eflags register. During CPU emulation, CC | ||
248 | - flags and DF are set to zero because they are | ||
249 | - stored elsewhere */ | ||
250 | - | ||
251 | - /* emulator internal eflags handling */ | ||
252 | - uint32_t cc_src; | ||
253 | - uint32_t cc_dst; | ||
254 | - uint32_t cc_op; | ||
255 | - int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ | ||
256 | - uint32_t hflags; /* hidden flags, see HF_xxx constants */ | ||
257 | - | ||
258 | - /* FPU state */ | ||
259 | - unsigned int fpstt; /* top of stack index */ | ||
260 | - unsigned int fpus; | ||
261 | - unsigned int fpuc; | ||
262 | - uint8_t fptags[8]; /* 0 = valid, 1 = empty */ | ||
263 | - CPU86_LDouble fpregs[8]; | ||
264 | - | ||
265 | - /* emulator internal variables */ | ||
266 | - CPU86_LDouble ft0; | ||
267 | - union { | ||
268 | - float f; | ||
269 | - double d; | ||
270 | - int i32; | ||
271 | - int64_t i64; | ||
272 | - } fp_convert; | ||
273 | - | ||
274 | - /* segments */ | ||
275 | - SegmentCache segs[6]; /* selector values */ | ||
276 | - SegmentCache ldt; | ||
277 | - SegmentCache tr; | ||
278 | - SegmentCache gdt; /* only base and limit are used */ | ||
279 | - SegmentCache idt; /* only base and limit are used */ | ||
280 | - | ||
281 | - /* sysenter registers */ | ||
282 | - uint32_t sysenter_cs; | ||
283 | - uint32_t sysenter_esp; | ||
284 | - uint32_t sysenter_eip; | ||
285 | - | ||
286 | - /* exception/interrupt handling */ | ||
287 | - jmp_buf jmp_env; | ||
288 | - int exception_index; | ||
289 | - int error_code; | ||
290 | - int exception_is_int; | ||
291 | - int exception_next_eip; | ||
292 | - struct TranslationBlock *current_tb; /* currently executing TB */ | ||
293 | - uint32_t cr[5]; /* NOTE: cr1 is unused */ | ||
294 | - uint32_t dr[8]; /* debug registers */ | ||
295 | - int interrupt_request; | ||
296 | - int user_mode_only; /* user mode only simulation */ | ||
297 | - | ||
298 | - /* soft mmu support */ | ||
299 | - /* 0 = kernel, 1 = user */ | ||
300 | - CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; | ||
301 | - CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; | ||
302 | - | ||
303 | - /* ice debug support */ | ||
304 | - uint32_t breakpoints[MAX_BREAKPOINTS]; | ||
305 | - int nb_breakpoints; | ||
306 | - int singlestep_enabled; | ||
307 | - | ||
308 | - /* user data */ | ||
309 | - void *opaque; | ||
310 | -} CPUX86State; | ||
311 | - | ||
312 | -#ifndef IN_OP_I386 | ||
313 | -void cpu_x86_outb(CPUX86State *env, int addr, int val); | ||
314 | -void cpu_x86_outw(CPUX86State *env, int addr, int val); | ||
315 | -void cpu_x86_outl(CPUX86State *env, int addr, int val); | ||
316 | -int cpu_x86_inb(CPUX86State *env, int addr); | ||
317 | -int cpu_x86_inw(CPUX86State *env, int addr); | ||
318 | -int cpu_x86_inl(CPUX86State *env, int addr); | ||
319 | -#endif | ||
320 | - | ||
321 | -CPUX86State *cpu_x86_init(void); | ||
322 | -int cpu_x86_exec(CPUX86State *s); | ||
323 | -void cpu_x86_close(CPUX86State *s); | ||
324 | -int cpu_x86_get_pic_interrupt(CPUX86State *s); | ||
325 | - | ||
326 | -/* this function must always be used to load data in the segment | ||
327 | - cache: it synchronizes the hflags with the segment cache values */ | ||
328 | -static inline void cpu_x86_load_seg_cache(CPUX86State *env, | ||
329 | - int seg_reg, unsigned int selector, | ||
330 | - uint8_t *base, unsigned int limit, | ||
331 | - unsigned int flags) | ||
332 | -{ | ||
333 | - SegmentCache *sc; | ||
334 | - unsigned int new_hflags; | ||
335 | - | ||
336 | - sc = &env->segs[seg_reg]; | ||
337 | - sc->selector = selector; | ||
338 | - sc->base = base; | ||
339 | - sc->limit = limit; | ||
340 | - sc->flags = flags; | ||
341 | - | ||
342 | - /* update the hidden flags */ | ||
343 | - new_hflags = (env->segs[R_CS].flags & DESC_B_MASK) | ||
344 | - >> (DESC_B_SHIFT - HF_CS32_SHIFT); | ||
345 | - new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK) | ||
346 | - >> (DESC_B_SHIFT - HF_SS32_SHIFT); | ||
347 | - if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { | ||
348 | - /* XXX: try to avoid this test. The problem comes from the | ||
349 | - fact that is real mode or vm86 mode we only modify the | ||
350 | - 'base' and 'selector' fields of the segment cache to go | ||
351 | - faster. A solution may be to force addseg to one in | ||
352 | - translate-i386.c. */ | ||
353 | - new_hflags |= HF_ADDSEG_MASK; | ||
354 | - } else { | ||
355 | - new_hflags |= (((unsigned long)env->segs[R_DS].base | | ||
356 | - (unsigned long)env->segs[R_ES].base | | ||
357 | - (unsigned long)env->segs[R_SS].base) != 0) << | ||
358 | - HF_ADDSEG_SHIFT; | ||
359 | - } | ||
360 | - env->hflags = (env->hflags & | ||
361 | - ~(HF_CS32_MASK | HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags; | ||
362 | -} | ||
363 | - | ||
364 | -/* wrapper, just in case memory mappings must be changed */ | ||
365 | -static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl) | ||
366 | -{ | ||
367 | -#if HF_CPL_MASK == 3 | ||
368 | - s->hflags = (s->hflags & ~HF_CPL_MASK) | cpl; | ||
369 | -#else | ||
370 | -#error HF_CPL_MASK is hardcoded | ||
371 | -#endif | ||
372 | -} | ||
373 | - | ||
374 | -/* the following helpers are only usable in user mode simulation as | ||
375 | - they can trigger unexpected exceptions */ | ||
376 | -void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); | ||
377 | -void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32); | ||
378 | -void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32); | ||
379 | - | ||
380 | -/* you can call this signal handler from your SIGBUS and SIGSEGV | ||
381 | - signal handlers to inform the virtual CPU of exceptions. non zero | ||
382 | - is returned if the signal was handled by the virtual CPU. */ | ||
383 | -struct siginfo; | ||
384 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
385 | - void *puc); | ||
386 | - | ||
387 | -/* MMU defines */ | ||
388 | -void cpu_x86_init_mmu(CPUX86State *env); | ||
389 | -extern int phys_ram_size; | ||
390 | -extern int phys_ram_fd; | ||
391 | -extern uint8_t *phys_ram_base; | ||
392 | - | ||
393 | -/* used to debug */ | ||
394 | -#define X86_DUMP_FPU 0x0001 /* dump FPU state too */ | ||
395 | -#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */ | ||
396 | -void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags); | ||
397 | - | ||
398 | -#define TARGET_PAGE_BITS 12 | ||
399 | -#include "cpu-all.h" | ||
400 | - | ||
401 | -#endif /* CPU_I386_H */ |
exec.h renamed to exec-all.h
exec-arm.h deleted
100644 → 0
1 | -/* | ||
2 | - * ARM execution defines | ||
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 | -#include "dyngen-exec.h" | ||
21 | - | ||
22 | -register struct CPUARMState *env asm(AREG0); | ||
23 | -register uint32_t T0 asm(AREG1); | ||
24 | -register uint32_t T1 asm(AREG2); | ||
25 | -register uint32_t T2 asm(AREG3); | ||
26 | - | ||
27 | -#include "cpu-arm.h" | ||
28 | -#include "exec.h" | ||
29 | - | ||
30 | -void cpu_lock(void); | ||
31 | -void cpu_unlock(void); | ||
32 | -void cpu_loop_exit(void); | ||
33 | - | ||
34 | -static inline int compute_cpsr(void) | ||
35 | -{ | ||
36 | - int ZF; | ||
37 | - ZF = (env->NZF == 0); | ||
38 | - return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | | ||
39 | - (env->CF << 29) | ((env->VF & 0x80000000) >> 3); | ||
40 | -} |
exec-i386.h deleted
100644 → 0
1 | -/* | ||
2 | - * i386 execution defines | ||
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 | -#include "dyngen-exec.h" | ||
21 | - | ||
22 | -/* at least 4 register variables are defines */ | ||
23 | -register struct CPUX86State *env asm(AREG0); | ||
24 | -register uint32_t T0 asm(AREG1); | ||
25 | -register uint32_t T1 asm(AREG2); | ||
26 | -register uint32_t T2 asm(AREG3); | ||
27 | - | ||
28 | -#define A0 T2 | ||
29 | - | ||
30 | -/* if more registers are available, we define some registers too */ | ||
31 | -#ifdef AREG4 | ||
32 | -register uint32_t EAX asm(AREG4); | ||
33 | -#define reg_EAX | ||
34 | -#endif | ||
35 | - | ||
36 | -#ifdef AREG5 | ||
37 | -register uint32_t ESP asm(AREG5); | ||
38 | -#define reg_ESP | ||
39 | -#endif | ||
40 | - | ||
41 | -#ifdef AREG6 | ||
42 | -register uint32_t EBP asm(AREG6); | ||
43 | -#define reg_EBP | ||
44 | -#endif | ||
45 | - | ||
46 | -#ifdef AREG7 | ||
47 | -register uint32_t ECX asm(AREG7); | ||
48 | -#define reg_ECX | ||
49 | -#endif | ||
50 | - | ||
51 | -#ifdef AREG8 | ||
52 | -register uint32_t EDX asm(AREG8); | ||
53 | -#define reg_EDX | ||
54 | -#endif | ||
55 | - | ||
56 | -#ifdef AREG9 | ||
57 | -register uint32_t EBX asm(AREG9); | ||
58 | -#define reg_EBX | ||
59 | -#endif | ||
60 | - | ||
61 | -#ifdef AREG10 | ||
62 | -register uint32_t ESI asm(AREG10); | ||
63 | -#define reg_ESI | ||
64 | -#endif | ||
65 | - | ||
66 | -#ifdef AREG11 | ||
67 | -register uint32_t EDI asm(AREG11); | ||
68 | -#define reg_EDI | ||
69 | -#endif | ||
70 | - | ||
71 | -extern FILE *logfile; | ||
72 | -extern int loglevel; | ||
73 | - | ||
74 | -#ifndef reg_EAX | ||
75 | -#define EAX (env->regs[R_EAX]) | ||
76 | -#endif | ||
77 | -#ifndef reg_ECX | ||
78 | -#define ECX (env->regs[R_ECX]) | ||
79 | -#endif | ||
80 | -#ifndef reg_EDX | ||
81 | -#define EDX (env->regs[R_EDX]) | ||
82 | -#endif | ||
83 | -#ifndef reg_EBX | ||
84 | -#define EBX (env->regs[R_EBX]) | ||
85 | -#endif | ||
86 | -#ifndef reg_ESP | ||
87 | -#define ESP (env->regs[R_ESP]) | ||
88 | -#endif | ||
89 | -#ifndef reg_EBP | ||
90 | -#define EBP (env->regs[R_EBP]) | ||
91 | -#endif | ||
92 | -#ifndef reg_ESI | ||
93 | -#define ESI (env->regs[R_ESI]) | ||
94 | -#endif | ||
95 | -#ifndef reg_EDI | ||
96 | -#define EDI (env->regs[R_EDI]) | ||
97 | -#endif | ||
98 | -#define EIP (env->eip) | ||
99 | -#define DF (env->df) | ||
100 | - | ||
101 | -#define CC_SRC (env->cc_src) | ||
102 | -#define CC_DST (env->cc_dst) | ||
103 | -#define CC_OP (env->cc_op) | ||
104 | - | ||
105 | -/* float macros */ | ||
106 | -#define FT0 (env->ft0) | ||
107 | -#define ST0 (env->fpregs[env->fpstt]) | ||
108 | -#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7]) | ||
109 | -#define ST1 ST(1) | ||
110 | - | ||
111 | -#ifdef USE_FP_CONVERT | ||
112 | -#define FP_CONVERT (env->fp_convert) | ||
113 | -#endif | ||
114 | - | ||
115 | -#include "cpu-i386.h" | ||
116 | -#include "exec.h" | ||
117 | - | ||
118 | -typedef struct CCTable { | ||
119 | - int (*compute_all)(void); /* return all the flags */ | ||
120 | - int (*compute_c)(void); /* return the C flag */ | ||
121 | -} CCTable; | ||
122 | - | ||
123 | -extern CCTable cc_table[]; | ||
124 | - | ||
125 | -void load_seg(int seg_reg, int selector, unsigned cur_eip); | ||
126 | -void helper_ljmp_protected_T0_T1(void); | ||
127 | -void helper_lcall_real_T0_T1(int shift, int next_eip); | ||
128 | -void helper_lcall_protected_T0_T1(int shift, int next_eip); | ||
129 | -void helper_iret_real(int shift); | ||
130 | -void helper_iret_protected(int shift); | ||
131 | -void helper_lret_protected(int shift, int addend); | ||
132 | -void helper_lldt_T0(void); | ||
133 | -void helper_ltr_T0(void); | ||
134 | -void helper_movl_crN_T0(int reg); | ||
135 | -void helper_movl_drN_T0(int reg); | ||
136 | -void helper_invlpg(unsigned int addr); | ||
137 | -void cpu_x86_update_cr0(CPUX86State *env); | ||
138 | -void cpu_x86_update_cr3(CPUX86State *env); | ||
139 | -void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); | ||
140 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write); | ||
141 | -void tlb_fill(unsigned long addr, int is_write, void *retaddr); | ||
142 | -void __hidden cpu_lock(void); | ||
143 | -void __hidden cpu_unlock(void); | ||
144 | -void do_interrupt(int intno, int is_int, int error_code, | ||
145 | - unsigned int next_eip, int is_hw); | ||
146 | -void do_interrupt_user(int intno, int is_int, int error_code, | ||
147 | - unsigned int next_eip); | ||
148 | -void raise_interrupt(int intno, int is_int, int error_code, | ||
149 | - unsigned int next_eip); | ||
150 | -void raise_exception_err(int exception_index, int error_code); | ||
151 | -void raise_exception(int exception_index); | ||
152 | -void __hidden cpu_loop_exit(void); | ||
153 | -void helper_fsave(uint8_t *ptr, int data32); | ||
154 | -void helper_frstor(uint8_t *ptr, int data32); | ||
155 | - | ||
156 | -void OPPROTO op_movl_eflags_T0(void); | ||
157 | -void OPPROTO op_movl_T0_eflags(void); | ||
158 | -void raise_interrupt(int intno, int is_int, int error_code, | ||
159 | - unsigned int next_eip); | ||
160 | -void raise_exception_err(int exception_index, int error_code); | ||
161 | -void raise_exception(int exception_index); | ||
162 | -void helper_divl_EAX_T0(uint32_t eip); | ||
163 | -void helper_idivl_EAX_T0(uint32_t eip); | ||
164 | -void helper_cmpxchg8b(void); | ||
165 | -void helper_cpuid(void); | ||
166 | -void helper_rdtsc(void); | ||
167 | -void helper_rdmsr(void); | ||
168 | -void helper_wrmsr(void); | ||
169 | -void helper_lsl(void); | ||
170 | -void helper_lar(void); | ||
171 | - | ||
172 | -#ifdef USE_X86LDOUBLE | ||
173 | -/* use long double functions */ | ||
174 | -#define lrint lrintl | ||
175 | -#define llrint llrintl | ||
176 | -#define fabs fabsl | ||
177 | -#define sin sinl | ||
178 | -#define cos cosl | ||
179 | -#define sqrt sqrtl | ||
180 | -#define pow powl | ||
181 | -#define log logl | ||
182 | -#define tan tanl | ||
183 | -#define atan2 atan2l | ||
184 | -#define floor floorl | ||
185 | -#define ceil ceill | ||
186 | -#define rint rintl | ||
187 | -#endif | ||
188 | - | ||
189 | -extern int lrint(CPU86_LDouble x); | ||
190 | -extern int64_t llrint(CPU86_LDouble x); | ||
191 | -extern CPU86_LDouble fabs(CPU86_LDouble x); | ||
192 | -extern CPU86_LDouble sin(CPU86_LDouble x); | ||
193 | -extern CPU86_LDouble cos(CPU86_LDouble x); | ||
194 | -extern CPU86_LDouble sqrt(CPU86_LDouble x); | ||
195 | -extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble); | ||
196 | -extern CPU86_LDouble log(CPU86_LDouble x); | ||
197 | -extern CPU86_LDouble tan(CPU86_LDouble x); | ||
198 | -extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble); | ||
199 | -extern CPU86_LDouble floor(CPU86_LDouble x); | ||
200 | -extern CPU86_LDouble ceil(CPU86_LDouble x); | ||
201 | -extern CPU86_LDouble rint(CPU86_LDouble x); | ||
202 | - | ||
203 | -#define RC_MASK 0xc00 | ||
204 | -#define RC_NEAR 0x000 | ||
205 | -#define RC_DOWN 0x400 | ||
206 | -#define RC_UP 0x800 | ||
207 | -#define RC_CHOP 0xc00 | ||
208 | - | ||
209 | -#define MAXTAN 9223372036854775808.0 | ||
210 | - | ||
211 | -#ifdef __arm__ | ||
212 | -/* we have no way to do correct rounding - a FPU emulator is needed */ | ||
213 | -#define FE_DOWNWARD FE_TONEAREST | ||
214 | -#define FE_UPWARD FE_TONEAREST | ||
215 | -#define FE_TOWARDZERO FE_TONEAREST | ||
216 | -#endif | ||
217 | - | ||
218 | -#ifdef USE_X86LDOUBLE | ||
219 | - | ||
220 | -/* only for x86 */ | ||
221 | -typedef union { | ||
222 | - long double d; | ||
223 | - struct { | ||
224 | - unsigned long long lower; | ||
225 | - unsigned short upper; | ||
226 | - } l; | ||
227 | -} CPU86_LDoubleU; | ||
228 | - | ||
229 | -/* the following deal with x86 long double-precision numbers */ | ||
230 | -#define MAXEXPD 0x7fff | ||
231 | -#define EXPBIAS 16383 | ||
232 | -#define EXPD(fp) (fp.l.upper & 0x7fff) | ||
233 | -#define SIGND(fp) ((fp.l.upper) & 0x8000) | ||
234 | -#define MANTD(fp) (fp.l.lower) | ||
235 | -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS | ||
236 | - | ||
237 | -#else | ||
238 | - | ||
239 | -/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ | ||
240 | -typedef union { | ||
241 | - double d; | ||
242 | -#if !defined(WORDS_BIGENDIAN) && !defined(__arm__) | ||
243 | - struct { | ||
244 | - uint32_t lower; | ||
245 | - int32_t upper; | ||
246 | - } l; | ||
247 | -#else | ||
248 | - struct { | ||
249 | - int32_t upper; | ||
250 | - uint32_t lower; | ||
251 | - } l; | ||
252 | -#endif | ||
253 | -#ifndef __arm__ | ||
254 | - int64_t ll; | ||
255 | -#endif | ||
256 | -} CPU86_LDoubleU; | ||
257 | - | ||
258 | -/* the following deal with IEEE double-precision numbers */ | ||
259 | -#define MAXEXPD 0x7ff | ||
260 | -#define EXPBIAS 1023 | ||
261 | -#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) | ||
262 | -#define SIGND(fp) ((fp.l.upper) & 0x80000000) | ||
263 | -#ifdef __arm__ | ||
264 | -#define MANTD(fp) (fp.l.lower | ((uint64_t)(fp.l.upper & ((1 << 20) - 1)) << 32)) | ||
265 | -#else | ||
266 | -#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) | ||
267 | -#endif | ||
268 | -#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) | ||
269 | -#endif | ||
270 | - | ||
271 | -static inline void fpush(void) | ||
272 | -{ | ||
273 | - env->fpstt = (env->fpstt - 1) & 7; | ||
274 | - env->fptags[env->fpstt] = 0; /* validate stack entry */ | ||
275 | -} | ||
276 | - | ||
277 | -static inline void fpop(void) | ||
278 | -{ | ||
279 | - env->fptags[env->fpstt] = 1; /* invvalidate stack entry */ | ||
280 | - env->fpstt = (env->fpstt + 1) & 7; | ||
281 | -} | ||
282 | - | ||
283 | -#ifndef USE_X86LDOUBLE | ||
284 | -static inline CPU86_LDouble helper_fldt(uint8_t *ptr) | ||
285 | -{ | ||
286 | - CPU86_LDoubleU temp; | ||
287 | - int upper, e; | ||
288 | - uint64_t ll; | ||
289 | - | ||
290 | - /* mantissa */ | ||
291 | - upper = lduw(ptr + 8); | ||
292 | - /* XXX: handle overflow ? */ | ||
293 | - e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ | ||
294 | - e |= (upper >> 4) & 0x800; /* sign */ | ||
295 | - ll = (ldq(ptr) >> 11) & ((1LL << 52) - 1); | ||
296 | -#ifdef __arm__ | ||
297 | - temp.l.upper = (e << 20) | (ll >> 32); | ||
298 | - temp.l.lower = ll; | ||
299 | -#else | ||
300 | - temp.ll = ll | ((uint64_t)e << 52); | ||
301 | -#endif | ||
302 | - return temp.d; | ||
303 | -} | ||
304 | - | ||
305 | -static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) | ||
306 | -{ | ||
307 | - CPU86_LDoubleU temp; | ||
308 | - int e; | ||
309 | - | ||
310 | - temp.d = f; | ||
311 | - /* mantissa */ | ||
312 | - stq(ptr, (MANTD(temp) << 11) | (1LL << 63)); | ||
313 | - /* exponent + sign */ | ||
314 | - e = EXPD(temp) - EXPBIAS + 16383; | ||
315 | - e |= SIGND(temp) >> 16; | ||
316 | - stw(ptr + 8, e); | ||
317 | -} | ||
318 | -#endif | ||
319 | - | ||
320 | -const CPU86_LDouble f15rk[7]; | ||
321 | - | ||
322 | -void helper_fldt_ST0_A0(void); | ||
323 | -void helper_fstt_ST0_A0(void); | ||
324 | -void helper_fbld_ST0_A0(void); | ||
325 | -void helper_fbst_ST0_A0(void); | ||
326 | -void helper_f2xm1(void); | ||
327 | -void helper_fyl2x(void); | ||
328 | -void helper_fptan(void); | ||
329 | -void helper_fpatan(void); | ||
330 | -void helper_fxtract(void); | ||
331 | -void helper_fprem1(void); | ||
332 | -void helper_fprem(void); | ||
333 | -void helper_fyl2xp1(void); | ||
334 | -void helper_fsqrt(void); | ||
335 | -void helper_fsincos(void); | ||
336 | -void helper_frndint(void); | ||
337 | -void helper_fscale(void); | ||
338 | -void helper_fsin(void); | ||
339 | -void helper_fcos(void); | ||
340 | -void helper_fxam_ST0(void); | ||
341 | -void helper_fstenv(uint8_t *ptr, int data32); | ||
342 | -void helper_fldenv(uint8_t *ptr, int data32); | ||
343 | -void helper_fsave(uint8_t *ptr, int data32); | ||
344 | -void helper_frstor(uint8_t *ptr, int data32); | ||
345 | - | ||
346 | -const uint8_t parity_table[256]; | ||
347 | -const uint8_t rclw_table[32]; | ||
348 | -const uint8_t rclb_table[32]; | ||
349 | - | ||
350 | -static inline uint32_t compute_eflags(void) | ||
351 | -{ | ||
352 | - return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); | ||
353 | -} | ||
354 | - | ||
355 | -#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK) | ||
356 | - | ||
357 | -#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \ | ||
358 | - RF_MASK | AC_MASK | ID_MASK) | ||
359 | - | ||
360 | -/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */ | ||
361 | -static inline void load_eflags(int eflags, int update_mask) | ||
362 | -{ | ||
363 | - CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | ||
364 | - DF = 1 - (2 * ((eflags >> 10) & 1)); | ||
365 | - env->eflags = (env->eflags & ~update_mask) | | ||
366 | - (eflags & update_mask); | ||
367 | -} | ||
368 | - | ||
369 | -/* memory access macros */ | ||
370 | - | ||
371 | -#define ldul ldl | ||
372 | -#define lduq ldq | ||
373 | -#define ldul_user ldl_user | ||
374 | -#define ldul_kernel ldl_kernel | ||
375 | - | ||
376 | -#define ldub_raw ldub | ||
377 | -#define ldsb_raw ldsb | ||
378 | -#define lduw_raw lduw | ||
379 | -#define ldsw_raw ldsw | ||
380 | -#define ldl_raw ldl | ||
381 | -#define ldq_raw ldq | ||
382 | - | ||
383 | -#define stb_raw stb | ||
384 | -#define stw_raw stw | ||
385 | -#define stl_raw stl | ||
386 | -#define stq_raw stq | ||
387 | - | ||
388 | -#define MEMUSER 0 | ||
389 | -#define DATA_SIZE 1 | ||
390 | -#include "softmmu_header.h" | ||
391 | - | ||
392 | -#define DATA_SIZE 2 | ||
393 | -#include "softmmu_header.h" | ||
394 | - | ||
395 | -#define DATA_SIZE 4 | ||
396 | -#include "softmmu_header.h" | ||
397 | - | ||
398 | -#define DATA_SIZE 8 | ||
399 | -#include "softmmu_header.h" | ||
400 | - | ||
401 | -#undef MEMUSER | ||
402 | -#define MEMUSER 1 | ||
403 | -#define DATA_SIZE 1 | ||
404 | -#include "softmmu_header.h" | ||
405 | - | ||
406 | -#define DATA_SIZE 2 | ||
407 | -#include "softmmu_header.h" | ||
408 | - | ||
409 | -#define DATA_SIZE 4 | ||
410 | -#include "softmmu_header.h" | ||
411 | - | ||
412 | -#define DATA_SIZE 8 | ||
413 | -#include "softmmu_header.h" | ||
414 | - | ||
415 | -#undef MEMUSER | ||
416 | - |
helper-i386.c deleted
100644 → 0
1 | -/* | ||
2 | - * i386 helpers | ||
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 | -#include "exec-i386.h" | ||
21 | - | ||
22 | -const uint8_t parity_table[256] = { | ||
23 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
24 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
25 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
26 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
27 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
28 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
29 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
30 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
31 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
32 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
33 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
34 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
35 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
36 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
37 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
38 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
39 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
40 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
41 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
42 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
43 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
44 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
45 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
46 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
47 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
48 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
49 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
50 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
51 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
52 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
53 | - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | ||
54 | - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | ||
55 | -}; | ||
56 | - | ||
57 | -/* modulo 17 table */ | ||
58 | -const uint8_t rclw_table[32] = { | ||
59 | - 0, 1, 2, 3, 4, 5, 6, 7, | ||
60 | - 8, 9,10,11,12,13,14,15, | ||
61 | - 16, 0, 1, 2, 3, 4, 5, 6, | ||
62 | - 7, 8, 9,10,11,12,13,14, | ||
63 | -}; | ||
64 | - | ||
65 | -/* modulo 9 table */ | ||
66 | -const uint8_t rclb_table[32] = { | ||
67 | - 0, 1, 2, 3, 4, 5, 6, 7, | ||
68 | - 8, 0, 1, 2, 3, 4, 5, 6, | ||
69 | - 7, 8, 0, 1, 2, 3, 4, 5, | ||
70 | - 6, 7, 8, 0, 1, 2, 3, 4, | ||
71 | -}; | ||
72 | - | ||
73 | -const CPU86_LDouble f15rk[7] = | ||
74 | -{ | ||
75 | - 0.00000000000000000000L, | ||
76 | - 1.00000000000000000000L, | ||
77 | - 3.14159265358979323851L, /*pi*/ | ||
78 | - 0.30102999566398119523L, /*lg2*/ | ||
79 | - 0.69314718055994530943L, /*ln2*/ | ||
80 | - 1.44269504088896340739L, /*l2e*/ | ||
81 | - 3.32192809488736234781L, /*l2t*/ | ||
82 | -}; | ||
83 | - | ||
84 | -/* thread support */ | ||
85 | - | ||
86 | -spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; | ||
87 | - | ||
88 | -void cpu_lock(void) | ||
89 | -{ | ||
90 | - spin_lock(&global_cpu_lock); | ||
91 | -} | ||
92 | - | ||
93 | -void cpu_unlock(void) | ||
94 | -{ | ||
95 | - spin_unlock(&global_cpu_lock); | ||
96 | -} | ||
97 | - | ||
98 | -void cpu_loop_exit(void) | ||
99 | -{ | ||
100 | - /* NOTE: the register at this point must be saved by hand because | ||
101 | - longjmp restore them */ | ||
102 | -#ifdef reg_EAX | ||
103 | - env->regs[R_EAX] = EAX; | ||
104 | -#endif | ||
105 | -#ifdef reg_ECX | ||
106 | - env->regs[R_ECX] = ECX; | ||
107 | -#endif | ||
108 | -#ifdef reg_EDX | ||
109 | - env->regs[R_EDX] = EDX; | ||
110 | -#endif | ||
111 | -#ifdef reg_EBX | ||
112 | - env->regs[R_EBX] = EBX; | ||
113 | -#endif | ||
114 | -#ifdef reg_ESP | ||
115 | - env->regs[R_ESP] = ESP; | ||
116 | -#endif | ||
117 | -#ifdef reg_EBP | ||
118 | - env->regs[R_EBP] = EBP; | ||
119 | -#endif | ||
120 | -#ifdef reg_ESI | ||
121 | - env->regs[R_ESI] = ESI; | ||
122 | -#endif | ||
123 | -#ifdef reg_EDI | ||
124 | - env->regs[R_EDI] = EDI; | ||
125 | -#endif | ||
126 | - longjmp(env->jmp_env, 1); | ||
127 | -} | ||
128 | - | ||
129 | -static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, | ||
130 | - uint32_t *esp_ptr, int dpl) | ||
131 | -{ | ||
132 | - int type, index, shift; | ||
133 | - | ||
134 | -#if 0 | ||
135 | - { | ||
136 | - int i; | ||
137 | - printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit); | ||
138 | - for(i=0;i<env->tr.limit;i++) { | ||
139 | - printf("%02x ", env->tr.base[i]); | ||
140 | - if ((i & 7) == 7) printf("\n"); | ||
141 | - } | ||
142 | - printf("\n"); | ||
143 | - } | ||
144 | -#endif | ||
145 | - | ||
146 | - if (!(env->tr.flags & DESC_P_MASK)) | ||
147 | - cpu_abort(env, "invalid tss"); | ||
148 | - type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf; | ||
149 | - if ((type & 7) != 1) | ||
150 | - cpu_abort(env, "invalid tss type"); | ||
151 | - shift = type >> 3; | ||
152 | - index = (dpl * 4 + 2) << shift; | ||
153 | - if (index + (4 << shift) - 1 > env->tr.limit) | ||
154 | - raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); | ||
155 | - if (shift == 0) { | ||
156 | - *esp_ptr = lduw(env->tr.base + index); | ||
157 | - *ss_ptr = lduw(env->tr.base + index + 2); | ||
158 | - } else { | ||
159 | - *esp_ptr = ldl(env->tr.base + index); | ||
160 | - *ss_ptr = lduw(env->tr.base + index + 4); | ||
161 | - } | ||
162 | -} | ||
163 | - | ||
164 | -/* return non zero if error */ | ||
165 | -static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, | ||
166 | - int selector) | ||
167 | -{ | ||
168 | - SegmentCache *dt; | ||
169 | - int index; | ||
170 | - uint8_t *ptr; | ||
171 | - | ||
172 | - if (selector & 0x4) | ||
173 | - dt = &env->ldt; | ||
174 | - else | ||
175 | - dt = &env->gdt; | ||
176 | - index = selector & ~7; | ||
177 | - if ((index + 7) > dt->limit) | ||
178 | - return -1; | ||
179 | - ptr = dt->base + index; | ||
180 | - *e1_ptr = ldl(ptr); | ||
181 | - *e2_ptr = ldl(ptr + 4); | ||
182 | - return 0; | ||
183 | -} | ||
184 | - | ||
185 | -static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2) | ||
186 | -{ | ||
187 | - unsigned int limit; | ||
188 | - limit = (e1 & 0xffff) | (e2 & 0x000f0000); | ||
189 | - if (e2 & DESC_G_MASK) | ||
190 | - limit = (limit << 12) | 0xfff; | ||
191 | - return limit; | ||
192 | -} | ||
193 | - | ||
194 | -static inline uint8_t *get_seg_base(uint32_t e1, uint32_t e2) | ||
195 | -{ | ||
196 | - return (uint8_t *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); | ||
197 | -} | ||
198 | - | ||
199 | -static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2) | ||
200 | -{ | ||
201 | - sc->base = get_seg_base(e1, e2); | ||
202 | - sc->limit = get_seg_limit(e1, e2); | ||
203 | - sc->flags = e2; | ||
204 | -} | ||
205 | - | ||
206 | -/* init the segment cache in vm86 mode. */ | ||
207 | -static inline void load_seg_vm(int seg, int selector) | ||
208 | -{ | ||
209 | - selector &= 0xffff; | ||
210 | - cpu_x86_load_seg_cache(env, seg, selector, | ||
211 | - (uint8_t *)(selector << 4), 0xffff, 0); | ||
212 | -} | ||
213 | - | ||
214 | -/* protected mode interrupt */ | ||
215 | -static void do_interrupt_protected(int intno, int is_int, int error_code, | ||
216 | - unsigned int next_eip, int is_hw) | ||
217 | -{ | ||
218 | - SegmentCache *dt; | ||
219 | - uint8_t *ptr, *ssp; | ||
220 | - int type, dpl, selector, ss_dpl, cpl; | ||
221 | - int has_error_code, new_stack, shift; | ||
222 | - uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; | ||
223 | - uint32_t old_cs, old_ss, old_esp, old_eip; | ||
224 | - | ||
225 | - dt = &env->idt; | ||
226 | - if (intno * 8 + 7 > dt->limit) | ||
227 | - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | ||
228 | - ptr = dt->base + intno * 8; | ||
229 | - e1 = ldl(ptr); | ||
230 | - e2 = ldl(ptr + 4); | ||
231 | - /* check gate type */ | ||
232 | - type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; | ||
233 | - switch(type) { | ||
234 | - case 5: /* task gate */ | ||
235 | - cpu_abort(env, "task gate not supported"); | ||
236 | - break; | ||
237 | - case 6: /* 286 interrupt gate */ | ||
238 | - case 7: /* 286 trap gate */ | ||
239 | - case 14: /* 386 interrupt gate */ | ||
240 | - case 15: /* 386 trap gate */ | ||
241 | - break; | ||
242 | - default: | ||
243 | - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | ||
244 | - break; | ||
245 | - } | ||
246 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
247 | - cpl = env->hflags & HF_CPL_MASK; | ||
248 | - /* check privledge if software int */ | ||
249 | - if (is_int && dpl < cpl) | ||
250 | - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | ||
251 | - /* check valid bit */ | ||
252 | - if (!(e2 & DESC_P_MASK)) | ||
253 | - raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2); | ||
254 | - selector = e1 >> 16; | ||
255 | - offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); | ||
256 | - if ((selector & 0xfffc) == 0) | ||
257 | - raise_exception_err(EXCP0D_GPF, 0); | ||
258 | - | ||
259 | - if (load_segment(&e1, &e2, selector) != 0) | ||
260 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
261 | - if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) | ||
262 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
263 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
264 | - if (dpl > cpl) | ||
265 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
266 | - if (!(e2 & DESC_P_MASK)) | ||
267 | - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
268 | - if (!(e2 & DESC_C_MASK) && dpl < cpl) { | ||
269 | - /* to inner priviledge */ | ||
270 | - get_ss_esp_from_tss(&ss, &esp, dpl); | ||
271 | - if ((ss & 0xfffc) == 0) | ||
272 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
273 | - if ((ss & 3) != dpl) | ||
274 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
275 | - if (load_segment(&ss_e1, &ss_e2, ss) != 0) | ||
276 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
277 | - ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; | ||
278 | - if (ss_dpl != dpl) | ||
279 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
280 | - if (!(ss_e2 & DESC_S_MASK) || | ||
281 | - (ss_e2 & DESC_CS_MASK) || | ||
282 | - !(ss_e2 & DESC_W_MASK)) | ||
283 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
284 | - if (!(ss_e2 & DESC_P_MASK)) | ||
285 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
286 | - new_stack = 1; | ||
287 | - } else if ((e2 & DESC_C_MASK) || dpl == cpl) { | ||
288 | - /* to same priviledge */ | ||
289 | - new_stack = 0; | ||
290 | - } else { | ||
291 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
292 | - new_stack = 0; /* avoid warning */ | ||
293 | - } | ||
294 | - | ||
295 | - shift = type >> 3; | ||
296 | - has_error_code = 0; | ||
297 | - if (!is_int && !is_hw) { | ||
298 | - switch(intno) { | ||
299 | - case 8: | ||
300 | - case 10: | ||
301 | - case 11: | ||
302 | - case 12: | ||
303 | - case 13: | ||
304 | - case 14: | ||
305 | - case 17: | ||
306 | - has_error_code = 1; | ||
307 | - break; | ||
308 | - } | ||
309 | - } | ||
310 | - push_size = 6 + (new_stack << 2) + (has_error_code << 1); | ||
311 | - if (env->eflags & VM_MASK) | ||
312 | - push_size += 8; | ||
313 | - push_size <<= shift; | ||
314 | - | ||
315 | - /* XXX: check that enough room is available */ | ||
316 | - if (new_stack) { | ||
317 | - old_esp = ESP; | ||
318 | - old_ss = env->segs[R_SS].selector; | ||
319 | - ss = (ss & ~3) | dpl; | ||
320 | - cpu_x86_load_seg_cache(env, R_SS, ss, | ||
321 | - get_seg_base(ss_e1, ss_e2), | ||
322 | - get_seg_limit(ss_e1, ss_e2), | ||
323 | - ss_e2); | ||
324 | - } else { | ||
325 | - old_esp = 0; | ||
326 | - old_ss = 0; | ||
327 | - esp = ESP; | ||
328 | - } | ||
329 | - if (is_int) | ||
330 | - old_eip = next_eip; | ||
331 | - else | ||
332 | - old_eip = env->eip; | ||
333 | - old_cs = env->segs[R_CS].selector; | ||
334 | - selector = (selector & ~3) | dpl; | ||
335 | - cpu_x86_load_seg_cache(env, R_CS, selector, | ||
336 | - get_seg_base(e1, e2), | ||
337 | - get_seg_limit(e1, e2), | ||
338 | - e2); | ||
339 | - cpu_x86_set_cpl(env, dpl); | ||
340 | - env->eip = offset; | ||
341 | - ESP = esp - push_size; | ||
342 | - ssp = env->segs[R_SS].base + esp; | ||
343 | - if (shift == 1) { | ||
344 | - int old_eflags; | ||
345 | - if (env->eflags & VM_MASK) { | ||
346 | - ssp -= 4; | ||
347 | - stl(ssp, env->segs[R_GS].selector); | ||
348 | - ssp -= 4; | ||
349 | - stl(ssp, env->segs[R_FS].selector); | ||
350 | - ssp -= 4; | ||
351 | - stl(ssp, env->segs[R_DS].selector); | ||
352 | - ssp -= 4; | ||
353 | - stl(ssp, env->segs[R_ES].selector); | ||
354 | - } | ||
355 | - if (new_stack) { | ||
356 | - ssp -= 4; | ||
357 | - stl(ssp, old_ss); | ||
358 | - ssp -= 4; | ||
359 | - stl(ssp, old_esp); | ||
360 | - } | ||
361 | - ssp -= 4; | ||
362 | - old_eflags = compute_eflags(); | ||
363 | - stl(ssp, old_eflags); | ||
364 | - ssp -= 4; | ||
365 | - stl(ssp, old_cs); | ||
366 | - ssp -= 4; | ||
367 | - stl(ssp, old_eip); | ||
368 | - if (has_error_code) { | ||
369 | - ssp -= 4; | ||
370 | - stl(ssp, error_code); | ||
371 | - } | ||
372 | - } else { | ||
373 | - if (new_stack) { | ||
374 | - ssp -= 2; | ||
375 | - stw(ssp, old_ss); | ||
376 | - ssp -= 2; | ||
377 | - stw(ssp, old_esp); | ||
378 | - } | ||
379 | - ssp -= 2; | ||
380 | - stw(ssp, compute_eflags()); | ||
381 | - ssp -= 2; | ||
382 | - stw(ssp, old_cs); | ||
383 | - ssp -= 2; | ||
384 | - stw(ssp, old_eip); | ||
385 | - if (has_error_code) { | ||
386 | - ssp -= 2; | ||
387 | - stw(ssp, error_code); | ||
388 | - } | ||
389 | - } | ||
390 | - | ||
391 | - /* interrupt gate clear IF mask */ | ||
392 | - if ((type & 1) == 0) { | ||
393 | - env->eflags &= ~IF_MASK; | ||
394 | - } | ||
395 | - env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); | ||
396 | -} | ||
397 | - | ||
398 | -/* real mode interrupt */ | ||
399 | -static void do_interrupt_real(int intno, int is_int, int error_code, | ||
400 | - unsigned int next_eip) | ||
401 | -{ | ||
402 | - SegmentCache *dt; | ||
403 | - uint8_t *ptr, *ssp; | ||
404 | - int selector; | ||
405 | - uint32_t offset, esp; | ||
406 | - uint32_t old_cs, old_eip; | ||
407 | - | ||
408 | - /* real mode (simpler !) */ | ||
409 | - dt = &env->idt; | ||
410 | - if (intno * 4 + 3 > dt->limit) | ||
411 | - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | ||
412 | - ptr = dt->base + intno * 4; | ||
413 | - offset = lduw(ptr); | ||
414 | - selector = lduw(ptr + 2); | ||
415 | - esp = ESP; | ||
416 | - ssp = env->segs[R_SS].base; | ||
417 | - if (is_int) | ||
418 | - old_eip = next_eip; | ||
419 | - else | ||
420 | - old_eip = env->eip; | ||
421 | - old_cs = env->segs[R_CS].selector; | ||
422 | - esp -= 2; | ||
423 | - stw(ssp + (esp & 0xffff), compute_eflags()); | ||
424 | - esp -= 2; | ||
425 | - stw(ssp + (esp & 0xffff), old_cs); | ||
426 | - esp -= 2; | ||
427 | - stw(ssp + (esp & 0xffff), old_eip); | ||
428 | - | ||
429 | - /* update processor state */ | ||
430 | - ESP = (ESP & ~0xffff) | (esp & 0xffff); | ||
431 | - env->eip = offset; | ||
432 | - env->segs[R_CS].selector = selector; | ||
433 | - env->segs[R_CS].base = (uint8_t *)(selector << 4); | ||
434 | - env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK); | ||
435 | -} | ||
436 | - | ||
437 | -/* fake user mode interrupt */ | ||
438 | -void do_interrupt_user(int intno, int is_int, int error_code, | ||
439 | - unsigned int next_eip) | ||
440 | -{ | ||
441 | - SegmentCache *dt; | ||
442 | - uint8_t *ptr; | ||
443 | - int dpl, cpl; | ||
444 | - uint32_t e2; | ||
445 | - | ||
446 | - dt = &env->idt; | ||
447 | - ptr = dt->base + (intno * 8); | ||
448 | - e2 = ldl(ptr + 4); | ||
449 | - | ||
450 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
451 | - cpl = env->hflags & HF_CPL_MASK; | ||
452 | - /* check privledge if software int */ | ||
453 | - if (is_int && dpl < cpl) | ||
454 | - raise_exception_err(EXCP0D_GPF, intno * 8 + 2); | ||
455 | - | ||
456 | - /* Since we emulate only user space, we cannot do more than | ||
457 | - exiting the emulation with the suitable exception and error | ||
458 | - code */ | ||
459 | - if (is_int) | ||
460 | - EIP = next_eip; | ||
461 | -} | ||
462 | - | ||
463 | -/* | ||
464 | - * Begin excution of an interruption. is_int is TRUE if coming from | ||
465 | - * the int instruction. next_eip is the EIP value AFTER the interrupt | ||
466 | - * instruction. It is only relevant if is_int is TRUE. | ||
467 | - */ | ||
468 | -void do_interrupt(int intno, int is_int, int error_code, | ||
469 | - unsigned int next_eip, int is_hw) | ||
470 | -{ | ||
471 | - if (env->cr[0] & CR0_PE_MASK) { | ||
472 | - do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); | ||
473 | - } else { | ||
474 | - do_interrupt_real(intno, is_int, error_code, next_eip); | ||
475 | - } | ||
476 | -} | ||
477 | - | ||
478 | -/* | ||
479 | - * Signal an interruption. It is executed in the main CPU loop. | ||
480 | - * is_int is TRUE if coming from the int instruction. next_eip is the | ||
481 | - * EIP value AFTER the interrupt instruction. It is only relevant if | ||
482 | - * is_int is TRUE. | ||
483 | - */ | ||
484 | -void raise_interrupt(int intno, int is_int, int error_code, | ||
485 | - unsigned int next_eip) | ||
486 | -{ | ||
487 | - env->exception_index = intno; | ||
488 | - env->error_code = error_code; | ||
489 | - env->exception_is_int = is_int; | ||
490 | - env->exception_next_eip = next_eip; | ||
491 | - cpu_loop_exit(); | ||
492 | -} | ||
493 | - | ||
494 | -/* shortcuts to generate exceptions */ | ||
495 | -void raise_exception_err(int exception_index, int error_code) | ||
496 | -{ | ||
497 | - raise_interrupt(exception_index, 0, error_code, 0); | ||
498 | -} | ||
499 | - | ||
500 | -void raise_exception(int exception_index) | ||
501 | -{ | ||
502 | - raise_interrupt(exception_index, 0, 0, 0); | ||
503 | -} | ||
504 | - | ||
505 | -#ifdef BUGGY_GCC_DIV64 | ||
506 | -/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we | ||
507 | - call it from another function */ | ||
508 | -uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den) | ||
509 | -{ | ||
510 | - *q_ptr = num / den; | ||
511 | - return num % den; | ||
512 | -} | ||
513 | - | ||
514 | -int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den) | ||
515 | -{ | ||
516 | - *q_ptr = num / den; | ||
517 | - return num % den; | ||
518 | -} | ||
519 | -#endif | ||
520 | - | ||
521 | -void helper_divl_EAX_T0(uint32_t eip) | ||
522 | -{ | ||
523 | - unsigned int den, q, r; | ||
524 | - uint64_t num; | ||
525 | - | ||
526 | - num = EAX | ((uint64_t)EDX << 32); | ||
527 | - den = T0; | ||
528 | - if (den == 0) { | ||
529 | - EIP = eip; | ||
530 | - raise_exception(EXCP00_DIVZ); | ||
531 | - } | ||
532 | -#ifdef BUGGY_GCC_DIV64 | ||
533 | - r = div64(&q, num, den); | ||
534 | -#else | ||
535 | - q = (num / den); | ||
536 | - r = (num % den); | ||
537 | -#endif | ||
538 | - EAX = q; | ||
539 | - EDX = r; | ||
540 | -} | ||
541 | - | ||
542 | -void helper_idivl_EAX_T0(uint32_t eip) | ||
543 | -{ | ||
544 | - int den, q, r; | ||
545 | - int64_t num; | ||
546 | - | ||
547 | - num = EAX | ((uint64_t)EDX << 32); | ||
548 | - den = T0; | ||
549 | - if (den == 0) { | ||
550 | - EIP = eip; | ||
551 | - raise_exception(EXCP00_DIVZ); | ||
552 | - } | ||
553 | -#ifdef BUGGY_GCC_DIV64 | ||
554 | - r = idiv64(&q, num, den); | ||
555 | -#else | ||
556 | - q = (num / den); | ||
557 | - r = (num % den); | ||
558 | -#endif | ||
559 | - EAX = q; | ||
560 | - EDX = r; | ||
561 | -} | ||
562 | - | ||
563 | -void helper_cmpxchg8b(void) | ||
564 | -{ | ||
565 | - uint64_t d; | ||
566 | - int eflags; | ||
567 | - | ||
568 | - eflags = cc_table[CC_OP].compute_all(); | ||
569 | - d = ldq((uint8_t *)A0); | ||
570 | - if (d == (((uint64_t)EDX << 32) | EAX)) { | ||
571 | - stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX); | ||
572 | - eflags |= CC_Z; | ||
573 | - } else { | ||
574 | - EDX = d >> 32; | ||
575 | - EAX = d; | ||
576 | - eflags &= ~CC_Z; | ||
577 | - } | ||
578 | - CC_SRC = eflags; | ||
579 | -} | ||
580 | - | ||
581 | -/* We simulate a pre-MMX pentium as in valgrind */ | ||
582 | -#define CPUID_FP87 (1 << 0) | ||
583 | -#define CPUID_VME (1 << 1) | ||
584 | -#define CPUID_DE (1 << 2) | ||
585 | -#define CPUID_PSE (1 << 3) | ||
586 | -#define CPUID_TSC (1 << 4) | ||
587 | -#define CPUID_MSR (1 << 5) | ||
588 | -#define CPUID_PAE (1 << 6) | ||
589 | -#define CPUID_MCE (1 << 7) | ||
590 | -#define CPUID_CX8 (1 << 8) | ||
591 | -#define CPUID_APIC (1 << 9) | ||
592 | -#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ | ||
593 | -#define CPUID_MTRR (1 << 12) | ||
594 | -#define CPUID_PGE (1 << 13) | ||
595 | -#define CPUID_MCA (1 << 14) | ||
596 | -#define CPUID_CMOV (1 << 15) | ||
597 | -/* ... */ | ||
598 | -#define CPUID_MMX (1 << 23) | ||
599 | -#define CPUID_FXSR (1 << 24) | ||
600 | -#define CPUID_SSE (1 << 25) | ||
601 | -#define CPUID_SSE2 (1 << 26) | ||
602 | - | ||
603 | -void helper_cpuid(void) | ||
604 | -{ | ||
605 | - if (EAX == 0) { | ||
606 | - EAX = 1; /* max EAX index supported */ | ||
607 | - EBX = 0x756e6547; | ||
608 | - ECX = 0x6c65746e; | ||
609 | - EDX = 0x49656e69; | ||
610 | - } else if (EAX == 1) { | ||
611 | - int family, model, stepping; | ||
612 | - /* EAX = 1 info */ | ||
613 | -#if 0 | ||
614 | - /* pentium 75-200 */ | ||
615 | - family = 5; | ||
616 | - model = 2; | ||
617 | - stepping = 11; | ||
618 | -#else | ||
619 | - /* pentium pro */ | ||
620 | - family = 6; | ||
621 | - model = 1; | ||
622 | - stepping = 3; | ||
623 | -#endif | ||
624 | - EAX = (family << 8) | (model << 4) | stepping; | ||
625 | - EBX = 0; | ||
626 | - ECX = 0; | ||
627 | - EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE | | ||
628 | - CPUID_TSC | CPUID_MSR | CPUID_MCE | | ||
629 | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV; | ||
630 | - } | ||
631 | -} | ||
632 | - | ||
633 | -void helper_lldt_T0(void) | ||
634 | -{ | ||
635 | - int selector; | ||
636 | - SegmentCache *dt; | ||
637 | - uint32_t e1, e2; | ||
638 | - int index; | ||
639 | - uint8_t *ptr; | ||
640 | - | ||
641 | - selector = T0 & 0xffff; | ||
642 | - if ((selector & 0xfffc) == 0) { | ||
643 | - /* XXX: NULL selector case: invalid LDT */ | ||
644 | - env->ldt.base = NULL; | ||
645 | - env->ldt.limit = 0; | ||
646 | - } else { | ||
647 | - if (selector & 0x4) | ||
648 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
649 | - dt = &env->gdt; | ||
650 | - index = selector & ~7; | ||
651 | - if ((index + 7) > dt->limit) | ||
652 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
653 | - ptr = dt->base + index; | ||
654 | - e1 = ldl(ptr); | ||
655 | - e2 = ldl(ptr + 4); | ||
656 | - if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) | ||
657 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
658 | - if (!(e2 & DESC_P_MASK)) | ||
659 | - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
660 | - load_seg_cache_raw_dt(&env->ldt, e1, e2); | ||
661 | - } | ||
662 | - env->ldt.selector = selector; | ||
663 | -} | ||
664 | - | ||
665 | -void helper_ltr_T0(void) | ||
666 | -{ | ||
667 | - int selector; | ||
668 | - SegmentCache *dt; | ||
669 | - uint32_t e1, e2; | ||
670 | - int index, type; | ||
671 | - uint8_t *ptr; | ||
672 | - | ||
673 | - selector = T0 & 0xffff; | ||
674 | - if ((selector & 0xfffc) == 0) { | ||
675 | - /* NULL selector case: invalid LDT */ | ||
676 | - env->tr.base = NULL; | ||
677 | - env->tr.limit = 0; | ||
678 | - env->tr.flags = 0; | ||
679 | - } else { | ||
680 | - if (selector & 0x4) | ||
681 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
682 | - dt = &env->gdt; | ||
683 | - index = selector & ~7; | ||
684 | - if ((index + 7) > dt->limit) | ||
685 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
686 | - ptr = dt->base + index; | ||
687 | - e1 = ldl(ptr); | ||
688 | - e2 = ldl(ptr + 4); | ||
689 | - type = (e2 >> DESC_TYPE_SHIFT) & 0xf; | ||
690 | - if ((e2 & DESC_S_MASK) || | ||
691 | - (type != 2 && type != 9)) | ||
692 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
693 | - if (!(e2 & DESC_P_MASK)) | ||
694 | - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
695 | - load_seg_cache_raw_dt(&env->tr, e1, e2); | ||
696 | - e2 |= 0x00000200; /* set the busy bit */ | ||
697 | - stl(ptr + 4, e2); | ||
698 | - } | ||
699 | - env->tr.selector = selector; | ||
700 | -} | ||
701 | - | ||
702 | -/* only works if protected mode and not VM86. Calling load_seg with | ||
703 | - seg_reg == R_CS is discouraged */ | ||
704 | -void load_seg(int seg_reg, int selector, unsigned int cur_eip) | ||
705 | -{ | ||
706 | - uint32_t e1, e2; | ||
707 | - | ||
708 | - if ((selector & 0xfffc) == 0) { | ||
709 | - /* null selector case */ | ||
710 | - if (seg_reg == R_SS) { | ||
711 | - EIP = cur_eip; | ||
712 | - raise_exception_err(EXCP0D_GPF, 0); | ||
713 | - } else { | ||
714 | - cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0); | ||
715 | - } | ||
716 | - } else { | ||
717 | - if (load_segment(&e1, &e2, selector) != 0) { | ||
718 | - EIP = cur_eip; | ||
719 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
720 | - } | ||
721 | - if (!(e2 & DESC_S_MASK) || | ||
722 | - (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { | ||
723 | - EIP = cur_eip; | ||
724 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
725 | - } | ||
726 | - | ||
727 | - if (seg_reg == R_SS) { | ||
728 | - if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) { | ||
729 | - EIP = cur_eip; | ||
730 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
731 | - } | ||
732 | - } else { | ||
733 | - if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { | ||
734 | - EIP = cur_eip; | ||
735 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
736 | - } | ||
737 | - } | ||
738 | - | ||
739 | - if (!(e2 & DESC_P_MASK)) { | ||
740 | - EIP = cur_eip; | ||
741 | - if (seg_reg == R_SS) | ||
742 | - raise_exception_err(EXCP0C_STACK, selector & 0xfffc); | ||
743 | - else | ||
744 | - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
745 | - } | ||
746 | - cpu_x86_load_seg_cache(env, seg_reg, selector, | ||
747 | - get_seg_base(e1, e2), | ||
748 | - get_seg_limit(e1, e2), | ||
749 | - e2); | ||
750 | -#if 0 | ||
751 | - fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n", | ||
752 | - selector, (unsigned long)sc->base, sc->limit, sc->flags); | ||
753 | -#endif | ||
754 | - } | ||
755 | -} | ||
756 | - | ||
757 | -/* protected mode jump */ | ||
758 | -void helper_ljmp_protected_T0_T1(void) | ||
759 | -{ | ||
760 | - int new_cs, new_eip; | ||
761 | - uint32_t e1, e2, cpl, dpl, rpl, limit; | ||
762 | - | ||
763 | - new_cs = T0; | ||
764 | - new_eip = T1; | ||
765 | - if ((new_cs & 0xfffc) == 0) | ||
766 | - raise_exception_err(EXCP0D_GPF, 0); | ||
767 | - if (load_segment(&e1, &e2, new_cs) != 0) | ||
768 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
769 | - cpl = env->hflags & HF_CPL_MASK; | ||
770 | - if (e2 & DESC_S_MASK) { | ||
771 | - if (!(e2 & DESC_CS_MASK)) | ||
772 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
773 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
774 | - if (e2 & DESC_CS_MASK) { | ||
775 | - /* conforming code segment */ | ||
776 | - if (dpl > cpl) | ||
777 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
778 | - } else { | ||
779 | - /* non conforming code segment */ | ||
780 | - rpl = new_cs & 3; | ||
781 | - if (rpl > cpl) | ||
782 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
783 | - if (dpl != cpl) | ||
784 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
785 | - } | ||
786 | - if (!(e2 & DESC_P_MASK)) | ||
787 | - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); | ||
788 | - limit = get_seg_limit(e1, e2); | ||
789 | - if (new_eip > limit) | ||
790 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
791 | - cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, | ||
792 | - get_seg_base(e1, e2), limit, e2); | ||
793 | - EIP = new_eip; | ||
794 | - } else { | ||
795 | - cpu_abort(env, "jmp to call/task gate not supported 0x%04x:0x%08x", | ||
796 | - new_cs, new_eip); | ||
797 | - } | ||
798 | -} | ||
799 | - | ||
800 | -/* real mode call */ | ||
801 | -void helper_lcall_real_T0_T1(int shift, int next_eip) | ||
802 | -{ | ||
803 | - int new_cs, new_eip; | ||
804 | - uint32_t esp, esp_mask; | ||
805 | - uint8_t *ssp; | ||
806 | - | ||
807 | - new_cs = T0; | ||
808 | - new_eip = T1; | ||
809 | - esp = ESP; | ||
810 | - esp_mask = 0xffffffff; | ||
811 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
812 | - esp_mask = 0xffff; | ||
813 | - ssp = env->segs[R_SS].base; | ||
814 | - if (shift) { | ||
815 | - esp -= 4; | ||
816 | - stl(ssp + (esp & esp_mask), env->segs[R_CS].selector); | ||
817 | - esp -= 4; | ||
818 | - stl(ssp + (esp & esp_mask), next_eip); | ||
819 | - } else { | ||
820 | - esp -= 2; | ||
821 | - stw(ssp + (esp & esp_mask), env->segs[R_CS].selector); | ||
822 | - esp -= 2; | ||
823 | - stw(ssp + (esp & esp_mask), next_eip); | ||
824 | - } | ||
825 | - | ||
826 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
827 | - ESP = (ESP & ~0xffff) | (esp & 0xffff); | ||
828 | - else | ||
829 | - ESP = esp; | ||
830 | - env->eip = new_eip; | ||
831 | - env->segs[R_CS].selector = new_cs; | ||
832 | - env->segs[R_CS].base = (uint8_t *)(new_cs << 4); | ||
833 | -} | ||
834 | - | ||
835 | -/* protected mode call */ | ||
836 | -void helper_lcall_protected_T0_T1(int shift, int next_eip) | ||
837 | -{ | ||
838 | - int new_cs, new_eip; | ||
839 | - uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; | ||
840 | - uint32_t ss, ss_e1, ss_e2, push_size, sp, type, ss_dpl; | ||
841 | - uint32_t old_ss, old_esp, val, i, limit; | ||
842 | - uint8_t *ssp, *old_ssp; | ||
843 | - | ||
844 | - new_cs = T0; | ||
845 | - new_eip = T1; | ||
846 | - if ((new_cs & 0xfffc) == 0) | ||
847 | - raise_exception_err(EXCP0D_GPF, 0); | ||
848 | - if (load_segment(&e1, &e2, new_cs) != 0) | ||
849 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
850 | - cpl = env->hflags & HF_CPL_MASK; | ||
851 | - if (e2 & DESC_S_MASK) { | ||
852 | - if (!(e2 & DESC_CS_MASK)) | ||
853 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
854 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
855 | - if (e2 & DESC_CS_MASK) { | ||
856 | - /* conforming code segment */ | ||
857 | - if (dpl > cpl) | ||
858 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
859 | - } else { | ||
860 | - /* non conforming code segment */ | ||
861 | - rpl = new_cs & 3; | ||
862 | - if (rpl > cpl) | ||
863 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
864 | - if (dpl != cpl) | ||
865 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
866 | - } | ||
867 | - if (!(e2 & DESC_P_MASK)) | ||
868 | - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); | ||
869 | - | ||
870 | - sp = ESP; | ||
871 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
872 | - sp &= 0xffff; | ||
873 | - ssp = env->segs[R_SS].base + sp; | ||
874 | - if (shift) { | ||
875 | - ssp -= 4; | ||
876 | - stl(ssp, env->segs[R_CS].selector); | ||
877 | - ssp -= 4; | ||
878 | - stl(ssp, next_eip); | ||
879 | - } else { | ||
880 | - ssp -= 2; | ||
881 | - stw(ssp, env->segs[R_CS].selector); | ||
882 | - ssp -= 2; | ||
883 | - stw(ssp, next_eip); | ||
884 | - } | ||
885 | - sp -= (4 << shift); | ||
886 | - | ||
887 | - limit = get_seg_limit(e1, e2); | ||
888 | - if (new_eip > limit) | ||
889 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
890 | - /* from this point, not restartable */ | ||
891 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
892 | - ESP = (ESP & 0xffff0000) | (sp & 0xffff); | ||
893 | - else | ||
894 | - ESP = sp; | ||
895 | - cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl, | ||
896 | - get_seg_base(e1, e2), limit, e2); | ||
897 | - EIP = new_eip; | ||
898 | - } else { | ||
899 | - /* check gate type */ | ||
900 | - type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; | ||
901 | - switch(type) { | ||
902 | - case 1: /* available 286 TSS */ | ||
903 | - case 9: /* available 386 TSS */ | ||
904 | - case 5: /* task gate */ | ||
905 | - cpu_abort(env, "task gate not supported"); | ||
906 | - break; | ||
907 | - case 4: /* 286 call gate */ | ||
908 | - case 12: /* 386 call gate */ | ||
909 | - break; | ||
910 | - default: | ||
911 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
912 | - break; | ||
913 | - } | ||
914 | - shift = type >> 3; | ||
915 | - | ||
916 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
917 | - rpl = new_cs & 3; | ||
918 | - if (dpl < cpl || dpl < rpl) | ||
919 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
920 | - /* check valid bit */ | ||
921 | - if (!(e2 & DESC_P_MASK)) | ||
922 | - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); | ||
923 | - selector = e1 >> 16; | ||
924 | - offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); | ||
925 | - if ((selector & 0xfffc) == 0) | ||
926 | - raise_exception_err(EXCP0D_GPF, 0); | ||
927 | - | ||
928 | - if (load_segment(&e1, &e2, selector) != 0) | ||
929 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
930 | - if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) | ||
931 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
932 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
933 | - if (dpl > cpl) | ||
934 | - raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | ||
935 | - if (!(e2 & DESC_P_MASK)) | ||
936 | - raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | ||
937 | - | ||
938 | - if (!(e2 & DESC_C_MASK) && dpl < cpl) { | ||
939 | - /* to inner priviledge */ | ||
940 | - get_ss_esp_from_tss(&ss, &sp, dpl); | ||
941 | - if ((ss & 0xfffc) == 0) | ||
942 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
943 | - if ((ss & 3) != dpl) | ||
944 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
945 | - if (load_segment(&ss_e1, &ss_e2, ss) != 0) | ||
946 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
947 | - ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; | ||
948 | - if (ss_dpl != dpl) | ||
949 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
950 | - if (!(ss_e2 & DESC_S_MASK) || | ||
951 | - (ss_e2 & DESC_CS_MASK) || | ||
952 | - !(ss_e2 & DESC_W_MASK)) | ||
953 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
954 | - if (!(ss_e2 & DESC_P_MASK)) | ||
955 | - raise_exception_err(EXCP0A_TSS, ss & 0xfffc); | ||
956 | - | ||
957 | - param_count = e2 & 0x1f; | ||
958 | - push_size = ((param_count * 2) + 8) << shift; | ||
959 | - | ||
960 | - old_esp = ESP; | ||
961 | - old_ss = env->segs[R_SS].selector; | ||
962 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
963 | - old_esp &= 0xffff; | ||
964 | - old_ssp = env->segs[R_SS].base + old_esp; | ||
965 | - | ||
966 | - /* XXX: from this point not restartable */ | ||
967 | - ss = (ss & ~3) | dpl; | ||
968 | - cpu_x86_load_seg_cache(env, R_SS, ss, | ||
969 | - get_seg_base(ss_e1, ss_e2), | ||
970 | - get_seg_limit(ss_e1, ss_e2), | ||
971 | - ss_e2); | ||
972 | - | ||
973 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
974 | - sp &= 0xffff; | ||
975 | - ssp = env->segs[R_SS].base + sp; | ||
976 | - if (shift) { | ||
977 | - ssp -= 4; | ||
978 | - stl(ssp, old_ss); | ||
979 | - ssp -= 4; | ||
980 | - stl(ssp, old_esp); | ||
981 | - ssp -= 4 * param_count; | ||
982 | - for(i = 0; i < param_count; i++) { | ||
983 | - val = ldl(old_ssp + i * 4); | ||
984 | - stl(ssp + i * 4, val); | ||
985 | - } | ||
986 | - } else { | ||
987 | - ssp -= 2; | ||
988 | - stw(ssp, old_ss); | ||
989 | - ssp -= 2; | ||
990 | - stw(ssp, old_esp); | ||
991 | - ssp -= 2 * param_count; | ||
992 | - for(i = 0; i < param_count; i++) { | ||
993 | - val = lduw(old_ssp + i * 2); | ||
994 | - stw(ssp + i * 2, val); | ||
995 | - } | ||
996 | - } | ||
997 | - } else { | ||
998 | - /* to same priviledge */ | ||
999 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
1000 | - sp &= 0xffff; | ||
1001 | - ssp = env->segs[R_SS].base + sp; | ||
1002 | - push_size = (4 << shift); | ||
1003 | - } | ||
1004 | - | ||
1005 | - if (shift) { | ||
1006 | - ssp -= 4; | ||
1007 | - stl(ssp, env->segs[R_CS].selector); | ||
1008 | - ssp -= 4; | ||
1009 | - stl(ssp, next_eip); | ||
1010 | - } else { | ||
1011 | - ssp -= 2; | ||
1012 | - stw(ssp, env->segs[R_CS].selector); | ||
1013 | - ssp -= 2; | ||
1014 | - stw(ssp, next_eip); | ||
1015 | - } | ||
1016 | - | ||
1017 | - sp -= push_size; | ||
1018 | - selector = (selector & ~3) | dpl; | ||
1019 | - cpu_x86_load_seg_cache(env, R_CS, selector, | ||
1020 | - get_seg_base(e1, e2), | ||
1021 | - get_seg_limit(e1, e2), | ||
1022 | - e2); | ||
1023 | - cpu_x86_set_cpl(env, dpl); | ||
1024 | - | ||
1025 | - /* from this point, not restartable if same priviledge */ | ||
1026 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
1027 | - ESP = (ESP & 0xffff0000) | (sp & 0xffff); | ||
1028 | - else | ||
1029 | - ESP = sp; | ||
1030 | - EIP = offset; | ||
1031 | - } | ||
1032 | -} | ||
1033 | - | ||
1034 | -/* real mode iret */ | ||
1035 | -void helper_iret_real(int shift) | ||
1036 | -{ | ||
1037 | - uint32_t sp, new_cs, new_eip, new_eflags, new_esp; | ||
1038 | - uint8_t *ssp; | ||
1039 | - int eflags_mask; | ||
1040 | - | ||
1041 | - sp = ESP & 0xffff; | ||
1042 | - ssp = env->segs[R_SS].base + sp; | ||
1043 | - if (shift == 1) { | ||
1044 | - /* 32 bits */ | ||
1045 | - new_eflags = ldl(ssp + 8); | ||
1046 | - new_cs = ldl(ssp + 4) & 0xffff; | ||
1047 | - new_eip = ldl(ssp) & 0xffff; | ||
1048 | - } else { | ||
1049 | - /* 16 bits */ | ||
1050 | - new_eflags = lduw(ssp + 4); | ||
1051 | - new_cs = lduw(ssp + 2); | ||
1052 | - new_eip = lduw(ssp); | ||
1053 | - } | ||
1054 | - new_esp = sp + (6 << shift); | ||
1055 | - ESP = (ESP & 0xffff0000) | | ||
1056 | - (new_esp & 0xffff); | ||
1057 | - load_seg_vm(R_CS, new_cs); | ||
1058 | - env->eip = new_eip; | ||
1059 | - eflags_mask = FL_UPDATE_CPL0_MASK; | ||
1060 | - if (shift == 0) | ||
1061 | - eflags_mask &= 0xffff; | ||
1062 | - load_eflags(new_eflags, eflags_mask); | ||
1063 | -} | ||
1064 | - | ||
1065 | -/* protected mode iret */ | ||
1066 | -static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
1067 | -{ | ||
1068 | - uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss; | ||
1069 | - uint32_t new_es, new_ds, new_fs, new_gs; | ||
1070 | - uint32_t e1, e2, ss_e1, ss_e2; | ||
1071 | - int cpl, dpl, rpl, eflags_mask; | ||
1072 | - uint8_t *ssp; | ||
1073 | - | ||
1074 | - sp = ESP; | ||
1075 | - if (!(env->segs[R_SS].flags & DESC_B_MASK)) | ||
1076 | - sp &= 0xffff; | ||
1077 | - ssp = env->segs[R_SS].base + sp; | ||
1078 | - if (shift == 1) { | ||
1079 | - /* 32 bits */ | ||
1080 | - if (is_iret) | ||
1081 | - new_eflags = ldl(ssp + 8); | ||
1082 | - new_cs = ldl(ssp + 4) & 0xffff; | ||
1083 | - new_eip = ldl(ssp); | ||
1084 | - if (is_iret && (new_eflags & VM_MASK)) | ||
1085 | - goto return_to_vm86; | ||
1086 | - } else { | ||
1087 | - /* 16 bits */ | ||
1088 | - if (is_iret) | ||
1089 | - new_eflags = lduw(ssp + 4); | ||
1090 | - new_cs = lduw(ssp + 2); | ||
1091 | - new_eip = lduw(ssp); | ||
1092 | - } | ||
1093 | - if ((new_cs & 0xfffc) == 0) | ||
1094 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1095 | - if (load_segment(&e1, &e2, new_cs) != 0) | ||
1096 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1097 | - if (!(e2 & DESC_S_MASK) || | ||
1098 | - !(e2 & DESC_CS_MASK)) | ||
1099 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1100 | - cpl = env->hflags & HF_CPL_MASK; | ||
1101 | - rpl = new_cs & 3; | ||
1102 | - if (rpl < cpl) | ||
1103 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1104 | - dpl = (e2 >> DESC_DPL_SHIFT) & 3; | ||
1105 | - if (e2 & DESC_CS_MASK) { | ||
1106 | - if (dpl > rpl) | ||
1107 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1108 | - } else { | ||
1109 | - if (dpl != rpl) | ||
1110 | - raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); | ||
1111 | - } | ||
1112 | - if (!(e2 & DESC_P_MASK)) | ||
1113 | - raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); | ||
1114 | - | ||
1115 | - if (rpl == cpl) { | ||
1116 | - /* return to same priledge level */ | ||
1117 | - cpu_x86_load_seg_cache(env, R_CS, new_cs, | ||
1118 | - get_seg_base(e1, e2), | ||
1119 | - get_seg_limit(e1, e2), | ||
1120 | - e2); | ||
1121 | - new_esp = sp + (4 << shift) + ((2 * is_iret) << shift) + addend; | ||
1122 | - } else { | ||
1123 | - /* return to different priviledge level */ | ||
1124 | - ssp += (4 << shift) + ((2 * is_iret) << shift) + addend; | ||
1125 | - if (shift == 1) { | ||
1126 | - /* 32 bits */ | ||
1127 | - new_esp = ldl(ssp); | ||
1128 | - new_ss = ldl(ssp + 4) & 0xffff; | ||
1129 | - } else { | ||
1130 | - /* 16 bits */ | ||
1131 | - new_esp = lduw(ssp); | ||
1132 | - new_ss = lduw(ssp + 2); | ||
1133 | - } | ||
1134 | - | ||
1135 | - if ((new_ss & 3) != rpl) | ||
1136 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | ||
1137 | - if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) | ||
1138 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | ||
1139 | - if (!(ss_e2 & DESC_S_MASK) || | ||
1140 | - (ss_e2 & DESC_CS_MASK) || | ||
1141 | - !(ss_e2 & DESC_W_MASK)) | ||
1142 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | ||
1143 | - dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; | ||
1144 | - if (dpl != rpl) | ||
1145 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | ||
1146 | - if (!(ss_e2 & DESC_P_MASK)) | ||
1147 | - raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc); | ||
1148 | - | ||
1149 | - cpu_x86_load_seg_cache(env, R_CS, new_cs, | ||
1150 | - get_seg_base(e1, e2), | ||
1151 | - get_seg_limit(e1, e2), | ||
1152 | - e2); | ||
1153 | - cpu_x86_load_seg_cache(env, R_SS, new_ss, | ||
1154 | - get_seg_base(ss_e1, ss_e2), | ||
1155 | - get_seg_limit(ss_e1, ss_e2), | ||
1156 | - ss_e2); | ||
1157 | - cpu_x86_set_cpl(env, rpl); | ||
1158 | - } | ||
1159 | - if (env->segs[R_SS].flags & DESC_B_MASK) | ||
1160 | - ESP = new_esp; | ||
1161 | - else | ||
1162 | - ESP = (ESP & 0xffff0000) | | ||
1163 | - (new_esp & 0xffff); | ||
1164 | - env->eip = new_eip; | ||
1165 | - if (is_iret) { | ||
1166 | - /* NOTE: 'cpl' can be different from the current CPL */ | ||
1167 | - if (cpl == 0) | ||
1168 | - eflags_mask = FL_UPDATE_CPL0_MASK; | ||
1169 | - else | ||
1170 | - eflags_mask = FL_UPDATE_MASK32; | ||
1171 | - if (shift == 0) | ||
1172 | - eflags_mask &= 0xffff; | ||
1173 | - load_eflags(new_eflags, eflags_mask); | ||
1174 | - } | ||
1175 | - return; | ||
1176 | - | ||
1177 | - return_to_vm86: | ||
1178 | - new_esp = ldl(ssp + 12); | ||
1179 | - new_ss = ldl(ssp + 16); | ||
1180 | - new_es = ldl(ssp + 20); | ||
1181 | - new_ds = ldl(ssp + 24); | ||
1182 | - new_fs = ldl(ssp + 28); | ||
1183 | - new_gs = ldl(ssp + 32); | ||
1184 | - | ||
1185 | - /* modify processor state */ | ||
1186 | - load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); | ||
1187 | - load_seg_vm(R_CS, new_cs); | ||
1188 | - cpu_x86_set_cpl(env, 3); | ||
1189 | - load_seg_vm(R_SS, new_ss); | ||
1190 | - load_seg_vm(R_ES, new_es); | ||
1191 | - load_seg_vm(R_DS, new_ds); | ||
1192 | - load_seg_vm(R_FS, new_fs); | ||
1193 | - load_seg_vm(R_GS, new_gs); | ||
1194 | - | ||
1195 | - env->eip = new_eip; | ||
1196 | - ESP = new_esp; | ||
1197 | -} | ||
1198 | - | ||
1199 | -void helper_iret_protected(int shift) | ||
1200 | -{ | ||
1201 | - helper_ret_protected(shift, 1, 0); | ||
1202 | -} | ||
1203 | - | ||
1204 | -void helper_lret_protected(int shift, int addend) | ||
1205 | -{ | ||
1206 | - helper_ret_protected(shift, 0, addend); | ||
1207 | -} | ||
1208 | - | ||
1209 | -void helper_movl_crN_T0(int reg) | ||
1210 | -{ | ||
1211 | - env->cr[reg] = T0; | ||
1212 | - switch(reg) { | ||
1213 | - case 0: | ||
1214 | - cpu_x86_update_cr0(env); | ||
1215 | - break; | ||
1216 | - case 3: | ||
1217 | - cpu_x86_update_cr3(env); | ||
1218 | - break; | ||
1219 | - } | ||
1220 | -} | ||
1221 | - | ||
1222 | -/* XXX: do more */ | ||
1223 | -void helper_movl_drN_T0(int reg) | ||
1224 | -{ | ||
1225 | - env->dr[reg] = T0; | ||
1226 | -} | ||
1227 | - | ||
1228 | -void helper_invlpg(unsigned int addr) | ||
1229 | -{ | ||
1230 | - cpu_x86_flush_tlb(env, addr); | ||
1231 | -} | ||
1232 | - | ||
1233 | -/* rdtsc */ | ||
1234 | -#ifndef __i386__ | ||
1235 | -uint64_t emu_time; | ||
1236 | -#endif | ||
1237 | - | ||
1238 | -void helper_rdtsc(void) | ||
1239 | -{ | ||
1240 | - uint64_t val; | ||
1241 | -#ifdef __i386__ | ||
1242 | - asm("rdtsc" : "=A" (val)); | ||
1243 | -#else | ||
1244 | - /* better than nothing: the time increases */ | ||
1245 | - val = emu_time++; | ||
1246 | -#endif | ||
1247 | - EAX = val; | ||
1248 | - EDX = val >> 32; | ||
1249 | -} | ||
1250 | - | ||
1251 | -void helper_wrmsr(void) | ||
1252 | -{ | ||
1253 | - switch(ECX) { | ||
1254 | - case MSR_IA32_SYSENTER_CS: | ||
1255 | - env->sysenter_cs = EAX & 0xffff; | ||
1256 | - break; | ||
1257 | - case MSR_IA32_SYSENTER_ESP: | ||
1258 | - env->sysenter_esp = EAX; | ||
1259 | - break; | ||
1260 | - case MSR_IA32_SYSENTER_EIP: | ||
1261 | - env->sysenter_eip = EAX; | ||
1262 | - break; | ||
1263 | - default: | ||
1264 | - /* XXX: exception ? */ | ||
1265 | - break; | ||
1266 | - } | ||
1267 | -} | ||
1268 | - | ||
1269 | -void helper_rdmsr(void) | ||
1270 | -{ | ||
1271 | - switch(ECX) { | ||
1272 | - case MSR_IA32_SYSENTER_CS: | ||
1273 | - EAX = env->sysenter_cs; | ||
1274 | - EDX = 0; | ||
1275 | - break; | ||
1276 | - case MSR_IA32_SYSENTER_ESP: | ||
1277 | - EAX = env->sysenter_esp; | ||
1278 | - EDX = 0; | ||
1279 | - break; | ||
1280 | - case MSR_IA32_SYSENTER_EIP: | ||
1281 | - EAX = env->sysenter_eip; | ||
1282 | - EDX = 0; | ||
1283 | - break; | ||
1284 | - default: | ||
1285 | - /* XXX: exception ? */ | ||
1286 | - break; | ||
1287 | - } | ||
1288 | -} | ||
1289 | - | ||
1290 | -void helper_lsl(void) | ||
1291 | -{ | ||
1292 | - unsigned int selector, limit; | ||
1293 | - uint32_t e1, e2; | ||
1294 | - | ||
1295 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | ||
1296 | - selector = T0 & 0xffff; | ||
1297 | - if (load_segment(&e1, &e2, selector) != 0) | ||
1298 | - return; | ||
1299 | - limit = (e1 & 0xffff) | (e2 & 0x000f0000); | ||
1300 | - if (e2 & (1 << 23)) | ||
1301 | - limit = (limit << 12) | 0xfff; | ||
1302 | - T1 = limit; | ||
1303 | - CC_SRC |= CC_Z; | ||
1304 | -} | ||
1305 | - | ||
1306 | -void helper_lar(void) | ||
1307 | -{ | ||
1308 | - unsigned int selector; | ||
1309 | - uint32_t e1, e2; | ||
1310 | - | ||
1311 | - CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; | ||
1312 | - selector = T0 & 0xffff; | ||
1313 | - if (load_segment(&e1, &e2, selector) != 0) | ||
1314 | - return; | ||
1315 | - T1 = e2 & 0x00f0ff00; | ||
1316 | - CC_SRC |= CC_Z; | ||
1317 | -} | ||
1318 | - | ||
1319 | -/* FPU helpers */ | ||
1320 | - | ||
1321 | -#ifndef USE_X86LDOUBLE | ||
1322 | -void helper_fldt_ST0_A0(void) | ||
1323 | -{ | ||
1324 | - int new_fpstt; | ||
1325 | - new_fpstt = (env->fpstt - 1) & 7; | ||
1326 | - env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0); | ||
1327 | - env->fpstt = new_fpstt; | ||
1328 | - env->fptags[new_fpstt] = 0; /* validate stack entry */ | ||
1329 | -} | ||
1330 | - | ||
1331 | -void helper_fstt_ST0_A0(void) | ||
1332 | -{ | ||
1333 | - helper_fstt(ST0, (uint8_t *)A0); | ||
1334 | -} | ||
1335 | -#endif | ||
1336 | - | ||
1337 | -/* BCD ops */ | ||
1338 | - | ||
1339 | -#define MUL10(iv) ( iv + iv + (iv << 3) ) | ||
1340 | - | ||
1341 | -void helper_fbld_ST0_A0(void) | ||
1342 | -{ | ||
1343 | - CPU86_LDouble tmp; | ||
1344 | - uint64_t val; | ||
1345 | - unsigned int v; | ||
1346 | - int i; | ||
1347 | - | ||
1348 | - val = 0; | ||
1349 | - for(i = 8; i >= 0; i--) { | ||
1350 | - v = ldub((uint8_t *)A0 + i); | ||
1351 | - val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); | ||
1352 | - } | ||
1353 | - tmp = val; | ||
1354 | - if (ldub((uint8_t *)A0 + 9) & 0x80) | ||
1355 | - tmp = -tmp; | ||
1356 | - fpush(); | ||
1357 | - ST0 = tmp; | ||
1358 | -} | ||
1359 | - | ||
1360 | -void helper_fbst_ST0_A0(void) | ||
1361 | -{ | ||
1362 | - CPU86_LDouble tmp; | ||
1363 | - int v; | ||
1364 | - uint8_t *mem_ref, *mem_end; | ||
1365 | - int64_t val; | ||
1366 | - | ||
1367 | - tmp = rint(ST0); | ||
1368 | - val = (int64_t)tmp; | ||
1369 | - mem_ref = (uint8_t *)A0; | ||
1370 | - mem_end = mem_ref + 9; | ||
1371 | - if (val < 0) { | ||
1372 | - stb(mem_end, 0x80); | ||
1373 | - val = -val; | ||
1374 | - } else { | ||
1375 | - stb(mem_end, 0x00); | ||
1376 | - } | ||
1377 | - while (mem_ref < mem_end) { | ||
1378 | - if (val == 0) | ||
1379 | - break; | ||
1380 | - v = val % 100; | ||
1381 | - val = val / 100; | ||
1382 | - v = ((v / 10) << 4) | (v % 10); | ||
1383 | - stb(mem_ref++, v); | ||
1384 | - } | ||
1385 | - while (mem_ref < mem_end) { | ||
1386 | - stb(mem_ref++, 0); | ||
1387 | - } | ||
1388 | -} | ||
1389 | - | ||
1390 | -void helper_f2xm1(void) | ||
1391 | -{ | ||
1392 | - ST0 = pow(2.0,ST0) - 1.0; | ||
1393 | -} | ||
1394 | - | ||
1395 | -void helper_fyl2x(void) | ||
1396 | -{ | ||
1397 | - CPU86_LDouble fptemp; | ||
1398 | - | ||
1399 | - fptemp = ST0; | ||
1400 | - if (fptemp>0.0){ | ||
1401 | - fptemp = log(fptemp)/log(2.0); /* log2(ST) */ | ||
1402 | - ST1 *= fptemp; | ||
1403 | - fpop(); | ||
1404 | - } else { | ||
1405 | - env->fpus &= (~0x4700); | ||
1406 | - env->fpus |= 0x400; | ||
1407 | - } | ||
1408 | -} | ||
1409 | - | ||
1410 | -void helper_fptan(void) | ||
1411 | -{ | ||
1412 | - CPU86_LDouble fptemp; | ||
1413 | - | ||
1414 | - fptemp = ST0; | ||
1415 | - if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
1416 | - env->fpus |= 0x400; | ||
1417 | - } else { | ||
1418 | - ST0 = tan(fptemp); | ||
1419 | - fpush(); | ||
1420 | - ST0 = 1.0; | ||
1421 | - env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
1422 | - /* the above code is for |arg| < 2**52 only */ | ||
1423 | - } | ||
1424 | -} | ||
1425 | - | ||
1426 | -void helper_fpatan(void) | ||
1427 | -{ | ||
1428 | - CPU86_LDouble fptemp, fpsrcop; | ||
1429 | - | ||
1430 | - fpsrcop = ST1; | ||
1431 | - fptemp = ST0; | ||
1432 | - ST1 = atan2(fpsrcop,fptemp); | ||
1433 | - fpop(); | ||
1434 | -} | ||
1435 | - | ||
1436 | -void helper_fxtract(void) | ||
1437 | -{ | ||
1438 | - CPU86_LDoubleU temp; | ||
1439 | - unsigned int expdif; | ||
1440 | - | ||
1441 | - temp.d = ST0; | ||
1442 | - expdif = EXPD(temp) - EXPBIAS; | ||
1443 | - /*DP exponent bias*/ | ||
1444 | - ST0 = expdif; | ||
1445 | - fpush(); | ||
1446 | - BIASEXPONENT(temp); | ||
1447 | - ST0 = temp.d; | ||
1448 | -} | ||
1449 | - | ||
1450 | -void helper_fprem1(void) | ||
1451 | -{ | ||
1452 | - CPU86_LDouble dblq, fpsrcop, fptemp; | ||
1453 | - CPU86_LDoubleU fpsrcop1, fptemp1; | ||
1454 | - int expdif; | ||
1455 | - int q; | ||
1456 | - | ||
1457 | - fpsrcop = ST0; | ||
1458 | - fptemp = ST1; | ||
1459 | - fpsrcop1.d = fpsrcop; | ||
1460 | - fptemp1.d = fptemp; | ||
1461 | - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); | ||
1462 | - if (expdif < 53) { | ||
1463 | - dblq = fpsrcop / fptemp; | ||
1464 | - dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); | ||
1465 | - ST0 = fpsrcop - fptemp*dblq; | ||
1466 | - q = (int)dblq; /* cutting off top bits is assumed here */ | ||
1467 | - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
1468 | - /* (C0,C1,C3) <-- (q2,q1,q0) */ | ||
1469 | - env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ | ||
1470 | - env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ | ||
1471 | - env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ | ||
1472 | - } else { | ||
1473 | - env->fpus |= 0x400; /* C2 <-- 1 */ | ||
1474 | - fptemp = pow(2.0, expdif-50); | ||
1475 | - fpsrcop = (ST0 / ST1) / fptemp; | ||
1476 | - /* fpsrcop = integer obtained by rounding to the nearest */ | ||
1477 | - fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)? | ||
1478 | - floor(fpsrcop): ceil(fpsrcop); | ||
1479 | - ST0 -= (ST1 * fpsrcop * fptemp); | ||
1480 | - } | ||
1481 | -} | ||
1482 | - | ||
1483 | -void helper_fprem(void) | ||
1484 | -{ | ||
1485 | - CPU86_LDouble dblq, fpsrcop, fptemp; | ||
1486 | - CPU86_LDoubleU fpsrcop1, fptemp1; | ||
1487 | - int expdif; | ||
1488 | - int q; | ||
1489 | - | ||
1490 | - fpsrcop = ST0; | ||
1491 | - fptemp = ST1; | ||
1492 | - fpsrcop1.d = fpsrcop; | ||
1493 | - fptemp1.d = fptemp; | ||
1494 | - expdif = EXPD(fpsrcop1) - EXPD(fptemp1); | ||
1495 | - if ( expdif < 53 ) { | ||
1496 | - dblq = fpsrcop / fptemp; | ||
1497 | - dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); | ||
1498 | - ST0 = fpsrcop - fptemp*dblq; | ||
1499 | - q = (int)dblq; /* cutting off top bits is assumed here */ | ||
1500 | - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
1501 | - /* (C0,C1,C3) <-- (q2,q1,q0) */ | ||
1502 | - env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ | ||
1503 | - env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ | ||
1504 | - env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ | ||
1505 | - } else { | ||
1506 | - env->fpus |= 0x400; /* C2 <-- 1 */ | ||
1507 | - fptemp = pow(2.0, expdif-50); | ||
1508 | - fpsrcop = (ST0 / ST1) / fptemp; | ||
1509 | - /* fpsrcop = integer obtained by chopping */ | ||
1510 | - fpsrcop = (fpsrcop < 0.0)? | ||
1511 | - -(floor(fabs(fpsrcop))): floor(fpsrcop); | ||
1512 | - ST0 -= (ST1 * fpsrcop * fptemp); | ||
1513 | - } | ||
1514 | -} | ||
1515 | - | ||
1516 | -void helper_fyl2xp1(void) | ||
1517 | -{ | ||
1518 | - CPU86_LDouble fptemp; | ||
1519 | - | ||
1520 | - fptemp = ST0; | ||
1521 | - if ((fptemp+1.0)>0.0) { | ||
1522 | - fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */ | ||
1523 | - ST1 *= fptemp; | ||
1524 | - fpop(); | ||
1525 | - } else { | ||
1526 | - env->fpus &= (~0x4700); | ||
1527 | - env->fpus |= 0x400; | ||
1528 | - } | ||
1529 | -} | ||
1530 | - | ||
1531 | -void helper_fsqrt(void) | ||
1532 | -{ | ||
1533 | - CPU86_LDouble fptemp; | ||
1534 | - | ||
1535 | - fptemp = ST0; | ||
1536 | - if (fptemp<0.0) { | ||
1537 | - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
1538 | - env->fpus |= 0x400; | ||
1539 | - } | ||
1540 | - ST0 = sqrt(fptemp); | ||
1541 | -} | ||
1542 | - | ||
1543 | -void helper_fsincos(void) | ||
1544 | -{ | ||
1545 | - CPU86_LDouble fptemp; | ||
1546 | - | ||
1547 | - fptemp = ST0; | ||
1548 | - if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
1549 | - env->fpus |= 0x400; | ||
1550 | - } else { | ||
1551 | - ST0 = sin(fptemp); | ||
1552 | - fpush(); | ||
1553 | - ST0 = cos(fptemp); | ||
1554 | - env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
1555 | - /* the above code is for |arg| < 2**63 only */ | ||
1556 | - } | ||
1557 | -} | ||
1558 | - | ||
1559 | -void helper_frndint(void) | ||
1560 | -{ | ||
1561 | - CPU86_LDouble a; | ||
1562 | - | ||
1563 | - a = ST0; | ||
1564 | -#ifdef __arm__ | ||
1565 | - switch(env->fpuc & RC_MASK) { | ||
1566 | - default: | ||
1567 | - case RC_NEAR: | ||
1568 | - asm("rndd %0, %1" : "=f" (a) : "f"(a)); | ||
1569 | - break; | ||
1570 | - case RC_DOWN: | ||
1571 | - asm("rnddm %0, %1" : "=f" (a) : "f"(a)); | ||
1572 | - break; | ||
1573 | - case RC_UP: | ||
1574 | - asm("rnddp %0, %1" : "=f" (a) : "f"(a)); | ||
1575 | - break; | ||
1576 | - case RC_CHOP: | ||
1577 | - asm("rnddz %0, %1" : "=f" (a) : "f"(a)); | ||
1578 | - break; | ||
1579 | - } | ||
1580 | -#else | ||
1581 | - a = rint(a); | ||
1582 | -#endif | ||
1583 | - ST0 = a; | ||
1584 | -} | ||
1585 | - | ||
1586 | -void helper_fscale(void) | ||
1587 | -{ | ||
1588 | - CPU86_LDouble fpsrcop, fptemp; | ||
1589 | - | ||
1590 | - fpsrcop = 2.0; | ||
1591 | - fptemp = pow(fpsrcop,ST1); | ||
1592 | - ST0 *= fptemp; | ||
1593 | -} | ||
1594 | - | ||
1595 | -void helper_fsin(void) | ||
1596 | -{ | ||
1597 | - CPU86_LDouble fptemp; | ||
1598 | - | ||
1599 | - fptemp = ST0; | ||
1600 | - if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
1601 | - env->fpus |= 0x400; | ||
1602 | - } else { | ||
1603 | - ST0 = sin(fptemp); | ||
1604 | - env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
1605 | - /* the above code is for |arg| < 2**53 only */ | ||
1606 | - } | ||
1607 | -} | ||
1608 | - | ||
1609 | -void helper_fcos(void) | ||
1610 | -{ | ||
1611 | - CPU86_LDouble fptemp; | ||
1612 | - | ||
1613 | - fptemp = ST0; | ||
1614 | - if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
1615 | - env->fpus |= 0x400; | ||
1616 | - } else { | ||
1617 | - ST0 = cos(fptemp); | ||
1618 | - env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
1619 | - /* the above code is for |arg5 < 2**63 only */ | ||
1620 | - } | ||
1621 | -} | ||
1622 | - | ||
1623 | -void helper_fxam_ST0(void) | ||
1624 | -{ | ||
1625 | - CPU86_LDoubleU temp; | ||
1626 | - int expdif; | ||
1627 | - | ||
1628 | - temp.d = ST0; | ||
1629 | - | ||
1630 | - env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
1631 | - if (SIGND(temp)) | ||
1632 | - env->fpus |= 0x200; /* C1 <-- 1 */ | ||
1633 | - | ||
1634 | - expdif = EXPD(temp); | ||
1635 | - if (expdif == MAXEXPD) { | ||
1636 | - if (MANTD(temp) == 0) | ||
1637 | - env->fpus |= 0x500 /*Infinity*/; | ||
1638 | - else | ||
1639 | - env->fpus |= 0x100 /*NaN*/; | ||
1640 | - } else if (expdif == 0) { | ||
1641 | - if (MANTD(temp) == 0) | ||
1642 | - env->fpus |= 0x4000 /*Zero*/; | ||
1643 | - else | ||
1644 | - env->fpus |= 0x4400 /*Denormal*/; | ||
1645 | - } else { | ||
1646 | - env->fpus |= 0x400; | ||
1647 | - } | ||
1648 | -} | ||
1649 | - | ||
1650 | -void helper_fstenv(uint8_t *ptr, int data32) | ||
1651 | -{ | ||
1652 | - int fpus, fptag, exp, i; | ||
1653 | - uint64_t mant; | ||
1654 | - CPU86_LDoubleU tmp; | ||
1655 | - | ||
1656 | - fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; | ||
1657 | - fptag = 0; | ||
1658 | - for (i=7; i>=0; i--) { | ||
1659 | - fptag <<= 2; | ||
1660 | - if (env->fptags[i]) { | ||
1661 | - fptag |= 3; | ||
1662 | - } else { | ||
1663 | - tmp.d = env->fpregs[i]; | ||
1664 | - exp = EXPD(tmp); | ||
1665 | - mant = MANTD(tmp); | ||
1666 | - if (exp == 0 && mant == 0) { | ||
1667 | - /* zero */ | ||
1668 | - fptag |= 1; | ||
1669 | - } else if (exp == 0 || exp == MAXEXPD | ||
1670 | -#ifdef USE_X86LDOUBLE | ||
1671 | - || (mant & (1LL << 63)) == 0 | ||
1672 | -#endif | ||
1673 | - ) { | ||
1674 | - /* NaNs, infinity, denormal */ | ||
1675 | - fptag |= 2; | ||
1676 | - } | ||
1677 | - } | ||
1678 | - } | ||
1679 | - if (data32) { | ||
1680 | - /* 32 bit */ | ||
1681 | - stl(ptr, env->fpuc); | ||
1682 | - stl(ptr + 4, fpus); | ||
1683 | - stl(ptr + 8, fptag); | ||
1684 | - stl(ptr + 12, 0); | ||
1685 | - stl(ptr + 16, 0); | ||
1686 | - stl(ptr + 20, 0); | ||
1687 | - stl(ptr + 24, 0); | ||
1688 | - } else { | ||
1689 | - /* 16 bit */ | ||
1690 | - stw(ptr, env->fpuc); | ||
1691 | - stw(ptr + 2, fpus); | ||
1692 | - stw(ptr + 4, fptag); | ||
1693 | - stw(ptr + 6, 0); | ||
1694 | - stw(ptr + 8, 0); | ||
1695 | - stw(ptr + 10, 0); | ||
1696 | - stw(ptr + 12, 0); | ||
1697 | - } | ||
1698 | -} | ||
1699 | - | ||
1700 | -void helper_fldenv(uint8_t *ptr, int data32) | ||
1701 | -{ | ||
1702 | - int i, fpus, fptag; | ||
1703 | - | ||
1704 | - if (data32) { | ||
1705 | - env->fpuc = lduw(ptr); | ||
1706 | - fpus = lduw(ptr + 4); | ||
1707 | - fptag = lduw(ptr + 8); | ||
1708 | - } | ||
1709 | - else { | ||
1710 | - env->fpuc = lduw(ptr); | ||
1711 | - fpus = lduw(ptr + 2); | ||
1712 | - fptag = lduw(ptr + 4); | ||
1713 | - } | ||
1714 | - env->fpstt = (fpus >> 11) & 7; | ||
1715 | - env->fpus = fpus & ~0x3800; | ||
1716 | - for(i = 0;i < 7; i++) { | ||
1717 | - env->fptags[i] = ((fptag & 3) == 3); | ||
1718 | - fptag >>= 2; | ||
1719 | - } | ||
1720 | -} | ||
1721 | - | ||
1722 | -void helper_fsave(uint8_t *ptr, int data32) | ||
1723 | -{ | ||
1724 | - CPU86_LDouble tmp; | ||
1725 | - int i; | ||
1726 | - | ||
1727 | - helper_fstenv(ptr, data32); | ||
1728 | - | ||
1729 | - ptr += (14 << data32); | ||
1730 | - for(i = 0;i < 8; i++) { | ||
1731 | - tmp = ST(i); | ||
1732 | -#ifdef USE_X86LDOUBLE | ||
1733 | - *(long double *)ptr = tmp; | ||
1734 | -#else | ||
1735 | - helper_fstt(tmp, ptr); | ||
1736 | -#endif | ||
1737 | - ptr += 10; | ||
1738 | - } | ||
1739 | - | ||
1740 | - /* fninit */ | ||
1741 | - env->fpus = 0; | ||
1742 | - env->fpstt = 0; | ||
1743 | - env->fpuc = 0x37f; | ||
1744 | - env->fptags[0] = 1; | ||
1745 | - env->fptags[1] = 1; | ||
1746 | - env->fptags[2] = 1; | ||
1747 | - env->fptags[3] = 1; | ||
1748 | - env->fptags[4] = 1; | ||
1749 | - env->fptags[5] = 1; | ||
1750 | - env->fptags[6] = 1; | ||
1751 | - env->fptags[7] = 1; | ||
1752 | -} | ||
1753 | - | ||
1754 | -void helper_frstor(uint8_t *ptr, int data32) | ||
1755 | -{ | ||
1756 | - CPU86_LDouble tmp; | ||
1757 | - int i; | ||
1758 | - | ||
1759 | - helper_fldenv(ptr, data32); | ||
1760 | - ptr += (14 << data32); | ||
1761 | - | ||
1762 | - for(i = 0;i < 8; i++) { | ||
1763 | -#ifdef USE_X86LDOUBLE | ||
1764 | - tmp = *(long double *)ptr; | ||
1765 | -#else | ||
1766 | - tmp = helper_fldt(ptr); | ||
1767 | -#endif | ||
1768 | - ST(i) = tmp; | ||
1769 | - ptr += 10; | ||
1770 | - } | ||
1771 | -} | ||
1772 | - | ||
1773 | -#define SHIFT 0 | ||
1774 | -#include "softmmu_template.h" | ||
1775 | - | ||
1776 | -#define SHIFT 1 | ||
1777 | -#include "softmmu_template.h" | ||
1778 | - | ||
1779 | -#define SHIFT 2 | ||
1780 | -#include "softmmu_template.h" | ||
1781 | - | ||
1782 | -#define SHIFT 3 | ||
1783 | -#include "softmmu_template.h" | ||
1784 | - | ||
1785 | -/* try to fill the TLB and return an exception if error */ | ||
1786 | -void tlb_fill(unsigned long addr, int is_write, void *retaddr) | ||
1787 | -{ | ||
1788 | - TranslationBlock *tb; | ||
1789 | - int ret; | ||
1790 | - unsigned long pc; | ||
1791 | - ret = cpu_x86_handle_mmu_fault(env, addr, is_write); | ||
1792 | - if (ret) { | ||
1793 | - /* now we have a real cpu fault */ | ||
1794 | - pc = (unsigned long)retaddr; | ||
1795 | - tb = tb_find_pc(pc); | ||
1796 | - if (tb) { | ||
1797 | - /* the PC is inside the translated code. It means that we have | ||
1798 | - a virtual CPU fault */ | ||
1799 | - cpu_restore_state(tb, env, pc); | ||
1800 | - } | ||
1801 | - raise_exception_err(EXCP0E_PAGE, env->error_code); | ||
1802 | - } | ||
1803 | -} |
helper2-i386.c deleted
100644 → 0
1 | -/* | ||
2 | - * i386 helpers (without register variable usage) | ||
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 | -#include <stdarg.h> | ||
21 | -#include <stdlib.h> | ||
22 | -#include <stdio.h> | ||
23 | -#include <string.h> | ||
24 | -#include <inttypes.h> | ||
25 | -#include <signal.h> | ||
26 | -#include <assert.h> | ||
27 | -#include <sys/mman.h> | ||
28 | - | ||
29 | -#include "cpu-i386.h" | ||
30 | -#include "exec.h" | ||
31 | - | ||
32 | -//#define DEBUG_MMU | ||
33 | - | ||
34 | -CPUX86State *cpu_x86_init(void) | ||
35 | -{ | ||
36 | - CPUX86State *env; | ||
37 | - int i; | ||
38 | - static int inited; | ||
39 | - | ||
40 | - cpu_exec_init(); | ||
41 | - | ||
42 | - env = malloc(sizeof(CPUX86State)); | ||
43 | - if (!env) | ||
44 | - return NULL; | ||
45 | - memset(env, 0, sizeof(CPUX86State)); | ||
46 | - /* basic FPU init */ | ||
47 | - for(i = 0;i < 8; i++) | ||
48 | - env->fptags[i] = 1; | ||
49 | - env->fpuc = 0x37f; | ||
50 | - /* flags setup : we activate the IRQs by default as in user mode */ | ||
51 | - env->eflags = 0x2 | IF_MASK; | ||
52 | - | ||
53 | - tlb_flush(env); | ||
54 | -#ifdef CONFIG_SOFTMMU | ||
55 | - env->hflags |= HF_SOFTMMU_MASK; | ||
56 | -#endif | ||
57 | - /* init various static tables */ | ||
58 | - if (!inited) { | ||
59 | - inited = 1; | ||
60 | - optimize_flags_init(); | ||
61 | - } | ||
62 | - return env; | ||
63 | -} | ||
64 | - | ||
65 | -void cpu_x86_close(CPUX86State *env) | ||
66 | -{ | ||
67 | - free(env); | ||
68 | -} | ||
69 | - | ||
70 | -/***********************************************************/ | ||
71 | -/* x86 debug */ | ||
72 | - | ||
73 | -static const char *cc_op_str[] = { | ||
74 | - "DYNAMIC", | ||
75 | - "EFLAGS", | ||
76 | - "MUL", | ||
77 | - "ADDB", | ||
78 | - "ADDW", | ||
79 | - "ADDL", | ||
80 | - "ADCB", | ||
81 | - "ADCW", | ||
82 | - "ADCL", | ||
83 | - "SUBB", | ||
84 | - "SUBW", | ||
85 | - "SUBL", | ||
86 | - "SBBB", | ||
87 | - "SBBW", | ||
88 | - "SBBL", | ||
89 | - "LOGICB", | ||
90 | - "LOGICW", | ||
91 | - "LOGICL", | ||
92 | - "INCB", | ||
93 | - "INCW", | ||
94 | - "INCL", | ||
95 | - "DECB", | ||
96 | - "DECW", | ||
97 | - "DECL", | ||
98 | - "SHLB", | ||
99 | - "SHLW", | ||
100 | - "SHLL", | ||
101 | - "SARB", | ||
102 | - "SARW", | ||
103 | - "SARL", | ||
104 | -}; | ||
105 | - | ||
106 | -void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) | ||
107 | -{ | ||
108 | - int eflags; | ||
109 | - char cc_op_name[32]; | ||
110 | - | ||
111 | - eflags = env->eflags; | ||
112 | - fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" | ||
113 | - "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" | ||
114 | - "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n", | ||
115 | - env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], | ||
116 | - env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], | ||
117 | - env->eip, eflags, | ||
118 | - eflags & DF_MASK ? 'D' : '-', | ||
119 | - eflags & CC_O ? 'O' : '-', | ||
120 | - eflags & CC_S ? 'S' : '-', | ||
121 | - eflags & CC_Z ? 'Z' : '-', | ||
122 | - eflags & CC_A ? 'A' : '-', | ||
123 | - eflags & CC_P ? 'P' : '-', | ||
124 | - eflags & CC_C ? 'C' : '-'); | ||
125 | - fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", | ||
126 | - env->segs[R_CS].selector, | ||
127 | - env->segs[R_SS].selector, | ||
128 | - env->segs[R_DS].selector, | ||
129 | - env->segs[R_ES].selector, | ||
130 | - env->segs[R_FS].selector, | ||
131 | - env->segs[R_GS].selector); | ||
132 | - if (flags & X86_DUMP_CCOP) { | ||
133 | - if ((unsigned)env->cc_op < CC_OP_NB) | ||
134 | - strcpy(cc_op_name, cc_op_str[env->cc_op]); | ||
135 | - else | ||
136 | - snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); | ||
137 | - fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", | ||
138 | - env->cc_src, env->cc_dst, cc_op_name); | ||
139 | - } | ||
140 | - if (flags & X86_DUMP_FPU) { | ||
141 | - fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", | ||
142 | - (double)env->fpregs[0], | ||
143 | - (double)env->fpregs[1], | ||
144 | - (double)env->fpregs[2], | ||
145 | - (double)env->fpregs[3]); | ||
146 | - fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", | ||
147 | - (double)env->fpregs[4], | ||
148 | - (double)env->fpregs[5], | ||
149 | - (double)env->fpregs[7], | ||
150 | - (double)env->fpregs[8]); | ||
151 | - } | ||
152 | -} | ||
153 | - | ||
154 | -/***********************************************************/ | ||
155 | -/* x86 mmu */ | ||
156 | -/* XXX: add PGE support */ | ||
157 | - | ||
158 | -/* called when cr3 or PG bit are modified */ | ||
159 | -static int last_pg_state = -1; | ||
160 | -static int last_pe_state = 0; | ||
161 | -int phys_ram_size; | ||
162 | -int phys_ram_fd; | ||
163 | -uint8_t *phys_ram_base; | ||
164 | - | ||
165 | -void cpu_x86_update_cr0(CPUX86State *env) | ||
166 | -{ | ||
167 | - int pg_state, pe_state; | ||
168 | - | ||
169 | -#ifdef DEBUG_MMU | ||
170 | - printf("CR0 update: CR0=0x%08x\n", env->cr[0]); | ||
171 | -#endif | ||
172 | - pg_state = env->cr[0] & CR0_PG_MASK; | ||
173 | - if (pg_state != last_pg_state) { | ||
174 | - page_unmap(); | ||
175 | - tlb_flush(env); | ||
176 | - last_pg_state = pg_state; | ||
177 | - } | ||
178 | - pe_state = env->cr[0] & CR0_PE_MASK; | ||
179 | - if (last_pe_state != pe_state) { | ||
180 | - tb_flush(); | ||
181 | - last_pe_state = pe_state; | ||
182 | - } | ||
183 | -} | ||
184 | - | ||
185 | -void cpu_x86_update_cr3(CPUX86State *env) | ||
186 | -{ | ||
187 | - if (env->cr[0] & CR0_PG_MASK) { | ||
188 | -#if defined(DEBUG_MMU) | ||
189 | - printf("CR3 update: CR3=%08x\n", env->cr[3]); | ||
190 | -#endif | ||
191 | - page_unmap(); | ||
192 | - tlb_flush(env); | ||
193 | - } | ||
194 | -} | ||
195 | - | ||
196 | -void cpu_x86_init_mmu(CPUX86State *env) | ||
197 | -{ | ||
198 | - last_pg_state = -1; | ||
199 | - cpu_x86_update_cr0(env); | ||
200 | -} | ||
201 | - | ||
202 | -/* XXX: also flush 4MB pages */ | ||
203 | -void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) | ||
204 | -{ | ||
205 | - int flags; | ||
206 | - unsigned long virt_addr; | ||
207 | - | ||
208 | - tlb_flush_page(env, addr); | ||
209 | - | ||
210 | - flags = page_get_flags(addr); | ||
211 | - if (flags & PAGE_VALID) { | ||
212 | - virt_addr = addr & ~0xfff; | ||
213 | - munmap((void *)virt_addr, 4096); | ||
214 | - page_set_flags(virt_addr, virt_addr + 4096, 0); | ||
215 | - } | ||
216 | -} | ||
217 | - | ||
218 | -/* return value: | ||
219 | - -1 = cannot handle fault | ||
220 | - 0 = nothing more to do | ||
221 | - 1 = generate PF fault | ||
222 | - 2 = soft MMU activation required for this block | ||
223 | -*/ | ||
224 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, int is_write) | ||
225 | -{ | ||
226 | - uint8_t *pde_ptr, *pte_ptr; | ||
227 | - uint32_t pde, pte, virt_addr; | ||
228 | - int cpl, error_code, is_dirty, is_user, prot, page_size, ret; | ||
229 | - unsigned long pd; | ||
230 | - | ||
231 | - cpl = env->hflags & HF_CPL_MASK; | ||
232 | - is_user = (cpl == 3); | ||
233 | - | ||
234 | -#ifdef DEBUG_MMU | ||
235 | - printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", | ||
236 | - addr, is_write, is_user, env->eip); | ||
237 | -#endif | ||
238 | - | ||
239 | - if (env->user_mode_only) { | ||
240 | - /* user mode only emulation */ | ||
241 | - error_code = 0; | ||
242 | - goto do_fault; | ||
243 | - } | ||
244 | - | ||
245 | - if (!(env->cr[0] & CR0_PG_MASK)) { | ||
246 | - pte = addr; | ||
247 | - virt_addr = addr & ~0xfff; | ||
248 | - prot = PROT_READ | PROT_WRITE; | ||
249 | - page_size = 4096; | ||
250 | - goto do_mapping; | ||
251 | - } | ||
252 | - | ||
253 | - /* page directory entry */ | ||
254 | - pde_ptr = phys_ram_base + ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)); | ||
255 | - pde = ldl(pde_ptr); | ||
256 | - if (!(pde & PG_PRESENT_MASK)) { | ||
257 | - error_code = 0; | ||
258 | - goto do_fault; | ||
259 | - } | ||
260 | - if (is_user) { | ||
261 | - if (!(pde & PG_USER_MASK)) | ||
262 | - goto do_fault_protect; | ||
263 | - if (is_write && !(pde & PG_RW_MASK)) | ||
264 | - goto do_fault_protect; | ||
265 | - } else { | ||
266 | - if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) && | ||
267 | - is_write && !(pde & PG_RW_MASK)) | ||
268 | - goto do_fault_protect; | ||
269 | - } | ||
270 | - /* if PSE bit is set, then we use a 4MB page */ | ||
271 | - if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | ||
272 | - is_dirty = is_write && !(pde & PG_DIRTY_MASK); | ||
273 | - if (!(pde & PG_ACCESSED_MASK)) { | ||
274 | - pde |= PG_ACCESSED_MASK; | ||
275 | - if (is_dirty) | ||
276 | - pde |= PG_DIRTY_MASK; | ||
277 | - stl(pde_ptr, pde); | ||
278 | - } | ||
279 | - | ||
280 | - pte = pde & ~0x003ff000; /* align to 4MB */ | ||
281 | - page_size = 4096 * 1024; | ||
282 | - virt_addr = addr & ~0x003fffff; | ||
283 | - } else { | ||
284 | - if (!(pde & PG_ACCESSED_MASK)) { | ||
285 | - pde |= PG_ACCESSED_MASK; | ||
286 | - stl(pde_ptr, pde); | ||
287 | - } | ||
288 | - | ||
289 | - /* page directory entry */ | ||
290 | - pte_ptr = phys_ram_base + ((pde & ~0xfff) + ((addr >> 10) & 0xffc)); | ||
291 | - pte = ldl(pte_ptr); | ||
292 | - if (!(pte & PG_PRESENT_MASK)) { | ||
293 | - error_code = 0; | ||
294 | - goto do_fault; | ||
295 | - } | ||
296 | - if (is_user) { | ||
297 | - if (!(pte & PG_USER_MASK)) | ||
298 | - goto do_fault_protect; | ||
299 | - if (is_write && !(pte & PG_RW_MASK)) | ||
300 | - goto do_fault_protect; | ||
301 | - } else { | ||
302 | - if ((env->cr[0] & CR0_WP_MASK) && (pte & PG_USER_MASK) && | ||
303 | - is_write && !(pte & PG_RW_MASK)) | ||
304 | - goto do_fault_protect; | ||
305 | - } | ||
306 | - is_dirty = is_write && !(pte & PG_DIRTY_MASK); | ||
307 | - if (!(pte & PG_ACCESSED_MASK) || is_dirty) { | ||
308 | - pte |= PG_ACCESSED_MASK; | ||
309 | - if (is_dirty) | ||
310 | - pte |= PG_DIRTY_MASK; | ||
311 | - stl(pte_ptr, pte); | ||
312 | - } | ||
313 | - page_size = 4096; | ||
314 | - virt_addr = addr & ~0xfff; | ||
315 | - } | ||
316 | - /* the page can be put in the TLB */ | ||
317 | - prot = PROT_READ; | ||
318 | - if (is_user) { | ||
319 | - if (pte & PG_RW_MASK) | ||
320 | - prot |= PROT_WRITE; | ||
321 | - } else { | ||
322 | - if (!(env->cr[0] & CR0_WP_MASK) || !(pte & PG_USER_MASK) || | ||
323 | - (pte & PG_RW_MASK)) | ||
324 | - prot |= PROT_WRITE; | ||
325 | - } | ||
326 | - | ||
327 | - do_mapping: | ||
328 | - if (env->hflags & HF_SOFTMMU_MASK) { | ||
329 | - unsigned long paddr, vaddr, address, addend, page_offset; | ||
330 | - int index; | ||
331 | - | ||
332 | - /* software MMU case. Even if 4MB pages, we map only one 4KB | ||
333 | - page in the cache to avoid filling it too fast */ | ||
334 | - page_offset = (addr & ~0xfff) & (page_size - 1); | ||
335 | - paddr = (pte & ~0xfff) + page_offset; | ||
336 | - vaddr = virt_addr + page_offset; | ||
337 | - index = (addr >> 12) & (CPU_TLB_SIZE - 1); | ||
338 | - pd = physpage_find(paddr); | ||
339 | - if (pd & 0xfff) { | ||
340 | - /* IO memory case */ | ||
341 | - address = vaddr | pd; | ||
342 | - addend = paddr; | ||
343 | - } else { | ||
344 | - /* standard memory */ | ||
345 | - address = vaddr; | ||
346 | - addend = (unsigned long)phys_ram_base + pd; | ||
347 | - } | ||
348 | - addend -= vaddr; | ||
349 | - env->tlb_read[is_user][index].address = address; | ||
350 | - env->tlb_read[is_user][index].addend = addend; | ||
351 | - if (prot & PROT_WRITE) { | ||
352 | - env->tlb_write[is_user][index].address = address; | ||
353 | - env->tlb_write[is_user][index].addend = addend; | ||
354 | - } | ||
355 | - } | ||
356 | - ret = 0; | ||
357 | - /* XXX: incorrect for 4MB pages */ | ||
358 | - pd = physpage_find(pte & ~0xfff); | ||
359 | - if ((pd & 0xfff) != 0) { | ||
360 | - /* IO access: no mapping is done as it will be handled by the | ||
361 | - soft MMU */ | ||
362 | - if (!(env->hflags & HF_SOFTMMU_MASK)) | ||
363 | - ret = 2; | ||
364 | - } else { | ||
365 | - void *map_addr; | ||
366 | - map_addr = mmap((void *)virt_addr, page_size, prot, | ||
367 | - MAP_SHARED | MAP_FIXED, phys_ram_fd, pd); | ||
368 | - if (map_addr == MAP_FAILED) { | ||
369 | - fprintf(stderr, | ||
370 | - "mmap failed when mapped physical address 0x%08x to virtual address 0x%08x\n", | ||
371 | - pte & ~0xfff, virt_addr); | ||
372 | - exit(1); | ||
373 | - } | ||
374 | -#ifdef DEBUG_MMU | ||
375 | - printf("mmaping 0x%08x to virt 0x%08x pse=%d\n", | ||
376 | - pte & ~0xfff, virt_addr, (page_size != 4096)); | ||
377 | -#endif | ||
378 | - page_set_flags(virt_addr, virt_addr + page_size, | ||
379 | - PAGE_VALID | PAGE_EXEC | prot); | ||
380 | - } | ||
381 | - return ret; | ||
382 | - do_fault_protect: | ||
383 | - error_code = PG_ERROR_P_MASK; | ||
384 | - do_fault: | ||
385 | - env->cr[2] = addr; | ||
386 | - env->error_code = (is_write << PG_ERROR_W_BIT) | error_code; | ||
387 | - if (is_user) | ||
388 | - env->error_code |= PG_ERROR_U_MASK; | ||
389 | - return 1; | ||
390 | -} |
op-arm-template.h deleted
100644 → 0
1 | -/* | ||
2 | - * ARM micro operations (templates for various register related | ||
3 | - * operations) | ||
4 | - * | ||
5 | - * Copyright (c) 2003 Fabrice Bellard | ||
6 | - * | ||
7 | - * This library is free software; you can redistribute it and/or | ||
8 | - * modify it under the terms of the GNU Lesser General Public | ||
9 | - * License as published by the Free Software Foundation; either | ||
10 | - * version 2 of the License, or (at your option) any later version. | ||
11 | - * | ||
12 | - * This library is distributed in the hope that it will be useful, | ||
13 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | - * Lesser General Public License for more details. | ||
16 | - * | ||
17 | - * You should have received a copy of the GNU Lesser General Public | ||
18 | - * License along with this library; if not, write to the Free Software | ||
19 | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | - */ | ||
21 | - | ||
22 | -void OPPROTO glue(op_movl_T0_, REGNAME)(void) | ||
23 | -{ | ||
24 | - T0 = REG; | ||
25 | -} | ||
26 | - | ||
27 | -void OPPROTO glue(op_movl_T1_, REGNAME)(void) | ||
28 | -{ | ||
29 | - T1 = REG; | ||
30 | -} | ||
31 | - | ||
32 | -void OPPROTO glue(op_movl_T2_, REGNAME)(void) | ||
33 | -{ | ||
34 | - T2 = REG; | ||
35 | -} | ||
36 | - | ||
37 | -void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void) | ||
38 | -{ | ||
39 | - REG = T0; | ||
40 | -} | ||
41 | - | ||
42 | -void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void) | ||
43 | -{ | ||
44 | - REG = T1; | ||
45 | -} | ||
46 | - | ||
47 | -#undef REG | ||
48 | -#undef REGNAME |
op-arm.c deleted
100644 → 0
1 | -/* | ||
2 | - * ARM micro operations | ||
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 | -#include "exec-arm.h" | ||
21 | - | ||
22 | -#define REGNAME r0 | ||
23 | -#define REG (env->regs[0]) | ||
24 | -#include "op-arm-template.h" | ||
25 | - | ||
26 | -#define REGNAME r1 | ||
27 | -#define REG (env->regs[1]) | ||
28 | -#include "op-arm-template.h" | ||
29 | - | ||
30 | -#define REGNAME r2 | ||
31 | -#define REG (env->regs[2]) | ||
32 | -#include "op-arm-template.h" | ||
33 | - | ||
34 | -#define REGNAME r3 | ||
35 | -#define REG (env->regs[3]) | ||
36 | -#include "op-arm-template.h" | ||
37 | - | ||
38 | -#define REGNAME r4 | ||
39 | -#define REG (env->regs[4]) | ||
40 | -#include "op-arm-template.h" | ||
41 | - | ||
42 | -#define REGNAME r5 | ||
43 | -#define REG (env->regs[5]) | ||
44 | -#include "op-arm-template.h" | ||
45 | - | ||
46 | -#define REGNAME r6 | ||
47 | -#define REG (env->regs[6]) | ||
48 | -#include "op-arm-template.h" | ||
49 | - | ||
50 | -#define REGNAME r7 | ||
51 | -#define REG (env->regs[7]) | ||
52 | -#include "op-arm-template.h" | ||
53 | - | ||
54 | -#define REGNAME r8 | ||
55 | -#define REG (env->regs[8]) | ||
56 | -#include "op-arm-template.h" | ||
57 | - | ||
58 | -#define REGNAME r9 | ||
59 | -#define REG (env->regs[9]) | ||
60 | -#include "op-arm-template.h" | ||
61 | - | ||
62 | -#define REGNAME r10 | ||
63 | -#define REG (env->regs[10]) | ||
64 | -#include "op-arm-template.h" | ||
65 | - | ||
66 | -#define REGNAME r11 | ||
67 | -#define REG (env->regs[11]) | ||
68 | -#include "op-arm-template.h" | ||
69 | - | ||
70 | -#define REGNAME r12 | ||
71 | -#define REG (env->regs[12]) | ||
72 | -#include "op-arm-template.h" | ||
73 | - | ||
74 | -#define REGNAME r13 | ||
75 | -#define REG (env->regs[13]) | ||
76 | -#include "op-arm-template.h" | ||
77 | - | ||
78 | -#define REGNAME r14 | ||
79 | -#define REG (env->regs[14]) | ||
80 | -#include "op-arm-template.h" | ||
81 | - | ||
82 | -#define REGNAME r15 | ||
83 | -#define REG (env->regs[15]) | ||
84 | -#include "op-arm-template.h" | ||
85 | - | ||
86 | -void OPPROTO op_movl_T0_0(void) | ||
87 | -{ | ||
88 | - T0 = 0; | ||
89 | -} | ||
90 | - | ||
91 | -void OPPROTO op_movl_T0_im(void) | ||
92 | -{ | ||
93 | - T0 = PARAM1; | ||
94 | -} | ||
95 | - | ||
96 | -void OPPROTO op_movl_T1_im(void) | ||
97 | -{ | ||
98 | - T1 = PARAM1; | ||
99 | -} | ||
100 | - | ||
101 | -void OPPROTO op_movl_T2_im(void) | ||
102 | -{ | ||
103 | - T2 = PARAM1; | ||
104 | -} | ||
105 | - | ||
106 | -void OPPROTO op_addl_T1_im(void) | ||
107 | -{ | ||
108 | - T1 += PARAM1; | ||
109 | -} | ||
110 | - | ||
111 | -void OPPROTO op_addl_T1_T2(void) | ||
112 | -{ | ||
113 | - T1 += T2; | ||
114 | -} | ||
115 | - | ||
116 | -void OPPROTO op_subl_T1_T2(void) | ||
117 | -{ | ||
118 | - T1 -= T2; | ||
119 | -} | ||
120 | - | ||
121 | -void OPPROTO op_addl_T0_T1(void) | ||
122 | -{ | ||
123 | - T0 += T1; | ||
124 | -} | ||
125 | - | ||
126 | -void OPPROTO op_addl_T0_T1_cc(void) | ||
127 | -{ | ||
128 | - unsigned int src1; | ||
129 | - src1 = T0; | ||
130 | - T0 += T1; | ||
131 | - env->NZF = T0; | ||
132 | - env->CF = T0 < src1; | ||
133 | - env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | ||
134 | -} | ||
135 | - | ||
136 | -void OPPROTO op_adcl_T0_T1(void) | ||
137 | -{ | ||
138 | - T0 += T1 + env->CF; | ||
139 | -} | ||
140 | - | ||
141 | -void OPPROTO op_adcl_T0_T1_cc(void) | ||
142 | -{ | ||
143 | - unsigned int src1; | ||
144 | - src1 = T0; | ||
145 | - if (!env->CF) { | ||
146 | - T0 += T1; | ||
147 | - env->CF = T0 < src1; | ||
148 | - } else { | ||
149 | - T0 += T1 + 1; | ||
150 | - env->CF = T0 <= src1; | ||
151 | - } | ||
152 | - env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | ||
153 | - env->NZF = T0; | ||
154 | - FORCE_RET(); | ||
155 | -} | ||
156 | - | ||
157 | -#define OPSUB(sub, sbc, res, T0, T1) \ | ||
158 | - \ | ||
159 | -void OPPROTO op_ ## sub ## l_T0_T1(void) \ | ||
160 | -{ \ | ||
161 | - res = T0 - T1; \ | ||
162 | -} \ | ||
163 | - \ | ||
164 | -void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ | ||
165 | -{ \ | ||
166 | - unsigned int src1; \ | ||
167 | - src1 = T0; \ | ||
168 | - T0 -= T1; \ | ||
169 | - env->NZF = T0; \ | ||
170 | - env->CF = src1 >= T1; \ | ||
171 | - env->VF = (src1 ^ T1) & (src1 ^ T0); \ | ||
172 | - res = T0; \ | ||
173 | -} \ | ||
174 | - \ | ||
175 | -void OPPROTO op_ ## sbc ## l_T0_T1(void) \ | ||
176 | -{ \ | ||
177 | - res = T0 - T1 + env->CF - 1; \ | ||
178 | -} \ | ||
179 | - \ | ||
180 | -void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ | ||
181 | -{ \ | ||
182 | - unsigned int src1; \ | ||
183 | - src1 = T0; \ | ||
184 | - if (!env->CF) { \ | ||
185 | - T0 = T0 - T1 - 1; \ | ||
186 | - env->CF = src1 >= T1; \ | ||
187 | - } else { \ | ||
188 | - T0 = T0 - T1; \ | ||
189 | - env->CF = src1 > T1; \ | ||
190 | - } \ | ||
191 | - env->VF = (src1 ^ T1) & (src1 ^ T0); \ | ||
192 | - env->NZF = T0; \ | ||
193 | - res = T0; \ | ||
194 | - FORCE_RET(); \ | ||
195 | -} | ||
196 | - | ||
197 | -OPSUB(sub, sbc, T0, T0, T1) | ||
198 | - | ||
199 | -OPSUB(rsb, rsc, T0, T1, T0) | ||
200 | - | ||
201 | -void OPPROTO op_andl_T0_T1(void) | ||
202 | -{ | ||
203 | - T0 &= T1; | ||
204 | -} | ||
205 | - | ||
206 | -void OPPROTO op_xorl_T0_T1(void) | ||
207 | -{ | ||
208 | - T0 ^= T1; | ||
209 | -} | ||
210 | - | ||
211 | -void OPPROTO op_orl_T0_T1(void) | ||
212 | -{ | ||
213 | - T0 |= T1; | ||
214 | -} | ||
215 | - | ||
216 | -void OPPROTO op_bicl_T0_T1(void) | ||
217 | -{ | ||
218 | - T0 &= ~T1; | ||
219 | -} | ||
220 | - | ||
221 | -void OPPROTO op_notl_T1(void) | ||
222 | -{ | ||
223 | - T1 = ~T1; | ||
224 | -} | ||
225 | - | ||
226 | -void OPPROTO op_logic_T0_cc(void) | ||
227 | -{ | ||
228 | - env->NZF = T0; | ||
229 | -} | ||
230 | - | ||
231 | -void OPPROTO op_logic_T1_cc(void) | ||
232 | -{ | ||
233 | - env->NZF = T1; | ||
234 | -} | ||
235 | - | ||
236 | -#define EIP (env->regs[15]) | ||
237 | - | ||
238 | -void OPPROTO op_test_eq(void) | ||
239 | -{ | ||
240 | - if (env->NZF == 0) | ||
241 | - JUMP_TB(op_test_eq, PARAM1, 0, PARAM2); | ||
242 | - FORCE_RET(); | ||
243 | -} | ||
244 | - | ||
245 | -void OPPROTO op_test_ne(void) | ||
246 | -{ | ||
247 | - if (env->NZF != 0) | ||
248 | - JUMP_TB(op_test_ne, PARAM1, 0, PARAM2); | ||
249 | - FORCE_RET(); | ||
250 | -} | ||
251 | - | ||
252 | -void OPPROTO op_test_cs(void) | ||
253 | -{ | ||
254 | - if (env->CF != 0) | ||
255 | - JUMP_TB(op_test_cs, PARAM1, 0, PARAM2); | ||
256 | - FORCE_RET(); | ||
257 | -} | ||
258 | - | ||
259 | -void OPPROTO op_test_cc(void) | ||
260 | -{ | ||
261 | - if (env->CF == 0) | ||
262 | - JUMP_TB(op_test_cc, PARAM1, 0, PARAM2); | ||
263 | - FORCE_RET(); | ||
264 | -} | ||
265 | - | ||
266 | -void OPPROTO op_test_mi(void) | ||
267 | -{ | ||
268 | - if ((env->NZF & 0x80000000) != 0) | ||
269 | - JUMP_TB(op_test_mi, PARAM1, 0, PARAM2); | ||
270 | - FORCE_RET(); | ||
271 | -} | ||
272 | - | ||
273 | -void OPPROTO op_test_pl(void) | ||
274 | -{ | ||
275 | - if ((env->NZF & 0x80000000) == 0) | ||
276 | - JUMP_TB(op_test_pl, PARAM1, 0, PARAM2); | ||
277 | - FORCE_RET(); | ||
278 | -} | ||
279 | - | ||
280 | -void OPPROTO op_test_vs(void) | ||
281 | -{ | ||
282 | - if ((env->VF & 0x80000000) != 0) | ||
283 | - JUMP_TB(op_test_vs, PARAM1, 0, PARAM2); | ||
284 | - FORCE_RET(); | ||
285 | -} | ||
286 | - | ||
287 | -void OPPROTO op_test_vc(void) | ||
288 | -{ | ||
289 | - if ((env->VF & 0x80000000) == 0) | ||
290 | - JUMP_TB(op_test_vc, PARAM1, 0, PARAM2); | ||
291 | - FORCE_RET(); | ||
292 | -} | ||
293 | - | ||
294 | -void OPPROTO op_test_hi(void) | ||
295 | -{ | ||
296 | - if (env->CF != 0 && env->NZF != 0) | ||
297 | - JUMP_TB(op_test_hi, PARAM1, 0, PARAM2); | ||
298 | - FORCE_RET(); | ||
299 | -} | ||
300 | - | ||
301 | -void OPPROTO op_test_ls(void) | ||
302 | -{ | ||
303 | - if (env->CF == 0 || env->NZF == 0) | ||
304 | - JUMP_TB(op_test_ls, PARAM1, 0, PARAM2); | ||
305 | - FORCE_RET(); | ||
306 | -} | ||
307 | - | ||
308 | -void OPPROTO op_test_ge(void) | ||
309 | -{ | ||
310 | - if (((env->VF ^ env->NZF) & 0x80000000) == 0) | ||
311 | - JUMP_TB(op_test_ge, PARAM1, 0, PARAM2); | ||
312 | - FORCE_RET(); | ||
313 | -} | ||
314 | - | ||
315 | -void OPPROTO op_test_lt(void) | ||
316 | -{ | ||
317 | - if (((env->VF ^ env->NZF) & 0x80000000) != 0) | ||
318 | - JUMP_TB(op_test_lt, PARAM1, 0, PARAM2); | ||
319 | - FORCE_RET(); | ||
320 | -} | ||
321 | - | ||
322 | -void OPPROTO op_test_gt(void) | ||
323 | -{ | ||
324 | - if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) | ||
325 | - JUMP_TB(op_test_gt, PARAM1, 0, PARAM2); | ||
326 | - FORCE_RET(); | ||
327 | -} | ||
328 | - | ||
329 | -void OPPROTO op_test_le(void) | ||
330 | -{ | ||
331 | - if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) | ||
332 | - JUMP_TB(op_test_le, PARAM1, 0, PARAM2); | ||
333 | - FORCE_RET(); | ||
334 | -} | ||
335 | - | ||
336 | -void OPPROTO op_jmp(void) | ||
337 | -{ | ||
338 | - JUMP_TB(op_jmp, PARAM1, 1, PARAM2); | ||
339 | -} | ||
340 | - | ||
341 | -void OPPROTO op_exit_tb(void) | ||
342 | -{ | ||
343 | - EXIT_TB(); | ||
344 | -} | ||
345 | - | ||
346 | -void OPPROTO op_movl_T0_psr(void) | ||
347 | -{ | ||
348 | - T0 = compute_cpsr(); | ||
349 | -} | ||
350 | - | ||
351 | -/* NOTE: N = 1 and Z = 1 cannot be stored currently */ | ||
352 | -void OPPROTO op_movl_psr_T0(void) | ||
353 | -{ | ||
354 | - unsigned int psr; | ||
355 | - psr = T0; | ||
356 | - env->CF = (psr >> 29) & 1; | ||
357 | - env->NZF = (psr & 0xc0000000) ^ 0x40000000; | ||
358 | - env->VF = (psr << 3) & 0x80000000; | ||
359 | - /* for user mode we do not update other state info */ | ||
360 | -} | ||
361 | - | ||
362 | -void OPPROTO op_mul_T0_T1(void) | ||
363 | -{ | ||
364 | - T0 = T0 * T1; | ||
365 | -} | ||
366 | - | ||
367 | -/* 64 bit unsigned mul */ | ||
368 | -void OPPROTO op_mull_T0_T1(void) | ||
369 | -{ | ||
370 | - uint64_t res; | ||
371 | - res = T0 * T1; | ||
372 | - T1 = res >> 32; | ||
373 | - T0 = res; | ||
374 | -} | ||
375 | - | ||
376 | -/* 64 bit signed mul */ | ||
377 | -void OPPROTO op_imull_T0_T1(void) | ||
378 | -{ | ||
379 | - uint64_t res; | ||
380 | - res = (int32_t)T0 * (int32_t)T1; | ||
381 | - T1 = res >> 32; | ||
382 | - T0 = res; | ||
383 | -} | ||
384 | - | ||
385 | -void OPPROTO op_addq_T0_T1(void) | ||
386 | -{ | ||
387 | - uint64_t res; | ||
388 | - res = ((uint64_t)T1 << 32) | T0; | ||
389 | - res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]); | ||
390 | - T1 = res >> 32; | ||
391 | - T0 = res; | ||
392 | -} | ||
393 | - | ||
394 | -void OPPROTO op_logicq_cc(void) | ||
395 | -{ | ||
396 | - env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); | ||
397 | -} | ||
398 | - | ||
399 | -/* memory access */ | ||
400 | - | ||
401 | -void OPPROTO op_ldub_T0_T1(void) | ||
402 | -{ | ||
403 | - T0 = ldub((void *)T1); | ||
404 | -} | ||
405 | - | ||
406 | -void OPPROTO op_ldsb_T0_T1(void) | ||
407 | -{ | ||
408 | - T0 = ldsb((void *)T1); | ||
409 | -} | ||
410 | - | ||
411 | -void OPPROTO op_lduw_T0_T1(void) | ||
412 | -{ | ||
413 | - T0 = lduw((void *)T1); | ||
414 | -} | ||
415 | - | ||
416 | -void OPPROTO op_ldsw_T0_T1(void) | ||
417 | -{ | ||
418 | - T0 = ldsw((void *)T1); | ||
419 | -} | ||
420 | - | ||
421 | -void OPPROTO op_ldl_T0_T1(void) | ||
422 | -{ | ||
423 | - T0 = ldl((void *)T1); | ||
424 | -} | ||
425 | - | ||
426 | -void OPPROTO op_stb_T0_T1(void) | ||
427 | -{ | ||
428 | - stb((void *)T1, T0); | ||
429 | -} | ||
430 | - | ||
431 | -void OPPROTO op_stw_T0_T1(void) | ||
432 | -{ | ||
433 | - stw((void *)T1, T0); | ||
434 | -} | ||
435 | - | ||
436 | -void OPPROTO op_stl_T0_T1(void) | ||
437 | -{ | ||
438 | - stl((void *)T1, T0); | ||
439 | -} | ||
440 | - | ||
441 | -void OPPROTO op_swpb_T0_T1(void) | ||
442 | -{ | ||
443 | - int tmp; | ||
444 | - | ||
445 | - cpu_lock(); | ||
446 | - tmp = ldub((void *)T1); | ||
447 | - stb((void *)T1, T0); | ||
448 | - T0 = tmp; | ||
449 | - cpu_unlock(); | ||
450 | -} | ||
451 | - | ||
452 | -void OPPROTO op_swpl_T0_T1(void) | ||
453 | -{ | ||
454 | - int tmp; | ||
455 | - | ||
456 | - cpu_lock(); | ||
457 | - tmp = ldl((void *)T1); | ||
458 | - stl((void *)T1, T0); | ||
459 | - T0 = tmp; | ||
460 | - cpu_unlock(); | ||
461 | -} | ||
462 | - | ||
463 | -/* shifts */ | ||
464 | - | ||
465 | -/* T1 based */ | ||
466 | -void OPPROTO op_shll_T1_im(void) | ||
467 | -{ | ||
468 | - T1 = T1 << PARAM1; | ||
469 | -} | ||
470 | - | ||
471 | -void OPPROTO op_shrl_T1_im(void) | ||
472 | -{ | ||
473 | - T1 = (uint32_t)T1 >> PARAM1; | ||
474 | -} | ||
475 | - | ||
476 | -void OPPROTO op_sarl_T1_im(void) | ||
477 | -{ | ||
478 | - T1 = (int32_t)T1 >> PARAM1; | ||
479 | -} | ||
480 | - | ||
481 | -void OPPROTO op_rorl_T1_im(void) | ||
482 | -{ | ||
483 | - int shift; | ||
484 | - shift = PARAM1; | ||
485 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | ||
486 | -} | ||
487 | - | ||
488 | -/* T1 based, set C flag */ | ||
489 | -void OPPROTO op_shll_T1_im_cc(void) | ||
490 | -{ | ||
491 | - env->CF = (T1 >> (32 - PARAM1)) & 1; | ||
492 | - T1 = T1 << PARAM1; | ||
493 | -} | ||
494 | - | ||
495 | -void OPPROTO op_shrl_T1_im_cc(void) | ||
496 | -{ | ||
497 | - env->CF = (T1 >> (PARAM1 - 1)) & 1; | ||
498 | - T1 = (uint32_t)T1 >> PARAM1; | ||
499 | -} | ||
500 | - | ||
501 | -void OPPROTO op_sarl_T1_im_cc(void) | ||
502 | -{ | ||
503 | - env->CF = (T1 >> (PARAM1 - 1)) & 1; | ||
504 | - T1 = (int32_t)T1 >> PARAM1; | ||
505 | -} | ||
506 | - | ||
507 | -void OPPROTO op_rorl_T1_im_cc(void) | ||
508 | -{ | ||
509 | - int shift; | ||
510 | - shift = PARAM1; | ||
511 | - env->CF = (T1 >> (shift - 1)) & 1; | ||
512 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | ||
513 | -} | ||
514 | - | ||
515 | -/* T2 based */ | ||
516 | -void OPPROTO op_shll_T2_im(void) | ||
517 | -{ | ||
518 | - T2 = T2 << PARAM1; | ||
519 | -} | ||
520 | - | ||
521 | -void OPPROTO op_shrl_T2_im(void) | ||
522 | -{ | ||
523 | - T2 = (uint32_t)T2 >> PARAM1; | ||
524 | -} | ||
525 | - | ||
526 | -void OPPROTO op_sarl_T2_im(void) | ||
527 | -{ | ||
528 | - T2 = (int32_t)T2 >> PARAM1; | ||
529 | -} | ||
530 | - | ||
531 | -void OPPROTO op_rorl_T2_im(void) | ||
532 | -{ | ||
533 | - int shift; | ||
534 | - shift = PARAM1; | ||
535 | - T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift)); | ||
536 | -} | ||
537 | - | ||
538 | -/* T1 based, use T0 as shift count */ | ||
539 | - | ||
540 | -void OPPROTO op_shll_T1_T0(void) | ||
541 | -{ | ||
542 | - int shift; | ||
543 | - shift = T0 & 0xff; | ||
544 | - if (shift >= 32) | ||
545 | - T1 = 0; | ||
546 | - else | ||
547 | - T1 = T1 << shift; | ||
548 | - FORCE_RET(); | ||
549 | -} | ||
550 | - | ||
551 | -void OPPROTO op_shrl_T1_T0(void) | ||
552 | -{ | ||
553 | - int shift; | ||
554 | - shift = T0 & 0xff; | ||
555 | - if (shift >= 32) | ||
556 | - T1 = 0; | ||
557 | - else | ||
558 | - T1 = (uint32_t)T1 >> shift; | ||
559 | - FORCE_RET(); | ||
560 | -} | ||
561 | - | ||
562 | -void OPPROTO op_sarl_T1_T0(void) | ||
563 | -{ | ||
564 | - int shift; | ||
565 | - shift = T0 & 0xff; | ||
566 | - if (shift >= 32) | ||
567 | - shift = 31; | ||
568 | - T1 = (int32_t)T1 >> shift; | ||
569 | -} | ||
570 | - | ||
571 | -void OPPROTO op_rorl_T1_T0(void) | ||
572 | -{ | ||
573 | - int shift; | ||
574 | - shift = T0 & 0x1f; | ||
575 | - if (shift) { | ||
576 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | ||
577 | - } | ||
578 | - FORCE_RET(); | ||
579 | -} | ||
580 | - | ||
581 | -/* T1 based, use T0 as shift count and compute CF */ | ||
582 | - | ||
583 | -void OPPROTO op_shll_T1_T0_cc(void) | ||
584 | -{ | ||
585 | - int shift; | ||
586 | - shift = T0 & 0xff; | ||
587 | - if (shift >= 32) { | ||
588 | - if (shift == 32) | ||
589 | - env->CF = T1 & 1; | ||
590 | - else | ||
591 | - env->CF = 0; | ||
592 | - T1 = 0; | ||
593 | - } else if (shift != 0) { | ||
594 | - env->CF = (T1 >> (32 - shift)) & 1; | ||
595 | - T1 = T1 << shift; | ||
596 | - } | ||
597 | - FORCE_RET(); | ||
598 | -} | ||
599 | - | ||
600 | -void OPPROTO op_shrl_T1_T0_cc(void) | ||
601 | -{ | ||
602 | - int shift; | ||
603 | - shift = T0 & 0xff; | ||
604 | - if (shift >= 32) { | ||
605 | - if (shift == 32) | ||
606 | - env->CF = (T1 >> 31) & 1; | ||
607 | - else | ||
608 | - env->CF = 0; | ||
609 | - T1 = 0; | ||
610 | - } else if (shift != 0) { | ||
611 | - env->CF = (T1 >> (shift - 1)) & 1; | ||
612 | - T1 = (uint32_t)T1 >> shift; | ||
613 | - } | ||
614 | - FORCE_RET(); | ||
615 | -} | ||
616 | - | ||
617 | -void OPPROTO op_sarl_T1_T0_cc(void) | ||
618 | -{ | ||
619 | - int shift; | ||
620 | - shift = T0 & 0xff; | ||
621 | - if (shift >= 32) { | ||
622 | - env->CF = (T1 >> 31) & 1; | ||
623 | - T1 = (int32_t)T1 >> 31; | ||
624 | - } else { | ||
625 | - env->CF = (T1 >> (shift - 1)) & 1; | ||
626 | - T1 = (int32_t)T1 >> shift; | ||
627 | - } | ||
628 | - FORCE_RET(); | ||
629 | -} | ||
630 | - | ||
631 | -void OPPROTO op_rorl_T1_T0_cc(void) | ||
632 | -{ | ||
633 | - int shift1, shift; | ||
634 | - shift1 = T0 & 0xff; | ||
635 | - shift = shift1 & 0x1f; | ||
636 | - if (shift == 0) { | ||
637 | - if (shift1 != 0) | ||
638 | - env->CF = (T1 >> 31) & 1; | ||
639 | - } else { | ||
640 | - env->CF = (T1 >> (shift - 1)) & 1; | ||
641 | - T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | ||
642 | - } | ||
643 | - FORCE_RET(); | ||
644 | -} | ||
645 | - | ||
646 | -/* exceptions */ | ||
647 | - | ||
648 | -void OPPROTO op_swi(void) | ||
649 | -{ | ||
650 | - env->exception_index = EXCP_SWI; | ||
651 | - cpu_loop_exit(); | ||
652 | -} | ||
653 | - | ||
654 | -void OPPROTO op_undef_insn(void) | ||
655 | -{ | ||
656 | - env->exception_index = EXCP_UDEF; | ||
657 | - cpu_loop_exit(); | ||
658 | -} | ||
659 | - | ||
660 | -/* thread support */ | ||
661 | - | ||
662 | -spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; | ||
663 | - | ||
664 | -void cpu_lock(void) | ||
665 | -{ | ||
666 | - spin_lock(&global_cpu_lock); | ||
667 | -} | ||
668 | - | ||
669 | -void cpu_unlock(void) | ||
670 | -{ | ||
671 | - spin_unlock(&global_cpu_lock); | ||
672 | -} | ||
673 | - |