@ -2289,104 +2289,6 @@ static void gen_sty_env_A0(DisasContext *s, int offset, bool align)
tcg_gen_qemu_st_i128 ( t , s - > tmp0 , mem_index , mop ) ;
}
static void gen_cmpxchg8b ( DisasContext * s , X86DecodedInsn * decode )
{
TCGv_i64 cmp , val , old ;
TCGv Z ;
gen_lea_modrm ( s , decode ) ;
cmp = tcg_temp_new_i64 ( ) ;
val = tcg_temp_new_i64 ( ) ;
old = tcg_temp_new_i64 ( ) ;
/* Construct the comparison values from the register pair. */
tcg_gen_concat_tl_i64 ( cmp , cpu_regs [ R_EAX ] , cpu_regs [ R_EDX ] ) ;
tcg_gen_concat_tl_i64 ( val , cpu_regs [ R_EBX ] , cpu_regs [ R_ECX ] ) ;
/* Only require atomic with LOCK; non-parallel handled in generator. */
if ( s - > prefix & PREFIX_LOCK ) {
tcg_gen_atomic_cmpxchg_i64 ( old , s - > A0 , cmp , val , s - > mem_index , MO_TEUQ ) ;
} else {
tcg_gen_nonatomic_cmpxchg_i64 ( old , s - > A0 , cmp , val ,
s - > mem_index , MO_TEUQ ) ;
}
/* Set tmp0 to match the required value of Z. */
tcg_gen_setcond_i64 ( TCG_COND_EQ , cmp , old , cmp ) ;
Z = tcg_temp_new ( ) ;
tcg_gen_trunc_i64_tl ( Z , cmp ) ;
/*
* Extract the result values for the register pair .
* For 32 - bit , we may do this unconditionally , because on success ( Z = 1 ) ,
* the old value matches the previous value in EDX : EAX . For x86_64 ,
* the store must be conditional , because we must leave the source
* registers unchanged on success , and zero - extend the writeback
* on failure ( Z = 0 ) .
*/
if ( TARGET_LONG_BITS = = 32 ) {
tcg_gen_extr_i64_tl ( cpu_regs [ R_EAX ] , cpu_regs [ R_EDX ] , old ) ;
} else {
TCGv zero = tcg_constant_tl ( 0 ) ;
tcg_gen_extr_i64_tl ( s - > T0 , s - > T1 , old ) ;
tcg_gen_movcond_tl ( TCG_COND_EQ , cpu_regs [ R_EAX ] , Z , zero ,
s - > T0 , cpu_regs [ R_EAX ] ) ;
tcg_gen_movcond_tl ( TCG_COND_EQ , cpu_regs [ R_EDX ] , Z , zero ,
s - > T1 , cpu_regs [ R_EDX ] ) ;
}
/* Update Z. */
gen_compute_eflags ( s ) ;
tcg_gen_deposit_tl ( cpu_cc_src , cpu_cc_src , Z , ctz32 ( CC_Z ) , 1 ) ;
}
# ifdef TARGET_X86_64
static void gen_cmpxchg16b ( DisasContext * s , X86DecodedInsn * decode )
{
MemOp mop = MO_TE | MO_128 | MO_ALIGN ;
TCGv_i64 t0 , t1 ;
TCGv_i128 cmp , val ;
gen_lea_modrm ( s , decode ) ;
cmp = tcg_temp_new_i128 ( ) ;
val = tcg_temp_new_i128 ( ) ;
tcg_gen_concat_i64_i128 ( cmp , cpu_regs [ R_EAX ] , cpu_regs [ R_EDX ] ) ;
tcg_gen_concat_i64_i128 ( val , cpu_regs [ R_EBX ] , cpu_regs [ R_ECX ] ) ;
/* Only require atomic with LOCK; non-parallel handled in generator. */
if ( s - > prefix & PREFIX_LOCK ) {
tcg_gen_atomic_cmpxchg_i128 ( val , s - > A0 , cmp , val , s - > mem_index , mop ) ;
} else {
tcg_gen_nonatomic_cmpxchg_i128 ( val , s - > A0 , cmp , val , s - > mem_index , mop ) ;
}
tcg_gen_extr_i128_i64 ( s - > T0 , s - > T1 , val ) ;
/* Determine success after the fact. */
t0 = tcg_temp_new_i64 ( ) ;
t1 = tcg_temp_new_i64 ( ) ;
tcg_gen_xor_i64 ( t0 , s - > T0 , cpu_regs [ R_EAX ] ) ;
tcg_gen_xor_i64 ( t1 , s - > T1 , cpu_regs [ R_EDX ] ) ;
tcg_gen_or_i64 ( t0 , t0 , t1 ) ;
/* Update Z. */
gen_compute_eflags ( s ) ;
tcg_gen_setcondi_i64 ( TCG_COND_EQ , t0 , t0 , 0 ) ;
tcg_gen_deposit_tl ( cpu_cc_src , cpu_cc_src , t0 , ctz32 ( CC_Z ) , 1 ) ;
/*
* Extract the result values for the register pair . We may do this
* unconditionally , because on success ( Z = 1 ) , the old value matches
* the previous value in RDX : RAX .
*/
tcg_gen_mov_i64 ( cpu_regs [ R_EAX ] , s - > T0 ) ;
tcg_gen_mov_i64 ( cpu_regs [ R_EDX ] , s - > T1 ) ;
}
# endif
# include "emit.c.inc"
static void gen_x87 ( DisasContext * s , X86DecodedInsn * decode )
@ -2962,29 +2864,10 @@ static void gen_multi0F(DisasContext *s, X86DecodedInsn *decode)
/* now check op code */
switch ( b ) {
case 0x1c7 : /* cmpxchg8b */
case 0x1c7 : /* RDSEED, RDPID with f3 prefix */
mod = ( modrm > > 6 ) & 3 ;
switch ( ( modrm > > 3 ) & 7 ) {
case 1 : /* CMPXCHG8, CMPXCHG16 */
if ( mod = = 3 ) {
goto illegal_op ;
}
# ifdef TARGET_X86_64
if ( dflag = = MO_64 ) {
if ( ! ( s - > cpuid_ext_features & CPUID_EXT_CX16 ) ) {
goto illegal_op ;
}
gen_cmpxchg16b ( s , decode ) ;
break ;
}
# endif
if ( ! ( s - > cpuid_features & CPUID_CX8 ) ) {
goto illegal_op ;
}
gen_cmpxchg8b ( s , decode ) ;
break ;
case 7 : /* RDSEED, RDPID with f3 prefix */
case 7 :
if ( mod ! = 3 | |
( s - > prefix & ( PREFIX_LOCK | PREFIX_REPNZ ) ) ) {
goto illegal_op ;