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 | 214 | #define MSR_IA32_SYSENTER_ESP 0x175 |
| 215 | 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 | 223 | #define MSR_EFER 0xc0000080 |
| 218 | 224 | |
| 219 | 225 | #define MSR_EFER_SCE (1 << 0) |
| ... | ... | @@ -246,6 +252,8 @@ |
| 246 | 252 | #define CPUID_PGE (1 << 13) |
| 247 | 253 | #define CPUID_MCA (1 << 14) |
| 248 | 254 | #define CPUID_CMOV (1 << 15) |
| 255 | +#define CPUID_PAT (1 << 16) | |
| 256 | +#define CPUID_CLFLUSH (1 << 19) | |
| 249 | 257 | /* ... */ |
| 250 | 258 | #define CPUID_MMX (1 << 23) |
| 251 | 259 | #define CPUID_FXSR (1 << 24) |
| ... | ... | @@ -474,6 +482,8 @@ typedef struct CPUX86State { |
| 474 | 482 | target_ulong kernelgsbase; |
| 475 | 483 | #endif |
| 476 | 484 | |
| 485 | + uint64_t pat; | |
| 486 | + | |
| 477 | 487 | /* temporary data for USE_CODE_COPY mode */ |
| 478 | 488 | #ifdef USE_CODE_COPY |
| 479 | 489 | uint32_t tmp0; | ... | ... |
target-i386/exec.h
| ... | ... | @@ -157,11 +157,11 @@ void helper_lldt_T0(void); |
| 157 | 157 | void helper_ltr_T0(void); |
| 158 | 158 | void helper_movl_crN_T0(int reg); |
| 159 | 159 | void helper_movl_drN_T0(int reg); |
| 160 | -void helper_invlpg(unsigned int addr); | |
| 160 | +void helper_invlpg(target_ulong addr); | |
| 161 | 161 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); |
| 162 | 162 | void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); |
| 163 | 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 | 165 | int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr, |
| 166 | 166 | int is_write, int is_user, int is_softmmu); |
| 167 | 167 | void tlb_fill(target_ulong addr, int is_write, int is_user, |
| ... | ... | @@ -190,6 +190,7 @@ void helper_idivq_EAX_T0(void); |
| 190 | 190 | void helper_cmpxchg8b(void); |
| 191 | 191 | void helper_cpuid(void); |
| 192 | 192 | void helper_enter_level(int level, int data32); |
| 193 | +void helper_enter64_level(int level, int data64); | |
| 193 | 194 | void helper_sysenter(void); |
| 194 | 195 | void helper_sysexit(void); |
| 195 | 196 | void helper_syscall(int next_eip_addend); | ... | ... |
target-i386/helper.c
| ... | ... | @@ -1334,6 +1334,20 @@ void helper_cpuid(void) |
| 1334 | 1334 | ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2]; |
| 1335 | 1335 | EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3]; |
| 1336 | 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 | 1351 | case 0x80000008: |
| 1338 | 1352 | /* virtual & phys address size in low 2 bytes. */ |
| 1339 | 1353 | EAX = 0x00003028; |
| ... | ... | @@ -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 | 1431 | void helper_lldt_T0(void) |
| 1387 | 1432 | { |
| 1388 | 1433 | int selector; |
| ... | ... | @@ -1963,6 +2008,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend) |
| 1963 | 2008 | #endif |
| 1964 | 2009 | sp_mask = get_sp_mask(env->segs[R_SS].flags); |
| 1965 | 2010 | sp = ESP; |
| 2011 | + /* XXX: ssp is zero in 64 bit ? */ | |
| 1966 | 2012 | ssp = env->segs[R_SS].base; |
| 1967 | 2013 | new_eflags = 0; /* avoid warning */ |
| 1968 | 2014 | #ifdef TARGET_X86_64 |
| ... | ... | @@ -2271,7 +2317,7 @@ void helper_movl_drN_T0(int reg) |
| 2271 | 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 | 2322 | cpu_x86_flush_tlb(env, addr); |
| 2277 | 2323 | } |
| ... | ... | @@ -2332,6 +2378,9 @@ void helper_wrmsr(void) |
| 2332 | 2378 | case MSR_STAR: |
| 2333 | 2379 | env->star = val; |
| 2334 | 2380 | break; |
| 2381 | + case MSR_PAT: | |
| 2382 | + env->pat = val; | |
| 2383 | + break; | |
| 2335 | 2384 | #ifdef TARGET_X86_64 |
| 2336 | 2385 | case MSR_LSTAR: |
| 2337 | 2386 | env->lstar = val; |
| ... | ... | @@ -2380,6 +2429,9 @@ void helper_rdmsr(void) |
| 2380 | 2429 | case MSR_STAR: |
| 2381 | 2430 | val = env->star; |
| 2382 | 2431 | break; |
| 2432 | + case MSR_PAT: | |
| 2433 | + val = env->pat; | |
| 2434 | + break; | |
| 2383 | 2435 | #ifdef TARGET_X86_64 |
| 2384 | 2436 | case MSR_LSTAR: |
| 2385 | 2437 | val = env->lstar; | ... | ... |
target-i386/helper2.c
| ... | ... | @@ -106,7 +106,9 @@ CPUX86State *cpu_x86_init(void) |
| 106 | 106 | env->cpuid_version = (family << 8) | (model << 4) | stepping; |
| 107 | 107 | env->cpuid_features = (CPUID_FP87 | CPUID_DE | CPUID_PSE | |
| 108 | 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 | 112 | env->cpuid_ext_features = 0; |
| 111 | 113 | env->cpuid_features |= CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | CPUID_PAE | CPUID_SEP; |
| 112 | 114 | env->cpuid_xlevel = 0; |
| ... | ... | @@ -128,6 +130,9 @@ CPUX86State *cpu_x86_init(void) |
| 128 | 130 | env->cpuid_ext2_features = (env->cpuid_features & 0x0183F3FF); |
| 129 | 131 | env->cpuid_ext2_features |= CPUID_EXT2_LM | CPUID_EXT2_SYSCALL; |
| 130 | 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 | 136 | #endif |
| 132 | 137 | } |
| 133 | 138 | cpu_single_env = env; |
| ... | ... | @@ -546,7 +551,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) |
| 546 | 551 | } |
| 547 | 552 | |
| 548 | 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 | 556 | tlb_flush_page(env, addr); |
| 552 | 557 | } | ... | ... |
target-i386/op.c
| ... | ... | @@ -898,6 +898,11 @@ void op_addw_ESP_im(void) |
| 898 | 898 | } |
| 899 | 899 | |
| 900 | 900 | #ifdef TARGET_X86_64 |
| 901 | +void op_subq_A0_2(void) | |
| 902 | +{ | |
| 903 | + A0 -= 2; | |
| 904 | +} | |
| 905 | + | |
| 901 | 906 | void op_subq_A0_8(void) |
| 902 | 907 | { |
| 903 | 908 | A0 -= 8; |
| ... | ... | @@ -929,6 +934,13 @@ void OPPROTO op_enter_level(void) |
| 929 | 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 | 944 | void OPPROTO op_sysenter(void) |
| 933 | 945 | { |
| 934 | 946 | helper_sysenter(); | ... | ... |
target-i386/translate.c
| ... | ... | @@ -1627,7 +1627,14 @@ static void gen_add_A0_ds_seg(DisasContext *s) |
| 1627 | 1627 | override = R_DS; |
| 1628 | 1628 | } |
| 1629 | 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 | 1955 | { |
| 1949 | 1956 | #ifdef TARGET_X86_64 |
| 1950 | 1957 | if (CODE64(s)) { |
| 1951 | - /* XXX: check 16 bit behaviour */ | |
| 1952 | 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 | 1966 | gen_op_movq_ESP_A0(); |
| 1956 | 1967 | } else |
| 1957 | 1968 | #endif |
| ... | ... | @@ -1985,10 +1996,14 @@ static void gen_push_T1(DisasContext *s) |
| 1985 | 1996 | { |
| 1986 | 1997 | #ifdef TARGET_X86_64 |
| 1987 | 1998 | if (CODE64(s)) { |
| 1988 | - /* XXX: check 16 bit behaviour */ | |
| 1989 | 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 | 2007 | gen_op_movq_ESP_A0(); |
| 1993 | 2008 | } else |
| 1994 | 2009 | #endif |
| ... | ... | @@ -2020,9 +2035,8 @@ static void gen_pop_T0(DisasContext *s) |
| 2020 | 2035 | { |
| 2021 | 2036 | #ifdef TARGET_X86_64 |
| 2022 | 2037 | if (CODE64(s)) { |
| 2023 | - /* XXX: check 16 bit behaviour */ | |
| 2024 | 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 | 2040 | } else |
| 2027 | 2041 | #endif |
| 2028 | 2042 | { |
| ... | ... | @@ -2041,7 +2055,7 @@ static void gen_pop_T0(DisasContext *s) |
| 2041 | 2055 | static void gen_pop_update(DisasContext *s) |
| 2042 | 2056 | { |
| 2043 | 2057 | #ifdef TARGET_X86_64 |
| 2044 | - if (CODE64(s)) { | |
| 2058 | + if (CODE64(s) && s->dflag) { | |
| 2045 | 2059 | gen_stack_update(s, 8); |
| 2046 | 2060 | } else |
| 2047 | 2061 | #endif |
| ... | ... | @@ -2105,26 +2119,48 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) |
| 2105 | 2119 | { |
| 2106 | 2120 | int ot, opsize; |
| 2107 | 2121 | |
| 2108 | - ot = s->dflag + OT_WORD; | |
| 2109 | 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 | 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 | 2937 | if (mod != 3) |
| 2902 | 2938 | goto illegal_op; |
| 2903 | 2939 | #ifdef TARGET_X86_64 |
| 2904 | - if (CODE64(s)) { | |
| 2940 | + if (s->aflag == 2) { | |
| 2905 | 2941 | gen_op_movq_A0_reg[R_EDI](); |
| 2906 | 2942 | } else |
| 2907 | 2943 | #endif |
| ... | ... | @@ -3697,7 +3733,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 3697 | 3733 | break; |
| 3698 | 3734 | case 0xc8: /* enter */ |
| 3699 | 3735 | { |
| 3700 | - /* XXX: long mode support */ | |
| 3701 | 3736 | int level; |
| 3702 | 3737 | val = lduw_code(s->pc); |
| 3703 | 3738 | s->pc += 2; |
| ... | ... | @@ -3707,7 +3742,6 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 3707 | 3742 | break; |
| 3708 | 3743 | case 0xc9: /* leave */ |
| 3709 | 3744 | /* XXX: exception not precise (ESP is updated before potential exception) */ |
| 3710 | - /* XXX: may be invalid for 16 bit in long mode */ | |
| 3711 | 3745 | if (CODE64(s)) { |
| 3712 | 3746 | gen_op_mov_TN_reg[OT_QUAD][0][R_EBP](); |
| 3713 | 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 | 3960 | else |
| 3927 | 3961 | ot = dflag + OT_WORD; |
| 3928 | 3962 | #ifdef TARGET_X86_64 |
| 3929 | - if (CODE64(s)) { | |
| 3963 | + if (s->aflag == 2) { | |
| 3930 | 3964 | offset_addr = ldq_code(s->pc); |
| 3931 | 3965 | s->pc += 8; |
| 3932 | 3966 | if (offset_addr == (int32_t)offset_addr) |
| ... | ... | @@ -3955,7 +3989,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 3955 | 3989 | break; |
| 3956 | 3990 | case 0xd7: /* xlat */ |
| 3957 | 3991 | #ifdef TARGET_X86_64 |
| 3958 | - if (CODE64(s)) { | |
| 3992 | + if (s->aflag == 2) { | |
| 3959 | 3993 | gen_op_movq_A0_reg[R_EBX](); |
| 3960 | 3994 | gen_op_addq_A0_AL(); |
| 3961 | 3995 | } else |
| ... | ... | @@ -4779,6 +4813,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 4779 | 4813 | val = ldsw_code(s->pc); |
| 4780 | 4814 | s->pc += 2; |
| 4781 | 4815 | gen_pop_T0(s); |
| 4816 | + if (CODE64(s) && s->dflag) | |
| 4817 | + s->dflag = 2; | |
| 4782 | 4818 | gen_stack_update(s, val + (2 << s->dflag)); |
| 4783 | 4819 | if (s->dflag == 0) |
| 4784 | 4820 | gen_op_andl_T0_ffff(); |
| ... | ... | @@ -5782,14 +5818,30 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 5782 | 5818 | break; |
| 5783 | 5819 | case 5: /* lfence */ |
| 5784 | 5820 | case 6: /* mfence */ |
| 5785 | - case 7: /* sfence */ | |
| 5786 | 5821 | if ((modrm & 0xc7) != 0xc0 || !(s->cpuid_features & CPUID_SSE)) |
| 5787 | 5822 | goto illegal_op; |
| 5788 | 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 | 5836 | default: |
| 5790 | 5837 | goto illegal_op; |
| 5791 | 5838 | } |
| 5792 | 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 | 5845 | case 0x110 ... 0x117: |
| 5794 | 5846 | case 0x128 ... 0x12f: |
| 5795 | 5847 | case 0x150 ... 0x177: | ... | ... |