Commit 8f091a59605092994c4b52c20b7173c514411e38
1 parent
2efbe911
x86_64 fixes (initial patch by Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1517 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
171 additions
and
39 deletions
target-i386/cpu.h
@@ -214,6 +214,12 @@ | @@ -214,6 +214,12 @@ | ||
214 | #define MSR_IA32_SYSENTER_ESP 0x175 | 214 | #define MSR_IA32_SYSENTER_ESP 0x175 |
215 | #define MSR_IA32_SYSENTER_EIP 0x176 | 215 | #define MSR_IA32_SYSENTER_EIP 0x176 |
216 | 216 | ||
217 | +#define MSR_MCG_CAP 0x179 | ||
218 | +#define MSR_MCG_STATUS 0x17a | ||
219 | +#define MSR_MCG_CTL 0x17b | ||
220 | + | ||
221 | +#define MSR_PAT 0x277 | ||
222 | + | ||
217 | #define MSR_EFER 0xc0000080 | 223 | #define MSR_EFER 0xc0000080 |
218 | 224 | ||
219 | #define MSR_EFER_SCE (1 << 0) | 225 | #define MSR_EFER_SCE (1 << 0) |
@@ -246,6 +252,8 @@ | @@ -246,6 +252,8 @@ | ||
246 | #define CPUID_PGE (1 << 13) | 252 | #define CPUID_PGE (1 << 13) |
247 | #define CPUID_MCA (1 << 14) | 253 | #define CPUID_MCA (1 << 14) |
248 | #define CPUID_CMOV (1 << 15) | 254 | #define CPUID_CMOV (1 << 15) |
255 | +#define CPUID_PAT (1 << 16) | ||
256 | +#define CPUID_CLFLUSH (1 << 19) | ||
249 | /* ... */ | 257 | /* ... */ |
250 | #define CPUID_MMX (1 << 23) | 258 | #define CPUID_MMX (1 << 23) |
251 | #define CPUID_FXSR (1 << 24) | 259 | #define CPUID_FXSR (1 << 24) |
@@ -474,6 +482,8 @@ typedef struct CPUX86State { | @@ -474,6 +482,8 @@ typedef struct CPUX86State { | ||
474 | target_ulong kernelgsbase; | 482 | target_ulong kernelgsbase; |
475 | #endif | 483 | #endif |
476 | 484 | ||
485 | + uint64_t pat; | ||
486 | + | ||
477 | /* temporary data for USE_CODE_COPY mode */ | 487 | /* temporary data for USE_CODE_COPY mode */ |
478 | #ifdef USE_CODE_COPY | 488 | #ifdef USE_CODE_COPY |
479 | uint32_t tmp0; | 489 | uint32_t tmp0; |
target-i386/exec.h
@@ -157,11 +157,11 @@ void helper_lldt_T0(void); | @@ -157,11 +157,11 @@ void helper_lldt_T0(void); | ||
157 | void helper_ltr_T0(void); | 157 | void helper_ltr_T0(void); |
158 | void helper_movl_crN_T0(int reg); | 158 | void helper_movl_crN_T0(int reg); |
159 | void helper_movl_drN_T0(int reg); | 159 | void helper_movl_drN_T0(int reg); |
160 | -void helper_invlpg(unsigned int addr); | 160 | +void helper_invlpg(target_ulong addr); |
161 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); | 161 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); |
162 | void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); | 162 | void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); |
163 | void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); | 163 | void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); |
164 | -void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr); | 164 | +void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr); |
165 | int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, | 165 | int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, |
166 | int is_write, int is_user, int is_softmmu); | 166 | int is_write, int is_user, int is_softmmu); |
167 | void tlb_fill(target_ulong addr, int is_write, int is_user, | 167 | void tlb_fill(target_ulong addr, int is_write, int is_user, |
@@ -190,6 +190,7 @@ void helper_idivq_EAX_T0(void); | @@ -190,6 +190,7 @@ void helper_idivq_EAX_T0(void); | ||
190 | void helper_cmpxchg8b(void); | 190 | void helper_cmpxchg8b(void); |
191 | void helper_cpuid(void); | 191 | void helper_cpuid(void); |
192 | void helper_enter_level(int level, int data32); | 192 | void helper_enter_level(int level, int data32); |
193 | +void helper_enter64_level(int level, int data64); | ||
193 | void helper_sysenter(void); | 194 | void helper_sysenter(void); |
194 | void helper_sysexit(void); | 195 | void helper_sysexit(void); |
195 | void helper_syscall(int next_eip_addend); | 196 | void helper_syscall(int next_eip_addend); |
target-i386/helper.c
@@ -1334,6 +1334,20 @@ void helper_cpuid(void) | @@ -1334,6 +1334,20 @@ void helper_cpuid(void) | ||
1334 | ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2]; | 1334 | ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2]; |
1335 | EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3]; | 1335 | EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3]; |
1336 | break; | 1336 | break; |
1337 | + case 0x80000005: | ||
1338 | + /* cache info (L1 cache) */ | ||
1339 | + EAX = 0x01ff01ff; | ||
1340 | + EBX = 0x01ff01ff; | ||
1341 | + ECX = 0x40020140; | ||
1342 | + EDX = 0x40020140; | ||
1343 | + break; | ||
1344 | + case 0x80000006: | ||
1345 | + /* cache info (L2 cache) */ | ||
1346 | + EAX = 0; | ||
1347 | + EBX = 0x42004200; | ||
1348 | + ECX = 0x02008140; | ||
1349 | + EDX = 0; | ||
1350 | + break; | ||
1337 | case 0x80000008: | 1351 | case 0x80000008: |
1338 | /* virtual & phys address size in low 2 bytes. */ | 1352 | /* virtual & phys address size in low 2 bytes. */ |
1339 | EAX = 0x00003028; | 1353 | EAX = 0x00003028; |
@@ -1383,6 +1397,37 @@ void helper_enter_level(int level, int data32) | @@ -1383,6 +1397,37 @@ void helper_enter_level(int level, int data32) | ||
1383 | } | 1397 | } |
1384 | } | 1398 | } |
1385 | 1399 | ||
1400 | +#ifdef TARGET_X86_64 | ||
1401 | +void helper_enter64_level(int level, int data64) | ||
1402 | +{ | ||
1403 | + target_ulong esp, ebp; | ||
1404 | + ebp = EBP; | ||
1405 | + esp = ESP; | ||
1406 | + | ||
1407 | + if (data64) { | ||
1408 | + /* 64 bit */ | ||
1409 | + esp -= 8; | ||
1410 | + while (--level) { | ||
1411 | + esp -= 8; | ||
1412 | + ebp -= 8; | ||
1413 | + stq(esp, ldq(ebp)); | ||
1414 | + } | ||
1415 | + esp -= 8; | ||
1416 | + stq(esp, T1); | ||
1417 | + } else { | ||
1418 | + /* 16 bit */ | ||
1419 | + esp -= 2; | ||
1420 | + while (--level) { | ||
1421 | + esp -= 2; | ||
1422 | + ebp -= 2; | ||
1423 | + stw(esp, lduw(ebp)); | ||
1424 | + } | ||
1425 | + esp -= 2; | ||
1426 | + stw(esp, T1); | ||
1427 | + } | ||
1428 | +} | ||
1429 | +#endif | ||
1430 | + | ||
1386 | void helper_lldt_T0(void) | 1431 | void helper_lldt_T0(void) |
1387 | { | 1432 | { |
1388 | int selector; | 1433 | int selector; |
@@ -1963,6 +2008,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | @@ -1963,6 +2008,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) | ||
1963 | #endif | 2008 | #endif |
1964 | sp_mask = get_sp_mask(env->segs[R_SS].flags); | 2009 | sp_mask = get_sp_mask(env->segs[R_SS].flags); |
1965 | sp = ESP; | 2010 | sp = ESP; |
2011 | + /* XXX: ssp is zero in 64 bit ? */ | ||
1966 | ssp = env->segs[R_SS].base; | 2012 | ssp = env->segs[R_SS].base; |
1967 | new_eflags = 0; /* avoid warning */ | 2013 | new_eflags = 0; /* avoid warning */ |
1968 | #ifdef TARGET_X86_64 | 2014 | #ifdef TARGET_X86_64 |
@@ -2271,7 +2317,7 @@ void helper_movl_drN_T0(int reg) | @@ -2271,7 +2317,7 @@ void helper_movl_drN_T0(int reg) | ||
2271 | env->dr[reg] = T0; | 2317 | env->dr[reg] = T0; |
2272 | } | 2318 | } |
2273 | 2319 | ||
2274 | -void helper_invlpg(unsigned int addr) | 2320 | +void helper_invlpg(target_ulong addr) |
2275 | { | 2321 | { |
2276 | cpu_x86_flush_tlb(env, addr); | 2322 | cpu_x86_flush_tlb(env, addr); |
2277 | } | 2323 | } |
@@ -2332,6 +2378,9 @@ void helper_wrmsr(void) | @@ -2332,6 +2378,9 @@ void helper_wrmsr(void) | ||
2332 | case MSR_STAR: | 2378 | case MSR_STAR: |
2333 | env->star = val; | 2379 | env->star = val; |
2334 | break; | 2380 | break; |
2381 | + case MSR_PAT: | ||
2382 | + env->pat = val; | ||
2383 | + break; | ||
2335 | #ifdef TARGET_X86_64 | 2384 | #ifdef TARGET_X86_64 |
2336 | case MSR_LSTAR: | 2385 | case MSR_LSTAR: |
2337 | env->lstar = val; | 2386 | env->lstar = val; |
@@ -2380,6 +2429,9 @@ void helper_rdmsr(void) | @@ -2380,6 +2429,9 @@ void helper_rdmsr(void) | ||
2380 | case MSR_STAR: | 2429 | case MSR_STAR: |
2381 | val = env->star; | 2430 | val = env->star; |
2382 | break; | 2431 | break; |
2432 | + case MSR_PAT: | ||
2433 | + val = env->pat; | ||
2434 | + break; | ||
2383 | #ifdef TARGET_X86_64 | 2435 | #ifdef TARGET_X86_64 |
2384 | case MSR_LSTAR: | 2436 | case MSR_LSTAR: |
2385 | val = env->lstar; | 2437 | val = env->lstar; |
target-i386/helper2.c
@@ -106,7 +106,9 @@ CPUX86State *cpu_x86_init(void) | @@ -106,7 +106,9 @@ CPUX86State *cpu_x86_init(void) | ||
106 | env->cpuid_version = (family << 8) | (model << 4) | stepping; | 106 | env->cpuid_version = (family << 8) | (model << 4) | stepping; |
107 | env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | | 107 | env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | |
108 | CPUID_TSC | CPUID_MSR | CPUID_MCE | | 108 | CPUID_TSC | CPUID_MSR | CPUID_MCE | |
109 | - CPUID_CX8 | CPUID_PGE | CPUID_CMOV); | 109 | + CPUID_CX8 | CPUID_PGE | CPUID_CMOV | |
110 | + CPUID_PAT); | ||
111 | + env->pat = 0x0007040600070406ULL; | ||
110 | env->cpuid_ext_features = 0; | 112 | env->cpuid_ext_features = 0; |
111 | env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP; | 113 | env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP; |
112 | env->cpuid_xlevel = 0; | 114 | env->cpuid_xlevel = 0; |
@@ -128,6 +130,9 @@ CPUX86State *cpu_x86_init(void) | @@ -128,6 +130,9 @@ CPUX86State *cpu_x86_init(void) | ||
128 | env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); | 130 | env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); |
129 | env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL; | 131 | env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL; |
130 | env->cpuid_xlevel = 0x80000008; | 132 | env->cpuid_xlevel = 0x80000008; |
133 | + | ||
134 | + /* these features are needed for Win64 and aren't fully implemented */ | ||
135 | + env->cpuid_features |= CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA; | ||
131 | #endif | 136 | #endif |
132 | } | 137 | } |
133 | cpu_single_env = env; | 138 | cpu_single_env = env; |
@@ -546,7 +551,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) | @@ -546,7 +551,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) | ||
546 | } | 551 | } |
547 | 552 | ||
548 | /* XXX: also flush 4MB pages */ | 553 | /* XXX: also flush 4MB pages */ |
549 | -void cpu_x86_flush_tlb(CPUX86State *env, uint32_t addr) | 554 | +void cpu_x86_flush_tlb(CPUX86State *env, target_ulong addr) |
550 | { | 555 | { |
551 | tlb_flush_page(env, addr); | 556 | tlb_flush_page(env, addr); |
552 | } | 557 | } |
target-i386/op.c
@@ -898,6 +898,11 @@ void op_addw_ESP_im(void) | @@ -898,6 +898,11 @@ void op_addw_ESP_im(void) | ||
898 | } | 898 | } |
899 | 899 | ||
900 | #ifdef TARGET_X86_64 | 900 | #ifdef TARGET_X86_64 |
901 | +void op_subq_A0_2(void) | ||
902 | +{ | ||
903 | + A0 -= 2; | ||
904 | +} | ||
905 | + | ||
901 | void op_subq_A0_8(void) | 906 | void op_subq_A0_8(void) |
902 | { | 907 | { |
903 | A0 -= 8; | 908 | A0 -= 8; |
@@ -929,6 +934,13 @@ void OPPROTO op_enter_level(void) | @@ -929,6 +934,13 @@ void OPPROTO op_enter_level(void) | ||
929 | helper_enter_level(PARAM1, PARAM2); | 934 | helper_enter_level(PARAM1, PARAM2); |
930 | } | 935 | } |
931 | 936 | ||
937 | +#ifdef TARGET_X86_64 | ||
938 | +void OPPROTO op_enter64_level(void) | ||
939 | +{ | ||
940 | + helper_enter64_level(PARAM1, PARAM2); | ||
941 | +} | ||
942 | +#endif | ||
943 | + | ||
932 | void OPPROTO op_sysenter(void) | 944 | void OPPROTO op_sysenter(void) |
933 | { | 945 | { |
934 | helper_sysenter(); | 946 | helper_sysenter(); |
target-i386/translate.c
@@ -1627,7 +1627,14 @@ static void gen_add_A0_ds_seg(DisasContext *s) | @@ -1627,7 +1627,14 @@ static void gen_add_A0_ds_seg(DisasContext *s) | ||
1627 | override = R_DS; | 1627 | override = R_DS; |
1628 | } | 1628 | } |
1629 | if (must_add_seg) { | 1629 | if (must_add_seg) { |
1630 | - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | 1630 | +#ifdef TARGET_X86_64 |
1631 | + if (CODE64(s)) { | ||
1632 | + gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base)); | ||
1633 | + } else | ||
1634 | +#endif | ||
1635 | + { | ||
1636 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); | ||
1637 | + } | ||
1631 | } | 1638 | } |
1632 | } | 1639 | } |
1633 | 1640 | ||
@@ -1948,10 +1955,14 @@ static void gen_push_T0(DisasContext *s) | @@ -1948,10 +1955,14 @@ static void gen_push_T0(DisasContext *s) | ||
1948 | { | 1955 | { |
1949 | #ifdef TARGET_X86_64 | 1956 | #ifdef TARGET_X86_64 |
1950 | if (CODE64(s)) { | 1957 | if (CODE64(s)) { |
1951 | - /* XXX: check 16 bit behaviour */ | ||
1952 | gen_op_movq_A0_reg[R_ESP](); | 1958 | gen_op_movq_A0_reg[R_ESP](); |
1953 | - gen_op_subq_A0_8(); | ||
1954 | - gen_op_st_T0_A0[OT_QUAD + s->mem_index](); | 1959 | + if (s->dflag) { |
1960 | + gen_op_subq_A0_8(); | ||
1961 | + gen_op_st_T0_A0[OT_QUAD + s->mem_index](); | ||
1962 | + } else { | ||
1963 | + gen_op_subq_A0_2(); | ||
1964 | + gen_op_st_T0_A0[OT_WORD + s->mem_index](); | ||
1965 | + } | ||
1955 | gen_op_movq_ESP_A0(); | 1966 | gen_op_movq_ESP_A0(); |
1956 | } else | 1967 | } else |
1957 | #endif | 1968 | #endif |
@@ -1985,10 +1996,14 @@ static void gen_push_T1(DisasContext *s) | @@ -1985,10 +1996,14 @@ static void gen_push_T1(DisasContext *s) | ||
1985 | { | 1996 | { |
1986 | #ifdef TARGET_X86_64 | 1997 | #ifdef TARGET_X86_64 |
1987 | if (CODE64(s)) { | 1998 | if (CODE64(s)) { |
1988 | - /* XXX: check 16 bit behaviour */ | ||
1989 | gen_op_movq_A0_reg[R_ESP](); | 1999 | gen_op_movq_A0_reg[R_ESP](); |
1990 | - gen_op_subq_A0_8(); | ||
1991 | - gen_op_st_T1_A0[OT_QUAD + s->mem_index](); | 2000 | + if (s->dflag) { |
2001 | + gen_op_subq_A0_8(); | ||
2002 | + gen_op_st_T1_A0[OT_QUAD + s->mem_index](); | ||
2003 | + } else { | ||
2004 | + gen_op_subq_A0_2(); | ||
2005 | + gen_op_st_T0_A0[OT_WORD + s->mem_index](); | ||
2006 | + } | ||
1992 | gen_op_movq_ESP_A0(); | 2007 | gen_op_movq_ESP_A0(); |
1993 | } else | 2008 | } else |
1994 | #endif | 2009 | #endif |
@@ -2020,9 +2035,8 @@ static void gen_pop_T0(DisasContext *s) | @@ -2020,9 +2035,8 @@ static void gen_pop_T0(DisasContext *s) | ||
2020 | { | 2035 | { |
2021 | #ifdef TARGET_X86_64 | 2036 | #ifdef TARGET_X86_64 |
2022 | if (CODE64(s)) { | 2037 | if (CODE64(s)) { |
2023 | - /* XXX: check 16 bit behaviour */ | ||
2024 | gen_op_movq_A0_reg[R_ESP](); | 2038 | gen_op_movq_A0_reg[R_ESP](); |
2025 | - gen_op_ld_T0_A0[OT_QUAD + s->mem_index](); | 2039 | + gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index](); |
2026 | } else | 2040 | } else |
2027 | #endif | 2041 | #endif |
2028 | { | 2042 | { |
@@ -2041,7 +2055,7 @@ static void gen_pop_T0(DisasContext *s) | @@ -2041,7 +2055,7 @@ static void gen_pop_T0(DisasContext *s) | ||
2041 | static void gen_pop_update(DisasContext *s) | 2055 | static void gen_pop_update(DisasContext *s) |
2042 | { | 2056 | { |
2043 | #ifdef TARGET_X86_64 | 2057 | #ifdef TARGET_X86_64 |
2044 | - if (CODE64(s)) { | 2058 | + if (CODE64(s) && s->dflag) { |
2045 | gen_stack_update(s, 8); | 2059 | gen_stack_update(s, 8); |
2046 | } else | 2060 | } else |
2047 | #endif | 2061 | #endif |
@@ -2105,26 +2119,48 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | @@ -2105,26 +2119,48 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | ||
2105 | { | 2119 | { |
2106 | int ot, opsize; | 2120 | int ot, opsize; |
2107 | 2121 | ||
2108 | - ot = s->dflag + OT_WORD; | ||
2109 | level &= 0x1f; | 2122 | level &= 0x1f; |
2110 | - opsize = 2 << s->dflag; | ||
2111 | - | ||
2112 | - gen_op_movl_A0_ESP(); | ||
2113 | - gen_op_addl_A0_im(-opsize); | ||
2114 | - if (!s->ss32) | ||
2115 | - gen_op_andl_A0_ffff(); | ||
2116 | - gen_op_movl_T1_A0(); | ||
2117 | - if (s->addseg) | ||
2118 | - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); | ||
2119 | - /* push bp */ | ||
2120 | - gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | ||
2121 | - gen_op_st_T0_A0[ot + s->mem_index](); | ||
2122 | - if (level) { | ||
2123 | - gen_op_enter_level(level, s->dflag); | 2123 | +#ifdef TARGET_X86_64 |
2124 | + if (CODE64(s)) { | ||
2125 | + ot = s->dflag ? OT_QUAD : OT_WORD; | ||
2126 | + opsize = 1 << ot; | ||
2127 | + | ||
2128 | + gen_op_movl_A0_ESP(); | ||
2129 | + gen_op_addq_A0_im(-opsize); | ||
2130 | + gen_op_movl_T1_A0(); | ||
2131 | + | ||
2132 | + /* push bp */ | ||
2133 | + gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | ||
2134 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
2135 | + if (level) { | ||
2136 | + gen_op_enter64_level(level, (ot == OT_QUAD)); | ||
2137 | + } | ||
2138 | + gen_op_mov_reg_T1[ot][R_EBP](); | ||
2139 | + gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); | ||
2140 | + gen_op_mov_reg_T1[OT_QUAD][R_ESP](); | ||
2141 | + } else | ||
2142 | +#endif | ||
2143 | + { | ||
2144 | + ot = s->dflag + OT_WORD; | ||
2145 | + opsize = 2 << s->dflag; | ||
2146 | + | ||
2147 | + gen_op_movl_A0_ESP(); | ||
2148 | + gen_op_addl_A0_im(-opsize); | ||
2149 | + if (!s->ss32) | ||
2150 | + gen_op_andl_A0_ffff(); | ||
2151 | + gen_op_movl_T1_A0(); | ||
2152 | + if (s->addseg) | ||
2153 | + gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); | ||
2154 | + /* push bp */ | ||
2155 | + gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | ||
2156 | + gen_op_st_T0_A0[ot + s->mem_index](); | ||
2157 | + if (level) { | ||
2158 | + gen_op_enter_level(level, s->dflag); | ||
2159 | + } | ||
2160 | + gen_op_mov_reg_T1[ot][R_EBP](); | ||
2161 | + gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); | ||
2162 | + gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP](); | ||
2124 | } | 2163 | } |
2125 | - gen_op_mov_reg_T1[ot][R_EBP](); | ||
2126 | - gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); | ||
2127 | - gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP](); | ||
2128 | } | 2164 | } |
2129 | 2165 | ||
2130 | static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) | 2166 | static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip) |
@@ -2901,7 +2937,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) | @@ -2901,7 +2937,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) | ||
2901 | if (mod != 3) | 2937 | if (mod != 3) |
2902 | goto illegal_op; | 2938 | goto illegal_op; |
2903 | #ifdef TARGET_X86_64 | 2939 | #ifdef TARGET_X86_64 |
2904 | - if (CODE64(s)) { | 2940 | + if (s->aflag == 2) { |
2905 | gen_op_movq_A0_reg[R_EDI](); | 2941 | gen_op_movq_A0_reg[R_EDI](); |
2906 | } else | 2942 | } else |
2907 | #endif | 2943 | #endif |
@@ -3697,7 +3733,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3697,7 +3733,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
3697 | break; | 3733 | break; |
3698 | case 0xc8: /* enter */ | 3734 | case 0xc8: /* enter */ |
3699 | { | 3735 | { |
3700 | - /* XXX: long mode support */ | ||
3701 | int level; | 3736 | int level; |
3702 | val = lduw_code(s->pc); | 3737 | val = lduw_code(s->pc); |
3703 | s->pc += 2; | 3738 | s->pc += 2; |
@@ -3707,7 +3742,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3707,7 +3742,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
3707 | break; | 3742 | break; |
3708 | case 0xc9: /* leave */ | 3743 | case 0xc9: /* leave */ |
3709 | /* XXX: exception not precise (ESP is updated before potential exception) */ | 3744 | /* XXX: exception not precise (ESP is updated before potential exception) */ |
3710 | - /* XXX: may be invalid for 16 bit in long mode */ | ||
3711 | if (CODE64(s)) { | 3745 | if (CODE64(s)) { |
3712 | gen_op_mov_TN_reg[OT_QUAD][0][R_EBP](); | 3746 | gen_op_mov_TN_reg[OT_QUAD][0][R_EBP](); |
3713 | gen_op_mov_reg_T0[OT_QUAD][R_ESP](); | 3747 | gen_op_mov_reg_T0[OT_QUAD][R_ESP](); |
@@ -3926,7 +3960,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3926,7 +3960,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
3926 | else | 3960 | else |
3927 | ot = dflag + OT_WORD; | 3961 | ot = dflag + OT_WORD; |
3928 | #ifdef TARGET_X86_64 | 3962 | #ifdef TARGET_X86_64 |
3929 | - if (CODE64(s)) { | 3963 | + if (s->aflag == 2) { |
3930 | offset_addr = ldq_code(s->pc); | 3964 | offset_addr = ldq_code(s->pc); |
3931 | s->pc += 8; | 3965 | s->pc += 8; |
3932 | if (offset_addr == (int32_t)offset_addr) | 3966 | if (offset_addr == (int32_t)offset_addr) |
@@ -3955,7 +3989,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -3955,7 +3989,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
3955 | break; | 3989 | break; |
3956 | case 0xd7: /* xlat */ | 3990 | case 0xd7: /* xlat */ |
3957 | #ifdef TARGET_X86_64 | 3991 | #ifdef TARGET_X86_64 |
3958 | - if (CODE64(s)) { | 3992 | + if (s->aflag == 2) { |
3959 | gen_op_movq_A0_reg[R_EBX](); | 3993 | gen_op_movq_A0_reg[R_EBX](); |
3960 | gen_op_addq_A0_AL(); | 3994 | gen_op_addq_A0_AL(); |
3961 | } else | 3995 | } else |
@@ -4779,6 +4813,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -4779,6 +4813,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
4779 | val = ldsw_code(s->pc); | 4813 | val = ldsw_code(s->pc); |
4780 | s->pc += 2; | 4814 | s->pc += 2; |
4781 | gen_pop_T0(s); | 4815 | gen_pop_T0(s); |
4816 | + if (CODE64(s) && s->dflag) | ||
4817 | + s->dflag = 2; | ||
4782 | gen_stack_update(s, val + (2 << s->dflag)); | 4818 | gen_stack_update(s, val + (2 << s->dflag)); |
4783 | if (s->dflag == 0) | 4819 | if (s->dflag == 0) |
4784 | gen_op_andl_T0_ffff(); | 4820 | gen_op_andl_T0_ffff(); |
@@ -5782,14 +5818,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -5782,14 +5818,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
5782 | break; | 5818 | break; |
5783 | case 5: /* lfence */ | 5819 | case 5: /* lfence */ |
5784 | case 6: /* mfence */ | 5820 | case 6: /* mfence */ |
5785 | - case 7: /* sfence */ | ||
5786 | if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) | 5821 | if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) |
5787 | goto illegal_op; | 5822 | goto illegal_op; |
5788 | break; | 5823 | break; |
5824 | + case 7: /* sfence / clflush */ | ||
5825 | + if ((modrm & 0xc7) == 0xc0) { | ||
5826 | + /* sfence */ | ||
5827 | + if (!(s->cpuid_features & CPUID_SSE)) | ||
5828 | + goto illegal_op; | ||
5829 | + } else { | ||
5830 | + /* clflush */ | ||
5831 | + if (!(s->cpuid_features & CPUID_CLFLUSH)) | ||
5832 | + goto illegal_op; | ||
5833 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
5834 | + } | ||
5835 | + break; | ||
5789 | default: | 5836 | default: |
5790 | goto illegal_op; | 5837 | goto illegal_op; |
5791 | } | 5838 | } |
5792 | break; | 5839 | break; |
5840 | + case 0x10d: /* prefetch */ | ||
5841 | + modrm = ldub_code(s->pc++); | ||
5842 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
5843 | + /* ignore for now */ | ||
5844 | + break; | ||
5793 | case 0x110 ... 0x117: | 5845 | case 0x110 ... 0x117: |
5794 | case 0x128 ... 0x12f: | 5846 | case 0x128 ... 0x12f: |
5795 | case 0x150 ... 0x177: | 5847 | case 0x150 ... 0x177: |