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
11 changed files
with
3678 additions
and
1300 deletions
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); | ... | ... |
target-i386/translate-copy.c
| ... | ... | @@ -57,7 +57,7 @@ typedef struct DisasContext { |
| 57 | 57 | int override; /* -1 if no override */ |
| 58 | 58 | int prefix; |
| 59 | 59 | int aflag, dflag; |
| 60 | - uint8_t *pc; /* pc = eip + cs_base */ | |
| 60 | + target_ulong pc; /* pc = eip + cs_base */ | |
| 61 | 61 | int is_jmp; /* 1 = means jump (stop translation), 2 means CPU |
| 62 | 62 | static state change (stop translation) */ |
| 63 | 63 | /* code output */ |
| ... | ... | @@ -65,7 +65,7 @@ typedef struct DisasContext { |
| 65 | 65 | uint8_t *gen_code_start; |
| 66 | 66 | |
| 67 | 67 | /* current block context */ |
| 68 | - uint8_t *cs_base; /* base of CS segment */ | |
| 68 | + target_ulong cs_base; /* base of CS segment */ | |
| 69 | 69 | int pe; /* protected mode */ |
| 70 | 70 | int code32; /* 32 bit code segment */ |
| 71 | 71 | int f_st; /* currently unused */ |
| ... | ... | @@ -277,7 +277,7 @@ static inline uint32_t insn_get(DisasContext *s, int ot) |
| 277 | 277 | be stopped. */ |
| 278 | 278 | static int disas_insn(DisasContext *s) |
| 279 | 279 | { |
| 280 | - uint8_t *pc_start, *pc_tmp, *pc_start_insn; | |
| 280 | + target_ulong pc_start, pc_tmp, pc_start_insn; | |
| 281 | 281 | int b, prefixes, aflag, dflag, next_eip, val; |
| 282 | 282 | int ot; |
| 283 | 283 | int modrm, mod, op, rm; |
| ... | ... | @@ -789,6 +789,8 @@ static int disas_insn(DisasContext *s) |
| 789 | 789 | break; |
| 790 | 790 | case 0x1e: /* fcomi */ |
| 791 | 791 | break; |
| 792 | + case 0x28: /* ffree sti */ | |
| 793 | + break; | |
| 792 | 794 | case 0x2a: /* fst sti */ |
| 793 | 795 | break; |
| 794 | 796 | case 0x2b: /* fstp sti */ |
| ... | ... | @@ -1176,9 +1178,9 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 1176 | 1178 | uint8_t *tc_ptr) |
| 1177 | 1179 | { |
| 1178 | 1180 | DisasContext dc1, *dc = &dc1; |
| 1179 | - uint8_t *pc_insn, *pc_start, *gen_code_end; | |
| 1181 | + target_ulong pc_insn, pc_start, cs_base; | |
| 1182 | + uint8_t *gen_code_end; | |
| 1180 | 1183 | int flags, ret; |
| 1181 | - uint8_t *cs_base; | |
| 1182 | 1184 | |
| 1183 | 1185 | if (env->nb_breakpoints > 0 || |
| 1184 | 1186 | env->singlestep_enabled) |
| ... | ... | @@ -1197,8 +1199,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 1197 | 1199 | dc->gen_code_start = gen_code_ptr; |
| 1198 | 1200 | |
| 1199 | 1201 | /* generate intermediate code */ |
| 1200 | - pc_start = (uint8_t *)tb->pc; | |
| 1201 | - cs_base = (uint8_t *)tb->cs_base; | |
| 1202 | + pc_start = tb->pc; | |
| 1203 | + cs_base = tb->cs_base; | |
| 1202 | 1204 | dc->pc = pc_start; |
| 1203 | 1205 | dc->cs_base = cs_base; |
| 1204 | 1206 | dc->pe = (flags >> HF_PE_SHIFT) & 1; |
| ... | ... | @@ -1249,7 +1251,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 1249 | 1251 | fprintf(logfile, "IN: COPY: %s fpu=%d\n", |
| 1250 | 1252 | lookup_symbol(pc_start), |
| 1251 | 1253 | tb->cflags & CF_TB_FP_USED ? 1 : 0); |
| 1252 | - disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32); | |
| 1254 | + target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32); | |
| 1253 | 1255 | fprintf(logfile, "\n"); |
| 1254 | 1256 | } |
| 1255 | 1257 | #endif | ... | ... |
target-i386/translate.c
| ... | ... | @@ -39,18 +39,45 @@ static uint32_t *gen_opparam_ptr; |
| 39 | 39 | #define PREFIX_DATA 0x08 |
| 40 | 40 | #define PREFIX_ADR 0x10 |
| 41 | 41 | |
| 42 | +#ifdef TARGET_X86_64 | |
| 43 | +#define X86_64_ONLY(x) x | |
| 44 | +#define X86_64_DEF(x...) x | |
| 45 | +#define CODE64(s) ((s)->code64) | |
| 46 | +#define REX_X(s) ((s)->rex_x) | |
| 47 | +#define REX_B(s) ((s)->rex_b) | |
| 48 | +/* XXX: gcc generates push/pop in some opcodes, so we cannot use them */ | |
| 49 | +#if 1 | |
| 50 | +#define BUGGY_64(x) NULL | |
| 51 | +#endif | |
| 52 | +#else | |
| 53 | +#define X86_64_ONLY(x) NULL | |
| 54 | +#define X86_64_DEF(x...) | |
| 55 | +#define CODE64(s) 0 | |
| 56 | +#define REX_X(s) 0 | |
| 57 | +#define REX_B(s) 0 | |
| 58 | +#endif | |
| 59 | + | |
| 60 | +#ifdef TARGET_X86_64 | |
| 61 | +static int x86_64_hregs; | |
| 62 | +#endif | |
| 63 | + | |
| 42 | 64 | typedef struct DisasContext { |
| 43 | 65 | /* current insn context */ |
| 44 | 66 | int override; /* -1 if no override */ |
| 45 | 67 | int prefix; |
| 46 | 68 | int aflag, dflag; |
| 47 | - uint8_t *pc; /* pc = eip + cs_base */ | |
| 69 | + target_ulong pc; /* pc = eip + cs_base */ | |
| 48 | 70 | int is_jmp; /* 1 = means jump (stop translation), 2 means CPU |
| 49 | 71 | static state change (stop translation) */ |
| 50 | 72 | /* current block context */ |
| 51 | - uint8_t *cs_base; /* base of CS segment */ | |
| 73 | + target_ulong cs_base; /* base of CS segment */ | |
| 52 | 74 | int pe; /* protected mode */ |
| 53 | 75 | int code32; /* 32 bit code segment */ |
| 76 | +#ifdef TARGET_X86_64 | |
| 77 | + int lma; /* long mode active */ | |
| 78 | + int code64; /* 64 bit code segment */ | |
| 79 | + int rex_x, rex_b; | |
| 80 | +#endif | |
| 54 | 81 | int ss32; /* 32 bit stack segment */ |
| 55 | 82 | int cc_op; /* current CC operation */ |
| 56 | 83 | int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
| ... | ... | @@ -65,10 +92,13 @@ typedef struct DisasContext { |
| 65 | 92 | int flags; /* all execution flags */ |
| 66 | 93 | struct TranslationBlock *tb; |
| 67 | 94 | int popl_esp_hack; /* for correct popl with esp base handling */ |
| 95 | + int rip_offset; /* only used in x86_64, but left for simplicity */ | |
| 96 | + int cpuid_features; | |
| 68 | 97 | } DisasContext; |
| 69 | 98 | |
| 70 | 99 | static void gen_eob(DisasContext *s); |
| 71 | -static void gen_jmp(DisasContext *s, unsigned int eip); | |
| 100 | +static void gen_jmp(DisasContext *s, target_ulong eip); | |
| 101 | +static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num); | |
| 72 | 102 | |
| 73 | 103 | /* i386 arith/logic operations */ |
| 74 | 104 | enum { |
| ... | ... | @@ -121,103 +151,182 @@ enum { |
| 121 | 151 | OR_EBP, |
| 122 | 152 | OR_ESI, |
| 123 | 153 | OR_EDI, |
| 124 | - OR_TMP0, /* temporary operand register */ | |
| 154 | + | |
| 155 | + OR_TMP0 = 16, /* temporary operand register */ | |
| 125 | 156 | OR_TMP1, |
| 126 | 157 | OR_A0, /* temporary register used when doing address evaluation */ |
| 127 | - OR_ZERO, /* fixed zero register */ | |
| 128 | - NB_OREGS, | |
| 129 | 158 | }; |
| 130 | 159 | |
| 131 | -static GenOpFunc *gen_op_mov_reg_T0[3][8] = { | |
| 160 | +#ifdef TARGET_X86_64 | |
| 161 | + | |
| 162 | +#define NB_OP_SIZES 4 | |
| 163 | + | |
| 164 | +#define DEF_REGS(prefix, suffix) \ | |
| 165 | + prefix ## EAX ## suffix,\ | |
| 166 | + prefix ## ECX ## suffix,\ | |
| 167 | + prefix ## EDX ## suffix,\ | |
| 168 | + prefix ## EBX ## suffix,\ | |
| 169 | + prefix ## ESP ## suffix,\ | |
| 170 | + prefix ## EBP ## suffix,\ | |
| 171 | + prefix ## ESI ## suffix,\ | |
| 172 | + prefix ## EDI ## suffix,\ | |
| 173 | + prefix ## R8 ## suffix,\ | |
| 174 | + prefix ## R9 ## suffix,\ | |
| 175 | + prefix ## R10 ## suffix,\ | |
| 176 | + prefix ## R11 ## suffix,\ | |
| 177 | + prefix ## R12 ## suffix,\ | |
| 178 | + prefix ## R13 ## suffix,\ | |
| 179 | + prefix ## R14 ## suffix,\ | |
| 180 | + prefix ## R15 ## suffix, | |
| 181 | + | |
| 182 | +#define DEF_BREGS(prefixb, prefixh, suffix) \ | |
| 183 | + \ | |
| 184 | +static void prefixb ## ESP ## suffix ## _wrapper(void) \ | |
| 185 | +{ \ | |
| 186 | + if (x86_64_hregs) \ | |
| 187 | + prefixb ## ESP ## suffix (); \ | |
| 188 | + else \ | |
| 189 | + prefixh ## EAX ## suffix (); \ | |
| 190 | +} \ | |
| 191 | + \ | |
| 192 | +static void prefixb ## EBP ## suffix ## _wrapper(void) \ | |
| 193 | +{ \ | |
| 194 | + if (x86_64_hregs) \ | |
| 195 | + prefixb ## EBP ## suffix (); \ | |
| 196 | + else \ | |
| 197 | + prefixh ## ECX ## suffix (); \ | |
| 198 | +} \ | |
| 199 | + \ | |
| 200 | +static void prefixb ## ESI ## suffix ## _wrapper(void) \ | |
| 201 | +{ \ | |
| 202 | + if (x86_64_hregs) \ | |
| 203 | + prefixb ## ESI ## suffix (); \ | |
| 204 | + else \ | |
| 205 | + prefixh ## EDX ## suffix (); \ | |
| 206 | +} \ | |
| 207 | + \ | |
| 208 | +static void prefixb ## EDI ## suffix ## _wrapper(void) \ | |
| 209 | +{ \ | |
| 210 | + if (x86_64_hregs) \ | |
| 211 | + prefixb ## EDI ## suffix (); \ | |
| 212 | + else \ | |
| 213 | + prefixh ## EBX ## suffix (); \ | |
| 214 | +} | |
| 215 | + | |
| 216 | +DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0) | |
| 217 | +DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1) | |
| 218 | +DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, ) | |
| 219 | +DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, ) | |
| 220 | + | |
| 221 | +#else /* !TARGET_X86_64 */ | |
| 222 | + | |
| 223 | +#define NB_OP_SIZES 3 | |
| 224 | + | |
| 225 | +#define DEF_REGS(prefix, suffix) \ | |
| 226 | + prefix ## EAX ## suffix,\ | |
| 227 | + prefix ## ECX ## suffix,\ | |
| 228 | + prefix ## EDX ## suffix,\ | |
| 229 | + prefix ## EBX ## suffix,\ | |
| 230 | + prefix ## ESP ## suffix,\ | |
| 231 | + prefix ## EBP ## suffix,\ | |
| 232 | + prefix ## ESI ## suffix,\ | |
| 233 | + prefix ## EDI ## suffix, | |
| 234 | + | |
| 235 | +#endif /* !TARGET_X86_64 */ | |
| 236 | + | |
| 237 | +static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = { | |
| 132 | 238 | [OT_BYTE] = { |
| 133 | 239 | gen_op_movb_EAX_T0, |
| 134 | 240 | gen_op_movb_ECX_T0, |
| 135 | 241 | gen_op_movb_EDX_T0, |
| 136 | 242 | gen_op_movb_EBX_T0, |
| 243 | +#ifdef TARGET_X86_64 | |
| 244 | + gen_op_movb_ESP_T0_wrapper, | |
| 245 | + gen_op_movb_EBP_T0_wrapper, | |
| 246 | + gen_op_movb_ESI_T0_wrapper, | |
| 247 | + gen_op_movb_EDI_T0_wrapper, | |
| 248 | + gen_op_movb_R8_T0, | |
| 249 | + gen_op_movb_R9_T0, | |
| 250 | + gen_op_movb_R10_T0, | |
| 251 | + gen_op_movb_R11_T0, | |
| 252 | + gen_op_movb_R12_T0, | |
| 253 | + gen_op_movb_R13_T0, | |
| 254 | + gen_op_movb_R14_T0, | |
| 255 | + gen_op_movb_R15_T0, | |
| 256 | +#else | |
| 137 | 257 | gen_op_movh_EAX_T0, |
| 138 | 258 | gen_op_movh_ECX_T0, |
| 139 | 259 | gen_op_movh_EDX_T0, |
| 140 | 260 | gen_op_movh_EBX_T0, |
| 261 | +#endif | |
| 141 | 262 | }, |
| 142 | 263 | [OT_WORD] = { |
| 143 | - gen_op_movw_EAX_T0, | |
| 144 | - gen_op_movw_ECX_T0, | |
| 145 | - gen_op_movw_EDX_T0, | |
| 146 | - gen_op_movw_EBX_T0, | |
| 147 | - gen_op_movw_ESP_T0, | |
| 148 | - gen_op_movw_EBP_T0, | |
| 149 | - gen_op_movw_ESI_T0, | |
| 150 | - gen_op_movw_EDI_T0, | |
| 264 | + DEF_REGS(gen_op_movw_, _T0) | |
| 151 | 265 | }, |
| 152 | 266 | [OT_LONG] = { |
| 153 | - gen_op_movl_EAX_T0, | |
| 154 | - gen_op_movl_ECX_T0, | |
| 155 | - gen_op_movl_EDX_T0, | |
| 156 | - gen_op_movl_EBX_T0, | |
| 157 | - gen_op_movl_ESP_T0, | |
| 158 | - gen_op_movl_EBP_T0, | |
| 159 | - gen_op_movl_ESI_T0, | |
| 160 | - gen_op_movl_EDI_T0, | |
| 267 | + DEF_REGS(gen_op_movl_, _T0) | |
| 161 | 268 | }, |
| 269 | +#ifdef TARGET_X86_64 | |
| 270 | + [OT_QUAD] = { | |
| 271 | + DEF_REGS(gen_op_movq_, _T0) | |
| 272 | + }, | |
| 273 | +#endif | |
| 162 | 274 | }; |
| 163 | 275 | |
| 164 | -static GenOpFunc *gen_op_mov_reg_T1[3][8] = { | |
| 276 | +static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = { | |
| 165 | 277 | [OT_BYTE] = { |
| 166 | 278 | gen_op_movb_EAX_T1, |
| 167 | 279 | gen_op_movb_ECX_T1, |
| 168 | 280 | gen_op_movb_EDX_T1, |
| 169 | 281 | gen_op_movb_EBX_T1, |
| 282 | +#ifdef TARGET_X86_64 | |
| 283 | + gen_op_movb_ESP_T1_wrapper, | |
| 284 | + gen_op_movb_EBP_T1_wrapper, | |
| 285 | + gen_op_movb_ESI_T1_wrapper, | |
| 286 | + gen_op_movb_EDI_T1_wrapper, | |
| 287 | + gen_op_movb_R8_T1, | |
| 288 | + gen_op_movb_R9_T1, | |
| 289 | + gen_op_movb_R10_T1, | |
| 290 | + gen_op_movb_R11_T1, | |
| 291 | + gen_op_movb_R12_T1, | |
| 292 | + gen_op_movb_R13_T1, | |
| 293 | + gen_op_movb_R14_T1, | |
| 294 | + gen_op_movb_R15_T1, | |
| 295 | +#else | |
| 170 | 296 | gen_op_movh_EAX_T1, |
| 171 | 297 | gen_op_movh_ECX_T1, |
| 172 | 298 | gen_op_movh_EDX_T1, |
| 173 | 299 | gen_op_movh_EBX_T1, |
| 300 | +#endif | |
| 174 | 301 | }, |
| 175 | 302 | [OT_WORD] = { |
| 176 | - gen_op_movw_EAX_T1, | |
| 177 | - gen_op_movw_ECX_T1, | |
| 178 | - gen_op_movw_EDX_T1, | |
| 179 | - gen_op_movw_EBX_T1, | |
| 180 | - gen_op_movw_ESP_T1, | |
| 181 | - gen_op_movw_EBP_T1, | |
| 182 | - gen_op_movw_ESI_T1, | |
| 183 | - gen_op_movw_EDI_T1, | |
| 303 | + DEF_REGS(gen_op_movw_, _T1) | |
| 184 | 304 | }, |
| 185 | 305 | [OT_LONG] = { |
| 186 | - gen_op_movl_EAX_T1, | |
| 187 | - gen_op_movl_ECX_T1, | |
| 188 | - gen_op_movl_EDX_T1, | |
| 189 | - gen_op_movl_EBX_T1, | |
| 190 | - gen_op_movl_ESP_T1, | |
| 191 | - gen_op_movl_EBP_T1, | |
| 192 | - gen_op_movl_ESI_T1, | |
| 193 | - gen_op_movl_EDI_T1, | |
| 306 | + DEF_REGS(gen_op_movl_, _T1) | |
| 307 | + }, | |
| 308 | +#ifdef TARGET_X86_64 | |
| 309 | + [OT_QUAD] = { | |
| 310 | + DEF_REGS(gen_op_movq_, _T1) | |
| 194 | 311 | }, |
| 312 | +#endif | |
| 195 | 313 | }; |
| 196 | 314 | |
| 197 | -static GenOpFunc *gen_op_mov_reg_A0[2][8] = { | |
| 315 | +static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = { | |
| 198 | 316 | [0] = { |
| 199 | - gen_op_movw_EAX_A0, | |
| 200 | - gen_op_movw_ECX_A0, | |
| 201 | - gen_op_movw_EDX_A0, | |
| 202 | - gen_op_movw_EBX_A0, | |
| 203 | - gen_op_movw_ESP_A0, | |
| 204 | - gen_op_movw_EBP_A0, | |
| 205 | - gen_op_movw_ESI_A0, | |
| 206 | - gen_op_movw_EDI_A0, | |
| 317 | + DEF_REGS(gen_op_movw_, _A0) | |
| 207 | 318 | }, |
| 208 | 319 | [1] = { |
| 209 | - gen_op_movl_EAX_A0, | |
| 210 | - gen_op_movl_ECX_A0, | |
| 211 | - gen_op_movl_EDX_A0, | |
| 212 | - gen_op_movl_EBX_A0, | |
| 213 | - gen_op_movl_ESP_A0, | |
| 214 | - gen_op_movl_EBP_A0, | |
| 215 | - gen_op_movl_ESI_A0, | |
| 216 | - gen_op_movl_EDI_A0, | |
| 320 | + DEF_REGS(gen_op_movl_, _A0) | |
| 321 | + }, | |
| 322 | +#ifdef TARGET_X86_64 | |
| 323 | + [2] = { | |
| 324 | + DEF_REGS(gen_op_movq_, _A0) | |
| 217 | 325 | }, |
| 326 | +#endif | |
| 218 | 327 | }; |
| 219 | 328 | |
| 220 | -static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = | |
| 329 | +static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] = | |
| 221 | 330 | { |
| 222 | 331 | [OT_BYTE] = { |
| 223 | 332 | { |
| ... | ... | @@ -225,144 +334,133 @@ static GenOpFunc *gen_op_mov_TN_reg[3][2][8] = |
| 225 | 334 | gen_op_movl_T0_ECX, |
| 226 | 335 | gen_op_movl_T0_EDX, |
| 227 | 336 | gen_op_movl_T0_EBX, |
| 337 | +#ifdef TARGET_X86_64 | |
| 338 | + gen_op_movl_T0_ESP_wrapper, | |
| 339 | + gen_op_movl_T0_EBP_wrapper, | |
| 340 | + gen_op_movl_T0_ESI_wrapper, | |
| 341 | + gen_op_movl_T0_EDI_wrapper, | |
| 342 | + gen_op_movl_T0_R8, | |
| 343 | + gen_op_movl_T0_R9, | |
| 344 | + gen_op_movl_T0_R10, | |
| 345 | + gen_op_movl_T0_R11, | |
| 346 | + gen_op_movl_T0_R12, | |
| 347 | + gen_op_movl_T0_R13, | |
| 348 | + gen_op_movl_T0_R14, | |
| 349 | + gen_op_movl_T0_R15, | |
| 350 | +#else | |
| 228 | 351 | gen_op_movh_T0_EAX, |
| 229 | 352 | gen_op_movh_T0_ECX, |
| 230 | 353 | gen_op_movh_T0_EDX, |
| 231 | 354 | gen_op_movh_T0_EBX, |
| 355 | +#endif | |
| 232 | 356 | }, |
| 233 | 357 | { |
| 234 | 358 | gen_op_movl_T1_EAX, |
| 235 | 359 | gen_op_movl_T1_ECX, |
| 236 | 360 | gen_op_movl_T1_EDX, |
| 237 | 361 | gen_op_movl_T1_EBX, |
| 362 | +#ifdef TARGET_X86_64 | |
| 363 | + gen_op_movl_T1_ESP_wrapper, | |
| 364 | + gen_op_movl_T1_EBP_wrapper, | |
| 365 | + gen_op_movl_T1_ESI_wrapper, | |
| 366 | + gen_op_movl_T1_EDI_wrapper, | |
| 367 | + gen_op_movl_T1_R8, | |
| 368 | + gen_op_movl_T1_R9, | |
| 369 | + gen_op_movl_T1_R10, | |
| 370 | + gen_op_movl_T1_R11, | |
| 371 | + gen_op_movl_T1_R12, | |
| 372 | + gen_op_movl_T1_R13, | |
| 373 | + gen_op_movl_T1_R14, | |
| 374 | + gen_op_movl_T1_R15, | |
| 375 | +#else | |
| 238 | 376 | gen_op_movh_T1_EAX, |
| 239 | 377 | gen_op_movh_T1_ECX, |
| 240 | 378 | gen_op_movh_T1_EDX, |
| 241 | 379 | gen_op_movh_T1_EBX, |
| 380 | +#endif | |
| 242 | 381 | }, |
| 243 | 382 | }, |
| 244 | 383 | [OT_WORD] = { |
| 245 | 384 | { |
| 246 | - gen_op_movl_T0_EAX, | |
| 247 | - gen_op_movl_T0_ECX, | |
| 248 | - gen_op_movl_T0_EDX, | |
| 249 | - gen_op_movl_T0_EBX, | |
| 250 | - gen_op_movl_T0_ESP, | |
| 251 | - gen_op_movl_T0_EBP, | |
| 252 | - gen_op_movl_T0_ESI, | |
| 253 | - gen_op_movl_T0_EDI, | |
| 385 | + DEF_REGS(gen_op_movl_T0_, ) | |
| 254 | 386 | }, |
| 255 | 387 | { |
| 256 | - gen_op_movl_T1_EAX, | |
| 257 | - gen_op_movl_T1_ECX, | |
| 258 | - gen_op_movl_T1_EDX, | |
| 259 | - gen_op_movl_T1_EBX, | |
| 260 | - gen_op_movl_T1_ESP, | |
| 261 | - gen_op_movl_T1_EBP, | |
| 262 | - gen_op_movl_T1_ESI, | |
| 263 | - gen_op_movl_T1_EDI, | |
| 388 | + DEF_REGS(gen_op_movl_T1_, ) | |
| 264 | 389 | }, |
| 265 | 390 | }, |
| 266 | 391 | [OT_LONG] = { |
| 267 | 392 | { |
| 268 | - gen_op_movl_T0_EAX, | |
| 269 | - gen_op_movl_T0_ECX, | |
| 270 | - gen_op_movl_T0_EDX, | |
| 271 | - gen_op_movl_T0_EBX, | |
| 272 | - gen_op_movl_T0_ESP, | |
| 273 | - gen_op_movl_T0_EBP, | |
| 274 | - gen_op_movl_T0_ESI, | |
| 275 | - gen_op_movl_T0_EDI, | |
| 393 | + DEF_REGS(gen_op_movl_T0_, ) | |
| 276 | 394 | }, |
| 277 | 395 | { |
| 278 | - gen_op_movl_T1_EAX, | |
| 279 | - gen_op_movl_T1_ECX, | |
| 280 | - gen_op_movl_T1_EDX, | |
| 281 | - gen_op_movl_T1_EBX, | |
| 282 | - gen_op_movl_T1_ESP, | |
| 283 | - gen_op_movl_T1_EBP, | |
| 284 | - gen_op_movl_T1_ESI, | |
| 285 | - gen_op_movl_T1_EDI, | |
| 396 | + DEF_REGS(gen_op_movl_T1_, ) | |
| 286 | 397 | }, |
| 287 | 398 | }, |
| 399 | +#ifdef TARGET_X86_64 | |
| 400 | + [OT_QUAD] = { | |
| 401 | + { | |
| 402 | + DEF_REGS(gen_op_movl_T0_, ) | |
| 403 | + }, | |
| 404 | + { | |
| 405 | + DEF_REGS(gen_op_movl_T1_, ) | |
| 406 | + }, | |
| 407 | + }, | |
| 408 | +#endif | |
| 288 | 409 | }; |
| 289 | 410 | |
| 290 | -static GenOpFunc *gen_op_movl_A0_reg[8] = { | |
| 291 | - gen_op_movl_A0_EAX, | |
| 292 | - gen_op_movl_A0_ECX, | |
| 293 | - gen_op_movl_A0_EDX, | |
| 294 | - gen_op_movl_A0_EBX, | |
| 295 | - gen_op_movl_A0_ESP, | |
| 296 | - gen_op_movl_A0_EBP, | |
| 297 | - gen_op_movl_A0_ESI, | |
| 298 | - gen_op_movl_A0_EDI, | |
| 411 | +static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = { | |
| 412 | + DEF_REGS(gen_op_movl_A0_, ) | |
| 299 | 413 | }; |
| 300 | 414 | |
| 301 | -static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { | |
| 415 | +static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = { | |
| 302 | 416 | [0] = { |
| 303 | - gen_op_addl_A0_EAX, | |
| 304 | - gen_op_addl_A0_ECX, | |
| 305 | - gen_op_addl_A0_EDX, | |
| 306 | - gen_op_addl_A0_EBX, | |
| 307 | - gen_op_addl_A0_ESP, | |
| 308 | - gen_op_addl_A0_EBP, | |
| 309 | - gen_op_addl_A0_ESI, | |
| 310 | - gen_op_addl_A0_EDI, | |
| 417 | + DEF_REGS(gen_op_addl_A0_, ) | |
| 311 | 418 | }, |
| 312 | 419 | [1] = { |
| 313 | - gen_op_addl_A0_EAX_s1, | |
| 314 | - gen_op_addl_A0_ECX_s1, | |
| 315 | - gen_op_addl_A0_EDX_s1, | |
| 316 | - gen_op_addl_A0_EBX_s1, | |
| 317 | - gen_op_addl_A0_ESP_s1, | |
| 318 | - gen_op_addl_A0_EBP_s1, | |
| 319 | - gen_op_addl_A0_ESI_s1, | |
| 320 | - gen_op_addl_A0_EDI_s1, | |
| 420 | + DEF_REGS(gen_op_addl_A0_, _s1) | |
| 321 | 421 | }, |
| 322 | 422 | [2] = { |
| 323 | - gen_op_addl_A0_EAX_s2, | |
| 324 | - gen_op_addl_A0_ECX_s2, | |
| 325 | - gen_op_addl_A0_EDX_s2, | |
| 326 | - gen_op_addl_A0_EBX_s2, | |
| 327 | - gen_op_addl_A0_ESP_s2, | |
| 328 | - gen_op_addl_A0_EBP_s2, | |
| 329 | - gen_op_addl_A0_ESI_s2, | |
| 330 | - gen_op_addl_A0_EDI_s2, | |
| 423 | + DEF_REGS(gen_op_addl_A0_, _s2) | |
| 331 | 424 | }, |
| 332 | 425 | [3] = { |
| 333 | - gen_op_addl_A0_EAX_s3, | |
| 334 | - gen_op_addl_A0_ECX_s3, | |
| 335 | - gen_op_addl_A0_EDX_s3, | |
| 336 | - gen_op_addl_A0_EBX_s3, | |
| 337 | - gen_op_addl_A0_ESP_s3, | |
| 338 | - gen_op_addl_A0_EBP_s3, | |
| 339 | - gen_op_addl_A0_ESI_s3, | |
| 340 | - gen_op_addl_A0_EDI_s3, | |
| 426 | + DEF_REGS(gen_op_addl_A0_, _s3) | |
| 341 | 427 | }, |
| 342 | 428 | }; |
| 343 | 429 | |
| 344 | -static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = { | |
| 430 | +#ifdef TARGET_X86_64 | |
| 431 | +static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = { | |
| 432 | + DEF_REGS(gen_op_movq_A0_, ) | |
| 433 | +}; | |
| 434 | + | |
| 435 | +static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = { | |
| 345 | 436 | [0] = { |
| 346 | - gen_op_cmovw_EAX_T1_T0, | |
| 347 | - gen_op_cmovw_ECX_T1_T0, | |
| 348 | - gen_op_cmovw_EDX_T1_T0, | |
| 349 | - gen_op_cmovw_EBX_T1_T0, | |
| 350 | - gen_op_cmovw_ESP_T1_T0, | |
| 351 | - gen_op_cmovw_EBP_T1_T0, | |
| 352 | - gen_op_cmovw_ESI_T1_T0, | |
| 353 | - gen_op_cmovw_EDI_T1_T0, | |
| 437 | + DEF_REGS(gen_op_addq_A0_, ) | |
| 354 | 438 | }, |
| 355 | 439 | [1] = { |
| 356 | - gen_op_cmovl_EAX_T1_T0, | |
| 357 | - gen_op_cmovl_ECX_T1_T0, | |
| 358 | - gen_op_cmovl_EDX_T1_T0, | |
| 359 | - gen_op_cmovl_EBX_T1_T0, | |
| 360 | - gen_op_cmovl_ESP_T1_T0, | |
| 361 | - gen_op_cmovl_EBP_T1_T0, | |
| 362 | - gen_op_cmovl_ESI_T1_T0, | |
| 363 | - gen_op_cmovl_EDI_T1_T0, | |
| 440 | + DEF_REGS(gen_op_addq_A0_, _s1) | |
| 441 | + }, | |
| 442 | + [2] = { | |
| 443 | + DEF_REGS(gen_op_addq_A0_, _s2) | |
| 444 | + }, | |
| 445 | + [3] = { | |
| 446 | + DEF_REGS(gen_op_addq_A0_, _s3) | |
| 364 | 447 | }, |
| 365 | 448 | }; |
| 449 | +#endif | |
| 450 | + | |
| 451 | +static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { | |
| 452 | + [0] = { | |
| 453 | + DEF_REGS(gen_op_cmovw_, _T1_T0) | |
| 454 | + }, | |
| 455 | + [1] = { | |
| 456 | + DEF_REGS(gen_op_cmovl_, _T1_T0) | |
| 457 | + }, | |
| 458 | +#ifdef TARGET_X86_64 | |
| 459 | + [2] = { | |
| 460 | + DEF_REGS(gen_op_cmovq_, _T1_T0) | |
| 461 | + }, | |
| 462 | +#endif | |
| 463 | +}; | |
| 366 | 464 | |
| 367 | 465 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
| 368 | 466 | NULL, |
| ... | ... | @@ -387,13 +485,17 @@ static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
| 387 | 485 | {\ |
| 388 | 486 | gen_op_adcl ## SUFFIX ## _T0_T1_cc,\ |
| 389 | 487 | gen_op_sbbl ## SUFFIX ## _T0_T1_cc,\ |
| 488 | + },\ | |
| 489 | + {\ | |
| 490 | + X86_64_ONLY(gen_op_adcq ## SUFFIX ## _T0_T1_cc),\ | |
| 491 | + X86_64_ONLY(gen_op_sbbq ## SUFFIX ## _T0_T1_cc),\ | |
| 390 | 492 | }, |
| 391 | 493 | |
| 392 | -static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = { | |
| 494 | +static GenOpFunc *gen_op_arithc_T0_T1_cc[4][2] = { | |
| 393 | 495 | DEF_ARITHC( ) |
| 394 | 496 | }; |
| 395 | 497 | |
| 396 | -static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[9][2] = { | |
| 498 | +static GenOpFunc *gen_op_arithc_mem_T0_T1_cc[3 * 4][2] = { | |
| 397 | 499 | DEF_ARITHC(_raw) |
| 398 | 500 | #ifndef CONFIG_USER_ONLY |
| 399 | 501 | DEF_ARITHC(_kernel) |
| ... | ... | @@ -415,14 +517,14 @@ static const int cc_op_arithb[8] = { |
| 415 | 517 | #define DEF_CMPXCHG(SUFFIX)\ |
| 416 | 518 | gen_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc,\ |
| 417 | 519 | gen_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc,\ |
| 418 | - gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc, | |
| 419 | - | |
| 520 | + gen_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc,\ | |
| 521 | + X86_64_ONLY(gen_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc), | |
| 420 | 522 | |
| 421 | -static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = { | |
| 523 | +static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[4] = { | |
| 422 | 524 | DEF_CMPXCHG( ) |
| 423 | 525 | }; |
| 424 | 526 | |
| 425 | -static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = { | |
| 527 | +static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[3 * 4] = { | |
| 426 | 528 | DEF_CMPXCHG(_raw) |
| 427 | 529 | #ifndef CONFIG_USER_ONLY |
| 428 | 530 | DEF_CMPXCHG(_kernel) |
| ... | ... | @@ -460,13 +562,23 @@ static GenOpFunc *gen_op_cmpxchg_mem_T0_T1_EAX_cc[9] = { |
| 460 | 562 | gen_op_shrl ## SUFFIX ## _T0_T1_cc,\ |
| 461 | 563 | gen_op_shll ## SUFFIX ## _T0_T1_cc,\ |
| 462 | 564 | gen_op_sarl ## SUFFIX ## _T0_T1_cc,\ |
| 565 | + },\ | |
| 566 | + {\ | |
| 567 | + X86_64_ONLY(gen_op_rolq ## SUFFIX ## _T0_T1_cc),\ | |
| 568 | + X86_64_ONLY(gen_op_rorq ## SUFFIX ## _T0_T1_cc),\ | |
| 569 | + X86_64_ONLY(gen_op_rclq ## SUFFIX ## _T0_T1_cc),\ | |
| 570 | + X86_64_ONLY(gen_op_rcrq ## SUFFIX ## _T0_T1_cc),\ | |
| 571 | + X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\ | |
| 572 | + X86_64_ONLY(gen_op_shrq ## SUFFIX ## _T0_T1_cc),\ | |
| 573 | + X86_64_ONLY(gen_op_shlq ## SUFFIX ## _T0_T1_cc),\ | |
| 574 | + X86_64_ONLY(gen_op_sarq ## SUFFIX ## _T0_T1_cc),\ | |
| 463 | 575 | }, |
| 464 | 576 | |
| 465 | -static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { | |
| 577 | +static GenOpFunc *gen_op_shift_T0_T1_cc[4][8] = { | |
| 466 | 578 | DEF_SHIFT( ) |
| 467 | 579 | }; |
| 468 | 580 | |
| 469 | -static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = { | |
| 581 | +static GenOpFunc *gen_op_shift_mem_T0_T1_cc[3 * 4][8] = { | |
| 470 | 582 | DEF_SHIFT(_raw) |
| 471 | 583 | #ifndef CONFIG_USER_ONLY |
| 472 | 584 | DEF_SHIFT(_kernel) |
| ... | ... | @@ -486,18 +598,19 @@ static GenOpFunc *gen_op_shift_mem_T0_T1_cc[9][8] = { |
| 486 | 598 | {\ |
| 487 | 599 | gen_op_shldl ## SUFFIX ## _T0_T1_ ## op ## _cc,\ |
| 488 | 600 | gen_op_shrdl ## SUFFIX ## _T0_T1_ ## op ## _cc,\ |
| 601 | + },\ | |
| 602 | + {\ | |
| 489 | 603 | }, |
| 490 | 604 | |
| 491 | - | |
| 492 | -static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[3][2] = { | |
| 605 | +static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[4][2] = { | |
| 493 | 606 | DEF_SHIFTD(, im) |
| 494 | 607 | }; |
| 495 | 608 | |
| 496 | -static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[3][2] = { | |
| 609 | +static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[4][2] = { | |
| 497 | 610 | DEF_SHIFTD(, ECX) |
| 498 | 611 | }; |
| 499 | 612 | |
| 500 | -static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = { | |
| 613 | +static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[3 * 4][2] = { | |
| 501 | 614 | DEF_SHIFTD(_raw, im) |
| 502 | 615 | #ifndef CONFIG_USER_ONLY |
| 503 | 616 | DEF_SHIFTD(_kernel, im) |
| ... | ... | @@ -505,7 +618,7 @@ static GenOpFunc1 *gen_op_shiftd_mem_T0_T1_im_cc[9][2] = { |
| 505 | 618 | #endif |
| 506 | 619 | }; |
| 507 | 620 | |
| 508 | -static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = { | |
| 621 | +static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[3 * 4][2] = { | |
| 509 | 622 | DEF_SHIFTD(_raw, ECX) |
| 510 | 623 | #ifndef CONFIG_USER_ONLY |
| 511 | 624 | DEF_SHIFTD(_kernel, ECX) |
| ... | ... | @@ -513,7 +626,7 @@ static GenOpFunc *gen_op_shiftd_mem_T0_T1_ECX_cc[9][2] = { |
| 513 | 626 | #endif |
| 514 | 627 | }; |
| 515 | 628 | |
| 516 | -static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { | |
| 629 | +static GenOpFunc *gen_op_btx_T0_T1_cc[3][4] = { | |
| 517 | 630 | [0] = { |
| 518 | 631 | gen_op_btw_T0_T1_cc, |
| 519 | 632 | gen_op_btsw_T0_T1_cc, |
| ... | ... | @@ -526,9 +639,23 @@ static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { |
| 526 | 639 | gen_op_btrl_T0_T1_cc, |
| 527 | 640 | gen_op_btcl_T0_T1_cc, |
| 528 | 641 | }, |
| 642 | +#ifdef TARGET_X86_64 | |
| 643 | + [2] = { | |
| 644 | + gen_op_btq_T0_T1_cc, | |
| 645 | + gen_op_btsq_T0_T1_cc, | |
| 646 | + gen_op_btrq_T0_T1_cc, | |
| 647 | + gen_op_btcq_T0_T1_cc, | |
| 648 | + }, | |
| 649 | +#endif | |
| 650 | +}; | |
| 651 | + | |
| 652 | +static GenOpFunc *gen_op_add_bit_A0_T1[3] = { | |
| 653 | + gen_op_add_bitw_A0_T1, | |
| 654 | + gen_op_add_bitl_A0_T1, | |
| 655 | + X86_64_ONLY(gen_op_add_bitq_A0_T1), | |
| 529 | 656 | }; |
| 530 | 657 | |
| 531 | -static GenOpFunc *gen_op_bsx_T0_cc[2][2] = { | |
| 658 | +static GenOpFunc *gen_op_bsx_T0_cc[3][2] = { | |
| 532 | 659 | [0] = { |
| 533 | 660 | gen_op_bsfw_T0_cc, |
| 534 | 661 | gen_op_bsrw_T0_cc, |
| ... | ... | @@ -537,109 +664,158 @@ static GenOpFunc *gen_op_bsx_T0_cc[2][2] = { |
| 537 | 664 | gen_op_bsfl_T0_cc, |
| 538 | 665 | gen_op_bsrl_T0_cc, |
| 539 | 666 | }, |
| 667 | +#ifdef TARGET_X86_64 | |
| 668 | + [2] = { | |
| 669 | + gen_op_bsfq_T0_cc, | |
| 670 | + gen_op_bsrq_T0_cc, | |
| 671 | + }, | |
| 672 | +#endif | |
| 540 | 673 | }; |
| 541 | 674 | |
| 542 | -static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { | |
| 675 | +static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = { | |
| 543 | 676 | gen_op_ldsb_raw_T0_A0, |
| 544 | 677 | gen_op_ldsw_raw_T0_A0, |
| 678 | + X86_64_ONLY(gen_op_ldsl_raw_T0_A0), | |
| 545 | 679 | NULL, |
| 546 | 680 | #ifndef CONFIG_USER_ONLY |
| 547 | 681 | gen_op_ldsb_kernel_T0_A0, |
| 548 | 682 | gen_op_ldsw_kernel_T0_A0, |
| 683 | + X86_64_ONLY(gen_op_ldsl_kernel_T0_A0), | |
| 549 | 684 | NULL, |
| 550 | 685 | |
| 551 | 686 | gen_op_ldsb_user_T0_A0, |
| 552 | 687 | gen_op_ldsw_user_T0_A0, |
| 688 | + X86_64_ONLY(gen_op_ldsl_user_T0_A0), | |
| 553 | 689 | NULL, |
| 554 | 690 | #endif |
| 555 | 691 | }; |
| 556 | 692 | |
| 557 | -static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { | |
| 693 | +static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = { | |
| 558 | 694 | gen_op_ldub_raw_T0_A0, |
| 559 | 695 | gen_op_lduw_raw_T0_A0, |
| 560 | 696 | NULL, |
| 697 | + NULL, | |
| 561 | 698 | |
| 562 | 699 | #ifndef CONFIG_USER_ONLY |
| 563 | 700 | gen_op_ldub_kernel_T0_A0, |
| 564 | 701 | gen_op_lduw_kernel_T0_A0, |
| 565 | 702 | NULL, |
| 703 | + NULL, | |
| 566 | 704 | |
| 567 | 705 | gen_op_ldub_user_T0_A0, |
| 568 | 706 | gen_op_lduw_user_T0_A0, |
| 569 | 707 | NULL, |
| 708 | + NULL, | |
| 570 | 709 | #endif |
| 571 | 710 | }; |
| 572 | 711 | |
| 573 | 712 | /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
| 574 | -static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { | |
| 713 | +static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = { | |
| 575 | 714 | gen_op_ldub_raw_T0_A0, |
| 576 | 715 | gen_op_lduw_raw_T0_A0, |
| 577 | 716 | gen_op_ldl_raw_T0_A0, |
| 717 | + X86_64_ONLY(gen_op_ldq_raw_T0_A0), | |
| 578 | 718 | |
| 579 | 719 | #ifndef CONFIG_USER_ONLY |
| 580 | 720 | gen_op_ldub_kernel_T0_A0, |
| 581 | 721 | gen_op_lduw_kernel_T0_A0, |
| 582 | 722 | gen_op_ldl_kernel_T0_A0, |
| 723 | + X86_64_ONLY(gen_op_ldq_kernel_T0_A0), | |
| 583 | 724 | |
| 584 | 725 | gen_op_ldub_user_T0_A0, |
| 585 | 726 | gen_op_lduw_user_T0_A0, |
| 586 | 727 | gen_op_ldl_user_T0_A0, |
| 728 | + X86_64_ONLY(gen_op_ldq_user_T0_A0), | |
| 587 | 729 | #endif |
| 588 | 730 | }; |
| 589 | 731 | |
| 590 | -static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { | |
| 732 | +static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = { | |
| 591 | 733 | gen_op_ldub_raw_T1_A0, |
| 592 | 734 | gen_op_lduw_raw_T1_A0, |
| 593 | 735 | gen_op_ldl_raw_T1_A0, |
| 736 | + X86_64_ONLY(gen_op_ldq_raw_T1_A0), | |
| 594 | 737 | |
| 595 | 738 | #ifndef CONFIG_USER_ONLY |
| 596 | 739 | gen_op_ldub_kernel_T1_A0, |
| 597 | 740 | gen_op_lduw_kernel_T1_A0, |
| 598 | 741 | gen_op_ldl_kernel_T1_A0, |
| 742 | + X86_64_ONLY(gen_op_ldq_kernel_T1_A0), | |
| 599 | 743 | |
| 600 | 744 | gen_op_ldub_user_T1_A0, |
| 601 | 745 | gen_op_lduw_user_T1_A0, |
| 602 | 746 | gen_op_ldl_user_T1_A0, |
| 747 | + X86_64_ONLY(gen_op_ldq_user_T1_A0), | |
| 603 | 748 | #endif |
| 604 | 749 | }; |
| 605 | 750 | |
| 606 | -static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { | |
| 751 | +static GenOpFunc *gen_op_st_T0_A0[3 * 4] = { | |
| 607 | 752 | gen_op_stb_raw_T0_A0, |
| 608 | 753 | gen_op_stw_raw_T0_A0, |
| 609 | 754 | gen_op_stl_raw_T0_A0, |
| 755 | + X86_64_ONLY(gen_op_stq_raw_T0_A0), | |
| 610 | 756 | |
| 611 | 757 | #ifndef CONFIG_USER_ONLY |
| 612 | 758 | gen_op_stb_kernel_T0_A0, |
| 613 | 759 | gen_op_stw_kernel_T0_A0, |
| 614 | 760 | gen_op_stl_kernel_T0_A0, |
| 761 | + X86_64_ONLY(gen_op_stq_kernel_T0_A0), | |
| 615 | 762 | |
| 616 | 763 | gen_op_stb_user_T0_A0, |
| 617 | 764 | gen_op_stw_user_T0_A0, |
| 618 | 765 | gen_op_stl_user_T0_A0, |
| 766 | + X86_64_ONLY(gen_op_stq_user_T0_A0), | |
| 619 | 767 | #endif |
| 620 | 768 | }; |
| 621 | 769 | |
| 622 | -static GenOpFunc *gen_op_st_T1_A0[3 * 3] = { | |
| 770 | +static GenOpFunc *gen_op_st_T1_A0[3 * 4] = { | |
| 623 | 771 | NULL, |
| 624 | 772 | gen_op_stw_raw_T1_A0, |
| 625 | 773 | gen_op_stl_raw_T1_A0, |
| 774 | + X86_64_ONLY(gen_op_stq_raw_T1_A0), | |
| 626 | 775 | |
| 627 | 776 | #ifndef CONFIG_USER_ONLY |
| 628 | 777 | NULL, |
| 629 | 778 | gen_op_stw_kernel_T1_A0, |
| 630 | 779 | gen_op_stl_kernel_T1_A0, |
| 780 | + X86_64_ONLY(gen_op_stq_kernel_T1_A0), | |
| 631 | 781 | |
| 632 | 782 | NULL, |
| 633 | 783 | gen_op_stw_user_T1_A0, |
| 634 | 784 | gen_op_stl_user_T1_A0, |
| 785 | + X86_64_ONLY(gen_op_stq_user_T1_A0), | |
| 635 | 786 | #endif |
| 636 | 787 | }; |
| 637 | 788 | |
| 789 | +static inline void gen_jmp_im(target_ulong pc) | |
| 790 | +{ | |
| 791 | +#ifdef TARGET_X86_64 | |
| 792 | + if (pc == (uint32_t)pc) { | |
| 793 | + gen_op_movl_eip_im(pc); | |
| 794 | + } else if (pc == (int32_t)pc) { | |
| 795 | + gen_op_movq_eip_im(pc); | |
| 796 | + } else { | |
| 797 | + gen_op_movq_eip_im64(pc >> 32, pc); | |
| 798 | + } | |
| 799 | +#else | |
| 800 | + gen_op_movl_eip_im(pc); | |
| 801 | +#endif | |
| 802 | +} | |
| 803 | + | |
| 638 | 804 | static inline void gen_string_movl_A0_ESI(DisasContext *s) |
| 639 | 805 | { |
| 640 | 806 | int override; |
| 641 | 807 | |
| 642 | 808 | override = s->override; |
| 809 | +#ifdef TARGET_X86_64 | |
| 810 | + if (s->aflag == 2) { | |
| 811 | + if (override >= 0) { | |
| 812 | + gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 813 | + gen_op_addq_A0_reg_sN[0][R_ESI](); | |
| 814 | + } else { | |
| 815 | + gen_op_movq_A0_reg[R_ESI](); | |
| 816 | + } | |
| 817 | + } else | |
| 818 | +#endif | |
| 643 | 819 | if (s->aflag) { |
| 644 | 820 | /* 32 bit address */ |
| 645 | 821 | if (s->addseg && override < 0) |
| ... | ... | @@ -662,6 +838,11 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s) |
| 662 | 838 | |
| 663 | 839 | static inline void gen_string_movl_A0_EDI(DisasContext *s) |
| 664 | 840 | { |
| 841 | +#ifdef TARGET_X86_64 | |
| 842 | + if (s->aflag == 2) { | |
| 843 | + gen_op_movq_A0_reg[R_EDI](); | |
| 844 | + } else | |
| 845 | +#endif | |
| 665 | 846 | if (s->aflag) { |
| 666 | 847 | if (s->addseg) { |
| 667 | 848 | gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); |
| ... | ... | @@ -676,58 +857,43 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) |
| 676 | 857 | } |
| 677 | 858 | } |
| 678 | 859 | |
| 679 | -static GenOpFunc *gen_op_movl_T0_Dshift[3] = { | |
| 860 | +static GenOpFunc *gen_op_movl_T0_Dshift[4] = { | |
| 680 | 861 | gen_op_movl_T0_Dshiftb, |
| 681 | 862 | gen_op_movl_T0_Dshiftw, |
| 682 | 863 | gen_op_movl_T0_Dshiftl, |
| 864 | + X86_64_ONLY(gen_op_movl_T0_Dshiftq), | |
| 683 | 865 | }; |
| 684 | 866 | |
| 685 | -static GenOpFunc2 *gen_op_jz_ecx[2] = { | |
| 686 | - gen_op_jz_ecxw, | |
| 687 | - gen_op_jz_ecxl, | |
| 867 | +static GenOpFunc1 *gen_op_jnz_ecx[3] = { | |
| 868 | + gen_op_jnz_ecxw, | |
| 869 | + gen_op_jnz_ecxl, | |
| 870 | + X86_64_ONLY(gen_op_jnz_ecxq), | |
| 688 | 871 | }; |
| 689 | 872 | |
| 690 | -static GenOpFunc1 *gen_op_jz_ecx_im[2] = { | |
| 691 | - gen_op_jz_ecxw_im, | |
| 692 | - gen_op_jz_ecxl_im, | |
| 873 | +static GenOpFunc1 *gen_op_jz_ecx[3] = { | |
| 874 | + gen_op_jz_ecxw, | |
| 875 | + gen_op_jz_ecxl, | |
| 876 | + X86_64_ONLY(gen_op_jz_ecxq), | |
| 693 | 877 | }; |
| 694 | 878 | |
| 695 | -static GenOpFunc *gen_op_dec_ECX[2] = { | |
| 879 | +static GenOpFunc *gen_op_dec_ECX[3] = { | |
| 696 | 880 | gen_op_decw_ECX, |
| 697 | 881 | gen_op_decl_ECX, |
| 882 | + X86_64_ONLY(gen_op_decq_ECX), | |
| 698 | 883 | }; |
| 699 | 884 | |
| 700 | -#ifdef USE_DIRECT_JUMP | |
| 701 | -typedef GenOpFunc GenOpFuncTB2; | |
| 702 | -#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot]() | |
| 703 | -#else | |
| 704 | -typedef GenOpFunc1 GenOpFuncTB2; | |
| 705 | -#define gen_op_string_jnz_sub(nz, ot, tb) gen_op_string_jnz_sub2[nz][ot](tb) | |
| 706 | -#endif | |
| 707 | - | |
| 708 | -static GenOpFuncTB2 *gen_op_string_jnz_sub2[2][3] = { | |
| 885 | +static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { | |
| 709 | 886 | { |
| 710 | - gen_op_string_jnz_subb, | |
| 711 | - gen_op_string_jnz_subw, | |
| 712 | - gen_op_string_jnz_subl, | |
| 887 | + gen_op_jnz_subb, | |
| 888 | + gen_op_jnz_subw, | |
| 889 | + gen_op_jnz_subl, | |
| 890 | + X86_64_ONLY(gen_op_jnz_subq), | |
| 713 | 891 | }, |
| 714 | 892 | { |
| 715 | - gen_op_string_jz_subb, | |
| 716 | - gen_op_string_jz_subw, | |
| 717 | - gen_op_string_jz_subl, | |
| 718 | - }, | |
| 719 | -}; | |
| 720 | - | |
| 721 | -static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = { | |
| 722 | - { | |
| 723 | - gen_op_string_jnz_subb_im, | |
| 724 | - gen_op_string_jnz_subw_im, | |
| 725 | - gen_op_string_jnz_subl_im, | |
| 726 | - }, | |
| 727 | - { | |
| 728 | - gen_op_string_jz_subb_im, | |
| 729 | - gen_op_string_jz_subw_im, | |
| 730 | - gen_op_string_jz_subl_im, | |
| 893 | + gen_op_jz_subb, | |
| 894 | + gen_op_jz_subw, | |
| 895 | + gen_op_jz_subl, | |
| 896 | + X86_64_ONLY(gen_op_jz_subq), | |
| 731 | 897 | }, |
| 732 | 898 | }; |
| 733 | 899 | |
| ... | ... | @@ -767,12 +933,12 @@ static GenOpFunc *gen_check_io_DX[3] = { |
| 767 | 933 | gen_op_check_iol_DX, |
| 768 | 934 | }; |
| 769 | 935 | |
| 770 | -static void gen_check_io(DisasContext *s, int ot, int use_dx, int cur_eip) | |
| 936 | +static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip) | |
| 771 | 937 | { |
| 772 | 938 | if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
| 773 | 939 | if (s->cc_op != CC_OP_DYNAMIC) |
| 774 | 940 | gen_op_set_cc_op(s->cc_op); |
| 775 | - gen_op_jmp_im(cur_eip); | |
| 941 | + gen_jmp_im(cur_eip); | |
| 776 | 942 | if (use_dx) |
| 777 | 943 | gen_check_io_DX[ot](); |
| 778 | 944 | else |
| ... | ... | @@ -787,6 +953,12 @@ static inline void gen_movs(DisasContext *s, int ot) |
| 787 | 953 | gen_string_movl_A0_EDI(s); |
| 788 | 954 | gen_op_st_T0_A0[ot + s->mem_index](); |
| 789 | 955 | gen_op_movl_T0_Dshift[ot](); |
| 956 | +#ifdef TARGET_X86_64 | |
| 957 | + if (s->aflag == 2) { | |
| 958 | + gen_op_addq_ESI_T0(); | |
| 959 | + gen_op_addq_EDI_T0(); | |
| 960 | + } else | |
| 961 | +#endif | |
| 790 | 962 | if (s->aflag) { |
| 791 | 963 | gen_op_addl_ESI_T0(); |
| 792 | 964 | gen_op_addl_EDI_T0(); |
| ... | ... | @@ -804,15 +976,19 @@ static inline void gen_update_cc_op(DisasContext *s) |
| 804 | 976 | } |
| 805 | 977 | } |
| 806 | 978 | |
| 807 | -static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip) | |
| 979 | +/* XXX: does not work with gdbstub "ice" single step - not a | |
| 980 | + serious problem */ | |
| 981 | +static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) | |
| 808 | 982 | { |
| 809 | - if (s->jmp_opt) { | |
| 810 | - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip); | |
| 811 | - } else { | |
| 812 | - /* XXX: does not work with gdbstub "ice" single step - not a | |
| 813 | - serious problem */ | |
| 814 | - gen_op_jz_ecx_im[s->aflag](next_eip); | |
| 815 | - } | |
| 983 | + int l1, l2; | |
| 984 | + | |
| 985 | + l1 = gen_new_label(); | |
| 986 | + l2 = gen_new_label(); | |
| 987 | + gen_op_jnz_ecx[s->aflag](l1); | |
| 988 | + gen_set_label(l2); | |
| 989 | + gen_jmp_tb(s, next_eip, 1); | |
| 990 | + gen_set_label(l1); | |
| 991 | + return l2; | |
| 816 | 992 | } |
| 817 | 993 | |
| 818 | 994 | static inline void gen_stos(DisasContext *s, int ot) |
| ... | ... | @@ -821,6 +997,11 @@ static inline void gen_stos(DisasContext *s, int ot) |
| 821 | 997 | gen_string_movl_A0_EDI(s); |
| 822 | 998 | gen_op_st_T0_A0[ot + s->mem_index](); |
| 823 | 999 | gen_op_movl_T0_Dshift[ot](); |
| 1000 | +#ifdef TARGET_X86_64 | |
| 1001 | + if (s->aflag == 2) { | |
| 1002 | + gen_op_addq_EDI_T0(); | |
| 1003 | + } else | |
| 1004 | +#endif | |
| 824 | 1005 | if (s->aflag) { |
| 825 | 1006 | gen_op_addl_EDI_T0(); |
| 826 | 1007 | } else { |
| ... | ... | @@ -834,6 +1015,11 @@ static inline void gen_lods(DisasContext *s, int ot) |
| 834 | 1015 | gen_op_ld_T0_A0[ot + s->mem_index](); |
| 835 | 1016 | gen_op_mov_reg_T0[ot][R_EAX](); |
| 836 | 1017 | gen_op_movl_T0_Dshift[ot](); |
| 1018 | +#ifdef TARGET_X86_64 | |
| 1019 | + if (s->aflag == 2) { | |
| 1020 | + gen_op_addq_ESI_T0(); | |
| 1021 | + } else | |
| 1022 | +#endif | |
| 837 | 1023 | if (s->aflag) { |
| 838 | 1024 | gen_op_addl_ESI_T0(); |
| 839 | 1025 | } else { |
| ... | ... | @@ -848,6 +1034,11 @@ static inline void gen_scas(DisasContext *s, int ot) |
| 848 | 1034 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 849 | 1035 | gen_op_cmpl_T0_T1_cc(); |
| 850 | 1036 | gen_op_movl_T0_Dshift[ot](); |
| 1037 | +#ifdef TARGET_X86_64 | |
| 1038 | + if (s->aflag == 2) { | |
| 1039 | + gen_op_addq_EDI_T0(); | |
| 1040 | + } else | |
| 1041 | +#endif | |
| 851 | 1042 | if (s->aflag) { |
| 852 | 1043 | gen_op_addl_EDI_T0(); |
| 853 | 1044 | } else { |
| ... | ... | @@ -863,6 +1054,12 @@ static inline void gen_cmps(DisasContext *s, int ot) |
| 863 | 1054 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 864 | 1055 | gen_op_cmpl_T0_T1_cc(); |
| 865 | 1056 | gen_op_movl_T0_Dshift[ot](); |
| 1057 | +#ifdef TARGET_X86_64 | |
| 1058 | + if (s->aflag == 2) { | |
| 1059 | + gen_op_addq_ESI_T0(); | |
| 1060 | + gen_op_addq_EDI_T0(); | |
| 1061 | + } else | |
| 1062 | +#endif | |
| 866 | 1063 | if (s->aflag) { |
| 867 | 1064 | gen_op_addl_ESI_T0(); |
| 868 | 1065 | gen_op_addl_EDI_T0(); |
| ... | ... | @@ -880,6 +1077,11 @@ static inline void gen_ins(DisasContext *s, int ot) |
| 880 | 1077 | gen_op_in_DX_T0[ot](); |
| 881 | 1078 | gen_op_st_T0_A0[ot + s->mem_index](); |
| 882 | 1079 | gen_op_movl_T0_Dshift[ot](); |
| 1080 | +#ifdef TARGET_X86_64 | |
| 1081 | + if (s->aflag == 2) { | |
| 1082 | + gen_op_addq_EDI_T0(); | |
| 1083 | + } else | |
| 1084 | +#endif | |
| 883 | 1085 | if (s->aflag) { |
| 884 | 1086 | gen_op_addl_EDI_T0(); |
| 885 | 1087 | } else { |
| ... | ... | @@ -893,6 +1095,11 @@ static inline void gen_outs(DisasContext *s, int ot) |
| 893 | 1095 | gen_op_ld_T0_A0[ot + s->mem_index](); |
| 894 | 1096 | gen_op_out_DX_T0[ot](); |
| 895 | 1097 | gen_op_movl_T0_Dshift[ot](); |
| 1098 | +#ifdef TARGET_X86_64 | |
| 1099 | + if (s->aflag == 2) { | |
| 1100 | + gen_op_addq_ESI_T0(); | |
| 1101 | + } else | |
| 1102 | +#endif | |
| 896 | 1103 | if (s->aflag) { |
| 897 | 1104 | gen_op_addl_ESI_T0(); |
| 898 | 1105 | } else { |
| ... | ... | @@ -904,36 +1111,35 @@ static inline void gen_outs(DisasContext *s, int ot) |
| 904 | 1111 | instruction */ |
| 905 | 1112 | #define GEN_REPZ(op) \ |
| 906 | 1113 | static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
| 907 | - unsigned int cur_eip, unsigned int next_eip) \ | |
| 1114 | + target_ulong cur_eip, target_ulong next_eip) \ | |
| 908 | 1115 | { \ |
| 1116 | + int l2;\ | |
| 909 | 1117 | gen_update_cc_op(s); \ |
| 910 | - gen_jz_ecx_string(s, next_eip); \ | |
| 1118 | + l2 = gen_jz_ecx_string(s, next_eip); \ | |
| 911 | 1119 | gen_ ## op(s, ot); \ |
| 912 | 1120 | gen_op_dec_ECX[s->aflag](); \ |
| 913 | 1121 | /* a loop would cause two single step exceptions if ECX = 1 \ |
| 914 | 1122 | before rep string_insn */ \ |
| 915 | 1123 | if (!s->jmp_opt) \ |
| 916 | - gen_op_jz_ecx_im[s->aflag](next_eip); \ | |
| 1124 | + gen_op_jz_ecx[s->aflag](l2); \ | |
| 917 | 1125 | gen_jmp(s, cur_eip); \ |
| 918 | 1126 | } |
| 919 | 1127 | |
| 920 | 1128 | #define GEN_REPZ2(op) \ |
| 921 | 1129 | static inline void gen_repz_ ## op(DisasContext *s, int ot, \ |
| 922 | - unsigned int cur_eip, \ | |
| 923 | - unsigned int next_eip, \ | |
| 1130 | + target_ulong cur_eip, \ | |
| 1131 | + target_ulong next_eip, \ | |
| 924 | 1132 | int nz) \ |
| 925 | 1133 | { \ |
| 1134 | + int l2;\ | |
| 926 | 1135 | gen_update_cc_op(s); \ |
| 927 | - gen_jz_ecx_string(s, next_eip); \ | |
| 1136 | + l2 = gen_jz_ecx_string(s, next_eip); \ | |
| 928 | 1137 | gen_ ## op(s, ot); \ |
| 929 | 1138 | gen_op_dec_ECX[s->aflag](); \ |
| 930 | 1139 | gen_op_set_cc_op(CC_OP_SUBB + ot); \ |
| 1140 | + gen_op_string_jnz_sub[nz][ot](l2);\ | |
| 931 | 1141 | if (!s->jmp_opt) \ |
| 932 | - gen_op_string_jnz_sub_im[nz][ot](next_eip); \ | |
| 933 | - else \ | |
| 934 | - gen_op_string_jnz_sub(nz, ot, (long)s->tb); \ | |
| 935 | - if (!s->jmp_opt) \ | |
| 936 | - gen_op_jz_ecx_im[s->aflag](next_eip); \ | |
| 1142 | + gen_op_jz_ecx[s->aflag](l2); \ | |
| 937 | 1143 | gen_jmp(s, cur_eip); \ |
| 938 | 1144 | } |
| 939 | 1145 | |
| ... | ... | @@ -956,7 +1162,7 @@ enum { |
| 956 | 1162 | JCC_LE, |
| 957 | 1163 | }; |
| 958 | 1164 | |
| 959 | -static GenOpFunc3 *gen_jcc_sub[3][8] = { | |
| 1165 | +static GenOpFunc1 *gen_jcc_sub[4][8] = { | |
| 960 | 1166 | [OT_BYTE] = { |
| 961 | 1167 | NULL, |
| 962 | 1168 | gen_op_jb_subb, |
| ... | ... | @@ -987,20 +1193,37 @@ static GenOpFunc3 *gen_jcc_sub[3][8] = { |
| 987 | 1193 | gen_op_jl_subl, |
| 988 | 1194 | gen_op_jle_subl, |
| 989 | 1195 | }, |
| 1196 | +#ifdef TARGET_X86_64 | |
| 1197 | + [OT_QUAD] = { | |
| 1198 | + NULL, | |
| 1199 | + BUGGY_64(gen_op_jb_subq), | |
| 1200 | + gen_op_jz_subq, | |
| 1201 | + BUGGY_64(gen_op_jbe_subq), | |
| 1202 | + gen_op_js_subq, | |
| 1203 | + NULL, | |
| 1204 | + BUGGY_64(gen_op_jl_subq), | |
| 1205 | + BUGGY_64(gen_op_jle_subq), | |
| 1206 | + }, | |
| 1207 | +#endif | |
| 990 | 1208 | }; |
| 991 | -static GenOpFunc2 *gen_op_loop[2][4] = { | |
| 1209 | +static GenOpFunc1 *gen_op_loop[3][4] = { | |
| 992 | 1210 | [0] = { |
| 993 | 1211 | gen_op_loopnzw, |
| 994 | 1212 | gen_op_loopzw, |
| 995 | - gen_op_loopw, | |
| 996 | - gen_op_jecxzw, | |
| 1213 | + gen_op_jnz_ecxw, | |
| 997 | 1214 | }, |
| 998 | 1215 | [1] = { |
| 999 | 1216 | gen_op_loopnzl, |
| 1000 | 1217 | gen_op_loopzl, |
| 1001 | - gen_op_loopl, | |
| 1002 | - gen_op_jecxzl, | |
| 1218 | + gen_op_jnz_ecxl, | |
| 1219 | + }, | |
| 1220 | +#ifdef TARGET_X86_64 | |
| 1221 | + [2] = { | |
| 1222 | + gen_op_loopnzq, | |
| 1223 | + gen_op_loopzq, | |
| 1224 | + gen_op_jnz_ecxq, | |
| 1003 | 1225 | }, |
| 1226 | +#endif | |
| 1004 | 1227 | }; |
| 1005 | 1228 | |
| 1006 | 1229 | static GenOpFunc *gen_setcc_slow[8] = { |
| ... | ... | @@ -1014,7 +1237,7 @@ static GenOpFunc *gen_setcc_slow[8] = { |
| 1014 | 1237 | gen_op_setle_T0_cc, |
| 1015 | 1238 | }; |
| 1016 | 1239 | |
| 1017 | -static GenOpFunc *gen_setcc_sub[3][8] = { | |
| 1240 | +static GenOpFunc *gen_setcc_sub[4][8] = { | |
| 1018 | 1241 | [OT_BYTE] = { |
| 1019 | 1242 | NULL, |
| 1020 | 1243 | gen_op_setb_T0_subb, |
| ... | ... | @@ -1045,6 +1268,18 @@ static GenOpFunc *gen_setcc_sub[3][8] = { |
| 1045 | 1268 | gen_op_setl_T0_subl, |
| 1046 | 1269 | gen_op_setle_T0_subl, |
| 1047 | 1270 | }, |
| 1271 | +#ifdef TARGET_X86_64 | |
| 1272 | + [OT_QUAD] = { | |
| 1273 | + NULL, | |
| 1274 | + gen_op_setb_T0_subq, | |
| 1275 | + gen_op_setz_T0_subq, | |
| 1276 | + gen_op_setbe_T0_subq, | |
| 1277 | + gen_op_sets_T0_subq, | |
| 1278 | + NULL, | |
| 1279 | + gen_op_setl_T0_subq, | |
| 1280 | + gen_op_setle_T0_subq, | |
| 1281 | + }, | |
| 1282 | +#endif | |
| 1048 | 1283 | }; |
| 1049 | 1284 | |
| 1050 | 1285 | static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { |
| ... | ... | @@ -1183,8 +1418,9 @@ static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c) |
| 1183 | 1418 | |
| 1184 | 1419 | static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr) |
| 1185 | 1420 | { |
| 1421 | + target_long disp; | |
| 1186 | 1422 | int havesib; |
| 1187 | - int base, disp; | |
| 1423 | + int base; | |
| 1188 | 1424 | int index; |
| 1189 | 1425 | int scale; |
| 1190 | 1426 | int opreg; |
| ... | ... | @@ -1208,16 +1444,20 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
| 1208 | 1444 | havesib = 1; |
| 1209 | 1445 | code = ldub_code(s->pc++); |
| 1210 | 1446 | scale = (code >> 6) & 3; |
| 1211 | - index = (code >> 3) & 7; | |
| 1212 | - base = code & 7; | |
| 1447 | + index = ((code >> 3) & 7) | REX_X(s); | |
| 1448 | + base = (code & 7); | |
| 1213 | 1449 | } |
| 1450 | + base |= REX_B(s); | |
| 1214 | 1451 | |
| 1215 | 1452 | switch (mod) { |
| 1216 | 1453 | case 0: |
| 1217 | - if (base == 5) { | |
| 1454 | + if ((base & 7) == 5) { | |
| 1218 | 1455 | base = -1; |
| 1219 | - disp = ldl_code(s->pc); | |
| 1456 | + disp = (int32_t)ldl_code(s->pc); | |
| 1220 | 1457 | s->pc += 4; |
| 1458 | + if (CODE64(s) && !havesib) { | |
| 1459 | + disp += s->pc + s->rip_offset; | |
| 1460 | + } | |
| 1221 | 1461 | } else { |
| 1222 | 1462 | disp = 0; |
| 1223 | 1463 | } |
| ... | ... | @@ -1236,15 +1476,45 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
| 1236 | 1476 | /* for correct popl handling with esp */ |
| 1237 | 1477 | if (base == 4 && s->popl_esp_hack) |
| 1238 | 1478 | disp += s->popl_esp_hack; |
| 1239 | - gen_op_movl_A0_reg[base](); | |
| 1240 | - if (disp != 0) | |
| 1241 | - gen_op_addl_A0_im(disp); | |
| 1479 | +#ifdef TARGET_X86_64 | |
| 1480 | + if (s->aflag == 2) { | |
| 1481 | + gen_op_movq_A0_reg[base](); | |
| 1482 | + if (disp != 0) { | |
| 1483 | + if ((int32_t)disp == disp) | |
| 1484 | + gen_op_addq_A0_im(disp); | |
| 1485 | + else | |
| 1486 | + gen_op_addq_A0_im64(disp >> 32, disp); | |
| 1487 | + } | |
| 1488 | + } else | |
| 1489 | +#endif | |
| 1490 | + { | |
| 1491 | + gen_op_movl_A0_reg[base](); | |
| 1492 | + if (disp != 0) | |
| 1493 | + gen_op_addl_A0_im(disp); | |
| 1494 | + } | |
| 1242 | 1495 | } else { |
| 1243 | - gen_op_movl_A0_im(disp); | |
| 1496 | +#ifdef TARGET_X86_64 | |
| 1497 | + if (s->aflag == 2) { | |
| 1498 | + if ((int32_t)disp == disp) | |
| 1499 | + gen_op_movq_A0_im(disp); | |
| 1500 | + else | |
| 1501 | + gen_op_movq_A0_im64(disp >> 32, disp); | |
| 1502 | + } else | |
| 1503 | +#endif | |
| 1504 | + { | |
| 1505 | + gen_op_movl_A0_im(disp); | |
| 1506 | + } | |
| 1244 | 1507 | } |
| 1245 | 1508 | /* XXX: index == 4 is always invalid */ |
| 1246 | 1509 | if (havesib && (index != 4 || scale != 0)) { |
| 1247 | - gen_op_addl_A0_reg_sN[scale][index](); | |
| 1510 | +#ifdef TARGET_X86_64 | |
| 1511 | + if (s->aflag == 2) { | |
| 1512 | + gen_op_addq_A0_reg_sN[scale][index](); | |
| 1513 | + } else | |
| 1514 | +#endif | |
| 1515 | + { | |
| 1516 | + gen_op_addl_A0_reg_sN[scale][index](); | |
| 1517 | + } | |
| 1248 | 1518 | } |
| 1249 | 1519 | if (must_add_seg) { |
| 1250 | 1520 | if (override < 0) { |
| ... | ... | @@ -1253,7 +1523,14 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
| 1253 | 1523 | else |
| 1254 | 1524 | override = R_DS; |
| 1255 | 1525 | } |
| 1256 | - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 1526 | +#ifdef TARGET_X86_64 | |
| 1527 | + if (s->aflag == 2) { | |
| 1528 | + gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 1529 | + } else | |
| 1530 | +#endif | |
| 1531 | + { | |
| 1532 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 1533 | + } | |
| 1257 | 1534 | } |
| 1258 | 1535 | } else { |
| 1259 | 1536 | switch (mod) { |
| ... | ... | @@ -1336,7 +1613,7 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s |
| 1336 | 1613 | int mod, rm, opreg, disp; |
| 1337 | 1614 | |
| 1338 | 1615 | mod = (modrm >> 6) & 3; |
| 1339 | - rm = modrm & 7; | |
| 1616 | + rm = (modrm & 7) | REX_B(s); | |
| 1340 | 1617 | if (mod == 3) { |
| 1341 | 1618 | if (is_store) { |
| 1342 | 1619 | if (reg != OR_TMP0) |
| ... | ... | @@ -1383,11 +1660,22 @@ static inline uint32_t insn_get(DisasContext *s, int ot) |
| 1383 | 1660 | return ret; |
| 1384 | 1661 | } |
| 1385 | 1662 | |
| 1386 | -static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip) | |
| 1663 | +static inline int insn_const_size(unsigned int ot) | |
| 1664 | +{ | |
| 1665 | + if (ot <= OT_LONG) | |
| 1666 | + return 1 << ot; | |
| 1667 | + else | |
| 1668 | + return 4; | |
| 1669 | +} | |
| 1670 | + | |
| 1671 | +static inline void gen_jcc(DisasContext *s, int b, | |
| 1672 | + target_ulong val, target_ulong next_eip) | |
| 1387 | 1673 | { |
| 1388 | 1674 | TranslationBlock *tb; |
| 1389 | 1675 | int inv, jcc_op; |
| 1390 | - GenOpFunc3 *func; | |
| 1676 | + GenOpFunc1 *func; | |
| 1677 | + target_ulong tmp; | |
| 1678 | + int l1, l2; | |
| 1391 | 1679 | |
| 1392 | 1680 | inv = b & 1; |
| 1393 | 1681 | jcc_op = (b >> 1) & 7; |
| ... | ... | @@ -1398,6 +1686,7 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip) |
| 1398 | 1686 | case CC_OP_SUBB: |
| 1399 | 1687 | case CC_OP_SUBW: |
| 1400 | 1688 | case CC_OP_SUBL: |
| 1689 | + case CC_OP_SUBQ: | |
| 1401 | 1690 | func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
| 1402 | 1691 | break; |
| 1403 | 1692 | |
| ... | ... | @@ -1405,33 +1694,48 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip) |
| 1405 | 1694 | case CC_OP_ADDB: |
| 1406 | 1695 | case CC_OP_ADDW: |
| 1407 | 1696 | case CC_OP_ADDL: |
| 1697 | + case CC_OP_ADDQ: | |
| 1698 | + | |
| 1408 | 1699 | case CC_OP_ADCB: |
| 1409 | 1700 | case CC_OP_ADCW: |
| 1410 | 1701 | case CC_OP_ADCL: |
| 1702 | + case CC_OP_ADCQ: | |
| 1703 | + | |
| 1411 | 1704 | case CC_OP_SBBB: |
| 1412 | 1705 | case CC_OP_SBBW: |
| 1413 | 1706 | case CC_OP_SBBL: |
| 1707 | + case CC_OP_SBBQ: | |
| 1708 | + | |
| 1414 | 1709 | case CC_OP_LOGICB: |
| 1415 | 1710 | case CC_OP_LOGICW: |
| 1416 | 1711 | case CC_OP_LOGICL: |
| 1712 | + case CC_OP_LOGICQ: | |
| 1713 | + | |
| 1417 | 1714 | case CC_OP_INCB: |
| 1418 | 1715 | case CC_OP_INCW: |
| 1419 | 1716 | case CC_OP_INCL: |
| 1717 | + case CC_OP_INCQ: | |
| 1718 | + | |
| 1420 | 1719 | case CC_OP_DECB: |
| 1421 | 1720 | case CC_OP_DECW: |
| 1422 | 1721 | case CC_OP_DECL: |
| 1722 | + case CC_OP_DECQ: | |
| 1723 | + | |
| 1423 | 1724 | case CC_OP_SHLB: |
| 1424 | 1725 | case CC_OP_SHLW: |
| 1425 | 1726 | case CC_OP_SHLL: |
| 1727 | + case CC_OP_SHLQ: | |
| 1728 | + | |
| 1426 | 1729 | case CC_OP_SARB: |
| 1427 | 1730 | case CC_OP_SARW: |
| 1428 | 1731 | case CC_OP_SARL: |
| 1732 | + case CC_OP_SARQ: | |
| 1429 | 1733 | switch(jcc_op) { |
| 1430 | 1734 | case JCC_Z: |
| 1431 | - func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; | |
| 1735 | + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; | |
| 1432 | 1736 | break; |
| 1433 | 1737 | case JCC_S: |
| 1434 | - func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; | |
| 1738 | + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; | |
| 1435 | 1739 | break; |
| 1436 | 1740 | default: |
| 1437 | 1741 | func = NULL; |
| ... | ... | @@ -1448,27 +1752,51 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip) |
| 1448 | 1752 | |
| 1449 | 1753 | if (!func) { |
| 1450 | 1754 | gen_setcc_slow[jcc_op](); |
| 1451 | - func = gen_op_jcc; | |
| 1755 | + func = gen_op_jnz_T0_label; | |
| 1452 | 1756 | } |
| 1453 | 1757 | |
| 1454 | - tb = s->tb; | |
| 1455 | - if (!inv) { | |
| 1456 | - func((long)tb, val, next_eip); | |
| 1457 | - } else { | |
| 1458 | - func((long)tb, next_eip, val); | |
| 1758 | + if (inv) { | |
| 1759 | + tmp = val; | |
| 1760 | + val = next_eip; | |
| 1761 | + next_eip = tmp; | |
| 1459 | 1762 | } |
| 1763 | + tb = s->tb; | |
| 1764 | + | |
| 1765 | + l1 = gen_new_label(); | |
| 1766 | + func(l1); | |
| 1767 | + | |
| 1768 | + gen_op_goto_tb0(); | |
| 1769 | + gen_jmp_im(next_eip); | |
| 1770 | + gen_op_movl_T0_im((long)tb + 0); | |
| 1771 | + gen_op_exit_tb(); | |
| 1772 | + | |
| 1773 | + gen_set_label(l1); | |
| 1774 | + gen_op_goto_tb1(); | |
| 1775 | + gen_jmp_im(val); | |
| 1776 | + gen_op_movl_T0_im((long)tb + 1); | |
| 1777 | + gen_op_exit_tb(); | |
| 1778 | + | |
| 1460 | 1779 | s->is_jmp = 3; |
| 1461 | 1780 | } else { |
| 1781 | + | |
| 1462 | 1782 | if (s->cc_op != CC_OP_DYNAMIC) { |
| 1463 | 1783 | gen_op_set_cc_op(s->cc_op); |
| 1464 | 1784 | s->cc_op = CC_OP_DYNAMIC; |
| 1465 | 1785 | } |
| 1466 | 1786 | gen_setcc_slow[jcc_op](); |
| 1467 | - if (!inv) { | |
| 1468 | - gen_op_jcc_im(val, next_eip); | |
| 1469 | - } else { | |
| 1470 | - gen_op_jcc_im(next_eip, val); | |
| 1787 | + if (inv) { | |
| 1788 | + tmp = val; | |
| 1789 | + val = next_eip; | |
| 1790 | + next_eip = tmp; | |
| 1471 | 1791 | } |
| 1792 | + l1 = gen_new_label(); | |
| 1793 | + l2 = gen_new_label(); | |
| 1794 | + gen_op_jnz_T0_label(l1); | |
| 1795 | + gen_jmp_im(next_eip); | |
| 1796 | + gen_op_jmp_label(l2); | |
| 1797 | + gen_set_label(l1); | |
| 1798 | + gen_jmp_im(val); | |
| 1799 | + gen_set_label(l2); | |
| 1472 | 1800 | gen_eob(s); |
| 1473 | 1801 | } |
| 1474 | 1802 | } |
| ... | ... | @@ -1485,6 +1813,7 @@ static void gen_setcc(DisasContext *s, int b) |
| 1485 | 1813 | case CC_OP_SUBB: |
| 1486 | 1814 | case CC_OP_SUBW: |
| 1487 | 1815 | case CC_OP_SUBL: |
| 1816 | + case CC_OP_SUBQ: | |
| 1488 | 1817 | func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op]; |
| 1489 | 1818 | if (!func) |
| 1490 | 1819 | goto slow_jcc; |
| ... | ... | @@ -1494,24 +1823,33 @@ static void gen_setcc(DisasContext *s, int b) |
| 1494 | 1823 | case CC_OP_ADDB: |
| 1495 | 1824 | case CC_OP_ADDW: |
| 1496 | 1825 | case CC_OP_ADDL: |
| 1826 | + case CC_OP_ADDQ: | |
| 1827 | + | |
| 1497 | 1828 | case CC_OP_LOGICB: |
| 1498 | 1829 | case CC_OP_LOGICW: |
| 1499 | 1830 | case CC_OP_LOGICL: |
| 1831 | + case CC_OP_LOGICQ: | |
| 1832 | + | |
| 1500 | 1833 | case CC_OP_INCB: |
| 1501 | 1834 | case CC_OP_INCW: |
| 1502 | 1835 | case CC_OP_INCL: |
| 1836 | + case CC_OP_INCQ: | |
| 1837 | + | |
| 1503 | 1838 | case CC_OP_DECB: |
| 1504 | 1839 | case CC_OP_DECW: |
| 1505 | 1840 | case CC_OP_DECL: |
| 1841 | + case CC_OP_DECQ: | |
| 1842 | + | |
| 1506 | 1843 | case CC_OP_SHLB: |
| 1507 | 1844 | case CC_OP_SHLW: |
| 1508 | 1845 | case CC_OP_SHLL: |
| 1846 | + case CC_OP_SHLQ: | |
| 1509 | 1847 | switch(jcc_op) { |
| 1510 | 1848 | case JCC_Z: |
| 1511 | - func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; | |
| 1849 | + func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; | |
| 1512 | 1850 | break; |
| 1513 | 1851 | case JCC_S: |
| 1514 | - func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op]; | |
| 1852 | + func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 4][jcc_op]; | |
| 1515 | 1853 | break; |
| 1516 | 1854 | default: |
| 1517 | 1855 | goto slow_jcc; |
| ... | ... | @@ -1532,13 +1870,13 @@ static void gen_setcc(DisasContext *s, int b) |
| 1532 | 1870 | |
| 1533 | 1871 | /* move T0 to seg_reg and compute if the CPU state may change. Never |
| 1534 | 1872 | call this function with seg_reg == R_CS */ |
| 1535 | -static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) | |
| 1873 | +static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) | |
| 1536 | 1874 | { |
| 1537 | 1875 | if (s->pe && !s->vm86) { |
| 1538 | 1876 | /* XXX: optimize by finding processor state dynamically */ |
| 1539 | 1877 | if (s->cc_op != CC_OP_DYNAMIC) |
| 1540 | 1878 | gen_op_set_cc_op(s->cc_op); |
| 1541 | - gen_op_jmp_im(cur_eip); | |
| 1879 | + gen_jmp_im(cur_eip); | |
| 1542 | 1880 | gen_op_movl_seg_T0(seg_reg); |
| 1543 | 1881 | /* abort translation because the addseg value may change or |
| 1544 | 1882 | because ss32 may change. For R_SS, translation must always |
| ... | ... | @@ -1555,6 +1893,14 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) |
| 1555 | 1893 | |
| 1556 | 1894 | static inline void gen_stack_update(DisasContext *s, int addend) |
| 1557 | 1895 | { |
| 1896 | +#ifdef TARGET_X86_64 | |
| 1897 | + if (CODE64(s)) { | |
| 1898 | + if (addend == 8) | |
| 1899 | + gen_op_addq_ESP_8(); | |
| 1900 | + else | |
| 1901 | + gen_op_addq_ESP_im(addend); | |
| 1902 | + } else | |
| 1903 | +#endif | |
| 1558 | 1904 | if (s->ss32) { |
| 1559 | 1905 | if (addend == 2) |
| 1560 | 1906 | gen_op_addl_ESP_2(); |
| ... | ... | @@ -1575,70 +1921,108 @@ static inline void gen_stack_update(DisasContext *s, int addend) |
| 1575 | 1921 | /* generate a push. It depends on ss32, addseg and dflag */ |
| 1576 | 1922 | static void gen_push_T0(DisasContext *s) |
| 1577 | 1923 | { |
| 1578 | - gen_op_movl_A0_reg[R_ESP](); | |
| 1579 | - if (!s->dflag) | |
| 1580 | - gen_op_subl_A0_2(); | |
| 1581 | - else | |
| 1582 | - gen_op_subl_A0_4(); | |
| 1583 | - if (s->ss32) { | |
| 1584 | - if (s->addseg) { | |
| 1924 | +#ifdef TARGET_X86_64 | |
| 1925 | + if (CODE64(s)) { | |
| 1926 | + /* XXX: check 16 bit behaviour */ | |
| 1927 | + gen_op_movq_A0_reg[R_ESP](); | |
| 1928 | + gen_op_subq_A0_8(); | |
| 1929 | + gen_op_st_T0_A0[OT_QUAD + s->mem_index](); | |
| 1930 | + gen_op_movq_ESP_A0(); | |
| 1931 | + } else | |
| 1932 | +#endif | |
| 1933 | + { | |
| 1934 | + gen_op_movl_A0_reg[R_ESP](); | |
| 1935 | + if (!s->dflag) | |
| 1936 | + gen_op_subl_A0_2(); | |
| 1937 | + else | |
| 1938 | + gen_op_subl_A0_4(); | |
| 1939 | + if (s->ss32) { | |
| 1940 | + if (s->addseg) { | |
| 1941 | + gen_op_movl_T1_A0(); | |
| 1942 | + gen_op_addl_A0_SS(); | |
| 1943 | + } | |
| 1944 | + } else { | |
| 1945 | + gen_op_andl_A0_ffff(); | |
| 1585 | 1946 | gen_op_movl_T1_A0(); |
| 1586 | 1947 | gen_op_addl_A0_SS(); |
| 1587 | 1948 | } |
| 1588 | - } else { | |
| 1589 | - gen_op_andl_A0_ffff(); | |
| 1590 | - gen_op_movl_T1_A0(); | |
| 1591 | - gen_op_addl_A0_SS(); | |
| 1949 | + gen_op_st_T0_A0[s->dflag + 1 + s->mem_index](); | |
| 1950 | + if (s->ss32 && !s->addseg) | |
| 1951 | + gen_op_movl_ESP_A0(); | |
| 1952 | + else | |
| 1953 | + gen_op_mov_reg_T1[s->ss32 + 1][R_ESP](); | |
| 1592 | 1954 | } |
| 1593 | - gen_op_st_T0_A0[s->dflag + 1 + s->mem_index](); | |
| 1594 | - if (s->ss32 && !s->addseg) | |
| 1595 | - gen_op_movl_ESP_A0(); | |
| 1596 | - else | |
| 1597 | - gen_op_mov_reg_T1[s->ss32 + 1][R_ESP](); | |
| 1598 | 1955 | } |
| 1599 | 1956 | |
| 1600 | 1957 | /* generate a push. It depends on ss32, addseg and dflag */ |
| 1601 | 1958 | /* slower version for T1, only used for call Ev */ |
| 1602 | 1959 | static void gen_push_T1(DisasContext *s) |
| 1603 | 1960 | { |
| 1604 | - gen_op_movl_A0_reg[R_ESP](); | |
| 1605 | - if (!s->dflag) | |
| 1606 | - gen_op_subl_A0_2(); | |
| 1607 | - else | |
| 1608 | - gen_op_subl_A0_4(); | |
| 1609 | - if (s->ss32) { | |
| 1610 | - if (s->addseg) { | |
| 1961 | +#ifdef TARGET_X86_64 | |
| 1962 | + if (CODE64(s)) { | |
| 1963 | + /* XXX: check 16 bit behaviour */ | |
| 1964 | + gen_op_movq_A0_reg[R_ESP](); | |
| 1965 | + gen_op_subq_A0_8(); | |
| 1966 | + gen_op_st_T1_A0[OT_QUAD + s->mem_index](); | |
| 1967 | + gen_op_movq_ESP_A0(); | |
| 1968 | + } else | |
| 1969 | +#endif | |
| 1970 | + { | |
| 1971 | + gen_op_movl_A0_reg[R_ESP](); | |
| 1972 | + if (!s->dflag) | |
| 1973 | + gen_op_subl_A0_2(); | |
| 1974 | + else | |
| 1975 | + gen_op_subl_A0_4(); | |
| 1976 | + if (s->ss32) { | |
| 1977 | + if (s->addseg) { | |
| 1978 | + gen_op_addl_A0_SS(); | |
| 1979 | + } | |
| 1980 | + } else { | |
| 1981 | + gen_op_andl_A0_ffff(); | |
| 1611 | 1982 | gen_op_addl_A0_SS(); |
| 1612 | 1983 | } |
| 1613 | - } else { | |
| 1614 | - gen_op_andl_A0_ffff(); | |
| 1615 | - gen_op_addl_A0_SS(); | |
| 1984 | + gen_op_st_T1_A0[s->dflag + 1 + s->mem_index](); | |
| 1985 | + | |
| 1986 | + if (s->ss32 && !s->addseg) | |
| 1987 | + gen_op_movl_ESP_A0(); | |
| 1988 | + else | |
| 1989 | + gen_stack_update(s, (-2) << s->dflag); | |
| 1616 | 1990 | } |
| 1617 | - gen_op_st_T1_A0[s->dflag + 1 + s->mem_index](); | |
| 1618 | - | |
| 1619 | - if (s->ss32 && !s->addseg) | |
| 1620 | - gen_op_movl_ESP_A0(); | |
| 1621 | - else | |
| 1622 | - gen_stack_update(s, (-2) << s->dflag); | |
| 1623 | 1991 | } |
| 1624 | 1992 | |
| 1625 | 1993 | /* two step pop is necessary for precise exceptions */ |
| 1626 | 1994 | static void gen_pop_T0(DisasContext *s) |
| 1627 | 1995 | { |
| 1628 | - gen_op_movl_A0_reg[R_ESP](); | |
| 1629 | - if (s->ss32) { | |
| 1630 | - if (s->addseg) | |
| 1996 | +#ifdef TARGET_X86_64 | |
| 1997 | + if (CODE64(s)) { | |
| 1998 | + /* XXX: check 16 bit behaviour */ | |
| 1999 | + gen_op_movq_A0_reg[R_ESP](); | |
| 2000 | + gen_op_ld_T0_A0[OT_QUAD + s->mem_index](); | |
| 2001 | + } else | |
| 2002 | +#endif | |
| 2003 | + { | |
| 2004 | + gen_op_movl_A0_reg[R_ESP](); | |
| 2005 | + if (s->ss32) { | |
| 2006 | + if (s->addseg) | |
| 2007 | + gen_op_addl_A0_SS(); | |
| 2008 | + } else { | |
| 2009 | + gen_op_andl_A0_ffff(); | |
| 1631 | 2010 | gen_op_addl_A0_SS(); |
| 1632 | - } else { | |
| 1633 | - gen_op_andl_A0_ffff(); | |
| 1634 | - gen_op_addl_A0_SS(); | |
| 2011 | + } | |
| 2012 | + gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index](); | |
| 1635 | 2013 | } |
| 1636 | - gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index](); | |
| 1637 | 2014 | } |
| 1638 | 2015 | |
| 1639 | 2016 | static void gen_pop_update(DisasContext *s) |
| 1640 | 2017 | { |
| 1641 | - gen_stack_update(s, 2 << s->dflag); | |
| 2018 | +#ifdef TARGET_X86_64 | |
| 2019 | + if (CODE64(s)) { | |
| 2020 | + gen_stack_update(s, 8); | |
| 2021 | + } else | |
| 2022 | +#endif | |
| 2023 | + { | |
| 2024 | + gen_stack_update(s, 2 << s->dflag); | |
| 2025 | + } | |
| 1642 | 2026 | } |
| 1643 | 2027 | |
| 1644 | 2028 | static void gen_stack_A0(DisasContext *s) |
| ... | ... | @@ -1718,11 +2102,11 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) |
| 1718 | 2102 | gen_op_mov_reg_T1[ot][R_ESP](); |
| 1719 | 2103 | } |
| 1720 | 2104 | |
| 1721 | -static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip) | |
| 2105 | +static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) | |
| 1722 | 2106 | { |
| 1723 | 2107 | if (s->cc_op != CC_OP_DYNAMIC) |
| 1724 | 2108 | gen_op_set_cc_op(s->cc_op); |
| 1725 | - gen_op_jmp_im(cur_eip); | |
| 2109 | + gen_jmp_im(cur_eip); | |
| 1726 | 2110 | gen_op_raise_exception(trapno); |
| 1727 | 2111 | s->is_jmp = 3; |
| 1728 | 2112 | } |
| ... | ... | @@ -1730,20 +2114,20 @@ static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip) |
| 1730 | 2114 | /* an interrupt is different from an exception because of the |
| 1731 | 2115 | priviledge checks */ |
| 1732 | 2116 | static void gen_interrupt(DisasContext *s, int intno, |
| 1733 | - unsigned int cur_eip, unsigned int next_eip) | |
| 2117 | + target_ulong cur_eip, target_ulong next_eip) | |
| 1734 | 2118 | { |
| 1735 | 2119 | if (s->cc_op != CC_OP_DYNAMIC) |
| 1736 | 2120 | gen_op_set_cc_op(s->cc_op); |
| 1737 | - gen_op_jmp_im(cur_eip); | |
| 2121 | + gen_jmp_im(cur_eip); | |
| 1738 | 2122 | gen_op_raise_interrupt(intno, next_eip); |
| 1739 | 2123 | s->is_jmp = 3; |
| 1740 | 2124 | } |
| 1741 | 2125 | |
| 1742 | -static void gen_debug(DisasContext *s, unsigned int cur_eip) | |
| 2126 | +static void gen_debug(DisasContext *s, target_ulong cur_eip) | |
| 1743 | 2127 | { |
| 1744 | 2128 | if (s->cc_op != CC_OP_DYNAMIC) |
| 1745 | 2129 | gen_op_set_cc_op(s->cc_op); |
| 1746 | - gen_op_jmp_im(cur_eip); | |
| 2130 | + gen_jmp_im(cur_eip); | |
| 1747 | 2131 | gen_op_debug(); |
| 1748 | 2132 | s->is_jmp = 3; |
| 1749 | 2133 | } |
| ... | ... | @@ -1770,80 +2154,186 @@ static void gen_eob(DisasContext *s) |
| 1770 | 2154 | |
| 1771 | 2155 | /* generate a jump to eip. No segment change must happen before as a |
| 1772 | 2156 | direct call to the next block may occur */ |
| 1773 | -static void gen_jmp(DisasContext *s, unsigned int eip) | |
| 2157 | +static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num) | |
| 1774 | 2158 | { |
| 1775 | 2159 | TranslationBlock *tb = s->tb; |
| 1776 | 2160 | |
| 1777 | 2161 | if (s->jmp_opt) { |
| 1778 | 2162 | if (s->cc_op != CC_OP_DYNAMIC) |
| 1779 | 2163 | gen_op_set_cc_op(s->cc_op); |
| 1780 | - gen_op_jmp((long)tb, eip); | |
| 2164 | + if (tb_num) | |
| 2165 | + gen_op_goto_tb1(); | |
| 2166 | + else | |
| 2167 | + gen_op_goto_tb0(); | |
| 2168 | + gen_jmp_im(eip); | |
| 2169 | + gen_op_movl_T0_im((long)tb + tb_num); | |
| 2170 | + gen_op_exit_tb(); | |
| 1781 | 2171 | s->is_jmp = 3; |
| 1782 | 2172 | } else { |
| 1783 | - gen_op_jmp_im(eip); | |
| 2173 | + gen_jmp_im(eip); | |
| 1784 | 2174 | gen_eob(s); |
| 1785 | 2175 | } |
| 1786 | 2176 | } |
| 1787 | 2177 | |
| 2178 | +static void gen_jmp(DisasContext *s, target_ulong eip) | |
| 2179 | +{ | |
| 2180 | + gen_jmp_tb(s, eip, 0); | |
| 2181 | +} | |
| 2182 | + | |
| 2183 | +static void gen_movtl_T0_im(target_ulong val) | |
| 2184 | +{ | |
| 2185 | +#ifdef TARGET_X86_64 | |
| 2186 | + if ((int32_t)val == val) { | |
| 2187 | + gen_op_movl_T0_im(val); | |
| 2188 | + } else { | |
| 2189 | + gen_op_movq_T0_im64(val >> 32, val); | |
| 2190 | + } | |
| 2191 | +#else | |
| 2192 | + gen_op_movl_T0_im(val); | |
| 2193 | +#endif | |
| 2194 | +} | |
| 2195 | + | |
| 2196 | +static GenOpFunc1 *gen_ldo_env_A0[3] = { | |
| 2197 | + gen_op_ldo_raw_env_A0, | |
| 2198 | +#ifndef CONFIG_USER_ONLY | |
| 2199 | + gen_op_ldo_kernel_env_A0, | |
| 2200 | + gen_op_ldo_user_env_A0, | |
| 2201 | +#endif | |
| 2202 | +}; | |
| 2203 | + | |
| 2204 | +static GenOpFunc1 *gen_sto_env_A0[3] = { | |
| 2205 | + gen_op_sto_raw_env_A0, | |
| 2206 | +#ifndef CONFIG_USER_ONLY | |
| 2207 | + gen_op_sto_kernel_env_A0, | |
| 2208 | + gen_op_sto_user_env_A0, | |
| 2209 | +#endif | |
| 2210 | +}; | |
| 2211 | + | |
| 1788 | 2212 | /* convert one instruction. s->is_jmp is set if the translation must |
| 1789 | 2213 | be stopped. Return the next pc value */ |
| 1790 | -static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | |
| 2214 | +static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | |
| 1791 | 2215 | { |
| 1792 | 2216 | int b, prefixes, aflag, dflag; |
| 1793 | 2217 | int shift, ot; |
| 1794 | 2218 | int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val; |
| 1795 | - unsigned int next_eip; | |
| 2219 | + target_ulong next_eip, tval; | |
| 2220 | + int rex_w, rex_r; | |
| 1796 | 2221 | |
| 1797 | 2222 | s->pc = pc_start; |
| 1798 | 2223 | prefixes = 0; |
| 1799 | 2224 | aflag = s->code32; |
| 1800 | 2225 | dflag = s->code32; |
| 1801 | 2226 | s->override = -1; |
| 2227 | + rex_w = -1; | |
| 2228 | + rex_r = 0; | |
| 2229 | +#ifdef TARGET_X86_64 | |
| 2230 | + s->rex_x = 0; | |
| 2231 | + s->rex_b = 0; | |
| 2232 | + x86_64_hregs = 0; | |
| 2233 | +#endif | |
| 2234 | + s->rip_offset = 0; /* for relative ip address */ | |
| 1802 | 2235 | next_byte: |
| 1803 | 2236 | b = ldub_code(s->pc); |
| 1804 | 2237 | s->pc++; |
| 1805 | 2238 | /* check prefixes */ |
| 1806 | - switch (b) { | |
| 1807 | - case 0xf3: | |
| 1808 | - prefixes |= PREFIX_REPZ; | |
| 1809 | - goto next_byte; | |
| 1810 | - case 0xf2: | |
| 1811 | - prefixes |= PREFIX_REPNZ; | |
| 1812 | - goto next_byte; | |
| 1813 | - case 0xf0: | |
| 1814 | - prefixes |= PREFIX_LOCK; | |
| 1815 | - goto next_byte; | |
| 1816 | - case 0x2e: | |
| 1817 | - s->override = R_CS; | |
| 1818 | - goto next_byte; | |
| 1819 | - case 0x36: | |
| 1820 | - s->override = R_SS; | |
| 1821 | - goto next_byte; | |
| 1822 | - case 0x3e: | |
| 1823 | - s->override = R_DS; | |
| 1824 | - goto next_byte; | |
| 1825 | - case 0x26: | |
| 1826 | - s->override = R_ES; | |
| 1827 | - goto next_byte; | |
| 1828 | - case 0x64: | |
| 1829 | - s->override = R_FS; | |
| 1830 | - goto next_byte; | |
| 1831 | - case 0x65: | |
| 1832 | - s->override = R_GS; | |
| 1833 | - goto next_byte; | |
| 1834 | - case 0x66: | |
| 1835 | - prefixes |= PREFIX_DATA; | |
| 1836 | - goto next_byte; | |
| 1837 | - case 0x67: | |
| 1838 | - prefixes |= PREFIX_ADR; | |
| 1839 | - goto next_byte; | |
| 2239 | +#ifdef TARGET_X86_64 | |
| 2240 | + if (CODE64(s)) { | |
| 2241 | + switch (b) { | |
| 2242 | + case 0xf3: | |
| 2243 | + prefixes |= PREFIX_REPZ; | |
| 2244 | + goto next_byte; | |
| 2245 | + case 0xf2: | |
| 2246 | + prefixes |= PREFIX_REPNZ; | |
| 2247 | + goto next_byte; | |
| 2248 | + case 0xf0: | |
| 2249 | + prefixes |= PREFIX_LOCK; | |
| 2250 | + goto next_byte; | |
| 2251 | + case 0x2e: | |
| 2252 | + s->override = R_CS; | |
| 2253 | + goto next_byte; | |
| 2254 | + case 0x36: | |
| 2255 | + s->override = R_SS; | |
| 2256 | + goto next_byte; | |
| 2257 | + case 0x3e: | |
| 2258 | + s->override = R_DS; | |
| 2259 | + goto next_byte; | |
| 2260 | + case 0x26: | |
| 2261 | + s->override = R_ES; | |
| 2262 | + goto next_byte; | |
| 2263 | + case 0x64: | |
| 2264 | + s->override = R_FS; | |
| 2265 | + goto next_byte; | |
| 2266 | + case 0x65: | |
| 2267 | + s->override = R_GS; | |
| 2268 | + goto next_byte; | |
| 2269 | + case 0x66: | |
| 2270 | + prefixes |= PREFIX_DATA; | |
| 2271 | + goto next_byte; | |
| 2272 | + case 0x67: | |
| 2273 | + prefixes |= PREFIX_ADR; | |
| 2274 | + goto next_byte; | |
| 2275 | + case 0x40 ... 0x4f: | |
| 2276 | + /* REX prefix */ | |
| 2277 | + rex_w = (b >> 3) & 1; | |
| 2278 | + rex_r = (b & 0x4) << 1; | |
| 2279 | + s->rex_x = (b & 0x2) << 2; | |
| 2280 | + REX_B(s) = (b & 0x1) << 3; | |
| 2281 | + x86_64_hregs = 1; /* select uniform byte register addressing */ | |
| 2282 | + goto next_byte; | |
| 2283 | + } | |
| 2284 | + if (rex_w == 1) { | |
| 2285 | + /* 0x66 is ignored if rex.w is set */ | |
| 2286 | + dflag = 2; | |
| 2287 | + } else { | |
| 2288 | + if (prefixes & PREFIX_DATA) | |
| 2289 | + dflag ^= 1; | |
| 2290 | + } | |
| 2291 | + if (!(prefixes & PREFIX_ADR)) | |
| 2292 | + aflag = 2; | |
| 2293 | + } else | |
| 2294 | +#endif | |
| 2295 | + { | |
| 2296 | + switch (b) { | |
| 2297 | + case 0xf3: | |
| 2298 | + prefixes |= PREFIX_REPZ; | |
| 2299 | + goto next_byte; | |
| 2300 | + case 0xf2: | |
| 2301 | + prefixes |= PREFIX_REPNZ; | |
| 2302 | + goto next_byte; | |
| 2303 | + case 0xf0: | |
| 2304 | + prefixes |= PREFIX_LOCK; | |
| 2305 | + goto next_byte; | |
| 2306 | + case 0x2e: | |
| 2307 | + s->override = R_CS; | |
| 2308 | + goto next_byte; | |
| 2309 | + case 0x36: | |
| 2310 | + s->override = R_SS; | |
| 2311 | + goto next_byte; | |
| 2312 | + case 0x3e: | |
| 2313 | + s->override = R_DS; | |
| 2314 | + goto next_byte; | |
| 2315 | + case 0x26: | |
| 2316 | + s->override = R_ES; | |
| 2317 | + goto next_byte; | |
| 2318 | + case 0x64: | |
| 2319 | + s->override = R_FS; | |
| 2320 | + goto next_byte; | |
| 2321 | + case 0x65: | |
| 2322 | + s->override = R_GS; | |
| 2323 | + goto next_byte; | |
| 2324 | + case 0x66: | |
| 2325 | + prefixes |= PREFIX_DATA; | |
| 2326 | + goto next_byte; | |
| 2327 | + case 0x67: | |
| 2328 | + prefixes |= PREFIX_ADR; | |
| 2329 | + goto next_byte; | |
| 2330 | + } | |
| 2331 | + if (prefixes & PREFIX_DATA) | |
| 2332 | + dflag ^= 1; | |
| 2333 | + if (prefixes & PREFIX_ADR) | |
| 2334 | + aflag ^= 1; | |
| 1840 | 2335 | } |
| 1841 | 2336 | |
| 1842 | - if (prefixes & PREFIX_DATA) | |
| 1843 | - dflag ^= 1; | |
| 1844 | - if (prefixes & PREFIX_ADR) | |
| 1845 | - aflag ^= 1; | |
| 1846 | - | |
| 1847 | 2337 | s->prefix = prefixes; |
| 1848 | 2338 | s->aflag = aflag; |
| 1849 | 2339 | s->dflag = dflag; |
| ... | ... | @@ -1879,14 +2369,14 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 1879 | 2369 | if ((b & 1) == 0) |
| 1880 | 2370 | ot = OT_BYTE; |
| 1881 | 2371 | else |
| 1882 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2372 | + ot = dflag + OT_WORD; | |
| 1883 | 2373 | |
| 1884 | 2374 | switch(f) { |
| 1885 | 2375 | case 0: /* OP Ev, Gv */ |
| 1886 | 2376 | modrm = ldub_code(s->pc++); |
| 1887 | - reg = ((modrm >> 3) & 7); | |
| 2377 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 1888 | 2378 | mod = (modrm >> 6) & 3; |
| 1889 | - rm = modrm & 7; | |
| 2379 | + rm = (modrm & 7) | REX_B(s); | |
| 1890 | 2380 | if (mod != 3) { |
| 1891 | 2381 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1892 | 2382 | opreg = OR_TMP0; |
| ... | ... | @@ -1907,8 +2397,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 1907 | 2397 | case 1: /* OP Gv, Ev */ |
| 1908 | 2398 | modrm = ldub_code(s->pc++); |
| 1909 | 2399 | mod = (modrm >> 6) & 3; |
| 1910 | - reg = ((modrm >> 3) & 7); | |
| 1911 | - rm = modrm & 7; | |
| 2400 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2401 | + rm = (modrm & 7) | REX_B(s); | |
| 1912 | 2402 | if (mod != 3) { |
| 1913 | 2403 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1914 | 2404 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| ... | ... | @@ -1938,18 +2428,22 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 1938 | 2428 | if ((b & 1) == 0) |
| 1939 | 2429 | ot = OT_BYTE; |
| 1940 | 2430 | else |
| 1941 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2431 | + ot = dflag + OT_WORD; | |
| 1942 | 2432 | |
| 1943 | 2433 | modrm = ldub_code(s->pc++); |
| 1944 | 2434 | mod = (modrm >> 6) & 3; |
| 1945 | - rm = modrm & 7; | |
| 2435 | + rm = (modrm & 7) | REX_B(s); | |
| 1946 | 2436 | op = (modrm >> 3) & 7; |
| 1947 | 2437 | |
| 1948 | 2438 | if (mod != 3) { |
| 2439 | + if (b == 0x83) | |
| 2440 | + s->rip_offset = 1; | |
| 2441 | + else | |
| 2442 | + s->rip_offset = insn_const_size(ot); | |
| 1949 | 2443 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1950 | 2444 | opreg = OR_TMP0; |
| 1951 | 2445 | } else { |
| 1952 | - opreg = rm + OR_EAX; | |
| 2446 | + opreg = rm; | |
| 1953 | 2447 | } |
| 1954 | 2448 | |
| 1955 | 2449 | switch(b) { |
| ... | ... | @@ -1983,13 +2477,15 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 1983 | 2477 | if ((b & 1) == 0) |
| 1984 | 2478 | ot = OT_BYTE; |
| 1985 | 2479 | else |
| 1986 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2480 | + ot = dflag + OT_WORD; | |
| 1987 | 2481 | |
| 1988 | 2482 | modrm = ldub_code(s->pc++); |
| 1989 | 2483 | mod = (modrm >> 6) & 3; |
| 1990 | - rm = modrm & 7; | |
| 2484 | + rm = (modrm & 7) | REX_B(s); | |
| 1991 | 2485 | op = (modrm >> 3) & 7; |
| 1992 | 2486 | if (mod != 3) { |
| 2487 | + if (op == 0) | |
| 2488 | + s->rip_offset = insn_const_size(ot); | |
| 1993 | 2489 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 1994 | 2490 | gen_op_ld_T0_A0[ot + s->mem_index](); |
| 1995 | 2491 | } else { |
| ... | ... | @@ -2036,6 +2532,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2036 | 2532 | gen_op_mull_EAX_T0(); |
| 2037 | 2533 | s->cc_op = CC_OP_MULL; |
| 2038 | 2534 | break; |
| 2535 | +#ifdef TARGET_X86_64 | |
| 2536 | + case OT_QUAD: | |
| 2537 | + gen_op_mulq_EAX_T0(); | |
| 2538 | + s->cc_op = CC_OP_MULQ; | |
| 2539 | + break; | |
| 2540 | +#endif | |
| 2039 | 2541 | } |
| 2040 | 2542 | break; |
| 2041 | 2543 | case 5: /* imul */ |
| ... | ... | @@ -2053,34 +2555,58 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2053 | 2555 | gen_op_imull_EAX_T0(); |
| 2054 | 2556 | s->cc_op = CC_OP_MULL; |
| 2055 | 2557 | break; |
| 2558 | +#ifdef TARGET_X86_64 | |
| 2559 | + case OT_QUAD: | |
| 2560 | + gen_op_imulq_EAX_T0(); | |
| 2561 | + s->cc_op = CC_OP_MULQ; | |
| 2562 | + break; | |
| 2563 | +#endif | |
| 2056 | 2564 | } |
| 2057 | 2565 | break; |
| 2058 | 2566 | case 6: /* div */ |
| 2059 | 2567 | switch(ot) { |
| 2060 | 2568 | case OT_BYTE: |
| 2061 | - gen_op_divb_AL_T0(pc_start - s->cs_base); | |
| 2569 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2570 | + gen_op_divb_AL_T0(); | |
| 2062 | 2571 | break; |
| 2063 | 2572 | case OT_WORD: |
| 2064 | - gen_op_divw_AX_T0(pc_start - s->cs_base); | |
| 2573 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2574 | + gen_op_divw_AX_T0(); | |
| 2065 | 2575 | break; |
| 2066 | 2576 | default: |
| 2067 | 2577 | case OT_LONG: |
| 2068 | - gen_op_divl_EAX_T0(pc_start - s->cs_base); | |
| 2578 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2579 | + gen_op_divl_EAX_T0(); | |
| 2580 | + break; | |
| 2581 | +#ifdef TARGET_X86_64 | |
| 2582 | + case OT_QUAD: | |
| 2583 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2584 | + gen_op_divq_EAX_T0(); | |
| 2069 | 2585 | break; |
| 2586 | +#endif | |
| 2070 | 2587 | } |
| 2071 | 2588 | break; |
| 2072 | 2589 | case 7: /* idiv */ |
| 2073 | 2590 | switch(ot) { |
| 2074 | 2591 | case OT_BYTE: |
| 2075 | - gen_op_idivb_AL_T0(pc_start - s->cs_base); | |
| 2592 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2593 | + gen_op_idivb_AL_T0(); | |
| 2076 | 2594 | break; |
| 2077 | 2595 | case OT_WORD: |
| 2078 | - gen_op_idivw_AX_T0(pc_start - s->cs_base); | |
| 2596 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2597 | + gen_op_idivw_AX_T0(); | |
| 2079 | 2598 | break; |
| 2080 | 2599 | default: |
| 2081 | 2600 | case OT_LONG: |
| 2082 | - gen_op_idivl_EAX_T0(pc_start - s->cs_base); | |
| 2601 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2602 | + gen_op_idivl_EAX_T0(); | |
| 2603 | + break; | |
| 2604 | +#ifdef TARGET_X86_64 | |
| 2605 | + case OT_QUAD: | |
| 2606 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2607 | + gen_op_idivq_EAX_T0(); | |
| 2083 | 2608 | break; |
| 2609 | +#endif | |
| 2084 | 2610 | } |
| 2085 | 2611 | break; |
| 2086 | 2612 | default: |
| ... | ... | @@ -2093,15 +2619,24 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2093 | 2619 | if ((b & 1) == 0) |
| 2094 | 2620 | ot = OT_BYTE; |
| 2095 | 2621 | else |
| 2096 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2622 | + ot = dflag + OT_WORD; | |
| 2097 | 2623 | |
| 2098 | 2624 | modrm = ldub_code(s->pc++); |
| 2099 | 2625 | mod = (modrm >> 6) & 3; |
| 2100 | - rm = modrm & 7; | |
| 2626 | + rm = (modrm & 7) | REX_B(s); | |
| 2101 | 2627 | op = (modrm >> 3) & 7; |
| 2102 | 2628 | if (op >= 2 && b == 0xfe) { |
| 2103 | 2629 | goto illegal_op; |
| 2104 | 2630 | } |
| 2631 | + if (CODE64(s)) { | |
| 2632 | + if (op >= 2 && op <= 5) { | |
| 2633 | + /* operand size for jumps is 64 bit */ | |
| 2634 | + ot = OT_QUAD; | |
| 2635 | + } else if (op == 6) { | |
| 2636 | + /* default push size is 64 bit */ | |
| 2637 | + ot = dflag ? OT_QUAD : OT_WORD; | |
| 2638 | + } | |
| 2639 | + } | |
| 2105 | 2640 | if (mod != 3) { |
| 2106 | 2641 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2107 | 2642 | if (op >= 2 && op != 3 && op != 5) |
| ... | ... | @@ -2143,7 +2678,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2143 | 2678 | if (s->pe && !s->vm86) { |
| 2144 | 2679 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2145 | 2680 | gen_op_set_cc_op(s->cc_op); |
| 2146 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 2681 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2147 | 2682 | gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base); |
| 2148 | 2683 | } else { |
| 2149 | 2684 | gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); |
| ... | ... | @@ -2164,7 +2699,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2164 | 2699 | if (s->pe && !s->vm86) { |
| 2165 | 2700 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2166 | 2701 | gen_op_set_cc_op(s->cc_op); |
| 2167 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 2702 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2168 | 2703 | gen_op_ljmp_protected_T0_T1(s->pc - s->cs_base); |
| 2169 | 2704 | } else { |
| 2170 | 2705 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
| ... | ... | @@ -2186,15 +2721,15 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2186 | 2721 | if ((b & 1) == 0) |
| 2187 | 2722 | ot = OT_BYTE; |
| 2188 | 2723 | else |
| 2189 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2724 | + ot = dflag + OT_WORD; | |
| 2190 | 2725 | |
| 2191 | 2726 | modrm = ldub_code(s->pc++); |
| 2192 | 2727 | mod = (modrm >> 6) & 3; |
| 2193 | - rm = modrm & 7; | |
| 2194 | - reg = (modrm >> 3) & 7; | |
| 2728 | + rm = (modrm & 7) | REX_B(s); | |
| 2729 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2195 | 2730 | |
| 2196 | 2731 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 2197 | - gen_op_mov_TN_reg[ot][1][reg + OR_EAX](); | |
| 2732 | + gen_op_mov_TN_reg[ot][1][reg](); | |
| 2198 | 2733 | gen_op_testl_T0_T1_cc(); |
| 2199 | 2734 | s->cc_op = CC_OP_LOGICB + ot; |
| 2200 | 2735 | break; |
| ... | ... | @@ -2204,7 +2739,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2204 | 2739 | if ((b & 1) == 0) |
| 2205 | 2740 | ot = OT_BYTE; |
| 2206 | 2741 | else |
| 2207 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2742 | + ot = dflag + OT_WORD; | |
| 2208 | 2743 | val = insn_get(s, ot); |
| 2209 | 2744 | |
| 2210 | 2745 | gen_op_mov_TN_reg[ot][0][OR_EAX](); |
| ... | ... | @@ -2214,13 +2749,23 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2214 | 2749 | break; |
| 2215 | 2750 | |
| 2216 | 2751 | case 0x98: /* CWDE/CBW */ |
| 2217 | - if (dflag) | |
| 2752 | +#ifdef TARGET_X86_64 | |
| 2753 | + if (dflag == 2) { | |
| 2754 | + gen_op_movslq_RAX_EAX(); | |
| 2755 | + } else | |
| 2756 | +#endif | |
| 2757 | + if (dflag == 1) | |
| 2218 | 2758 | gen_op_movswl_EAX_AX(); |
| 2219 | 2759 | else |
| 2220 | 2760 | gen_op_movsbw_AX_AL(); |
| 2221 | 2761 | break; |
| 2222 | 2762 | case 0x99: /* CDQ/CWD */ |
| 2223 | - if (dflag) | |
| 2763 | +#ifdef TARGET_X86_64 | |
| 2764 | + if (dflag == 2) { | |
| 2765 | + gen_op_movsqo_RDX_RAX(); | |
| 2766 | + } else | |
| 2767 | +#endif | |
| 2768 | + if (dflag == 1) | |
| 2224 | 2769 | gen_op_movslq_EDX_EAX(); |
| 2225 | 2770 | else |
| 2226 | 2771 | gen_op_movswl_DX_AX(); |
| ... | ... | @@ -2228,9 +2773,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2228 | 2773 | case 0x1af: /* imul Gv, Ev */ |
| 2229 | 2774 | case 0x69: /* imul Gv, Ev, I */ |
| 2230 | 2775 | case 0x6b: |
| 2231 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2776 | + ot = dflag + OT_WORD; | |
| 2232 | 2777 | modrm = ldub_code(s->pc++); |
| 2233 | - reg = ((modrm >> 3) & 7) + OR_EAX; | |
| 2778 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2779 | + if (b == 0x69) | |
| 2780 | + s->rip_offset = insn_const_size(ot); | |
| 2781 | + else if (b == 0x6b) | |
| 2782 | + s->rip_offset = 1; | |
| 2234 | 2783 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 2235 | 2784 | if (b == 0x69) { |
| 2236 | 2785 | val = insn_get(s, ot); |
| ... | ... | @@ -2242,6 +2791,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2242 | 2791 | gen_op_mov_TN_reg[ot][1][reg](); |
| 2243 | 2792 | } |
| 2244 | 2793 | |
| 2794 | +#ifdef TARGET_X86_64 | |
| 2795 | + if (ot == OT_QUAD) { | |
| 2796 | + gen_op_imulq_T0_T1(); | |
| 2797 | + } else | |
| 2798 | +#endif | |
| 2245 | 2799 | if (ot == OT_LONG) { |
| 2246 | 2800 | gen_op_imull_T0_T1(); |
| 2247 | 2801 | } else { |
| ... | ... | @@ -2255,12 +2809,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2255 | 2809 | if ((b & 1) == 0) |
| 2256 | 2810 | ot = OT_BYTE; |
| 2257 | 2811 | else |
| 2258 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2812 | + ot = dflag + OT_WORD; | |
| 2259 | 2813 | modrm = ldub_code(s->pc++); |
| 2260 | - reg = (modrm >> 3) & 7; | |
| 2814 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2261 | 2815 | mod = (modrm >> 6) & 3; |
| 2262 | 2816 | if (mod == 3) { |
| 2263 | - rm = modrm & 7; | |
| 2817 | + rm = (modrm & 7) | REX_B(s); | |
| 2264 | 2818 | gen_op_mov_TN_reg[ot][0][reg](); |
| 2265 | 2819 | gen_op_mov_TN_reg[ot][1][rm](); |
| 2266 | 2820 | gen_op_addl_T0_T1(); |
| ... | ... | @@ -2282,13 +2836,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2282 | 2836 | if ((b & 1) == 0) |
| 2283 | 2837 | ot = OT_BYTE; |
| 2284 | 2838 | else |
| 2285 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2839 | + ot = dflag + OT_WORD; | |
| 2286 | 2840 | modrm = ldub_code(s->pc++); |
| 2287 | - reg = (modrm >> 3) & 7; | |
| 2841 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2288 | 2842 | mod = (modrm >> 6) & 3; |
| 2289 | 2843 | gen_op_mov_TN_reg[ot][1][reg](); |
| 2290 | 2844 | if (mod == 3) { |
| 2291 | - rm = modrm & 7; | |
| 2845 | + rm = (modrm & 7) | REX_B(s); | |
| 2292 | 2846 | gen_op_mov_TN_reg[ot][0][rm](); |
| 2293 | 2847 | gen_op_cmpxchg_T0_T1_EAX_cc[ot](); |
| 2294 | 2848 | gen_op_mov_reg_T0[ot][rm](); |
| ... | ... | @@ -2314,25 +2868,37 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2314 | 2868 | /**************************/ |
| 2315 | 2869 | /* push/pop */ |
| 2316 | 2870 | case 0x50 ... 0x57: /* push */ |
| 2317 | - gen_op_mov_TN_reg[OT_LONG][0][b & 7](); | |
| 2871 | + gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)](); | |
| 2318 | 2872 | gen_push_T0(s); |
| 2319 | 2873 | break; |
| 2320 | 2874 | case 0x58 ... 0x5f: /* pop */ |
| 2321 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2875 | + if (CODE64(s)) { | |
| 2876 | + ot = dflag ? OT_QUAD : OT_WORD; | |
| 2877 | + } else { | |
| 2878 | + ot = dflag + OT_WORD; | |
| 2879 | + } | |
| 2322 | 2880 | gen_pop_T0(s); |
| 2323 | 2881 | /* NOTE: order is important for pop %sp */ |
| 2324 | 2882 | gen_pop_update(s); |
| 2325 | - gen_op_mov_reg_T0[ot][b & 7](); | |
| 2883 | + gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)](); | |
| 2326 | 2884 | break; |
| 2327 | 2885 | case 0x60: /* pusha */ |
| 2886 | + if (CODE64(s)) | |
| 2887 | + goto illegal_op; | |
| 2328 | 2888 | gen_pusha(s); |
| 2329 | 2889 | break; |
| 2330 | 2890 | case 0x61: /* popa */ |
| 2891 | + if (CODE64(s)) | |
| 2892 | + goto illegal_op; | |
| 2331 | 2893 | gen_popa(s); |
| 2332 | 2894 | break; |
| 2333 | 2895 | case 0x68: /* push Iv */ |
| 2334 | 2896 | case 0x6a: |
| 2335 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2897 | + if (CODE64(s)) { | |
| 2898 | + ot = dflag ? OT_QUAD : OT_WORD; | |
| 2899 | + } else { | |
| 2900 | + ot = dflag + OT_WORD; | |
| 2901 | + } | |
| 2336 | 2902 | if (b == 0x68) |
| 2337 | 2903 | val = insn_get(s, ot); |
| 2338 | 2904 | else |
| ... | ... | @@ -2341,18 +2907,22 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2341 | 2907 | gen_push_T0(s); |
| 2342 | 2908 | break; |
| 2343 | 2909 | case 0x8f: /* pop Ev */ |
| 2344 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2910 | + if (CODE64(s)) { | |
| 2911 | + ot = dflag ? OT_QUAD : OT_WORD; | |
| 2912 | + } else { | |
| 2913 | + ot = dflag + OT_WORD; | |
| 2914 | + } | |
| 2345 | 2915 | modrm = ldub_code(s->pc++); |
| 2346 | 2916 | mod = (modrm >> 6) & 3; |
| 2347 | 2917 | gen_pop_T0(s); |
| 2348 | 2918 | if (mod == 3) { |
| 2349 | 2919 | /* NOTE: order is important for pop %sp */ |
| 2350 | 2920 | gen_pop_update(s); |
| 2351 | - rm = modrm & 7; | |
| 2921 | + rm = (modrm & 7) | REX_B(s); | |
| 2352 | 2922 | gen_op_mov_reg_T0[ot][rm](); |
| 2353 | 2923 | } else { |
| 2354 | 2924 | /* NOTE: order is important too for MMU exceptions */ |
| 2355 | - s->popl_esp_hack = 2 << dflag; | |
| 2925 | + s->popl_esp_hack = 1 << ot; | |
| 2356 | 2926 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
| 2357 | 2927 | s->popl_esp_hack = 0; |
| 2358 | 2928 | gen_pop_update(s); |
| ... | ... | @@ -2360,6 +2930,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2360 | 2930 | break; |
| 2361 | 2931 | case 0xc8: /* enter */ |
| 2362 | 2932 | { |
| 2933 | + /* XXX: long mode support */ | |
| 2363 | 2934 | int level; |
| 2364 | 2935 | val = lduw_code(s->pc); |
| 2365 | 2936 | s->pc += 2; |
| ... | ... | @@ -2369,7 +2940,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2369 | 2940 | break; |
| 2370 | 2941 | case 0xc9: /* leave */ |
| 2371 | 2942 | /* XXX: exception not precise (ESP is updated before potential exception) */ |
| 2372 | - if (s->ss32) { | |
| 2943 | + /* XXX: may be invalid for 16 bit in long mode */ | |
| 2944 | + if (CODE64(s)) { | |
| 2945 | + gen_op_mov_TN_reg[OT_QUAD][0][R_EBP](); | |
| 2946 | + gen_op_mov_reg_T0[OT_QUAD][R_ESP](); | |
| 2947 | + } else if (s->ss32) { | |
| 2373 | 2948 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
| 2374 | 2949 | gen_op_mov_reg_T0[OT_LONG][R_ESP](); |
| 2375 | 2950 | } else { |
| ... | ... | @@ -2377,7 +2952,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2377 | 2952 | gen_op_mov_reg_T0[OT_WORD][R_ESP](); |
| 2378 | 2953 | } |
| 2379 | 2954 | gen_pop_T0(s); |
| 2380 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2955 | + if (CODE64(s)) { | |
| 2956 | + ot = dflag ? OT_QUAD : OT_WORD; | |
| 2957 | + } else { | |
| 2958 | + ot = dflag + OT_WORD; | |
| 2959 | + } | |
| 2381 | 2960 | gen_op_mov_reg_T0[ot][R_EBP](); |
| 2382 | 2961 | gen_pop_update(s); |
| 2383 | 2962 | break; |
| ... | ... | @@ -2385,6 +2964,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2385 | 2964 | case 0x0e: /* push cs */ |
| 2386 | 2965 | case 0x16: /* push ss */ |
| 2387 | 2966 | case 0x1e: /* push ds */ |
| 2967 | + if (CODE64(s)) | |
| 2968 | + goto illegal_op; | |
| 2388 | 2969 | gen_op_movl_T0_seg(b >> 3); |
| 2389 | 2970 | gen_push_T0(s); |
| 2390 | 2971 | break; |
| ... | ... | @@ -2396,6 +2977,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2396 | 2977 | case 0x07: /* pop es */ |
| 2397 | 2978 | case 0x17: /* pop ss */ |
| 2398 | 2979 | case 0x1f: /* pop ds */ |
| 2980 | + if (CODE64(s)) | |
| 2981 | + goto illegal_op; | |
| 2399 | 2982 | reg = b >> 3; |
| 2400 | 2983 | gen_pop_T0(s); |
| 2401 | 2984 | gen_movl_seg_T0(s, reg, pc_start - s->cs_base); |
| ... | ... | @@ -2409,7 +2992,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2409 | 2992 | s->tf = 0; |
| 2410 | 2993 | } |
| 2411 | 2994 | if (s->is_jmp) { |
| 2412 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 2995 | + gen_jmp_im(s->pc - s->cs_base); | |
| 2413 | 2996 | gen_eob(s); |
| 2414 | 2997 | } |
| 2415 | 2998 | break; |
| ... | ... | @@ -2419,7 +3002,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2419 | 3002 | gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base); |
| 2420 | 3003 | gen_pop_update(s); |
| 2421 | 3004 | if (s->is_jmp) { |
| 2422 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 3005 | + gen_jmp_im(s->pc - s->cs_base); | |
| 2423 | 3006 | gen_eob(s); |
| 2424 | 3007 | } |
| 2425 | 3008 | break; |
| ... | ... | @@ -2431,38 +3014,40 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2431 | 3014 | if ((b & 1) == 0) |
| 2432 | 3015 | ot = OT_BYTE; |
| 2433 | 3016 | else |
| 2434 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3017 | + ot = dflag + OT_WORD; | |
| 2435 | 3018 | modrm = ldub_code(s->pc++); |
| 2436 | - reg = (modrm >> 3) & 7; | |
| 3019 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2437 | 3020 | |
| 2438 | 3021 | /* generate a generic store */ |
| 2439 | - gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1); | |
| 3022 | + gen_ldst_modrm(s, modrm, ot, reg, 1); | |
| 2440 | 3023 | break; |
| 2441 | 3024 | case 0xc6: |
| 2442 | 3025 | case 0xc7: /* mov Ev, Iv */ |
| 2443 | 3026 | if ((b & 1) == 0) |
| 2444 | 3027 | ot = OT_BYTE; |
| 2445 | 3028 | else |
| 2446 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3029 | + ot = dflag + OT_WORD; | |
| 2447 | 3030 | modrm = ldub_code(s->pc++); |
| 2448 | 3031 | mod = (modrm >> 6) & 3; |
| 2449 | - if (mod != 3) | |
| 3032 | + if (mod != 3) { | |
| 3033 | + s->rip_offset = insn_const_size(ot); | |
| 2450 | 3034 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3035 | + } | |
| 2451 | 3036 | val = insn_get(s, ot); |
| 2452 | 3037 | gen_op_movl_T0_im(val); |
| 2453 | 3038 | if (mod != 3) |
| 2454 | 3039 | gen_op_st_T0_A0[ot + s->mem_index](); |
| 2455 | 3040 | else |
| 2456 | - gen_op_mov_reg_T0[ot][modrm & 7](); | |
| 3041 | + gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)](); | |
| 2457 | 3042 | break; |
| 2458 | 3043 | case 0x8a: |
| 2459 | 3044 | case 0x8b: /* mov Ev, Gv */ |
| 2460 | 3045 | if ((b & 1) == 0) |
| 2461 | 3046 | ot = OT_BYTE; |
| 2462 | 3047 | else |
| 2463 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3048 | + ot = OT_WORD + dflag; | |
| 2464 | 3049 | modrm = ldub_code(s->pc++); |
| 2465 | - reg = (modrm >> 3) & 7; | |
| 3050 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2466 | 3051 | |
| 2467 | 3052 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 2468 | 3053 | gen_op_mov_reg_T0[ot][reg](); |
| ... | ... | @@ -2483,7 +3068,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2483 | 3068 | s->tf = 0; |
| 2484 | 3069 | } |
| 2485 | 3070 | if (s->is_jmp) { |
| 2486 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 3071 | + gen_jmp_im(s->pc - s->cs_base); | |
| 2487 | 3072 | gen_eob(s); |
| 2488 | 3073 | } |
| 2489 | 3074 | break; |
| ... | ... | @@ -2494,9 +3079,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2494 | 3079 | if (reg >= 6) |
| 2495 | 3080 | goto illegal_op; |
| 2496 | 3081 | gen_op_movl_T0_seg(reg); |
| 2497 | - ot = OT_WORD; | |
| 2498 | - if (mod == 3 && dflag) | |
| 2499 | - ot = OT_LONG; | |
| 3082 | + if (mod == 3) | |
| 3083 | + ot = OT_WORD + dflag; | |
| 3084 | + else | |
| 3085 | + ot = OT_WORD; | |
| 2500 | 3086 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
| 2501 | 3087 | break; |
| 2502 | 3088 | |
| ... | ... | @@ -2511,9 +3097,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2511 | 3097 | /* ot is the size of source */ |
| 2512 | 3098 | ot = (b & 1) + OT_BYTE; |
| 2513 | 3099 | modrm = ldub_code(s->pc++); |
| 2514 | - reg = ((modrm >> 3) & 7) + OR_EAX; | |
| 3100 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2515 | 3101 | mod = (modrm >> 6) & 3; |
| 2516 | - rm = modrm & 7; | |
| 3102 | + rm = (modrm & 7) | REX_B(s); | |
| 2517 | 3103 | |
| 2518 | 3104 | if (mod == 3) { |
| 2519 | 3105 | gen_op_mov_TN_reg[ot][0][rm](); |
| ... | ... | @@ -2546,12 +3132,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2546 | 3132 | break; |
| 2547 | 3133 | |
| 2548 | 3134 | case 0x8d: /* lea */ |
| 2549 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3135 | + ot = dflag + OT_WORD; | |
| 2550 | 3136 | modrm = ldub_code(s->pc++); |
| 2551 | 3137 | mod = (modrm >> 6) & 3; |
| 2552 | 3138 | if (mod == 3) |
| 2553 | 3139 | goto illegal_op; |
| 2554 | - reg = (modrm >> 3) & 7; | |
| 3140 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2555 | 3141 | /* we must ensure that no segment is added */ |
| 2556 | 3142 | s->override = -1; |
| 2557 | 3143 | val = s->addseg; |
| ... | ... | @@ -2565,42 +3151,67 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2565 | 3151 | case 0xa1: |
| 2566 | 3152 | case 0xa2: /* mov Ov, EAX */ |
| 2567 | 3153 | case 0xa3: |
| 2568 | - if ((b & 1) == 0) | |
| 2569 | - ot = OT_BYTE; | |
| 2570 | - else | |
| 2571 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2572 | - if (s->aflag) | |
| 2573 | - offset_addr = insn_get(s, OT_LONG); | |
| 2574 | - else | |
| 2575 | - offset_addr = insn_get(s, OT_WORD); | |
| 2576 | - gen_op_movl_A0_im(offset_addr); | |
| 2577 | - /* handle override */ | |
| 2578 | 3154 | { |
| 2579 | - int override, must_add_seg; | |
| 2580 | - must_add_seg = s->addseg; | |
| 2581 | - if (s->override >= 0) { | |
| 2582 | - override = s->override; | |
| 2583 | - must_add_seg = 1; | |
| 2584 | - } else { | |
| 2585 | - override = R_DS; | |
| 3155 | + target_ulong offset_addr; | |
| 3156 | + | |
| 3157 | + if ((b & 1) == 0) | |
| 3158 | + ot = OT_BYTE; | |
| 3159 | + else | |
| 3160 | + ot = dflag + OT_WORD; | |
| 3161 | +#ifdef TARGET_X86_64 | |
| 3162 | + if (CODE64(s)) { | |
| 3163 | + offset_addr = ldq_code(s->pc); | |
| 3164 | + s->pc += 8; | |
| 3165 | + if (offset_addr == (int32_t)offset_addr) | |
| 3166 | + gen_op_movq_A0_im(offset_addr); | |
| 3167 | + else | |
| 3168 | + gen_op_movq_A0_im64(offset_addr >> 32, offset_addr); | |
| 3169 | + } else | |
| 3170 | +#endif | |
| 3171 | + { | |
| 3172 | + if (s->aflag) { | |
| 3173 | + offset_addr = insn_get(s, OT_LONG); | |
| 3174 | + } else { | |
| 3175 | + offset_addr = insn_get(s, OT_WORD); | |
| 3176 | + } | |
| 3177 | + gen_op_movl_A0_im(offset_addr); | |
| 3178 | + } | |
| 3179 | + /* handle override */ | |
| 3180 | + { | |
| 3181 | + int override, must_add_seg; | |
| 3182 | + must_add_seg = s->addseg; | |
| 3183 | + if (s->override >= 0) { | |
| 3184 | + override = s->override; | |
| 3185 | + must_add_seg = 1; | |
| 3186 | + } else { | |
| 3187 | + override = R_DS; | |
| 3188 | + } | |
| 3189 | + if (must_add_seg) { | |
| 3190 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 3191 | + } | |
| 2586 | 3192 | } |
| 2587 | - if (must_add_seg) { | |
| 2588 | - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | |
| 3193 | + if ((b & 2) == 0) { | |
| 3194 | + gen_op_ld_T0_A0[ot + s->mem_index](); | |
| 3195 | + gen_op_mov_reg_T0[ot][R_EAX](); | |
| 3196 | + } else { | |
| 3197 | + gen_op_mov_TN_reg[ot][0][R_EAX](); | |
| 3198 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
| 2589 | 3199 | } |
| 2590 | 3200 | } |
| 2591 | - if ((b & 2) == 0) { | |
| 2592 | - gen_op_ld_T0_A0[ot + s->mem_index](); | |
| 2593 | - gen_op_mov_reg_T0[ot][R_EAX](); | |
| 2594 | - } else { | |
| 2595 | - gen_op_mov_TN_reg[ot][0][R_EAX](); | |
| 2596 | - gen_op_st_T0_A0[ot + s->mem_index](); | |
| 2597 | - } | |
| 2598 | 3201 | break; |
| 2599 | 3202 | case 0xd7: /* xlat */ |
| 2600 | - gen_op_movl_A0_reg[R_EBX](); | |
| 2601 | - gen_op_addl_A0_AL(); | |
| 2602 | - if (s->aflag == 0) | |
| 2603 | - gen_op_andl_A0_ffff(); | |
| 3203 | +#ifdef TARGET_X86_64 | |
| 3204 | + if (CODE64(s)) { | |
| 3205 | + gen_op_movq_A0_reg[R_EBX](); | |
| 3206 | + gen_op_addq_A0_AL(); | |
| 3207 | + } else | |
| 3208 | +#endif | |
| 3209 | + { | |
| 3210 | + gen_op_movl_A0_reg[R_EBX](); | |
| 3211 | + gen_op_addl_A0_AL(); | |
| 3212 | + if (s->aflag == 0) | |
| 3213 | + gen_op_andl_A0_ffff(); | |
| 3214 | + } | |
| 2604 | 3215 | /* handle override */ |
| 2605 | 3216 | { |
| 2606 | 3217 | int override, must_add_seg; |
| ... | ... | @@ -2622,19 +3233,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2622 | 3233 | case 0xb0 ... 0xb7: /* mov R, Ib */ |
| 2623 | 3234 | val = insn_get(s, OT_BYTE); |
| 2624 | 3235 | gen_op_movl_T0_im(val); |
| 2625 | - gen_op_mov_reg_T0[OT_BYTE][b & 7](); | |
| 3236 | + gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)](); | |
| 2626 | 3237 | break; |
| 2627 | 3238 | case 0xb8 ... 0xbf: /* mov R, Iv */ |
| 2628 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2629 | - val = insn_get(s, ot); | |
| 2630 | - reg = OR_EAX + (b & 7); | |
| 2631 | - gen_op_movl_T0_im(val); | |
| 2632 | - gen_op_mov_reg_T0[ot][reg](); | |
| 3239 | +#ifdef TARGET_X86_64 | |
| 3240 | + if (dflag == 2) { | |
| 3241 | + uint64_t tmp; | |
| 3242 | + /* 64 bit case */ | |
| 3243 | + tmp = ldq_code(s->pc); | |
| 3244 | + s->pc += 8; | |
| 3245 | + reg = (b & 7) | REX_B(s); | |
| 3246 | + gen_movtl_T0_im(tmp); | |
| 3247 | + gen_op_mov_reg_T0[OT_QUAD][reg](); | |
| 3248 | + } else | |
| 3249 | +#endif | |
| 3250 | + { | |
| 3251 | + ot = dflag ? OT_LONG : OT_WORD; | |
| 3252 | + val = insn_get(s, ot); | |
| 3253 | + reg = (b & 7) | REX_B(s); | |
| 3254 | + gen_op_movl_T0_im(val); | |
| 3255 | + gen_op_mov_reg_T0[ot][reg](); | |
| 3256 | + } | |
| 2633 | 3257 | break; |
| 2634 | 3258 | |
| 2635 | 3259 | case 0x91 ... 0x97: /* xchg R, EAX */ |
| 2636 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 2637 | - reg = b & 7; | |
| 3260 | + ot = dflag + OT_WORD; | |
| 3261 | + reg = (b & 7) | REX_B(s); | |
| 2638 | 3262 | rm = R_EAX; |
| 2639 | 3263 | goto do_xchg_reg; |
| 2640 | 3264 | case 0x86: |
| ... | ... | @@ -2642,12 +3266,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2642 | 3266 | if ((b & 1) == 0) |
| 2643 | 3267 | ot = OT_BYTE; |
| 2644 | 3268 | else |
| 2645 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3269 | + ot = dflag + OT_WORD; | |
| 2646 | 3270 | modrm = ldub_code(s->pc++); |
| 2647 | - reg = (modrm >> 3) & 7; | |
| 3271 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2648 | 3272 | mod = (modrm >> 6) & 3; |
| 2649 | 3273 | if (mod == 3) { |
| 2650 | - rm = modrm & 7; | |
| 3274 | + rm = (modrm & 7) | REX_B(s); | |
| 2651 | 3275 | do_xchg_reg: |
| 2652 | 3276 | gen_op_mov_TN_reg[ot][0][reg](); |
| 2653 | 3277 | gen_op_mov_TN_reg[ot][1][rm](); |
| ... | ... | @@ -2667,9 +3291,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2667 | 3291 | } |
| 2668 | 3292 | break; |
| 2669 | 3293 | case 0xc4: /* les Gv */ |
| 3294 | + if (CODE64(s)) | |
| 3295 | + goto illegal_op; | |
| 2670 | 3296 | op = R_ES; |
| 2671 | 3297 | goto do_lxx; |
| 2672 | 3298 | case 0xc5: /* lds Gv */ |
| 3299 | + if (CODE64(s)) | |
| 3300 | + goto illegal_op; | |
| 2673 | 3301 | op = R_DS; |
| 2674 | 3302 | goto do_lxx; |
| 2675 | 3303 | case 0x1b2: /* lss Gv */ |
| ... | ... | @@ -2683,7 +3311,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2683 | 3311 | do_lxx: |
| 2684 | 3312 | ot = dflag ? OT_LONG : OT_WORD; |
| 2685 | 3313 | modrm = ldub_code(s->pc++); |
| 2686 | - reg = (modrm >> 3) & 7; | |
| 3314 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2687 | 3315 | mod = (modrm >> 6) & 3; |
| 2688 | 3316 | if (mod == 3) |
| 2689 | 3317 | goto illegal_op; |
| ... | ... | @@ -2696,7 +3324,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2696 | 3324 | /* then put the data */ |
| 2697 | 3325 | gen_op_mov_reg_T1[ot][reg](); |
| 2698 | 3326 | if (s->is_jmp) { |
| 2699 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 3327 | + gen_jmp_im(s->pc - s->cs_base); | |
| 2700 | 3328 | gen_eob(s); |
| 2701 | 3329 | } |
| 2702 | 3330 | break; |
| ... | ... | @@ -2712,18 +3340,20 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2712 | 3340 | if ((b & 1) == 0) |
| 2713 | 3341 | ot = OT_BYTE; |
| 2714 | 3342 | else |
| 2715 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3343 | + ot = dflag + OT_WORD; | |
| 2716 | 3344 | |
| 2717 | 3345 | modrm = ldub_code(s->pc++); |
| 2718 | 3346 | mod = (modrm >> 6) & 3; |
| 2719 | - rm = modrm & 7; | |
| 2720 | 3347 | op = (modrm >> 3) & 7; |
| 2721 | 3348 | |
| 2722 | 3349 | if (mod != 3) { |
| 3350 | + if (shift == 2) { | |
| 3351 | + s->rip_offset = 1; | |
| 3352 | + } | |
| 2723 | 3353 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 2724 | 3354 | opreg = OR_TMP0; |
| 2725 | 3355 | } else { |
| 2726 | - opreg = rm + OR_EAX; | |
| 3356 | + opreg = (modrm & 7) | REX_B(s); | |
| 2727 | 3357 | } |
| 2728 | 3358 | |
| 2729 | 3359 | /* simpler op */ |
| ... | ... | @@ -2764,11 +3394,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2764 | 3394 | op = 1; |
| 2765 | 3395 | shift = 0; |
| 2766 | 3396 | do_shiftd: |
| 2767 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3397 | + ot = dflag + OT_WORD; | |
| 2768 | 3398 | modrm = ldub_code(s->pc++); |
| 2769 | 3399 | mod = (modrm >> 6) & 3; |
| 2770 | - rm = modrm & 7; | |
| 2771 | - reg = (modrm >> 3) & 7; | |
| 3400 | + rm = (modrm & 7) | REX_B(s); | |
| 3401 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 2772 | 3402 | |
| 2773 | 3403 | if (mod != 3) { |
| 2774 | 3404 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| ... | ... | @@ -2780,7 +3410,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2780 | 3410 | |
| 2781 | 3411 | if (shift) { |
| 2782 | 3412 | val = ldub_code(s->pc++); |
| 2783 | - val &= 0x1f; | |
| 3413 | + if (ot == OT_QUAD) | |
| 3414 | + val &= 0x3f; | |
| 3415 | + else | |
| 3416 | + val &= 0x1f; | |
| 2784 | 3417 | if (val) { |
| 2785 | 3418 | if (mod == 3) |
| 2786 | 3419 | gen_op_shiftd_T0_T1_im_cc[ot][op](val); |
| ... | ... | @@ -2970,7 +3603,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 2970 | 3603 | /* check exceptions (FreeBSD FPU probe) */ |
| 2971 | 3604 | if (s->cc_op != CC_OP_DYNAMIC) |
| 2972 | 3605 | gen_op_set_cc_op(s->cc_op); |
| 2973 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 3606 | + gen_jmp_im(pc_start - s->cs_base); | |
| 2974 | 3607 | gen_op_fwait(); |
| 2975 | 3608 | break; |
| 2976 | 3609 | default: |
| ... | ... | @@ -3257,7 +3890,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3257 | 3890 | if ((b & 1) == 0) |
| 3258 | 3891 | ot = OT_BYTE; |
| 3259 | 3892 | else |
| 3260 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3893 | + ot = dflag + OT_WORD; | |
| 3261 | 3894 | |
| 3262 | 3895 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 3263 | 3896 | gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| ... | ... | @@ -3271,7 +3904,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3271 | 3904 | if ((b & 1) == 0) |
| 3272 | 3905 | ot = OT_BYTE; |
| 3273 | 3906 | else |
| 3274 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3907 | + ot = dflag + OT_WORD; | |
| 3275 | 3908 | |
| 3276 | 3909 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 3277 | 3910 | gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| ... | ... | @@ -3284,7 +3917,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3284 | 3917 | if ((b & 1) == 0) |
| 3285 | 3918 | ot = OT_BYTE; |
| 3286 | 3919 | else |
| 3287 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3920 | + ot = dflag + OT_WORD; | |
| 3288 | 3921 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
| 3289 | 3922 | gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
| 3290 | 3923 | } else { |
| ... | ... | @@ -3296,7 +3929,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3296 | 3929 | if ((b & 1) == 0) |
| 3297 | 3930 | ot = OT_BYTE; |
| 3298 | 3931 | else |
| 3299 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3932 | + ot = dflag + OT_WORD; | |
| 3300 | 3933 | if (prefixes & PREFIX_REPNZ) { |
| 3301 | 3934 | gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); |
| 3302 | 3935 | } else if (prefixes & PREFIX_REPZ) { |
| ... | ... | @@ -3312,7 +3945,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3312 | 3945 | if ((b & 1) == 0) |
| 3313 | 3946 | ot = OT_BYTE; |
| 3314 | 3947 | else |
| 3315 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3948 | + ot = dflag + OT_WORD; | |
| 3316 | 3949 | if (prefixes & PREFIX_REPNZ) { |
| 3317 | 3950 | gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1); |
| 3318 | 3951 | } else if (prefixes & PREFIX_REPZ) { |
| ... | ... | @@ -3427,7 +4060,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3427 | 4060 | if (s->pe && !s->vm86) { |
| 3428 | 4061 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3429 | 4062 | gen_op_set_cc_op(s->cc_op); |
| 3430 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4063 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3431 | 4064 | gen_op_lret_protected(s->dflag, val); |
| 3432 | 4065 | } else { |
| 3433 | 4066 | gen_stack_A0(s); |
| ... | ... | @@ -3465,7 +4098,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3465 | 4098 | } else { |
| 3466 | 4099 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3467 | 4100 | gen_op_set_cc_op(s->cc_op); |
| 3468 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4101 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3469 | 4102 | gen_op_iret_protected(s->dflag, s->pc - s->cs_base); |
| 3470 | 4103 | s->cc_op = CC_OP_EFLAGS; |
| 3471 | 4104 | } |
| ... | ... | @@ -3473,72 +4106,79 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3473 | 4106 | break; |
| 3474 | 4107 | case 0xe8: /* call im */ |
| 3475 | 4108 | { |
| 3476 | - unsigned int next_eip; | |
| 3477 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3478 | - val = insn_get(s, ot); | |
| 4109 | + if (dflag) | |
| 4110 | + tval = (int32_t)insn_get(s, OT_LONG); | |
| 4111 | + else | |
| 4112 | + tval = (int16_t)insn_get(s, OT_WORD); | |
| 3479 | 4113 | next_eip = s->pc - s->cs_base; |
| 3480 | - val += next_eip; | |
| 4114 | + tval += next_eip; | |
| 3481 | 4115 | if (s->dflag == 0) |
| 3482 | - val &= 0xffff; | |
| 3483 | - gen_op_movl_T0_im(next_eip); | |
| 4116 | + tval &= 0xffff; | |
| 4117 | + gen_movtl_T0_im(next_eip); | |
| 3484 | 4118 | gen_push_T0(s); |
| 3485 | - gen_jmp(s, val); | |
| 4119 | + gen_jmp(s, tval); | |
| 3486 | 4120 | } |
| 3487 | 4121 | break; |
| 3488 | 4122 | case 0x9a: /* lcall im */ |
| 3489 | 4123 | { |
| 3490 | 4124 | unsigned int selector, offset; |
| 3491 | - | |
| 4125 | + | |
| 4126 | + if (CODE64(s)) | |
| 4127 | + goto illegal_op; | |
| 3492 | 4128 | ot = dflag ? OT_LONG : OT_WORD; |
| 3493 | 4129 | offset = insn_get(s, ot); |
| 3494 | 4130 | selector = insn_get(s, OT_WORD); |
| 3495 | 4131 | |
| 3496 | 4132 | gen_op_movl_T0_im(selector); |
| 3497 | - gen_op_movl_T1_im(offset); | |
| 4133 | + gen_op_movl_T1_imu(offset); | |
| 3498 | 4134 | } |
| 3499 | 4135 | goto do_lcall; |
| 3500 | 4136 | case 0xe9: /* jmp */ |
| 3501 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 3502 | - val = insn_get(s, ot); | |
| 3503 | - val += s->pc - s->cs_base; | |
| 4137 | + if (dflag) | |
| 4138 | + tval = (int32_t)insn_get(s, OT_LONG); | |
| 4139 | + else | |
| 4140 | + tval = (int16_t)insn_get(s, OT_WORD); | |
| 4141 | + tval += s->pc - s->cs_base; | |
| 3504 | 4142 | if (s->dflag == 0) |
| 3505 | - val = val & 0xffff; | |
| 3506 | - gen_jmp(s, val); | |
| 4143 | + tval &= 0xffff; | |
| 4144 | + gen_jmp(s, tval); | |
| 3507 | 4145 | break; |
| 3508 | 4146 | case 0xea: /* ljmp im */ |
| 3509 | 4147 | { |
| 3510 | 4148 | unsigned int selector, offset; |
| 3511 | 4149 | |
| 4150 | + if (CODE64(s)) | |
| 4151 | + goto illegal_op; | |
| 3512 | 4152 | ot = dflag ? OT_LONG : OT_WORD; |
| 3513 | 4153 | offset = insn_get(s, ot); |
| 3514 | 4154 | selector = insn_get(s, OT_WORD); |
| 3515 | 4155 | |
| 3516 | 4156 | gen_op_movl_T0_im(selector); |
| 3517 | - gen_op_movl_T1_im(offset); | |
| 4157 | + gen_op_movl_T1_imu(offset); | |
| 3518 | 4158 | } |
| 3519 | 4159 | goto do_ljmp; |
| 3520 | 4160 | case 0xeb: /* jmp Jb */ |
| 3521 | - val = (int8_t)insn_get(s, OT_BYTE); | |
| 3522 | - val += s->pc - s->cs_base; | |
| 4161 | + tval = (int8_t)insn_get(s, OT_BYTE); | |
| 4162 | + tval += s->pc - s->cs_base; | |
| 3523 | 4163 | if (s->dflag == 0) |
| 3524 | - val = val & 0xffff; | |
| 3525 | - gen_jmp(s, val); | |
| 4164 | + tval &= 0xffff; | |
| 4165 | + gen_jmp(s, tval); | |
| 3526 | 4166 | break; |
| 3527 | 4167 | case 0x70 ... 0x7f: /* jcc Jb */ |
| 3528 | - val = (int8_t)insn_get(s, OT_BYTE); | |
| 4168 | + tval = (int8_t)insn_get(s, OT_BYTE); | |
| 3529 | 4169 | goto do_jcc; |
| 3530 | 4170 | case 0x180 ... 0x18f: /* jcc Jv */ |
| 3531 | 4171 | if (dflag) { |
| 3532 | - val = insn_get(s, OT_LONG); | |
| 4172 | + tval = (int32_t)insn_get(s, OT_LONG); | |
| 3533 | 4173 | } else { |
| 3534 | - val = (int16_t)insn_get(s, OT_WORD); | |
| 4174 | + tval = (int16_t)insn_get(s, OT_WORD); | |
| 3535 | 4175 | } |
| 3536 | 4176 | do_jcc: |
| 3537 | 4177 | next_eip = s->pc - s->cs_base; |
| 3538 | - val += next_eip; | |
| 4178 | + tval += next_eip; | |
| 3539 | 4179 | if (s->dflag == 0) |
| 3540 | - val &= 0xffff; | |
| 3541 | - gen_jcc(s, b, val, next_eip); | |
| 4180 | + tval &= 0xffff; | |
| 4181 | + gen_jcc(s, b, tval, next_eip); | |
| 3542 | 4182 | break; |
| 3543 | 4183 | |
| 3544 | 4184 | case 0x190 ... 0x19f: /* setcc Gv */ |
| ... | ... | @@ -3547,16 +4187,16 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3547 | 4187 | gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
| 3548 | 4188 | break; |
| 3549 | 4189 | case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
| 3550 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 4190 | + ot = dflag + OT_WORD; | |
| 3551 | 4191 | modrm = ldub_code(s->pc++); |
| 3552 | - reg = (modrm >> 3) & 7; | |
| 4192 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 3553 | 4193 | mod = (modrm >> 6) & 3; |
| 3554 | 4194 | gen_setcc(s, b); |
| 3555 | 4195 | if (mod != 3) { |
| 3556 | 4196 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3557 | 4197 | gen_op_ld_T1_A0[ot + s->mem_index](); |
| 3558 | 4198 | } else { |
| 3559 | - rm = modrm & 7; | |
| 4199 | + rm = (modrm & 7) | REX_B(s); | |
| 3560 | 4200 | gen_op_mov_TN_reg[ot][1][rm](); |
| 3561 | 4201 | } |
| 3562 | 4202 | gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg](); |
| ... | ... | @@ -3603,11 +4243,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3603 | 4243 | gen_pop_update(s); |
| 3604 | 4244 | s->cc_op = CC_OP_EFLAGS; |
| 3605 | 4245 | /* abort translation because TF flag may change */ |
| 3606 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4246 | + gen_jmp_im(s->pc - s->cs_base); | |
| 3607 | 4247 | gen_eob(s); |
| 3608 | 4248 | } |
| 3609 | 4249 | break; |
| 3610 | 4250 | case 0x9e: /* sahf */ |
| 4251 | + if (CODE64(s)) | |
| 4252 | + goto illegal_op; | |
| 3611 | 4253 | gen_op_mov_TN_reg[OT_BYTE][0][R_AH](); |
| 3612 | 4254 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3613 | 4255 | gen_op_set_cc_op(s->cc_op); |
| ... | ... | @@ -3615,6 +4257,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3615 | 4257 | s->cc_op = CC_OP_EFLAGS; |
| 3616 | 4258 | break; |
| 3617 | 4259 | case 0x9f: /* lahf */ |
| 4260 | + if (CODE64(s)) | |
| 4261 | + goto illegal_op; | |
| 3618 | 4262 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3619 | 4263 | gen_op_set_cc_op(s->cc_op); |
| 3620 | 4264 | gen_op_movl_T0_eflags(); |
| ... | ... | @@ -3648,12 +4292,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3648 | 4292 | /************************/ |
| 3649 | 4293 | /* bit operations */ |
| 3650 | 4294 | case 0x1ba: /* bt/bts/btr/btc Gv, im */ |
| 3651 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 4295 | + ot = dflag + OT_WORD; | |
| 3652 | 4296 | modrm = ldub_code(s->pc++); |
| 3653 | - op = (modrm >> 3) & 7; | |
| 4297 | + op = ((modrm >> 3) & 7) | rex_r; | |
| 3654 | 4298 | mod = (modrm >> 6) & 3; |
| 3655 | - rm = modrm & 7; | |
| 4299 | + rm = (modrm & 7) | REX_B(s); | |
| 3656 | 4300 | if (mod != 3) { |
| 4301 | + s->rip_offset = 1; | |
| 3657 | 4302 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3658 | 4303 | gen_op_ld_T0_A0[ot + s->mem_index](); |
| 3659 | 4304 | } else { |
| ... | ... | @@ -3687,19 +4332,16 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3687 | 4332 | case 0x1bb: /* btc */ |
| 3688 | 4333 | op = 3; |
| 3689 | 4334 | do_btx: |
| 3690 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 4335 | + ot = dflag + OT_WORD; | |
| 3691 | 4336 | modrm = ldub_code(s->pc++); |
| 3692 | - reg = (modrm >> 3) & 7; | |
| 4337 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 3693 | 4338 | mod = (modrm >> 6) & 3; |
| 3694 | - rm = modrm & 7; | |
| 4339 | + rm = (modrm & 7) | REX_B(s); | |
| 3695 | 4340 | gen_op_mov_TN_reg[OT_LONG][1][reg](); |
| 3696 | 4341 | if (mod != 3) { |
| 3697 | 4342 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 3698 | 4343 | /* specific case: we need to add a displacement */ |
| 3699 | - if (ot == OT_WORD) | |
| 3700 | - gen_op_add_bitw_A0_T1(); | |
| 3701 | - else | |
| 3702 | - gen_op_add_bitl_A0_T1(); | |
| 4344 | + gen_op_add_bit_A0_T1[ot - OT_WORD](); | |
| 3703 | 4345 | gen_op_ld_T0_A0[ot + s->mem_index](); |
| 3704 | 4346 | } else { |
| 3705 | 4347 | gen_op_mov_TN_reg[ot][0][rm](); |
| ... | ... | @@ -3716,9 +4358,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3716 | 4358 | break; |
| 3717 | 4359 | case 0x1bc: /* bsf */ |
| 3718 | 4360 | case 0x1bd: /* bsr */ |
| 3719 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 4361 | + ot = dflag + OT_WORD; | |
| 3720 | 4362 | modrm = ldub_code(s->pc++); |
| 3721 | - reg = (modrm >> 3) & 7; | |
| 4363 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 3722 | 4364 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 3723 | 4365 | /* NOTE: in order to handle the 0 case, we must load the |
| 3724 | 4366 | result. It could be optimized with a generated jump */ |
| ... | ... | @@ -3730,35 +4372,47 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3730 | 4372 | /************************/ |
| 3731 | 4373 | /* bcd */ |
| 3732 | 4374 | case 0x27: /* daa */ |
| 4375 | + if (CODE64(s)) | |
| 4376 | + goto illegal_op; | |
| 3733 | 4377 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3734 | 4378 | gen_op_set_cc_op(s->cc_op); |
| 3735 | 4379 | gen_op_daa(); |
| 3736 | 4380 | s->cc_op = CC_OP_EFLAGS; |
| 3737 | 4381 | break; |
| 3738 | 4382 | case 0x2f: /* das */ |
| 4383 | + if (CODE64(s)) | |
| 4384 | + goto illegal_op; | |
| 3739 | 4385 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3740 | 4386 | gen_op_set_cc_op(s->cc_op); |
| 3741 | 4387 | gen_op_das(); |
| 3742 | 4388 | s->cc_op = CC_OP_EFLAGS; |
| 3743 | 4389 | break; |
| 3744 | 4390 | case 0x37: /* aaa */ |
| 4391 | + if (CODE64(s)) | |
| 4392 | + goto illegal_op; | |
| 3745 | 4393 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3746 | 4394 | gen_op_set_cc_op(s->cc_op); |
| 3747 | 4395 | gen_op_aaa(); |
| 3748 | 4396 | s->cc_op = CC_OP_EFLAGS; |
| 3749 | 4397 | break; |
| 3750 | 4398 | case 0x3f: /* aas */ |
| 4399 | + if (CODE64(s)) | |
| 4400 | + goto illegal_op; | |
| 3751 | 4401 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3752 | 4402 | gen_op_set_cc_op(s->cc_op); |
| 3753 | 4403 | gen_op_aas(); |
| 3754 | 4404 | s->cc_op = CC_OP_EFLAGS; |
| 3755 | 4405 | break; |
| 3756 | 4406 | case 0xd4: /* aam */ |
| 4407 | + if (CODE64(s)) | |
| 4408 | + goto illegal_op; | |
| 3757 | 4409 | val = ldub_code(s->pc++); |
| 3758 | 4410 | gen_op_aam(val); |
| 3759 | 4411 | s->cc_op = CC_OP_LOGICB; |
| 3760 | 4412 | break; |
| 3761 | 4413 | case 0xd5: /* aad */ |
| 4414 | + if (CODE64(s)) | |
| 4415 | + goto illegal_op; | |
| 3762 | 4416 | val = ldub_code(s->pc++); |
| 3763 | 4417 | gen_op_aad(val); |
| 3764 | 4418 | s->cc_op = CC_OP_LOGICB; |
| ... | ... | @@ -3766,6 +4420,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3766 | 4420 | /************************/ |
| 3767 | 4421 | /* misc */ |
| 3768 | 4422 | case 0x90: /* nop */ |
| 4423 | + /* XXX: xchg + rex handling */ | |
| 3769 | 4424 | /* XXX: correct lock test for all insn */ |
| 3770 | 4425 | if (prefixes & PREFIX_LOCK) |
| 3771 | 4426 | goto illegal_op; |
| ... | ... | @@ -3777,7 +4432,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3777 | 4432 | } else { |
| 3778 | 4433 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3779 | 4434 | gen_op_set_cc_op(s->cc_op); |
| 3780 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4435 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3781 | 4436 | gen_op_fwait(); |
| 3782 | 4437 | } |
| 3783 | 4438 | break; |
| ... | ... | @@ -3793,12 +4448,19 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3793 | 4448 | } |
| 3794 | 4449 | break; |
| 3795 | 4450 | case 0xce: /* into */ |
| 4451 | + if (CODE64(s)) | |
| 4452 | + goto illegal_op; | |
| 3796 | 4453 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3797 | 4454 | gen_op_set_cc_op(s->cc_op); |
| 3798 | 4455 | gen_op_into(s->pc - s->cs_base); |
| 3799 | 4456 | break; |
| 3800 | 4457 | case 0xf1: /* icebp (undocumented, exits to external debugger) */ |
| 4458 | +#if 0 | |
| 3801 | 4459 | gen_debug(s, pc_start - s->cs_base); |
| 4460 | +#else | |
| 4461 | + /* test ! */ | |
| 4462 | + cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_PCALL); | |
| 4463 | +#endif | |
| 3802 | 4464 | break; |
| 3803 | 4465 | case 0xfa: /* cli */ |
| 3804 | 4466 | if (!s->vm86) { |
| ... | ... | @@ -3826,7 +4488,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3826 | 4488 | if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK)) |
| 3827 | 4489 | gen_op_set_inhibit_irq(); |
| 3828 | 4490 | /* give a chance to handle pending irqs */ |
| 3829 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4491 | + gen_jmp_im(s->pc - s->cs_base); | |
| 3830 | 4492 | gen_eob(s); |
| 3831 | 4493 | } else { |
| 3832 | 4494 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| ... | ... | @@ -3840,6 +4502,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3840 | 4502 | } |
| 3841 | 4503 | break; |
| 3842 | 4504 | case 0x62: /* bound */ |
| 4505 | + if (CODE64(s)) | |
| 4506 | + goto illegal_op; | |
| 3843 | 4507 | ot = dflag ? OT_LONG : OT_WORD; |
| 3844 | 4508 | modrm = ldub_code(s->pc++); |
| 3845 | 4509 | reg = (modrm >> 3) & 7; |
| ... | ... | @@ -3848,18 +4512,30 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3848 | 4512 | goto illegal_op; |
| 3849 | 4513 | gen_op_mov_TN_reg[ot][0][reg](); |
| 3850 | 4514 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 4515 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3851 | 4516 | if (ot == OT_WORD) |
| 3852 | - gen_op_boundw(pc_start - s->cs_base); | |
| 4517 | + gen_op_boundw(); | |
| 3853 | 4518 | else |
| 3854 | - gen_op_boundl(pc_start - s->cs_base); | |
| 4519 | + gen_op_boundl(); | |
| 3855 | 4520 | break; |
| 3856 | 4521 | case 0x1c8 ... 0x1cf: /* bswap reg */ |
| 3857 | - reg = b & 7; | |
| 3858 | - gen_op_mov_TN_reg[OT_LONG][0][reg](); | |
| 3859 | - gen_op_bswapl_T0(); | |
| 3860 | - gen_op_mov_reg_T0[OT_LONG][reg](); | |
| 4522 | + reg = (b & 7) | REX_B(s); | |
| 4523 | +#ifdef TARGET_X86_64 | |
| 4524 | + if (dflag == 2) { | |
| 4525 | + gen_op_mov_TN_reg[OT_QUAD][0][reg](); | |
| 4526 | + gen_op_bswapq_T0(); | |
| 4527 | + gen_op_mov_reg_T0[OT_QUAD][reg](); | |
| 4528 | + } else | |
| 4529 | +#endif | |
| 4530 | + { | |
| 4531 | + gen_op_mov_TN_reg[OT_LONG][0][reg](); | |
| 4532 | + gen_op_bswapl_T0(); | |
| 4533 | + gen_op_mov_reg_T0[OT_LONG][reg](); | |
| 4534 | + } | |
| 3861 | 4535 | break; |
| 3862 | 4536 | case 0xd6: /* salc */ |
| 4537 | + if (CODE64(s)) | |
| 4538 | + goto illegal_op; | |
| 3863 | 4539 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3864 | 4540 | gen_op_set_cc_op(s->cc_op); |
| 3865 | 4541 | gen_op_salc(); |
| ... | ... | @@ -3871,13 +4547,32 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3871 | 4547 | /* FALL THRU */ |
| 3872 | 4548 | case 0xe2: /* loop */ |
| 3873 | 4549 | case 0xe3: /* jecxz */ |
| 3874 | - val = (int8_t)insn_get(s, OT_BYTE); | |
| 3875 | - next_eip = s->pc - s->cs_base; | |
| 3876 | - val += next_eip; | |
| 3877 | - if (s->dflag == 0) | |
| 3878 | - val &= 0xffff; | |
| 3879 | - gen_op_loop[s->aflag][b & 3](val, next_eip); | |
| 3880 | - gen_eob(s); | |
| 4550 | + { | |
| 4551 | + int l1, l2; | |
| 4552 | + | |
| 4553 | + tval = (int8_t)insn_get(s, OT_BYTE); | |
| 4554 | + next_eip = s->pc - s->cs_base; | |
| 4555 | + tval += next_eip; | |
| 4556 | + if (s->dflag == 0) | |
| 4557 | + tval &= 0xffff; | |
| 4558 | + | |
| 4559 | + l1 = gen_new_label(); | |
| 4560 | + l2 = gen_new_label(); | |
| 4561 | + b &= 3; | |
| 4562 | + if (b == 3) { | |
| 4563 | + gen_op_jz_ecx[s->aflag](l1); | |
| 4564 | + } else { | |
| 4565 | + gen_op_dec_ECX[s->aflag](); | |
| 4566 | + gen_op_loop[s->aflag][b](l1); | |
| 4567 | + } | |
| 4568 | + | |
| 4569 | + gen_jmp_im(next_eip); | |
| 4570 | + gen_op_jmp_label(l2); | |
| 4571 | + gen_set_label(l1); | |
| 4572 | + gen_jmp_im(tval); | |
| 4573 | + gen_set_label(l2); | |
| 4574 | + gen_eob(s); | |
| 4575 | + } | |
| 3881 | 4576 | break; |
| 3882 | 4577 | case 0x130: /* wrmsr */ |
| 3883 | 4578 | case 0x132: /* rdmsr */ |
| ... | ... | @@ -3894,6 +4589,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3894 | 4589 | gen_op_rdtsc(); |
| 3895 | 4590 | break; |
| 3896 | 4591 | case 0x134: /* sysenter */ |
| 4592 | + if (CODE64(s)) | |
| 4593 | + goto illegal_op; | |
| 3897 | 4594 | if (!s->pe) { |
| 3898 | 4595 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3899 | 4596 | } else { |
| ... | ... | @@ -3901,12 +4598,14 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3901 | 4598 | gen_op_set_cc_op(s->cc_op); |
| 3902 | 4599 | s->cc_op = CC_OP_DYNAMIC; |
| 3903 | 4600 | } |
| 3904 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4601 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3905 | 4602 | gen_op_sysenter(); |
| 3906 | 4603 | gen_eob(s); |
| 3907 | 4604 | } |
| 3908 | 4605 | break; |
| 3909 | 4606 | case 0x135: /* sysexit */ |
| 4607 | + if (CODE64(s)) | |
| 4608 | + goto illegal_op; | |
| 3910 | 4609 | if (!s->pe) { |
| 3911 | 4610 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3912 | 4611 | } else { |
| ... | ... | @@ -3914,11 +4613,36 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3914 | 4613 | gen_op_set_cc_op(s->cc_op); |
| 3915 | 4614 | s->cc_op = CC_OP_DYNAMIC; |
| 3916 | 4615 | } |
| 3917 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4616 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3918 | 4617 | gen_op_sysexit(); |
| 3919 | 4618 | gen_eob(s); |
| 3920 | 4619 | } |
| 3921 | 4620 | break; |
| 4621 | +#ifdef TARGET_X86_64 | |
| 4622 | + case 0x105: /* syscall */ | |
| 4623 | + /* XXX: is it usable in real mode ? */ | |
| 4624 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
| 4625 | + gen_op_set_cc_op(s->cc_op); | |
| 4626 | + s->cc_op = CC_OP_DYNAMIC; | |
| 4627 | + } | |
| 4628 | + gen_jmp_im(pc_start - s->cs_base); | |
| 4629 | + gen_op_syscall(); | |
| 4630 | + gen_eob(s); | |
| 4631 | + break; | |
| 4632 | + case 0x107: /* sysret */ | |
| 4633 | + if (!s->pe) { | |
| 4634 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | |
| 4635 | + } else { | |
| 4636 | + if (s->cc_op != CC_OP_DYNAMIC) { | |
| 4637 | + gen_op_set_cc_op(s->cc_op); | |
| 4638 | + s->cc_op = CC_OP_DYNAMIC; | |
| 4639 | + } | |
| 4640 | + gen_jmp_im(pc_start - s->cs_base); | |
| 4641 | + gen_op_sysret(s->dflag); | |
| 4642 | + gen_eob(s); | |
| 4643 | + } | |
| 4644 | + break; | |
| 4645 | +#endif | |
| 3922 | 4646 | case 0x1a2: /* cpuid */ |
| 3923 | 4647 | gen_op_cpuid(); |
| 3924 | 4648 | break; |
| ... | ... | @@ -3928,7 +4652,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3928 | 4652 | } else { |
| 3929 | 4653 | if (s->cc_op != CC_OP_DYNAMIC) |
| 3930 | 4654 | gen_op_set_cc_op(s->cc_op); |
| 3931 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4655 | + gen_jmp_im(s->pc - s->cs_base); | |
| 3932 | 4656 | gen_op_hlt(); |
| 3933 | 4657 | s->is_jmp = 3; |
| 3934 | 4658 | } |
| ... | ... | @@ -3954,7 +4678,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3954 | 4678 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3955 | 4679 | } else { |
| 3956 | 4680 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 3957 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4681 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3958 | 4682 | gen_op_lldt_T0(); |
| 3959 | 4683 | } |
| 3960 | 4684 | break; |
| ... | ... | @@ -3974,7 +4698,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 3974 | 4698 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 3975 | 4699 | } else { |
| 3976 | 4700 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 3977 | - gen_op_jmp_im(pc_start - s->cs_base); | |
| 4701 | + gen_jmp_im(pc_start - s->cs_base); | |
| 3978 | 4702 | gen_op_ltr_T0(); |
| 3979 | 4703 | } |
| 3980 | 4704 | break; |
| ... | ... | @@ -4010,14 +4734,19 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4010 | 4734 | else |
| 4011 | 4735 | gen_op_movl_T0_env(offsetof(CPUX86State,idt.limit)); |
| 4012 | 4736 | gen_op_st_T0_A0[OT_WORD + s->mem_index](); |
| 4013 | - gen_op_addl_A0_im(2); | |
| 4737 | +#ifdef TARGET_X86_64 | |
| 4738 | + if (CODE64(s)) | |
| 4739 | + gen_op_addq_A0_im(2); | |
| 4740 | + else | |
| 4741 | +#endif | |
| 4742 | + gen_op_addl_A0_im(2); | |
| 4014 | 4743 | if (op == 0) |
| 4015 | - gen_op_movl_T0_env(offsetof(CPUX86State,gdt.base)); | |
| 4744 | + gen_op_movtl_T0_env(offsetof(CPUX86State,gdt.base)); | |
| 4016 | 4745 | else |
| 4017 | - gen_op_movl_T0_env(offsetof(CPUX86State,idt.base)); | |
| 4746 | + gen_op_movtl_T0_env(offsetof(CPUX86State,idt.base)); | |
| 4018 | 4747 | if (!s->dflag) |
| 4019 | 4748 | gen_op_andl_T0_im(0xffffff); |
| 4020 | - gen_op_st_T0_A0[OT_LONG + s->mem_index](); | |
| 4749 | + gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); | |
| 4021 | 4750 | break; |
| 4022 | 4751 | case 2: /* lgdt */ |
| 4023 | 4752 | case 3: /* lidt */ |
| ... | ... | @@ -4028,15 +4757,20 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4028 | 4757 | } else { |
| 4029 | 4758 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 4030 | 4759 | gen_op_ld_T1_A0[OT_WORD + s->mem_index](); |
| 4031 | - gen_op_addl_A0_im(2); | |
| 4032 | - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); | |
| 4760 | +#ifdef TARGET_X86_64 | |
| 4761 | + if (CODE64(s)) | |
| 4762 | + gen_op_addq_A0_im(2); | |
| 4763 | + else | |
| 4764 | +#endif | |
| 4765 | + gen_op_addl_A0_im(2); | |
| 4766 | + gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); | |
| 4033 | 4767 | if (!s->dflag) |
| 4034 | 4768 | gen_op_andl_T0_im(0xffffff); |
| 4035 | 4769 | if (op == 2) { |
| 4036 | - gen_op_movl_env_T0(offsetof(CPUX86State,gdt.base)); | |
| 4770 | + gen_op_movtl_env_T0(offsetof(CPUX86State,gdt.base)); | |
| 4037 | 4771 | gen_op_movl_env_T1(offsetof(CPUX86State,gdt.limit)); |
| 4038 | 4772 | } else { |
| 4039 | - gen_op_movl_env_T0(offsetof(CPUX86State,idt.base)); | |
| 4773 | + gen_op_movtl_env_T0(offsetof(CPUX86State,idt.base)); | |
| 4040 | 4774 | gen_op_movl_env_T1(offsetof(CPUX86State,idt.limit)); |
| 4041 | 4775 | } |
| 4042 | 4776 | } |
| ... | ... | @@ -4051,7 +4785,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4051 | 4785 | } else { |
| 4052 | 4786 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
| 4053 | 4787 | gen_op_lmsw_T0(); |
| 4054 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4788 | + gen_jmp_im(s->pc - s->cs_base); | |
| 4055 | 4789 | gen_eob(s); |
| 4056 | 4790 | } |
| 4057 | 4791 | break; |
| ... | ... | @@ -4059,12 +4793,25 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4059 | 4793 | if (s->cpl != 0) { |
| 4060 | 4794 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 4061 | 4795 | } else { |
| 4062 | - if (mod == 3) | |
| 4063 | - goto illegal_op; | |
| 4064 | - gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 4065 | - gen_op_invlpg_A0(); | |
| 4066 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4067 | - gen_eob(s); | |
| 4796 | + if (mod == 3) { | |
| 4797 | +#ifdef TARGET_X86_64 | |
| 4798 | + if (CODE64(s) && (modrm & 7) == 0) { | |
| 4799 | + /* swapgs */ | |
| 4800 | + gen_op_movtl_T0_env(offsetof(CPUX86State,segs[R_GS].base)); | |
| 4801 | + gen_op_movtl_T1_env(offsetof(CPUX86State,kernelgsbase)); | |
| 4802 | + gen_op_movtl_env_T1(offsetof(CPUX86State,segs[R_GS].base)); | |
| 4803 | + gen_op_movtl_env_T0(offsetof(CPUX86State,kernelgsbase)); | |
| 4804 | + } else | |
| 4805 | +#endif | |
| 4806 | + { | |
| 4807 | + goto illegal_op; | |
| 4808 | + } | |
| 4809 | + } else { | |
| 4810 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 4811 | + gen_op_invlpg_A0(); | |
| 4812 | + gen_jmp_im(s->pc - s->cs_base); | |
| 4813 | + gen_eob(s); | |
| 4814 | + } | |
| 4068 | 4815 | } |
| 4069 | 4816 | break; |
| 4070 | 4817 | default: |
| ... | ... | @@ -4079,30 +4826,87 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4079 | 4826 | /* nothing to do */ |
| 4080 | 4827 | } |
| 4081 | 4828 | break; |
| 4082 | - case 0x63: /* arpl */ | |
| 4083 | - if (!s->pe || s->vm86) | |
| 4084 | - goto illegal_op; | |
| 4085 | - ot = dflag ? OT_LONG : OT_WORD; | |
| 4829 | + case 0x1ae: /* sfence */ | |
| 4086 | 4830 | modrm = ldub_code(s->pc++); |
| 4087 | - reg = (modrm >> 3) & 7; | |
| 4088 | 4831 | mod = (modrm >> 6) & 3; |
| 4089 | - rm = modrm & 7; | |
| 4090 | - if (mod != 3) { | |
| 4832 | + op = (modrm >> 3) & 7; | |
| 4833 | + switch(op) { | |
| 4834 | + case 0: /* fxsave */ | |
| 4835 | + if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) | |
| 4836 | + goto illegal_op; | |
| 4091 | 4837 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 4092 | - gen_op_ld_T0_A0[ot + s->mem_index](); | |
| 4093 | - } else { | |
| 4094 | - gen_op_mov_TN_reg[ot][0][rm](); | |
| 4838 | + gen_op_fxsave_A0((s->dflag == 2)); | |
| 4839 | + break; | |
| 4840 | + case 1: /* fxrstor */ | |
| 4841 | + if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) | |
| 4842 | + goto illegal_op; | |
| 4843 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 4844 | + gen_op_fxrstor_A0((s->dflag == 2)); | |
| 4845 | + break; | |
| 4846 | + case 5: /* lfence */ | |
| 4847 | + case 6: /* mfence */ | |
| 4848 | + case 7: /* sfence */ | |
| 4849 | + if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) | |
| 4850 | + goto illegal_op; | |
| 4851 | + break; | |
| 4852 | + default: | |
| 4853 | + goto illegal_op; | |
| 4095 | 4854 | } |
| 4096 | - if (s->cc_op != CC_OP_DYNAMIC) | |
| 4097 | - gen_op_set_cc_op(s->cc_op); | |
| 4098 | - gen_op_arpl(); | |
| 4099 | - s->cc_op = CC_OP_EFLAGS; | |
| 4100 | - if (mod != 3) { | |
| 4101 | - gen_op_st_T0_A0[ot + s->mem_index](); | |
| 4102 | - } else { | |
| 4103 | - gen_op_mov_reg_T0[ot][rm](); | |
| 4855 | + break; | |
| 4856 | + case 0x63: /* arpl or movslS (x86_64) */ | |
| 4857 | +#ifdef TARGET_X86_64 | |
| 4858 | + if (CODE64(s)) { | |
| 4859 | + int d_ot; | |
| 4860 | + /* d_ot is the size of destination */ | |
| 4861 | + d_ot = dflag + OT_WORD; | |
| 4862 | + | |
| 4863 | + modrm = ldub_code(s->pc++); | |
| 4864 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 4865 | + mod = (modrm >> 6) & 3; | |
| 4866 | + rm = (modrm & 7) | REX_B(s); | |
| 4867 | + | |
| 4868 | + if (mod == 3) { | |
| 4869 | + gen_op_mov_TN_reg[OT_LONG][0][rm](); | |
| 4870 | + /* sign extend */ | |
| 4871 | + if (d_ot == OT_QUAD) | |
| 4872 | + gen_op_movslq_T0_T0(); | |
| 4873 | + gen_op_mov_reg_T0[d_ot][reg](); | |
| 4874 | + } else { | |
| 4875 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 4876 | + if (d_ot == OT_QUAD) { | |
| 4877 | + gen_op_lds_T0_A0[OT_LONG + s->mem_index](); | |
| 4878 | + } else { | |
| 4879 | + gen_op_ld_T0_A0[OT_LONG + s->mem_index](); | |
| 4880 | + } | |
| 4881 | + gen_op_mov_reg_T0[d_ot][reg](); | |
| 4882 | + } | |
| 4883 | + } else | |
| 4884 | +#endif | |
| 4885 | + { | |
| 4886 | + if (!s->pe || s->vm86) | |
| 4887 | + goto illegal_op; | |
| 4888 | + ot = dflag ? OT_LONG : OT_WORD; | |
| 4889 | + modrm = ldub_code(s->pc++); | |
| 4890 | + reg = (modrm >> 3) & 7; | |
| 4891 | + mod = (modrm >> 6) & 3; | |
| 4892 | + rm = modrm & 7; | |
| 4893 | + if (mod != 3) { | |
| 4894 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 4895 | + gen_op_ld_T0_A0[ot + s->mem_index](); | |
| 4896 | + } else { | |
| 4897 | + gen_op_mov_TN_reg[ot][0][rm](); | |
| 4898 | + } | |
| 4899 | + if (s->cc_op != CC_OP_DYNAMIC) | |
| 4900 | + gen_op_set_cc_op(s->cc_op); | |
| 4901 | + gen_op_arpl(); | |
| 4902 | + s->cc_op = CC_OP_EFLAGS; | |
| 4903 | + if (mod != 3) { | |
| 4904 | + gen_op_st_T0_A0[ot + s->mem_index](); | |
| 4905 | + } else { | |
| 4906 | + gen_op_mov_reg_T0[ot][rm](); | |
| 4907 | + } | |
| 4908 | + gen_op_arpl_update(); | |
| 4104 | 4909 | } |
| 4105 | - gen_op_arpl_update(); | |
| 4106 | 4910 | break; |
| 4107 | 4911 | case 0x102: /* lar */ |
| 4108 | 4912 | case 0x103: /* lsl */ |
| ... | ... | @@ -4110,7 +4914,7 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4110 | 4914 | goto illegal_op; |
| 4111 | 4915 | ot = dflag ? OT_LONG : OT_WORD; |
| 4112 | 4916 | modrm = ldub_code(s->pc++); |
| 4113 | - reg = (modrm >> 3) & 7; | |
| 4917 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 4114 | 4918 | gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
| 4115 | 4919 | gen_op_mov_TN_reg[ot][1][reg](); |
| 4116 | 4920 | if (s->cc_op != CC_OP_DYNAMIC) |
| ... | ... | @@ -4148,23 +4952,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4148 | 4952 | modrm = ldub_code(s->pc++); |
| 4149 | 4953 | if ((modrm & 0xc0) != 0xc0) |
| 4150 | 4954 | goto illegal_op; |
| 4151 | - rm = modrm & 7; | |
| 4152 | - reg = (modrm >> 3) & 7; | |
| 4955 | + rm = (modrm & 7) | REX_B(s); | |
| 4956 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 4957 | + if (CODE64(s)) | |
| 4958 | + ot = OT_QUAD; | |
| 4959 | + else | |
| 4960 | + ot = OT_LONG; | |
| 4153 | 4961 | switch(reg) { |
| 4154 | 4962 | case 0: |
| 4155 | 4963 | case 2: |
| 4156 | 4964 | case 3: |
| 4157 | 4965 | case 4: |
| 4158 | 4966 | if (b & 2) { |
| 4159 | - gen_op_mov_TN_reg[OT_LONG][0][rm](); | |
| 4967 | + gen_op_mov_TN_reg[ot][0][rm](); | |
| 4160 | 4968 | gen_op_movl_crN_T0(reg); |
| 4161 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 4969 | + gen_jmp_im(s->pc - s->cs_base); | |
| 4162 | 4970 | gen_eob(s); |
| 4163 | 4971 | } else { |
| 4164 | - gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg])); | |
| 4165 | - gen_op_mov_reg_T0[OT_LONG][rm](); | |
| 4972 | + gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg])); | |
| 4973 | + gen_op_mov_reg_T0[ot][rm](); | |
| 4166 | 4974 | } |
| 4167 | 4975 | break; |
| 4976 | + /* XXX: add CR8 for x86_64 */ | |
| 4168 | 4977 | default: |
| 4169 | 4978 | goto illegal_op; |
| 4170 | 4979 | } |
| ... | ... | @@ -4178,19 +4987,23 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4178 | 4987 | modrm = ldub_code(s->pc++); |
| 4179 | 4988 | if ((modrm & 0xc0) != 0xc0) |
| 4180 | 4989 | goto illegal_op; |
| 4181 | - rm = modrm & 7; | |
| 4182 | - reg = (modrm >> 3) & 7; | |
| 4990 | + rm = (modrm & 7) | REX_B(s); | |
| 4991 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 4992 | + if (CODE64(s)) | |
| 4993 | + ot = OT_QUAD; | |
| 4994 | + else | |
| 4995 | + ot = OT_LONG; | |
| 4183 | 4996 | /* XXX: do it dynamically with CR4.DE bit */ |
| 4184 | - if (reg == 4 || reg == 5) | |
| 4997 | + if (reg == 4 || reg == 5 || reg >= 8) | |
| 4185 | 4998 | goto illegal_op; |
| 4186 | 4999 | if (b & 2) { |
| 4187 | - gen_op_mov_TN_reg[OT_LONG][0][rm](); | |
| 5000 | + gen_op_mov_TN_reg[ot][0][rm](); | |
| 4188 | 5001 | gen_op_movl_drN_T0(reg); |
| 4189 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 5002 | + gen_jmp_im(s->pc - s->cs_base); | |
| 4190 | 5003 | gen_eob(s); |
| 4191 | 5004 | } else { |
| 4192 | - gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg])); | |
| 4193 | - gen_op_mov_reg_T0[OT_LONG][rm](); | |
| 5005 | + gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg])); | |
| 5006 | + gen_op_mov_reg_T0[ot][rm](); | |
| 4194 | 5007 | } |
| 4195 | 5008 | } |
| 4196 | 5009 | break; |
| ... | ... | @@ -4200,10 +5013,69 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) |
| 4200 | 5013 | } else { |
| 4201 | 5014 | gen_op_clts(); |
| 4202 | 5015 | /* abort block because static cpu state changed */ |
| 4203 | - gen_op_jmp_im(s->pc - s->cs_base); | |
| 5016 | + gen_jmp_im(s->pc - s->cs_base); | |
| 4204 | 5017 | gen_eob(s); |
| 4205 | 5018 | } |
| 4206 | 5019 | break; |
| 5020 | + /* SSE support */ | |
| 5021 | + case 0x16f: | |
| 5022 | + if (prefixes & PREFIX_DATA) { | |
| 5023 | + /* movdqa xmm1, xmm2/mem128 */ | |
| 5024 | + if (!(s->cpuid_features & CPUID_SSE)) | |
| 5025 | + goto illegal_op; | |
| 5026 | + modrm = ldub_code(s->pc++); | |
| 5027 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 5028 | + mod = (modrm >> 6) & 3; | |
| 5029 | + if (mod != 3) { | |
| 5030 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 5031 | + gen_ldo_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); | |
| 5032 | + } else { | |
| 5033 | + rm = (modrm & 7) | REX_B(s); | |
| 5034 | + gen_op_movo(offsetof(CPUX86State,xmm_regs[reg]), | |
| 5035 | + offsetof(CPUX86State,xmm_regs[rm])); | |
| 5036 | + } | |
| 5037 | + } else { | |
| 5038 | + goto illegal_op; | |
| 5039 | + } | |
| 5040 | + break; | |
| 5041 | + case 0x1e7: | |
| 5042 | + if (prefixes & PREFIX_DATA) { | |
| 5043 | + /* movntdq mem128, xmm1 */ | |
| 5044 | + if (!(s->cpuid_features & CPUID_SSE)) | |
| 5045 | + goto illegal_op; | |
| 5046 | + modrm = ldub_code(s->pc++); | |
| 5047 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 5048 | + mod = (modrm >> 6) & 3; | |
| 5049 | + if (mod != 3) { | |
| 5050 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 5051 | + gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); | |
| 5052 | + } else { | |
| 5053 | + goto illegal_op; | |
| 5054 | + } | |
| 5055 | + } else { | |
| 5056 | + goto illegal_op; | |
| 5057 | + } | |
| 5058 | + break; | |
| 5059 | + case 0x17f: | |
| 5060 | + if (prefixes & PREFIX_DATA) { | |
| 5061 | + /* movdqa xmm2/mem128, xmm1 */ | |
| 5062 | + if (!(s->cpuid_features & CPUID_SSE)) | |
| 5063 | + goto illegal_op; | |
| 5064 | + modrm = ldub_code(s->pc++); | |
| 5065 | + reg = ((modrm >> 3) & 7) | rex_r; | |
| 5066 | + mod = (modrm >> 6) & 3; | |
| 5067 | + if (mod != 3) { | |
| 5068 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
| 5069 | + gen_sto_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_regs[reg])); | |
| 5070 | + } else { | |
| 5071 | + rm = (modrm & 7) | REX_B(s); | |
| 5072 | + gen_op_movo(offsetof(CPUX86State,xmm_regs[rm]), | |
| 5073 | + offsetof(CPUX86State,xmm_regs[reg])); | |
| 5074 | + } | |
| 5075 | + } else { | |
| 5076 | + goto illegal_op; | |
| 5077 | + } | |
| 5078 | + break; | |
| 4207 | 5079 | default: |
| 4208 | 5080 | goto illegal_op; |
| 4209 | 5081 | } |
| ... | ... | @@ -4301,26 +5173,51 @@ static uint16_t opc_read_flags[NB_OPS] = { |
| 4301 | 5173 | [INDEX_op_salc] = CC_C, |
| 4302 | 5174 | |
| 4303 | 5175 | /* needed for correct flag optimisation before string ops */ |
| 5176 | + [INDEX_op_jnz_ecxw] = CC_OSZAPC, | |
| 5177 | + [INDEX_op_jnz_ecxl] = CC_OSZAPC, | |
| 4304 | 5178 | [INDEX_op_jz_ecxw] = CC_OSZAPC, |
| 4305 | 5179 | [INDEX_op_jz_ecxl] = CC_OSZAPC, |
| 4306 | - [INDEX_op_jz_ecxw_im] = CC_OSZAPC, | |
| 4307 | - [INDEX_op_jz_ecxl_im] = CC_OSZAPC, | |
| 5180 | + | |
| 5181 | +#ifdef TARGET_X86_64 | |
| 5182 | + [INDEX_op_jb_subq] = CC_C, | |
| 5183 | + [INDEX_op_jz_subq] = CC_Z, | |
| 5184 | + [INDEX_op_jbe_subq] = CC_Z | CC_C, | |
| 5185 | + [INDEX_op_js_subq] = CC_S, | |
| 5186 | + [INDEX_op_jl_subq] = CC_O | CC_S, | |
| 5187 | + [INDEX_op_jle_subq] = CC_O | CC_S | CC_Z, | |
| 5188 | + | |
| 5189 | + [INDEX_op_loopnzq] = CC_Z, | |
| 5190 | + [INDEX_op_loopzq] = CC_Z, | |
| 5191 | + | |
| 5192 | + [INDEX_op_setb_T0_subq] = CC_C, | |
| 5193 | + [INDEX_op_setz_T0_subq] = CC_Z, | |
| 5194 | + [INDEX_op_setbe_T0_subq] = CC_Z | CC_C, | |
| 5195 | + [INDEX_op_sets_T0_subq] = CC_S, | |
| 5196 | + [INDEX_op_setl_T0_subq] = CC_O | CC_S, | |
| 5197 | + [INDEX_op_setle_T0_subq] = CC_O | CC_S | CC_Z, | |
| 5198 | + | |
| 5199 | + [INDEX_op_jnz_ecxq] = CC_OSZAPC, | |
| 5200 | + [INDEX_op_jz_ecxq] = CC_OSZAPC, | |
| 5201 | +#endif | |
| 4308 | 5202 | |
| 4309 | 5203 | #define DEF_READF(SUFFIX)\ |
| 4310 | 5204 | [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4311 | 5205 | [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4312 | 5206 | [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 5207 | + X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_C,)\ | |
| 4313 | 5208 | [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4314 | 5209 | [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4315 | 5210 | [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 5211 | + X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_C,)\ | |
| 4316 | 5212 | \ |
| 4317 | 5213 | [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4318 | 5214 | [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4319 | 5215 | [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 5216 | + X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_C,)\ | |
| 4320 | 5217 | [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4321 | 5218 | [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_C,\ |
| 4322 | - [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C, | |
| 4323 | - | |
| 5219 | + [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_C,\ | |
| 5220 | + X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_C,) | |
| 4324 | 5221 | |
| 4325 | 5222 | DEF_READF( ) |
| 4326 | 5223 | DEF_READF(_raw) |
| ... | ... | @@ -4341,14 +5238,17 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 4341 | 5238 | [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
| 4342 | 5239 | |
| 4343 | 5240 | [INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
| 4344 | - [INDEX_op_imulb_AL_T0] = CC_OSZAPC, | |
| 4345 | 5241 | [INDEX_op_mulw_AX_T0] = CC_OSZAPC, |
| 4346 | - [INDEX_op_imulw_AX_T0] = CC_OSZAPC, | |
| 4347 | 5242 | [INDEX_op_mull_EAX_T0] = CC_OSZAPC, |
| 5243 | + X86_64_DEF([INDEX_op_mulq_EAX_T0] = CC_OSZAPC,) | |
| 5244 | + [INDEX_op_imulb_AL_T0] = CC_OSZAPC, | |
| 5245 | + [INDEX_op_imulw_AX_T0] = CC_OSZAPC, | |
| 4348 | 5246 | [INDEX_op_imull_EAX_T0] = CC_OSZAPC, |
| 5247 | + X86_64_DEF([INDEX_op_imulq_EAX_T0] = CC_OSZAPC,) | |
| 4349 | 5248 | [INDEX_op_imulw_T0_T1] = CC_OSZAPC, |
| 4350 | 5249 | [INDEX_op_imull_T0_T1] = CC_OSZAPC, |
| 4351 | - | |
| 5250 | + X86_64_DEF([INDEX_op_imulq_T0_T1] = CC_OSZAPC,) | |
| 5251 | + | |
| 4352 | 5252 | /* bcd */ |
| 4353 | 5253 | [INDEX_op_aam] = CC_OSZAPC, |
| 4354 | 5254 | [INDEX_op_aad] = CC_OSZAPC, |
| ... | ... | @@ -4370,21 +5270,28 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 4370 | 5270 | |
| 4371 | 5271 | [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC, |
| 4372 | 5272 | [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC, |
| 5273 | + X86_64_DEF([INDEX_op_btq_T0_T1_cc] = CC_OSZAPC,) | |
| 4373 | 5274 | [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC, |
| 4374 | 5275 | [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC, |
| 5276 | + X86_64_DEF([INDEX_op_btsq_T0_T1_cc] = CC_OSZAPC,) | |
| 4375 | 5277 | [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC, |
| 4376 | 5278 | [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC, |
| 5279 | + X86_64_DEF([INDEX_op_btrq_T0_T1_cc] = CC_OSZAPC,) | |
| 4377 | 5280 | [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC, |
| 4378 | 5281 | [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC, |
| 5282 | + X86_64_DEF([INDEX_op_btcq_T0_T1_cc] = CC_OSZAPC,) | |
| 4379 | 5283 | |
| 4380 | 5284 | [INDEX_op_bsfw_T0_cc] = CC_OSZAPC, |
| 4381 | 5285 | [INDEX_op_bsfl_T0_cc] = CC_OSZAPC, |
| 5286 | + X86_64_DEF([INDEX_op_bsfq_T0_cc] = CC_OSZAPC,) | |
| 4382 | 5287 | [INDEX_op_bsrw_T0_cc] = CC_OSZAPC, |
| 4383 | 5288 | [INDEX_op_bsrl_T0_cc] = CC_OSZAPC, |
| 5289 | + X86_64_DEF([INDEX_op_bsrq_T0_cc] = CC_OSZAPC,) | |
| 4384 | 5290 | |
| 4385 | 5291 | [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC, |
| 4386 | 5292 | [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, |
| 4387 | 5293 | [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, |
| 5294 | + X86_64_DEF([INDEX_op_cmpxchgq_T0_T1_EAX_cc] = CC_OSZAPC,) | |
| 4388 | 5295 | |
| 4389 | 5296 | [INDEX_op_cmpxchg8b] = CC_Z, |
| 4390 | 5297 | [INDEX_op_lar] = CC_Z, |
| ... | ... | @@ -4396,49 +5303,63 @@ static uint16_t opc_write_flags[NB_OPS] = { |
| 4396 | 5303 | [INDEX_op_adcb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4397 | 5304 | [INDEX_op_adcw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4398 | 5305 | [INDEX_op_adcl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 5306 | + X86_64_DEF([INDEX_op_adcq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\ | |
| 4399 | 5307 | [INDEX_op_sbbb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4400 | 5308 | [INDEX_op_sbbw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4401 | 5309 | [INDEX_op_sbbl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 5310 | + X86_64_DEF([INDEX_op_sbbq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\ | |
| 4402 | 5311 | \ |
| 4403 | 5312 | [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4404 | 5313 | [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4405 | 5314 | [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 5315 | + X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\ | |
| 4406 | 5316 | [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4407 | 5317 | [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4408 | 5318 | [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 5319 | + X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\ | |
| 4409 | 5320 | \ |
| 4410 | 5321 | [INDEX_op_rclb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4411 | 5322 | [INDEX_op_rclw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4412 | 5323 | [INDEX_op_rcll ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 5324 | + X86_64_DEF([INDEX_op_rclq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\ | |
| 4413 | 5325 | [INDEX_op_rcrb ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4414 | 5326 | [INDEX_op_rcrw ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 4415 | 5327 | [INDEX_op_rcrl ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,\ |
| 5328 | + X86_64_DEF([INDEX_op_rcrq ## SUFFIX ## _T0_T1_cc] = CC_O | CC_C,)\ | |
| 4416 | 5329 | \ |
| 4417 | 5330 | [INDEX_op_shlb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4418 | 5331 | [INDEX_op_shlw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4419 | 5332 | [INDEX_op_shll ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 5333 | + X86_64_DEF([INDEX_op_shlq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\ | |
| 4420 | 5334 | \ |
| 4421 | 5335 | [INDEX_op_shrb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4422 | 5336 | [INDEX_op_shrw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4423 | 5337 | [INDEX_op_shrl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 5338 | + X86_64_DEF([INDEX_op_shrq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\ | |
| 4424 | 5339 | \ |
| 4425 | 5340 | [INDEX_op_sarb ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4426 | 5341 | [INDEX_op_sarw ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 4427 | 5342 | [INDEX_op_sarl ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,\ |
| 5343 | + X86_64_DEF([INDEX_op_sarq ## SUFFIX ## _T0_T1_cc] = CC_OSZAPC,)\ | |
| 4428 | 5344 | \ |
| 4429 | 5345 | [INDEX_op_shldw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\ |
| 4430 | 5346 | [INDEX_op_shldl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\ |
| 5347 | + X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\ | |
| 4431 | 5348 | [INDEX_op_shldw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\ |
| 4432 | 5349 | [INDEX_op_shldl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\ |
| 5350 | + X86_64_DEF([INDEX_op_shldq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\ | |
| 4433 | 5351 | \ |
| 4434 | 5352 | [INDEX_op_shrdw ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\ |
| 4435 | 5353 | [INDEX_op_shrdl ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,\ |
| 5354 | + X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_ECX_cc] = CC_OSZAPC,)\ | |
| 4436 | 5355 | [INDEX_op_shrdw ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\ |
| 4437 | 5356 | [INDEX_op_shrdl ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,\ |
| 5357 | + X86_64_DEF([INDEX_op_shrdq ## SUFFIX ## _T0_T1_im_cc] = CC_OSZAPC,)\ | |
| 4438 | 5358 | \ |
| 4439 | 5359 | [INDEX_op_cmpxchgb ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\ |
| 4440 | 5360 | [INDEX_op_cmpxchgw ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\ |
| 4441 | - [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC, | |
| 5361 | + [INDEX_op_cmpxchgl ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,\ | |
| 5362 | + X86_64_DEF([INDEX_op_cmpxchgq ## SUFFIX ## _T0_T1_EAX_cc] = CC_OSZAPC,) | |
| 4442 | 5363 | |
| 4443 | 5364 | |
| 4444 | 5365 | DEF_WRITEF( ) |
| ... | ... | @@ -4462,23 +5383,28 @@ static uint16_t opc_simpler[NB_OPS] = { |
| 4462 | 5383 | [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1, |
| 4463 | 5384 | [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1, |
| 4464 | 5385 | [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1, |
| 5386 | + X86_64_DEF([INDEX_op_shlq_T0_T1_cc] = INDEX_op_shlq_T0_T1,) | |
| 4465 | 5387 | |
| 4466 | 5388 | [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1, |
| 4467 | 5389 | [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1, |
| 4468 | 5390 | [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1, |
| 5391 | + X86_64_DEF([INDEX_op_shrq_T0_T1_cc] = INDEX_op_shrq_T0_T1,) | |
| 4469 | 5392 | |
| 4470 | 5393 | [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1, |
| 4471 | 5394 | [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1, |
| 4472 | 5395 | [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1, |
| 5396 | + X86_64_DEF([INDEX_op_sarq_T0_T1_cc] = INDEX_op_sarq_T0_T1,) | |
| 4473 | 5397 | |
| 4474 | 5398 | #define DEF_SIMPLER(SUFFIX)\ |
| 4475 | 5399 | [INDEX_op_rolb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolb ## SUFFIX ## _T0_T1,\ |
| 4476 | 5400 | [INDEX_op_rolw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolw ## SUFFIX ## _T0_T1,\ |
| 4477 | 5401 | [INDEX_op_roll ## SUFFIX ## _T0_T1_cc] = INDEX_op_roll ## SUFFIX ## _T0_T1,\ |
| 5402 | + X86_64_DEF([INDEX_op_rolq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rolq ## SUFFIX ## _T0_T1,)\ | |
| 4478 | 5403 | \ |
| 4479 | 5404 | [INDEX_op_rorb ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorb ## SUFFIX ## _T0_T1,\ |
| 4480 | 5405 | [INDEX_op_rorw ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorw ## SUFFIX ## _T0_T1,\ |
| 4481 | - [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1, | |
| 5406 | + [INDEX_op_rorl ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorl ## SUFFIX ## _T0_T1,\ | |
| 5407 | + X86_64_DEF([INDEX_op_rorq ## SUFFIX ## _T0_T1_cc] = INDEX_op_rorq ## SUFFIX ## _T0_T1,) | |
| 4482 | 5408 | |
| 4483 | 5409 | DEF_SIMPLER( ) |
| 4484 | 5410 | DEF_SIMPLER(_raw) |
| ... | ... | @@ -4533,15 +5459,15 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4533 | 5459 | int search_pc) |
| 4534 | 5460 | { |
| 4535 | 5461 | DisasContext dc1, *dc = &dc1; |
| 4536 | - uint8_t *pc_ptr; | |
| 5462 | + target_ulong pc_ptr; | |
| 4537 | 5463 | uint16_t *gen_opc_end; |
| 4538 | 5464 | int flags, j, lj, cflags; |
| 4539 | - uint8_t *pc_start; | |
| 4540 | - uint8_t *cs_base; | |
| 5465 | + target_ulong pc_start; | |
| 5466 | + target_ulong cs_base; | |
| 4541 | 5467 | |
| 4542 | 5468 | /* generate intermediate code */ |
| 4543 | - pc_start = (uint8_t *)tb->pc; | |
| 4544 | - cs_base = (uint8_t *)tb->cs_base; | |
| 5469 | + pc_start = tb->pc; | |
| 5470 | + cs_base = tb->cs_base; | |
| 4545 | 5471 | flags = tb->flags; |
| 4546 | 5472 | cflags = tb->cflags; |
| 4547 | 5473 | |
| ... | ... | @@ -4563,10 +5489,15 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4563 | 5489 | dc->mem_index = 0; |
| 4564 | 5490 | if (flags & HF_SOFTMMU_MASK) { |
| 4565 | 5491 | if (dc->cpl == 3) |
| 4566 | - dc->mem_index = 6; | |
| 5492 | + dc->mem_index = 2 * 4; | |
| 4567 | 5493 | else |
| 4568 | - dc->mem_index = 3; | |
| 5494 | + dc->mem_index = 1 * 4; | |
| 4569 | 5495 | } |
| 5496 | + dc->cpuid_features = env->cpuid_features; | |
| 5497 | +#ifdef TARGET_X86_64 | |
| 5498 | + dc->lma = (flags >> HF_LMA_SHIFT) & 1; | |
| 5499 | + dc->code64 = (flags >> HF_CS64_SHIFT) & 1; | |
| 5500 | +#endif | |
| 4570 | 5501 | dc->flags = flags; |
| 4571 | 5502 | dc->jmp_opt = !(dc->tf || env->singlestep_enabled || |
| 4572 | 5503 | (flags & HF_INHIBIT_IRQ_MASK) |
| ... | ... | @@ -4583,6 +5514,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4583 | 5514 | gen_opc_ptr = gen_opc_buf; |
| 4584 | 5515 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
| 4585 | 5516 | gen_opparam_ptr = gen_opparam_buf; |
| 5517 | + nb_gen_labels = 0; | |
| 4586 | 5518 | |
| 4587 | 5519 | dc->is_jmp = DISAS_NEXT; |
| 4588 | 5520 | pc_ptr = pc_start; |
| ... | ... | @@ -4591,7 +5523,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4591 | 5523 | for(;;) { |
| 4592 | 5524 | if (env->nb_breakpoints > 0) { |
| 4593 | 5525 | for(j = 0; j < env->nb_breakpoints; j++) { |
| 4594 | - if (env->breakpoints[j] == (unsigned long)pc_ptr) { | |
| 5526 | + if (env->breakpoints[j] == pc_ptr) { | |
| 4595 | 5527 | gen_debug(dc, pc_ptr - dc->cs_base); |
| 4596 | 5528 | break; |
| 4597 | 5529 | } |
| ... | ... | @@ -4604,7 +5536,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4604 | 5536 | while (lj < j) |
| 4605 | 5537 | gen_opc_instr_start[lj++] = 0; |
| 4606 | 5538 | } |
| 4607 | - gen_opc_pc[lj] = (uint32_t)pc_ptr; | |
| 5539 | + gen_opc_pc[lj] = pc_ptr; | |
| 4608 | 5540 | gen_opc_cc_op[lj] = dc->cc_op; |
| 4609 | 5541 | gen_opc_instr_start[lj] = 1; |
| 4610 | 5542 | } |
| ... | ... | @@ -4620,14 +5552,14 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4620 | 5552 | if (dc->tf || dc->singlestep_enabled || |
| 4621 | 5553 | (flags & HF_INHIBIT_IRQ_MASK) || |
| 4622 | 5554 | (cflags & CF_SINGLE_INSN)) { |
| 4623 | - gen_op_jmp_im(pc_ptr - dc->cs_base); | |
| 5555 | + gen_jmp_im(pc_ptr - dc->cs_base); | |
| 4624 | 5556 | gen_eob(dc); |
| 4625 | 5557 | break; |
| 4626 | 5558 | } |
| 4627 | 5559 | /* if too long translation, stop generation too */ |
| 4628 | 5560 | if (gen_opc_ptr >= gen_opc_end || |
| 4629 | 5561 | (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) { |
| 4630 | - gen_op_jmp_im(pc_ptr - dc->cs_base); | |
| 5562 | + gen_jmp_im(pc_ptr - dc->cs_base); | |
| 4631 | 5563 | gen_eob(dc); |
| 4632 | 5564 | break; |
| 4633 | 5565 | } |
| ... | ... | @@ -4646,9 +5578,16 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
| 4646 | 5578 | cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP); |
| 4647 | 5579 | } |
| 4648 | 5580 | if (loglevel & CPU_LOG_TB_IN_ASM) { |
| 5581 | + int disas_flags; | |
| 4649 | 5582 | fprintf(logfile, "----------------\n"); |
| 4650 | 5583 | fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
| 4651 | - disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32); | |
| 5584 | +#ifdef TARGET_X86_64 | |
| 5585 | + if (dc->code64) | |
| 5586 | + disas_flags = 2; | |
| 5587 | + else | |
| 5588 | +#endif | |
| 5589 | + disas_flags = !dc->code32; | |
| 5590 | + target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags); | |
| 4652 | 5591 | fprintf(logfile, "\n"); |
| 4653 | 5592 | if (loglevel & CPU_LOG_TB_OP) { |
| 4654 | 5593 | fprintf(logfile, "OP:\n"); | ... | ... |