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 | ... | ... |