1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
runtime: 0.425
instruction: 0.371
syscall: 0.205
x86: BT/BTS/BTR/BTC: ZF flag is unaffected
Hello!
Bug was found in qemu.git.
See target-i386/translate.c:
case 0x1ba: /* bt/bts/btr/btc Gv, im */
ot = dflag + OT_WORD;
modrm = ldub_code(s->pc++);
op = (modrm >> 3) & 7;
mod = (modrm >> 6) & 3;
rm = (modrm & 7) | REX_B(s);
if (mod != 3) {
s->rip_offset = 1;
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
gen_op_ld_T0_A0(ot + s->mem_index);
} else {
gen_op_mov_TN_reg(ot, 0, rm);
}
/* load shift */
val = ldub_code(s->pc++);
gen_op_movl_T1_im(val);
if (op < 4)
goto illegal_op;
op -= 4;
goto bt_op;
case 0x1a3: /* bt Gv, Ev */
op = 0;
goto do_btx;
case 0x1ab: /* bts */
op = 1;
goto do_btx;
case 0x1b3: /* btr */
op = 2;
goto do_btx;
case 0x1bb: /* btc */
op = 3;
do_btx:
ot = dflag + OT_WORD;
modrm = ldub_code(s->pc++);
reg = ((modrm >> 3) & 7) | rex_r;
mod = (modrm >> 6) & 3;
rm = (modrm & 7) | REX_B(s);
gen_op_mov_TN_reg(OT_LONG, 1, reg);
if (mod != 3) {
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
/* specific case: we need to add a displacement */
gen_exts(ot, cpu_T[1]);
tcg_gen_sari_tl(cpu_tmp0, cpu_T[1], 3 + ot);
tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, ot);
tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
gen_op_ld_T0_A0(ot + s->mem_index);
} else {
gen_op_mov_TN_reg(ot, 0, rm);
}
bt_op:
tcg_gen_andi_tl(cpu_T[1], cpu_T[1], (1 << (3 + ot)) - 1);
switch(op) {
case 0:
tcg_gen_shr_tl(cpu_cc_src, cpu_T[0], cpu_T[1]);
tcg_gen_movi_tl(cpu_cc_dst, 0); <<<<<<<<<<<<<<<<<<<<<< always set zf
break;
case 1:
tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
tcg_gen_movi_tl(cpu_tmp0, 1);
tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
break;
case 2:
tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
tcg_gen_movi_tl(cpu_tmp0, 1);
tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
tcg_gen_not_tl(cpu_tmp0, cpu_tmp0);
tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
break;
default:
case 3:
tcg_gen_shr_tl(cpu_tmp4, cpu_T[0], cpu_T[1]);
tcg_gen_movi_tl(cpu_tmp0, 1);
tcg_gen_shl_tl(cpu_tmp0, cpu_tmp0, cpu_T[1]);
tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_tmp0);
break;
}
s->cc_op = CC_OP_SARB + ot;
if (op != 0) {
if (mod != 3)
gen_op_st_T0_A0(ot + s->mem_index);
else
gen_op_mov_reg_T0(ot, rm);
tcg_gen_mov_tl(cpu_cc_src, cpu_tmp4);
tcg_gen_movi_tl(cpu_cc_dst, 0); <<<<<<<<<<<<<<<<<<<<<< always set zf
}
break;
always set zf...
There is fixed patch.
|