Commit b8b6a50b552e1ddb9f0c563cbfb6f67aa0330b64
1 parent
6e01bdae
converted more helpers to TCG - fixed some SVM issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4459 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
404 additions
and
485 deletions
target-i386/TODO
... | ... | @@ -3,12 +3,13 @@ Correctness issues: |
3 | 3 | - rework eflags optimization (will be a consequence of TCG port) |
4 | 4 | - SVM: rework the implementation: simplify code, move most intercept |
5 | 5 | tests as dynamic, correct segment access, verify exception safety, |
6 | - remove most of the added CPU state. | |
6 | + cpu save/restore, SMM save/restore. | |
7 | 7 | - arpl eflags computation is invalid |
8 | 8 | - x86_64: fxsave/fxrestore intel/amd differences |
9 | 9 | - x86_64: lcall/ljmp intel/amd differences ? |
10 | 10 | - x86_64: cmpxchgl intel/amd differences ? |
11 | -- x86_64: cmovl bug intel/amd differences ? | |
11 | +- x86_64: cmovl intel/amd differences ? | |
12 | +- cmpxchg16b + cmpxchg8b cpuid test | |
12 | 13 | - x86: monitor invalid |
13 | 14 | - better code fetch (different exception handling + CS.limit support) |
14 | 15 | - user/kernel PUSHL/POPL in helper.c |
... | ... | @@ -19,10 +20,18 @@ Correctness issues: |
19 | 20 | - full support of segment limit/rights |
20 | 21 | - full x87 exception support |
21 | 22 | - improve x87 bit exactness (use bochs code ?) |
23 | +- DRx register support | |
24 | +- CR0.AC emulation | |
25 | +- SSE alignment checks | |
26 | +- fix SSE min/max with nans | |
22 | 27 | |
23 | 28 | Optimizations/Features: |
24 | 29 | |
25 | 30 | - finish TCG port |
31 | +- add SVM nested paging support | |
32 | +- add VMX support | |
33 | +- add AVX support | |
34 | +- add SSE5 support | |
26 | 35 | - evaluate x87 stack pointer statically |
27 | 36 | - find a way to avoid translating several time the same TB if CR0.TS |
28 | 37 | is set or not. | ... | ... |
target-i386/exec.h
... | ... | @@ -105,16 +105,6 @@ typedef struct CCTable { |
105 | 105 | |
106 | 106 | extern CCTable cc_table[]; |
107 | 107 | |
108 | -void helper_load_seg(int seg_reg, int selector); | |
109 | -void helper_ljmp_protected_T0_T1(int next_eip); | |
110 | -void helper_lcall_real_T0_T1(int shift, int next_eip); | |
111 | -void helper_lcall_protected_T0_T1(int shift, int next_eip); | |
112 | -void helper_iret_real(int shift); | |
113 | -void helper_iret_protected(int shift, int next_eip); | |
114 | -void helper_lret_protected(int shift, int addend); | |
115 | -void helper_movl_crN_T0(int reg); | |
116 | -void helper_movl_drN_T0(int reg); | |
117 | -void helper_invlpg(target_ulong addr); | |
118 | 108 | void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); |
119 | 109 | void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3); |
120 | 110 | void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4); |
... | ... | @@ -141,17 +131,10 @@ void OPPROTO op_movl_T0_eflags(void); |
141 | 131 | |
142 | 132 | #include "helper.h" |
143 | 133 | |
144 | -void helper_mulq_EAX_T0(void); | |
145 | -void helper_imulq_EAX_T0(void); | |
146 | -void helper_imulq_T0_T1(void); | |
147 | -void helper_cmpxchg8b(void); | |
148 | - | |
149 | -void check_iob_T0(void); | |
150 | -void check_iow_T0(void); | |
151 | -void check_iol_T0(void); | |
152 | -void check_iob_DX(void); | |
153 | -void check_iow_DX(void); | |
154 | -void check_iol_DX(void); | |
134 | +static inline void svm_check_intercept(uint32_t type) | |
135 | +{ | |
136 | + helper_svm_check_intercept_param(type, 0); | |
137 | +} | |
155 | 138 | |
156 | 139 | #if !defined(CONFIG_USER_ONLY) |
157 | 140 | |
... | ... | @@ -363,7 +346,6 @@ extern const CPU86_LDouble f15rk[7]; |
363 | 346 | void fpu_raise_exception(void); |
364 | 347 | void restore_native_fp_state(CPUState *env); |
365 | 348 | void save_native_fp_state(CPUState *env); |
366 | -void vmexit(uint64_t exit_code, uint64_t exit_info_1); | |
367 | 349 | |
368 | 350 | extern const uint8_t parity_table[256]; |
369 | 351 | extern const uint8_t rclw_table[32]; | ... | ... |
target-i386/helper.c
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | * License along with this library; if not, write to the Free Software |
18 | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | 19 | */ |
20 | +#define CPU_NO_GLOBAL_REGS | |
20 | 21 | #include "exec.h" |
21 | 22 | #include "host-utils.h" |
22 | 23 | |
... | ... | @@ -93,16 +94,16 @@ const CPU86_LDouble f15rk[7] = |
93 | 94 | 3.32192809488736234781L, /*l2t*/ |
94 | 95 | }; |
95 | 96 | |
96 | -/* thread support */ | |
97 | +/* broken thread support */ | |
97 | 98 | |
98 | 99 | spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; |
99 | 100 | |
100 | -void cpu_lock(void) | |
101 | +void helper_lock(void) | |
101 | 102 | { |
102 | 103 | spin_lock(&global_cpu_lock); |
103 | 104 | } |
104 | 105 | |
105 | -void cpu_unlock(void) | |
106 | +void helper_unlock(void) | |
106 | 107 | { |
107 | 108 | spin_unlock(&global_cpu_lock); |
108 | 109 | } |
... | ... | @@ -508,34 +509,49 @@ static inline void check_io(int addr, int size) |
508 | 509 | } |
509 | 510 | } |
510 | 511 | |
511 | -void check_iob_T0(void) | |
512 | +void helper_check_iob(uint32_t t0) | |
512 | 513 | { |
513 | - check_io(T0, 1); | |
514 | + check_io(t0, 1); | |
514 | 515 | } |
515 | 516 | |
516 | -void check_iow_T0(void) | |
517 | +void helper_check_iow(uint32_t t0) | |
517 | 518 | { |
518 | - check_io(T0, 2); | |
519 | + check_io(t0, 2); | |
519 | 520 | } |
520 | 521 | |
521 | -void check_iol_T0(void) | |
522 | +void helper_check_iol(uint32_t t0) | |
522 | 523 | { |
523 | - check_io(T0, 4); | |
524 | + check_io(t0, 4); | |
524 | 525 | } |
525 | 526 | |
526 | -void check_iob_DX(void) | |
527 | +void helper_outb(uint32_t port, uint32_t data) | |
527 | 528 | { |
528 | - check_io(EDX & 0xffff, 1); | |
529 | + cpu_outb(env, port, data & 0xff); | |
529 | 530 | } |
530 | 531 | |
531 | -void check_iow_DX(void) | |
532 | +target_ulong helper_inb(uint32_t port) | |
532 | 533 | { |
533 | - check_io(EDX & 0xffff, 2); | |
534 | + return cpu_inb(env, port); | |
534 | 535 | } |
535 | 536 | |
536 | -void check_iol_DX(void) | |
537 | +void helper_outw(uint32_t port, uint32_t data) | |
537 | 538 | { |
538 | - check_io(EDX & 0xffff, 4); | |
539 | + cpu_outw(env, port, data & 0xffff); | |
540 | +} | |
541 | + | |
542 | +target_ulong helper_inw(uint32_t port) | |
543 | +{ | |
544 | + return cpu_inw(env, port); | |
545 | +} | |
546 | + | |
547 | +void helper_outl(uint32_t port, uint32_t data) | |
548 | +{ | |
549 | + cpu_outl(env, port, data); | |
550 | +} | |
551 | + | |
552 | +target_ulong helper_inl(uint32_t port) | |
553 | +{ | |
554 | + return cpu_inl(env, port); | |
539 | 555 | } |
540 | 556 | |
541 | 557 | static inline unsigned int get_sp_mask(unsigned int e2) |
... | ... | @@ -1275,7 +1291,7 @@ void raise_interrupt(int intno, int is_int, int error_code, |
1275 | 1291 | int next_eip_addend) |
1276 | 1292 | { |
1277 | 1293 | if (!is_int) { |
1278 | - svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); | |
1294 | + helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code); | |
1279 | 1295 | intno = check_exception(intno, &error_code); |
1280 | 1296 | } |
1281 | 1297 | |
... | ... | @@ -1857,19 +1873,19 @@ void helper_das(void) |
1857 | 1873 | FORCE_RET(); |
1858 | 1874 | } |
1859 | 1875 | |
1860 | -void helper_cmpxchg8b(void) | |
1876 | +void helper_cmpxchg8b(target_ulong a0) | |
1861 | 1877 | { |
1862 | 1878 | uint64_t d; |
1863 | 1879 | int eflags; |
1864 | 1880 | |
1865 | 1881 | eflags = cc_table[CC_OP].compute_all(); |
1866 | - d = ldq(A0); | |
1882 | + d = ldq(a0); | |
1867 | 1883 | if (d == (((uint64_t)EDX << 32) | EAX)) { |
1868 | - stq(A0, ((uint64_t)ECX << 32) | EBX); | |
1884 | + stq(a0, ((uint64_t)ECX << 32) | EBX); | |
1869 | 1885 | eflags |= CC_Z; |
1870 | 1886 | } else { |
1871 | - EDX = d >> 32; | |
1872 | - EAX = d; | |
1887 | + EDX = (uint32_t)(d >> 32); | |
1888 | + EAX = (uint32_t)d; | |
1873 | 1889 | eflags &= ~CC_Z; |
1874 | 1890 | } |
1875 | 1891 | CC_SRC = eflags; |
... | ... | @@ -1986,7 +2002,7 @@ void helper_cpuid(void) |
1986 | 2002 | } |
1987 | 2003 | } |
1988 | 2004 | |
1989 | -void helper_enter_level(int level, int data32) | |
2005 | +void helper_enter_level(int level, int data32, target_ulong t1) | |
1990 | 2006 | { |
1991 | 2007 | target_ulong ssp; |
1992 | 2008 | uint32_t esp_mask, esp, ebp; |
... | ... | @@ -2004,7 +2020,7 @@ void helper_enter_level(int level, int data32) |
2004 | 2020 | stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask))); |
2005 | 2021 | } |
2006 | 2022 | esp -= 4; |
2007 | - stl(ssp + (esp & esp_mask), T1); | |
2023 | + stl(ssp + (esp & esp_mask), t1); | |
2008 | 2024 | } else { |
2009 | 2025 | /* 16 bit */ |
2010 | 2026 | esp -= 2; |
... | ... | @@ -2014,12 +2030,12 @@ void helper_enter_level(int level, int data32) |
2014 | 2030 | stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask))); |
2015 | 2031 | } |
2016 | 2032 | esp -= 2; |
2017 | - stw(ssp + (esp & esp_mask), T1); | |
2033 | + stw(ssp + (esp & esp_mask), t1); | |
2018 | 2034 | } |
2019 | 2035 | } |
2020 | 2036 | |
2021 | 2037 | #ifdef TARGET_X86_64 |
2022 | -void helper_enter64_level(int level, int data64) | |
2038 | +void helper_enter64_level(int level, int data64, target_ulong t1) | |
2023 | 2039 | { |
2024 | 2040 | target_ulong esp, ebp; |
2025 | 2041 | ebp = EBP; |
... | ... | @@ -2034,7 +2050,7 @@ void helper_enter64_level(int level, int data64) |
2034 | 2050 | stq(esp, ldq(ebp)); |
2035 | 2051 | } |
2036 | 2052 | esp -= 8; |
2037 | - stq(esp, T1); | |
2053 | + stq(esp, t1); | |
2038 | 2054 | } else { |
2039 | 2055 | /* 16 bit */ |
2040 | 2056 | esp -= 2; |
... | ... | @@ -2044,7 +2060,7 @@ void helper_enter64_level(int level, int data64) |
2044 | 2060 | stw(esp, lduw(ebp)); |
2045 | 2061 | } |
2046 | 2062 | esp -= 2; |
2047 | - stw(esp, T1); | |
2063 | + stw(esp, t1); | |
2048 | 2064 | } |
2049 | 2065 | } |
2050 | 2066 | #endif |
... | ... | @@ -2231,14 +2247,13 @@ void helper_load_seg(int seg_reg, int selector) |
2231 | 2247 | } |
2232 | 2248 | |
2233 | 2249 | /* protected mode jump */ |
2234 | -void helper_ljmp_protected_T0_T1(int next_eip_addend) | |
2250 | +void helper_ljmp_protected(int new_cs, target_ulong new_eip, | |
2251 | + int next_eip_addend) | |
2235 | 2252 | { |
2236 | - int new_cs, gate_cs, type; | |
2253 | + int gate_cs, type; | |
2237 | 2254 | uint32_t e1, e2, cpl, dpl, rpl, limit; |
2238 | - target_ulong new_eip, next_eip; | |
2255 | + target_ulong next_eip; | |
2239 | 2256 | |
2240 | - new_cs = T0; | |
2241 | - new_eip = T1; | |
2242 | 2257 | if ((new_cs & 0xfffc) == 0) |
2243 | 2258 | raise_exception_err(EXCP0D_GPF, 0); |
2244 | 2259 | if (load_segment(&e1, &e2, new_cs) != 0) |
... | ... | @@ -2322,14 +2337,14 @@ void helper_ljmp_protected_T0_T1(int next_eip_addend) |
2322 | 2337 | } |
2323 | 2338 | |
2324 | 2339 | /* real mode call */ |
2325 | -void helper_lcall_real_T0_T1(int shift, int next_eip) | |
2340 | +void helper_lcall_real(int new_cs, target_ulong new_eip1, | |
2341 | + int shift, int next_eip) | |
2326 | 2342 | { |
2327 | - int new_cs, new_eip; | |
2343 | + int new_eip; | |
2328 | 2344 | uint32_t esp, esp_mask; |
2329 | 2345 | target_ulong ssp; |
2330 | 2346 | |
2331 | - new_cs = T0; | |
2332 | - new_eip = T1; | |
2347 | + new_eip = new_eip1; | |
2333 | 2348 | esp = ESP; |
2334 | 2349 | esp_mask = get_sp_mask(env->segs[R_SS].flags); |
2335 | 2350 | ssp = env->segs[R_SS].base; |
... | ... | @@ -2348,16 +2363,15 @@ void helper_lcall_real_T0_T1(int shift, int next_eip) |
2348 | 2363 | } |
2349 | 2364 | |
2350 | 2365 | /* protected mode call */ |
2351 | -void helper_lcall_protected_T0_T1(int shift, int next_eip_addend) | |
2366 | +void helper_lcall_protected(int new_cs, target_ulong new_eip, | |
2367 | + int shift, int next_eip_addend) | |
2352 | 2368 | { |
2353 | - int new_cs, new_stack, i; | |
2369 | + int new_stack, i; | |
2354 | 2370 | uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count; |
2355 | 2371 | uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask; |
2356 | 2372 | uint32_t val, limit, old_sp_mask; |
2357 | - target_ulong ssp, old_ssp, next_eip, new_eip; | |
2373 | + target_ulong ssp, old_ssp, next_eip; | |
2358 | 2374 | |
2359 | - new_cs = T0; | |
2360 | - new_eip = T1; | |
2361 | 2375 | next_eip = env->eip + next_eip_addend; |
2362 | 2376 | #ifdef DEBUG_PCALL |
2363 | 2377 | if (loglevel & CPU_LOG_PCALL) { |
... | ... | @@ -2922,34 +2936,55 @@ void helper_sysexit(void) |
2922 | 2936 | #endif |
2923 | 2937 | } |
2924 | 2938 | |
2925 | -void helper_movl_crN_T0(int reg) | |
2939 | +void helper_movl_crN_T0(int reg, target_ulong t0) | |
2926 | 2940 | { |
2927 | 2941 | #if !defined(CONFIG_USER_ONLY) |
2928 | 2942 | switch(reg) { |
2929 | 2943 | case 0: |
2930 | - cpu_x86_update_cr0(env, T0); | |
2944 | + cpu_x86_update_cr0(env, t0); | |
2931 | 2945 | break; |
2932 | 2946 | case 3: |
2933 | - cpu_x86_update_cr3(env, T0); | |
2947 | + cpu_x86_update_cr3(env, t0); | |
2934 | 2948 | break; |
2935 | 2949 | case 4: |
2936 | - cpu_x86_update_cr4(env, T0); | |
2950 | + cpu_x86_update_cr4(env, t0); | |
2937 | 2951 | break; |
2938 | 2952 | case 8: |
2939 | - cpu_set_apic_tpr(env, T0); | |
2940 | - env->cr[8] = T0; | |
2953 | + cpu_set_apic_tpr(env, t0); | |
2954 | + env->cr[8] = t0; | |
2941 | 2955 | break; |
2942 | 2956 | default: |
2943 | - env->cr[reg] = T0; | |
2957 | + env->cr[reg] = t0; | |
2944 | 2958 | break; |
2945 | 2959 | } |
2946 | 2960 | #endif |
2947 | 2961 | } |
2948 | 2962 | |
2963 | +void helper_lmsw(target_ulong t0) | |
2964 | +{ | |
2965 | + /* only 4 lower bits of CR0 are modified. PE cannot be set to zero | |
2966 | + if already set to one. */ | |
2967 | + t0 = (env->cr[0] & ~0xe) | (t0 & 0xf); | |
2968 | + helper_movl_crN_T0(0, t0); | |
2969 | +} | |
2970 | + | |
2971 | +void helper_clts(void) | |
2972 | +{ | |
2973 | + env->cr[0] &= ~CR0_TS_MASK; | |
2974 | + env->hflags &= ~HF_TS_MASK; | |
2975 | +} | |
2976 | + | |
2977 | +#if !defined(CONFIG_USER_ONLY) | |
2978 | +target_ulong helper_movtl_T0_cr8(void) | |
2979 | +{ | |
2980 | + return cpu_get_apic_tpr(env); | |
2981 | +} | |
2982 | +#endif | |
2983 | + | |
2949 | 2984 | /* XXX: do more */ |
2950 | -void helper_movl_drN_T0(int reg) | |
2985 | +void helper_movl_drN_T0(int reg, target_ulong t0) | |
2951 | 2986 | { |
2952 | - env->dr[reg] = T0; | |
2987 | + env->dr[reg] = t0; | |
2953 | 2988 | } |
2954 | 2989 | |
2955 | 2990 | void helper_invlpg(target_ulong addr) |
... | ... | @@ -2975,10 +3010,10 @@ void helper_rdpmc(void) |
2975 | 3010 | raise_exception(EXCP0D_GPF); |
2976 | 3011 | } |
2977 | 3012 | |
2978 | - if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) { | |
2979 | - /* currently unimplemented */ | |
2980 | - raise_exception_err(EXCP06_ILLOP, 0); | |
2981 | - } | |
3013 | + helper_svm_check_intercept_param(SVM_EXIT_RDPMC, 0); | |
3014 | + | |
3015 | + /* currently unimplemented */ | |
3016 | + raise_exception_err(EXCP06_ILLOP, 0); | |
2982 | 3017 | } |
2983 | 3018 | |
2984 | 3019 | #if defined(CONFIG_USER_ONLY) |
... | ... | @@ -3118,7 +3153,7 @@ void helper_rdmsr(void) |
3118 | 3153 | } |
3119 | 3154 | #endif |
3120 | 3155 | |
3121 | -void helper_lsl(uint32_t selector) | |
3156 | +uint32_t helper_lsl(uint32_t selector) | |
3122 | 3157 | { |
3123 | 3158 | unsigned int limit; |
3124 | 3159 | uint32_t e1, e2, eflags; |
... | ... | @@ -3153,15 +3188,15 @@ void helper_lsl(uint32_t selector) |
3153 | 3188 | if (dpl < cpl || dpl < rpl) { |
3154 | 3189 | fail: |
3155 | 3190 | CC_SRC = eflags & ~CC_Z; |
3156 | - return; | |
3191 | + return 0; | |
3157 | 3192 | } |
3158 | 3193 | } |
3159 | 3194 | limit = get_seg_limit(e1, e2); |
3160 | - T1 = limit; | |
3161 | 3195 | CC_SRC = eflags | CC_Z; |
3196 | + return limit; | |
3162 | 3197 | } |
3163 | 3198 | |
3164 | -void helper_lar(uint32_t selector) | |
3199 | +uint32_t helper_lar(uint32_t selector) | |
3165 | 3200 | { |
3166 | 3201 | uint32_t e1, e2, eflags; |
3167 | 3202 | int rpl, dpl, cpl, type; |
... | ... | @@ -3200,11 +3235,11 @@ void helper_lar(uint32_t selector) |
3200 | 3235 | if (dpl < cpl || dpl < rpl) { |
3201 | 3236 | fail: |
3202 | 3237 | CC_SRC = eflags & ~CC_Z; |
3203 | - return; | |
3238 | + return 0; | |
3204 | 3239 | } |
3205 | 3240 | } |
3206 | - T1 = e2 & 0x00f0ff00; | |
3207 | 3241 | CC_SRC = eflags | CC_Z; |
3242 | + return e2 & 0x00f0ff00; | |
3208 | 3243 | } |
3209 | 3244 | |
3210 | 3245 | void helper_verr(uint32_t selector) |
... | ... | @@ -4412,36 +4447,36 @@ static int idiv64(uint64_t *plow, uint64_t *phigh, int64_t b) |
4412 | 4447 | return 0; |
4413 | 4448 | } |
4414 | 4449 | |
4415 | -void helper_mulq_EAX_T0(void) | |
4450 | +void helper_mulq_EAX_T0(target_ulong t0) | |
4416 | 4451 | { |
4417 | 4452 | uint64_t r0, r1; |
4418 | 4453 | |
4419 | - mulu64(&r0, &r1, EAX, T0); | |
4454 | + mulu64(&r0, &r1, EAX, t0); | |
4420 | 4455 | EAX = r0; |
4421 | 4456 | EDX = r1; |
4422 | 4457 | CC_DST = r0; |
4423 | 4458 | CC_SRC = r1; |
4424 | 4459 | } |
4425 | 4460 | |
4426 | -void helper_imulq_EAX_T0(void) | |
4461 | +void helper_imulq_EAX_T0(target_ulong t0) | |
4427 | 4462 | { |
4428 | 4463 | uint64_t r0, r1; |
4429 | 4464 | |
4430 | - muls64(&r0, &r1, EAX, T0); | |
4465 | + muls64(&r0, &r1, EAX, t0); | |
4431 | 4466 | EAX = r0; |
4432 | 4467 | EDX = r1; |
4433 | 4468 | CC_DST = r0; |
4434 | 4469 | CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); |
4435 | 4470 | } |
4436 | 4471 | |
4437 | -void helper_imulq_T0_T1(void) | |
4472 | +target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1) | |
4438 | 4473 | { |
4439 | 4474 | uint64_t r0, r1; |
4440 | 4475 | |
4441 | - muls64(&r0, &r1, T0, T1); | |
4442 | - T0 = r0; | |
4476 | + muls64(&r0, &r1, t0, t1); | |
4443 | 4477 | CC_DST = r0; |
4444 | 4478 | CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63)); |
4479 | + return r0; | |
4445 | 4480 | } |
4446 | 4481 | |
4447 | 4482 | void helper_divq_EAX(target_ulong t0) |
... | ... | @@ -4553,24 +4588,23 @@ void helper_reset_inhibit_irq(void) |
4553 | 4588 | env->hflags &= ~HF_INHIBIT_IRQ_MASK; |
4554 | 4589 | } |
4555 | 4590 | |
4556 | -void helper_boundw(void) | |
4591 | +void helper_boundw(target_ulong a0, int v) | |
4557 | 4592 | { |
4558 | - int low, high, v; | |
4559 | - low = ldsw(A0); | |
4560 | - high = ldsw(A0 + 2); | |
4561 | - v = (int16_t)T0; | |
4593 | + int low, high; | |
4594 | + low = ldsw(a0); | |
4595 | + high = ldsw(a0 + 2); | |
4596 | + v = (int16_t)v; | |
4562 | 4597 | if (v < low || v > high) { |
4563 | 4598 | raise_exception(EXCP05_BOUND); |
4564 | 4599 | } |
4565 | 4600 | FORCE_RET(); |
4566 | 4601 | } |
4567 | 4602 | |
4568 | -void helper_boundl(void) | |
4603 | +void helper_boundl(target_ulong a0, int v) | |
4569 | 4604 | { |
4570 | - int low, high, v; | |
4571 | - low = ldl(A0); | |
4572 | - high = ldl(A0 + 4); | |
4573 | - v = T0; | |
4605 | + int low, high; | |
4606 | + low = ldl(a0); | |
4607 | + high = ldl(a0 + 4); | |
4574 | 4608 | if (v < low || v > high) { |
4575 | 4609 | raise_exception(EXCP05_BOUND); |
4576 | 4610 | } |
... | ... | @@ -4661,18 +4695,35 @@ void helper_clgi(void) |
4661 | 4695 | |
4662 | 4696 | #if defined(CONFIG_USER_ONLY) |
4663 | 4697 | |
4664 | -void helper_vmrun(void) { } | |
4665 | -void helper_vmmcall(void) { } | |
4666 | -void helper_vmload(void) { } | |
4667 | -void helper_vmsave(void) { } | |
4668 | -void helper_skinit(void) { } | |
4669 | -void helper_invlpga(void) { } | |
4670 | -void vmexit(uint64_t exit_code, uint64_t exit_info_1) { } | |
4671 | -int svm_check_intercept_param(uint32_t type, uint64_t param) | |
4698 | +void helper_vmrun(void) | |
4699 | +{ | |
4700 | +} | |
4701 | +void helper_vmmcall(void) | |
4702 | +{ | |
4703 | +} | |
4704 | +void helper_vmload(void) | |
4705 | +{ | |
4706 | +} | |
4707 | +void helper_vmsave(void) | |
4708 | +{ | |
4709 | +} | |
4710 | +void helper_skinit(void) | |
4711 | +{ | |
4712 | +} | |
4713 | +void helper_invlpga(void) | |
4714 | +{ | |
4715 | +} | |
4716 | +void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | |
4717 | +{ | |
4718 | +} | |
4719 | +void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | |
4672 | 4720 | { |
4673 | - return 0; | |
4674 | 4721 | } |
4675 | 4722 | |
4723 | +void helper_svm_check_io(uint32_t port, uint32_t param, | |
4724 | + uint32_t next_eip_addend) | |
4725 | +{ | |
4726 | +} | |
4676 | 4727 | #else |
4677 | 4728 | |
4678 | 4729 | static inline uint32_t |
... | ... | @@ -4702,7 +4753,6 @@ void helper_vmrun(void) |
4702 | 4753 | fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr); |
4703 | 4754 | |
4704 | 4755 | env->vm_vmcb = addr; |
4705 | - regs_to_env(); | |
4706 | 4756 | |
4707 | 4757 | /* save the current CPU state in the hsave page */ |
4708 | 4758 | stq_phys(env->vm_hsave + offsetof(struct vmcb, save.gdtr.base), env->gdt.base); |
... | ... | @@ -4801,8 +4851,6 @@ void helper_vmrun(void) |
4801 | 4851 | |
4802 | 4852 | helper_stgi(); |
4803 | 4853 | |
4804 | - regs_to_env(); | |
4805 | - | |
4806 | 4854 | /* maybe we need to inject an event */ |
4807 | 4855 | event_inj = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj)); |
4808 | 4856 | if (event_inj & SVM_EVTINJ_VALID) { |
... | ... | @@ -4927,95 +4975,98 @@ void helper_invlpga(void) |
4927 | 4975 | tlb_flush(env, 0); |
4928 | 4976 | } |
4929 | 4977 | |
4930 | -int svm_check_intercept_param(uint32_t type, uint64_t param) | |
4978 | +void helper_svm_check_intercept_param(uint32_t type, uint64_t param) | |
4931 | 4979 | { |
4932 | 4980 | switch(type) { |
4933 | 4981 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_READ_CR0 + 8: |
4934 | 4982 | if (INTERCEPTEDw(_cr_read, (1 << (type - SVM_EXIT_READ_CR0)))) { |
4935 | - vmexit(type, param); | |
4936 | - return 1; | |
4983 | + helper_vmexit(type, param); | |
4937 | 4984 | } |
4938 | 4985 | break; |
4939 | 4986 | case SVM_EXIT_READ_DR0 ... SVM_EXIT_READ_DR0 + 8: |
4940 | 4987 | if (INTERCEPTEDw(_dr_read, (1 << (type - SVM_EXIT_READ_DR0)))) { |
4941 | - vmexit(type, param); | |
4942 | - return 1; | |
4988 | + helper_vmexit(type, param); | |
4943 | 4989 | } |
4944 | 4990 | break; |
4945 | 4991 | case SVM_EXIT_WRITE_CR0 ... SVM_EXIT_WRITE_CR0 + 8: |
4946 | 4992 | if (INTERCEPTEDw(_cr_write, (1 << (type - SVM_EXIT_WRITE_CR0)))) { |
4947 | - vmexit(type, param); | |
4948 | - return 1; | |
4993 | + helper_vmexit(type, param); | |
4949 | 4994 | } |
4950 | 4995 | break; |
4951 | 4996 | case SVM_EXIT_WRITE_DR0 ... SVM_EXIT_WRITE_DR0 + 8: |
4952 | 4997 | if (INTERCEPTEDw(_dr_write, (1 << (type - SVM_EXIT_WRITE_DR0)))) { |
4953 | - vmexit(type, param); | |
4954 | - return 1; | |
4998 | + helper_vmexit(type, param); | |
4955 | 4999 | } |
4956 | 5000 | break; |
4957 | 5001 | case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 16: |
4958 | 5002 | if (INTERCEPTEDl(_exceptions, (1 << (type - SVM_EXIT_EXCP_BASE)))) { |
4959 | - vmexit(type, param); | |
4960 | - return 1; | |
5003 | + helper_vmexit(type, param); | |
4961 | 5004 | } |
4962 | 5005 | break; |
4963 | 5006 | case SVM_EXIT_IOIO: |
4964 | - if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) { | |
4965 | - /* FIXME: this should be read in at vmrun (faster this way?) */ | |
4966 | - uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); | |
4967 | - uint16_t port = (uint16_t) (param >> 16); | |
4968 | - | |
4969 | - uint16_t mask = (1 << ((param >> 4) & 7)) - 1; | |
4970 | - if(lduw_phys(addr + port / 8) & (mask << (port & 7))) | |
4971 | - vmexit(type, param); | |
4972 | - } | |
4973 | 5007 | break; |
4974 | 5008 | |
4975 | 5009 | case SVM_EXIT_MSR: |
4976 | 5010 | if (INTERCEPTED(1ULL << INTERCEPT_MSR_PROT)) { |
4977 | 5011 | /* FIXME: this should be read in at vmrun (faster this way?) */ |
4978 | 5012 | uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.msrpm_base_pa)); |
5013 | + uint32_t t0, t1; | |
4979 | 5014 | switch((uint32_t)ECX) { |
4980 | 5015 | case 0 ... 0x1fff: |
4981 | - T0 = (ECX * 2) % 8; | |
4982 | - T1 = ECX / 8; | |
5016 | + t0 = (ECX * 2) % 8; | |
5017 | + t1 = ECX / 8; | |
4983 | 5018 | break; |
4984 | 5019 | case 0xc0000000 ... 0xc0001fff: |
4985 | - T0 = (8192 + ECX - 0xc0000000) * 2; | |
4986 | - T1 = (T0 / 8); | |
4987 | - T0 %= 8; | |
5020 | + t0 = (8192 + ECX - 0xc0000000) * 2; | |
5021 | + t1 = (t0 / 8); | |
5022 | + t0 %= 8; | |
4988 | 5023 | break; |
4989 | 5024 | case 0xc0010000 ... 0xc0011fff: |
4990 | - T0 = (16384 + ECX - 0xc0010000) * 2; | |
4991 | - T1 = (T0 / 8); | |
4992 | - T0 %= 8; | |
5025 | + t0 = (16384 + ECX - 0xc0010000) * 2; | |
5026 | + t1 = (t0 / 8); | |
5027 | + t0 %= 8; | |
4993 | 5028 | break; |
4994 | 5029 | default: |
4995 | - vmexit(type, param); | |
4996 | - return 1; | |
5030 | + helper_vmexit(type, param); | |
5031 | + t0 = 0; | |
5032 | + t1 = 0; | |
5033 | + break; | |
4997 | 5034 | } |
4998 | - if (ldub_phys(addr + T1) & ((1 << param) << T0)) | |
4999 | - vmexit(type, param); | |
5000 | - return 1; | |
5035 | + if (ldub_phys(addr + t1) & ((1 << param) << t0)) | |
5036 | + helper_vmexit(type, param); | |
5001 | 5037 | } |
5002 | 5038 | break; |
5003 | 5039 | default: |
5004 | 5040 | if (INTERCEPTED((1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR)))) { |
5005 | - vmexit(type, param); | |
5006 | - return 1; | |
5041 | + helper_vmexit(type, param); | |
5007 | 5042 | } |
5008 | 5043 | break; |
5009 | 5044 | } |
5010 | - return 0; | |
5011 | 5045 | } |
5012 | 5046 | |
5013 | -void vmexit(uint64_t exit_code, uint64_t exit_info_1) | |
5047 | +void helper_svm_check_io(uint32_t port, uint32_t param, | |
5048 | + uint32_t next_eip_addend) | |
5049 | +{ | |
5050 | + if (INTERCEPTED(1ULL << INTERCEPT_IOIO_PROT)) { | |
5051 | + /* FIXME: this should be read in at vmrun (faster this way?) */ | |
5052 | + uint64_t addr = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.iopm_base_pa)); | |
5053 | + uint16_t mask = (1 << ((param >> 4) & 7)) - 1; | |
5054 | + if(lduw_phys(addr + port / 8) & (mask << (port & 7))) { | |
5055 | + /* next EIP */ | |
5056 | + stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), | |
5057 | + env->eip + next_eip_addend); | |
5058 | + helper_vmexit(SVM_EXIT_IOIO, param | (port << 16)); | |
5059 | + } | |
5060 | + } | |
5061 | +} | |
5062 | + | |
5063 | +/* Note: currently only 32 bits of exit_code are used */ | |
5064 | +void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | |
5014 | 5065 | { |
5015 | 5066 | uint32_t int_ctl; |
5016 | 5067 | |
5017 | 5068 | if (loglevel & CPU_LOG_TB_IN_ASM) |
5018 | - fprintf(logfile,"vmexit(%016" PRIx64 ", %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n", | |
5069 | + fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n", | |
5019 | 5070 | exit_code, exit_info_1, |
5020 | 5071 | ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)), |
5021 | 5072 | EIP); |
... | ... | @@ -5105,8 +5156,7 @@ void vmexit(uint64_t exit_code, uint64_t exit_info_1) |
5105 | 5156 | |
5106 | 5157 | /* other setups */ |
5107 | 5158 | cpu_x86_set_cpl(env, 0); |
5108 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code_hi), (uint32_t)(exit_code >> 32)); | |
5109 | - stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); | |
5159 | + stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_code), exit_code); | |
5110 | 5160 | stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_1), exit_info_1); |
5111 | 5161 | |
5112 | 5162 | helper_clgi(); |
... | ... | @@ -5137,7 +5187,6 @@ void vmexit(uint64_t exit_code, uint64_t exit_info_1) |
5137 | 5187 | env->error_code = 0; |
5138 | 5188 | env->old_exception = -1; |
5139 | 5189 | |
5140 | - regs_to_env(); | |
5141 | 5190 | cpu_loop_exit(); |
5142 | 5191 | } |
5143 | 5192 | ... | ... |
target-i386/helper.h
1 | 1 | #define TCG_HELPER_PROTO |
2 | 2 | |
3 | +void helper_lock(void); | |
4 | +void helper_unlock(void); | |
3 | 5 | void helper_divb_AL(target_ulong t0); |
4 | 6 | void helper_idivb_AL(target_ulong t0); |
5 | 7 | void helper_divw_AX(target_ulong t0); |
... | ... | @@ -7,6 +9,9 @@ void helper_idivw_AX(target_ulong t0); |
7 | 9 | void helper_divl_EAX(target_ulong t0); |
8 | 10 | void helper_idivl_EAX(target_ulong t0); |
9 | 11 | #ifdef TARGET_X86_64 |
12 | +void helper_mulq_EAX_T0(target_ulong t0); | |
13 | +void helper_imulq_EAX_T0(target_ulong t0); | |
14 | +target_ulong helper_imulq_T0_T1(target_ulong t0, target_ulong t1); | |
10 | 15 | void helper_divq_EAX(target_ulong t0); |
11 | 16 | void helper_idivq_EAX(target_ulong t0); |
12 | 17 | #endif |
... | ... | @@ -18,26 +23,34 @@ void helper_aas(void); |
18 | 23 | void helper_daa(void); |
19 | 24 | void helper_das(void); |
20 | 25 | |
21 | -void helper_lsl(uint32_t selector); | |
22 | -void helper_lar(uint32_t selector); | |
26 | +uint32_t helper_lsl(uint32_t selector); | |
27 | +uint32_t helper_lar(uint32_t selector); | |
23 | 28 | void helper_verr(uint32_t selector); |
24 | 29 | void helper_verw(uint32_t selector); |
25 | 30 | void helper_lldt(int selector); |
26 | 31 | void helper_ltr(int selector); |
27 | 32 | void helper_load_seg(int seg_reg, int selector); |
28 | -void helper_ljmp_protected_T0_T1(int next_eip); | |
29 | -void helper_lcall_real_T0_T1(int shift, int next_eip); | |
30 | -void helper_lcall_protected_T0_T1(int shift, int next_eip); | |
33 | +void helper_ljmp_protected(int new_cs, target_ulong new_eip, | |
34 | + int next_eip_addend); | |
35 | +void helper_lcall_real(int new_cs, target_ulong new_eip1, | |
36 | + int shift, int next_eip); | |
37 | +void helper_lcall_protected(int new_cs, target_ulong new_eip, | |
38 | + int shift, int next_eip_addend); | |
31 | 39 | void helper_iret_real(int shift); |
32 | 40 | void helper_iret_protected(int shift, int next_eip); |
33 | 41 | void helper_lret_protected(int shift, int addend); |
34 | -void helper_movl_crN_T0(int reg); | |
35 | -void helper_movl_drN_T0(int reg); | |
42 | +void helper_movl_crN_T0(int reg, target_ulong t0); | |
43 | +void helper_lmsw(target_ulong t0); | |
44 | +void helper_clts(void); | |
45 | +#if !defined(CONFIG_USER_ONLY) | |
46 | +target_ulong helper_movtl_T0_cr8(void); | |
47 | +#endif | |
48 | +void helper_movl_drN_T0(int reg, target_ulong t0); | |
36 | 49 | void helper_invlpg(target_ulong addr); |
37 | 50 | |
38 | -void helper_enter_level(int level, int data32); | |
51 | +void helper_enter_level(int level, int data32, target_ulong t1); | |
39 | 52 | #ifdef TARGET_X86_64 |
40 | -void helper_enter64_level(int level, int data64); | |
53 | +void helper_enter64_level(int level, int data64, target_ulong t1); | |
41 | 54 | #endif |
42 | 55 | void helper_sysenter(void); |
43 | 56 | void helper_sysexit(void); |
... | ... | @@ -55,9 +68,10 @@ void helper_cli(void); |
55 | 68 | void helper_sti(void); |
56 | 69 | void helper_set_inhibit_irq(void); |
57 | 70 | void helper_reset_inhibit_irq(void); |
58 | -void helper_boundw(void); | |
59 | -void helper_boundl(void); | |
71 | +void helper_boundw(target_ulong a0, int v); | |
72 | +void helper_boundl(target_ulong a0, int v); | |
60 | 73 | void helper_rsm(void); |
74 | +void helper_cmpxchg8b(target_ulong a0); | |
61 | 75 | void helper_single_step(void); |
62 | 76 | void helper_cpuid(void); |
63 | 77 | void helper_rdtsc(void); |
... | ... | @@ -65,6 +79,20 @@ void helper_rdpmc(void); |
65 | 79 | void helper_rdmsr(void); |
66 | 80 | void helper_wrmsr(void); |
67 | 81 | |
82 | +void helper_check_iob(uint32_t t0); | |
83 | +void helper_check_iow(uint32_t t0); | |
84 | +void helper_check_iol(uint32_t t0); | |
85 | +void helper_outb(uint32_t port, uint32_t data); | |
86 | +target_ulong helper_inb(uint32_t port); | |
87 | +void helper_outw(uint32_t port, uint32_t data); | |
88 | +target_ulong helper_inw(uint32_t port); | |
89 | +void helper_outl(uint32_t port, uint32_t data); | |
90 | +target_ulong helper_inl(uint32_t port); | |
91 | + | |
92 | +void helper_svm_check_intercept_param(uint32_t type, uint64_t param); | |
93 | +void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1); | |
94 | +void helper_svm_check_io(uint32_t port, uint32_t param, | |
95 | + uint32_t next_eip_addend); | |
68 | 96 | void helper_vmrun(void); |
69 | 97 | void helper_vmmcall(void); |
70 | 98 | void helper_vmload(void); | ... | ... |
target-i386/op.c
... | ... | @@ -276,17 +276,17 @@ void OPPROTO op_imull_T0_T1(void) |
276 | 276 | #ifdef TARGET_X86_64 |
277 | 277 | void OPPROTO op_mulq_EAX_T0(void) |
278 | 278 | { |
279 | - helper_mulq_EAX_T0(); | |
279 | + helper_mulq_EAX_T0(T0); | |
280 | 280 | } |
281 | 281 | |
282 | 282 | void OPPROTO op_imulq_EAX_T0(void) |
283 | 283 | { |
284 | - helper_imulq_EAX_T0(); | |
284 | + helper_imulq_EAX_T0(T0); | |
285 | 285 | } |
286 | 286 | |
287 | 287 | void OPPROTO op_imulq_T0_T1(void) |
288 | 288 | { |
289 | - helper_imulq_T0_T1(); | |
289 | + T0 = helper_imulq_T0_T1(T0, T1); | |
290 | 290 | } |
291 | 291 | #endif |
292 | 292 | |
... | ... | @@ -351,7 +351,7 @@ void OPPROTO op_into(void) |
351 | 351 | |
352 | 352 | void OPPROTO op_cmpxchg8b(void) |
353 | 353 | { |
354 | - helper_cmpxchg8b(); | |
354 | + helper_cmpxchg8b(A0); | |
355 | 355 | } |
356 | 356 | |
357 | 357 | /* multiple size ops */ |
... | ... | @@ -522,12 +522,6 @@ void OPPROTO op_das(void) |
522 | 522 | |
523 | 523 | /* segment handling */ |
524 | 524 | |
525 | -/* never use it with R_CS */ | |
526 | -void OPPROTO op_movl_seg_T0(void) | |
527 | -{ | |
528 | - helper_load_seg(PARAM1, T0); | |
529 | -} | |
530 | - | |
531 | 525 | /* faster VM86 version */ |
532 | 526 | void OPPROTO op_movl_seg_T0_vm(void) |
533 | 527 | { |
... | ... | @@ -548,12 +542,20 @@ void OPPROTO op_movl_T0_seg(void) |
548 | 542 | |
549 | 543 | void OPPROTO op_lsl(void) |
550 | 544 | { |
551 | - helper_lsl(T0); | |
545 | + uint32_t val; | |
546 | + val = helper_lsl(T0); | |
547 | + if (CC_SRC & CC_Z) | |
548 | + T1 = val; | |
549 | + FORCE_RET(); | |
552 | 550 | } |
553 | 551 | |
554 | 552 | void OPPROTO op_lar(void) |
555 | 553 | { |
556 | - helper_lar(T0); | |
554 | + uint32_t val; | |
555 | + val = helper_lar(T0); | |
556 | + if (CC_SRC & CC_Z) | |
557 | + T1 = val; | |
558 | + FORCE_RET(); | |
557 | 559 | } |
558 | 560 | |
559 | 561 | void OPPROTO op_verr(void) |
... | ... | @@ -585,104 +587,6 @@ void OPPROTO op_arpl_update(void) |
585 | 587 | CC_SRC = (eflags & ~CC_Z) | T1; |
586 | 588 | } |
587 | 589 | |
588 | -/* T0: segment, T1:eip */ | |
589 | -void OPPROTO op_ljmp_protected_T0_T1(void) | |
590 | -{ | |
591 | - helper_ljmp_protected_T0_T1(PARAM1); | |
592 | -} | |
593 | - | |
594 | -void OPPROTO op_lcall_real_T0_T1(void) | |
595 | -{ | |
596 | - helper_lcall_real_T0_T1(PARAM1, PARAM2); | |
597 | -} | |
598 | - | |
599 | -void OPPROTO op_lcall_protected_T0_T1(void) | |
600 | -{ | |
601 | - helper_lcall_protected_T0_T1(PARAM1, PARAM2); | |
602 | -} | |
603 | - | |
604 | -void OPPROTO op_iret_real(void) | |
605 | -{ | |
606 | - helper_iret_real(PARAM1); | |
607 | -} | |
608 | - | |
609 | -void OPPROTO op_iret_protected(void) | |
610 | -{ | |
611 | - helper_iret_protected(PARAM1, PARAM2); | |
612 | -} | |
613 | - | |
614 | -void OPPROTO op_lret_protected(void) | |
615 | -{ | |
616 | - helper_lret_protected(PARAM1, PARAM2); | |
617 | -} | |
618 | - | |
619 | -/* CR registers access. */ | |
620 | -void OPPROTO op_movl_crN_T0(void) | |
621 | -{ | |
622 | - helper_movl_crN_T0(PARAM1); | |
623 | -} | |
624 | - | |
625 | -/* These pseudo-opcodes check for SVM intercepts. */ | |
626 | -void OPPROTO op_svm_check_intercept(void) | |
627 | -{ | |
628 | - A0 = PARAM1 & PARAM2; | |
629 | - svm_check_intercept(PARAMQ1); | |
630 | -} | |
631 | - | |
632 | -void OPPROTO op_svm_check_intercept_param(void) | |
633 | -{ | |
634 | - A0 = PARAM1 & PARAM2; | |
635 | - svm_check_intercept_param(PARAMQ1, T1); | |
636 | -} | |
637 | - | |
638 | -void OPPROTO op_svm_vmexit(void) | |
639 | -{ | |
640 | - A0 = PARAM1 & PARAM2; | |
641 | - vmexit(PARAMQ1, T1); | |
642 | -} | |
643 | - | |
644 | -void OPPROTO op_geneflags(void) | |
645 | -{ | |
646 | - CC_SRC = cc_table[CC_OP].compute_all(); | |
647 | -} | |
648 | - | |
649 | -/* This pseudo-opcode checks for IO intercepts. */ | |
650 | -#if !defined(CONFIG_USER_ONLY) | |
651 | -void OPPROTO op_svm_check_intercept_io(void) | |
652 | -{ | |
653 | - A0 = PARAM1 & PARAM2; | |
654 | - /* PARAMQ1 = TYPE (0 = OUT, 1 = IN; 4 = STRING; 8 = REP) | |
655 | - T0 = PORT | |
656 | - T1 = next eip */ | |
657 | - stq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), T1); | |
658 | - /* ASIZE does not appear on real hw */ | |
659 | - svm_check_intercept_param(SVM_EXIT_IOIO, | |
660 | - (PARAMQ1 & ~SVM_IOIO_ASIZE_MASK) | | |
661 | - ((T0 & 0xffff) << 16)); | |
662 | -} | |
663 | -#endif | |
664 | - | |
665 | -#if !defined(CONFIG_USER_ONLY) | |
666 | -void OPPROTO op_movtl_T0_cr8(void) | |
667 | -{ | |
668 | - T0 = cpu_get_apic_tpr(env); | |
669 | -} | |
670 | -#endif | |
671 | - | |
672 | -/* DR registers access */ | |
673 | -void OPPROTO op_movl_drN_T0(void) | |
674 | -{ | |
675 | - helper_movl_drN_T0(PARAM1); | |
676 | -} | |
677 | - | |
678 | -void OPPROTO op_lmsw_T0(void) | |
679 | -{ | |
680 | - /* only 4 lower bits of CR0 are modified. PE cannot be set to zero | |
681 | - if already set to one. */ | |
682 | - T0 = (env->cr[0] & ~0xe) | (T0 & 0xf); | |
683 | - helper_movl_crN_T0(0); | |
684 | -} | |
685 | - | |
686 | 590 | void OPPROTO op_movl_T0_env(void) |
687 | 591 | { |
688 | 592 | T0 = *(uint32_t *)((char *)env + PARAM1); |
... | ... | @@ -718,12 +622,6 @@ void OPPROTO op_movtl_env_T1(void) |
718 | 622 | *(target_ulong *)((char *)env + PARAM1) = T1; |
719 | 623 | } |
720 | 624 | |
721 | -void OPPROTO op_clts(void) | |
722 | -{ | |
723 | - env->cr[0] &= ~CR0_TS_MASK; | |
724 | - env->hflags &= ~HF_TS_MASK; | |
725 | -} | |
726 | - | |
727 | 625 | /* flags handling */ |
728 | 626 | |
729 | 627 | void OPPROTO op_jmp_label(void) |
... | ... | @@ -1028,17 +926,6 @@ void OPPROTO op_fcomi_dummy(void) |
1028 | 926 | T0 = 0; |
1029 | 927 | } |
1030 | 928 | |
1031 | -/* threading support */ | |
1032 | -void OPPROTO op_lock(void) | |
1033 | -{ | |
1034 | - cpu_lock(); | |
1035 | -} | |
1036 | - | |
1037 | -void OPPROTO op_unlock(void) | |
1038 | -{ | |
1039 | - cpu_unlock(); | |
1040 | -} | |
1041 | - | |
1042 | 929 | /* SSE support */ |
1043 | 930 | void OPPROTO op_com_dummy(void) |
1044 | 931 | { | ... | ... |
target-i386/ops_sse.h
... | ... | @@ -471,12 +471,12 @@ void glue(helper_psadbw, SUFFIX) (Reg *d, Reg *s) |
471 | 471 | #endif |
472 | 472 | } |
473 | 473 | |
474 | -void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s) | |
474 | +void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0) | |
475 | 475 | { |
476 | 476 | int i; |
477 | 477 | for(i = 0; i < (8 << SHIFT); i++) { |
478 | 478 | if (s->B(i) & 0x80) |
479 | - stb(A0 + i, d->B(i)); | |
479 | + stb(a0 + i, d->B(i)); | |
480 | 480 | } |
481 | 481 | FORCE_RET(); |
482 | 482 | } | ... | ... |
target-i386/ops_sse_header.h
... | ... | @@ -104,7 +104,7 @@ void glue(helper_pmuludq, SUFFIX) (Reg *d, Reg *s); |
104 | 104 | void glue(helper_pmaddwd, SUFFIX) (Reg *d, Reg *s); |
105 | 105 | |
106 | 106 | void glue(helper_psadbw, SUFFIX) (Reg *d, Reg *s); |
107 | -void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s); | |
107 | +void glue(helper_maskmov, SUFFIX) (Reg *d, Reg *s, target_ulong a0); | |
108 | 108 | void glue(helper_movl_mm_T0, SUFFIX) (Reg *d, uint32_t val); |
109 | 109 | #ifdef TARGET_X86_64 |
110 | 110 | void glue(helper_movq_mm_T0, SUFFIX) (Reg *d, uint64_t val); | ... | ... |
target-i386/ops_template.h
... | ... | @@ -554,39 +554,6 @@ void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void) |
554 | 554 | T0 = DF << SHIFT; |
555 | 555 | } |
556 | 556 | |
557 | -/* port I/O */ | |
558 | -#if DATA_BITS <= 32 | |
559 | -void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) | |
560 | -{ | |
561 | - glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK); | |
562 | -} | |
563 | - | |
564 | -void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void) | |
565 | -{ | |
566 | - T1 = glue(cpu_in, SUFFIX)(env, T0); | |
567 | -} | |
568 | - | |
569 | -void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void) | |
570 | -{ | |
571 | - T0 = glue(cpu_in, SUFFIX)(env, EDX & 0xffff); | |
572 | -} | |
573 | - | |
574 | -void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void) | |
575 | -{ | |
576 | - glue(cpu_out, SUFFIX)(env, EDX & 0xffff, T0); | |
577 | -} | |
578 | - | |
579 | -void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void) | |
580 | -{ | |
581 | - glue(glue(check_io, SUFFIX), _T0)(); | |
582 | -} | |
583 | - | |
584 | -void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void) | |
585 | -{ | |
586 | - glue(glue(check_io, SUFFIX), _DX)(); | |
587 | -} | |
588 | -#endif | |
589 | - | |
590 | 557 | #undef DATA_BITS |
591 | 558 | #undef SHIFT_MASK |
592 | 559 | #undef SHIFT1_MASK | ... | ... |
target-i386/svm.h
... | ... | @@ -71,8 +71,7 @@ struct __attribute__ ((__packed__)) vmcb_control_area { |
71 | 71 | uint32_t int_vector; |
72 | 72 | uint32_t int_state; |
73 | 73 | uint8_t reserved_3[4]; |
74 | - uint32_t exit_code; | |
75 | - uint32_t exit_code_hi; | |
74 | + uint64_t exit_code; | |
76 | 75 | uint64_t exit_info_1; |
77 | 76 | uint64_t exit_info_2; |
78 | 77 | uint32_t exit_int_info; |
... | ... | @@ -323,14 +322,6 @@ struct __attribute__ ((__packed__)) vmcb { |
323 | 322 | |
324 | 323 | /* function references */ |
325 | 324 | |
326 | -void helper_stgi(void); | |
327 | -void vmexit(uint64_t exit_code, uint64_t exit_info_1); | |
328 | -int svm_check_intercept_param(uint32_t type, uint64_t param); | |
329 | -static inline int svm_check_intercept(unsigned int type) { | |
330 | - return svm_check_intercept_param(type, 0); | |
331 | -} | |
332 | - | |
333 | - | |
334 | 325 | #define INTERCEPTED(mask) (env->intercept & mask) |
335 | 326 | #define INTERCEPTEDw(var, mask) (env->intercept ## var & mask) |
336 | 327 | #define INTERCEPTEDl(var, mask) (env->intercept ## var & mask) | ... | ... |
target-i386/translate.c
... | ... | @@ -60,7 +60,7 @@ |
60 | 60 | /* global register indexes */ |
61 | 61 | static TCGv cpu_env, cpu_T[2], cpu_A0; |
62 | 62 | /* local register indexes (only used inside old micro ops) */ |
63 | -static TCGv cpu_tmp0, cpu_tmp1, cpu_tmp2, cpu_ptr0, cpu_ptr1; | |
63 | +static TCGv cpu_tmp0, cpu_tmp1, cpu_tmp2, cpu_tmp3, cpu_ptr0, cpu_ptr1; | |
64 | 64 | |
65 | 65 | #ifdef TARGET_X86_64 |
66 | 66 | static int x86_64_hregs; |
... | ... | @@ -903,52 +903,54 @@ static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { |
903 | 903 | }, |
904 | 904 | }; |
905 | 905 | |
906 | -static GenOpFunc *gen_op_in_DX_T0[3] = { | |
907 | - gen_op_inb_DX_T0, | |
908 | - gen_op_inw_DX_T0, | |
909 | - gen_op_inl_DX_T0, | |
906 | +static void *helper_in_func[3] = { | |
907 | + helper_inb, | |
908 | + helper_inw, | |
909 | + helper_inl, | |
910 | 910 | }; |
911 | 911 | |
912 | -static GenOpFunc *gen_op_out_DX_T0[3] = { | |
913 | - gen_op_outb_DX_T0, | |
914 | - gen_op_outw_DX_T0, | |
915 | - gen_op_outl_DX_T0, | |
912 | +static void *helper_out_func[3] = { | |
913 | + helper_outb, | |
914 | + helper_outw, | |
915 | + helper_outl, | |
916 | 916 | }; |
917 | 917 | |
918 | -static GenOpFunc *gen_op_in[3] = { | |
919 | - gen_op_inb_T0_T1, | |
920 | - gen_op_inw_T0_T1, | |
921 | - gen_op_inl_T0_T1, | |
918 | +static void *gen_check_io_func[3] = { | |
919 | + helper_check_iob, | |
920 | + helper_check_iow, | |
921 | + helper_check_iol, | |
922 | 922 | }; |
923 | 923 | |
924 | -static GenOpFunc *gen_op_out[3] = { | |
925 | - gen_op_outb_T0_T1, | |
926 | - gen_op_outw_T0_T1, | |
927 | - gen_op_outl_T0_T1, | |
928 | -}; | |
929 | - | |
930 | -static GenOpFunc *gen_check_io_T0[3] = { | |
931 | - gen_op_check_iob_T0, | |
932 | - gen_op_check_iow_T0, | |
933 | - gen_op_check_iol_T0, | |
934 | -}; | |
935 | - | |
936 | -static GenOpFunc *gen_check_io_DX[3] = { | |
937 | - gen_op_check_iob_DX, | |
938 | - gen_op_check_iow_DX, | |
939 | - gen_op_check_iol_DX, | |
940 | -}; | |
941 | - | |
942 | -static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_eip) | |
924 | +static void gen_check_io(DisasContext *s, int ot, target_ulong cur_eip, | |
925 | + uint32_t svm_flags) | |
943 | 926 | { |
927 | + int state_saved; | |
928 | + target_ulong next_eip; | |
929 | + | |
930 | + state_saved = 0; | |
944 | 931 | if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
945 | 932 | if (s->cc_op != CC_OP_DYNAMIC) |
946 | 933 | gen_op_set_cc_op(s->cc_op); |
947 | 934 | gen_jmp_im(cur_eip); |
948 | - if (use_dx) | |
949 | - gen_check_io_DX[ot](); | |
950 | - else | |
951 | - gen_check_io_T0[ot](); | |
935 | + state_saved = 1; | |
936 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
937 | + tcg_gen_helper_0_1(gen_check_io_func[ot], | |
938 | + cpu_tmp2); | |
939 | + } | |
940 | + if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) { | |
941 | + if (!state_saved) { | |
942 | + if (s->cc_op != CC_OP_DYNAMIC) | |
943 | + gen_op_set_cc_op(s->cc_op); | |
944 | + gen_jmp_im(cur_eip); | |
945 | + state_saved = 1; | |
946 | + } | |
947 | + svm_flags |= (1 << (4 + ot)); | |
948 | + next_eip = s->pc - s->cs_base; | |
949 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
950 | + tcg_gen_helper_0_3(helper_svm_check_io, | |
951 | + cpu_tmp2, | |
952 | + tcg_const_i32(svm_flags), | |
953 | + tcg_const_i32(next_eip - cur_eip)); | |
952 | 954 | } |
953 | 955 | } |
954 | 956 | |
... | ... | @@ -1080,7 +1082,10 @@ static inline void gen_ins(DisasContext *s, int ot) |
1080 | 1082 | gen_string_movl_A0_EDI(s); |
1081 | 1083 | gen_op_movl_T0_0(); |
1082 | 1084 | gen_op_st_T0_A0(ot + s->mem_index); |
1083 | - gen_op_in_DX_T0[ot](); | |
1085 | + gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); | |
1086 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[1]); | |
1087 | + tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff); | |
1088 | + tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2); | |
1084 | 1089 | gen_op_st_T0_A0(ot + s->mem_index); |
1085 | 1090 | gen_op_movl_T0_Dshift[ot](); |
1086 | 1091 | #ifdef TARGET_X86_64 |
... | ... | @@ -1099,7 +1104,13 @@ static inline void gen_outs(DisasContext *s, int ot) |
1099 | 1104 | { |
1100 | 1105 | gen_string_movl_A0_ESI(s); |
1101 | 1106 | gen_op_ld_T0_A0(ot + s->mem_index); |
1102 | - gen_op_out_DX_T0[ot](); | |
1107 | + | |
1108 | + gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); | |
1109 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[1]); | |
1110 | + tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff); | |
1111 | + tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[0]); | |
1112 | + tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3); | |
1113 | + | |
1103 | 1114 | gen_op_movl_T0_Dshift[ot](); |
1104 | 1115 | #ifdef TARGET_X86_64 |
1105 | 1116 | if (s->aflag == 2) { |
... | ... | @@ -1976,7 +1987,8 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) |
1976 | 1987 | if (s->cc_op != CC_OP_DYNAMIC) |
1977 | 1988 | gen_op_set_cc_op(s->cc_op); |
1978 | 1989 | gen_jmp_im(cur_eip); |
1979 | - gen_op_movl_seg_T0(seg_reg); | |
1990 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
1991 | + tcg_gen_helper_0_2(helper_load_seg, tcg_const_i32(seg_reg), cpu_tmp2); | |
1980 | 1992 | /* abort translation because the addseg value may change or |
1981 | 1993 | because ss32 may change. For R_SS, translation must always |
1982 | 1994 | stop as a special handling must be done to disable hardware |
... | ... | @@ -1990,28 +2002,6 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) |
1990 | 2002 | } |
1991 | 2003 | } |
1992 | 2004 | |
1993 | -#define SVM_movq_T1_im(x) gen_movtl_T1_im(x) | |
1994 | - | |
1995 | -static inline int | |
1996 | -gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type) | |
1997 | -{ | |
1998 | -#if !defined(CONFIG_USER_ONLY) | |
1999 | - if(s->flags & (1ULL << INTERCEPT_IOIO_PROT)) { | |
2000 | - if (s->cc_op != CC_OP_DYNAMIC) | |
2001 | - gen_op_set_cc_op(s->cc_op); | |
2002 | - SVM_movq_T1_im(s->pc - s->cs_base); | |
2003 | - gen_jmp_im(pc_start - s->cs_base); | |
2004 | - gen_op_geneflags(); | |
2005 | - gen_op_svm_check_intercept_io((uint32_t)(type >> 32), (uint32_t)type); | |
2006 | - s->cc_op = CC_OP_DYNAMIC; | |
2007 | - /* FIXME: maybe we could move the io intercept vector to the TB as well | |
2008 | - so we know if this is an EOB or not ... let's assume it's not | |
2009 | - for now. */ | |
2010 | - } | |
2011 | -#endif | |
2012 | - return 0; | |
2013 | -} | |
2014 | - | |
2015 | 2005 | static inline int svm_is_rep(int prefixes) |
2016 | 2006 | { |
2017 | 2007 | return ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) ? 8 : 0); |
... | ... | @@ -2019,7 +2009,7 @@ static inline int svm_is_rep(int prefixes) |
2019 | 2009 | |
2020 | 2010 | static inline int |
2021 | 2011 | gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
2022 | - uint64_t type, uint64_t param) | |
2012 | + uint32_t type, uint64_t param) | |
2023 | 2013 | { |
2024 | 2014 | if(!(s->flags & (INTERCEPT_SVM_MASK))) |
2025 | 2015 | /* no SVM activated */ |
... | ... | @@ -2029,12 +2019,10 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
2029 | 2019 | case SVM_EXIT_READ_CR0 ... SVM_EXIT_EXCP_BASE - 1: |
2030 | 2020 | if (s->cc_op != CC_OP_DYNAMIC) { |
2031 | 2021 | gen_op_set_cc_op(s->cc_op); |
2032 | - s->cc_op = CC_OP_DYNAMIC; | |
2033 | 2022 | } |
2034 | 2023 | gen_jmp_im(pc_start - s->cs_base); |
2035 | - SVM_movq_T1_im(param); | |
2036 | - gen_op_geneflags(); | |
2037 | - gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type); | |
2024 | + tcg_gen_helper_0_2(helper_svm_check_intercept_param, | |
2025 | + tcg_const_i32(type), tcg_const_i64(param)); | |
2038 | 2026 | /* this is a special case as we do not know if the interception occurs |
2039 | 2027 | so we assume there was none */ |
2040 | 2028 | return 0; |
... | ... | @@ -2042,12 +2030,10 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
2042 | 2030 | if(s->flags & (1ULL << INTERCEPT_MSR_PROT)) { |
2043 | 2031 | if (s->cc_op != CC_OP_DYNAMIC) { |
2044 | 2032 | gen_op_set_cc_op(s->cc_op); |
2045 | - s->cc_op = CC_OP_DYNAMIC; | |
2046 | 2033 | } |
2047 | 2034 | gen_jmp_im(pc_start - s->cs_base); |
2048 | - SVM_movq_T1_im(param); | |
2049 | - gen_op_geneflags(); | |
2050 | - gen_op_svm_check_intercept_param((uint32_t)(type >> 32), (uint32_t)type); | |
2035 | + tcg_gen_helper_0_2(helper_svm_check_intercept_param, | |
2036 | + tcg_const_i32(type), tcg_const_i64(param)); | |
2051 | 2037 | /* this is a special case as we do not know if the interception occurs |
2052 | 2038 | so we assume there was none */ |
2053 | 2039 | return 0; |
... | ... | @@ -2057,12 +2043,10 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, |
2057 | 2043 | if(s->flags & (1ULL << ((type - SVM_EXIT_INTR) + INTERCEPT_INTR))) { |
2058 | 2044 | if (s->cc_op != CC_OP_DYNAMIC) { |
2059 | 2045 | gen_op_set_cc_op(s->cc_op); |
2060 | - s->cc_op = CC_OP_EFLAGS; | |
2061 | 2046 | } |
2062 | 2047 | gen_jmp_im(pc_start - s->cs_base); |
2063 | - SVM_movq_T1_im(param); | |
2064 | - gen_op_geneflags(); | |
2065 | - gen_op_svm_vmexit(type >> 32, type); | |
2048 | + tcg_gen_helper_0_2(helper_vmexit, | |
2049 | + tcg_const_i32(type), tcg_const_i64(param)); | |
2066 | 2050 | /* we can optimize this one so TBs don't get longer |
2067 | 2051 | than up to vmexit */ |
2068 | 2052 | gen_eob(s); |
... | ... | @@ -2276,9 +2260,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) |
2276 | 2260 | gen_op_st_T0_A0(ot + s->mem_index); |
2277 | 2261 | if (level) { |
2278 | 2262 | /* XXX: must save state */ |
2279 | - tcg_gen_helper_0_2(helper_enter64_level, | |
2263 | + tcg_gen_helper_0_3(helper_enter64_level, | |
2280 | 2264 | tcg_const_i32(level), |
2281 | - tcg_const_i32((ot == OT_QUAD))); | |
2265 | + tcg_const_i32((ot == OT_QUAD)), | |
2266 | + cpu_T[1]); | |
2282 | 2267 | } |
2283 | 2268 | gen_op_mov_reg_T1(ot, R_EBP); |
2284 | 2269 | gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); |
... | ... | @@ -2301,9 +2286,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) |
2301 | 2286 | gen_op_st_T0_A0(ot + s->mem_index); |
2302 | 2287 | if (level) { |
2303 | 2288 | /* XXX: must save state */ |
2304 | - tcg_gen_helper_0_2(helper_enter_level, | |
2289 | + tcg_gen_helper_0_3(helper_enter_level, | |
2305 | 2290 | tcg_const_i32(level), |
2306 | - tcg_const_i32(s->dflag)); | |
2291 | + tcg_const_i32(s->dflag), | |
2292 | + cpu_T[1]); | |
2307 | 2293 | } |
2308 | 2294 | gen_op_mov_reg_T1(ot, R_EBP); |
2309 | 2295 | gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); |
... | ... | @@ -3208,22 +3194,6 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) |
3208 | 3194 | } else { |
3209 | 3195 | /* generic MMX or SSE operation */ |
3210 | 3196 | switch(b) { |
3211 | - case 0xf7: | |
3212 | - /* maskmov : we must prepare A0 */ | |
3213 | - if (mod != 3) | |
3214 | - goto illegal_op; | |
3215 | -#ifdef TARGET_X86_64 | |
3216 | - if (s->aflag == 2) { | |
3217 | - gen_op_movq_A0_reg(R_EDI); | |
3218 | - } else | |
3219 | -#endif | |
3220 | - { | |
3221 | - gen_op_movl_A0_reg(R_EDI); | |
3222 | - if (s->aflag == 0) | |
3223 | - gen_op_andl_A0_ffff(); | |
3224 | - } | |
3225 | - gen_add_A0_ds_seg(s); | |
3226 | - break; | |
3227 | 3197 | case 0x70: /* pshufx insn */ |
3228 | 3198 | case 0xc6: /* pshufx insn */ |
3229 | 3199 | case 0xc2: /* compare insns */ |
... | ... | @@ -3295,6 +3265,26 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) |
3295 | 3265 | tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
3296 | 3266 | tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1); |
3297 | 3267 | break; |
3268 | + case 0xf7: | |
3269 | + /* maskmov : we must prepare A0 */ | |
3270 | + if (mod != 3) | |
3271 | + goto illegal_op; | |
3272 | +#ifdef TARGET_X86_64 | |
3273 | + if (s->aflag == 2) { | |
3274 | + gen_op_movq_A0_reg(R_EDI); | |
3275 | + } else | |
3276 | +#endif | |
3277 | + { | |
3278 | + gen_op_movl_A0_reg(R_EDI); | |
3279 | + if (s->aflag == 0) | |
3280 | + gen_op_andl_A0_ffff(); | |
3281 | + } | |
3282 | + gen_add_A0_ds_seg(s); | |
3283 | + | |
3284 | + tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); | |
3285 | + tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); | |
3286 | + tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, cpu_A0); | |
3287 | + break; | |
3298 | 3288 | default: |
3299 | 3289 | tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset); |
3300 | 3290 | tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset); |
... | ... | @@ -3440,7 +3430,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3440 | 3430 | |
3441 | 3431 | /* lock generation */ |
3442 | 3432 | if (prefixes & PREFIX_LOCK) |
3443 | - gen_op_lock(); | |
3433 | + tcg_gen_helper_0_0(helper_lock); | |
3444 | 3434 | |
3445 | 3435 | /* now check op code */ |
3446 | 3436 | reswitch: |
... | ... | @@ -3783,9 +3773,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3783 | 3773 | if (s->cc_op != CC_OP_DYNAMIC) |
3784 | 3774 | gen_op_set_cc_op(s->cc_op); |
3785 | 3775 | gen_jmp_im(pc_start - s->cs_base); |
3786 | - gen_op_lcall_protected_T0_T1(dflag, s->pc - pc_start); | |
3776 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
3777 | + tcg_gen_helper_0_4(helper_lcall_protected, | |
3778 | + cpu_tmp2, cpu_T[1], | |
3779 | + tcg_const_i32(dflag), | |
3780 | + tcg_const_i32(s->pc - pc_start)); | |
3787 | 3781 | } else { |
3788 | - gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); | |
3782 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
3783 | + tcg_gen_helper_0_4(helper_lcall_real, | |
3784 | + cpu_tmp2, cpu_T[1], | |
3785 | + tcg_const_i32(dflag), | |
3786 | + tcg_const_i32(s->pc - s->cs_base)); | |
3789 | 3787 | } |
3790 | 3788 | gen_eob(s); |
3791 | 3789 | break; |
... | ... | @@ -3804,7 +3802,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
3804 | 3802 | if (s->cc_op != CC_OP_DYNAMIC) |
3805 | 3803 | gen_op_set_cc_op(s->cc_op); |
3806 | 3804 | gen_jmp_im(pc_start - s->cs_base); |
3807 | - gen_op_ljmp_protected_T0_T1(s->pc - pc_start); | |
3805 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
3806 | + tcg_gen_helper_0_3(helper_ljmp_protected, | |
3807 | + cpu_tmp2, | |
3808 | + cpu_T[1], | |
3809 | + tcg_const_i32(s->pc - pc_start)); | |
3808 | 3810 | } else { |
3809 | 3811 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
3810 | 3812 | gen_op_movl_T0_T1(); |
... | ... | @@ -4355,11 +4357,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
4355 | 4357 | gen_op_mov_TN_reg(ot, 0, reg); |
4356 | 4358 | /* for xchg, lock is implicit */ |
4357 | 4359 | if (!(prefixes & PREFIX_LOCK)) |
4358 | - gen_op_lock(); | |
4360 | + tcg_gen_helper_0_0(helper_lock); | |
4359 | 4361 | gen_op_ld_T1_A0(ot + s->mem_index); |
4360 | 4362 | gen_op_st_T0_A0(ot + s->mem_index); |
4361 | 4363 | if (!(prefixes & PREFIX_LOCK)) |
4362 | - gen_op_unlock(); | |
4364 | + tcg_gen_helper_0_0(helper_unlock); | |
4363 | 4365 | gen_op_mov_reg_T1(ot, reg); |
4364 | 4366 | } |
4365 | 4367 | break; |
... | ... | @@ -5117,13 +5119,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5117 | 5119 | ot = OT_BYTE; |
5118 | 5120 | else |
5119 | 5121 | ot = dflag ? OT_LONG : OT_WORD; |
5120 | - gen_check_io(s, ot, 1, pc_start - s->cs_base); | |
5121 | 5122 | gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
5122 | 5123 | gen_op_andl_T0_ffff(); |
5123 | - if (gen_svm_check_io(s, pc_start, | |
5124 | - SVM_IOIO_TYPE_MASK | (1 << (4+ot)) | | |
5125 | - svm_is_rep(prefixes) | 4 | (1 << (7+s->aflag)))) | |
5126 | - break; | |
5124 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5125 | + SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4); | |
5127 | 5126 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
5128 | 5127 | gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
5129 | 5128 | } else { |
... | ... | @@ -5136,13 +5135,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5136 | 5135 | ot = OT_BYTE; |
5137 | 5136 | else |
5138 | 5137 | ot = dflag ? OT_LONG : OT_WORD; |
5139 | - gen_check_io(s, ot, 1, pc_start - s->cs_base); | |
5140 | 5138 | gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
5141 | 5139 | gen_op_andl_T0_ffff(); |
5142 | - if (gen_svm_check_io(s, pc_start, | |
5143 | - (1 << (4+ot)) | svm_is_rep(prefixes) | | |
5144 | - 4 | (1 << (7+s->aflag)))) | |
5145 | - break; | |
5140 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5141 | + svm_is_rep(prefixes) | 4); | |
5146 | 5142 | if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
5147 | 5143 | gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
5148 | 5144 | } else { |
... | ... | @@ -5161,12 +5157,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5161 | 5157 | ot = dflag ? OT_LONG : OT_WORD; |
5162 | 5158 | val = ldub_code(s->pc++); |
5163 | 5159 | gen_op_movl_T0_im(val); |
5164 | - gen_check_io(s, ot, 0, pc_start - s->cs_base); | |
5165 | - if (gen_svm_check_io(s, pc_start, | |
5166 | - SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | | |
5167 | - (1 << (4+ot)))) | |
5168 | - break; | |
5169 | - gen_op_in[ot](); | |
5160 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5161 | + SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); | |
5162 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
5163 | + tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2); | |
5170 | 5164 | gen_op_mov_reg_T1(ot, R_EAX); |
5171 | 5165 | break; |
5172 | 5166 | case 0xe6: |
... | ... | @@ -5177,12 +5171,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5177 | 5171 | ot = dflag ? OT_LONG : OT_WORD; |
5178 | 5172 | val = ldub_code(s->pc++); |
5179 | 5173 | gen_op_movl_T0_im(val); |
5180 | - gen_check_io(s, ot, 0, pc_start - s->cs_base); | |
5181 | - if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) | | |
5182 | - (1 << (4+ot)))) | |
5183 | - break; | |
5174 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5175 | + svm_is_rep(prefixes)); | |
5184 | 5176 | gen_op_mov_TN_reg(ot, 1, R_EAX); |
5185 | - gen_op_out[ot](); | |
5177 | + | |
5178 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
5179 | + tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff); | |
5180 | + tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[1]); | |
5181 | + tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3); | |
5186 | 5182 | break; |
5187 | 5183 | case 0xec: |
5188 | 5184 | case 0xed: |
... | ... | @@ -5192,12 +5188,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5192 | 5188 | ot = dflag ? OT_LONG : OT_WORD; |
5193 | 5189 | gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
5194 | 5190 | gen_op_andl_T0_ffff(); |
5195 | - gen_check_io(s, ot, 0, pc_start - s->cs_base); | |
5196 | - if (gen_svm_check_io(s, pc_start, | |
5197 | - SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | | |
5198 | - (1 << (4+ot)))) | |
5199 | - break; | |
5200 | - gen_op_in[ot](); | |
5191 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5192 | + SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); | |
5193 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
5194 | + tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[1], cpu_tmp2); | |
5201 | 5195 | gen_op_mov_reg_T1(ot, R_EAX); |
5202 | 5196 | break; |
5203 | 5197 | case 0xee: |
... | ... | @@ -5208,12 +5202,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5208 | 5202 | ot = dflag ? OT_LONG : OT_WORD; |
5209 | 5203 | gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); |
5210 | 5204 | gen_op_andl_T0_ffff(); |
5211 | - gen_check_io(s, ot, 0, pc_start - s->cs_base); | |
5212 | - if (gen_svm_check_io(s, pc_start, | |
5213 | - svm_is_rep(prefixes) | (1 << (4+ot)))) | |
5214 | - break; | |
5205 | + gen_check_io(s, ot, pc_start - s->cs_base, | |
5206 | + svm_is_rep(prefixes)); | |
5215 | 5207 | gen_op_mov_TN_reg(ot, 1, R_EAX); |
5216 | - gen_op_out[ot](); | |
5208 | + | |
5209 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
5210 | + tcg_gen_andi_i32(cpu_tmp2, cpu_tmp2, 0xffff); | |
5211 | + tcg_gen_trunc_tl_i32(cpu_tmp3, cpu_T[1]); | |
5212 | + tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2, cpu_tmp3); | |
5217 | 5213 | break; |
5218 | 5214 | |
5219 | 5215 | /************************/ |
... | ... | @@ -5246,7 +5242,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5246 | 5242 | if (s->cc_op != CC_OP_DYNAMIC) |
5247 | 5243 | gen_op_set_cc_op(s->cc_op); |
5248 | 5244 | gen_jmp_im(pc_start - s->cs_base); |
5249 | - gen_op_lret_protected(s->dflag, val); | |
5245 | + tcg_gen_helper_0_2(helper_lret_protected, | |
5246 | + tcg_const_i32(s->dflag), | |
5247 | + tcg_const_i32(val)); | |
5250 | 5248 | } else { |
5251 | 5249 | gen_stack_A0(s); |
5252 | 5250 | /* pop offset */ |
... | ... | @@ -5273,20 +5271,22 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5273 | 5271 | break; |
5274 | 5272 | if (!s->pe) { |
5275 | 5273 | /* real mode */ |
5276 | - gen_op_iret_real(s->dflag); | |
5274 | + tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag)); | |
5277 | 5275 | s->cc_op = CC_OP_EFLAGS; |
5278 | 5276 | } else if (s->vm86) { |
5279 | 5277 | if (s->iopl != 3) { |
5280 | 5278 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
5281 | 5279 | } else { |
5282 | - gen_op_iret_real(s->dflag); | |
5280 | + tcg_gen_helper_0_1(helper_iret_real, tcg_const_i32(s->dflag)); | |
5283 | 5281 | s->cc_op = CC_OP_EFLAGS; |
5284 | 5282 | } |
5285 | 5283 | } else { |
5286 | 5284 | if (s->cc_op != CC_OP_DYNAMIC) |
5287 | 5285 | gen_op_set_cc_op(s->cc_op); |
5288 | 5286 | gen_jmp_im(pc_start - s->cs_base); |
5289 | - gen_op_iret_protected(s->dflag, s->pc - s->cs_base); | |
5287 | + tcg_gen_helper_0_2(helper_iret_protected, | |
5288 | + tcg_const_i32(s->dflag), | |
5289 | + tcg_const_i32(s->pc - s->cs_base)); | |
5290 | 5290 | s->cc_op = CC_OP_EFLAGS; |
5291 | 5291 | } |
5292 | 5292 | gen_eob(s); |
... | ... | @@ -5723,10 +5723,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
5723 | 5723 | gen_op_mov_TN_reg(ot, 0, reg); |
5724 | 5724 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
5725 | 5725 | gen_jmp_im(pc_start - s->cs_base); |
5726 | + tcg_gen_trunc_tl_i32(cpu_tmp2, cpu_T[0]); | |
5726 | 5727 | if (ot == OT_WORD) |
5727 | - tcg_gen_helper_0_0(helper_boundw); | |
5728 | + tcg_gen_helper_0_2(helper_boundw, cpu_A0, cpu_tmp2); | |
5728 | 5729 | else |
5729 | - tcg_gen_helper_0_0(helper_boundl); | |
5730 | + tcg_gen_helper_0_2(helper_boundl, cpu_A0, cpu_tmp2); | |
5730 | 5731 | break; |
5731 | 5732 | case 0x1c8 ... 0x1cf: /* bswap reg */ |
5732 | 5733 | reg = (b & 7) | REX_B(s); |
... | ... | @@ -6134,7 +6135,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6134 | 6135 | if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0)) |
6135 | 6136 | break; |
6136 | 6137 | gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
6137 | - gen_op_lmsw_T0(); | |
6138 | + tcg_gen_helper_0_1(helper_lmsw, cpu_T[0]); | |
6138 | 6139 | gen_jmp_im(s->pc - s->cs_base); |
6139 | 6140 | gen_eob(s); |
6140 | 6141 | } |
... | ... | @@ -6223,6 +6224,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6223 | 6224 | } else { |
6224 | 6225 | gen_op_mov_TN_reg(ot, 0, rm); |
6225 | 6226 | } |
6227 | + gen_op_mov_TN_reg(ot, 1, reg); | |
6226 | 6228 | if (s->cc_op != CC_OP_DYNAMIC) |
6227 | 6229 | gen_op_set_cc_op(s->cc_op); |
6228 | 6230 | gen_op_arpl(); |
... | ... | @@ -6299,14 +6301,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6299 | 6301 | if (b & 2) { |
6300 | 6302 | gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg); |
6301 | 6303 | gen_op_mov_TN_reg(ot, 0, rm); |
6302 | - gen_op_movl_crN_T0(reg); | |
6304 | + tcg_gen_helper_0_2(helper_movl_crN_T0, | |
6305 | + tcg_const_i32(reg), cpu_T[0]); | |
6303 | 6306 | gen_jmp_im(s->pc - s->cs_base); |
6304 | 6307 | gen_eob(s); |
6305 | 6308 | } else { |
6306 | 6309 | gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_CR0 + reg); |
6307 | 6310 | #if !defined(CONFIG_USER_ONLY) |
6308 | 6311 | if (reg == 8) |
6309 | - gen_op_movtl_T0_cr8(); | |
6312 | + tcg_gen_helper_1_0(helper_movtl_T0_cr8, cpu_T[0]); | |
6310 | 6313 | else |
6311 | 6314 | #endif |
6312 | 6315 | gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg])); |
... | ... | @@ -6338,7 +6341,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6338 | 6341 | if (b & 2) { |
6339 | 6342 | gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); |
6340 | 6343 | gen_op_mov_TN_reg(ot, 0, rm); |
6341 | - gen_op_movl_drN_T0(reg); | |
6344 | + tcg_gen_helper_0_2(helper_movl_drN_T0, | |
6345 | + tcg_const_i32(reg), cpu_T[0]); | |
6342 | 6346 | gen_jmp_im(s->pc - s->cs_base); |
6343 | 6347 | gen_eob(s); |
6344 | 6348 | } else { |
... | ... | @@ -6353,7 +6357,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6353 | 6357 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
6354 | 6358 | } else { |
6355 | 6359 | gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0); |
6356 | - gen_op_clts(); | |
6360 | + tcg_gen_helper_0_0(helper_clts); | |
6357 | 6361 | /* abort block because static cpu state changed */ |
6358 | 6362 | gen_jmp_im(s->pc - s->cs_base); |
6359 | 6363 | gen_eob(s); |
... | ... | @@ -6485,11 +6489,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
6485 | 6489 | } |
6486 | 6490 | /* lock generation */ |
6487 | 6491 | if (s->prefix & PREFIX_LOCK) |
6488 | - gen_op_unlock(); | |
6492 | + tcg_gen_helper_0_0(helper_unlock); | |
6489 | 6493 | return s->pc; |
6490 | 6494 | illegal_op: |
6491 | 6495 | if (s->prefix & PREFIX_LOCK) |
6492 | - gen_op_unlock(); | |
6496 | + tcg_gen_helper_0_0(helper_unlock); | |
6493 | 6497 | /* XXX: ensure that no lock was generated */ |
6494 | 6498 | gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base); |
6495 | 6499 | return s->pc; |
... | ... | @@ -6861,7 +6865,8 @@ void optimize_flags_init(void) |
6861 | 6865 | cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1"); |
6862 | 6866 | cpu_A0 = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "A0"); |
6863 | 6867 | #endif |
6864 | -#if defined(__i386__) | |
6868 | +#if defined(__i386__) && (TARGET_LONG_BITS <= HOST_LONG_BITS) | |
6869 | + /* XXX: must be suppressed once there are less fixed registers */ | |
6865 | 6870 | cpu_tmp1 = tcg_global_reg2_new_hack(TCG_TYPE_I64, TCG_AREG1, TCG_AREG2, "tmp1"); |
6866 | 6871 | #endif |
6867 | 6872 | } |
... | ... | @@ -6957,10 +6962,11 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
6957 | 6962 | #endif |
6958 | 6963 | |
6959 | 6964 | cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL); |
6960 | -#if !defined(__i386__) | |
6965 | +#if !(defined(__i386__) && (TARGET_LONG_BITS <= HOST_LONG_BITS)) | |
6961 | 6966 | cpu_tmp1 = tcg_temp_new(TCG_TYPE_I64); |
6962 | 6967 | #endif |
6963 | 6968 | cpu_tmp2 = tcg_temp_new(TCG_TYPE_I32); |
6969 | + cpu_tmp3 = tcg_temp_new(TCG_TYPE_I32); | |
6964 | 6970 | cpu_ptr0 = tcg_temp_new(TCG_TYPE_PTR); |
6965 | 6971 | cpu_ptr1 = tcg_temp_new(TCG_TYPE_PTR); |
6966 | 6972 | ... | ... |