Commit 1b9d9ebb8a2efb780365214313625b7d717bca83
1 parent
1130328e
cmpxchg8b fix - added cmpxchg16b
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4522 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
47 additions
and
7 deletions
target-i386/helper.c
... | ... | @@ -1879,8 +1879,8 @@ void helper_cmpxchg8b(target_ulong a0) |
1879 | 1879 | |
1880 | 1880 | eflags = cc_table[CC_OP].compute_all(); |
1881 | 1881 | d = ldq(a0); |
1882 | - if (d == (((uint64_t)EDX << 32) | EAX)) { | |
1883 | - stq(a0, ((uint64_t)ECX << 32) | EBX); | |
1882 | + if (d == (((uint64_t)EDX << 32) | (uint32_t)EAX)) { | |
1883 | + stq(a0, ((uint64_t)ECX << 32) | (uint32_t)EBX); | |
1884 | 1884 | eflags |= CC_Z; |
1885 | 1885 | } else { |
1886 | 1886 | EDX = (uint32_t)(d >> 32); |
... | ... | @@ -1890,6 +1890,28 @@ void helper_cmpxchg8b(target_ulong a0) |
1890 | 1890 | CC_SRC = eflags; |
1891 | 1891 | } |
1892 | 1892 | |
1893 | +#ifdef TARGET_X86_64 | |
1894 | +void helper_cmpxchg16b(target_ulong a0) | |
1895 | +{ | |
1896 | + uint64_t d0, d1; | |
1897 | + int eflags; | |
1898 | + | |
1899 | + eflags = cc_table[CC_OP].compute_all(); | |
1900 | + d0 = ldq(a0); | |
1901 | + d1 = ldq(a0 + 8); | |
1902 | + if (d0 == EAX && d1 == EDX) { | |
1903 | + stq(a0, EBX); | |
1904 | + stq(a0 + 8, ECX); | |
1905 | + eflags |= CC_Z; | |
1906 | + } else { | |
1907 | + EDX = d1; | |
1908 | + EAX = d0; | |
1909 | + eflags &= ~CC_Z; | |
1910 | + } | |
1911 | + CC_SRC = eflags; | |
1912 | +} | |
1913 | +#endif | |
1914 | + | |
1893 | 1915 | void helper_single_step(void) |
1894 | 1916 | { |
1895 | 1917 | env->dr[6] |= 0x4000; | ... | ... |
target-i386/helper.h
... | ... | @@ -75,6 +75,9 @@ void helper_boundl(target_ulong a0, int v); |
75 | 75 | void helper_rsm(void); |
76 | 76 | void helper_into(int next_eip_addend); |
77 | 77 | void helper_cmpxchg8b(target_ulong a0); |
78 | +#ifdef TARGET_X86_64 | |
79 | +void helper_cmpxchg16b(target_ulong a0); | |
80 | +#endif | |
78 | 81 | void helper_single_step(void); |
79 | 82 | void helper_cpuid(void); |
80 | 83 | void helper_rdtsc(void); | ... | ... |
target-i386/translate.c
... | ... | @@ -4333,11 +4333,26 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
4333 | 4333 | mod = (modrm >> 6) & 3; |
4334 | 4334 | if ((mod == 3) || ((modrm & 0x38) != 0x8)) |
4335 | 4335 | goto illegal_op; |
4336 | - gen_jmp_im(pc_start - s->cs_base); | |
4337 | - if (s->cc_op != CC_OP_DYNAMIC) | |
4338 | - gen_op_set_cc_op(s->cc_op); | |
4339 | - gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
4340 | - tcg_gen_helper_0_1(helper_cmpxchg8b, cpu_A0); | |
4336 | +#ifdef TARGET_X86_64 | |
4337 | + if (dflag == 2) { | |
4338 | + if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) | |
4339 | + goto illegal_op; | |
4340 | + gen_jmp_im(pc_start - s->cs_base); | |
4341 | + if (s->cc_op != CC_OP_DYNAMIC) | |
4342 | + gen_op_set_cc_op(s->cc_op); | |
4343 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
4344 | + tcg_gen_helper_0_1(helper_cmpxchg16b, cpu_A0); | |
4345 | + } else | |
4346 | +#endif | |
4347 | + { | |
4348 | + if (!(s->cpuid_features & CPUID_CX8)) | |
4349 | + goto illegal_op; | |
4350 | + gen_jmp_im(pc_start - s->cs_base); | |
4351 | + if (s->cc_op != CC_OP_DYNAMIC) | |
4352 | + gen_op_set_cc_op(s->cc_op); | |
4353 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | |
4354 | + tcg_gen_helper_0_1(helper_cmpxchg8b, cpu_A0); | |
4355 | + } | |
4341 | 4356 | s->cc_op = CC_OP_EFLAGS; |
4342 | 4357 | break; |
4343 | 4358 | ... | ... |