Commit 14ce26e755135e80f3726d42a5a887723d615291
1 parent
c4687878
x86_64 target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1197 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
2124 additions
and
687 deletions
Too many changes to show.
To preserve performance only 9 of 11 files are displayed.
target-i386/cpu.h
... | ... | @@ -20,7 +20,13 @@ |
20 | 20 | #ifndef CPU_I386_H |
21 | 21 | #define CPU_I386_H |
22 | 22 | |
23 | +#include "config.h" | |
24 | + | |
25 | +#ifdef TARGET_X86_64 | |
26 | +#define TARGET_LONG_BITS 64 | |
27 | +#else | |
23 | 28 | #define TARGET_LONG_BITS 32 |
29 | +#endif | |
24 | 30 | |
25 | 31 | /* target supports implicit self modifying code */ |
26 | 32 | #define TARGET_HAS_SMC |
... | ... | @@ -63,6 +69,8 @@ |
63 | 69 | #define DESC_G_MASK (1 << 23) |
64 | 70 | #define DESC_B_SHIFT 22 |
65 | 71 | #define DESC_B_MASK (1 << DESC_B_SHIFT) |
72 | +#define DESC_L_SHIFT 21 /* x86_64 only : 64 bit code segment */ | |
73 | +#define DESC_L_MASK (1 << DESC_L_SHIFT) | |
66 | 74 | #define DESC_AVL_MASK (1 << 20) |
67 | 75 | #define DESC_P_MASK (1 << 15) |
68 | 76 | #define DESC_DPL_SHIFT 13 |
... | ... | @@ -125,6 +133,8 @@ |
125 | 133 | #define HF_EM_SHIFT 10 |
126 | 134 | #define HF_TS_SHIFT 11 |
127 | 135 | #define HF_IOPL_SHIFT 12 /* must be same as eflags */ |
136 | +#define HF_LMA_SHIFT 14 /* only used on x86_64: long mode active */ | |
137 | +#define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment */ | |
128 | 138 | #define HF_VM_SHIFT 17 /* must be same as eflags */ |
129 | 139 | |
130 | 140 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) |
... | ... | @@ -138,6 +148,8 @@ |
138 | 148 | #define HF_MP_MASK (1 << HF_MP_SHIFT) |
139 | 149 | #define HF_EM_MASK (1 << HF_EM_SHIFT) |
140 | 150 | #define HF_TS_MASK (1 << HF_TS_SHIFT) |
151 | +#define HF_LMA_MASK (1 << HF_LMA_SHIFT) | |
152 | +#define HF_CS64_MASK (1 << HF_CS64_SHIFT) | |
141 | 153 | |
142 | 154 | #define CR0_PE_MASK (1 << 0) |
143 | 155 | #define CR0_MP_MASK (1 << 1) |
... | ... | @@ -156,6 +168,9 @@ |
156 | 168 | #define CR4_PSE_MASK (1 << 4) |
157 | 169 | #define CR4_PAE_MASK (1 << 5) |
158 | 170 | #define CR4_PGE_MASK (1 << 7) |
171 | +#define CR4_PCE_MASK (1 << 8) | |
172 | +#define CR4_OSFXSR_MASK (1 << 9) | |
173 | +#define CR4_OSXMMEXCPT_MASK (1 << 10) | |
159 | 174 | |
160 | 175 | #define PG_PRESENT_BIT 0 |
161 | 176 | #define PG_RW_BIT 1 |
... | ... | @@ -193,6 +208,44 @@ |
193 | 208 | #define MSR_IA32_SYSENTER_ESP 0x175 |
194 | 209 | #define MSR_IA32_SYSENTER_EIP 0x176 |
195 | 210 | |
211 | +#define MSR_EFER 0xc0000080 | |
212 | + | |
213 | +#define MSR_EFER_SCE (1 << 0) | |
214 | +#define MSR_EFER_LME (1 << 8) | |
215 | +#define MSR_EFER_LMA (1 << 10) | |
216 | +#define MSR_EFER_NXE (1 << 11) | |
217 | +#define MSR_EFER_FFXSR (1 << 14) | |
218 | + | |
219 | +#define MSR_STAR 0xc0000081 | |
220 | +#define MSR_LSTAR 0xc0000082 | |
221 | +#define MSR_CSTAR 0xc0000083 | |
222 | +#define MSR_FMASK 0xc0000084 | |
223 | +#define MSR_FSBASE 0xc0000100 | |
224 | +#define MSR_GSBASE 0xc0000101 | |
225 | +#define MSR_KERNELGSBASE 0xc0000102 | |
226 | + | |
227 | +/* cpuid_features bits */ | |
228 | +#define CPUID_FP87 (1 << 0) | |
229 | +#define CPUID_VME (1 << 1) | |
230 | +#define CPUID_DE (1 << 2) | |
231 | +#define CPUID_PSE (1 << 3) | |
232 | +#define CPUID_TSC (1 << 4) | |
233 | +#define CPUID_MSR (1 << 5) | |
234 | +#define CPUID_PAE (1 << 6) | |
235 | +#define CPUID_MCE (1 << 7) | |
236 | +#define CPUID_CX8 (1 << 8) | |
237 | +#define CPUID_APIC (1 << 9) | |
238 | +#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ | |
239 | +#define CPUID_MTRR (1 << 12) | |
240 | +#define CPUID_PGE (1 << 13) | |
241 | +#define CPUID_MCA (1 << 14) | |
242 | +#define CPUID_CMOV (1 << 15) | |
243 | +/* ... */ | |
244 | +#define CPUID_MMX (1 << 23) | |
245 | +#define CPUID_FXSR (1 << 24) | |
246 | +#define CPUID_SSE (1 << 25) | |
247 | +#define CPUID_SSE2 (1 << 26) | |
248 | + | |
196 | 249 | #define EXCP00_DIVZ 0 |
197 | 250 | #define EXCP01_SSTP 1 |
198 | 251 | #define EXCP02_NMI 2 |
... | ... | @@ -219,42 +272,52 @@ enum { |
219 | 272 | CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */ |
220 | 273 | CC_OP_MULW, |
221 | 274 | CC_OP_MULL, |
275 | + CC_OP_MULQ, | |
222 | 276 | |
223 | 277 | CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
224 | 278 | CC_OP_ADDW, |
225 | 279 | CC_OP_ADDL, |
280 | + CC_OP_ADDQ, | |
226 | 281 | |
227 | 282 | CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
228 | 283 | CC_OP_ADCW, |
229 | 284 | CC_OP_ADCL, |
285 | + CC_OP_ADCQ, | |
230 | 286 | |
231 | 287 | CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
232 | 288 | CC_OP_SUBW, |
233 | 289 | CC_OP_SUBL, |
290 | + CC_OP_SUBQ, | |
234 | 291 | |
235 | 292 | CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */ |
236 | 293 | CC_OP_SBBW, |
237 | 294 | CC_OP_SBBL, |
295 | + CC_OP_SBBQ, | |
238 | 296 | |
239 | 297 | CC_OP_LOGICB, /* modify all flags, CC_DST = res */ |
240 | 298 | CC_OP_LOGICW, |
241 | 299 | CC_OP_LOGICL, |
300 | + CC_OP_LOGICQ, | |
242 | 301 | |
243 | 302 | CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
244 | 303 | CC_OP_INCW, |
245 | 304 | CC_OP_INCL, |
305 | + CC_OP_INCQ, | |
246 | 306 | |
247 | 307 | CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C */ |
248 | 308 | CC_OP_DECW, |
249 | 309 | CC_OP_DECL, |
310 | + CC_OP_DECQ, | |
250 | 311 | |
251 | 312 | CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.msb = C */ |
252 | 313 | CC_OP_SHLW, |
253 | 314 | CC_OP_SHLL, |
315 | + CC_OP_SHLQ, | |
254 | 316 | |
255 | 317 | CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */ |
256 | 318 | CC_OP_SARW, |
257 | 319 | CC_OP_SARL, |
320 | + CC_OP_SARQ, | |
258 | 321 | |
259 | 322 | CC_OP_NB, |
260 | 323 | }; |
... | ... | @@ -271,22 +334,42 @@ typedef double CPU86_LDouble; |
271 | 334 | |
272 | 335 | typedef struct SegmentCache { |
273 | 336 | uint32_t selector; |
274 | - uint8_t *base; | |
337 | + target_ulong base; | |
275 | 338 | uint32_t limit; |
276 | 339 | uint32_t flags; |
277 | 340 | } SegmentCache; |
278 | 341 | |
342 | +typedef struct { | |
343 | + union { | |
344 | + uint8_t b[16]; | |
345 | + uint16_t w[8]; | |
346 | + uint32_t l[4]; | |
347 | + uint64_t q[2]; | |
348 | + } u; | |
349 | +} XMMReg; | |
350 | + | |
351 | +#ifdef TARGET_X86_64 | |
352 | +#define CPU_NB_REGS 16 | |
353 | +#else | |
354 | +#define CPU_NB_REGS 8 | |
355 | +#endif | |
356 | + | |
279 | 357 | typedef struct CPUX86State { |
358 | +#if TARGET_LONG_BITS > HOST_LONG_BITS | |
359 | + /* temporaries if we cannot store them in host registers */ | |
360 | + target_ulong t0, t1, t2; | |
361 | +#endif | |
362 | + | |
280 | 363 | /* standard registers */ |
281 | - uint32_t regs[8]; | |
282 | - uint32_t eip; | |
283 | - uint32_t eflags; /* eflags register. During CPU emulation, CC | |
364 | + target_ulong regs[CPU_NB_REGS]; | |
365 | + target_ulong eip; | |
366 | + target_ulong eflags; /* eflags register. During CPU emulation, CC | |
284 | 367 | flags and DF are set to zero because they are |
285 | 368 | stored elsewhere */ |
286 | 369 | |
287 | 370 | /* emulator internal eflags handling */ |
288 | - uint32_t cc_src; | |
289 | - uint32_t cc_dst; | |
371 | + target_ulong cc_src; | |
372 | + target_ulong cc_dst; | |
290 | 373 | uint32_t cc_op; |
291 | 374 | int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ |
292 | 375 | uint32_t hflags; /* hidden flags, see HF_xxx constants */ |
... | ... | @@ -314,10 +397,21 @@ typedef struct CPUX86State { |
314 | 397 | SegmentCache gdt; /* only base and limit are used */ |
315 | 398 | SegmentCache idt; /* only base and limit are used */ |
316 | 399 | |
400 | + XMMReg xmm_regs[CPU_NB_REGS]; | |
401 | + XMMReg xmm_t0; | |
402 | + | |
317 | 403 | /* sysenter registers */ |
318 | 404 | uint32_t sysenter_cs; |
319 | 405 | uint32_t sysenter_esp; |
320 | 406 | uint32_t sysenter_eip; |
407 | +#ifdef TARGET_X86_64 | |
408 | + target_ulong efer; | |
409 | + target_ulong star; | |
410 | + target_ulong lstar; | |
411 | + target_ulong cstar; | |
412 | + target_ulong fmask; | |
413 | + target_ulong kernelgsbase; | |
414 | +#endif | |
321 | 415 | |
322 | 416 | /* temporary data for USE_CODE_COPY mode */ |
323 | 417 | #ifdef USE_CODE_COPY |
... | ... | @@ -333,8 +427,8 @@ typedef struct CPUX86State { |
333 | 427 | int exception_is_int; |
334 | 428 | int exception_next_eip; |
335 | 429 | struct TranslationBlock *current_tb; /* currently executing TB */ |
336 | - uint32_t cr[5]; /* NOTE: cr1 is unused */ | |
337 | - uint32_t dr[8]; /* debug registers */ | |
430 | + target_ulong cr[5]; /* NOTE: cr1 is unused */ | |
431 | + target_ulong dr[8]; /* debug registers */ | |
338 | 432 | int interrupt_request; |
339 | 433 | int user_mode_only; /* user mode only simulation */ |
340 | 434 | |
... | ... | @@ -346,18 +440,28 @@ typedef struct CPUX86State { |
346 | 440 | context) */ |
347 | 441 | unsigned long mem_write_pc; /* host pc at which the memory was |
348 | 442 | written */ |
349 | - unsigned long mem_write_vaddr; /* target virtual addr at which the | |
350 | - memory was written */ | |
443 | + target_ulong mem_write_vaddr; /* target virtual addr at which the | |
444 | + memory was written */ | |
351 | 445 | /* 0 = kernel, 1 = user */ |
352 | 446 | CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; |
353 | 447 | CPUTLBEntry tlb_write[2][CPU_TLB_SIZE]; |
354 | 448 | |
355 | 449 | /* from this point: preserved by CPU reset */ |
356 | 450 | /* ice debug support */ |
357 | - uint32_t breakpoints[MAX_BREAKPOINTS]; | |
451 | + target_ulong breakpoints[MAX_BREAKPOINTS]; | |
358 | 452 | int nb_breakpoints; |
359 | 453 | int singlestep_enabled; |
360 | 454 | |
455 | + /* processor features (e.g. for CPUID insn) */ | |
456 | + uint32_t cpuid_vendor1; | |
457 | + uint32_t cpuid_vendor2; | |
458 | + uint32_t cpuid_vendor3; | |
459 | + uint32_t cpuid_version; | |
460 | + uint32_t cpuid_features; | |
461 | + | |
462 | + /* in order to simplify APIC support, we leave this pointer to the | |
463 | + user */ | |
464 | + struct APICState *apic_state; | |
361 | 465 | /* user data */ |
362 | 466 | void *opaque; |
363 | 467 | } CPUX86State; |
... | ... | @@ -382,7 +486,7 @@ void cpu_set_ferr(CPUX86State *s); |
382 | 486 | cache: it synchronizes the hflags with the segment cache values */ |
383 | 487 | static inline void cpu_x86_load_seg_cache(CPUX86State *env, |
384 | 488 | int seg_reg, unsigned int selector, |
385 | - uint8_t *base, unsigned int limit, | |
489 | + uint32_t base, unsigned int limit, | |
386 | 490 | unsigned int flags) |
387 | 491 | { |
388 | 492 | SegmentCache *sc; |
... | ... | @@ -395,27 +499,45 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env, |
395 | 499 | sc->flags = flags; |
396 | 500 | |
397 | 501 | /* update the hidden flags */ |
398 | - new_hflags = (env->segs[R_CS].flags & DESC_B_MASK) | |
399 | - >> (DESC_B_SHIFT - HF_CS32_SHIFT); | |
400 | - new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK) | |
401 | - >> (DESC_B_SHIFT - HF_SS32_SHIFT); | |
402 | - if (!(env->cr[0] & CR0_PE_MASK) || | |
403 | - (env->eflags & VM_MASK) || | |
404 | - !(new_hflags & HF_CS32_MASK)) { | |
405 | - /* XXX: try to avoid this test. The problem comes from the | |
406 | - fact that is real mode or vm86 mode we only modify the | |
407 | - 'base' and 'selector' fields of the segment cache to go | |
408 | - faster. A solution may be to force addseg to one in | |
409 | - translate-i386.c. */ | |
410 | - new_hflags |= HF_ADDSEG_MASK; | |
411 | - } else { | |
412 | - new_hflags |= (((unsigned long)env->segs[R_DS].base | | |
413 | - (unsigned long)env->segs[R_ES].base | | |
414 | - (unsigned long)env->segs[R_SS].base) != 0) << | |
415 | - HF_ADDSEG_SHIFT; | |
502 | + { | |
503 | + if (seg_reg == R_CS) { | |
504 | +#ifdef TARGET_X86_64 | |
505 | + if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) { | |
506 | + /* long mode */ | |
507 | + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK; | |
508 | + env->hflags &= ~(HF_ADDSEG_MASK); | |
509 | + } else | |
510 | +#endif | |
511 | + { | |
512 | + /* legacy / compatibility case */ | |
513 | + new_hflags = (env->segs[R_CS].flags & DESC_B_MASK) | |
514 | + >> (DESC_B_SHIFT - HF_CS32_SHIFT); | |
515 | + env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) | | |
516 | + new_hflags; | |
517 | + } | |
518 | + } | |
519 | + new_hflags = (env->segs[R_SS].flags & DESC_B_MASK) | |
520 | + >> (DESC_B_SHIFT - HF_SS32_SHIFT); | |
521 | + if (env->hflags & HF_CS64_MASK) { | |
522 | + /* zero base assumed for DS, ES and SS in long mode */ | |
523 | + } else if (!(env->cr[0] & CR0_PE_MASK) || | |
524 | + (env->eflags & VM_MASK) || | |
525 | + !(new_hflags & HF_CS32_MASK)) { | |
526 | + /* XXX: try to avoid this test. The problem comes from the | |
527 | + fact that is real mode or vm86 mode we only modify the | |
528 | + 'base' and 'selector' fields of the segment cache to go | |
529 | + faster. A solution may be to force addseg to one in | |
530 | + translate-i386.c. */ | |
531 | + new_hflags |= HF_ADDSEG_MASK; | |
532 | + } else { | |
533 | + new_hflags |= (((unsigned long)env->segs[R_DS].base | | |
534 | + (unsigned long)env->segs[R_ES].base | | |
535 | + (unsigned long)env->segs[R_SS].base) != 0) << | |
536 | + HF_ADDSEG_SHIFT; | |
537 | + } | |
538 | + env->hflags = (env->hflags & | |
539 | + ~(HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags; | |
416 | 540 | } |
417 | - env->hflags = (env->hflags & | |
418 | - ~(HF_CS32_MASK | HF_SS32_MASK | HF_ADDSEG_MASK)) | new_hflags; | |
419 | 541 | } |
420 | 542 | |
421 | 543 | /* wrapper, just in case memory mappings must be changed */ |
... | ... | @@ -448,6 +570,9 @@ void cpu_x86_set_a20(CPUX86State *env, int a20_state); |
448 | 570 | |
449 | 571 | uint64_t cpu_get_tsc(CPUX86State *env); |
450 | 572 | |
573 | +void cpu_set_apic_base(CPUX86State *env, uint64_t val); | |
574 | +uint64_t cpu_get_apic_base(CPUX86State *env); | |
575 | + | |
451 | 576 | /* will be suppressed */ |
452 | 577 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); |
453 | 578 | ... | ... |
target-i386/exec.h
... | ... | @@ -20,14 +20,29 @@ |
20 | 20 | #include "config.h" |
21 | 21 | #include "dyngen-exec.h" |
22 | 22 | |
23 | +/* XXX: factorize this mess */ | |
24 | +#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) | |
25 | +#define HOST_LONG_BITS 64 | |
26 | +#else | |
27 | +#define HOST_LONG_BITS 32 | |
28 | +#endif | |
29 | + | |
30 | +#ifdef TARGET_X86_64 | |
31 | +#define TARGET_LONG_BITS 64 | |
32 | +#else | |
33 | +#define TARGET_LONG_BITS 32 | |
34 | +#endif | |
35 | + | |
23 | 36 | /* at least 4 register variables are defined */ |
24 | 37 | register struct CPUX86State *env asm(AREG0); |
38 | + | |
39 | +/* XXX: use 64 bit regs if HOST_LONG_BITS == 64 */ | |
40 | +#if TARGET_LONG_BITS == 32 | |
41 | + | |
25 | 42 | register uint32_t T0 asm(AREG1); |
26 | 43 | register uint32_t T1 asm(AREG2); |
27 | 44 | register uint32_t T2 asm(AREG3); |
28 | 45 | |
29 | -#define A0 T2 | |
30 | - | |
31 | 46 | /* if more registers are available, we define some registers too */ |
32 | 47 | #ifdef AREG4 |
33 | 48 | register uint32_t EAX asm(AREG4); |
... | ... | @@ -69,6 +84,17 @@ register uint32_t EDI asm(AREG11); |
69 | 84 | #define reg_EDI |
70 | 85 | #endif |
71 | 86 | |
87 | +#else | |
88 | + | |
89 | +/* no registers can be used */ | |
90 | +#define T0 (env->t0) | |
91 | +#define T1 (env->t1) | |
92 | +#define T2 (env->t2) | |
93 | + | |
94 | +#endif | |
95 | + | |
96 | +#define A0 T2 | |
97 | + | |
72 | 98 | extern FILE *logfile; |
73 | 99 | extern int loglevel; |
74 | 100 | |
... | ... | @@ -136,26 +162,24 @@ void helper_movl_crN_T0(int reg); |
136 | 162 | void helper_movl_drN_T0(int reg); |
137 | 163 | void helper_invlpg(unsigned int addr); |
138 | 164 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); |
139 | -void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3); | |
165 | +void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); | |
140 | 166 | void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); |
141 | 167 | void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); |
142 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | |
168 | +int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, | |
143 | 169 | int is_write, int is_user, int is_softmmu); |
144 | -void tlb_fill(unsigned long addr, int is_write, int is_user, | |
170 | +void tlb_fill(target_ulong addr, int is_write, int is_user, | |
145 | 171 | void *retaddr); |
146 | 172 | void __hidden cpu_lock(void); |
147 | 173 | void __hidden cpu_unlock(void); |
148 | 174 | void do_interrupt(int intno, int is_int, int error_code, |
149 | - unsigned int next_eip, int is_hw); | |
175 | + target_ulong next_eip, int is_hw); | |
150 | 176 | void do_interrupt_user(int intno, int is_int, int error_code, |
151 | - unsigned int next_eip); | |
177 | + target_ulong next_eip); | |
152 | 178 | void raise_interrupt(int intno, int is_int, int error_code, |
153 | 179 | unsigned int next_eip); |
154 | 180 | void raise_exception_err(int exception_index, int error_code); |
155 | 181 | void raise_exception(int exception_index); |
156 | 182 | void __hidden cpu_loop_exit(void); |
157 | -void helper_fsave(uint8_t *ptr, int data32); | |
158 | -void helper_frstor(uint8_t *ptr, int data32); | |
159 | 183 | |
160 | 184 | void OPPROTO op_movl_eflags_T0(void); |
161 | 185 | void OPPROTO op_movl_T0_eflags(void); |
... | ... | @@ -163,13 +187,20 @@ void raise_interrupt(int intno, int is_int, int error_code, |
163 | 187 | unsigned int next_eip); |
164 | 188 | void raise_exception_err(int exception_index, int error_code); |
165 | 189 | void raise_exception(int exception_index); |
166 | -void helper_divl_EAX_T0(uint32_t eip); | |
167 | -void helper_idivl_EAX_T0(uint32_t eip); | |
190 | +void helper_divl_EAX_T0(void); | |
191 | +void helper_idivl_EAX_T0(void); | |
192 | +void helper_mulq_EAX_T0(void); | |
193 | +void helper_imulq_EAX_T0(void); | |
194 | +void helper_imulq_T0_T1(void); | |
195 | +void helper_divq_EAX_T0(void); | |
196 | +void helper_idivq_EAX_T0(void); | |
168 | 197 | void helper_cmpxchg8b(void); |
169 | 198 | void helper_cpuid(void); |
170 | 199 | void helper_enter_level(int level, int data32); |
171 | 200 | void helper_sysenter(void); |
172 | 201 | void helper_sysexit(void); |
202 | +void helper_syscall(void); | |
203 | +void helper_sysret(int dflag); | |
173 | 204 | void helper_rdtsc(void); |
174 | 205 | void helper_rdmsr(void); |
175 | 206 | void helper_wrmsr(void); |
... | ... | @@ -252,7 +283,7 @@ void check_iol_DX(void); |
252 | 283 | #define stl(p, v) stl_data(p, v) |
253 | 284 | #define stq(p, v) stq_data(p, v) |
254 | 285 | |
255 | -static inline double ldfq(void *ptr) | |
286 | +static inline double ldfq(target_ulong ptr) | |
256 | 287 | { |
257 | 288 | union { |
258 | 289 | double d; |
... | ... | @@ -262,7 +293,7 @@ static inline double ldfq(void *ptr) |
262 | 293 | return u.d; |
263 | 294 | } |
264 | 295 | |
265 | -static inline void stfq(void *ptr, double v) | |
296 | +static inline void stfq(target_ulong ptr, double v) | |
266 | 297 | { |
267 | 298 | union { |
268 | 299 | double d; |
... | ... | @@ -272,7 +303,7 @@ static inline void stfq(void *ptr, double v) |
272 | 303 | stq(ptr, u.i); |
273 | 304 | } |
274 | 305 | |
275 | -static inline float ldfl(void *ptr) | |
306 | +static inline float ldfl(target_ulong ptr) | |
276 | 307 | { |
277 | 308 | union { |
278 | 309 | float f; |
... | ... | @@ -282,7 +313,7 @@ static inline float ldfl(void *ptr) |
282 | 313 | return u.f; |
283 | 314 | } |
284 | 315 | |
285 | -static inline void stfl(void *ptr, float v) | |
316 | +static inline void stfl(target_ulong ptr, float v) | |
286 | 317 | { |
287 | 318 | union { |
288 | 319 | float f; |
... | ... | @@ -411,7 +442,7 @@ static inline void fpop(void) |
411 | 442 | } |
412 | 443 | |
413 | 444 | #ifndef USE_X86LDOUBLE |
414 | -static inline CPU86_LDouble helper_fldt(uint8_t *ptr) | |
445 | +static inline CPU86_LDouble helper_fldt(target_ulong ptr) | |
415 | 446 | { |
416 | 447 | CPU86_LDoubleU temp; |
417 | 448 | int upper, e; |
... | ... | @@ -451,12 +482,12 @@ static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) |
451 | 482 | |
452 | 483 | #ifdef CONFIG_USER_ONLY |
453 | 484 | |
454 | -static inline CPU86_LDouble helper_fldt(uint8_t *ptr) | |
485 | +static inline CPU86_LDouble helper_fldt(target_ulong ptr) | |
455 | 486 | { |
456 | 487 | return *(CPU86_LDouble *)ptr; |
457 | 488 | } |
458 | 489 | |
459 | -static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) | |
490 | +static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) | |
460 | 491 | { |
461 | 492 | *(CPU86_LDouble *)ptr = f; |
462 | 493 | } |
... | ... | @@ -465,7 +496,7 @@ static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) |
465 | 496 | |
466 | 497 | /* we use memory access macros */ |
467 | 498 | |
468 | -static inline CPU86_LDouble helper_fldt(uint8_t *ptr) | |
499 | +static inline CPU86_LDouble helper_fldt(target_ulong ptr) | |
469 | 500 | { |
470 | 501 | CPU86_LDoubleU temp; |
471 | 502 | |
... | ... | @@ -474,7 +505,7 @@ static inline CPU86_LDouble helper_fldt(uint8_t *ptr) |
474 | 505 | return temp.d; |
475 | 506 | } |
476 | 507 | |
477 | -static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) | |
508 | +static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr) | |
478 | 509 | { |
479 | 510 | CPU86_LDoubleU temp; |
480 | 511 | |
... | ... | @@ -522,10 +553,12 @@ void helper_fscale(void); |
522 | 553 | void helper_fsin(void); |
523 | 554 | void helper_fcos(void); |
524 | 555 | void helper_fxam_ST0(void); |
525 | -void helper_fstenv(uint8_t *ptr, int data32); | |
526 | -void helper_fldenv(uint8_t *ptr, int data32); | |
527 | -void helper_fsave(uint8_t *ptr, int data32); | |
528 | -void helper_frstor(uint8_t *ptr, int data32); | |
556 | +void helper_fstenv(target_ulong ptr, int data32); | |
557 | +void helper_fldenv(target_ulong ptr, int data32); | |
558 | +void helper_fsave(target_ulong ptr, int data32); | |
559 | +void helper_frstor(target_ulong ptr, int data32); | |
560 | +void helper_fxsave(target_ulong ptr, int data64); | |
561 | +void helper_fxrstor(target_ulong ptr, int data64); | |
529 | 562 | void restore_native_fp_state(CPUState *env); |
530 | 563 | void save_native_fp_state(CPUState *env); |
531 | 564 | ... | ... |
target-i386/helper.c
... | ... | @@ -119,7 +119,7 @@ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, |
119 | 119 | { |
120 | 120 | SegmentCache *dt; |
121 | 121 | int index; |
122 | - uint8_t *ptr; | |
122 | + target_ulong ptr; | |
123 | 123 | |
124 | 124 | if (selector & 0x4) |
125 | 125 | dt = &env->ldt; |
... | ... | @@ -143,9 +143,9 @@ static inline unsigned int get_seg_limit(uint32_t e1, uint32_t e2) |
143 | 143 | return limit; |
144 | 144 | } |
145 | 145 | |
146 | -static inline uint8_t *get_seg_base(uint32_t e1, uint32_t e2) | |
146 | +static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2) | |
147 | 147 | { |
148 | - return (uint8_t *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); | |
148 | + return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); | |
149 | 149 | } |
150 | 150 | |
151 | 151 | static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2) |
... | ... | @@ -160,7 +160,7 @@ static inline void load_seg_vm(int seg, int selector) |
160 | 160 | { |
161 | 161 | selector &= 0xffff; |
162 | 162 | cpu_x86_load_seg_cache(env, seg, selector, |
163 | - (uint8_t *)(selector << 4), 0xffff, 0); | |
163 | + (selector << 4), 0xffff, 0); | |
164 | 164 | } |
165 | 165 | |
166 | 166 | static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, |
... | ... | @@ -258,13 +258,13 @@ static void switch_tss(int tss_selector, |
258 | 258 | uint32_t next_eip) |
259 | 259 | { |
260 | 260 | int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i; |
261 | - uint8_t *tss_base; | |
261 | + target_ulong tss_base; | |
262 | 262 | uint32_t new_regs[8], new_segs[6]; |
263 | 263 | uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap; |
264 | 264 | uint32_t old_eflags, eflags_mask; |
265 | 265 | SegmentCache *dt; |
266 | 266 | int index; |
267 | - uint8_t *ptr; | |
267 | + target_ulong ptr; | |
268 | 268 | |
269 | 269 | type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
270 | 270 | #ifdef DEBUG_PCALL |
... | ... | @@ -345,7 +345,7 @@ static void switch_tss(int tss_selector, |
345 | 345 | |
346 | 346 | /* clear busy bit (it is restartable) */ |
347 | 347 | if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) { |
348 | - uint8_t *ptr; | |
348 | + target_ulong ptr; | |
349 | 349 | uint32_t e2; |
350 | 350 | ptr = env->gdt.base + (env->tr.selector & ~7); |
351 | 351 | e2 = ldl_kernel(ptr + 4); |
... | ... | @@ -397,7 +397,7 @@ static void switch_tss(int tss_selector, |
397 | 397 | |
398 | 398 | /* set busy bit */ |
399 | 399 | if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) { |
400 | - uint8_t *ptr; | |
400 | + target_ulong ptr; | |
401 | 401 | uint32_t e2; |
402 | 402 | ptr = env->gdt.base + (tss_selector & ~7); |
403 | 403 | e2 = ldl_kernel(ptr + 4); |
... | ... | @@ -445,11 +445,11 @@ static void switch_tss(int tss_selector, |
445 | 445 | cpu_x86_set_cpl(env, new_segs[R_CS] & 3); |
446 | 446 | /* first just selectors as the rest may trigger exceptions */ |
447 | 447 | for(i = 0; i < 6; i++) |
448 | - cpu_x86_load_seg_cache(env, i, new_segs[i], NULL, 0, 0); | |
448 | + cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0); | |
449 | 449 | } |
450 | 450 | |
451 | 451 | env->ldt.selector = new_ldt & ~4; |
452 | - env->ldt.base = NULL; | |
452 | + env->ldt.base = 0; | |
453 | 453 | env->ldt.limit = 0; |
454 | 454 | env->ldt.flags = 0; |
455 | 455 | |
... | ... | @@ -573,7 +573,7 @@ static inline unsigned int get_sp_mask(unsigned int e2) |
573 | 573 | |
574 | 574 | #define POPL(ssp, sp, sp_mask, val)\ |
575 | 575 | {\ |
576 | - val = ldl_kernel((ssp) + (sp & (sp_mask)));\ | |
576 | + val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\ | |
577 | 577 | sp += 4;\ |
578 | 578 | } |
579 | 579 | |
... | ... | @@ -582,7 +582,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
582 | 582 | unsigned int next_eip, int is_hw) |
583 | 583 | { |
584 | 584 | SegmentCache *dt; |
585 | - uint8_t *ptr, *ssp; | |
585 | + target_ulong ptr, ssp; | |
586 | 586 | int type, dpl, selector, ss_dpl, cpl, sp_mask; |
587 | 587 | int has_error_code, new_stack, shift; |
588 | 588 | uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2; |
... | ... | @@ -703,7 +703,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
703 | 703 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
704 | 704 | new_stack = 0; /* avoid warning */ |
705 | 705 | sp_mask = 0; /* avoid warning */ |
706 | - ssp = NULL; /* avoid warning */ | |
706 | + ssp = 0; /* avoid warning */ | |
707 | 707 | esp = 0; /* avoid warning */ |
708 | 708 | } |
709 | 709 | |
... | ... | @@ -754,10 +754,10 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
754 | 754 | |
755 | 755 | if (new_stack) { |
756 | 756 | if (env->eflags & VM_MASK) { |
757 | - cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0, 0); | |
758 | - cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0, 0); | |
759 | - cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0, 0); | |
760 | - cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0, 0); | |
757 | + cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0); | |
758 | + cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0); | |
759 | + cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0); | |
760 | + cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0); | |
761 | 761 | } |
762 | 762 | ss = (ss & ~3) | dpl; |
763 | 763 | cpu_x86_load_seg_cache(env, R_SS, ss, |
... | ... | @@ -780,12 +780,264 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
780 | 780 | env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); |
781 | 781 | } |
782 | 782 | |
783 | +#ifdef TARGET_X86_64 | |
784 | + | |
785 | +#define PUSHQ(sp, val)\ | |
786 | +{\ | |
787 | + sp -= 8;\ | |
788 | + stq_kernel(sp, (val));\ | |
789 | +} | |
790 | + | |
791 | +#define POPQ(sp, val)\ | |
792 | +{\ | |
793 | + val = ldq_kernel(sp);\ | |
794 | + sp += 8;\ | |
795 | +} | |
796 | + | |
797 | +static inline target_ulong get_rsp_from_tss(int level) | |
798 | +{ | |
799 | + int index; | |
800 | + | |
801 | +#if 0 | |
802 | + printf("TR: base=" TARGET_FMT_lx " limit=%x\n", | |
803 | + env->tr.base, env->tr.limit); | |
804 | +#endif | |
805 | + | |
806 | + if (!(env->tr.flags & DESC_P_MASK)) | |
807 | + cpu_abort(env, "invalid tss"); | |
808 | + index = 8 * level + 4; | |
809 | + if ((index + 7) > env->tr.limit) | |
810 | + raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); | |
811 | + return ldq_kernel(env->tr.base + index); | |
812 | +} | |
813 | + | |
814 | +/* 64 bit interrupt */ | |
815 | +static void do_interrupt64(int intno, int is_int, int error_code, | |
816 | + target_ulong next_eip, int is_hw) | |
817 | +{ | |
818 | + SegmentCache *dt; | |
819 | + target_ulong ptr; | |
820 | + int type, dpl, selector, cpl, ist; | |
821 | + int has_error_code, new_stack; | |
822 | + uint32_t e1, e2, e3, ss; | |
823 | + target_ulong old_eip, esp, offset; | |
824 | + | |
825 | + has_error_code = 0; | |
826 | + if (!is_int && !is_hw) { | |
827 | + switch(intno) { | |
828 | + case 8: | |
829 | + case 10: | |
830 | + case 11: | |
831 | + case 12: | |
832 | + case 13: | |
833 | + case 14: | |
834 | + case 17: | |
835 | + has_error_code = 1; | |
836 | + break; | |
837 | + } | |
838 | + } | |
839 | + if (is_int) | |
840 | + old_eip = next_eip; | |
841 | + else | |
842 | + old_eip = env->eip; | |
843 | + | |
844 | + dt = &env->idt; | |
845 | + if (intno * 16 + 15 > dt->limit) | |
846 | + raise_exception_err(EXCP0D_GPF, intno * 16 + 2); | |
847 | + ptr = dt->base + intno * 16; | |
848 | + e1 = ldl_kernel(ptr); | |
849 | + e2 = ldl_kernel(ptr + 4); | |
850 | + e3 = ldl_kernel(ptr + 8); | |
851 | + /* check gate type */ | |
852 | + type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; | |
853 | + switch(type) { | |
854 | + case 14: /* 386 interrupt gate */ | |
855 | + case 15: /* 386 trap gate */ | |
856 | + break; | |
857 | + default: | |
858 | + raise_exception_err(EXCP0D_GPF, intno * 16 + 2); | |
859 | + break; | |
860 | + } | |
861 | + dpl = (e2 >> DESC_DPL_SHIFT) & 3; | |
862 | + cpl = env->hflags & HF_CPL_MASK; | |
863 | + /* check privledge if software int */ | |
864 | + if (is_int && dpl < cpl) | |
865 | + raise_exception_err(EXCP0D_GPF, intno * 16 + 2); | |
866 | + /* check valid bit */ | |
867 | + if (!(e2 & DESC_P_MASK)) | |
868 | + raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2); | |
869 | + selector = e1 >> 16; | |
870 | + offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff); | |
871 | + ist = e2 & 7; | |
872 | + if ((selector & 0xfffc) == 0) | |
873 | + raise_exception_err(EXCP0D_GPF, 0); | |
874 | + | |
875 | + if (load_segment(&e1, &e2, selector) != 0) | |
876 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
877 | + if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK))) | |
878 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
879 | + dpl = (e2 >> DESC_DPL_SHIFT) & 3; | |
880 | + if (dpl > cpl) | |
881 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
882 | + if (!(e2 & DESC_P_MASK)) | |
883 | + raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); | |
884 | + if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK)) | |
885 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
886 | + if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) { | |
887 | + /* to inner priviledge */ | |
888 | + if (ist != 0) | |
889 | + esp = get_rsp_from_tss(ist + 3); | |
890 | + else | |
891 | + esp = get_rsp_from_tss(dpl); | |
892 | + ss = 0; | |
893 | + new_stack = 1; | |
894 | + } else if ((e2 & DESC_C_MASK) || dpl == cpl) { | |
895 | + /* to same priviledge */ | |
896 | + if (env->eflags & VM_MASK) | |
897 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
898 | + new_stack = 0; | |
899 | + esp = ESP & ~0xf; /* align stack */ | |
900 | + dpl = cpl; | |
901 | + } else { | |
902 | + raise_exception_err(EXCP0D_GPF, selector & 0xfffc); | |
903 | + new_stack = 0; /* avoid warning */ | |
904 | + esp = 0; /* avoid warning */ | |
905 | + } | |
906 | + | |
907 | + PUSHQ(esp, env->segs[R_SS].selector); | |
908 | + PUSHQ(esp, ESP); | |
909 | + PUSHQ(esp, compute_eflags()); | |
910 | + PUSHQ(esp, env->segs[R_CS].selector); | |
911 | + PUSHQ(esp, old_eip); | |
912 | + if (has_error_code) { | |
913 | + PUSHQ(esp, error_code); | |
914 | + } | |
915 | + | |
916 | + if (new_stack) { | |
917 | + ss = 0 | dpl; | |
918 | + cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0); | |
919 | + } | |
920 | + ESP = esp; | |
921 | + | |
922 | + selector = (selector & ~3) | dpl; | |
923 | + cpu_x86_load_seg_cache(env, R_CS, selector, | |
924 | + get_seg_base(e1, e2), | |
925 | + get_seg_limit(e1, e2), | |
926 | + e2); | |
927 | + cpu_x86_set_cpl(env, dpl); | |
928 | + env->eip = offset; | |
929 | + | |
930 | + /* interrupt gate clear IF mask */ | |
931 | + if ((type & 1) == 0) { | |
932 | + env->eflags &= ~IF_MASK; | |
933 | + } | |
934 | + env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK); | |
935 | +} | |
936 | + | |
937 | +void helper_syscall(void) | |
938 | +{ | |
939 | + int selector; | |
940 | + | |
941 | + if (!(env->efer & MSR_EFER_SCE)) { | |
942 | + raise_exception_err(EXCP06_ILLOP, 0); | |
943 | + } | |
944 | + selector = (env->star >> 32) & 0xffff; | |
945 | + if (env->hflags & HF_LMA_MASK) { | |
946 | + ECX = env->eip; | |
947 | + env->regs[11] = compute_eflags(); | |
948 | + | |
949 | + cpu_x86_set_cpl(env, 0); | |
950 | + cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, | |
951 | + 0, 0xffffffff, | |
952 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
953 | + DESC_S_MASK | | |
954 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK); | |
955 | + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, | |
956 | + 0, 0xffffffff, | |
957 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
958 | + DESC_S_MASK | | |
959 | + DESC_W_MASK | DESC_A_MASK); | |
960 | + env->eflags &= ~env->fmask; | |
961 | + if (env->hflags & HF_CS64_MASK) | |
962 | + env->eip = env->lstar; | |
963 | + else | |
964 | + env->eip = env->cstar; | |
965 | + } else { | |
966 | + ECX = (uint32_t)env->eip; | |
967 | + | |
968 | + cpu_x86_set_cpl(env, 0); | |
969 | + cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, | |
970 | + 0, 0xffffffff, | |
971 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
972 | + DESC_S_MASK | | |
973 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
974 | + cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, | |
975 | + 0, 0xffffffff, | |
976 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
977 | + DESC_S_MASK | | |
978 | + DESC_W_MASK | DESC_A_MASK); | |
979 | + env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK); | |
980 | + env->eip = (uint32_t)env->star; | |
981 | + } | |
982 | +} | |
983 | + | |
984 | +void helper_sysret(int dflag) | |
985 | +{ | |
986 | + int cpl, selector; | |
987 | + | |
988 | + cpl = env->hflags & HF_CPL_MASK; | |
989 | + if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) { | |
990 | + raise_exception_err(EXCP0D_GPF, 0); | |
991 | + } | |
992 | + selector = (env->star >> 48) & 0xffff; | |
993 | + if (env->hflags & HF_LMA_MASK) { | |
994 | + if (dflag == 2) { | |
995 | + cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, | |
996 | + 0, 0xffffffff, | |
997 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
998 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
999 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | | |
1000 | + DESC_L_MASK); | |
1001 | + env->eip = ECX; | |
1002 | + } else { | |
1003 | + cpu_x86_load_seg_cache(env, R_CS, selector | 3, | |
1004 | + 0, 0xffffffff, | |
1005 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1006 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1007 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
1008 | + env->eip = (uint32_t)ECX; | |
1009 | + } | |
1010 | + cpu_x86_load_seg_cache(env, R_SS, selector + 8, | |
1011 | + 0, 0xffffffff, | |
1012 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1013 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1014 | + DESC_W_MASK | DESC_A_MASK); | |
1015 | + load_eflags((uint32_t)(env->regs[11]), 0xffffffff); | |
1016 | + cpu_x86_set_cpl(env, 3); | |
1017 | + } else { | |
1018 | + cpu_x86_load_seg_cache(env, R_CS, selector | 3, | |
1019 | + 0, 0xffffffff, | |
1020 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1021 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1022 | + DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); | |
1023 | + env->eip = (uint32_t)ECX; | |
1024 | + cpu_x86_load_seg_cache(env, R_SS, selector + 8, | |
1025 | + 0, 0xffffffff, | |
1026 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1027 | + DESC_S_MASK | (3 << DESC_DPL_SHIFT) | | |
1028 | + DESC_W_MASK | DESC_A_MASK); | |
1029 | + env->eflags |= IF_MASK; | |
1030 | + cpu_x86_set_cpl(env, 3); | |
1031 | + } | |
1032 | +} | |
1033 | +#endif | |
1034 | + | |
783 | 1035 | /* real mode interrupt */ |
784 | 1036 | static void do_interrupt_real(int intno, int is_int, int error_code, |
785 | 1037 | unsigned int next_eip) |
786 | 1038 | { |
787 | 1039 | SegmentCache *dt; |
788 | - uint8_t *ptr, *ssp; | |
1040 | + target_ulong ptr, ssp; | |
789 | 1041 | int selector; |
790 | 1042 | uint32_t offset, esp; |
791 | 1043 | uint32_t old_cs, old_eip; |
... | ... | @@ -813,16 +1065,16 @@ static void do_interrupt_real(int intno, int is_int, int error_code, |
813 | 1065 | ESP = (ESP & ~0xffff) | (esp & 0xffff); |
814 | 1066 | env->eip = offset; |
815 | 1067 | env->segs[R_CS].selector = selector; |
816 | - env->segs[R_CS].base = (uint8_t *)(selector << 4); | |
1068 | + env->segs[R_CS].base = (selector << 4); | |
817 | 1069 | env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK); |
818 | 1070 | } |
819 | 1071 | |
820 | 1072 | /* fake user mode interrupt */ |
821 | 1073 | void do_interrupt_user(int intno, int is_int, int error_code, |
822 | - unsigned int next_eip) | |
1074 | + target_ulong next_eip) | |
823 | 1075 | { |
824 | 1076 | SegmentCache *dt; |
825 | - uint8_t *ptr; | |
1077 | + target_ulong ptr; | |
826 | 1078 | int dpl, cpl; |
827 | 1079 | uint32_t e2; |
828 | 1080 | |
... | ... | @@ -849,26 +1101,26 @@ void do_interrupt_user(int intno, int is_int, int error_code, |
849 | 1101 | * instruction. It is only relevant if is_int is TRUE. |
850 | 1102 | */ |
851 | 1103 | void do_interrupt(int intno, int is_int, int error_code, |
852 | - unsigned int next_eip, int is_hw) | |
1104 | + target_ulong next_eip, int is_hw) | |
853 | 1105 | { |
854 | 1106 | #ifdef DEBUG_PCALL |
855 | 1107 | if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) { |
856 | 1108 | if ((env->cr[0] & CR0_PE_MASK)) { |
857 | 1109 | static int count; |
858 | - fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x pc=%08x SP=%04x:%08x", | |
1110 | + fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx, | |
859 | 1111 | count, intno, error_code, is_int, |
860 | 1112 | env->hflags & HF_CPL_MASK, |
861 | 1113 | env->segs[R_CS].selector, EIP, |
862 | 1114 | (int)env->segs[R_CS].base + EIP, |
863 | 1115 | env->segs[R_SS].selector, ESP); |
864 | 1116 | if (intno == 0x0e) { |
865 | - fprintf(logfile, " CR2=%08x", env->cr[2]); | |
1117 | + fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]); | |
866 | 1118 | } else { |
867 | - fprintf(logfile, " EAX=%08x", EAX); | |
1119 | + fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX); | |
868 | 1120 | } |
869 | 1121 | fprintf(logfile, "\n"); |
870 | -#if 0 | |
871 | 1122 | cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP); |
1123 | +#if 0 | |
872 | 1124 | { |
873 | 1125 | int i; |
874 | 1126 | uint8_t *ptr; |
... | ... | @@ -885,7 +1137,14 @@ void do_interrupt(int intno, int is_int, int error_code, |
885 | 1137 | } |
886 | 1138 | #endif |
887 | 1139 | if (env->cr[0] & CR0_PE_MASK) { |
888 | - do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); | |
1140 | +#if TARGET_X86_64 | |
1141 | + if (env->hflags & HF_LMA_MASK) { | |
1142 | + do_interrupt64(intno, is_int, error_code, next_eip, is_hw); | |
1143 | + } else | |
1144 | +#endif | |
1145 | + { | |
1146 | + do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw); | |
1147 | + } | |
889 | 1148 | } else { |
890 | 1149 | do_interrupt_real(intno, is_int, error_code, next_eip); |
891 | 1150 | } |
... | ... | @@ -932,20 +1191,20 @@ void raise_exception(int exception_index) |
932 | 1191 | #ifdef BUGGY_GCC_DIV64 |
933 | 1192 | /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we |
934 | 1193 | call it from another function */ |
935 | -uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den) | |
1194 | +uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den) | |
936 | 1195 | { |
937 | 1196 | *q_ptr = num / den; |
938 | 1197 | return num % den; |
939 | 1198 | } |
940 | 1199 | |
941 | -int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den) | |
1200 | +int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den) | |
942 | 1201 | { |
943 | 1202 | *q_ptr = num / den; |
944 | 1203 | return num % den; |
945 | 1204 | } |
946 | 1205 | #endif |
947 | 1206 | |
948 | -void helper_divl_EAX_T0(uint32_t eip) | |
1207 | +void helper_divl_EAX_T0(void) | |
949 | 1208 | { |
950 | 1209 | unsigned int den, q, r; |
951 | 1210 | uint64_t num; |
... | ... | @@ -953,20 +1212,19 @@ void helper_divl_EAX_T0(uint32_t eip) |
953 | 1212 | num = EAX | ((uint64_t)EDX << 32); |
954 | 1213 | den = T0; |
955 | 1214 | if (den == 0) { |
956 | - EIP = eip; | |
957 | 1215 | raise_exception(EXCP00_DIVZ); |
958 | 1216 | } |
959 | 1217 | #ifdef BUGGY_GCC_DIV64 |
960 | - r = div64(&q, num, den); | |
1218 | + r = div32(&q, num, den); | |
961 | 1219 | #else |
962 | 1220 | q = (num / den); |
963 | 1221 | r = (num % den); |
964 | 1222 | #endif |
965 | - EAX = q; | |
966 | - EDX = r; | |
1223 | + EAX = (uint32_t)q; | |
1224 | + EDX = (uint32_t)r; | |
967 | 1225 | } |
968 | 1226 | |
969 | -void helper_idivl_EAX_T0(uint32_t eip) | |
1227 | +void helper_idivl_EAX_T0(void) | |
970 | 1228 | { |
971 | 1229 | int den, q, r; |
972 | 1230 | int64_t num; |
... | ... | @@ -974,17 +1232,16 @@ void helper_idivl_EAX_T0(uint32_t eip) |
974 | 1232 | num = EAX | ((uint64_t)EDX << 32); |
975 | 1233 | den = T0; |
976 | 1234 | if (den == 0) { |
977 | - EIP = eip; | |
978 | 1235 | raise_exception(EXCP00_DIVZ); |
979 | 1236 | } |
980 | 1237 | #ifdef BUGGY_GCC_DIV64 |
981 | - r = idiv64(&q, num, den); | |
1238 | + r = idiv32(&q, num, den); | |
982 | 1239 | #else |
983 | 1240 | q = (num / den); |
984 | 1241 | r = (num % den); |
985 | 1242 | #endif |
986 | - EAX = q; | |
987 | - EDX = r; | |
1243 | + EAX = (uint32_t)q; | |
1244 | + EDX = (uint32_t)r; | |
988 | 1245 | } |
989 | 1246 | |
990 | 1247 | void helper_cmpxchg8b(void) |
... | ... | @@ -993,9 +1250,9 @@ void helper_cmpxchg8b(void) |
993 | 1250 | int eflags; |
994 | 1251 | |
995 | 1252 | eflags = cc_table[CC_OP].compute_all(); |
996 | - d = ldq((uint8_t *)A0); | |
1253 | + d = ldq(A0); | |
997 | 1254 | if (d == (((uint64_t)EDX << 32) | EAX)) { |
998 | - stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX); | |
1255 | + stq(A0, ((uint64_t)ECX << 32) | EBX); | |
999 | 1256 | eflags |= CC_Z; |
1000 | 1257 | } else { |
1001 | 1258 | EDX = d >> 32; |
... | ... | @@ -1005,58 +1262,20 @@ void helper_cmpxchg8b(void) |
1005 | 1262 | CC_SRC = eflags; |
1006 | 1263 | } |
1007 | 1264 | |
1008 | -#define CPUID_FP87 (1 << 0) | |
1009 | -#define CPUID_VME (1 << 1) | |
1010 | -#define CPUID_DE (1 << 2) | |
1011 | -#define CPUID_PSE (1 << 3) | |
1012 | -#define CPUID_TSC (1 << 4) | |
1013 | -#define CPUID_MSR (1 << 5) | |
1014 | -#define CPUID_PAE (1 << 6) | |
1015 | -#define CPUID_MCE (1 << 7) | |
1016 | -#define CPUID_CX8 (1 << 8) | |
1017 | -#define CPUID_APIC (1 << 9) | |
1018 | -#define CPUID_SEP (1 << 11) /* sysenter/sysexit */ | |
1019 | -#define CPUID_MTRR (1 << 12) | |
1020 | -#define CPUID_PGE (1 << 13) | |
1021 | -#define CPUID_MCA (1 << 14) | |
1022 | -#define CPUID_CMOV (1 << 15) | |
1023 | -/* ... */ | |
1024 | -#define CPUID_MMX (1 << 23) | |
1025 | -#define CPUID_FXSR (1 << 24) | |
1026 | -#define CPUID_SSE (1 << 25) | |
1027 | -#define CPUID_SSE2 (1 << 26) | |
1028 | - | |
1029 | 1265 | void helper_cpuid(void) |
1030 | 1266 | { |
1031 | - switch(EAX) { | |
1267 | + switch((uint32_t)EAX) { | |
1032 | 1268 | case 0: |
1033 | 1269 | EAX = 2; /* max EAX index supported */ |
1034 | - EBX = 0x756e6547; | |
1035 | - ECX = 0x6c65746e; | |
1036 | - EDX = 0x49656e69; | |
1270 | + EBX = env->cpuid_vendor1; | |
1271 | + EDX = env->cpuid_vendor2; | |
1272 | + ECX = env->cpuid_vendor3; | |
1037 | 1273 | break; |
1038 | 1274 | case 1: |
1039 | - { | |
1040 | - int family, model, stepping; | |
1041 | - /* EAX = 1 info */ | |
1042 | -#if 0 | |
1043 | - /* pentium 75-200 */ | |
1044 | - family = 5; | |
1045 | - model = 2; | |
1046 | - stepping = 11; | |
1047 | -#else | |
1048 | - /* pentium pro */ | |
1049 | - family = 6; | |
1050 | - model = 1; | |
1051 | - stepping = 3; | |
1052 | -#endif | |
1053 | - EAX = (family << 8) | (model << 4) | stepping; | |
1054 | - EBX = 0; | |
1055 | - ECX = 0; | |
1056 | - EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE | | |
1057 | - CPUID_TSC | CPUID_MSR | CPUID_MCE | | |
1058 | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV; | |
1059 | - } | |
1275 | + EAX = env->cpuid_version; | |
1276 | + EBX = 0; | |
1277 | + ECX = 0; | |
1278 | + EDX = env->cpuid_features; | |
1060 | 1279 | break; |
1061 | 1280 | default: |
1062 | 1281 | /* cache info: needed for Pentium Pro compatibility */ |
... | ... | @@ -1065,12 +1284,34 @@ void helper_cpuid(void) |
1065 | 1284 | ECX = 0; |
1066 | 1285 | EDX = 0; |
1067 | 1286 | break; |
1287 | +#ifdef TARGET_X86_64 | |
1288 | + case 0x80000000: | |
1289 | + EAX = 0x80000008; | |
1290 | + EBX = env->cpuid_vendor1; | |
1291 | + EDX = env->cpuid_vendor2; | |
1292 | + ECX = env->cpuid_vendor3; | |
1293 | + break; | |
1294 | + case 0x80000001: | |
1295 | + EAX = env->cpuid_features; | |
1296 | + EBX = 0; | |
1297 | + ECX = 0; | |
1298 | + /* long mode + syscall/sysret features */ | |
1299 | + EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11); | |
1300 | + break; | |
1301 | + case 0x80000008: | |
1302 | + /* virtual & phys address size in low 2 bytes. */ | |
1303 | + EAX = 0x00003028; | |
1304 | + EBX = 0; | |
1305 | + ECX = 0; | |
1306 | + EDX = 0; | |
1307 | + break; | |
1308 | +#endif | |
1068 | 1309 | } |
1069 | 1310 | } |
1070 | 1311 | |
1071 | 1312 | void helper_enter_level(int level, int data32) |
1072 | 1313 | { |
1073 | - uint8_t *ssp; | |
1314 | + target_ulong ssp; | |
1074 | 1315 | uint32_t esp_mask, esp, ebp; |
1075 | 1316 | |
1076 | 1317 | esp_mask = get_sp_mask(env->segs[R_SS].flags); |
... | ... | @@ -1105,20 +1346,26 @@ void helper_lldt_T0(void) |
1105 | 1346 | int selector; |
1106 | 1347 | SegmentCache *dt; |
1107 | 1348 | uint32_t e1, e2; |
1108 | - int index; | |
1109 | - uint8_t *ptr; | |
1349 | + int index, entry_limit; | |
1350 | + target_ulong ptr; | |
1110 | 1351 | |
1111 | 1352 | selector = T0 & 0xffff; |
1112 | 1353 | if ((selector & 0xfffc) == 0) { |
1113 | 1354 | /* XXX: NULL selector case: invalid LDT */ |
1114 | - env->ldt.base = NULL; | |
1355 | + env->ldt.base = 0; | |
1115 | 1356 | env->ldt.limit = 0; |
1116 | 1357 | } else { |
1117 | 1358 | if (selector & 0x4) |
1118 | 1359 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1119 | 1360 | dt = &env->gdt; |
1120 | 1361 | index = selector & ~7; |
1121 | - if ((index + 7) > dt->limit) | |
1362 | +#ifdef TARGET_X86_64 | |
1363 | + if (env->hflags & HF_LMA_MASK) | |
1364 | + entry_limit = 15; | |
1365 | + else | |
1366 | +#endif | |
1367 | + entry_limit = 7; | |
1368 | + if ((index + entry_limit) > dt->limit) | |
1122 | 1369 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1123 | 1370 | ptr = dt->base + index; |
1124 | 1371 | e1 = ldl_kernel(ptr); |
... | ... | @@ -1127,7 +1374,17 @@ void helper_lldt_T0(void) |
1127 | 1374 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1128 | 1375 | if (!(e2 & DESC_P_MASK)) |
1129 | 1376 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
1130 | - load_seg_cache_raw_dt(&env->ldt, e1, e2); | |
1377 | +#ifdef TARGET_X86_64 | |
1378 | + if (env->hflags & HF_LMA_MASK) { | |
1379 | + uint32_t e3; | |
1380 | + e3 = ldl_kernel(ptr + 8); | |
1381 | + load_seg_cache_raw_dt(&env->ldt, e1, e2); | |
1382 | + env->ldt.base |= (target_ulong)e3 << 32; | |
1383 | + } else | |
1384 | +#endif | |
1385 | + { | |
1386 | + load_seg_cache_raw_dt(&env->ldt, e1, e2); | |
1387 | + } | |
1131 | 1388 | } |
1132 | 1389 | env->ldt.selector = selector; |
1133 | 1390 | } |
... | ... | @@ -1137,13 +1394,13 @@ void helper_ltr_T0(void) |
1137 | 1394 | int selector; |
1138 | 1395 | SegmentCache *dt; |
1139 | 1396 | uint32_t e1, e2; |
1140 | - int index, type; | |
1141 | - uint8_t *ptr; | |
1397 | + int index, type, entry_limit; | |
1398 | + target_ulong ptr; | |
1142 | 1399 | |
1143 | 1400 | selector = T0 & 0xffff; |
1144 | 1401 | if ((selector & 0xfffc) == 0) { |
1145 | - /* NULL selector case: invalid LDT */ | |
1146 | - env->tr.base = NULL; | |
1402 | + /* NULL selector case: invalid TR */ | |
1403 | + env->tr.base = 0; | |
1147 | 1404 | env->tr.limit = 0; |
1148 | 1405 | env->tr.flags = 0; |
1149 | 1406 | } else { |
... | ... | @@ -1151,7 +1408,13 @@ void helper_ltr_T0(void) |
1151 | 1408 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1152 | 1409 | dt = &env->gdt; |
1153 | 1410 | index = selector & ~7; |
1154 | - if ((index + 7) > dt->limit) | |
1411 | +#ifdef TARGET_X86_64 | |
1412 | + if (env->hflags & HF_LMA_MASK) | |
1413 | + entry_limit = 15; | |
1414 | + else | |
1415 | +#endif | |
1416 | + entry_limit = 7; | |
1417 | + if ((index + entry_limit) > dt->limit) | |
1155 | 1418 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1156 | 1419 | ptr = dt->base + index; |
1157 | 1420 | e1 = ldl_kernel(ptr); |
... | ... | @@ -1162,7 +1425,17 @@ void helper_ltr_T0(void) |
1162 | 1425 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1163 | 1426 | if (!(e2 & DESC_P_MASK)) |
1164 | 1427 | raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
1165 | - load_seg_cache_raw_dt(&env->tr, e1, e2); | |
1428 | +#ifdef TARGET_X86_64 | |
1429 | + if (env->hflags & HF_LMA_MASK) { | |
1430 | + uint32_t e3; | |
1431 | + e3 = ldl_kernel(ptr + 8); | |
1432 | + load_seg_cache_raw_dt(&env->tr, e1, e2); | |
1433 | + env->tr.base |= (target_ulong)e3 << 32; | |
1434 | + } else | |
1435 | +#endif | |
1436 | + { | |
1437 | + load_seg_cache_raw_dt(&env->tr, e1, e2); | |
1438 | + } | |
1166 | 1439 | e2 |= DESC_TSS_BUSY_MASK; |
1167 | 1440 | stl_kernel(ptr + 4, e2); |
1168 | 1441 | } |
... | ... | @@ -1176,14 +1449,14 @@ void load_seg(int seg_reg, int selector) |
1176 | 1449 | int cpl, dpl, rpl; |
1177 | 1450 | SegmentCache *dt; |
1178 | 1451 | int index; |
1179 | - uint8_t *ptr; | |
1452 | + target_ulong ptr; | |
1180 | 1453 | |
1181 | 1454 | selector &= 0xffff; |
1182 | 1455 | if ((selector & 0xfffc) == 0) { |
1183 | 1456 | /* null selector case */ |
1184 | 1457 | if (seg_reg == R_SS) |
1185 | 1458 | raise_exception_err(EXCP0D_GPF, 0); |
1186 | - cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0); | |
1459 | + cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0); | |
1187 | 1460 | } else { |
1188 | 1461 | |
1189 | 1462 | if (selector & 0x4) |
... | ... | @@ -1196,7 +1469,7 @@ void load_seg(int seg_reg, int selector) |
1196 | 1469 | ptr = dt->base + index; |
1197 | 1470 | e1 = ldl_kernel(ptr); |
1198 | 1471 | e2 = ldl_kernel(ptr + 4); |
1199 | - | |
1472 | + | |
1200 | 1473 | if (!(e2 & DESC_S_MASK)) |
1201 | 1474 | raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1202 | 1475 | rpl = selector & 3; |
... | ... | @@ -1247,9 +1520,10 @@ void load_seg(int seg_reg, int selector) |
1247 | 1520 | /* protected mode jump */ |
1248 | 1521 | void helper_ljmp_protected_T0_T1(int next_eip) |
1249 | 1522 | { |
1250 | - int new_cs, new_eip, gate_cs, type; | |
1523 | + int new_cs, gate_cs, type; | |
1251 | 1524 | uint32_t e1, e2, cpl, dpl, rpl, limit; |
1252 | - | |
1525 | + target_ulong new_eip; | |
1526 | + | |
1253 | 1527 | new_cs = T0; |
1254 | 1528 | new_eip = T1; |
1255 | 1529 | if ((new_cs & 0xfffc) == 0) |
... | ... | @@ -1312,7 +1586,7 @@ void helper_ljmp_protected_T0_T1(int next_eip) |
1312 | 1586 | if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != |
1313 | 1587 | (DESC_S_MASK | DESC_CS_MASK))) |
1314 | 1588 | raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); |
1315 | - if (((e2 & DESC_C_MASK) && (dpl > cpl)) || | |
1589 | + if (((e2 & DESC_C_MASK) && (dpl > cpl)) || | |
1316 | 1590 | (!(e2 & DESC_C_MASK) && (dpl != cpl))) |
1317 | 1591 | raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc); |
1318 | 1592 | if (!(e2 & DESC_P_MASK)) |
... | ... | @@ -1336,7 +1610,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) |
1336 | 1610 | { |
1337 | 1611 | int new_cs, new_eip; |
1338 | 1612 | uint32_t esp, esp_mask; |
1339 | - uint8_t *ssp; | |
1613 | + target_ulong ssp; | |
1340 | 1614 | |
1341 | 1615 | new_cs = T0; |
1342 | 1616 | new_eip = T1; |
... | ... | @@ -1354,7 +1628,7 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) |
1354 | 1628 | ESP = (ESP & ~esp_mask) | (esp & esp_mask); |
1355 | 1629 | env->eip = new_eip; |
1356 | 1630 | env->segs[R_CS].selector = new_cs; |
1357 | - env->segs[R_CS].base = (uint8_t *)(new_cs << 4); | |
1631 | + env->segs[R_CS].base = (new_cs << 4); | |
1358 | 1632 | } |
1359 | 1633 | |
1360 | 1634 | /* protected mode call */ |
... | ... | @@ -1364,7 +1638,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1364 | 1638 | uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
1365 | 1639 | uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
1366 | 1640 | uint32_t val, limit, old_sp_mask; |
1367 | - uint8_t *ssp, *old_ssp; | |
1641 | + target_ulong ssp, old_ssp; | |
1368 | 1642 | |
1369 | 1643 | new_cs = T0; |
1370 | 1644 | new_eip = T1; |
... | ... | @@ -1471,7 +1745,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1471 | 1745 | get_ss_esp_from_tss(&ss, &sp, dpl); |
1472 | 1746 | #ifdef DEBUG_PCALL |
1473 | 1747 | if (loglevel & CPU_LOG_PCALL) |
1474 | - fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=%x\n", | |
1748 | + fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", | |
1475 | 1749 | ss, sp, param_count, ESP); |
1476 | 1750 | #endif |
1477 | 1751 | if ((ss & 0xfffc) == 0) |
... | ... | @@ -1555,7 +1829,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip) |
1555 | 1829 | void helper_iret_real(int shift) |
1556 | 1830 | { |
1557 | 1831 | uint32_t sp, new_cs, new_eip, new_eflags, sp_mask; |
1558 | - uint8_t *ssp; | |
1832 | + target_ulong ssp; | |
1559 | 1833 | int eflags_mask; |
1560 | 1834 | |
1561 | 1835 | sp_mask = 0xffff; /* XXXX: use SS segment size ? */ |
... | ... | @@ -1595,7 +1869,7 @@ static inline void validate_seg(int seg_reg, int cpl) |
1595 | 1869 | if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) { |
1596 | 1870 | /* data or non conforming code segment */ |
1597 | 1871 | if (dpl < cpl) { |
1598 | - cpu_x86_load_seg_cache(env, seg_reg, 0, NULL, 0, 0); | |
1872 | + cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0); | |
1599 | 1873 | } |
1600 | 1874 | } |
1601 | 1875 | } |
... | ... | @@ -1603,16 +1877,31 @@ static inline void validate_seg(int seg_reg, int cpl) |
1603 | 1877 | /* protected mode iret */ |
1604 | 1878 | static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1605 | 1879 | { |
1606 | - uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask; | |
1880 | + uint32_t new_cs, new_eflags, new_ss; | |
1607 | 1881 | uint32_t new_es, new_ds, new_fs, new_gs; |
1608 | 1882 | uint32_t e1, e2, ss_e1, ss_e2; |
1609 | 1883 | int cpl, dpl, rpl, eflags_mask, iopl; |
1610 | - uint8_t *ssp; | |
1884 | + target_ulong ssp, sp, new_eip, new_esp, sp_mask; | |
1611 | 1885 | |
1612 | - sp_mask = get_sp_mask(env->segs[R_SS].flags); | |
1886 | +#ifdef TARGET_X86_64 | |
1887 | + if (shift == 2) | |
1888 | + sp_mask = -1; | |
1889 | + else | |
1890 | +#endif | |
1891 | + sp_mask = get_sp_mask(env->segs[R_SS].flags); | |
1613 | 1892 | sp = ESP; |
1614 | 1893 | ssp = env->segs[R_SS].base; |
1615 | 1894 | new_eflags = 0; /* avoid warning */ |
1895 | +#ifdef TARGET_X86_64 | |
1896 | + if (shift == 2) { | |
1897 | + POPQ(sp, new_eip); | |
1898 | + POPQ(sp, new_cs); | |
1899 | + new_cs &= 0xffff; | |
1900 | + if (is_iret) { | |
1901 | + POPQ(sp, new_eflags); | |
1902 | + } | |
1903 | + } else | |
1904 | +#endif | |
1616 | 1905 | if (shift == 1) { |
1617 | 1906 | /* 32 bits */ |
1618 | 1907 | POPL(ssp, sp, sp_mask, new_eip); |
... | ... | @@ -1632,7 +1921,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1632 | 1921 | } |
1633 | 1922 | #ifdef DEBUG_PCALL |
1634 | 1923 | if (loglevel & CPU_LOG_PCALL) { |
1635 | - fprintf(logfile, "lret new %04x:%08x s=%d addend=0x%x\n", | |
1924 | + fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n", | |
1636 | 1925 | new_cs, new_eip, shift, addend); |
1637 | 1926 | cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP); |
1638 | 1927 | } |
... | ... | @@ -1660,7 +1949,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1660 | 1949 | raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
1661 | 1950 | |
1662 | 1951 | sp += addend; |
1663 | - if (rpl == cpl) { | |
1952 | + if (rpl == cpl && !(env->hflags & HF_CS64_MASK)) { | |
1664 | 1953 | /* return to same priledge level */ |
1665 | 1954 | cpu_x86_load_seg_cache(env, R_CS, new_cs, |
1666 | 1955 | get_seg_base(e1, e2), |
... | ... | @@ -1668,6 +1957,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1668 | 1957 | e2); |
1669 | 1958 | } else { |
1670 | 1959 | /* return to different priviledge level */ |
1960 | +#ifdef TARGET_X86_64 | |
1961 | + if (shift == 2) { | |
1962 | + POPQ(sp, new_esp); | |
1963 | + POPQ(sp, new_ss); | |
1964 | + new_ss &= 0xffff; | |
1965 | + } else | |
1966 | +#endif | |
1671 | 1967 | if (shift == 1) { |
1672 | 1968 | /* 32 bits */ |
1673 | 1969 | POPL(ssp, sp, sp_mask, new_esp); |
... | ... | @@ -1680,36 +1976,49 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
1680 | 1976 | } |
1681 | 1977 | #ifdef DEBUG_PCALL |
1682 | 1978 | if (loglevel & CPU_LOG_PCALL) { |
1683 | - fprintf(logfile, "new ss:esp=%04x:%08x\n", | |
1979 | + fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n", | |
1684 | 1980 | new_ss, new_esp); |
1685 | 1981 | } |
1686 | 1982 | #endif |
1687 | - | |
1688 | - if ((new_ss & 3) != rpl) | |
1689 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1690 | - if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) | |
1691 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1692 | - if (!(ss_e2 & DESC_S_MASK) || | |
1693 | - (ss_e2 & DESC_CS_MASK) || | |
1694 | - !(ss_e2 & DESC_W_MASK)) | |
1695 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1696 | - dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; | |
1697 | - if (dpl != rpl) | |
1698 | - raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1699 | - if (!(ss_e2 & DESC_P_MASK)) | |
1700 | - raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc); | |
1983 | + if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) { | |
1984 | + /* NULL ss is allowed in long mode */ | |
1985 | + cpu_x86_load_seg_cache(env, R_SS, new_ss, | |
1986 | + 0, 0xffffffff, | |
1987 | + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | | |
1988 | + DESC_S_MASK | (rpl << DESC_DPL_SHIFT) | | |
1989 | + DESC_W_MASK | DESC_A_MASK); | |
1990 | + } else { | |
1991 | + if ((new_ss & 3) != rpl) | |
1992 | + raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1993 | + if (load_segment(&ss_e1, &ss_e2, new_ss) != 0) | |
1994 | + raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1995 | + if (!(ss_e2 & DESC_S_MASK) || | |
1996 | + (ss_e2 & DESC_CS_MASK) || | |
1997 | + !(ss_e2 & DESC_W_MASK)) | |
1998 | + raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
1999 | + dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3; | |
2000 | + if (dpl != rpl) | |
2001 | + raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc); | |
2002 | + if (!(ss_e2 & DESC_P_MASK)) | |
2003 | + raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc); | |
2004 | + cpu_x86_load_seg_cache(env, R_SS, new_ss, | |
2005 | + get_seg_base(ss_e1, ss_e2), | |
2006 | + get_seg_limit(ss_e1, ss_e2), | |
2007 | + ss_e2); | |
2008 | + } | |
1701 | 2009 | |
1702 | 2010 | cpu_x86_load_seg_cache(env, R_CS, new_cs, |
1703 | 2011 | get_seg_base(e1, e2), |
1704 | 2012 | get_seg_limit(e1, e2), |
1705 | 2013 | e2); |
1706 | - cpu_x86_load_seg_cache(env, R_SS, new_ss, | |
1707 | - get_seg_base(ss_e1, ss_e2), | |
1708 | - get_seg_limit(ss_e1, ss_e2), | |
1709 | - ss_e2); | |
1710 | 2014 | cpu_x86_set_cpl(env, rpl); |
1711 | 2015 | sp = new_esp; |
1712 | - sp_mask = get_sp_mask(ss_e2); | |
2016 | +#ifdef TARGET_X86_64 | |
2017 | + if (shift == 2) | |
2018 | + sp_mask = -1; | |
2019 | + else | |
2020 | +#endif | |
2021 | + sp_mask = get_sp_mask(ss_e2); | |
1713 | 2022 | |
1714 | 2023 | /* validate data segments */ |
1715 | 2024 | validate_seg(R_ES, cpl); |
... | ... | @@ -1765,6 +2074,10 @@ void helper_iret_protected(int shift, int next_eip) |
1765 | 2074 | |
1766 | 2075 | /* specific case for TSS */ |
1767 | 2076 | if (env->eflags & NT_MASK) { |
2077 | +#ifdef TARGET_X86_64 | |
2078 | + if (env->hflags & HF_LMA_MASK) | |
2079 | + raise_exception_err(EXCP0D_GPF, 0); | |
2080 | +#endif | |
1768 | 2081 | tss_selector = lduw_kernel(env->tr.base + 0); |
1769 | 2082 | if (tss_selector & 4) |
1770 | 2083 | raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc); |
... | ... | @@ -1793,12 +2106,12 @@ void helper_sysenter(void) |
1793 | 2106 | env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK); |
1794 | 2107 | cpu_x86_set_cpl(env, 0); |
1795 | 2108 | cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, |
1796 | - NULL, 0xffffffff, | |
2109 | + 0, 0xffffffff, | |
1797 | 2110 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
1798 | 2111 | DESC_S_MASK | |
1799 | 2112 | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); |
1800 | 2113 | cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, |
1801 | - NULL, 0xffffffff, | |
2114 | + 0, 0xffffffff, | |
1802 | 2115 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
1803 | 2116 | DESC_S_MASK | |
1804 | 2117 | DESC_W_MASK | DESC_A_MASK); |
... | ... | @@ -1816,12 +2129,12 @@ void helper_sysexit(void) |
1816 | 2129 | } |
1817 | 2130 | cpu_x86_set_cpl(env, 3); |
1818 | 2131 | cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, |
1819 | - NULL, 0xffffffff, | |
2132 | + 0, 0xffffffff, | |
1820 | 2133 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
1821 | 2134 | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | |
1822 | 2135 | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); |
1823 | 2136 | cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, |
1824 | - NULL, 0xffffffff, | |
2137 | + 0, 0xffffffff, | |
1825 | 2138 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | |
1826 | 2139 | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | |
1827 | 2140 | DESC_W_MASK | DESC_A_MASK); |
... | ... | @@ -1863,22 +2176,67 @@ void helper_rdtsc(void) |
1863 | 2176 | uint64_t val; |
1864 | 2177 | |
1865 | 2178 | val = cpu_get_tsc(env); |
1866 | - EAX = val; | |
1867 | - EDX = val >> 32; | |
2179 | + EAX = (uint32_t)(val); | |
2180 | + EDX = (uint32_t)(val >> 32); | |
2181 | +} | |
2182 | + | |
2183 | +#if defined(CONFIG_USER_ONLY) | |
2184 | +void helper_wrmsr(void) | |
2185 | +{ | |
1868 | 2186 | } |
1869 | 2187 | |
2188 | +void helper_rdmsr(void) | |
2189 | +{ | |
2190 | +} | |
2191 | +#else | |
1870 | 2192 | void helper_wrmsr(void) |
1871 | 2193 | { |
1872 | - switch(ECX) { | |
2194 | + uint64_t val; | |
2195 | + | |
2196 | + val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); | |
2197 | + | |
2198 | + switch((uint32_t)ECX) { | |
1873 | 2199 | case MSR_IA32_SYSENTER_CS: |
1874 | - env->sysenter_cs = EAX & 0xffff; | |
2200 | + env->sysenter_cs = val & 0xffff; | |
1875 | 2201 | break; |
1876 | 2202 | case MSR_IA32_SYSENTER_ESP: |
1877 | - env->sysenter_esp = EAX; | |
2203 | + env->sysenter_esp = val; | |
1878 | 2204 | break; |
1879 | 2205 | case MSR_IA32_SYSENTER_EIP: |
1880 | - env->sysenter_eip = EAX; | |
2206 | + env->sysenter_eip = val; | |
2207 | + break; | |
2208 | + case MSR_IA32_APICBASE: | |
2209 | + cpu_set_apic_base(env, val); | |
2210 | + break; | |
2211 | +#ifdef TARGET_X86_64 | |
2212 | + case MSR_EFER: | |
2213 | +#define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \ | |
2214 | + MSR_EFER_NXE | MSR_EFER_FFXSR) | |
2215 | + env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | | |
2216 | + (val & MSR_EFER_UPDATE_MASK); | |
1881 | 2217 | break; |
2218 | + case MSR_STAR: | |
2219 | + env->star = val; | |
2220 | + break; | |
2221 | + case MSR_LSTAR: | |
2222 | + env->lstar = val; | |
2223 | + break; | |
2224 | + case MSR_CSTAR: | |
2225 | + env->cstar = val; | |
2226 | + break; | |
2227 | + case MSR_FMASK: | |
2228 | + env->fmask = val; | |
2229 | + break; | |
2230 | + case MSR_FSBASE: | |
2231 | + env->segs[R_FS].base = val; | |
2232 | + break; | |
2233 | + case MSR_GSBASE: | |
2234 | + env->segs[R_GS].base = val; | |
2235 | + break; | |
2236 | + case MSR_KERNELGSBASE: | |
2237 | + env->kernelgsbase = val; | |
2238 | + break; | |
2239 | +#endif | |
1882 | 2240 | default: |
1883 | 2241 | /* XXX: exception ? */ |
1884 | 2242 | break; |
... | ... | @@ -1887,24 +2245,55 @@ void helper_wrmsr(void) |
1887 | 2245 | |
1888 | 2246 | void helper_rdmsr(void) |
1889 | 2247 | { |
1890 | - switch(ECX) { | |
2248 | + uint64_t val; | |
2249 | + switch((uint32_t)ECX) { | |
1891 | 2250 | case MSR_IA32_SYSENTER_CS: |
1892 | - EAX = env->sysenter_cs; | |
1893 | - EDX = 0; | |
2251 | + val = env->sysenter_cs; | |
1894 | 2252 | break; |
1895 | 2253 | case MSR_IA32_SYSENTER_ESP: |
1896 | - EAX = env->sysenter_esp; | |
1897 | - EDX = 0; | |
2254 | + val = env->sysenter_esp; | |
1898 | 2255 | break; |
1899 | 2256 | case MSR_IA32_SYSENTER_EIP: |
1900 | - EAX = env->sysenter_eip; | |
1901 | - EDX = 0; | |
2257 | + val = env->sysenter_eip; | |
2258 | + break; | |
2259 | + case MSR_IA32_APICBASE: | |
2260 | + val = cpu_get_apic_base(env); | |
2261 | + break; | |
2262 | +#ifdef TARGET_X86_64 | |
2263 | + case MSR_EFER: | |
2264 | + val = env->efer; | |
2265 | + break; | |
2266 | + case MSR_STAR: | |
2267 | + val = env->star; | |
2268 | + break; | |
2269 | + case MSR_LSTAR: | |
2270 | + val = env->lstar; | |
2271 | + break; | |
2272 | + case MSR_CSTAR: | |
2273 | + val = env->cstar; | |
2274 | + break; | |
2275 | + case MSR_FMASK: | |
2276 | + val = env->fmask; | |
2277 | + break; | |
2278 | + case MSR_FSBASE: | |
2279 | + val = env->segs[R_FS].base; | |
2280 | + break; | |
2281 | + case MSR_GSBASE: | |
2282 | + val = env->segs[R_GS].base; | |
1902 | 2283 | break; |
2284 | + case MSR_KERNELGSBASE: | |
2285 | + val = env->kernelgsbase; | |
2286 | + break; | |
2287 | +#endif | |
1903 | 2288 | default: |
1904 | 2289 | /* XXX: exception ? */ |
2290 | + val = 0; | |
1905 | 2291 | break; |
1906 | 2292 | } |
2293 | + EAX = (uint32_t)(val); | |
2294 | + EDX = (uint32_t)(val >> 32); | |
1907 | 2295 | } |
2296 | +#endif | |
1908 | 2297 | |
1909 | 2298 | void helper_lsl(void) |
1910 | 2299 | { |
... | ... | @@ -2055,14 +2444,14 @@ void helper_fldt_ST0_A0(void) |
2055 | 2444 | { |
2056 | 2445 | int new_fpstt; |
2057 | 2446 | new_fpstt = (env->fpstt - 1) & 7; |
2058 | - env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0); | |
2447 | + env->fpregs[new_fpstt] = helper_fldt(A0); | |
2059 | 2448 | env->fpstt = new_fpstt; |
2060 | 2449 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
2061 | 2450 | } |
2062 | 2451 | |
2063 | 2452 | void helper_fstt_ST0_A0(void) |
2064 | 2453 | { |
2065 | - helper_fstt(ST0, (uint8_t *)A0); | |
2454 | + helper_fstt(ST0, A0); | |
2066 | 2455 | } |
2067 | 2456 | |
2068 | 2457 | void fpu_set_exception(int mask) |
... | ... | @@ -2102,11 +2491,11 @@ void helper_fbld_ST0_A0(void) |
2102 | 2491 | |
2103 | 2492 | val = 0; |
2104 | 2493 | for(i = 8; i >= 0; i--) { |
2105 | - v = ldub((uint8_t *)A0 + i); | |
2494 | + v = ldub(A0 + i); | |
2106 | 2495 | val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); |
2107 | 2496 | } |
2108 | 2497 | tmp = val; |
2109 | - if (ldub((uint8_t *)A0 + 9) & 0x80) | |
2498 | + if (ldub(A0 + 9) & 0x80) | |
2110 | 2499 | tmp = -tmp; |
2111 | 2500 | fpush(); |
2112 | 2501 | ST0 = tmp; |
... | ... | @@ -2116,12 +2505,12 @@ void helper_fbst_ST0_A0(void) |
2116 | 2505 | { |
2117 | 2506 | CPU86_LDouble tmp; |
2118 | 2507 | int v; |
2119 | - uint8_t *mem_ref, *mem_end; | |
2508 | + target_ulong mem_ref, mem_end; | |
2120 | 2509 | int64_t val; |
2121 | 2510 | |
2122 | 2511 | tmp = rint(ST0); |
2123 | 2512 | val = (int64_t)tmp; |
2124 | - mem_ref = (uint8_t *)A0; | |
2513 | + mem_ref = A0; | |
2125 | 2514 | mem_end = mem_ref + 9; |
2126 | 2515 | if (val < 0) { |
2127 | 2516 | stb(mem_end, 0x80); |
... | ... | @@ -2402,7 +2791,7 @@ void helper_fxam_ST0(void) |
2402 | 2791 | } |
2403 | 2792 | } |
2404 | 2793 | |
2405 | -void helper_fstenv(uint8_t *ptr, int data32) | |
2794 | +void helper_fstenv(target_ulong ptr, int data32) | |
2406 | 2795 | { |
2407 | 2796 | int fpus, fptag, exp, i; |
2408 | 2797 | uint64_t mant; |
... | ... | @@ -2452,7 +2841,7 @@ void helper_fstenv(uint8_t *ptr, int data32) |
2452 | 2841 | } |
2453 | 2842 | } |
2454 | 2843 | |
2455 | -void helper_fldenv(uint8_t *ptr, int data32) | |
2844 | +void helper_fldenv(target_ulong ptr, int data32) | |
2456 | 2845 | { |
2457 | 2846 | int i, fpus, fptag; |
2458 | 2847 | |
... | ... | @@ -2474,7 +2863,7 @@ void helper_fldenv(uint8_t *ptr, int data32) |
2474 | 2863 | } |
2475 | 2864 | } |
2476 | 2865 | |
2477 | -void helper_fsave(uint8_t *ptr, int data32) | |
2866 | +void helper_fsave(target_ulong ptr, int data32) | |
2478 | 2867 | { |
2479 | 2868 | CPU86_LDouble tmp; |
2480 | 2869 | int i; |
... | ... | @@ -2502,7 +2891,7 @@ void helper_fsave(uint8_t *ptr, int data32) |
2502 | 2891 | env->fptags[7] = 1; |
2503 | 2892 | } |
2504 | 2893 | |
2505 | -void helper_frstor(uint8_t *ptr, int data32) | |
2894 | +void helper_frstor(target_ulong ptr, int data32) | |
2506 | 2895 | { |
2507 | 2896 | CPU86_LDouble tmp; |
2508 | 2897 | int i; |
... | ... | @@ -2517,7 +2906,78 @@ void helper_frstor(uint8_t *ptr, int data32) |
2517 | 2906 | } |
2518 | 2907 | } |
2519 | 2908 | |
2520 | -/* XXX: merge with helper_fstt ? */ | |
2909 | +void helper_fxsave(target_ulong ptr, int data64) | |
2910 | +{ | |
2911 | + int fpus, fptag, i, nb_xmm_regs; | |
2912 | + CPU86_LDouble tmp; | |
2913 | + target_ulong addr; | |
2914 | + | |
2915 | + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; | |
2916 | + fptag = 0; | |
2917 | + for(i = 0; i < 8; i++) { | |
2918 | + fptag |= ((!env->fptags[(env->fpstt + i) & 7]) << i); | |
2919 | + } | |
2920 | + stw(ptr, env->fpuc); | |
2921 | + stw(ptr + 2, fpus); | |
2922 | + stw(ptr + 4, fptag); | |
2923 | + | |
2924 | + addr = ptr + 0x20; | |
2925 | + for(i = 0;i < 8; i++) { | |
2926 | + tmp = ST(i); | |
2927 | + helper_fstt(tmp, addr); | |
2928 | + addr += 16; | |
2929 | + } | |
2930 | + | |
2931 | + if (env->cr[4] & CR4_OSFXSR_MASK) { | |
2932 | + /* XXX: finish it, endianness */ | |
2933 | + stl(ptr + 0x18, 0); /* mxcsr */ | |
2934 | + stl(ptr + 0x1c, 0); /* mxcsr_mask */ | |
2935 | + nb_xmm_regs = 8 << data64; | |
2936 | + addr = ptr + 0xa0; | |
2937 | + for(i = 0; i < nb_xmm_regs; i++) { | |
2938 | + stq(addr, env->xmm_regs[i].u.q[0]); | |
2939 | + stq(addr, env->xmm_regs[i].u.q[1]); | |
2940 | + addr += 16; | |
2941 | + } | |
2942 | + } | |
2943 | +} | |
2944 | + | |
2945 | +void helper_fxrstor(target_ulong ptr, int data64) | |
2946 | +{ | |
2947 | + int i, fpus, fptag, nb_xmm_regs; | |
2948 | + CPU86_LDouble tmp; | |
2949 | + target_ulong addr; | |
2950 | + | |
2951 | + env->fpuc = lduw(ptr); | |
2952 | + fpus = lduw(ptr + 2); | |
2953 | + fptag = ldub(ptr + 4); | |
2954 | + env->fpstt = (fpus >> 11) & 7; | |
2955 | + env->fpus = fpus & ~0x3800; | |
2956 | + fptag ^= 0xff; | |
2957 | + for(i = 0;i < 8; i++) { | |
2958 | + env->fptags[(env->fpstt + i) & 7] = ((fptag >> i) & 1); | |
2959 | + } | |
2960 | + | |
2961 | + addr = ptr + 0x20; | |
2962 | + for(i = 0;i < 8; i++) { | |
2963 | + tmp = helper_fldt(addr); | |
2964 | + ST(i) = tmp; | |
2965 | + addr += 16; | |
2966 | + } | |
2967 | + | |
2968 | + if (env->cr[4] & CR4_OSFXSR_MASK) { | |
2969 | + /* XXX: finish it, endianness */ | |
2970 | + //ldl(ptr + 0x18); | |
2971 | + //ldl(ptr + 0x1c); | |
2972 | + nb_xmm_regs = 8 << data64; | |
2973 | + addr = ptr + 0xa0; | |
2974 | + for(i = 0; i < nb_xmm_regs; i++) { | |
2975 | + env->xmm_regs[i].u.q[0] = ldq(addr); | |
2976 | + env->xmm_regs[i].u.q[1] = ldq(addr); | |
2977 | + addr += 16; | |
2978 | + } | |
2979 | + } | |
2980 | +} | |
2521 | 2981 | |
2522 | 2982 | #ifndef USE_X86LDOUBLE |
2523 | 2983 | |
... | ... | @@ -2575,6 +3035,179 @@ CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper) |
2575 | 3035 | } |
2576 | 3036 | #endif |
2577 | 3037 | |
3038 | +#ifdef TARGET_X86_64 | |
3039 | + | |
3040 | +//#define DEBUG_MULDIV | |
3041 | + | |
3042 | +static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
3043 | +{ | |
3044 | + *plow += a; | |
3045 | + /* carry test */ | |
3046 | + if (*plow < a) | |
3047 | + (*phigh)++; | |
3048 | + *phigh += b; | |
3049 | +} | |
3050 | + | |
3051 | +static void neg128(uint64_t *plow, uint64_t *phigh) | |
3052 | +{ | |
3053 | + *plow = ~ *plow; | |
3054 | + *phigh = ~ *phigh; | |
3055 | + add128(plow, phigh, 1, 0); | |
3056 | +} | |
3057 | + | |
3058 | +static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) | |
3059 | +{ | |
3060 | + uint32_t a0, a1, b0, b1; | |
3061 | + uint64_t v; | |
3062 | + | |
3063 | + a0 = a; | |
3064 | + a1 = a >> 32; | |
3065 | + | |
3066 | + b0 = b; | |
3067 | + b1 = b >> 32; | |
3068 | + | |
3069 | + v = (uint64_t)a0 * (uint64_t)b0; | |
3070 | + *plow = v; | |
3071 | + *phigh = 0; | |
3072 | + | |
3073 | + v = (uint64_t)a0 * (uint64_t)b1; | |
3074 | + add128(plow, phigh, v << 32, v >> 32); | |
3075 | + | |
3076 | + v = (uint64_t)a1 * (uint64_t)b0; | |
3077 | + add128(plow, phigh, v << 32, v >> 32); | |
3078 | + | |
3079 | + v = (uint64_t)a1 * (uint64_t)b1; | |
3080 | + *phigh += v; | |
3081 | +#ifdef DEBUG_MULDIV | |
3082 | + printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n", | |
3083 | + a, b, *phigh, *plow); | |
3084 | +#endif | |
3085 | +} | |
3086 | + | |
3087 | +static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) | |
3088 | +{ | |
3089 | + int sa, sb; | |
3090 | + sa = (a < 0); | |
3091 | + if (sa) | |
3092 | + a = -a; | |
3093 | + sb = (b < 0); | |
3094 | + if (sb) | |
3095 | + b = -b; | |
3096 | + mul64(plow, phigh, a, b); | |
3097 | + if (sa ^ sb) { | |
3098 | + neg128(plow, phigh); | |
3099 | + } | |
3100 | +} | |
3101 | + | |
3102 | +static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b) | |
3103 | +{ | |
3104 | + uint64_t q, r, a1, a0; | |
3105 | + int i, qb; | |
3106 | + | |
3107 | + a0 = *plow; | |
3108 | + a1 = *phigh; | |
3109 | + if (a1 == 0) { | |
3110 | + q = a0 / b; | |
3111 | + r = a0 % b; | |
3112 | + *plow = q; | |
3113 | + *phigh = r; | |
3114 | + } else { | |
3115 | + /* XXX: use a better algorithm */ | |
3116 | + for(i = 0; i < 64; i++) { | |
3117 | + if (a1 >= b) { | |
3118 | + a1 -= b; | |
3119 | + qb = 1; | |
3120 | + } else { | |
3121 | + qb = 0; | |
3122 | + } | |
3123 | + a1 = (a1 << 1) | (a0 >> 63); | |
3124 | + a0 = (a0 << 1) | qb; | |
3125 | + } | |
3126 | +#if defined(DEBUG_MULDIV) || 1 | |
3127 | + printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n", | |
3128 | + *phigh, *plow, b, a0, a1); | |
3129 | +#endif | |
3130 | + *plow = a0; | |
3131 | + *phigh = a1; | |
3132 | + } | |
3133 | +} | |
3134 | + | |
3135 | +static void idiv64(uint64_t *plow, uint64_t *phigh, uint64_t b) | |
3136 | +{ | |
3137 | + int sa, sb; | |
3138 | + sa = ((int64_t)*phigh < 0); | |
3139 | + if (sa) | |
3140 | + neg128(plow, phigh); | |
3141 | + sb = (b < 0); | |
3142 | + if (sb) | |
3143 | + b = -b; | |
3144 | + div64(plow, phigh, b); | |
3145 | + if (sa ^ sb) | |
3146 | + *plow = - *plow; | |
3147 | + if (sb) | |
3148 | + *phigh = - *phigh; | |
3149 | +} | |
3150 | + | |
3151 | +void helper_mulq_EAX_T0(void) | |
3152 | +{ | |
3153 | + uint64_t r0, r1; | |
3154 | + | |
3155 | + mul64(&r0, &r1, EAX, T0); | |
3156 | + EAX = r0; | |
3157 | + EDX = r1; | |
3158 | + CC_DST = r0; | |
3159 | + CC_SRC = r1; | |
3160 | +} | |
3161 | + | |
3162 | +void helper_imulq_EAX_T0(void) | |
3163 | +{ | |
3164 | + uint64_t r0, r1; | |
3165 | + | |
3166 | + imul64(&r0, &r1, EAX, T0); | |
3167 | + EAX = r0; | |
3168 | + EDX = r1; | |
3169 | + CC_DST = r0; | |
3170 | + CC_SRC = (r1 != (r0 >> 63)); | |
3171 | +} | |
3172 | + | |
3173 | +void helper_imulq_T0_T1(void) | |
3174 | +{ | |
3175 | + uint64_t r0, r1; | |
3176 | + | |
3177 | + imul64(&r0, &r1, T0, T1); | |
3178 | + T0 = r0; | |
3179 | + CC_DST = r0; | |
3180 | + CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); | |
3181 | +} | |
3182 | + | |
3183 | +void helper_divq_EAX_T0(void) | |
3184 | +{ | |
3185 | + uint64_t r0, r1; | |
3186 | + if (T0 == 0) { | |
3187 | + raise_exception(EXCP00_DIVZ); | |
3188 | + } | |
3189 | + r0 = EAX; | |
3190 | + r1 = EDX; | |
3191 | + div64(&r0, &r1, T0); | |
3192 | + EAX = r0; | |
3193 | + EDX = r1; | |
3194 | +} | |
3195 | + | |
3196 | +void helper_idivq_EAX_T0(void) | |
3197 | +{ | |
3198 | + uint64_t r0, r1; | |
3199 | + if (T0 == 0) { | |
3200 | + raise_exception(EXCP00_DIVZ); | |
3201 | + } | |
3202 | + r0 = EAX; | |
3203 | + r1 = EDX; | |
3204 | + idiv64(&r0, &r1, T0); | |
3205 | + EAX = r0; | |
3206 | + EDX = r1; | |
3207 | +} | |
3208 | + | |
3209 | +#endif | |
3210 | + | |
2578 | 3211 | #if !defined(CONFIG_USER_ONLY) |
2579 | 3212 | |
2580 | 3213 | #define MMUSUFFIX _mmu |
... | ... | @@ -2598,7 +3231,7 @@ CPU86_LDouble cpu_set_fp80(uint64_t mant, uint16_t upper) |
2598 | 3231 | NULL, it means that the function was called in C code (i.e. not |
2599 | 3232 | from generated code or from helper.c) */ |
2600 | 3233 | /* XXX: fix it to restore all registers */ |
2601 | -void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) | |
3234 | +void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) | |
2602 | 3235 | { |
2603 | 3236 | TranslationBlock *tb; |
2604 | 3237 | int ret; | ... | ... |
target-i386/helper2.c
... | ... | @@ -77,6 +77,41 @@ CPUX86State *cpu_x86_init(void) |
77 | 77 | asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7)); |
78 | 78 | } |
79 | 79 | #endif |
80 | + { | |
81 | + int family, model, stepping; | |
82 | +#ifdef TARGET_X86_64 | |
83 | + env->cpuid_vendor1 = 0x68747541; /* "Auth" */ | |
84 | + env->cpuid_vendor2 = 0x69746e65; /* "enti" */ | |
85 | + env->cpuid_vendor3 = 0x444d4163; /* "cAMD" */ | |
86 | + family = 6; | |
87 | + model = 2; | |
88 | + stepping = 3; | |
89 | +#else | |
90 | + env->cpuid_vendor1 = 0x756e6547; /* "Genu" */ | |
91 | + env->cpuid_vendor2 = 0x49656e69; /* "ineI" */ | |
92 | + env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */ | |
93 | +#if 0 | |
94 | + /* pentium 75-200 */ | |
95 | + family = 5; | |
96 | + model = 2; | |
97 | + stepping = 11; | |
98 | +#else | |
99 | + /* pentium pro */ | |
100 | + family = 6; | |
101 | + model = 1; | |
102 | + stepping = 3; | |
103 | +#endif | |
104 | +#endif | |
105 | + env->cpuid_version = (family << 8) | (model << 4) | stepping; | |
106 | + env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | | |
107 | + CPUID_TSC | CPUID_MSR | CPUID_MCE | | |
108 | + CPUID_CX8 | CPUID_PGE | CPUID_CMOV); | |
109 | +#ifdef TARGET_X86_64 | |
110 | + /* currently not enabled for std i386 because not fully tested */ | |
111 | + env->cpuid_features |= CPUID_APIC | CPUID_FXSR | CPUID_PAE | | |
112 | + CPUID_SSE | CPUID_SSE2; | |
113 | +#endif | |
114 | + } | |
80 | 115 | cpu_single_env = env; |
81 | 116 | cpu_reset(env); |
82 | 117 | return env; |
... | ... | @@ -107,12 +142,12 @@ void cpu_reset(CPUX86State *env) |
107 | 142 | env->tr.limit = 0xffff; |
108 | 143 | env->tr.flags = DESC_P_MASK; |
109 | 144 | |
110 | - cpu_x86_load_seg_cache(env, R_CS, 0xf000, (uint8_t *)0xffff0000, 0xffff, 0); | |
111 | - cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0xffff, 0); | |
112 | - cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0xffff, 0); | |
113 | - cpu_x86_load_seg_cache(env, R_SS, 0, NULL, 0xffff, 0); | |
114 | - cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0xffff, 0); | |
115 | - cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0xffff, 0); | |
145 | + cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff, 0); | |
146 | + cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff, 0); | |
147 | + cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff, 0); | |
148 | + cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff, 0); | |
149 | + cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff, 0); | |
150 | + cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff, 0); | |
116 | 151 | |
117 | 152 | env->eip = 0xfff0; |
118 | 153 | env->regs[R_EDX] = 0x600; /* indicate P6 processor */ |
... | ... | @@ -136,36 +171,56 @@ void cpu_x86_close(CPUX86State *env) |
136 | 171 | static const char *cc_op_str[] = { |
137 | 172 | "DYNAMIC", |
138 | 173 | "EFLAGS", |
174 | + | |
139 | 175 | "MULB", |
140 | 176 | "MULW", |
141 | 177 | "MULL", |
178 | + "MULQ", | |
179 | + | |
142 | 180 | "ADDB", |
143 | 181 | "ADDW", |
144 | 182 | "ADDL", |
183 | + "ADDQ", | |
184 | + | |
145 | 185 | "ADCB", |
146 | 186 | "ADCW", |
147 | 187 | "ADCL", |
188 | + "ADCQ", | |
189 | + | |
148 | 190 | "SUBB", |
149 | 191 | "SUBW", |
150 | 192 | "SUBL", |
193 | + "SUBQ", | |
194 | + | |
151 | 195 | "SBBB", |
152 | 196 | "SBBW", |
153 | 197 | "SBBL", |
198 | + "SBBQ", | |
199 | + | |
154 | 200 | "LOGICB", |
155 | 201 | "LOGICW", |
156 | 202 | "LOGICL", |
203 | + "LOGICQ", | |
204 | + | |
157 | 205 | "INCB", |
158 | 206 | "INCW", |
159 | 207 | "INCL", |
208 | + "INCQ", | |
209 | + | |
160 | 210 | "DECB", |
161 | 211 | "DECW", |
162 | 212 | "DECL", |
213 | + "DECQ", | |
214 | + | |
163 | 215 | "SHLB", |
164 | 216 | "SHLW", |
165 | 217 | "SHLL", |
218 | + "SHLQ", | |
219 | + | |
166 | 220 | "SARB", |
167 | 221 | "SARW", |
168 | 222 | "SARL", |
223 | + "SARQ", | |
169 | 224 | }; |
170 | 225 | |
171 | 226 | void cpu_dump_state(CPUState *env, FILE *f, |
... | ... | @@ -177,55 +232,147 @@ void cpu_dump_state(CPUState *env, FILE *f, |
177 | 232 | static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" }; |
178 | 233 | |
179 | 234 | eflags = env->eflags; |
180 | - cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" | |
181 | - "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" | |
182 | - "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d\n", | |
183 | - env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], | |
184 | - env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], | |
185 | - env->eip, eflags, | |
186 | - eflags & DF_MASK ? 'D' : '-', | |
187 | - eflags & CC_O ? 'O' : '-', | |
188 | - eflags & CC_S ? 'S' : '-', | |
189 | - eflags & CC_Z ? 'Z' : '-', | |
190 | - eflags & CC_A ? 'A' : '-', | |
191 | - eflags & CC_P ? 'P' : '-', | |
192 | - eflags & CC_C ? 'C' : '-', | |
193 | - env->hflags & HF_CPL_MASK, | |
194 | - (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, | |
195 | - (env->a20_mask >> 20) & 1); | |
196 | - for(i = 0; i < 6; i++) { | |
197 | - SegmentCache *sc = &env->segs[i]; | |
198 | - cpu_fprintf(f, "%s =%04x %08x %08x %08x\n", | |
199 | - seg_name[i], | |
200 | - sc->selector, | |
201 | - (int)sc->base, | |
202 | - sc->limit, | |
203 | - sc->flags); | |
235 | +#ifdef TARGET_X86_64 | |
236 | + if (env->hflags & HF_CS64_MASK) { | |
237 | + cpu_fprintf(f, | |
238 | + "RAX=%016llx RBX=%016llx RCX=%016llx RDX=%016llx\n" | |
239 | + "RSI=%016llx RDI=%016llx RBP=%016llx RSP=%016llx\n" | |
240 | + "R8 =%016llx R9 =%016llx R10=%016llx R11=%016llx\n" | |
241 | + "R12=%016llx R13=%016llx R14=%016llx R15=%016llx\n" | |
242 | + "RIP=%016llx RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d\n", | |
243 | + env->regs[R_EAX], | |
244 | + env->regs[R_EBX], | |
245 | + env->regs[R_ECX], | |
246 | + env->regs[R_EDX], | |
247 | + env->regs[R_ESI], | |
248 | + env->regs[R_EDI], | |
249 | + env->regs[R_EBP], | |
250 | + env->regs[R_ESP], | |
251 | + env->regs[8], | |
252 | + env->regs[9], | |
253 | + env->regs[10], | |
254 | + env->regs[11], | |
255 | + env->regs[12], | |
256 | + env->regs[13], | |
257 | + env->regs[14], | |
258 | + env->regs[15], | |
259 | + env->eip, eflags, | |
260 | + eflags & DF_MASK ? 'D' : '-', | |
261 | + eflags & CC_O ? 'O' : '-', | |
262 | + eflags & CC_S ? 'S' : '-', | |
263 | + eflags & CC_Z ? 'Z' : '-', | |
264 | + eflags & CC_A ? 'A' : '-', | |
265 | + eflags & CC_P ? 'P' : '-', | |
266 | + eflags & CC_C ? 'C' : '-', | |
267 | + env->hflags & HF_CPL_MASK, | |
268 | + (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, | |
269 | + (env->a20_mask >> 20) & 1); | |
270 | + } else | |
271 | +#endif | |
272 | + { | |
273 | + cpu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" | |
274 | + "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" | |
275 | + "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d\n", | |
276 | + (uint32_t)env->regs[R_EAX], | |
277 | + (uint32_t)env->regs[R_EBX], | |
278 | + (uint32_t)env->regs[R_ECX], | |
279 | + (uint32_t)env->regs[R_EDX], | |
280 | + (uint32_t)env->regs[R_ESI], | |
281 | + (uint32_t)env->regs[R_EDI], | |
282 | + (uint32_t)env->regs[R_EBP], | |
283 | + (uint32_t)env->regs[R_ESP], | |
284 | + (uint32_t)env->eip, eflags, | |
285 | + eflags & DF_MASK ? 'D' : '-', | |
286 | + eflags & CC_O ? 'O' : '-', | |
287 | + eflags & CC_S ? 'S' : '-', | |
288 | + eflags & CC_Z ? 'Z' : '-', | |
289 | + eflags & CC_A ? 'A' : '-', | |
290 | + eflags & CC_P ? 'P' : '-', | |
291 | + eflags & CC_C ? 'C' : '-', | |
292 | + env->hflags & HF_CPL_MASK, | |
293 | + (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, | |
294 | + (env->a20_mask >> 20) & 1); | |
295 | + } | |
296 | + | |
297 | +#ifdef TARGET_X86_64 | |
298 | + if (env->hflags & HF_LMA_MASK) { | |
299 | + for(i = 0; i < 6; i++) { | |
300 | + SegmentCache *sc = &env->segs[i]; | |
301 | + cpu_fprintf(f, "%s =%04x %016llx %08x %08x\n", | |
302 | + seg_name[i], | |
303 | + sc->selector, | |
304 | + sc->base, | |
305 | + sc->limit, | |
306 | + sc->flags); | |
307 | + } | |
308 | + cpu_fprintf(f, "LDT=%04x %016llx %08x %08x\n", | |
309 | + env->ldt.selector, | |
310 | + env->ldt.base, | |
311 | + env->ldt.limit, | |
312 | + env->ldt.flags); | |
313 | + cpu_fprintf(f, "TR =%04x %016llx %08x %08x\n", | |
314 | + env->tr.selector, | |
315 | + env->tr.base, | |
316 | + env->tr.limit, | |
317 | + env->tr.flags); | |
318 | + cpu_fprintf(f, "GDT= %016llx %08x\n", | |
319 | + env->gdt.base, env->gdt.limit); | |
320 | + cpu_fprintf(f, "IDT= %016llx %08x\n", | |
321 | + env->idt.base, env->idt.limit); | |
322 | + cpu_fprintf(f, "CR0=%08x CR2=%016llx CR3=%016llx CR4=%08x\n", | |
323 | + (uint32_t)env->cr[0], | |
324 | + env->cr[2], | |
325 | + env->cr[3], | |
326 | + (uint32_t)env->cr[4]); | |
327 | + } else | |
328 | +#endif | |
329 | + { | |
330 | + for(i = 0; i < 6; i++) { | |
331 | + SegmentCache *sc = &env->segs[i]; | |
332 | + cpu_fprintf(f, "%s =%04x %08x %08x %08x\n", | |
333 | + seg_name[i], | |
334 | + sc->selector, | |
335 | + (uint32_t)sc->base, | |
336 | + sc->limit, | |
337 | + sc->flags); | |
338 | + } | |
339 | + cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n", | |
340 | + env->ldt.selector, | |
341 | + (uint32_t)env->ldt.base, | |
342 | + env->ldt.limit, | |
343 | + env->ldt.flags); | |
344 | + cpu_fprintf(f, "TR =%04x %08x %08x %08x\n", | |
345 | + env->tr.selector, | |
346 | + (uint32_t)env->tr.base, | |
347 | + env->tr.limit, | |
348 | + env->tr.flags); | |
349 | + cpu_fprintf(f, "GDT= %08x %08x\n", | |
350 | + (uint32_t)env->gdt.base, env->gdt.limit); | |
351 | + cpu_fprintf(f, "IDT= %08x %08x\n", | |
352 | + (uint32_t)env->idt.base, env->idt.limit); | |
353 | + cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n", | |
354 | + (uint32_t)env->cr[0], | |
355 | + (uint32_t)env->cr[2], | |
356 | + (uint32_t)env->cr[3], | |
357 | + (uint32_t)env->cr[4]); | |
204 | 358 | } |
205 | - cpu_fprintf(f, "LDT=%04x %08x %08x %08x\n", | |
206 | - env->ldt.selector, | |
207 | - (int)env->ldt.base, | |
208 | - env->ldt.limit, | |
209 | - env->ldt.flags); | |
210 | - cpu_fprintf(f, "TR =%04x %08x %08x %08x\n", | |
211 | - env->tr.selector, | |
212 | - (int)env->tr.base, | |
213 | - env->tr.limit, | |
214 | - env->tr.flags); | |
215 | - cpu_fprintf(f, "GDT= %08x %08x\n", | |
216 | - (int)env->gdt.base, env->gdt.limit); | |
217 | - cpu_fprintf(f, "IDT= %08x %08x\n", | |
218 | - (int)env->idt.base, env->idt.limit); | |
219 | - cpu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n", | |
220 | - env->cr[0], env->cr[2], env->cr[3], env->cr[4]); | |
221 | - | |
222 | 359 | if (flags & X86_DUMP_CCOP) { |
223 | 360 | if ((unsigned)env->cc_op < CC_OP_NB) |
224 | 361 | snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]); |
225 | 362 | else |
226 | 363 | snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); |
227 | - cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", | |
228 | - env->cc_src, env->cc_dst, cc_op_name); | |
364 | +#ifdef TARGET_X86_64 | |
365 | + if (env->hflags & HF_CS64_MASK) { | |
366 | + cpu_fprintf(f, "CCS=%016llx CCD=%016llx CCO=%-8s\n", | |
367 | + env->cc_src, env->cc_dst, | |
368 | + cc_op_name); | |
369 | + } else | |
370 | +#endif | |
371 | + { | |
372 | + cpu_fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", | |
373 | + (uint32_t)env->cc_src, (uint32_t)env->cc_dst, | |
374 | + cc_op_name); | |
375 | + } | |
229 | 376 | } |
230 | 377 | if (flags & X86_DUMP_FPU) { |
231 | 378 | cpu_fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", |
... | ... | @@ -274,6 +421,24 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) |
274 | 421 | (env->cr[0] & (CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK))) { |
275 | 422 | tlb_flush(env, 1); |
276 | 423 | } |
424 | + | |
425 | +#ifdef TARGET_X86_64 | |
426 | + if (!(env->cr[0] & CR0_PG_MASK) && (new_cr0 & CR0_PG_MASK) && | |
427 | + (env->efer & MSR_EFER_LME)) { | |
428 | + /* enter in long mode */ | |
429 | + /* XXX: generate an exception */ | |
430 | + if (!(env->cr[4] & CR4_PAE_MASK)) | |
431 | + return; | |
432 | + env->efer |= MSR_EFER_LMA; | |
433 | + env->hflags |= HF_LMA_MASK; | |
434 | + } else if ((env->cr[0] & CR0_PG_MASK) && !(new_cr0 & CR0_PG_MASK) && | |
435 | + (env->efer & MSR_EFER_LMA)) { | |
436 | + /* exit long mode */ | |
437 | + env->efer &= ~MSR_EFER_LMA; | |
438 | + env->hflags &= ~(HF_LMA_MASK | HF_CS64_MASK); | |
439 | + env->eip &= 0xffffffff; | |
440 | + } | |
441 | +#endif | |
277 | 442 | env->cr[0] = new_cr0 | CR0_ET_MASK; |
278 | 443 | |
279 | 444 | /* update PE flag in hidden flags */ |
... | ... | @@ -286,12 +451,12 @@ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0) |
286 | 451 | ((new_cr0 << (HF_MP_SHIFT - 1)) & (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK)); |
287 | 452 | } |
288 | 453 | |
289 | -void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3) | |
454 | +void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3) | |
290 | 455 | { |
291 | 456 | env->cr[3] = new_cr3; |
292 | 457 | if (env->cr[0] & CR0_PG_MASK) { |
293 | 458 | #if defined(DEBUG_MMU) |
294 | - printf("CR3 update: CR3=%08x\n", new_cr3); | |
459 | + printf("CR3 update: CR3=" TARGET_FMT_lx "\n", new_cr3); | |
295 | 460 | #endif |
296 | 461 | tlb_flush(env, 0); |
297 | 462 | } |
... | ... | @@ -300,7 +465,7 @@ void cpu_x86_update_cr3(CPUX86State *env, uint32_t new_cr3) |
300 | 465 | void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) |
301 | 466 | { |
302 | 467 | #if defined(DEBUG_MMU) |
303 | - printf("CR4 update: CR4=%08x\n", env->cr[4]); | |
468 | + printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]); | |
304 | 469 | #endif |
305 | 470 | if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) != |
306 | 471 | (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) { |
... | ... | @@ -315,22 +480,51 @@ void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) |
315 | 480 | tlb_flush_page(env, addr); |
316 | 481 | } |
317 | 482 | |
483 | +static inline uint8_t *get_phys_mem_ptr(target_phys_addr_t addr) | |
484 | +{ | |
485 | + /* XXX: incorrect */ | |
486 | + return phys_ram_base + addr; | |
487 | +} | |
488 | + | |
489 | +/* WARNING: addr must be aligned */ | |
490 | +uint32_t ldl_phys_aligned(target_phys_addr_t addr) | |
491 | +{ | |
492 | + uint8_t *ptr; | |
493 | + uint32_t val; | |
494 | + ptr = get_phys_mem_ptr(addr); | |
495 | + if (!ptr) | |
496 | + val = 0; | |
497 | + else | |
498 | + val = ldl_raw(ptr); | |
499 | + return val; | |
500 | +} | |
501 | + | |
502 | +void stl_phys_aligned(target_phys_addr_t addr, uint32_t val) | |
503 | +{ | |
504 | + uint8_t *ptr; | |
505 | + ptr = get_phys_mem_ptr(addr); | |
506 | + if (!ptr) | |
507 | + return; | |
508 | + stl_raw(ptr, val); | |
509 | +} | |
510 | + | |
318 | 511 | /* return value: |
319 | 512 | -1 = cannot handle fault |
320 | 513 | 0 = nothing more to do |
321 | 514 | 1 = generate PF fault |
322 | 515 | 2 = soft MMU activation required for this block |
323 | 516 | */ |
324 | -int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, | |
517 | +int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, | |
325 | 518 | int is_write, int is_user, int is_softmmu) |
326 | 519 | { |
327 | - uint8_t *pde_ptr, *pte_ptr; | |
328 | - uint32_t pde, pte, virt_addr, ptep; | |
520 | + uint32_t pdpe_addr, pde_addr, pte_addr; | |
521 | + uint32_t pde, pte, ptep, pdpe; | |
329 | 522 | int error_code, is_dirty, prot, page_size, ret; |
330 | - unsigned long paddr, vaddr, page_offset; | |
523 | + unsigned long paddr, page_offset; | |
524 | + target_ulong vaddr, virt_addr; | |
331 | 525 | |
332 | 526 | #if defined(DEBUG_MMU) |
333 | - printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", | |
527 | + printf("MMU fault: addr=" TARGET_FMT_lx " w=%d u=%d eip=" TARGET_FMT_lx "\n", | |
334 | 528 | addr, is_write, is_user, env->eip); |
335 | 529 | #endif |
336 | 530 | is_write &= 1; |
... | ... | @@ -349,90 +543,166 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, |
349 | 543 | goto do_mapping; |
350 | 544 | } |
351 | 545 | |
352 | - /* page directory entry */ | |
353 | - pde_ptr = phys_ram_base + | |
354 | - (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & env->a20_mask); | |
355 | - pde = ldl_raw(pde_ptr); | |
356 | - if (!(pde & PG_PRESENT_MASK)) { | |
357 | - error_code = 0; | |
358 | - goto do_fault; | |
359 | - } | |
360 | - /* if PSE bit is set, then we use a 4MB page */ | |
361 | - if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | |
362 | - if (is_user) { | |
363 | - if (!(pde & PG_USER_MASK)) | |
364 | - goto do_fault_protect; | |
365 | - if (is_write && !(pde & PG_RW_MASK)) | |
366 | - goto do_fault_protect; | |
367 | - } else { | |
368 | - if ((env->cr[0] & CR0_WP_MASK) && | |
369 | - is_write && !(pde & PG_RW_MASK)) | |
370 | - goto do_fault_protect; | |
546 | + | |
547 | + if (env->cr[4] & CR4_PAE_MASK) { | |
548 | + /* XXX: we only use 32 bit physical addresses */ | |
549 | +#ifdef TARGET_X86_64 | |
550 | + if (env->hflags & HF_LMA_MASK) { | |
551 | + uint32_t pml4e_addr, pml4e; | |
552 | + int32_t sext; | |
553 | + | |
554 | + /* XXX: handle user + rw rights */ | |
555 | + /* XXX: handle NX flag */ | |
556 | + /* test virtual address sign extension */ | |
557 | + sext = (int64_t)addr >> 47; | |
558 | + if (sext != 0 && sext != -1) { | |
559 | + error_code = 0; | |
560 | + goto do_fault; | |
561 | + } | |
562 | + | |
563 | + pml4e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 39) & 0x1ff) << 3)) & | |
564 | + env->a20_mask; | |
565 | + pml4e = ldl_phys_aligned(pml4e_addr); | |
566 | + if (!(pml4e & PG_PRESENT_MASK)) { | |
567 | + error_code = 0; | |
568 | + goto do_fault; | |
569 | + } | |
570 | + if (!(pml4e & PG_ACCESSED_MASK)) { | |
571 | + pml4e |= PG_ACCESSED_MASK; | |
572 | + stl_phys_aligned(pml4e_addr, pml4e); | |
573 | + } | |
574 | + | |
575 | + pdpe_addr = ((pml4e & ~0xfff) + (((addr >> 30) & 0x1ff) << 3)) & | |
576 | + env->a20_mask; | |
577 | + pdpe = ldl_phys_aligned(pdpe_addr); | |
578 | + if (!(pdpe & PG_PRESENT_MASK)) { | |
579 | + error_code = 0; | |
580 | + goto do_fault; | |
581 | + } | |
582 | + if (!(pdpe & PG_ACCESSED_MASK)) { | |
583 | + pdpe |= PG_ACCESSED_MASK; | |
584 | + stl_phys_aligned(pdpe_addr, pdpe); | |
585 | + } | |
586 | + } else | |
587 | +#endif | |
588 | + { | |
589 | + pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 30) << 3)) & | |
590 | + env->a20_mask; | |
591 | + pdpe = ldl_phys_aligned(pdpe_addr); | |
592 | + if (!(pdpe & PG_PRESENT_MASK)) { | |
593 | + error_code = 0; | |
594 | + goto do_fault; | |
595 | + } | |
371 | 596 | } |
372 | - is_dirty = is_write && !(pde & PG_DIRTY_MASK); | |
373 | - if (!(pde & PG_ACCESSED_MASK) || is_dirty) { | |
374 | - pde |= PG_ACCESSED_MASK; | |
375 | - if (is_dirty) | |
376 | - pde |= PG_DIRTY_MASK; | |
377 | - stl_raw(pde_ptr, pde); | |
597 | + | |
598 | + pde_addr = ((pdpe & ~0xfff) + (((addr >> 21) & 0x1ff) << 3)) & | |
599 | + env->a20_mask; | |
600 | + pde = ldl_phys_aligned(pde_addr); | |
601 | + if (!(pde & PG_PRESENT_MASK)) { | |
602 | + error_code = 0; | |
603 | + goto do_fault; | |
378 | 604 | } |
379 | - | |
380 | - pte = pde & ~0x003ff000; /* align to 4MB */ | |
381 | - ptep = pte; | |
382 | - page_size = 4096 * 1024; | |
383 | - virt_addr = addr & ~0x003fffff; | |
384 | - } else { | |
385 | - if (!(pde & PG_ACCESSED_MASK)) { | |
386 | - pde |= PG_ACCESSED_MASK; | |
387 | - stl_raw(pde_ptr, pde); | |
605 | + if (pde & PG_PSE_MASK) { | |
606 | + /* 2 MB page */ | |
607 | + page_size = 2048 * 1024; | |
608 | + goto handle_big_page; | |
609 | + } else { | |
610 | + /* 4 KB page */ | |
611 | + if (!(pde & PG_ACCESSED_MASK)) { | |
612 | + pde |= PG_ACCESSED_MASK; | |
613 | + stl_phys_aligned(pde_addr, pde); | |
614 | + } | |
615 | + pte_addr = ((pde & ~0xfff) + (((addr >> 12) & 0x1ff) << 3)) & | |
616 | + env->a20_mask; | |
617 | + goto handle_4k_page; | |
388 | 618 | } |
389 | - | |
619 | + } else { | |
390 | 620 | /* page directory entry */ |
391 | - pte_ptr = phys_ram_base + | |
392 | - (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & env->a20_mask); | |
393 | - pte = ldl_raw(pte_ptr); | |
394 | - if (!(pte & PG_PRESENT_MASK)) { | |
621 | + pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & | |
622 | + env->a20_mask; | |
623 | + pde = ldl_phys_aligned(pde_addr); | |
624 | + if (!(pde & PG_PRESENT_MASK)) { | |
395 | 625 | error_code = 0; |
396 | 626 | goto do_fault; |
397 | 627 | } |
398 | - /* combine pde and pte user and rw protections */ | |
399 | - ptep = pte & pde; | |
400 | - if (is_user) { | |
401 | - if (!(ptep & PG_USER_MASK)) | |
402 | - goto do_fault_protect; | |
403 | - if (is_write && !(ptep & PG_RW_MASK)) | |
404 | - goto do_fault_protect; | |
628 | + /* if PSE bit is set, then we use a 4MB page */ | |
629 | + if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { | |
630 | + page_size = 4096 * 1024; | |
631 | + handle_big_page: | |
632 | + if (is_user) { | |
633 | + if (!(pde & PG_USER_MASK)) | |
634 | + goto do_fault_protect; | |
635 | + if (is_write && !(pde & PG_RW_MASK)) | |
636 | + goto do_fault_protect; | |
637 | + } else { | |
638 | + if ((env->cr[0] & CR0_WP_MASK) && | |
639 | + is_write && !(pde & PG_RW_MASK)) | |
640 | + goto do_fault_protect; | |
641 | + } | |
642 | + is_dirty = is_write && !(pde & PG_DIRTY_MASK); | |
643 | + if (!(pde & PG_ACCESSED_MASK) || is_dirty) { | |
644 | + pde |= PG_ACCESSED_MASK; | |
645 | + if (is_dirty) | |
646 | + pde |= PG_DIRTY_MASK; | |
647 | + stl_phys_aligned(pde_addr, pde); | |
648 | + } | |
649 | + | |
650 | + pte = pde & ~( (page_size - 1) & ~0xfff); /* align to page_size */ | |
651 | + ptep = pte; | |
652 | + virt_addr = addr & ~(page_size - 1); | |
405 | 653 | } else { |
406 | - if ((env->cr[0] & CR0_WP_MASK) && | |
407 | - is_write && !(ptep & PG_RW_MASK)) | |
408 | - goto do_fault_protect; | |
409 | - } | |
410 | - is_dirty = is_write && !(pte & PG_DIRTY_MASK); | |
411 | - if (!(pte & PG_ACCESSED_MASK) || is_dirty) { | |
412 | - pte |= PG_ACCESSED_MASK; | |
413 | - if (is_dirty) | |
414 | - pte |= PG_DIRTY_MASK; | |
415 | - stl_raw(pte_ptr, pte); | |
654 | + if (!(pde & PG_ACCESSED_MASK)) { | |
655 | + pde |= PG_ACCESSED_MASK; | |
656 | + stl_phys_aligned(pde_addr, pde); | |
657 | + } | |
658 | + | |
659 | + /* page directory entry */ | |
660 | + pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & | |
661 | + env->a20_mask; | |
662 | + handle_4k_page: | |
663 | + pte = ldl_phys_aligned(pte_addr); | |
664 | + if (!(pte & PG_PRESENT_MASK)) { | |
665 | + error_code = 0; | |
666 | + goto do_fault; | |
667 | + } | |
668 | + /* combine pde and pte user and rw protections */ | |
669 | + ptep = pte & pde; | |
670 | + if (is_user) { | |
671 | + if (!(ptep & PG_USER_MASK)) | |
672 | + goto do_fault_protect; | |
673 | + if (is_write && !(ptep & PG_RW_MASK)) | |
674 | + goto do_fault_protect; | |
675 | + } else { | |
676 | + if ((env->cr[0] & CR0_WP_MASK) && | |
677 | + is_write && !(ptep & PG_RW_MASK)) | |
678 | + goto do_fault_protect; | |
679 | + } | |
680 | + is_dirty = is_write && !(pte & PG_DIRTY_MASK); | |
681 | + if (!(pte & PG_ACCESSED_MASK) || is_dirty) { | |
682 | + pte |= PG_ACCESSED_MASK; | |
683 | + if (is_dirty) | |
684 | + pte |= PG_DIRTY_MASK; | |
685 | + stl_phys_aligned(pte_addr, pte); | |
686 | + } | |
687 | + page_size = 4096; | |
688 | + virt_addr = addr & ~0xfff; | |
416 | 689 | } |
417 | - page_size = 4096; | |
418 | - virt_addr = addr & ~0xfff; | |
419 | - } | |
420 | 690 | |
421 | - /* the page can be put in the TLB */ | |
422 | - prot = PAGE_READ; | |
423 | - if (pte & PG_DIRTY_MASK) { | |
424 | - /* only set write access if already dirty... otherwise wait | |
425 | - for dirty access */ | |
426 | - if (is_user) { | |
427 | - if (ptep & PG_RW_MASK) | |
428 | - prot |= PAGE_WRITE; | |
429 | - } else { | |
430 | - if (!(env->cr[0] & CR0_WP_MASK) || | |
431 | - (ptep & PG_RW_MASK)) | |
432 | - prot |= PAGE_WRITE; | |
691 | + /* the page can be put in the TLB */ | |
692 | + prot = PAGE_READ; | |
693 | + if (pte & PG_DIRTY_MASK) { | |
694 | + /* only set write access if already dirty... otherwise wait | |
695 | + for dirty access */ | |
696 | + if (is_user) { | |
697 | + if (ptep & PG_RW_MASK) | |
698 | + prot |= PAGE_WRITE; | |
699 | + } else { | |
700 | + if (!(env->cr[0] & CR0_WP_MASK) || | |
701 | + (ptep & PG_RW_MASK)) | |
702 | + prot |= PAGE_WRITE; | |
703 | + } | |
433 | 704 | } |
434 | 705 | } |
435 | - | |
436 | 706 | do_mapping: |
437 | 707 | pte = pte & env->a20_mask; |
438 | 708 | ... | ... |
target-i386/op.c
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | #include "exec.h" |
23 | 23 | |
24 | 24 | /* n must be a constant to be efficient */ |
25 | -static inline int lshift(int x, int n) | |
25 | +static inline target_long lshift(target_long x, int n) | |
26 | 26 | { |
27 | 27 | if (n >= 0) |
28 | 28 | return x << n; |
... | ... | @@ -80,6 +80,58 @@ static inline int lshift(int x, int n) |
80 | 80 | #undef REG |
81 | 81 | #undef REGNAME |
82 | 82 | |
83 | +#ifdef TARGET_X86_64 | |
84 | + | |
85 | +#define REG (env->regs[8]) | |
86 | +#define REGNAME _R8 | |
87 | +#include "opreg_template.h" | |
88 | +#undef REG | |
89 | +#undef REGNAME | |
90 | + | |
91 | +#define REG (env->regs[9]) | |
92 | +#define REGNAME _R9 | |
93 | +#include "opreg_template.h" | |
94 | +#undef REG | |
95 | +#undef REGNAME | |
96 | + | |
97 | +#define REG (env->regs[10]) | |
98 | +#define REGNAME _R10 | |
99 | +#include "opreg_template.h" | |
100 | +#undef REG | |
101 | +#undef REGNAME | |
102 | + | |
103 | +#define REG (env->regs[11]) | |
104 | +#define REGNAME _R11 | |
105 | +#include "opreg_template.h" | |
106 | +#undef REG | |
107 | +#undef REGNAME | |
108 | + | |
109 | +#define REG (env->regs[12]) | |
110 | +#define REGNAME _R12 | |
111 | +#include "opreg_template.h" | |
112 | +#undef REG | |
113 | +#undef REGNAME | |
114 | + | |
115 | +#define REG (env->regs[13]) | |
116 | +#define REGNAME _R13 | |
117 | +#include "opreg_template.h" | |
118 | +#undef REG | |
119 | +#undef REGNAME | |
120 | + | |
121 | +#define REG (env->regs[14]) | |
122 | +#define REGNAME _R14 | |
123 | +#include "opreg_template.h" | |
124 | +#undef REG | |
125 | +#undef REGNAME | |
126 | + | |
127 | +#define REG (env->regs[15]) | |
128 | +#define REGNAME _R15 | |
129 | +#include "opreg_template.h" | |
130 | +#undef REG | |
131 | +#undef REGNAME | |
132 | + | |
133 | +#endif | |
134 | + | |
83 | 135 | /* operations with flags */ |
84 | 136 | |
85 | 137 | /* update flags with T0 and T1 (add/sub case) */ |
... | ... | @@ -170,6 +222,13 @@ void OPPROTO op_bswapl_T0(void) |
170 | 222 | T0 = bswap32(T0); |
171 | 223 | } |
172 | 224 | |
225 | +#ifdef TARGET_X86_64 | |
226 | +void OPPROTO op_bswapq_T0(void) | |
227 | +{ | |
228 | + T0 = bswap64(T0); | |
229 | +} | |
230 | +#endif | |
231 | + | |
173 | 232 | /* multiply/divide */ |
174 | 233 | |
175 | 234 | /* XXX: add eflags optimizations */ |
... | ... | @@ -179,7 +238,7 @@ void OPPROTO op_mulb_AL_T0(void) |
179 | 238 | { |
180 | 239 | unsigned int res; |
181 | 240 | res = (uint8_t)EAX * (uint8_t)T0; |
182 | - EAX = (EAX & 0xffff0000) | res; | |
241 | + EAX = (EAX & ~0xffff) | res; | |
183 | 242 | CC_DST = res; |
184 | 243 | CC_SRC = (res & 0xff00); |
185 | 244 | } |
... | ... | @@ -188,7 +247,7 @@ void OPPROTO op_imulb_AL_T0(void) |
188 | 247 | { |
189 | 248 | int res; |
190 | 249 | res = (int8_t)EAX * (int8_t)T0; |
191 | - EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
250 | + EAX = (EAX & ~0xffff) | (res & 0xffff); | |
192 | 251 | CC_DST = res; |
193 | 252 | CC_SRC = (res != (int8_t)res); |
194 | 253 | } |
... | ... | @@ -197,8 +256,8 @@ void OPPROTO op_mulw_AX_T0(void) |
197 | 256 | { |
198 | 257 | unsigned int res; |
199 | 258 | res = (uint16_t)EAX * (uint16_t)T0; |
200 | - EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
201 | - EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); | |
259 | + EAX = (EAX & ~0xffff) | (res & 0xffff); | |
260 | + EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); | |
202 | 261 | CC_DST = res; |
203 | 262 | CC_SRC = res >> 16; |
204 | 263 | } |
... | ... | @@ -207,8 +266,8 @@ void OPPROTO op_imulw_AX_T0(void) |
207 | 266 | { |
208 | 267 | int res; |
209 | 268 | res = (int16_t)EAX * (int16_t)T0; |
210 | - EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
211 | - EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); | |
269 | + EAX = (EAX & ~0xffff) | (res & 0xffff); | |
270 | + EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); | |
212 | 271 | CC_DST = res; |
213 | 272 | CC_SRC = (res != (int16_t)res); |
214 | 273 | } |
... | ... | @@ -217,10 +276,10 @@ void OPPROTO op_mull_EAX_T0(void) |
217 | 276 | { |
218 | 277 | uint64_t res; |
219 | 278 | res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); |
220 | - EAX = res; | |
221 | - EDX = res >> 32; | |
222 | - CC_DST = res; | |
223 | - CC_SRC = res >> 32; | |
279 | + EAX = (uint32_t)res; | |
280 | + EDX = (uint32_t)(res >> 32); | |
281 | + CC_DST = (uint32_t)res; | |
282 | + CC_SRC = (uint32_t)(res >> 32); | |
224 | 283 | } |
225 | 284 | |
226 | 285 | void OPPROTO op_imull_EAX_T0(void) |
... | ... | @@ -251,6 +310,23 @@ void OPPROTO op_imull_T0_T1(void) |
251 | 310 | CC_SRC = (res != (int32_t)res); |
252 | 311 | } |
253 | 312 | |
313 | +#ifdef TARGET_X86_64 | |
314 | +void OPPROTO op_mulq_EAX_T0(void) | |
315 | +{ | |
316 | + helper_mulq_EAX_T0(); | |
317 | +} | |
318 | + | |
319 | +void OPPROTO op_imulq_EAX_T0(void) | |
320 | +{ | |
321 | + helper_imulq_EAX_T0(); | |
322 | +} | |
323 | + | |
324 | +void OPPROTO op_imulq_T0_T1(void) | |
325 | +{ | |
326 | + helper_imulq_T0_T1(); | |
327 | +} | |
328 | +#endif | |
329 | + | |
254 | 330 | /* division, flags are undefined */ |
255 | 331 | /* XXX: add exceptions for overflow */ |
256 | 332 | |
... | ... | @@ -261,12 +337,11 @@ void OPPROTO op_divb_AL_T0(void) |
261 | 337 | num = (EAX & 0xffff); |
262 | 338 | den = (T0 & 0xff); |
263 | 339 | if (den == 0) { |
264 | - EIP = PARAM1; | |
265 | 340 | raise_exception(EXCP00_DIVZ); |
266 | 341 | } |
267 | 342 | q = (num / den) & 0xff; |
268 | 343 | r = (num % den) & 0xff; |
269 | - EAX = (EAX & 0xffff0000) | (r << 8) | q; | |
344 | + EAX = (EAX & ~0xffff) | (r << 8) | q; | |
270 | 345 | } |
271 | 346 | |
272 | 347 | void OPPROTO op_idivb_AL_T0(void) |
... | ... | @@ -276,12 +351,11 @@ void OPPROTO op_idivb_AL_T0(void) |
276 | 351 | num = (int16_t)EAX; |
277 | 352 | den = (int8_t)T0; |
278 | 353 | if (den == 0) { |
279 | - EIP = PARAM1; | |
280 | 354 | raise_exception(EXCP00_DIVZ); |
281 | 355 | } |
282 | 356 | q = (num / den) & 0xff; |
283 | 357 | r = (num % den) & 0xff; |
284 | - EAX = (EAX & 0xffff0000) | (r << 8) | q; | |
358 | + EAX = (EAX & ~0xffff) | (r << 8) | q; | |
285 | 359 | } |
286 | 360 | |
287 | 361 | void OPPROTO op_divw_AX_T0(void) |
... | ... | @@ -291,13 +365,12 @@ void OPPROTO op_divw_AX_T0(void) |
291 | 365 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
292 | 366 | den = (T0 & 0xffff); |
293 | 367 | if (den == 0) { |
294 | - EIP = PARAM1; | |
295 | 368 | raise_exception(EXCP00_DIVZ); |
296 | 369 | } |
297 | 370 | q = (num / den) & 0xffff; |
298 | 371 | r = (num % den) & 0xffff; |
299 | - EAX = (EAX & 0xffff0000) | q; | |
300 | - EDX = (EDX & 0xffff0000) | r; | |
372 | + EAX = (EAX & ~0xffff) | q; | |
373 | + EDX = (EDX & ~0xffff) | r; | |
301 | 374 | } |
302 | 375 | |
303 | 376 | void OPPROTO op_idivw_AX_T0(void) |
... | ... | @@ -307,30 +380,47 @@ void OPPROTO op_idivw_AX_T0(void) |
307 | 380 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); |
308 | 381 | den = (int16_t)T0; |
309 | 382 | if (den == 0) { |
310 | - EIP = PARAM1; | |
311 | 383 | raise_exception(EXCP00_DIVZ); |
312 | 384 | } |
313 | 385 | q = (num / den) & 0xffff; |
314 | 386 | r = (num % den) & 0xffff; |
315 | - EAX = (EAX & 0xffff0000) | q; | |
316 | - EDX = (EDX & 0xffff0000) | r; | |
387 | + EAX = (EAX & ~0xffff) | q; | |
388 | + EDX = (EDX & ~0xffff) | r; | |
317 | 389 | } |
318 | 390 | |
319 | 391 | void OPPROTO op_divl_EAX_T0(void) |
320 | 392 | { |
321 | - helper_divl_EAX_T0(PARAM1); | |
393 | + helper_divl_EAX_T0(); | |
322 | 394 | } |
323 | 395 | |
324 | 396 | void OPPROTO op_idivl_EAX_T0(void) |
325 | 397 | { |
326 | - helper_idivl_EAX_T0(PARAM1); | |
398 | + helper_idivl_EAX_T0(); | |
327 | 399 | } |
328 | 400 | |
401 | +#ifdef TARGET_X86_64 | |
402 | +void OPPROTO op_divq_EAX_T0(void) | |
403 | +{ | |
404 | + helper_divq_EAX_T0(); | |
405 | +} | |
406 | + | |
407 | +void OPPROTO op_idivq_EAX_T0(void) | |
408 | +{ | |
409 | + helper_idivq_EAX_T0(); | |
410 | +} | |
411 | +#endif | |
412 | + | |
329 | 413 | /* constant load & misc op */ |
330 | 414 | |
415 | +/* XXX: consistent names */ | |
416 | +void OPPROTO op_movl_T0_imu(void) | |
417 | +{ | |
418 | + T0 = (uint32_t)PARAM1; | |
419 | +} | |
420 | + | |
331 | 421 | void OPPROTO op_movl_T0_im(void) |
332 | 422 | { |
333 | - T0 = PARAM1; | |
423 | + T0 = (int32_t)PARAM1; | |
334 | 424 | } |
335 | 425 | |
336 | 426 | void OPPROTO op_addl_T0_im(void) |
... | ... | @@ -353,9 +443,14 @@ void OPPROTO op_movl_T0_T1(void) |
353 | 443 | T0 = T1; |
354 | 444 | } |
355 | 445 | |
446 | +void OPPROTO op_movl_T1_imu(void) | |
447 | +{ | |
448 | + T1 = (uint32_t)PARAM1; | |
449 | +} | |
450 | + | |
356 | 451 | void OPPROTO op_movl_T1_im(void) |
357 | 452 | { |
358 | - T1 = PARAM1; | |
453 | + T1 = (int32_t)PARAM1; | |
359 | 454 | } |
360 | 455 | |
361 | 456 | void OPPROTO op_addl_T1_im(void) |
... | ... | @@ -370,19 +465,95 @@ void OPPROTO op_movl_T1_A0(void) |
370 | 465 | |
371 | 466 | void OPPROTO op_movl_A0_im(void) |
372 | 467 | { |
373 | - A0 = PARAM1; | |
468 | + A0 = (uint32_t)PARAM1; | |
374 | 469 | } |
375 | 470 | |
376 | 471 | void OPPROTO op_addl_A0_im(void) |
377 | 472 | { |
378 | - A0 += PARAM1; | |
473 | + A0 = (uint32_t)(A0 + PARAM1); | |
474 | +} | |
475 | + | |
476 | +void OPPROTO op_movl_A0_seg(void) | |
477 | +{ | |
478 | + A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1); | |
479 | +} | |
480 | + | |
481 | +void OPPROTO op_addl_A0_seg(void) | |
482 | +{ | |
483 | + A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1)); | |
379 | 484 | } |
380 | 485 | |
381 | 486 | void OPPROTO op_addl_A0_AL(void) |
382 | 487 | { |
383 | - A0 += (EAX & 0xff); | |
488 | + A0 = (uint32_t)(A0 + (EAX & 0xff)); | |
489 | +} | |
490 | + | |
491 | +#ifdef WORDS_BIGENDIAN | |
492 | +typedef union UREG64 { | |
493 | + struct { uint16_t v3, v2, v1, v0; } w; | |
494 | + struct { uint32_t v1, v0; } l; | |
495 | + uint64_t q; | |
496 | +} UREG64; | |
497 | +#else | |
498 | +typedef union UREG64 { | |
499 | + struct { uint16_t v0, v1, v2, v3; } w; | |
500 | + struct { uint32_t v0, v1; } l; | |
501 | + uint64_t q; | |
502 | +} UREG64; | |
503 | +#endif | |
504 | + | |
505 | +#ifdef TARGET_X86_64 | |
506 | + | |
507 | +#define PARAMQ1 \ | |
508 | +({\ | |
509 | + UREG64 __p;\ | |
510 | + __p.l.v1 = PARAM1;\ | |
511 | + __p.l.v0 = PARAM2;\ | |
512 | + __p.q;\ | |
513 | +}) | |
514 | + | |
515 | +void OPPROTO op_movq_T0_im64(void) | |
516 | +{ | |
517 | + T0 = PARAMQ1; | |
384 | 518 | } |
385 | 519 | |
520 | +void OPPROTO op_movq_A0_im(void) | |
521 | +{ | |
522 | + A0 = (int32_t)PARAM1; | |
523 | +} | |
524 | + | |
525 | +void OPPROTO op_movq_A0_im64(void) | |
526 | +{ | |
527 | + A0 = PARAMQ1; | |
528 | +} | |
529 | + | |
530 | +void OPPROTO op_addq_A0_im(void) | |
531 | +{ | |
532 | + A0 = (A0 + (int32_t)PARAM1); | |
533 | +} | |
534 | + | |
535 | +void OPPROTO op_addq_A0_im64(void) | |
536 | +{ | |
537 | + A0 = (A0 + PARAMQ1); | |
538 | +} | |
539 | + | |
540 | +void OPPROTO op_movq_A0_seg(void) | |
541 | +{ | |
542 | + A0 = *(target_ulong *)((char *)env + PARAM1); | |
543 | +} | |
544 | + | |
545 | +void OPPROTO op_addq_A0_seg(void) | |
546 | +{ | |
547 | + A0 += *(target_ulong *)((char *)env + PARAM1); | |
548 | +} | |
549 | + | |
550 | +void OPPROTO op_addq_A0_AL(void) | |
551 | +{ | |
552 | + A0 = (A0 + (EAX & 0xff)); | |
553 | +} | |
554 | + | |
555 | +#endif | |
556 | + | |
386 | 557 | void OPPROTO op_andl_A0_ffff(void) |
387 | 558 | { |
388 | 559 | A0 = A0 & 0xffff; |
... | ... | @@ -401,29 +572,29 @@ void OPPROTO op_andl_A0_ffff(void) |
401 | 572 | #include "ops_mem.h" |
402 | 573 | #endif |
403 | 574 | |
404 | -/* used for bit operations */ | |
575 | +/* indirect jump */ | |
405 | 576 | |
406 | -void OPPROTO op_add_bitw_A0_T1(void) | |
577 | +void OPPROTO op_jmp_T0(void) | |
407 | 578 | { |
408 | - A0 += ((int16_t)T1 >> 4) << 1; | |
579 | + EIP = T0; | |
409 | 580 | } |
410 | 581 | |
411 | -void OPPROTO op_add_bitl_A0_T1(void) | |
582 | +void OPPROTO op_movl_eip_im(void) | |
412 | 583 | { |
413 | - A0 += ((int32_t)T1 >> 5) << 2; | |
584 | + EIP = (uint32_t)PARAM1; | |
414 | 585 | } |
415 | 586 | |
416 | -/* indirect jump */ | |
417 | - | |
418 | -void OPPROTO op_jmp_T0(void) | |
587 | +#ifdef TARGET_X86_64 | |
588 | +void OPPROTO op_movq_eip_im(void) | |
419 | 589 | { |
420 | - EIP = T0; | |
590 | + EIP = (int32_t)PARAM1; | |
421 | 591 | } |
422 | 592 | |
423 | -void OPPROTO op_jmp_im(void) | |
593 | +void OPPROTO op_movq_eip_im64(void) | |
424 | 594 | { |
425 | - EIP = PARAM1; | |
595 | + EIP = PARAMQ1; | |
426 | 596 | } |
597 | +#endif | |
427 | 598 | |
428 | 599 | void OPPROTO op_hlt(void) |
429 | 600 | { |
... | ... | @@ -505,11 +676,10 @@ void OPPROTO op_sti_vm(void) |
505 | 676 | void OPPROTO op_boundw(void) |
506 | 677 | { |
507 | 678 | int low, high, v; |
508 | - low = ldsw((uint8_t *)A0); | |
509 | - high = ldsw((uint8_t *)A0 + 2); | |
679 | + low = ldsw(A0); | |
680 | + high = ldsw(A0 + 2); | |
510 | 681 | v = (int16_t)T0; |
511 | 682 | if (v < low || v > high) { |
512 | - EIP = PARAM1; | |
513 | 683 | raise_exception(EXCP05_BOUND); |
514 | 684 | } |
515 | 685 | FORCE_RET(); |
... | ... | @@ -518,11 +688,10 @@ void OPPROTO op_boundw(void) |
518 | 688 | void OPPROTO op_boundl(void) |
519 | 689 | { |
520 | 690 | int low, high, v; |
521 | - low = ldl((uint8_t *)A0); | |
522 | - high = ldl((uint8_t *)A0 + 4); | |
691 | + low = ldl(A0); | |
692 | + high = ldl(A0 + 4); | |
523 | 693 | v = T0; |
524 | 694 | if (v < low || v > high) { |
525 | - EIP = PARAM1; | |
526 | 695 | raise_exception(EXCP05_BOUND); |
527 | 696 | } |
528 | 697 | FORCE_RET(); |
... | ... | @@ -533,11 +702,6 @@ void OPPROTO op_cmpxchg8b(void) |
533 | 702 | helper_cmpxchg8b(); |
534 | 703 | } |
535 | 704 | |
536 | -void OPPROTO op_jmp(void) | |
537 | -{ | |
538 | - JUMP_TB(op_jmp, PARAM1, 0, PARAM2); | |
539 | -} | |
540 | - | |
541 | 705 | void OPPROTO op_movl_T0_0(void) |
542 | 706 | { |
543 | 707 | T0 = 0; |
... | ... | @@ -564,6 +728,14 @@ void OPPROTO op_exit_tb(void) |
564 | 728 | #include "ops_template.h" |
565 | 729 | #undef SHIFT |
566 | 730 | |
731 | +#ifdef TARGET_X86_64 | |
732 | + | |
733 | +#define SHIFT 3 | |
734 | +#include "ops_template.h" | |
735 | +#undef SHIFT | |
736 | + | |
737 | +#endif | |
738 | + | |
567 | 739 | /* sign extend */ |
568 | 740 | |
569 | 741 | void OPPROTO op_movsbl_T0_T0(void) |
... | ... | @@ -581,6 +753,11 @@ void OPPROTO op_movswl_T0_T0(void) |
581 | 753 | T0 = (int16_t)T0; |
582 | 754 | } |
583 | 755 | |
756 | +void OPPROTO op_movslq_T0_T0(void) | |
757 | +{ | |
758 | + T0 = (int32_t)T0; | |
759 | +} | |
760 | + | |
584 | 761 | void OPPROTO op_movzwl_T0_T0(void) |
585 | 762 | { |
586 | 763 | T0 = (uint16_t)T0; |
... | ... | @@ -591,9 +768,16 @@ void OPPROTO op_movswl_EAX_AX(void) |
591 | 768 | EAX = (int16_t)EAX; |
592 | 769 | } |
593 | 770 | |
771 | +#ifdef TARGET_X86_64 | |
772 | +void OPPROTO op_movslq_RAX_EAX(void) | |
773 | +{ | |
774 | + EAX = (int32_t)EAX; | |
775 | +} | |
776 | +#endif | |
777 | + | |
594 | 778 | void OPPROTO op_movsbw_AX_AL(void) |
595 | 779 | { |
596 | - EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff); | |
780 | + EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff); | |
597 | 781 | } |
598 | 782 | |
599 | 783 | void OPPROTO op_movslq_EDX_EAX(void) |
... | ... | @@ -603,14 +787,21 @@ void OPPROTO op_movslq_EDX_EAX(void) |
603 | 787 | |
604 | 788 | void OPPROTO op_movswl_DX_AX(void) |
605 | 789 | { |
606 | - EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff); | |
790 | + EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff); | |
791 | +} | |
792 | + | |
793 | +#ifdef TARGET_X86_64 | |
794 | +void OPPROTO op_movsqo_RDX_RAX(void) | |
795 | +{ | |
796 | + EDX = (int64_t)EAX >> 63; | |
607 | 797 | } |
798 | +#endif | |
608 | 799 | |
609 | 800 | /* string ops helpers */ |
610 | 801 | |
611 | 802 | void OPPROTO op_addl_ESI_T0(void) |
612 | 803 | { |
613 | - ESI += T0; | |
804 | + ESI = (uint32_t)(ESI + T0); | |
614 | 805 | } |
615 | 806 | |
616 | 807 | void OPPROTO op_addw_ESI_T0(void) |
... | ... | @@ -620,7 +811,7 @@ void OPPROTO op_addw_ESI_T0(void) |
620 | 811 | |
621 | 812 | void OPPROTO op_addl_EDI_T0(void) |
622 | 813 | { |
623 | - EDI += T0; | |
814 | + EDI = (uint32_t)(EDI + T0); | |
624 | 815 | } |
625 | 816 | |
626 | 817 | void OPPROTO op_addw_EDI_T0(void) |
... | ... | @@ -630,7 +821,7 @@ void OPPROTO op_addw_EDI_T0(void) |
630 | 821 | |
631 | 822 | void OPPROTO op_decl_ECX(void) |
632 | 823 | { |
633 | - ECX--; | |
824 | + ECX = (uint32_t)(ECX - 1); | |
634 | 825 | } |
635 | 826 | |
636 | 827 | void OPPROTO op_decw_ECX(void) |
... | ... | @@ -638,6 +829,23 @@ void OPPROTO op_decw_ECX(void) |
638 | 829 | ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); |
639 | 830 | } |
640 | 831 | |
832 | +#ifdef TARGET_X86_64 | |
833 | +void OPPROTO op_addq_ESI_T0(void) | |
834 | +{ | |
835 | + ESI = (ESI + T0); | |
836 | +} | |
837 | + | |
838 | +void OPPROTO op_addq_EDI_T0(void) | |
839 | +{ | |
840 | + EDI = (EDI + T0); | |
841 | +} | |
842 | + | |
843 | +void OPPROTO op_decq_ECX(void) | |
844 | +{ | |
845 | + ECX--; | |
846 | +} | |
847 | +#endif | |
848 | + | |
641 | 849 | /* push/pop utils */ |
642 | 850 | |
643 | 851 | void op_addl_A0_SS(void) |
... | ... | @@ -647,22 +855,22 @@ void op_addl_A0_SS(void) |
647 | 855 | |
648 | 856 | void op_subl_A0_2(void) |
649 | 857 | { |
650 | - A0 -= 2; | |
858 | + A0 = (uint32_t)(A0 - 2); | |
651 | 859 | } |
652 | 860 | |
653 | 861 | void op_subl_A0_4(void) |
654 | 862 | { |
655 | - A0 -= 4; | |
863 | + A0 = (uint32_t)(A0 - 4); | |
656 | 864 | } |
657 | 865 | |
658 | 866 | void op_addl_ESP_4(void) |
659 | 867 | { |
660 | - ESP += 4; | |
868 | + ESP = (uint32_t)(ESP + 4); | |
661 | 869 | } |
662 | 870 | |
663 | 871 | void op_addl_ESP_2(void) |
664 | 872 | { |
665 | - ESP += 2; | |
873 | + ESP = (uint32_t)(ESP + 2); | |
666 | 874 | } |
667 | 875 | |
668 | 876 | void op_addw_ESP_4(void) |
... | ... | @@ -677,7 +885,7 @@ void op_addw_ESP_2(void) |
677 | 885 | |
678 | 886 | void op_addl_ESP_im(void) |
679 | 887 | { |
680 | - ESP += PARAM1; | |
888 | + ESP = (uint32_t)(ESP + PARAM1); | |
681 | 889 | } |
682 | 890 | |
683 | 891 | void op_addw_ESP_im(void) |
... | ... | @@ -685,6 +893,23 @@ void op_addw_ESP_im(void) |
685 | 893 | ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff); |
686 | 894 | } |
687 | 895 | |
896 | +#ifdef TARGET_X86_64 | |
897 | +void op_subq_A0_8(void) | |
898 | +{ | |
899 | + A0 -= 8; | |
900 | +} | |
901 | + | |
902 | +void op_addq_ESP_8(void) | |
903 | +{ | |
904 | + ESP += 8; | |
905 | +} | |
906 | + | |
907 | +void op_addq_ESP_im(void) | |
908 | +{ | |
909 | + ESP += PARAM1; | |
910 | +} | |
911 | +#endif | |
912 | + | |
688 | 913 | void OPPROTO op_rdtsc(void) |
689 | 914 | { |
690 | 915 | helper_rdtsc(); |
... | ... | @@ -710,6 +935,18 @@ void OPPROTO op_sysexit(void) |
710 | 935 | helper_sysexit(); |
711 | 936 | } |
712 | 937 | |
938 | +#ifdef TARGET_X86_64 | |
939 | +void OPPROTO op_syscall(void) | |
940 | +{ | |
941 | + helper_syscall(); | |
942 | +} | |
943 | + | |
944 | +void OPPROTO op_sysret(void) | |
945 | +{ | |
946 | + helper_sysret(PARAM1); | |
947 | +} | |
948 | +#endif | |
949 | + | |
713 | 950 | void OPPROTO op_rdmsr(void) |
714 | 951 | { |
715 | 952 | helper_rdmsr(); |
... | ... | @@ -868,7 +1105,7 @@ void OPPROTO op_movl_seg_T0_vm(void) |
868 | 1105 | /* env->segs[] access */ |
869 | 1106 | sc = (SegmentCache *)((char *)env + PARAM1); |
870 | 1107 | sc->selector = selector; |
871 | - sc->base = (void *)(selector << 4); | |
1108 | + sc->base = (selector << 4); | |
872 | 1109 | } |
873 | 1110 | |
874 | 1111 | void OPPROTO op_movl_T0_seg(void) |
... | ... | @@ -876,16 +1113,6 @@ void OPPROTO op_movl_T0_seg(void) |
876 | 1113 | T0 = env->segs[PARAM1].selector; |
877 | 1114 | } |
878 | 1115 | |
879 | -void OPPROTO op_movl_A0_seg(void) | |
880 | -{ | |
881 | - A0 = *(unsigned long *)((char *)env + PARAM1); | |
882 | -} | |
883 | - | |
884 | -void OPPROTO op_addl_A0_seg(void) | |
885 | -{ | |
886 | - A0 += *(unsigned long *)((char *)env + PARAM1); | |
887 | -} | |
888 | - | |
889 | 1116 | void OPPROTO op_lsl(void) |
890 | 1117 | { |
891 | 1118 | helper_lsl(); |
... | ... | @@ -1006,6 +1233,26 @@ void OPPROTO op_movl_env_T1(void) |
1006 | 1233 | *(uint32_t *)((char *)env + PARAM1) = T1; |
1007 | 1234 | } |
1008 | 1235 | |
1236 | +void OPPROTO op_movtl_T0_env(void) | |
1237 | +{ | |
1238 | + T0 = *(target_ulong *)((char *)env + PARAM1); | |
1239 | +} | |
1240 | + | |
1241 | +void OPPROTO op_movtl_env_T0(void) | |
1242 | +{ | |
1243 | + *(target_ulong *)((char *)env + PARAM1) = T0; | |
1244 | +} | |
1245 | + | |
1246 | +void OPPROTO op_movtl_T1_env(void) | |
1247 | +{ | |
1248 | + T1 = *(target_ulong *)((char *)env + PARAM1); | |
1249 | +} | |
1250 | + | |
1251 | +void OPPROTO op_movtl_env_T1(void) | |
1252 | +{ | |
1253 | + *(target_ulong *)((char *)env + PARAM1) = T1; | |
1254 | +} | |
1255 | + | |
1009 | 1256 | void OPPROTO op_clts(void) |
1010 | 1257 | { |
1011 | 1258 | env->cr[0] &= ~CR0_TS_MASK; |
... | ... | @@ -1014,25 +1261,31 @@ void OPPROTO op_clts(void) |
1014 | 1261 | |
1015 | 1262 | /* flags handling */ |
1016 | 1263 | |
1017 | -/* slow jumps cases : in order to avoid calling a function with a | |
1018 | - pointer (which can generate a stack frame on PowerPC), we use | |
1019 | - op_setcc to set T0 and then call op_jcc. */ | |
1020 | -void OPPROTO op_jcc(void) | |
1264 | +void OPPROTO op_goto_tb0(void) | |
1021 | 1265 | { |
1022 | - if (T0) | |
1023 | - JUMP_TB(op_jcc, PARAM1, 0, PARAM2); | |
1024 | - else | |
1025 | - JUMP_TB(op_jcc, PARAM1, 1, PARAM3); | |
1026 | - FORCE_RET(); | |
1266 | + GOTO_TB(op_goto_tb0, 0); | |
1267 | +} | |
1268 | + | |
1269 | +void OPPROTO op_goto_tb1(void) | |
1270 | +{ | |
1271 | + GOTO_TB(op_goto_tb1, 1); | |
1272 | +} | |
1273 | + | |
1274 | +void OPPROTO op_jmp_label(void) | |
1275 | +{ | |
1276 | + GOTO_LABEL_PARAM(1); | |
1027 | 1277 | } |
1028 | 1278 | |
1029 | -void OPPROTO op_jcc_im(void) | |
1279 | +void OPPROTO op_jnz_T0_label(void) | |
1030 | 1280 | { |
1031 | 1281 | if (T0) |
1032 | - EIP = PARAM1; | |
1033 | - else | |
1034 | - EIP = PARAM2; | |
1035 | - FORCE_RET(); | |
1282 | + GOTO_LABEL_PARAM(1); | |
1283 | +} | |
1284 | + | |
1285 | +void OPPROTO op_jz_T0_label(void) | |
1286 | +{ | |
1287 | + if (!T0) | |
1288 | + GOTO_LABEL_PARAM(1); | |
1036 | 1289 | } |
1037 | 1290 | |
1038 | 1291 | /* slow set cases (compute x86 flags) */ |
... | ... | @@ -1299,6 +1552,28 @@ CCTable cc_table[CC_OP_NB] = { |
1299 | 1552 | [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl }, |
1300 | 1553 | [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl }, |
1301 | 1554 | [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl }, |
1555 | + | |
1556 | +#ifdef TARGET_X86_64 | |
1557 | + [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull }, | |
1558 | + | |
1559 | + [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq }, | |
1560 | + | |
1561 | + [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq }, | |
1562 | + | |
1563 | + [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq }, | |
1564 | + | |
1565 | + [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq }, | |
1566 | + | |
1567 | + [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq }, | |
1568 | + | |
1569 | + [CC_OP_INCQ] = { compute_all_incq, compute_c_incl }, | |
1570 | + | |
1571 | + [CC_OP_DECQ] = { compute_all_decq, compute_c_incl }, | |
1572 | + | |
1573 | + [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq }, | |
1574 | + | |
1575 | + [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl }, | |
1576 | +#endif | |
1302 | 1577 | }; |
1303 | 1578 | |
1304 | 1579 | /* floating point support. Some of the code for complicated x87 |
... | ... | @@ -1330,20 +1605,20 @@ double qemu_rint(double x) |
1330 | 1605 | void OPPROTO op_flds_FT0_A0(void) |
1331 | 1606 | { |
1332 | 1607 | #ifdef USE_FP_CONVERT |
1333 | - FP_CONVERT.i32 = ldl((void *)A0); | |
1608 | + FP_CONVERT.i32 = ldl(A0); | |
1334 | 1609 | FT0 = FP_CONVERT.f; |
1335 | 1610 | #else |
1336 | - FT0 = ldfl((void *)A0); | |
1611 | + FT0 = ldfl(A0); | |
1337 | 1612 | #endif |
1338 | 1613 | } |
1339 | 1614 | |
1340 | 1615 | void OPPROTO op_fldl_FT0_A0(void) |
1341 | 1616 | { |
1342 | 1617 | #ifdef USE_FP_CONVERT |
1343 | - FP_CONVERT.i64 = ldq((void *)A0); | |
1618 | + FP_CONVERT.i64 = ldq(A0); | |
1344 | 1619 | FT0 = FP_CONVERT.d; |
1345 | 1620 | #else |
1346 | - FT0 = ldfq((void *)A0); | |
1621 | + FT0 = ldfq(A0); | |
1347 | 1622 | #endif |
1348 | 1623 | } |
1349 | 1624 | |
... | ... | @@ -1352,17 +1627,17 @@ void OPPROTO op_fldl_FT0_A0(void) |
1352 | 1627 | |
1353 | 1628 | void helper_fild_FT0_A0(void) |
1354 | 1629 | { |
1355 | - FT0 = (CPU86_LDouble)ldsw((void *)A0); | |
1630 | + FT0 = (CPU86_LDouble)ldsw(A0); | |
1356 | 1631 | } |
1357 | 1632 | |
1358 | 1633 | void helper_fildl_FT0_A0(void) |
1359 | 1634 | { |
1360 | - FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1635 | + FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); | |
1361 | 1636 | } |
1362 | 1637 | |
1363 | 1638 | void helper_fildll_FT0_A0(void) |
1364 | 1639 | { |
1365 | - FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1640 | + FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); | |
1366 | 1641 | } |
1367 | 1642 | |
1368 | 1643 | void OPPROTO op_fild_FT0_A0(void) |
... | ... | @@ -1385,30 +1660,30 @@ void OPPROTO op_fildll_FT0_A0(void) |
1385 | 1660 | void OPPROTO op_fild_FT0_A0(void) |
1386 | 1661 | { |
1387 | 1662 | #ifdef USE_FP_CONVERT |
1388 | - FP_CONVERT.i32 = ldsw((void *)A0); | |
1663 | + FP_CONVERT.i32 = ldsw(A0); | |
1389 | 1664 | FT0 = (CPU86_LDouble)FP_CONVERT.i32; |
1390 | 1665 | #else |
1391 | - FT0 = (CPU86_LDouble)ldsw((void *)A0); | |
1666 | + FT0 = (CPU86_LDouble)ldsw(A0); | |
1392 | 1667 | #endif |
1393 | 1668 | } |
1394 | 1669 | |
1395 | 1670 | void OPPROTO op_fildl_FT0_A0(void) |
1396 | 1671 | { |
1397 | 1672 | #ifdef USE_FP_CONVERT |
1398 | - FP_CONVERT.i32 = (int32_t) ldl((void *)A0); | |
1673 | + FP_CONVERT.i32 = (int32_t) ldl(A0); | |
1399 | 1674 | FT0 = (CPU86_LDouble)FP_CONVERT.i32; |
1400 | 1675 | #else |
1401 | - FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1676 | + FT0 = (CPU86_LDouble)((int32_t)ldl(A0)); | |
1402 | 1677 | #endif |
1403 | 1678 | } |
1404 | 1679 | |
1405 | 1680 | void OPPROTO op_fildll_FT0_A0(void) |
1406 | 1681 | { |
1407 | 1682 | #ifdef USE_FP_CONVERT |
1408 | - FP_CONVERT.i64 = (int64_t) ldq((void *)A0); | |
1683 | + FP_CONVERT.i64 = (int64_t) ldq(A0); | |
1409 | 1684 | FT0 = (CPU86_LDouble)FP_CONVERT.i64; |
1410 | 1685 | #else |
1411 | - FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1686 | + FT0 = (CPU86_LDouble)((int64_t)ldq(A0)); | |
1412 | 1687 | #endif |
1413 | 1688 | } |
1414 | 1689 | #endif |
... | ... | @@ -1420,10 +1695,10 @@ void OPPROTO op_flds_ST0_A0(void) |
1420 | 1695 | int new_fpstt; |
1421 | 1696 | new_fpstt = (env->fpstt - 1) & 7; |
1422 | 1697 | #ifdef USE_FP_CONVERT |
1423 | - FP_CONVERT.i32 = ldl((void *)A0); | |
1698 | + FP_CONVERT.i32 = ldl(A0); | |
1424 | 1699 | env->fpregs[new_fpstt] = FP_CONVERT.f; |
1425 | 1700 | #else |
1426 | - env->fpregs[new_fpstt] = ldfl((void *)A0); | |
1701 | + env->fpregs[new_fpstt] = ldfl(A0); | |
1427 | 1702 | #endif |
1428 | 1703 | env->fpstt = new_fpstt; |
1429 | 1704 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
... | ... | @@ -1434,10 +1709,10 @@ void OPPROTO op_fldl_ST0_A0(void) |
1434 | 1709 | int new_fpstt; |
1435 | 1710 | new_fpstt = (env->fpstt - 1) & 7; |
1436 | 1711 | #ifdef USE_FP_CONVERT |
1437 | - FP_CONVERT.i64 = ldq((void *)A0); | |
1712 | + FP_CONVERT.i64 = ldq(A0); | |
1438 | 1713 | env->fpregs[new_fpstt] = FP_CONVERT.d; |
1439 | 1714 | #else |
1440 | - env->fpregs[new_fpstt] = ldfq((void *)A0); | |
1715 | + env->fpregs[new_fpstt] = ldfq(A0); | |
1441 | 1716 | #endif |
1442 | 1717 | env->fpstt = new_fpstt; |
1443 | 1718 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
... | ... | @@ -1455,7 +1730,7 @@ void helper_fild_ST0_A0(void) |
1455 | 1730 | { |
1456 | 1731 | int new_fpstt; |
1457 | 1732 | new_fpstt = (env->fpstt - 1) & 7; |
1458 | - env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw((void *)A0); | |
1733 | + env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw(A0); | |
1459 | 1734 | env->fpstt = new_fpstt; |
1460 | 1735 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
1461 | 1736 | } |
... | ... | @@ -1464,7 +1739,7 @@ void helper_fildl_ST0_A0(void) |
1464 | 1739 | { |
1465 | 1740 | int new_fpstt; |
1466 | 1741 | new_fpstt = (env->fpstt - 1) & 7; |
1467 | - env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1742 | + env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl(A0)); | |
1468 | 1743 | env->fpstt = new_fpstt; |
1469 | 1744 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
1470 | 1745 | } |
... | ... | @@ -1473,7 +1748,7 @@ void helper_fildll_ST0_A0(void) |
1473 | 1748 | { |
1474 | 1749 | int new_fpstt; |
1475 | 1750 | new_fpstt = (env->fpstt - 1) & 7; |
1476 | - env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1751 | + env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq(A0)); | |
1477 | 1752 | env->fpstt = new_fpstt; |
1478 | 1753 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
1479 | 1754 | } |
... | ... | @@ -1500,10 +1775,10 @@ void OPPROTO op_fild_ST0_A0(void) |
1500 | 1775 | int new_fpstt; |
1501 | 1776 | new_fpstt = (env->fpstt - 1) & 7; |
1502 | 1777 | #ifdef USE_FP_CONVERT |
1503 | - FP_CONVERT.i32 = ldsw((void *)A0); | |
1778 | + FP_CONVERT.i32 = ldsw(A0); | |
1504 | 1779 | env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32; |
1505 | 1780 | #else |
1506 | - env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw((void *)A0); | |
1781 | + env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw(A0); | |
1507 | 1782 | #endif |
1508 | 1783 | env->fpstt = new_fpstt; |
1509 | 1784 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
... | ... | @@ -1514,10 +1789,10 @@ void OPPROTO op_fildl_ST0_A0(void) |
1514 | 1789 | int new_fpstt; |
1515 | 1790 | new_fpstt = (env->fpstt - 1) & 7; |
1516 | 1791 | #ifdef USE_FP_CONVERT |
1517 | - FP_CONVERT.i32 = (int32_t) ldl((void *)A0); | |
1792 | + FP_CONVERT.i32 = (int32_t) ldl(A0); | |
1518 | 1793 | env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32; |
1519 | 1794 | #else |
1520 | - env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1795 | + env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl(A0)); | |
1521 | 1796 | #endif |
1522 | 1797 | env->fpstt = new_fpstt; |
1523 | 1798 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
... | ... | @@ -1528,10 +1803,10 @@ void OPPROTO op_fildll_ST0_A0(void) |
1528 | 1803 | int new_fpstt; |
1529 | 1804 | new_fpstt = (env->fpstt - 1) & 7; |
1530 | 1805 | #ifdef USE_FP_CONVERT |
1531 | - FP_CONVERT.i64 = (int64_t) ldq((void *)A0); | |
1806 | + FP_CONVERT.i64 = (int64_t) ldq(A0); | |
1532 | 1807 | env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i64; |
1533 | 1808 | #else |
1534 | - env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1809 | + env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq(A0)); | |
1535 | 1810 | #endif |
1536 | 1811 | env->fpstt = new_fpstt; |
1537 | 1812 | env->fptags[new_fpstt] = 0; /* validate stack entry */ |
... | ... | @@ -1545,15 +1820,15 @@ void OPPROTO op_fsts_ST0_A0(void) |
1545 | 1820 | { |
1546 | 1821 | #ifdef USE_FP_CONVERT |
1547 | 1822 | FP_CONVERT.f = (float)ST0; |
1548 | - stfl((void *)A0, FP_CONVERT.f); | |
1823 | + stfl(A0, FP_CONVERT.f); | |
1549 | 1824 | #else |
1550 | - stfl((void *)A0, (float)ST0); | |
1825 | + stfl(A0, (float)ST0); | |
1551 | 1826 | #endif |
1552 | 1827 | } |
1553 | 1828 | |
1554 | 1829 | void OPPROTO op_fstl_ST0_A0(void) |
1555 | 1830 | { |
1556 | - stfq((void *)A0, (double)ST0); | |
1831 | + stfq(A0, (double)ST0); | |
1557 | 1832 | } |
1558 | 1833 | |
1559 | 1834 | void OPPROTO op_fstt_ST0_A0(void) |
... | ... | @@ -1574,7 +1849,7 @@ void OPPROTO op_fist_ST0_A0(void) |
1574 | 1849 | val = lrint(d); |
1575 | 1850 | if (val != (int16_t)val) |
1576 | 1851 | val = -32768; |
1577 | - stw((void *)A0, val); | |
1852 | + stw(A0, val); | |
1578 | 1853 | } |
1579 | 1854 | |
1580 | 1855 | void OPPROTO op_fistl_ST0_A0(void) |
... | ... | @@ -1588,7 +1863,7 @@ void OPPROTO op_fistl_ST0_A0(void) |
1588 | 1863 | |
1589 | 1864 | d = ST0; |
1590 | 1865 | val = lrint(d); |
1591 | - stl((void *)A0, val); | |
1866 | + stl(A0, val); | |
1592 | 1867 | } |
1593 | 1868 | |
1594 | 1869 | void OPPROTO op_fistll_ST0_A0(void) |
... | ... | @@ -1602,7 +1877,7 @@ void OPPROTO op_fistll_ST0_A0(void) |
1602 | 1877 | |
1603 | 1878 | d = ST0; |
1604 | 1879 | val = llrint(d); |
1605 | - stq((void *)A0, val); | |
1880 | + stq(A0, val); | |
1606 | 1881 | } |
1607 | 1882 | |
1608 | 1883 | void OPPROTO op_fbld_ST0_A0(void) |
... | ... | @@ -1934,25 +2209,25 @@ void OPPROTO op_fnstsw_A0(void) |
1934 | 2209 | { |
1935 | 2210 | int fpus; |
1936 | 2211 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
1937 | - stw((void *)A0, fpus); | |
2212 | + stw(A0, fpus); | |
1938 | 2213 | } |
1939 | 2214 | |
1940 | 2215 | void OPPROTO op_fnstsw_EAX(void) |
1941 | 2216 | { |
1942 | 2217 | int fpus; |
1943 | 2218 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
1944 | - EAX = (EAX & 0xffff0000) | fpus; | |
2219 | + EAX = (EAX & ~0xffff) | fpus; | |
1945 | 2220 | } |
1946 | 2221 | |
1947 | 2222 | void OPPROTO op_fnstcw_A0(void) |
1948 | 2223 | { |
1949 | - stw((void *)A0, env->fpuc); | |
2224 | + stw(A0, env->fpuc); | |
1950 | 2225 | } |
1951 | 2226 | |
1952 | 2227 | void OPPROTO op_fldcw_A0(void) |
1953 | 2228 | { |
1954 | 2229 | int rnd_type; |
1955 | - env->fpuc = lduw((void *)A0); | |
2230 | + env->fpuc = lduw(A0); | |
1956 | 2231 | /* set rounding mode */ |
1957 | 2232 | switch(env->fpuc & RC_MASK) { |
1958 | 2233 | default: |
... | ... | @@ -2001,22 +2276,22 @@ void OPPROTO op_fninit(void) |
2001 | 2276 | |
2002 | 2277 | void OPPROTO op_fnstenv_A0(void) |
2003 | 2278 | { |
2004 | - helper_fstenv((uint8_t *)A0, PARAM1); | |
2279 | + helper_fstenv(A0, PARAM1); | |
2005 | 2280 | } |
2006 | 2281 | |
2007 | 2282 | void OPPROTO op_fldenv_A0(void) |
2008 | 2283 | { |
2009 | - helper_fldenv((uint8_t *)A0, PARAM1); | |
2284 | + helper_fldenv(A0, PARAM1); | |
2010 | 2285 | } |
2011 | 2286 | |
2012 | 2287 | void OPPROTO op_fnsave_A0(void) |
2013 | 2288 | { |
2014 | - helper_fsave((uint8_t *)A0, PARAM1); | |
2289 | + helper_fsave(A0, PARAM1); | |
2015 | 2290 | } |
2016 | 2291 | |
2017 | 2292 | void OPPROTO op_frstor_A0(void) |
2018 | 2293 | { |
2019 | - helper_frstor((uint8_t *)A0, PARAM1); | |
2294 | + helper_frstor(A0, PARAM1); | |
2020 | 2295 | } |
2021 | 2296 | |
2022 | 2297 | /* threading support */ |
... | ... | @@ -2030,3 +2305,30 @@ void OPPROTO op_unlock(void) |
2030 | 2305 | cpu_unlock(); |
2031 | 2306 | } |
2032 | 2307 | |
2308 | +/* SSE support */ | |
2309 | +static inline void memcpy16(void *d, void *s) | |
2310 | +{ | |
2311 | + ((uint32_t *)d)[0] = ((uint32_t *)s)[0]; | |
2312 | + ((uint32_t *)d)[1] = ((uint32_t *)s)[1]; | |
2313 | + ((uint32_t *)d)[2] = ((uint32_t *)s)[2]; | |
2314 | + ((uint32_t *)d)[3] = ((uint32_t *)s)[3]; | |
2315 | +} | |
2316 | + | |
2317 | +void OPPROTO op_movo(void) | |
2318 | +{ | |
2319 | + /* XXX: badly generated code */ | |
2320 | + XMMReg *d, *s; | |
2321 | + d = (XMMReg *)((char *)env + PARAM1); | |
2322 | + s = (XMMReg *)((char *)env + PARAM2); | |
2323 | + memcpy16(d, s); | |
2324 | +} | |
2325 | + | |
2326 | +void OPPROTO op_fxsave_A0(void) | |
2327 | +{ | |
2328 | + helper_fxsave(A0, PARAM1); | |
2329 | +} | |
2330 | + | |
2331 | +void OPPROTO op_fxrstor_A0(void) | |
2332 | +{ | |
2333 | + helper_fxrstor(A0, PARAM1); | |
2334 | +} | ... | ... |
target-i386/opreg_template.h
... | ... | @@ -20,29 +20,56 @@ |
20 | 20 | */ |
21 | 21 | void OPPROTO glue(op_movl_A0,REGNAME)(void) |
22 | 22 | { |
23 | - A0 = REG; | |
23 | + A0 = (uint32_t)REG; | |
24 | 24 | } |
25 | 25 | |
26 | 26 | void OPPROTO glue(op_addl_A0,REGNAME)(void) |
27 | 27 | { |
28 | - A0 += REG; | |
28 | + A0 = (uint32_t)(A0 + REG); | |
29 | 29 | } |
30 | 30 | |
31 | 31 | void OPPROTO glue(glue(op_addl_A0,REGNAME),_s1)(void) |
32 | 32 | { |
33 | - A0 += REG << 1; | |
33 | + A0 = (uint32_t)(A0 + (REG << 1)); | |
34 | 34 | } |
35 | 35 | |
36 | 36 | void OPPROTO glue(glue(op_addl_A0,REGNAME),_s2)(void) |
37 | 37 | { |
38 | - A0 += REG << 2; | |
38 | + A0 = (uint32_t)(A0 + (REG << 2)); | |
39 | 39 | } |
40 | 40 | |
41 | 41 | void OPPROTO glue(glue(op_addl_A0,REGNAME),_s3)(void) |
42 | 42 | { |
43 | - A0 += REG << 3; | |
43 | + A0 = (uint32_t)(A0 + (REG << 3)); | |
44 | +} | |
45 | + | |
46 | +#ifdef TARGET_X86_64 | |
47 | +void OPPROTO glue(op_movq_A0,REGNAME)(void) | |
48 | +{ | |
49 | + A0 = REG; | |
50 | +} | |
51 | + | |
52 | +void OPPROTO glue(op_addq_A0,REGNAME)(void) | |
53 | +{ | |
54 | + A0 = (A0 + REG); | |
55 | +} | |
56 | + | |
57 | +void OPPROTO glue(glue(op_addq_A0,REGNAME),_s1)(void) | |
58 | +{ | |
59 | + A0 = (A0 + (REG << 1)); | |
60 | +} | |
61 | + | |
62 | +void OPPROTO glue(glue(op_addq_A0,REGNAME),_s2)(void) | |
63 | +{ | |
64 | + A0 = (A0 + (REG << 2)); | |
44 | 65 | } |
45 | 66 | |
67 | +void OPPROTO glue(glue(op_addq_A0,REGNAME),_s3)(void) | |
68 | +{ | |
69 | + A0 = (A0 + (REG << 3)); | |
70 | +} | |
71 | +#endif | |
72 | + | |
46 | 73 | void OPPROTO glue(op_movl_T0,REGNAME)(void) |
47 | 74 | { |
48 | 75 | T0 = REG; |
... | ... | @@ -65,72 +92,99 @@ void OPPROTO glue(op_movh_T1,REGNAME)(void) |
65 | 92 | |
66 | 93 | void OPPROTO glue(glue(op_movl,REGNAME),_T0)(void) |
67 | 94 | { |
68 | - REG = T0; | |
95 | + REG = (uint32_t)T0; | |
69 | 96 | } |
70 | 97 | |
71 | 98 | void OPPROTO glue(glue(op_movl,REGNAME),_T1)(void) |
72 | 99 | { |
73 | - REG = T1; | |
100 | + REG = (uint32_t)T1; | |
74 | 101 | } |
75 | 102 | |
76 | 103 | void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void) |
77 | 104 | { |
105 | + REG = (uint32_t)A0; | |
106 | +} | |
107 | + | |
108 | +#ifdef TARGET_X86_64 | |
109 | +void OPPROTO glue(glue(op_movq,REGNAME),_T0)(void) | |
110 | +{ | |
111 | + REG = T0; | |
112 | +} | |
113 | + | |
114 | +void OPPROTO glue(glue(op_movq,REGNAME),_T1)(void) | |
115 | +{ | |
116 | + REG = T1; | |
117 | +} | |
118 | + | |
119 | +void OPPROTO glue(glue(op_movq,REGNAME),_A0)(void) | |
120 | +{ | |
78 | 121 | REG = A0; |
79 | 122 | } |
123 | +#endif | |
80 | 124 | |
81 | 125 | /* mov T1 to REG if T0 is true */ |
82 | 126 | void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void) |
83 | 127 | { |
84 | 128 | if (T0) |
85 | - REG = (REG & 0xffff0000) | (T1 & 0xffff); | |
129 | + REG = (REG & ~0xffff) | (T1 & 0xffff); | |
86 | 130 | FORCE_RET(); |
87 | 131 | } |
88 | 132 | |
89 | 133 | void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void) |
90 | 134 | { |
91 | 135 | if (T0) |
136 | + REG = (uint32_t)T1; | |
137 | + FORCE_RET(); | |
138 | +} | |
139 | + | |
140 | +#ifdef TARGET_X86_64 | |
141 | +void OPPROTO glue(glue(op_cmovq,REGNAME),_T1_T0)(void) | |
142 | +{ | |
143 | + if (T0) | |
92 | 144 | REG = T1; |
93 | 145 | FORCE_RET(); |
94 | 146 | } |
147 | +#endif | |
95 | 148 | |
96 | 149 | /* NOTE: T0 high order bits are ignored */ |
97 | 150 | void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void) |
98 | 151 | { |
99 | - REG = (REG & 0xffff0000) | (T0 & 0xffff); | |
152 | + REG = (REG & ~0xffff) | (T0 & 0xffff); | |
100 | 153 | } |
101 | 154 | |
102 | 155 | /* NOTE: T0 high order bits are ignored */ |
103 | 156 | void OPPROTO glue(glue(op_movw,REGNAME),_T1)(void) |
104 | 157 | { |
105 | - REG = (REG & 0xffff0000) | (T1 & 0xffff); | |
158 | + REG = (REG & ~0xffff) | (T1 & 0xffff); | |
106 | 159 | } |
107 | 160 | |
108 | 161 | /* NOTE: A0 high order bits are ignored */ |
109 | 162 | void OPPROTO glue(glue(op_movw,REGNAME),_A0)(void) |
110 | 163 | { |
111 | - REG = (REG & 0xffff0000) | (A0 & 0xffff); | |
164 | + REG = (REG & ~0xffff) | (A0 & 0xffff); | |
112 | 165 | } |
113 | 166 | |
114 | 167 | /* NOTE: T0 high order bits are ignored */ |
115 | 168 | void OPPROTO glue(glue(op_movb,REGNAME),_T0)(void) |
116 | 169 | { |
117 | - REG = (REG & 0xffffff00) | (T0 & 0xff); | |
170 | + REG = (REG & ~0xff) | (T0 & 0xff); | |
118 | 171 | } |
119 | 172 | |
120 | 173 | /* NOTE: T0 high order bits are ignored */ |
121 | 174 | void OPPROTO glue(glue(op_movh,REGNAME),_T0)(void) |
122 | 175 | { |
123 | - REG = (REG & 0xffff00ff) | ((T0 & 0xff) << 8); | |
176 | + REG = (REG & ~0xff00) | ((T0 & 0xff) << 8); | |
124 | 177 | } |
125 | 178 | |
126 | 179 | /* NOTE: T1 high order bits are ignored */ |
127 | 180 | void OPPROTO glue(glue(op_movb,REGNAME),_T1)(void) |
128 | 181 | { |
129 | - REG = (REG & 0xffffff00) | (T1 & 0xff); | |
182 | + REG = (REG & ~0xff) | (T1 & 0xff); | |
130 | 183 | } |
131 | 184 | |
132 | 185 | /* NOTE: T1 high order bits are ignored */ |
133 | 186 | void OPPROTO glue(glue(op_movh,REGNAME),_T1)(void) |
134 | 187 | { |
135 | - REG = (REG & 0xffff00ff) | ((T1 & 0xff) << 8); | |
188 | + REG = (REG & ~0xff00) | ((T1 & 0xff) << 8); | |
136 | 189 | } |
190 | + | ... | ... |
target-i386/ops_mem.h
1 | 1 | void OPPROTO glue(glue(op_ldub, MEMSUFFIX), _T0_A0)(void) |
2 | 2 | { |
3 | - T0 = glue(ldub, MEMSUFFIX)((uint8_t *)A0); | |
3 | + T0 = glue(ldub, MEMSUFFIX)(A0); | |
4 | 4 | } |
5 | 5 | |
6 | 6 | void OPPROTO glue(glue(op_ldsb, MEMSUFFIX), _T0_A0)(void) |
7 | 7 | { |
8 | - T0 = glue(ldsb, MEMSUFFIX)((int8_t *)A0); | |
8 | + T0 = glue(ldsb, MEMSUFFIX)(A0); | |
9 | 9 | } |
10 | 10 | |
11 | 11 | void OPPROTO glue(glue(op_lduw, MEMSUFFIX), _T0_A0)(void) |
12 | 12 | { |
13 | - T0 = glue(lduw, MEMSUFFIX)((uint8_t *)A0); | |
13 | + T0 = glue(lduw, MEMSUFFIX)(A0); | |
14 | 14 | } |
15 | 15 | |
16 | 16 | void OPPROTO glue(glue(op_ldsw, MEMSUFFIX), _T0_A0)(void) |
17 | 17 | { |
18 | - T0 = glue(ldsw, MEMSUFFIX)((int8_t *)A0); | |
18 | + T0 = glue(ldsw, MEMSUFFIX)(A0); | |
19 | 19 | } |
20 | 20 | |
21 | 21 | void OPPROTO glue(glue(op_ldl, MEMSUFFIX), _T0_A0)(void) |
22 | 22 | { |
23 | - T0 = glue(ldl, MEMSUFFIX)((uint8_t *)A0); | |
23 | + T0 = (uint32_t)glue(ldl, MEMSUFFIX)(A0); | |
24 | 24 | } |
25 | 25 | |
26 | 26 | void OPPROTO glue(glue(op_ldub, MEMSUFFIX), _T1_A0)(void) |
27 | 27 | { |
28 | - T1 = glue(ldub, MEMSUFFIX)((uint8_t *)A0); | |
28 | + T1 = glue(ldub, MEMSUFFIX)(A0); | |
29 | 29 | } |
30 | 30 | |
31 | 31 | void OPPROTO glue(glue(op_ldsb, MEMSUFFIX), _T1_A0)(void) |
32 | 32 | { |
33 | - T1 = glue(ldsb, MEMSUFFIX)((int8_t *)A0); | |
33 | + T1 = glue(ldsb, MEMSUFFIX)(A0); | |
34 | 34 | } |
35 | 35 | |
36 | 36 | void OPPROTO glue(glue(op_lduw, MEMSUFFIX), _T1_A0)(void) |
37 | 37 | { |
38 | - T1 = glue(lduw, MEMSUFFIX)((uint8_t *)A0); | |
38 | + T1 = glue(lduw, MEMSUFFIX)(A0); | |
39 | 39 | } |
40 | 40 | |
41 | 41 | void OPPROTO glue(glue(op_ldsw, MEMSUFFIX), _T1_A0)(void) |
42 | 42 | { |
43 | - T1 = glue(ldsw, MEMSUFFIX)((int8_t *)A0); | |
43 | + T1 = glue(ldsw, MEMSUFFIX)(A0); | |
44 | 44 | } |
45 | 45 | |
46 | 46 | void OPPROTO glue(glue(op_ldl, MEMSUFFIX), _T1_A0)(void) |
47 | 47 | { |
48 | - T1 = glue(ldl, MEMSUFFIX)((uint8_t *)A0); | |
48 | + T1 = glue(ldl, MEMSUFFIX)(A0); | |
49 | 49 | } |
50 | 50 | |
51 | 51 | void OPPROTO glue(glue(op_stb, MEMSUFFIX), _T0_A0)(void) |
52 | 52 | { |
53 | - glue(stb, MEMSUFFIX)((uint8_t *)A0, T0); | |
53 | + glue(stb, MEMSUFFIX)(A0, T0); | |
54 | 54 | } |
55 | 55 | |
56 | 56 | void OPPROTO glue(glue(op_stw, MEMSUFFIX), _T0_A0)(void) |
57 | 57 | { |
58 | - glue(stw, MEMSUFFIX)((uint8_t *)A0, T0); | |
58 | + glue(stw, MEMSUFFIX)(A0, T0); | |
59 | 59 | } |
60 | 60 | |
61 | 61 | void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T0_A0)(void) |
62 | 62 | { |
63 | - glue(stl, MEMSUFFIX)((uint8_t *)A0, T0); | |
63 | + glue(stl, MEMSUFFIX)(A0, T0); | |
64 | 64 | } |
65 | 65 | |
66 | 66 | #if 0 |
67 | 67 | void OPPROTO glue(glue(op_stb, MEMSUFFIX), _T1_A0)(void) |
68 | 68 | { |
69 | - glue(stb, MEMSUFFIX)((uint8_t *)A0, T1); | |
69 | + glue(stb, MEMSUFFIX)(A0, T1); | |
70 | 70 | } |
71 | 71 | #endif |
72 | 72 | |
73 | 73 | void OPPROTO glue(glue(op_stw, MEMSUFFIX), _T1_A0)(void) |
74 | 74 | { |
75 | - glue(stw, MEMSUFFIX)((uint8_t *)A0, T1); | |
75 | + glue(stw, MEMSUFFIX)(A0, T1); | |
76 | 76 | } |
77 | 77 | |
78 | 78 | void OPPROTO glue(glue(op_stl, MEMSUFFIX), _T1_A0)(void) |
79 | 79 | { |
80 | - glue(stl, MEMSUFFIX)((uint8_t *)A0, T1); | |
80 | + glue(stl, MEMSUFFIX)(A0, T1); | |
81 | 81 | } |
82 | 82 | |
83 | +/* SSE support */ | |
84 | +void OPPROTO glue(glue(op_ldo, MEMSUFFIX), _env_A0)(void) | |
85 | +{ | |
86 | + XMMReg *p; | |
87 | + p = (XMMReg *)((char *)env + PARAM1); | |
88 | + /* XXX: host endianness ? */ | |
89 | + p->u.q[0] = glue(ldq, MEMSUFFIX)(A0); | |
90 | + p->u.q[1] = glue(ldq, MEMSUFFIX)(A0 + 8); | |
91 | +} | |
92 | + | |
93 | +void OPPROTO glue(glue(op_sto, MEMSUFFIX), _env_A0)(void) | |
94 | +{ | |
95 | + XMMReg *p; | |
96 | + p = (XMMReg *)((char *)env + PARAM1); | |
97 | + /* XXX: host endianness ? */ | |
98 | + glue(stq, MEMSUFFIX)(A0, p->u.q[0]); | |
99 | + glue(stq, MEMSUFFIX)(A0 + 8, p->u.q[1]); | |
100 | +} | |
101 | + | |
102 | +#ifdef TARGET_X86_64 | |
103 | +void OPPROTO glue(glue(op_ldsl, MEMSUFFIX), _T0_A0)(void) | |
104 | +{ | |
105 | + T0 = (int32_t)glue(ldl, MEMSUFFIX)(A0); | |
106 | +} | |
107 | + | |
108 | +void OPPROTO glue(glue(op_ldsl, MEMSUFFIX), _T1_A0)(void) | |
109 | +{ | |
110 | + T1 = (int32_t)glue(ldl, MEMSUFFIX)(A0); | |
111 | +} | |
112 | + | |
113 | +void OPPROTO glue(glue(op_ldq, MEMSUFFIX), _T0_A0)(void) | |
114 | +{ | |
115 | + T0 = glue(ldq, MEMSUFFIX)(A0); | |
116 | +} | |
117 | + | |
118 | +void OPPROTO glue(glue(op_ldq, MEMSUFFIX), _T1_A0)(void) | |
119 | +{ | |
120 | + T1 = glue(ldq, MEMSUFFIX)(A0); | |
121 | +} | |
122 | + | |
123 | +void OPPROTO glue(glue(op_stq, MEMSUFFIX), _T0_A0)(void) | |
124 | +{ | |
125 | + glue(stq, MEMSUFFIX)(A0, T0); | |
126 | +} | |
127 | + | |
128 | +void OPPROTO glue(glue(op_stq, MEMSUFFIX), _T1_A0)(void) | |
129 | +{ | |
130 | + glue(stq, MEMSUFFIX)(A0, T1); | |
131 | +} | |
132 | +#endif | |
133 | + | |
83 | 134 | #undef MEMSUFFIX | ... | ... |
target-i386/ops_template.h
... | ... | @@ -20,7 +20,12 @@ |
20 | 20 | */ |
21 | 21 | #define DATA_BITS (1 << (3 + SHIFT)) |
22 | 22 | #define SHIFT_MASK (DATA_BITS - 1) |
23 | -#define SIGN_MASK (1 << (DATA_BITS - 1)) | |
23 | +#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1)) | |
24 | +#if DATA_BITS <= 32 | |
25 | +#define SHIFT1_MASK 0x1f | |
26 | +#else | |
27 | +#define SHIFT1_MASK 0x3f | |
28 | +#endif | |
24 | 29 | |
25 | 30 | #if DATA_BITS == 8 |
26 | 31 | #define SUFFIX b |
... | ... | @@ -37,6 +42,11 @@ |
37 | 42 | #define DATA_TYPE uint32_t |
38 | 43 | #define DATA_STYPE int32_t |
39 | 44 | #define DATA_MASK 0xffffffff |
45 | +#elif DATA_BITS == 64 | |
46 | +#define SUFFIX q | |
47 | +#define DATA_TYPE uint64_t | |
48 | +#define DATA_STYPE int64_t | |
49 | +#define DATA_MASK 0xffffffffffffffff | |
40 | 50 | #else |
41 | 51 | #error unhandled operand size |
42 | 52 | #endif |
... | ... | @@ -46,7 +56,7 @@ |
46 | 56 | static int glue(compute_all_add, SUFFIX)(void) |
47 | 57 | { |
48 | 58 | int cf, pf, af, zf, sf, of; |
49 | - int src1, src2; | |
59 | + target_long src1, src2; | |
50 | 60 | src1 = CC_SRC; |
51 | 61 | src2 = CC_DST - CC_SRC; |
52 | 62 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; |
... | ... | @@ -60,7 +70,8 @@ static int glue(compute_all_add, SUFFIX)(void) |
60 | 70 | |
61 | 71 | static int glue(compute_c_add, SUFFIX)(void) |
62 | 72 | { |
63 | - int src1, cf; | |
73 | + int cf; | |
74 | + target_long src1; | |
64 | 75 | src1 = CC_SRC; |
65 | 76 | cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1; |
66 | 77 | return cf; |
... | ... | @@ -69,7 +80,7 @@ static int glue(compute_c_add, SUFFIX)(void) |
69 | 80 | static int glue(compute_all_adc, SUFFIX)(void) |
70 | 81 | { |
71 | 82 | int cf, pf, af, zf, sf, of; |
72 | - int src1, src2; | |
83 | + target_long src1, src2; | |
73 | 84 | src1 = CC_SRC; |
74 | 85 | src2 = CC_DST - CC_SRC - 1; |
75 | 86 | cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; |
... | ... | @@ -83,7 +94,8 @@ static int glue(compute_all_adc, SUFFIX)(void) |
83 | 94 | |
84 | 95 | static int glue(compute_c_adc, SUFFIX)(void) |
85 | 96 | { |
86 | - int src1, cf; | |
97 | + int cf; | |
98 | + target_long src1; | |
87 | 99 | src1 = CC_SRC; |
88 | 100 | cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1; |
89 | 101 | return cf; |
... | ... | @@ -92,7 +104,7 @@ static int glue(compute_c_adc, SUFFIX)(void) |
92 | 104 | static int glue(compute_all_sub, SUFFIX)(void) |
93 | 105 | { |
94 | 106 | int cf, pf, af, zf, sf, of; |
95 | - int src1, src2; | |
107 | + target_long src1, src2; | |
96 | 108 | src1 = CC_DST + CC_SRC; |
97 | 109 | src2 = CC_SRC; |
98 | 110 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; |
... | ... | @@ -106,7 +118,8 @@ static int glue(compute_all_sub, SUFFIX)(void) |
106 | 118 | |
107 | 119 | static int glue(compute_c_sub, SUFFIX)(void) |
108 | 120 | { |
109 | - int src1, src2, cf; | |
121 | + int cf; | |
122 | + target_long src1, src2; | |
110 | 123 | src1 = CC_DST + CC_SRC; |
111 | 124 | src2 = CC_SRC; |
112 | 125 | cf = (DATA_TYPE)src1 < (DATA_TYPE)src2; |
... | ... | @@ -116,7 +129,7 @@ static int glue(compute_c_sub, SUFFIX)(void) |
116 | 129 | static int glue(compute_all_sbb, SUFFIX)(void) |
117 | 130 | { |
118 | 131 | int cf, pf, af, zf, sf, of; |
119 | - int src1, src2; | |
132 | + target_long src1, src2; | |
120 | 133 | src1 = CC_DST + CC_SRC + 1; |
121 | 134 | src2 = CC_SRC; |
122 | 135 | cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; |
... | ... | @@ -130,7 +143,8 @@ static int glue(compute_all_sbb, SUFFIX)(void) |
130 | 143 | |
131 | 144 | static int glue(compute_c_sbb, SUFFIX)(void) |
132 | 145 | { |
133 | - int src1, src2, cf; | |
146 | + int cf; | |
147 | + target_long src1, src2; | |
134 | 148 | src1 = CC_DST + CC_SRC + 1; |
135 | 149 | src2 = CC_SRC; |
136 | 150 | cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2; |
... | ... | @@ -157,7 +171,7 @@ static int glue(compute_c_logic, SUFFIX)(void) |
157 | 171 | static int glue(compute_all_inc, SUFFIX)(void) |
158 | 172 | { |
159 | 173 | int cf, pf, af, zf, sf, of; |
160 | - int src1, src2; | |
174 | + target_long src1, src2; | |
161 | 175 | src1 = CC_DST - 1; |
162 | 176 | src2 = 1; |
163 | 177 | cf = CC_SRC; |
... | ... | @@ -179,7 +193,7 @@ static int glue(compute_c_inc, SUFFIX)(void) |
179 | 193 | static int glue(compute_all_dec, SUFFIX)(void) |
180 | 194 | { |
181 | 195 | int cf, pf, af, zf, sf, of; |
182 | - int src1, src2; | |
196 | + target_long src1, src2; | |
183 | 197 | src1 = CC_DST + 1; |
184 | 198 | src2 = 1; |
185 | 199 | cf = CC_SRC; |
... | ... | @@ -187,7 +201,7 @@ static int glue(compute_all_dec, SUFFIX)(void) |
187 | 201 | af = (CC_DST ^ src1 ^ src2) & 0x10; |
188 | 202 | zf = ((DATA_TYPE)CC_DST == 0) << 6; |
189 | 203 | sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80; |
190 | - of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11; | |
204 | + of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11; | |
191 | 205 | return cf | pf | af | zf | sf | of; |
192 | 206 | } |
193 | 207 | |
... | ... | @@ -256,71 +270,66 @@ static int glue(compute_all_mul, SUFFIX)(void) |
256 | 270 | |
257 | 271 | void OPPROTO glue(op_jb_sub, SUFFIX)(void) |
258 | 272 | { |
259 | - int src1, src2; | |
273 | + target_long src1, src2; | |
260 | 274 | src1 = CC_DST + CC_SRC; |
261 | 275 | src2 = CC_SRC; |
262 | 276 | |
263 | 277 | if ((DATA_TYPE)src1 < (DATA_TYPE)src2) |
264 | - JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 0, PARAM2); | |
265 | - else | |
266 | - JUMP_TB(glue(op_jb_sub, SUFFIX), PARAM1, 1, PARAM3); | |
278 | + GOTO_LABEL_PARAM(1); | |
267 | 279 | FORCE_RET(); |
268 | 280 | } |
269 | 281 | |
270 | 282 | void OPPROTO glue(op_jz_sub, SUFFIX)(void) |
271 | 283 | { |
272 | 284 | if ((DATA_TYPE)CC_DST == 0) |
273 | - JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 0, PARAM2); | |
274 | - else | |
275 | - JUMP_TB(glue(op_jz_sub, SUFFIX), PARAM1, 1, PARAM3); | |
285 | + GOTO_LABEL_PARAM(1); | |
286 | + FORCE_RET(); | |
287 | +} | |
288 | + | |
289 | +void OPPROTO glue(op_jnz_sub, SUFFIX)(void) | |
290 | +{ | |
291 | + if ((DATA_TYPE)CC_DST != 0) | |
292 | + GOTO_LABEL_PARAM(1); | |
276 | 293 | FORCE_RET(); |
277 | 294 | } |
278 | 295 | |
279 | 296 | void OPPROTO glue(op_jbe_sub, SUFFIX)(void) |
280 | 297 | { |
281 | - int src1, src2; | |
298 | + target_long src1, src2; | |
282 | 299 | src1 = CC_DST + CC_SRC; |
283 | 300 | src2 = CC_SRC; |
284 | 301 | |
285 | 302 | if ((DATA_TYPE)src1 <= (DATA_TYPE)src2) |
286 | - JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 0, PARAM2); | |
287 | - else | |
288 | - JUMP_TB(glue(op_jbe_sub, SUFFIX), PARAM1, 1, PARAM3); | |
303 | + GOTO_LABEL_PARAM(1); | |
289 | 304 | FORCE_RET(); |
290 | 305 | } |
291 | 306 | |
292 | 307 | void OPPROTO glue(op_js_sub, SUFFIX)(void) |
293 | 308 | { |
294 | 309 | if (CC_DST & SIGN_MASK) |
295 | - JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 0, PARAM2); | |
296 | - else | |
297 | - JUMP_TB(glue(op_js_sub, SUFFIX), PARAM1, 1, PARAM3); | |
310 | + GOTO_LABEL_PARAM(1); | |
298 | 311 | FORCE_RET(); |
299 | 312 | } |
300 | 313 | |
301 | 314 | void OPPROTO glue(op_jl_sub, SUFFIX)(void) |
302 | 315 | { |
303 | - int src1, src2; | |
316 | + target_long src1, src2; | |
304 | 317 | src1 = CC_DST + CC_SRC; |
305 | 318 | src2 = CC_SRC; |
306 | 319 | |
307 | 320 | if ((DATA_STYPE)src1 < (DATA_STYPE)src2) |
308 | - JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 0, PARAM2); | |
309 | - else | |
310 | - JUMP_TB(glue(op_jl_sub, SUFFIX), PARAM1, 1, PARAM3); | |
321 | + GOTO_LABEL_PARAM(1); | |
311 | 322 | FORCE_RET(); |
312 | 323 | } |
313 | 324 | |
314 | 325 | void OPPROTO glue(op_jle_sub, SUFFIX)(void) |
315 | 326 | { |
316 | - int src1, src2; | |
327 | + target_long src1, src2; | |
317 | 328 | src1 = CC_DST + CC_SRC; |
318 | 329 | src2 = CC_SRC; |
319 | 330 | |
320 | 331 | if ((DATA_STYPE)src1 <= (DATA_STYPE)src2) |
321 | - JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 0, PARAM2); | |
322 | - else | |
323 | - JUMP_TB(glue(op_jle_sub, SUFFIX), PARAM1, 1, PARAM3); | |
332 | + GOTO_LABEL_PARAM(1); | |
324 | 333 | FORCE_RET(); |
325 | 334 | } |
326 | 335 | |
... | ... | @@ -330,50 +339,33 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void) |
330 | 339 | |
331 | 340 | void OPPROTO glue(op_loopnz, SUFFIX)(void) |
332 | 341 | { |
333 | - unsigned int tmp; | |
334 | 342 | int eflags; |
335 | 343 | eflags = cc_table[CC_OP].compute_all(); |
336 | - tmp = (ECX - 1) & DATA_MASK; | |
337 | - ECX = (ECX & ~DATA_MASK) | tmp; | |
338 | - if (tmp != 0 && !(eflags & CC_Z)) | |
339 | - EIP = PARAM1; | |
340 | - else | |
341 | - EIP = PARAM2; | |
344 | + if ((DATA_TYPE)ECX != 0 && !(eflags & CC_Z)) | |
345 | + GOTO_LABEL_PARAM(1); | |
342 | 346 | FORCE_RET(); |
343 | 347 | } |
344 | 348 | |
345 | 349 | void OPPROTO glue(op_loopz, SUFFIX)(void) |
346 | 350 | { |
347 | - unsigned int tmp; | |
348 | 351 | int eflags; |
349 | 352 | eflags = cc_table[CC_OP].compute_all(); |
350 | - tmp = (ECX - 1) & DATA_MASK; | |
351 | - ECX = (ECX & ~DATA_MASK) | tmp; | |
352 | - if (tmp != 0 && (eflags & CC_Z)) | |
353 | - EIP = PARAM1; | |
354 | - else | |
355 | - EIP = PARAM2; | |
353 | + if ((DATA_TYPE)ECX != 0 && (eflags & CC_Z)) | |
354 | + GOTO_LABEL_PARAM(1); | |
356 | 355 | FORCE_RET(); |
357 | 356 | } |
358 | 357 | |
359 | -void OPPROTO glue(op_loop, SUFFIX)(void) | |
358 | +void OPPROTO glue(op_jz_ecx, SUFFIX)(void) | |
360 | 359 | { |
361 | - unsigned int tmp; | |
362 | - tmp = (ECX - 1) & DATA_MASK; | |
363 | - ECX = (ECX & ~DATA_MASK) | tmp; | |
364 | - if (tmp != 0) | |
365 | - EIP = PARAM1; | |
366 | - else | |
367 | - EIP = PARAM2; | |
360 | + if ((DATA_TYPE)ECX == 0) | |
361 | + GOTO_LABEL_PARAM(1); | |
368 | 362 | FORCE_RET(); |
369 | 363 | } |
370 | 364 | |
371 | -void OPPROTO glue(op_jecxz, SUFFIX)(void) | |
365 | +void OPPROTO glue(op_jnz_ecx, SUFFIX)(void) | |
372 | 366 | { |
373 | - if ((DATA_TYPE)ECX == 0) | |
374 | - EIP = PARAM1; | |
375 | - else | |
376 | - EIP = PARAM2; | |
367 | + if ((DATA_TYPE)ECX != 0) | |
368 | + GOTO_LABEL_PARAM(1); | |
377 | 369 | FORCE_RET(); |
378 | 370 | } |
379 | 371 | |
... | ... | @@ -383,7 +375,7 @@ void OPPROTO glue(op_jecxz, SUFFIX)(void) |
383 | 375 | |
384 | 376 | void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) |
385 | 377 | { |
386 | - int src1, src2; | |
378 | + target_long src1, src2; | |
387 | 379 | src1 = CC_DST + CC_SRC; |
388 | 380 | src2 = CC_SRC; |
389 | 381 | |
... | ... | @@ -397,7 +389,7 @@ void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void) |
397 | 389 | |
398 | 390 | void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void) |
399 | 391 | { |
400 | - int src1, src2; | |
392 | + target_long src1, src2; | |
401 | 393 | src1 = CC_DST + CC_SRC; |
402 | 394 | src2 = CC_SRC; |
403 | 395 | |
... | ... | @@ -411,7 +403,7 @@ void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void) |
411 | 403 | |
412 | 404 | void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void) |
413 | 405 | { |
414 | - int src1, src2; | |
406 | + target_long src1, src2; | |
415 | 407 | src1 = CC_DST + CC_SRC; |
416 | 408 | src2 = CC_SRC; |
417 | 409 | |
... | ... | @@ -420,7 +412,7 @@ void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void) |
420 | 412 | |
421 | 413 | void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) |
422 | 414 | { |
423 | - int src1, src2; | |
415 | + target_long src1, src2; | |
424 | 416 | src1 = CC_DST + CC_SRC; |
425 | 417 | src2 = CC_SRC; |
426 | 418 | |
... | ... | @@ -432,7 +424,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) |
432 | 424 | void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void) |
433 | 425 | { |
434 | 426 | int count; |
435 | - count = T1 & 0x1f; | |
427 | + count = T1 & SHIFT1_MASK; | |
436 | 428 | T0 = T0 << count; |
437 | 429 | FORCE_RET(); |
438 | 430 | } |
... | ... | @@ -440,7 +432,7 @@ void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void) |
440 | 432 | void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void) |
441 | 433 | { |
442 | 434 | int count; |
443 | - count = T1 & 0x1f; | |
435 | + count = T1 & SHIFT1_MASK; | |
444 | 436 | T0 &= DATA_MASK; |
445 | 437 | T0 = T0 >> count; |
446 | 438 | FORCE_RET(); |
... | ... | @@ -448,8 +440,10 @@ void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void) |
448 | 440 | |
449 | 441 | void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void) |
450 | 442 | { |
451 | - int count, src; | |
452 | - count = T1 & 0x1f; | |
443 | + int count; | |
444 | + target_long src; | |
445 | + | |
446 | + count = T1 & SHIFT1_MASK; | |
453 | 447 | src = (DATA_STYPE)T0; |
454 | 448 | T0 = src >> count; |
455 | 449 | FORCE_RET(); |
... | ... | @@ -484,7 +478,7 @@ void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void) |
484 | 478 | int count; |
485 | 479 | count = T1 & SHIFT_MASK; |
486 | 480 | T1 = T0 >> count; |
487 | - T0 |= (1 << count); | |
481 | + T0 |= (((target_long)1) << count); | |
488 | 482 | } |
489 | 483 | |
490 | 484 | void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void) |
... | ... | @@ -492,7 +486,7 @@ void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void) |
492 | 486 | int count; |
493 | 487 | count = T1 & SHIFT_MASK; |
494 | 488 | T1 = T0 >> count; |
495 | - T0 &= ~(1 << count); | |
489 | + T0 &= ~(((target_long)1) << count); | |
496 | 490 | } |
497 | 491 | |
498 | 492 | void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void) |
... | ... | @@ -500,12 +494,19 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void) |
500 | 494 | int count; |
501 | 495 | count = T1 & SHIFT_MASK; |
502 | 496 | T1 = T0 >> count; |
503 | - T0 ^= (1 << count); | |
497 | + T0 ^= (((target_long)1) << count); | |
498 | +} | |
499 | + | |
500 | +void OPPROTO glue(glue(op_add_bit, SUFFIX), _A0_T1)(void) | |
501 | +{ | |
502 | + A0 += ((DATA_STYPE)T1 >> (3 + SHIFT)) << SHIFT; | |
504 | 503 | } |
505 | 504 | |
506 | 505 | void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void) |
507 | 506 | { |
508 | - int res, count; | |
507 | + int count; | |
508 | + target_long res; | |
509 | + | |
509 | 510 | res = T0 & DATA_MASK; |
510 | 511 | if (res != 0) { |
511 | 512 | count = 0; |
... | ... | @@ -523,7 +524,9 @@ void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void) |
523 | 524 | |
524 | 525 | void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void) |
525 | 526 | { |
526 | - int res, count; | |
527 | + int count; | |
528 | + target_long res; | |
529 | + | |
527 | 530 | res = T0 & DATA_MASK; |
528 | 531 | if (res != 0) { |
529 | 532 | count = DATA_BITS - 1; |
... | ... | @@ -555,70 +558,8 @@ void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void) |
555 | 558 | T0 = DF << SHIFT; |
556 | 559 | } |
557 | 560 | |
558 | -void OPPROTO glue(op_string_jz_sub, SUFFIX)(void) | |
559 | -{ | |
560 | - if ((DATA_TYPE)CC_DST == 0) | |
561 | - JUMP_TB2(glue(op_string_jz_sub, SUFFIX), PARAM1, 3); | |
562 | - FORCE_RET(); | |
563 | -} | |
564 | - | |
565 | -void OPPROTO glue(op_string_jnz_sub, SUFFIX)(void) | |
566 | -{ | |
567 | - if ((DATA_TYPE)CC_DST != 0) | |
568 | - JUMP_TB2(glue(op_string_jnz_sub, SUFFIX), PARAM1, 3); | |
569 | - FORCE_RET(); | |
570 | -} | |
571 | - | |
572 | -void OPPROTO glue(glue(op_string_jz_sub, SUFFIX), _im)(void) | |
573 | -{ | |
574 | - if ((DATA_TYPE)CC_DST == 0) { | |
575 | - EIP = PARAM1; | |
576 | - if (env->eflags & TF_MASK) { | |
577 | - raise_exception(EXCP01_SSTP); | |
578 | - } | |
579 | - T0 = 0; | |
580 | - EXIT_TB(); | |
581 | - } | |
582 | - FORCE_RET(); | |
583 | -} | |
584 | - | |
585 | -void OPPROTO glue(glue(op_string_jnz_sub, SUFFIX), _im)(void) | |
586 | -{ | |
587 | - if ((DATA_TYPE)CC_DST != 0) { | |
588 | - EIP = PARAM1; | |
589 | - if (env->eflags & TF_MASK) { | |
590 | - raise_exception(EXCP01_SSTP); | |
591 | - } | |
592 | - T0 = 0; | |
593 | - EXIT_TB(); | |
594 | - } | |
595 | - FORCE_RET(); | |
596 | -} | |
597 | - | |
598 | -#if DATA_BITS >= 16 | |
599 | -void OPPROTO glue(op_jz_ecx, SUFFIX)(void) | |
600 | -{ | |
601 | - if ((DATA_TYPE)ECX == 0) | |
602 | - JUMP_TB(glue(op_jz_ecx, SUFFIX), PARAM1, 1, PARAM2); | |
603 | - FORCE_RET(); | |
604 | -} | |
605 | - | |
606 | -void OPPROTO glue(glue(op_jz_ecx, SUFFIX), _im)(void) | |
607 | -{ | |
608 | - if ((DATA_TYPE)ECX == 0) { | |
609 | - EIP = PARAM1; | |
610 | - if (env->eflags & TF_MASK) { | |
611 | - raise_exception(EXCP01_SSTP); | |
612 | - } | |
613 | - T0 = 0; | |
614 | - EXIT_TB(); | |
615 | - } | |
616 | - FORCE_RET(); | |
617 | -} | |
618 | -#endif | |
619 | - | |
620 | 561 | /* port I/O */ |
621 | - | |
562 | +#if DATA_BITS <= 32 | |
622 | 563 | void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) |
623 | 564 | { |
624 | 565 | glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK); |
... | ... | @@ -648,9 +589,11 @@ void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void) |
648 | 589 | { |
649 | 590 | glue(glue(check_io, SUFFIX), _DX)(); |
650 | 591 | } |
592 | +#endif | |
651 | 593 | |
652 | 594 | #undef DATA_BITS |
653 | 595 | #undef SHIFT_MASK |
596 | +#undef SHIFT1_MASK | |
654 | 597 | #undef SIGN_MASK |
655 | 598 | #undef DATA_TYPE |
656 | 599 | #undef DATA_STYPE | ... | ... |
target-i386/ops_template_mem.h
... | ... | @@ -28,6 +28,8 @@ |
28 | 28 | #define MEM_SUFFIX w_raw |
29 | 29 | #elif DATA_BITS == 32 |
30 | 30 | #define MEM_SUFFIX l_raw |
31 | +#elif DATA_BITS == 64 | |
32 | +#define MEM_SUFFIX q_raw | |
31 | 33 | #endif |
32 | 34 | |
33 | 35 | #elif MEM_WRITE == 1 |
... | ... | @@ -38,6 +40,8 @@ |
38 | 40 | #define MEM_SUFFIX w_kernel |
39 | 41 | #elif DATA_BITS == 32 |
40 | 42 | #define MEM_SUFFIX l_kernel |
43 | +#elif DATA_BITS == 64 | |
44 | +#define MEM_SUFFIX q_kernel | |
41 | 45 | #endif |
42 | 46 | |
43 | 47 | #elif MEM_WRITE == 2 |
... | ... | @@ -48,6 +52,8 @@ |
48 | 52 | #define MEM_SUFFIX w_user |
49 | 53 | #elif DATA_BITS == 32 |
50 | 54 | #define MEM_SUFFIX l_user |
55 | +#elif DATA_BITS == 64 | |
56 | +#define MEM_SUFFIX q_user | |
51 | 57 | #endif |
52 | 58 | |
53 | 59 | #else |
... | ... | @@ -64,14 +70,16 @@ |
64 | 70 | |
65 | 71 | void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void) |
66 | 72 | { |
67 | - int count, src; | |
73 | + int count; | |
74 | + target_long src; | |
75 | + | |
68 | 76 | count = T1 & SHIFT_MASK; |
69 | 77 | if (count) { |
70 | 78 | src = T0; |
71 | 79 | T0 &= DATA_MASK; |
72 | 80 | T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); |
73 | 81 | #ifdef MEM_WRITE |
74 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
82 | + glue(st, MEM_SUFFIX)(A0, T0); | |
75 | 83 | #else |
76 | 84 | /* gcc 3.2 workaround. This is really a bug in gcc. */ |
77 | 85 | asm volatile("" : : "r" (T0)); |
... | ... | @@ -86,14 +94,16 @@ void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1_cc)(void) |
86 | 94 | |
87 | 95 | void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1_cc)(void) |
88 | 96 | { |
89 | - int count, src; | |
97 | + int count; | |
98 | + target_long src; | |
99 | + | |
90 | 100 | count = T1 & SHIFT_MASK; |
91 | 101 | if (count) { |
92 | 102 | src = T0; |
93 | 103 | T0 &= DATA_MASK; |
94 | 104 | T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); |
95 | 105 | #ifdef MEM_WRITE |
96 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
106 | + glue(st, MEM_SUFFIX)(A0, T0); | |
97 | 107 | #else |
98 | 108 | /* gcc 3.2 workaround. This is really a bug in gcc. */ |
99 | 109 | asm volatile("" : : "r" (T0)); |
... | ... | @@ -114,7 +124,7 @@ void OPPROTO glue(glue(op_rol, MEM_SUFFIX), _T0_T1)(void) |
114 | 124 | T0 &= DATA_MASK; |
115 | 125 | T0 = (T0 << count) | (T0 >> (DATA_BITS - count)); |
116 | 126 | #ifdef MEM_WRITE |
117 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
127 | + glue(st, MEM_SUFFIX)(A0, T0); | |
118 | 128 | #endif |
119 | 129 | } |
120 | 130 | FORCE_RET(); |
... | ... | @@ -128,7 +138,7 @@ void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void) |
128 | 138 | T0 &= DATA_MASK; |
129 | 139 | T0 = (T0 >> count) | (T0 << (DATA_BITS - count)); |
130 | 140 | #ifdef MEM_WRITE |
131 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
141 | + glue(st, MEM_SUFFIX)(A0, T0); | |
132 | 142 | #endif |
133 | 143 | } |
134 | 144 | FORCE_RET(); |
... | ... | @@ -136,10 +146,11 @@ void OPPROTO glue(glue(op_ror, MEM_SUFFIX), _T0_T1)(void) |
136 | 146 | |
137 | 147 | void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void) |
138 | 148 | { |
139 | - int count, res, eflags; | |
140 | - unsigned int src; | |
149 | + int count, eflags; | |
150 | + target_ulong src; | |
151 | + target_long res; | |
141 | 152 | |
142 | - count = T1 & 0x1f; | |
153 | + count = T1 & SHIFT1_MASK; | |
143 | 154 | #if DATA_BITS == 16 |
144 | 155 | count = rclw_table[count]; |
145 | 156 | #elif DATA_BITS == 8 |
... | ... | @@ -154,7 +165,7 @@ void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void) |
154 | 165 | res |= T0 >> (DATA_BITS + 1 - count); |
155 | 166 | T0 = res; |
156 | 167 | #ifdef MEM_WRITE |
157 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
168 | + glue(st, MEM_SUFFIX)(A0, T0); | |
158 | 169 | #endif |
159 | 170 | CC_SRC = (eflags & ~(CC_C | CC_O)) | |
160 | 171 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | |
... | ... | @@ -166,10 +177,11 @@ void OPPROTO glue(glue(op_rcl, MEM_SUFFIX), _T0_T1_cc)(void) |
166 | 177 | |
167 | 178 | void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void) |
168 | 179 | { |
169 | - int count, res, eflags; | |
170 | - unsigned int src; | |
180 | + int count, eflags; | |
181 | + target_ulong src; | |
182 | + target_long res; | |
171 | 183 | |
172 | - count = T1 & 0x1f; | |
184 | + count = T1 & SHIFT1_MASK; | |
173 | 185 | #if DATA_BITS == 16 |
174 | 186 | count = rclw_table[count]; |
175 | 187 | #elif DATA_BITS == 8 |
... | ... | @@ -184,7 +196,7 @@ void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void) |
184 | 196 | res |= T0 << (DATA_BITS + 1 - count); |
185 | 197 | T0 = res; |
186 | 198 | #ifdef MEM_WRITE |
187 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
199 | + glue(st, MEM_SUFFIX)(A0, T0); | |
188 | 200 | #endif |
189 | 201 | CC_SRC = (eflags & ~(CC_C | CC_O)) | |
190 | 202 | (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) | |
... | ... | @@ -196,13 +208,15 @@ void OPPROTO glue(glue(op_rcr, MEM_SUFFIX), _T0_T1_cc)(void) |
196 | 208 | |
197 | 209 | void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void) |
198 | 210 | { |
199 | - int count, src; | |
200 | - count = T1 & 0x1f; | |
211 | + int count; | |
212 | + target_long src; | |
213 | + | |
214 | + count = T1 & SHIFT1_MASK; | |
201 | 215 | if (count) { |
202 | 216 | src = (DATA_TYPE)T0 << (count - 1); |
203 | 217 | T0 = T0 << count; |
204 | 218 | #ifdef MEM_WRITE |
205 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
219 | + glue(st, MEM_SUFFIX)(A0, T0); | |
206 | 220 | #endif |
207 | 221 | CC_SRC = src; |
208 | 222 | CC_DST = T0; |
... | ... | @@ -213,14 +227,16 @@ void OPPROTO glue(glue(op_shl, MEM_SUFFIX), _T0_T1_cc)(void) |
213 | 227 | |
214 | 228 | void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void) |
215 | 229 | { |
216 | - int count, src; | |
217 | - count = T1 & 0x1f; | |
230 | + int count; | |
231 | + target_long src; | |
232 | + | |
233 | + count = T1 & SHIFT1_MASK; | |
218 | 234 | if (count) { |
219 | 235 | T0 &= DATA_MASK; |
220 | 236 | src = T0 >> (count - 1); |
221 | 237 | T0 = T0 >> count; |
222 | 238 | #ifdef MEM_WRITE |
223 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
239 | + glue(st, MEM_SUFFIX)(A0, T0); | |
224 | 240 | #endif |
225 | 241 | CC_SRC = src; |
226 | 242 | CC_DST = T0; |
... | ... | @@ -231,14 +247,16 @@ void OPPROTO glue(glue(op_shr, MEM_SUFFIX), _T0_T1_cc)(void) |
231 | 247 | |
232 | 248 | void OPPROTO glue(glue(op_sar, MEM_SUFFIX), _T0_T1_cc)(void) |
233 | 249 | { |
234 | - int count, src; | |
235 | - count = T1 & 0x1f; | |
250 | + int count; | |
251 | + target_long src; | |
252 | + | |
253 | + count = T1 & SHIFT1_MASK; | |
236 | 254 | if (count) { |
237 | 255 | src = (DATA_STYPE)T0; |
238 | 256 | T0 = src >> count; |
239 | 257 | src = src >> (count - 1); |
240 | 258 | #ifdef MEM_WRITE |
241 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
259 | + glue(st, MEM_SUFFIX)(A0, T0); | |
242 | 260 | #endif |
243 | 261 | CC_SRC = src; |
244 | 262 | CC_DST = T0; |
... | ... | @@ -262,7 +280,7 @@ void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) |
262 | 280 | res |= T1 << (count - 16); |
263 | 281 | T0 = res >> 16; |
264 | 282 | #ifdef MEM_WRITE |
265 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
283 | + glue(st, MEM_SUFFIX)(A0, T0); | |
266 | 284 | #endif |
267 | 285 | CC_SRC = tmp; |
268 | 286 | CC_DST = T0; |
... | ... | @@ -282,7 +300,7 @@ void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
282 | 300 | res |= T1 << (count - 16); |
283 | 301 | T0 = res >> 16; |
284 | 302 | #ifdef MEM_WRITE |
285 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
303 | + glue(st, MEM_SUFFIX)(A0, T0); | |
286 | 304 | #endif |
287 | 305 | CC_SRC = tmp; |
288 | 306 | CC_DST = T0; |
... | ... | @@ -304,7 +322,7 @@ void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) |
304 | 322 | res |= T1 << (32 - count); |
305 | 323 | T0 = res; |
306 | 324 | #ifdef MEM_WRITE |
307 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
325 | + glue(st, MEM_SUFFIX)(A0, T0); | |
308 | 326 | #endif |
309 | 327 | CC_SRC = tmp; |
310 | 328 | CC_DST = T0; |
... | ... | @@ -325,7 +343,7 @@ void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
325 | 343 | res |= T1 << (32 - count); |
326 | 344 | T0 = res; |
327 | 345 | #ifdef MEM_WRITE |
328 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
346 | + glue(st, MEM_SUFFIX)(A0, T0); | |
329 | 347 | #endif |
330 | 348 | CC_SRC = tmp; |
331 | 349 | CC_DST = T0; |
... | ... | @@ -335,17 +353,19 @@ void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
335 | 353 | } |
336 | 354 | #endif |
337 | 355 | |
338 | -#if DATA_BITS == 32 | |
356 | +#if DATA_BITS >= 32 | |
339 | 357 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) |
340 | 358 | { |
341 | - int count, tmp; | |
359 | + int count; | |
360 | + target_long tmp; | |
361 | + | |
342 | 362 | count = PARAM1; |
343 | 363 | T0 &= DATA_MASK; |
344 | 364 | T1 &= DATA_MASK; |
345 | 365 | tmp = T0 << (count - 1); |
346 | 366 | T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); |
347 | 367 | #ifdef MEM_WRITE |
348 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
368 | + glue(st, MEM_SUFFIX)(A0, T0); | |
349 | 369 | #endif |
350 | 370 | CC_SRC = tmp; |
351 | 371 | CC_DST = T0; |
... | ... | @@ -353,15 +373,17 @@ void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_im_cc)(void) |
353 | 373 | |
354 | 374 | void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
355 | 375 | { |
356 | - int count, tmp; | |
357 | - count = ECX & 0x1f; | |
376 | + int count; | |
377 | + target_long tmp; | |
378 | + | |
379 | + count = ECX & SHIFT1_MASK; | |
358 | 380 | if (count) { |
359 | 381 | T0 &= DATA_MASK; |
360 | 382 | T1 &= DATA_MASK; |
361 | 383 | tmp = T0 << (count - 1); |
362 | 384 | T0 = (T0 << count) | (T1 >> (DATA_BITS - count)); |
363 | 385 | #ifdef MEM_WRITE |
364 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
386 | + glue(st, MEM_SUFFIX)(A0, T0); | |
365 | 387 | #endif |
366 | 388 | CC_SRC = tmp; |
367 | 389 | CC_DST = T0; |
... | ... | @@ -372,14 +394,16 @@ void OPPROTO glue(glue(op_shld, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
372 | 394 | |
373 | 395 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) |
374 | 396 | { |
375 | - int count, tmp; | |
397 | + int count; | |
398 | + target_long tmp; | |
399 | + | |
376 | 400 | count = PARAM1; |
377 | 401 | T0 &= DATA_MASK; |
378 | 402 | T1 &= DATA_MASK; |
379 | 403 | tmp = T0 >> (count - 1); |
380 | 404 | T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); |
381 | 405 | #ifdef MEM_WRITE |
382 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
406 | + glue(st, MEM_SUFFIX)(A0, T0); | |
383 | 407 | #endif |
384 | 408 | CC_SRC = tmp; |
385 | 409 | CC_DST = T0; |
... | ... | @@ -388,15 +412,17 @@ void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_im_cc)(void) |
388 | 412 | |
389 | 413 | void OPPROTO glue(glue(op_shrd, MEM_SUFFIX), _T0_T1_ECX_cc)(void) |
390 | 414 | { |
391 | - int count, tmp; | |
392 | - count = ECX & 0x1f; | |
415 | + int count; | |
416 | + target_long tmp; | |
417 | + | |
418 | + count = ECX & SHIFT1_MASK; | |
393 | 419 | if (count) { |
394 | 420 | T0 &= DATA_MASK; |
395 | 421 | T1 &= DATA_MASK; |
396 | 422 | tmp = T0 >> (count - 1); |
397 | 423 | T0 = (T0 >> count) | (T1 << (DATA_BITS - count)); |
398 | 424 | #ifdef MEM_WRITE |
399 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
425 | + glue(st, MEM_SUFFIX)(A0, T0); | |
400 | 426 | #endif |
401 | 427 | CC_SRC = tmp; |
402 | 428 | CC_DST = T0; |
... | ... | @@ -414,11 +440,11 @@ void OPPROTO glue(glue(op_adc, MEM_SUFFIX), _T0_T1_cc)(void) |
414 | 440 | cf = cc_table[CC_OP].compute_c(); |
415 | 441 | T0 = T0 + T1 + cf; |
416 | 442 | #ifdef MEM_WRITE |
417 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
443 | + glue(st, MEM_SUFFIX)(A0, T0); | |
418 | 444 | #endif |
419 | 445 | CC_SRC = T1; |
420 | 446 | CC_DST = T0; |
421 | - CC_OP = CC_OP_ADDB + SHIFT + cf * 3; | |
447 | + CC_OP = CC_OP_ADDB + SHIFT + cf * 4; | |
422 | 448 | } |
423 | 449 | |
424 | 450 | void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) |
... | ... | @@ -427,23 +453,23 @@ void OPPROTO glue(glue(op_sbb, MEM_SUFFIX), _T0_T1_cc)(void) |
427 | 453 | cf = cc_table[CC_OP].compute_c(); |
428 | 454 | T0 = T0 - T1 - cf; |
429 | 455 | #ifdef MEM_WRITE |
430 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
456 | + glue(st, MEM_SUFFIX)(A0, T0); | |
431 | 457 | #endif |
432 | 458 | CC_SRC = T1; |
433 | 459 | CC_DST = T0; |
434 | - CC_OP = CC_OP_SUBB + SHIFT + cf * 3; | |
460 | + CC_OP = CC_OP_SUBB + SHIFT + cf * 4; | |
435 | 461 | } |
436 | 462 | |
437 | 463 | void OPPROTO glue(glue(op_cmpxchg, MEM_SUFFIX), _T0_T1_EAX_cc)(void) |
438 | 464 | { |
439 | - unsigned int src, dst; | |
465 | + target_ulong src, dst; | |
440 | 466 | |
441 | 467 | src = T0; |
442 | 468 | dst = EAX - T0; |
443 | 469 | if ((DATA_TYPE)dst == 0) { |
444 | 470 | T0 = T1; |
445 | 471 | #ifdef MEM_WRITE |
446 | - glue(st, MEM_SUFFIX)((uint8_t *)A0, T0); | |
472 | + glue(st, MEM_SUFFIX)(A0, T0); | |
447 | 473 | #endif |
448 | 474 | } else { |
449 | 475 | EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK); | ... | ... |