xref: /openbmc/qemu/target/i386/emulate/x86_emu.c (revision 27458df871097d7fc14b19d9e01c35d29737b9b3)
1*27458df8SWei Liu /*
2*27458df8SWei Liu  * Copyright (C) 2016 Veertu Inc,
3*27458df8SWei Liu  * Copyright (C) 2017 Google Inc,
4*27458df8SWei Liu  *
5*27458df8SWei Liu  * This program is free software; you can redistribute it and/or
6*27458df8SWei Liu  * modify it under the terms of the GNU Lesser General Public
7*27458df8SWei Liu  * License as published by the Free Software Foundation; either
8*27458df8SWei Liu  * version 2.1 of the License, or (at your option) any later version.
9*27458df8SWei Liu  *
10*27458df8SWei Liu  * This program is distributed in the hope that it will be useful,
11*27458df8SWei Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*27458df8SWei Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*27458df8SWei Liu  * Lesser General Public License for more details.
14*27458df8SWei Liu  *
15*27458df8SWei Liu  * You should have received a copy of the GNU Lesser General Public
16*27458df8SWei Liu  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
17*27458df8SWei Liu  */
18*27458df8SWei Liu 
19*27458df8SWei Liu /////////////////////////////////////////////////////////////////////////
20*27458df8SWei Liu //
21*27458df8SWei Liu //  Copyright (C) 2001-2012  The Bochs Project
22*27458df8SWei Liu //
23*27458df8SWei Liu //  This library is free software; you can redistribute it and/or
24*27458df8SWei Liu //  modify it under the terms of the GNU Lesser General Public
25*27458df8SWei Liu //  License as published by the Free Software Foundation; either
26*27458df8SWei Liu //  version 2.1 of the License, or (at your option) any later version.
27*27458df8SWei Liu //
28*27458df8SWei Liu //  This library is distributed in the hope that it will be useful,
29*27458df8SWei Liu //  but WITHOUT ANY WARRANTY; without even the implied warranty of
30*27458df8SWei Liu //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31*27458df8SWei Liu //  Lesser General Public License for more details.
32*27458df8SWei Liu //
33*27458df8SWei Liu //  You should have received a copy of the GNU Lesser General Public
34*27458df8SWei Liu //  License along with this library; if not, write to the Free Software
35*27458df8SWei Liu //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
36*27458df8SWei Liu /////////////////////////////////////////////////////////////////////////
37*27458df8SWei Liu 
38*27458df8SWei Liu #include "qemu/osdep.h"
39*27458df8SWei Liu #include "panic.h"
40*27458df8SWei Liu #include "x86_decode.h"
41*27458df8SWei Liu #include "x86.h"
42*27458df8SWei Liu #include "x86_emu.h"
43*27458df8SWei Liu #include "x86_flags.h"
44*27458df8SWei Liu 
45*27458df8SWei Liu #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
46*27458df8SWei Liu {                                                       \
47*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);  \
48*27458df8SWei Liu     switch (decode->operand_size) {                     \
49*27458df8SWei Liu     case 1:                                         \
50*27458df8SWei Liu     {                                               \
51*27458df8SWei Liu         uint8_t v1 = (uint8_t)decode->op[0].val;    \
52*27458df8SWei Liu         uint8_t v2 = (uint8_t)decode->op[1].val;    \
53*27458df8SWei Liu         uint8_t diff = v1 cmd v2;                   \
54*27458df8SWei Liu         if (save_res) {                              \
55*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 1);  \
56*27458df8SWei Liu         } \
57*27458df8SWei Liu         FLAGS_FUNC##8(env, v1, v2, diff);           \
58*27458df8SWei Liu         break;                                      \
59*27458df8SWei Liu     }                                               \
60*27458df8SWei Liu     case 2:                                        \
61*27458df8SWei Liu     {                                               \
62*27458df8SWei Liu         uint16_t v1 = (uint16_t)decode->op[0].val;  \
63*27458df8SWei Liu         uint16_t v2 = (uint16_t)decode->op[1].val;  \
64*27458df8SWei Liu         uint16_t diff = v1 cmd v2;                  \
65*27458df8SWei Liu         if (save_res) {                              \
66*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 2); \
67*27458df8SWei Liu         } \
68*27458df8SWei Liu         FLAGS_FUNC##16(env, v1, v2, diff);          \
69*27458df8SWei Liu         break;                                      \
70*27458df8SWei Liu     }                                               \
71*27458df8SWei Liu     case 4:                                        \
72*27458df8SWei Liu     {                                               \
73*27458df8SWei Liu         uint32_t v1 = (uint32_t)decode->op[0].val;  \
74*27458df8SWei Liu         uint32_t v2 = (uint32_t)decode->op[1].val;  \
75*27458df8SWei Liu         uint32_t diff = v1 cmd v2;                  \
76*27458df8SWei Liu         if (save_res) {                              \
77*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 4); \
78*27458df8SWei Liu         } \
79*27458df8SWei Liu         FLAGS_FUNC##32(env, v1, v2, diff);          \
80*27458df8SWei Liu         break;                                      \
81*27458df8SWei Liu     }                                               \
82*27458df8SWei Liu     default:                                        \
83*27458df8SWei Liu         VM_PANIC("bad size\n");                    \
84*27458df8SWei Liu     }                                                   \
85*27458df8SWei Liu }                                                       \
86*27458df8SWei Liu 
87*27458df8SWei Liu target_ulong read_reg(CPUX86State *env, int reg, int size)
88*27458df8SWei Liu {
89*27458df8SWei Liu     switch (size) {
90*27458df8SWei Liu     case 1:
91*27458df8SWei Liu         return x86_reg(env, reg)->lx;
92*27458df8SWei Liu     case 2:
93*27458df8SWei Liu         return x86_reg(env, reg)->rx;
94*27458df8SWei Liu     case 4:
95*27458df8SWei Liu         return x86_reg(env, reg)->erx;
96*27458df8SWei Liu     case 8:
97*27458df8SWei Liu         return x86_reg(env, reg)->rrx;
98*27458df8SWei Liu     default:
99*27458df8SWei Liu         abort();
100*27458df8SWei Liu     }
101*27458df8SWei Liu     return 0;
102*27458df8SWei Liu }
103*27458df8SWei Liu 
104*27458df8SWei Liu void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
105*27458df8SWei Liu {
106*27458df8SWei Liu     switch (size) {
107*27458df8SWei Liu     case 1:
108*27458df8SWei Liu         x86_reg(env, reg)->lx = val;
109*27458df8SWei Liu         break;
110*27458df8SWei Liu     case 2:
111*27458df8SWei Liu         x86_reg(env, reg)->rx = val;
112*27458df8SWei Liu         break;
113*27458df8SWei Liu     case 4:
114*27458df8SWei Liu         x86_reg(env, reg)->rrx = (uint32_t)val;
115*27458df8SWei Liu         break;
116*27458df8SWei Liu     case 8:
117*27458df8SWei Liu         x86_reg(env, reg)->rrx = val;
118*27458df8SWei Liu         break;
119*27458df8SWei Liu     default:
120*27458df8SWei Liu         abort();
121*27458df8SWei Liu     }
122*27458df8SWei Liu }
123*27458df8SWei Liu 
124*27458df8SWei Liu target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
125*27458df8SWei Liu {
126*27458df8SWei Liu     target_ulong val;
127*27458df8SWei Liu 
128*27458df8SWei Liu     switch (size) {
129*27458df8SWei Liu     case 1:
130*27458df8SWei Liu         val = *(uint8_t *)reg_ptr;
131*27458df8SWei Liu         break;
132*27458df8SWei Liu     case 2:
133*27458df8SWei Liu         val = *(uint16_t *)reg_ptr;
134*27458df8SWei Liu         break;
135*27458df8SWei Liu     case 4:
136*27458df8SWei Liu         val = *(uint32_t *)reg_ptr;
137*27458df8SWei Liu         break;
138*27458df8SWei Liu     case 8:
139*27458df8SWei Liu         val = *(uint64_t *)reg_ptr;
140*27458df8SWei Liu         break;
141*27458df8SWei Liu     default:
142*27458df8SWei Liu         abort();
143*27458df8SWei Liu     }
144*27458df8SWei Liu     return val;
145*27458df8SWei Liu }
146*27458df8SWei Liu 
147*27458df8SWei Liu void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
148*27458df8SWei Liu {
149*27458df8SWei Liu     switch (size) {
150*27458df8SWei Liu     case 1:
151*27458df8SWei Liu         *(uint8_t *)reg_ptr = val;
152*27458df8SWei Liu         break;
153*27458df8SWei Liu     case 2:
154*27458df8SWei Liu         *(uint16_t *)reg_ptr = val;
155*27458df8SWei Liu         break;
156*27458df8SWei Liu     case 4:
157*27458df8SWei Liu         *(uint64_t *)reg_ptr = (uint32_t)val;
158*27458df8SWei Liu         break;
159*27458df8SWei Liu     case 8:
160*27458df8SWei Liu         *(uint64_t *)reg_ptr = val;
161*27458df8SWei Liu         break;
162*27458df8SWei Liu     default:
163*27458df8SWei Liu         abort();
164*27458df8SWei Liu     }
165*27458df8SWei Liu }
166*27458df8SWei Liu 
167*27458df8SWei Liu static bool is_host_reg(CPUX86State *env, target_ulong ptr)
168*27458df8SWei Liu {
169*27458df8SWei Liu     return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
170*27458df8SWei Liu }
171*27458df8SWei Liu 
172*27458df8SWei Liu void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
173*27458df8SWei Liu {
174*27458df8SWei Liu     if (is_host_reg(env, ptr)) {
175*27458df8SWei Liu         write_val_to_reg(ptr, val, size);
176*27458df8SWei Liu         return;
177*27458df8SWei Liu     }
178*27458df8SWei Liu     emul_ops->write_mem(env_cpu(env), &val, ptr, size);
179*27458df8SWei Liu }
180*27458df8SWei Liu 
181*27458df8SWei Liu uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
182*27458df8SWei Liu {
183*27458df8SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
184*27458df8SWei Liu     return env->emu_mmio_buf;
185*27458df8SWei Liu }
186*27458df8SWei Liu 
187*27458df8SWei Liu 
188*27458df8SWei Liu target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
189*27458df8SWei Liu {
190*27458df8SWei Liu     target_ulong val;
191*27458df8SWei Liu     uint8_t *mmio_ptr;
192*27458df8SWei Liu 
193*27458df8SWei Liu     if (is_host_reg(env, ptr)) {
194*27458df8SWei Liu         return read_val_from_reg(ptr, size);
195*27458df8SWei Liu     }
196*27458df8SWei Liu 
197*27458df8SWei Liu     mmio_ptr = read_mmio(env, ptr, size);
198*27458df8SWei Liu     switch (size) {
199*27458df8SWei Liu     case 1:
200*27458df8SWei Liu         val = *(uint8_t *)mmio_ptr;
201*27458df8SWei Liu         break;
202*27458df8SWei Liu     case 2:
203*27458df8SWei Liu         val = *(uint16_t *)mmio_ptr;
204*27458df8SWei Liu         break;
205*27458df8SWei Liu     case 4:
206*27458df8SWei Liu         val = *(uint32_t *)mmio_ptr;
207*27458df8SWei Liu         break;
208*27458df8SWei Liu     case 8:
209*27458df8SWei Liu         val = *(uint64_t *)mmio_ptr;
210*27458df8SWei Liu         break;
211*27458df8SWei Liu     default:
212*27458df8SWei Liu         VM_PANIC("bad size\n");
213*27458df8SWei Liu         break;
214*27458df8SWei Liu     }
215*27458df8SWei Liu     return val;
216*27458df8SWei Liu }
217*27458df8SWei Liu 
218*27458df8SWei Liu static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
219*27458df8SWei Liu                            int n, bool val_op0, bool val_op1, bool val_op2)
220*27458df8SWei Liu {
221*27458df8SWei Liu     int i;
222*27458df8SWei Liu     bool calc_val[3] = {val_op0, val_op1, val_op2};
223*27458df8SWei Liu 
224*27458df8SWei Liu     for (i = 0; i < n; i++) {
225*27458df8SWei Liu         switch (decode->op[i].type) {
226*27458df8SWei Liu         case X86_VAR_IMMEDIATE:
227*27458df8SWei Liu             break;
228*27458df8SWei Liu         case X86_VAR_REG:
229*27458df8SWei Liu             VM_PANIC_ON(!decode->op[i].ptr);
230*27458df8SWei Liu             if (calc_val[i]) {
231*27458df8SWei Liu                 decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
232*27458df8SWei Liu                                                       decode->operand_size);
233*27458df8SWei Liu             }
234*27458df8SWei Liu             break;
235*27458df8SWei Liu         case X86_VAR_RM:
236*27458df8SWei Liu             calc_modrm_operand(env, decode, &decode->op[i]);
237*27458df8SWei Liu             if (calc_val[i]) {
238*27458df8SWei Liu                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
239*27458df8SWei Liu                                                  decode->operand_size);
240*27458df8SWei Liu             }
241*27458df8SWei Liu             break;
242*27458df8SWei Liu         case X86_VAR_OFFSET:
243*27458df8SWei Liu             decode->op[i].ptr = decode_linear_addr(env, decode,
244*27458df8SWei Liu                                                    decode->op[i].ptr,
245*27458df8SWei Liu                                                    R_DS);
246*27458df8SWei Liu             if (calc_val[i]) {
247*27458df8SWei Liu                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
248*27458df8SWei Liu                                                  decode->operand_size);
249*27458df8SWei Liu             }
250*27458df8SWei Liu             break;
251*27458df8SWei Liu         default:
252*27458df8SWei Liu             break;
253*27458df8SWei Liu         }
254*27458df8SWei Liu     }
255*27458df8SWei Liu }
256*27458df8SWei Liu 
257*27458df8SWei Liu static void exec_mov(CPUX86State *env, struct x86_decode *decode)
258*27458df8SWei Liu {
259*27458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
260*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
261*27458df8SWei Liu                   decode->operand_size);
262*27458df8SWei Liu 
263*27458df8SWei Liu     env->eip += decode->len;
264*27458df8SWei Liu }
265*27458df8SWei Liu 
266*27458df8SWei Liu static void exec_add(CPUX86State *env, struct x86_decode *decode)
267*27458df8SWei Liu {
268*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
269*27458df8SWei Liu     env->eip += decode->len;
270*27458df8SWei Liu }
271*27458df8SWei Liu 
272*27458df8SWei Liu static void exec_or(CPUX86State *env, struct x86_decode *decode)
273*27458df8SWei Liu {
274*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
275*27458df8SWei Liu     env->eip += decode->len;
276*27458df8SWei Liu }
277*27458df8SWei Liu 
278*27458df8SWei Liu static void exec_adc(CPUX86State *env, struct x86_decode *decode)
279*27458df8SWei Liu {
280*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
281*27458df8SWei Liu     env->eip += decode->len;
282*27458df8SWei Liu }
283*27458df8SWei Liu 
284*27458df8SWei Liu static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
285*27458df8SWei Liu {
286*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
287*27458df8SWei Liu     env->eip += decode->len;
288*27458df8SWei Liu }
289*27458df8SWei Liu 
290*27458df8SWei Liu static void exec_and(CPUX86State *env, struct x86_decode *decode)
291*27458df8SWei Liu {
292*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
293*27458df8SWei Liu     env->eip += decode->len;
294*27458df8SWei Liu }
295*27458df8SWei Liu 
296*27458df8SWei Liu static void exec_sub(CPUX86State *env, struct x86_decode *decode)
297*27458df8SWei Liu {
298*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
299*27458df8SWei Liu     env->eip += decode->len;
300*27458df8SWei Liu }
301*27458df8SWei Liu 
302*27458df8SWei Liu static void exec_xor(CPUX86State *env, struct x86_decode *decode)
303*27458df8SWei Liu {
304*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
305*27458df8SWei Liu     env->eip += decode->len;
306*27458df8SWei Liu }
307*27458df8SWei Liu 
308*27458df8SWei Liu static void exec_neg(CPUX86State *env, struct x86_decode *decode)
309*27458df8SWei Liu {
310*27458df8SWei Liu     /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
311*27458df8SWei Liu     int32_t val;
312*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
313*27458df8SWei Liu 
314*27458df8SWei Liu     val = 0 - sign(decode->op[1].val, decode->operand_size);
315*27458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
316*27458df8SWei Liu 
317*27458df8SWei Liu     if (4 == decode->operand_size) {
318*27458df8SWei Liu         SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
319*27458df8SWei Liu     } else if (2 == decode->operand_size) {
320*27458df8SWei Liu         SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
321*27458df8SWei Liu     } else if (1 == decode->operand_size) {
322*27458df8SWei Liu         SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
323*27458df8SWei Liu     } else {
324*27458df8SWei Liu         VM_PANIC("bad op size\n");
325*27458df8SWei Liu     }
326*27458df8SWei Liu 
327*27458df8SWei Liu     /*lflags_to_rflags(env);*/
328*27458df8SWei Liu     env->eip += decode->len;
329*27458df8SWei Liu }
330*27458df8SWei Liu 
331*27458df8SWei Liu static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
332*27458df8SWei Liu {
333*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
334*27458df8SWei Liu     env->eip += decode->len;
335*27458df8SWei Liu }
336*27458df8SWei Liu 
337*27458df8SWei Liu static void exec_inc(CPUX86State *env, struct x86_decode *decode)
338*27458df8SWei Liu {
339*27458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
340*27458df8SWei Liu     decode->op[1].val = 0;
341*27458df8SWei Liu 
342*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
343*27458df8SWei Liu 
344*27458df8SWei Liu     env->eip += decode->len;
345*27458df8SWei Liu }
346*27458df8SWei Liu 
347*27458df8SWei Liu static void exec_dec(CPUX86State *env, struct x86_decode *decode)
348*27458df8SWei Liu {
349*27458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
350*27458df8SWei Liu     decode->op[1].val = 0;
351*27458df8SWei Liu 
352*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
353*27458df8SWei Liu     env->eip += decode->len;
354*27458df8SWei Liu }
355*27458df8SWei Liu 
356*27458df8SWei Liu static void exec_tst(CPUX86State *env, struct x86_decode *decode)
357*27458df8SWei Liu {
358*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
359*27458df8SWei Liu     env->eip += decode->len;
360*27458df8SWei Liu }
361*27458df8SWei Liu 
362*27458df8SWei Liu static void exec_not(CPUX86State *env, struct x86_decode *decode)
363*27458df8SWei Liu {
364*27458df8SWei Liu     fetch_operands(env, decode, 1, true, false, false);
365*27458df8SWei Liu 
366*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
367*27458df8SWei Liu                   decode->operand_size);
368*27458df8SWei Liu     env->eip += decode->len;
369*27458df8SWei Liu }
370*27458df8SWei Liu 
371*27458df8SWei Liu void exec_movzx(CPUX86State *env, struct x86_decode *decode)
372*27458df8SWei Liu {
373*27458df8SWei Liu     int src_op_size;
374*27458df8SWei Liu     int op_size = decode->operand_size;
375*27458df8SWei Liu 
376*27458df8SWei Liu     fetch_operands(env, decode, 1, false, false, false);
377*27458df8SWei Liu 
378*27458df8SWei Liu     if (0xb6 == decode->opcode[1]) {
379*27458df8SWei Liu         src_op_size = 1;
380*27458df8SWei Liu     } else {
381*27458df8SWei Liu         src_op_size = 2;
382*27458df8SWei Liu     }
383*27458df8SWei Liu     decode->operand_size = src_op_size;
384*27458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
385*27458df8SWei Liu     decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
386*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
387*27458df8SWei Liu 
388*27458df8SWei Liu     env->eip += decode->len;
389*27458df8SWei Liu }
390*27458df8SWei Liu 
391*27458df8SWei Liu static void exec_out(CPUX86State *env, struct x86_decode *decode)
392*27458df8SWei Liu {
393*27458df8SWei Liu     switch (decode->opcode[0]) {
394*27458df8SWei Liu     case 0xe6:
395*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
396*27458df8SWei Liu         break;
397*27458df8SWei Liu     case 0xe7:
398*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
399*27458df8SWei Liu                             decode->operand_size, 1);
400*27458df8SWei Liu         break;
401*27458df8SWei Liu     case 0xee:
402*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
403*27458df8SWei Liu         break;
404*27458df8SWei Liu     case 0xef:
405*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
406*27458df8SWei Liu                             decode->operand_size, 1);
407*27458df8SWei Liu         break;
408*27458df8SWei Liu     default:
409*27458df8SWei Liu         VM_PANIC("Bad out opcode\n");
410*27458df8SWei Liu         break;
411*27458df8SWei Liu     }
412*27458df8SWei Liu     env->eip += decode->len;
413*27458df8SWei Liu }
414*27458df8SWei Liu 
415*27458df8SWei Liu static void exec_in(CPUX86State *env, struct x86_decode *decode)
416*27458df8SWei Liu {
417*27458df8SWei Liu     target_ulong val = 0;
418*27458df8SWei Liu     switch (decode->opcode[0]) {
419*27458df8SWei Liu     case 0xe4:
420*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
421*27458df8SWei Liu         break;
422*27458df8SWei Liu     case 0xe5:
423*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
424*27458df8SWei Liu                       decode->operand_size, 1);
425*27458df8SWei Liu         if (decode->operand_size == 2) {
426*27458df8SWei Liu             AX(env) = val;
427*27458df8SWei Liu         } else {
428*27458df8SWei Liu             RAX(env) = (uint32_t)val;
429*27458df8SWei Liu         }
430*27458df8SWei Liu         break;
431*27458df8SWei Liu     case 0xec:
432*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
433*27458df8SWei Liu         break;
434*27458df8SWei Liu     case 0xed:
435*27458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
436*27458df8SWei Liu                             decode->operand_size, 1);
437*27458df8SWei Liu         if (decode->operand_size == 2) {
438*27458df8SWei Liu             AX(env) = val;
439*27458df8SWei Liu         } else {
440*27458df8SWei Liu             RAX(env) = (uint32_t)val;
441*27458df8SWei Liu         }
442*27458df8SWei Liu 
443*27458df8SWei Liu         break;
444*27458df8SWei Liu     default:
445*27458df8SWei Liu         VM_PANIC("Bad in opcode\n");
446*27458df8SWei Liu         break;
447*27458df8SWei Liu     }
448*27458df8SWei Liu 
449*27458df8SWei Liu     env->eip += decode->len;
450*27458df8SWei Liu }
451*27458df8SWei Liu 
452*27458df8SWei Liu static inline void string_increment_reg(CPUX86State *env, int reg,
453*27458df8SWei Liu                                         struct x86_decode *decode)
454*27458df8SWei Liu {
455*27458df8SWei Liu     target_ulong val = read_reg(env, reg, decode->addressing_size);
456*27458df8SWei Liu     if (env->eflags & DF_MASK) {
457*27458df8SWei Liu         val -= decode->operand_size;
458*27458df8SWei Liu     } else {
459*27458df8SWei Liu         val += decode->operand_size;
460*27458df8SWei Liu     }
461*27458df8SWei Liu     write_reg(env, reg, val, decode->addressing_size);
462*27458df8SWei Liu }
463*27458df8SWei Liu 
464*27458df8SWei Liu static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
465*27458df8SWei Liu                               void (*func)(CPUX86State *env,
466*27458df8SWei Liu                                            struct x86_decode *ins), int rep)
467*27458df8SWei Liu {
468*27458df8SWei Liu     target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
469*27458df8SWei Liu     while (rcx--) {
470*27458df8SWei Liu         func(env, decode);
471*27458df8SWei Liu         write_reg(env, R_ECX, rcx, decode->addressing_size);
472*27458df8SWei Liu         if ((PREFIX_REP == rep) && !get_ZF(env)) {
473*27458df8SWei Liu             break;
474*27458df8SWei Liu         }
475*27458df8SWei Liu         if ((PREFIX_REPN == rep) && get_ZF(env)) {
476*27458df8SWei Liu             break;
477*27458df8SWei Liu         }
478*27458df8SWei Liu     }
479*27458df8SWei Liu }
480*27458df8SWei Liu 
481*27458df8SWei Liu static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
482*27458df8SWei Liu {
483*27458df8SWei Liu     target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
484*27458df8SWei Liu                                          decode->addressing_size, R_ES);
485*27458df8SWei Liu 
486*27458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
487*27458df8SWei Liu                         decode->operand_size, 1);
488*27458df8SWei Liu     emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
489*27458df8SWei Liu                         decode->operand_size);
490*27458df8SWei Liu 
491*27458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
492*27458df8SWei Liu }
493*27458df8SWei Liu 
494*27458df8SWei Liu static void exec_ins(CPUX86State *env, struct x86_decode *decode)
495*27458df8SWei Liu {
496*27458df8SWei Liu     if (decode->rep) {
497*27458df8SWei Liu         string_rep(env, decode, exec_ins_single, 0);
498*27458df8SWei Liu     } else {
499*27458df8SWei Liu         exec_ins_single(env, decode);
500*27458df8SWei Liu     }
501*27458df8SWei Liu 
502*27458df8SWei Liu     env->eip += decode->len;
503*27458df8SWei Liu }
504*27458df8SWei Liu 
505*27458df8SWei Liu static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
506*27458df8SWei Liu {
507*27458df8SWei Liu     target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
508*27458df8SWei Liu 
509*27458df8SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
510*27458df8SWei Liu                        decode->operand_size);
511*27458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
512*27458df8SWei Liu                         decode->operand_size, 1);
513*27458df8SWei Liu 
514*27458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
515*27458df8SWei Liu }
516*27458df8SWei Liu 
517*27458df8SWei Liu static void exec_outs(CPUX86State *env, struct x86_decode *decode)
518*27458df8SWei Liu {
519*27458df8SWei Liu     if (decode->rep) {
520*27458df8SWei Liu         string_rep(env, decode, exec_outs_single, 0);
521*27458df8SWei Liu     } else {
522*27458df8SWei Liu         exec_outs_single(env, decode);
523*27458df8SWei Liu     }
524*27458df8SWei Liu 
525*27458df8SWei Liu     env->eip += decode->len;
526*27458df8SWei Liu }
527*27458df8SWei Liu 
528*27458df8SWei Liu static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
529*27458df8SWei Liu {
530*27458df8SWei Liu     target_ulong src_addr;
531*27458df8SWei Liu     target_ulong dst_addr;
532*27458df8SWei Liu     target_ulong val;
533*27458df8SWei Liu 
534*27458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
535*27458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
536*27458df8SWei Liu                                 decode->addressing_size, R_ES);
537*27458df8SWei Liu 
538*27458df8SWei Liu     val = read_val_ext(env, src_addr, decode->operand_size);
539*27458df8SWei Liu     write_val_ext(env, dst_addr, val, decode->operand_size);
540*27458df8SWei Liu 
541*27458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
542*27458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
543*27458df8SWei Liu }
544*27458df8SWei Liu 
545*27458df8SWei Liu static void exec_movs(CPUX86State *env, struct x86_decode *decode)
546*27458df8SWei Liu {
547*27458df8SWei Liu     if (decode->rep) {
548*27458df8SWei Liu         string_rep(env, decode, exec_movs_single, 0);
549*27458df8SWei Liu     } else {
550*27458df8SWei Liu         exec_movs_single(env, decode);
551*27458df8SWei Liu     }
552*27458df8SWei Liu 
553*27458df8SWei Liu     env->eip += decode->len;
554*27458df8SWei Liu }
555*27458df8SWei Liu 
556*27458df8SWei Liu static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
557*27458df8SWei Liu {
558*27458df8SWei Liu     target_ulong src_addr;
559*27458df8SWei Liu     target_ulong dst_addr;
560*27458df8SWei Liu 
561*27458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
562*27458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
563*27458df8SWei Liu                                 decode->addressing_size, R_ES);
564*27458df8SWei Liu 
565*27458df8SWei Liu     decode->op[0].type = X86_VAR_IMMEDIATE;
566*27458df8SWei Liu     decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
567*27458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
568*27458df8SWei Liu     decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
569*27458df8SWei Liu 
570*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
571*27458df8SWei Liu 
572*27458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
573*27458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
574*27458df8SWei Liu }
575*27458df8SWei Liu 
576*27458df8SWei Liu static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
577*27458df8SWei Liu {
578*27458df8SWei Liu     if (decode->rep) {
579*27458df8SWei Liu         string_rep(env, decode, exec_cmps_single, decode->rep);
580*27458df8SWei Liu     } else {
581*27458df8SWei Liu         exec_cmps_single(env, decode);
582*27458df8SWei Liu     }
583*27458df8SWei Liu     env->eip += decode->len;
584*27458df8SWei Liu }
585*27458df8SWei Liu 
586*27458df8SWei Liu 
587*27458df8SWei Liu static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
588*27458df8SWei Liu {
589*27458df8SWei Liu     target_ulong addr;
590*27458df8SWei Liu     target_ulong val;
591*27458df8SWei Liu 
592*27458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
593*27458df8SWei Liu                             decode->addressing_size, R_ES);
594*27458df8SWei Liu     val = read_reg(env, R_EAX, decode->operand_size);
595*27458df8SWei Liu     emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
596*27458df8SWei Liu 
597*27458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
598*27458df8SWei Liu }
599*27458df8SWei Liu 
600*27458df8SWei Liu 
601*27458df8SWei Liu static void exec_stos(CPUX86State *env, struct x86_decode *decode)
602*27458df8SWei Liu {
603*27458df8SWei Liu     if (decode->rep) {
604*27458df8SWei Liu         string_rep(env, decode, exec_stos_single, 0);
605*27458df8SWei Liu     } else {
606*27458df8SWei Liu         exec_stos_single(env, decode);
607*27458df8SWei Liu     }
608*27458df8SWei Liu 
609*27458df8SWei Liu     env->eip += decode->len;
610*27458df8SWei Liu }
611*27458df8SWei Liu 
612*27458df8SWei Liu static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
613*27458df8SWei Liu {
614*27458df8SWei Liu     target_ulong addr;
615*27458df8SWei Liu 
616*27458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
617*27458df8SWei Liu                             decode->addressing_size, R_ES);
618*27458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
619*27458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
620*27458df8SWei Liu 
621*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
622*27458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
623*27458df8SWei Liu }
624*27458df8SWei Liu 
625*27458df8SWei Liu static void exec_scas(CPUX86State *env, struct x86_decode *decode)
626*27458df8SWei Liu {
627*27458df8SWei Liu     decode->op[0].type = X86_VAR_REG;
628*27458df8SWei Liu     decode->op[0].reg = R_EAX;
629*27458df8SWei Liu     if (decode->rep) {
630*27458df8SWei Liu         string_rep(env, decode, exec_scas_single, decode->rep);
631*27458df8SWei Liu     } else {
632*27458df8SWei Liu         exec_scas_single(env, decode);
633*27458df8SWei Liu     }
634*27458df8SWei Liu 
635*27458df8SWei Liu     env->eip += decode->len;
636*27458df8SWei Liu }
637*27458df8SWei Liu 
638*27458df8SWei Liu static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
639*27458df8SWei Liu {
640*27458df8SWei Liu     target_ulong addr;
641*27458df8SWei Liu     target_ulong val = 0;
642*27458df8SWei Liu 
643*27458df8SWei Liu     addr = decode_linear_addr(env, decode, RSI(env), R_DS);
644*27458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
645*27458df8SWei Liu     write_reg(env, R_EAX, val, decode->operand_size);
646*27458df8SWei Liu 
647*27458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
648*27458df8SWei Liu }
649*27458df8SWei Liu 
650*27458df8SWei Liu static void exec_lods(CPUX86State *env, struct x86_decode *decode)
651*27458df8SWei Liu {
652*27458df8SWei Liu     if (decode->rep) {
653*27458df8SWei Liu         string_rep(env, decode, exec_lods_single, 0);
654*27458df8SWei Liu     } else {
655*27458df8SWei Liu         exec_lods_single(env, decode);
656*27458df8SWei Liu     }
657*27458df8SWei Liu 
658*27458df8SWei Liu     env->eip += decode->len;
659*27458df8SWei Liu }
660*27458df8SWei Liu 
661*27458df8SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
662*27458df8SWei Liu {
663*27458df8SWei Liu     env->exception_nr = exception_index;
664*27458df8SWei Liu     env->error_code = error_code;
665*27458df8SWei Liu     env->has_error_code = true;
666*27458df8SWei Liu     env->exception_injected = 1;
667*27458df8SWei Liu }
668*27458df8SWei Liu 
669*27458df8SWei Liu static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
670*27458df8SWei Liu {
671*27458df8SWei Liu     emul_ops->simulate_rdmsr(env_cpu(env));
672*27458df8SWei Liu     env->eip += decode->len;
673*27458df8SWei Liu }
674*27458df8SWei Liu 
675*27458df8SWei Liu static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
676*27458df8SWei Liu {
677*27458df8SWei Liu     emul_ops->simulate_wrmsr(env_cpu(env));
678*27458df8SWei Liu     env->eip += decode->len;
679*27458df8SWei Liu }
680*27458df8SWei Liu 
681*27458df8SWei Liu /*
682*27458df8SWei Liu  * flag:
683*27458df8SWei Liu  * 0 - bt, 1 - btc, 2 - bts, 3 - btr
684*27458df8SWei Liu  */
685*27458df8SWei Liu static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
686*27458df8SWei Liu {
687*27458df8SWei Liu     int32_t displacement;
688*27458df8SWei Liu     uint8_t index;
689*27458df8SWei Liu     bool cf;
690*27458df8SWei Liu     int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
691*27458df8SWei Liu 
692*27458df8SWei Liu     VM_PANIC_ON(decode->rex.rex);
693*27458df8SWei Liu 
694*27458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
695*27458df8SWei Liu     index = decode->op[1].val & mask;
696*27458df8SWei Liu 
697*27458df8SWei Liu     if (decode->op[0].type != X86_VAR_REG) {
698*27458df8SWei Liu         if (4 == decode->operand_size) {
699*27458df8SWei Liu             displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
700*27458df8SWei Liu             decode->op[0].ptr += 4 * displacement;
701*27458df8SWei Liu         } else if (2 == decode->operand_size) {
702*27458df8SWei Liu             displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
703*27458df8SWei Liu             decode->op[0].ptr += 2 * displacement;
704*27458df8SWei Liu         } else {
705*27458df8SWei Liu             VM_PANIC("bt 64bit\n");
706*27458df8SWei Liu         }
707*27458df8SWei Liu     }
708*27458df8SWei Liu     decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
709*27458df8SWei Liu                                      decode->operand_size);
710*27458df8SWei Liu     cf = (decode->op[0].val >> index) & 0x01;
711*27458df8SWei Liu 
712*27458df8SWei Liu     switch (flag) {
713*27458df8SWei Liu     case 0:
714*27458df8SWei Liu         set_CF(env, cf);
715*27458df8SWei Liu         return;
716*27458df8SWei Liu     case 1:
717*27458df8SWei Liu         decode->op[0].val ^= (1u << index);
718*27458df8SWei Liu         break;
719*27458df8SWei Liu     case 2:
720*27458df8SWei Liu         decode->op[0].val |= (1u << index);
721*27458df8SWei Liu         break;
722*27458df8SWei Liu     case 3:
723*27458df8SWei Liu         decode->op[0].val &= ~(1u << index);
724*27458df8SWei Liu         break;
725*27458df8SWei Liu     }
726*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
727*27458df8SWei Liu                   decode->operand_size);
728*27458df8SWei Liu     set_CF(env, cf);
729*27458df8SWei Liu }
730*27458df8SWei Liu 
731*27458df8SWei Liu static void exec_bt(CPUX86State *env, struct x86_decode *decode)
732*27458df8SWei Liu {
733*27458df8SWei Liu     do_bt(env, decode, 0);
734*27458df8SWei Liu     env->eip += decode->len;
735*27458df8SWei Liu }
736*27458df8SWei Liu 
737*27458df8SWei Liu static void exec_btc(CPUX86State *env, struct x86_decode *decode)
738*27458df8SWei Liu {
739*27458df8SWei Liu     do_bt(env, decode, 1);
740*27458df8SWei Liu     env->eip += decode->len;
741*27458df8SWei Liu }
742*27458df8SWei Liu 
743*27458df8SWei Liu static void exec_btr(CPUX86State *env, struct x86_decode *decode)
744*27458df8SWei Liu {
745*27458df8SWei Liu     do_bt(env, decode, 3);
746*27458df8SWei Liu     env->eip += decode->len;
747*27458df8SWei Liu }
748*27458df8SWei Liu 
749*27458df8SWei Liu static void exec_bts(CPUX86State *env, struct x86_decode *decode)
750*27458df8SWei Liu {
751*27458df8SWei Liu     do_bt(env, decode, 2);
752*27458df8SWei Liu     env->eip += decode->len;
753*27458df8SWei Liu }
754*27458df8SWei Liu 
755*27458df8SWei Liu void exec_shl(CPUX86State *env, struct x86_decode *decode)
756*27458df8SWei Liu {
757*27458df8SWei Liu     uint8_t count;
758*27458df8SWei Liu     int of = 0, cf = 0;
759*27458df8SWei Liu 
760*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
761*27458df8SWei Liu 
762*27458df8SWei Liu     count = decode->op[1].val;
763*27458df8SWei Liu     count &= 0x1f;      /* count is masked to 5 bits*/
764*27458df8SWei Liu     if (!count) {
765*27458df8SWei Liu         goto exit;
766*27458df8SWei Liu     }
767*27458df8SWei Liu 
768*27458df8SWei Liu     switch (decode->operand_size) {
769*27458df8SWei Liu     case 1:
770*27458df8SWei Liu     {
771*27458df8SWei Liu         uint8_t res = 0;
772*27458df8SWei Liu         if (count <= 8) {
773*27458df8SWei Liu             res = (decode->op[0].val << count);
774*27458df8SWei Liu             cf = (decode->op[0].val >> (8 - count)) & 0x1;
775*27458df8SWei Liu             of = cf ^ (res >> 7);
776*27458df8SWei Liu         }
777*27458df8SWei Liu 
778*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
779*27458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
780*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
781*27458df8SWei Liu         break;
782*27458df8SWei Liu     }
783*27458df8SWei Liu     case 2:
784*27458df8SWei Liu     {
785*27458df8SWei Liu         uint16_t res = 0;
786*27458df8SWei Liu 
787*27458df8SWei Liu         /* from bochs */
788*27458df8SWei Liu         if (count <= 16) {
789*27458df8SWei Liu             res = (decode->op[0].val << count);
790*27458df8SWei Liu             cf = (decode->op[0].val >> (16 - count)) & 0x1;
791*27458df8SWei Liu             of = cf ^ (res >> 15); /* of = cf ^ result15 */
792*27458df8SWei Liu         }
793*27458df8SWei Liu 
794*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
795*27458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
796*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
797*27458df8SWei Liu         break;
798*27458df8SWei Liu     }
799*27458df8SWei Liu     case 4:
800*27458df8SWei Liu     {
801*27458df8SWei Liu         uint32_t res = decode->op[0].val << count;
802*27458df8SWei Liu 
803*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
804*27458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
805*27458df8SWei Liu         cf = (decode->op[0].val >> (32 - count)) & 0x1;
806*27458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
807*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
808*27458df8SWei Liu         break;
809*27458df8SWei Liu     }
810*27458df8SWei Liu     default:
811*27458df8SWei Liu         abort();
812*27458df8SWei Liu     }
813*27458df8SWei Liu 
814*27458df8SWei Liu exit:
815*27458df8SWei Liu     /* lflags_to_rflags(env); */
816*27458df8SWei Liu     env->eip += decode->len;
817*27458df8SWei Liu }
818*27458df8SWei Liu 
819*27458df8SWei Liu void exec_movsx(CPUX86State *env, struct x86_decode *decode)
820*27458df8SWei Liu {
821*27458df8SWei Liu     int src_op_size;
822*27458df8SWei Liu     int op_size = decode->operand_size;
823*27458df8SWei Liu 
824*27458df8SWei Liu     fetch_operands(env, decode, 2, false, false, false);
825*27458df8SWei Liu 
826*27458df8SWei Liu     if (0xbe == decode->opcode[1]) {
827*27458df8SWei Liu         src_op_size = 1;
828*27458df8SWei Liu     } else {
829*27458df8SWei Liu         src_op_size = 2;
830*27458df8SWei Liu     }
831*27458df8SWei Liu 
832*27458df8SWei Liu     decode->operand_size = src_op_size;
833*27458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
834*27458df8SWei Liu     decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
835*27458df8SWei Liu                              src_op_size);
836*27458df8SWei Liu 
837*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
838*27458df8SWei Liu 
839*27458df8SWei Liu     env->eip += decode->len;
840*27458df8SWei Liu }
841*27458df8SWei Liu 
842*27458df8SWei Liu void exec_ror(CPUX86State *env, struct x86_decode *decode)
843*27458df8SWei Liu {
844*27458df8SWei Liu     uint8_t count;
845*27458df8SWei Liu 
846*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
847*27458df8SWei Liu     count = decode->op[1].val;
848*27458df8SWei Liu 
849*27458df8SWei Liu     switch (decode->operand_size) {
850*27458df8SWei Liu     case 1:
851*27458df8SWei Liu     {
852*27458df8SWei Liu         uint32_t bit6, bit7;
853*27458df8SWei Liu         uint8_t res;
854*27458df8SWei Liu 
855*27458df8SWei Liu         if ((count & 0x07) == 0) {
856*27458df8SWei Liu             if (count & 0x18) {
857*27458df8SWei Liu                 bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
858*27458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
859*27458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
860*27458df8SWei Liu              }
861*27458df8SWei Liu         } else {
862*27458df8SWei Liu             count &= 0x7; /* use only bottom 3 bits */
863*27458df8SWei Liu             res = ((uint8_t)decode->op[0].val >> count) |
864*27458df8SWei Liu                    ((uint8_t)decode->op[0].val << (8 - count));
865*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 1);
866*27458df8SWei Liu             bit6 = (res >> 6) & 1;
867*27458df8SWei Liu             bit7 = (res >> 7) & 1;
868*27458df8SWei Liu             /* set eflags: ROR count affects the following flags: C, O */
869*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
870*27458df8SWei Liu         }
871*27458df8SWei Liu         break;
872*27458df8SWei Liu     }
873*27458df8SWei Liu     case 2:
874*27458df8SWei Liu     {
875*27458df8SWei Liu         uint32_t bit14, bit15;
876*27458df8SWei Liu         uint16_t res;
877*27458df8SWei Liu 
878*27458df8SWei Liu         if ((count & 0x0f) == 0) {
879*27458df8SWei Liu             if (count & 0x10) {
880*27458df8SWei Liu                 bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
881*27458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
882*27458df8SWei Liu                 /* of = result14 ^ result15 */
883*27458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
884*27458df8SWei Liu             }
885*27458df8SWei Liu         } else {
886*27458df8SWei Liu             count &= 0x0f;  /* use only 4 LSB's */
887*27458df8SWei Liu             res = ((uint16_t)decode->op[0].val >> count) |
888*27458df8SWei Liu                    ((uint16_t)decode->op[0].val << (16 - count));
889*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 2);
890*27458df8SWei Liu 
891*27458df8SWei Liu             bit14 = (res >> 14) & 1;
892*27458df8SWei Liu             bit15 = (res >> 15) & 1;
893*27458df8SWei Liu             /* of = result14 ^ result15 */
894*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
895*27458df8SWei Liu         }
896*27458df8SWei Liu         break;
897*27458df8SWei Liu     }
898*27458df8SWei Liu     case 4:
899*27458df8SWei Liu     {
900*27458df8SWei Liu         uint32_t bit31, bit30;
901*27458df8SWei Liu         uint32_t res;
902*27458df8SWei Liu 
903*27458df8SWei Liu         count &= 0x1f;
904*27458df8SWei Liu         if (count) {
905*27458df8SWei Liu             res = ((uint32_t)decode->op[0].val >> count) |
906*27458df8SWei Liu                    ((uint32_t)decode->op[0].val << (32 - count));
907*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 4);
908*27458df8SWei Liu 
909*27458df8SWei Liu             bit31 = (res >> 31) & 1;
910*27458df8SWei Liu             bit30 = (res >> 30) & 1;
911*27458df8SWei Liu             /* of = result30 ^ result31 */
912*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
913*27458df8SWei Liu         }
914*27458df8SWei Liu         break;
915*27458df8SWei Liu         }
916*27458df8SWei Liu     }
917*27458df8SWei Liu     env->eip += decode->len;
918*27458df8SWei Liu }
919*27458df8SWei Liu 
920*27458df8SWei Liu void exec_rol(CPUX86State *env, struct x86_decode *decode)
921*27458df8SWei Liu {
922*27458df8SWei Liu     uint8_t count;
923*27458df8SWei Liu 
924*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
925*27458df8SWei Liu     count = decode->op[1].val;
926*27458df8SWei Liu 
927*27458df8SWei Liu     switch (decode->operand_size) {
928*27458df8SWei Liu     case 1:
929*27458df8SWei Liu     {
930*27458df8SWei Liu         uint32_t bit0, bit7;
931*27458df8SWei Liu         uint8_t res;
932*27458df8SWei Liu 
933*27458df8SWei Liu         if ((count & 0x07) == 0) {
934*27458df8SWei Liu             if (count & 0x18) {
935*27458df8SWei Liu                 bit0 = ((uint8_t)decode->op[0].val & 1);
936*27458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7);
937*27458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
938*27458df8SWei Liu             }
939*27458df8SWei Liu         }  else {
940*27458df8SWei Liu             count &= 0x7; /* use only lowest 3 bits */
941*27458df8SWei Liu             res = ((uint8_t)decode->op[0].val << count) |
942*27458df8SWei Liu                    ((uint8_t)decode->op[0].val >> (8 - count));
943*27458df8SWei Liu 
944*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 1);
945*27458df8SWei Liu             /* set eflags:
946*27458df8SWei Liu              * ROL count affects the following flags: C, O
947*27458df8SWei Liu              */
948*27458df8SWei Liu             bit0 = (res &  1);
949*27458df8SWei Liu             bit7 = (res >> 7);
950*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
951*27458df8SWei Liu         }
952*27458df8SWei Liu         break;
953*27458df8SWei Liu     }
954*27458df8SWei Liu     case 2:
955*27458df8SWei Liu     {
956*27458df8SWei Liu         uint32_t bit0, bit15;
957*27458df8SWei Liu         uint16_t res;
958*27458df8SWei Liu 
959*27458df8SWei Liu         if ((count & 0x0f) == 0) {
960*27458df8SWei Liu             if (count & 0x10) {
961*27458df8SWei Liu                 bit0  = ((uint16_t)decode->op[0].val & 0x1);
962*27458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15);
963*27458df8SWei Liu                 /* of = cf ^ result15 */
964*27458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
965*27458df8SWei Liu             }
966*27458df8SWei Liu         } else {
967*27458df8SWei Liu             count &= 0x0f; /* only use bottom 4 bits */
968*27458df8SWei Liu             res = ((uint16_t)decode->op[0].val << count) |
969*27458df8SWei Liu                    ((uint16_t)decode->op[0].val >> (16 - count));
970*27458df8SWei Liu 
971*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 2);
972*27458df8SWei Liu             bit0  = (res & 0x1);
973*27458df8SWei Liu             bit15 = (res >> 15);
974*27458df8SWei Liu             /* of = cf ^ result15 */
975*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
976*27458df8SWei Liu         }
977*27458df8SWei Liu         break;
978*27458df8SWei Liu     }
979*27458df8SWei Liu     case 4:
980*27458df8SWei Liu     {
981*27458df8SWei Liu         uint32_t bit0, bit31;
982*27458df8SWei Liu         uint32_t res;
983*27458df8SWei Liu 
984*27458df8SWei Liu         count &= 0x1f;
985*27458df8SWei Liu         if (count) {
986*27458df8SWei Liu             res = ((uint32_t)decode->op[0].val << count) |
987*27458df8SWei Liu                    ((uint32_t)decode->op[0].val >> (32 - count));
988*27458df8SWei Liu 
989*27458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 4);
990*27458df8SWei Liu             bit0  = (res & 0x1);
991*27458df8SWei Liu             bit31 = (res >> 31);
992*27458df8SWei Liu             /* of = cf ^ result31 */
993*27458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
994*27458df8SWei Liu         }
995*27458df8SWei Liu         break;
996*27458df8SWei Liu         }
997*27458df8SWei Liu     }
998*27458df8SWei Liu     env->eip += decode->len;
999*27458df8SWei Liu }
1000*27458df8SWei Liu 
1001*27458df8SWei Liu 
1002*27458df8SWei Liu void exec_rcl(CPUX86State *env, struct x86_decode *decode)
1003*27458df8SWei Liu {
1004*27458df8SWei Liu     uint8_t count;
1005*27458df8SWei Liu     int of = 0, cf = 0;
1006*27458df8SWei Liu 
1007*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
1008*27458df8SWei Liu     count = decode->op[1].val & 0x1f;
1009*27458df8SWei Liu 
1010*27458df8SWei Liu     switch (decode->operand_size) {
1011*27458df8SWei Liu     case 1:
1012*27458df8SWei Liu     {
1013*27458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
1014*27458df8SWei Liu         uint8_t res;
1015*27458df8SWei Liu         count %= 9;
1016*27458df8SWei Liu         if (!count) {
1017*27458df8SWei Liu             break;
1018*27458df8SWei Liu         }
1019*27458df8SWei Liu 
1020*27458df8SWei Liu         if (1 == count) {
1021*27458df8SWei Liu             res = (op1_8 << 1) | get_CF(env);
1022*27458df8SWei Liu         } else {
1023*27458df8SWei Liu             res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
1024*27458df8SWei Liu                    (op1_8 >> (9 - count));
1025*27458df8SWei Liu         }
1026*27458df8SWei Liu 
1027*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
1028*27458df8SWei Liu 
1029*27458df8SWei Liu         cf = (op1_8 >> (8 - count)) & 0x01;
1030*27458df8SWei Liu         of = cf ^ (res >> 7); /* of = cf ^ result7 */
1031*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1032*27458df8SWei Liu         break;
1033*27458df8SWei Liu     }
1034*27458df8SWei Liu     case 2:
1035*27458df8SWei Liu     {
1036*27458df8SWei Liu         uint16_t res;
1037*27458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
1038*27458df8SWei Liu 
1039*27458df8SWei Liu         count %= 17;
1040*27458df8SWei Liu         if (!count) {
1041*27458df8SWei Liu             break;
1042*27458df8SWei Liu         }
1043*27458df8SWei Liu 
1044*27458df8SWei Liu         if (1 == count) {
1045*27458df8SWei Liu             res = (op1_16 << 1) | get_CF(env);
1046*27458df8SWei Liu         } else if (count == 16) {
1047*27458df8SWei Liu             res = (get_CF(env) << 15) | (op1_16 >> 1);
1048*27458df8SWei Liu         } else { /* 2..15 */
1049*27458df8SWei Liu             res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
1050*27458df8SWei Liu                    (op1_16 >> (17 - count));
1051*27458df8SWei Liu         }
1052*27458df8SWei Liu 
1053*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
1054*27458df8SWei Liu 
1055*27458df8SWei Liu         cf = (op1_16 >> (16 - count)) & 0x1;
1056*27458df8SWei Liu         of = cf ^ (res >> 15); /* of = cf ^ result15 */
1057*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1058*27458df8SWei Liu         break;
1059*27458df8SWei Liu     }
1060*27458df8SWei Liu     case 4:
1061*27458df8SWei Liu     {
1062*27458df8SWei Liu         uint32_t res;
1063*27458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
1064*27458df8SWei Liu 
1065*27458df8SWei Liu         if (!count) {
1066*27458df8SWei Liu             break;
1067*27458df8SWei Liu         }
1068*27458df8SWei Liu 
1069*27458df8SWei Liu         if (1 == count) {
1070*27458df8SWei Liu             res = (op1_32 << 1) | get_CF(env);
1071*27458df8SWei Liu         } else {
1072*27458df8SWei Liu             res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
1073*27458df8SWei Liu                    (op1_32 >> (33 - count));
1074*27458df8SWei Liu         }
1075*27458df8SWei Liu 
1076*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
1077*27458df8SWei Liu 
1078*27458df8SWei Liu         cf = (op1_32 >> (32 - count)) & 0x1;
1079*27458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
1080*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1081*27458df8SWei Liu         break;
1082*27458df8SWei Liu         }
1083*27458df8SWei Liu     }
1084*27458df8SWei Liu     env->eip += decode->len;
1085*27458df8SWei Liu }
1086*27458df8SWei Liu 
1087*27458df8SWei Liu void exec_rcr(CPUX86State *env, struct x86_decode *decode)
1088*27458df8SWei Liu {
1089*27458df8SWei Liu     uint8_t count;
1090*27458df8SWei Liu     int of = 0, cf = 0;
1091*27458df8SWei Liu 
1092*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
1093*27458df8SWei Liu     count = decode->op[1].val & 0x1f;
1094*27458df8SWei Liu 
1095*27458df8SWei Liu     switch (decode->operand_size) {
1096*27458df8SWei Liu     case 1:
1097*27458df8SWei Liu     {
1098*27458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
1099*27458df8SWei Liu         uint8_t res;
1100*27458df8SWei Liu 
1101*27458df8SWei Liu         count %= 9;
1102*27458df8SWei Liu         if (!count) {
1103*27458df8SWei Liu             break;
1104*27458df8SWei Liu         }
1105*27458df8SWei Liu         res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
1106*27458df8SWei Liu                (op1_8 << (9 - count));
1107*27458df8SWei Liu 
1108*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
1109*27458df8SWei Liu 
1110*27458df8SWei Liu         cf = (op1_8 >> (count - 1)) & 0x1;
1111*27458df8SWei Liu         of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
1112*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1113*27458df8SWei Liu         break;
1114*27458df8SWei Liu     }
1115*27458df8SWei Liu     case 2:
1116*27458df8SWei Liu     {
1117*27458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
1118*27458df8SWei Liu         uint16_t res;
1119*27458df8SWei Liu 
1120*27458df8SWei Liu         count %= 17;
1121*27458df8SWei Liu         if (!count) {
1122*27458df8SWei Liu             break;
1123*27458df8SWei Liu         }
1124*27458df8SWei Liu         res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
1125*27458df8SWei Liu                (op1_16 << (17 - count));
1126*27458df8SWei Liu 
1127*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
1128*27458df8SWei Liu 
1129*27458df8SWei Liu         cf = (op1_16 >> (count - 1)) & 0x1;
1130*27458df8SWei Liu         of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
1131*27458df8SWei Liu                                                             result14 */
1132*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1133*27458df8SWei Liu         break;
1134*27458df8SWei Liu     }
1135*27458df8SWei Liu     case 4:
1136*27458df8SWei Liu     {
1137*27458df8SWei Liu         uint32_t res;
1138*27458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
1139*27458df8SWei Liu 
1140*27458df8SWei Liu         if (!count) {
1141*27458df8SWei Liu             break;
1142*27458df8SWei Liu         }
1143*27458df8SWei Liu 
1144*27458df8SWei Liu         if (1 == count) {
1145*27458df8SWei Liu             res = (op1_32 >> 1) | (get_CF(env) << 31);
1146*27458df8SWei Liu         } else {
1147*27458df8SWei Liu             res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
1148*27458df8SWei Liu                    (op1_32 << (33 - count));
1149*27458df8SWei Liu         }
1150*27458df8SWei Liu 
1151*27458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
1152*27458df8SWei Liu 
1153*27458df8SWei Liu         cf = (op1_32 >> (count - 1)) & 0x1;
1154*27458df8SWei Liu         of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
1155*27458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
1156*27458df8SWei Liu         break;
1157*27458df8SWei Liu         }
1158*27458df8SWei Liu     }
1159*27458df8SWei Liu     env->eip += decode->len;
1160*27458df8SWei Liu }
1161*27458df8SWei Liu 
1162*27458df8SWei Liu static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
1163*27458df8SWei Liu {
1164*27458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
1165*27458df8SWei Liu 
1166*27458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
1167*27458df8SWei Liu                   decode->operand_size);
1168*27458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
1169*27458df8SWei Liu                   decode->operand_size);
1170*27458df8SWei Liu 
1171*27458df8SWei Liu     env->eip += decode->len;
1172*27458df8SWei Liu }
1173*27458df8SWei Liu 
1174*27458df8SWei Liu static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
1175*27458df8SWei Liu {
1176*27458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
1177*27458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
1178*27458df8SWei Liu                   decode->operand_size);
1179*27458df8SWei Liu 
1180*27458df8SWei Liu     env->eip += decode->len;
1181*27458df8SWei Liu }
1182*27458df8SWei Liu 
1183*27458df8SWei Liu static struct cmd_handler {
1184*27458df8SWei Liu     enum x86_decode_cmd cmd;
1185*27458df8SWei Liu     void (*handler)(CPUX86State *env, struct x86_decode *ins);
1186*27458df8SWei Liu } handlers[] = {
1187*27458df8SWei Liu     {X86_DECODE_CMD_INVL, NULL,},
1188*27458df8SWei Liu     {X86_DECODE_CMD_MOV, exec_mov},
1189*27458df8SWei Liu     {X86_DECODE_CMD_ADD, exec_add},
1190*27458df8SWei Liu     {X86_DECODE_CMD_OR, exec_or},
1191*27458df8SWei Liu     {X86_DECODE_CMD_ADC, exec_adc},
1192*27458df8SWei Liu     {X86_DECODE_CMD_SBB, exec_sbb},
1193*27458df8SWei Liu     {X86_DECODE_CMD_AND, exec_and},
1194*27458df8SWei Liu     {X86_DECODE_CMD_SUB, exec_sub},
1195*27458df8SWei Liu     {X86_DECODE_CMD_NEG, exec_neg},
1196*27458df8SWei Liu     {X86_DECODE_CMD_XOR, exec_xor},
1197*27458df8SWei Liu     {X86_DECODE_CMD_CMP, exec_cmp},
1198*27458df8SWei Liu     {X86_DECODE_CMD_INC, exec_inc},
1199*27458df8SWei Liu     {X86_DECODE_CMD_DEC, exec_dec},
1200*27458df8SWei Liu     {X86_DECODE_CMD_TST, exec_tst},
1201*27458df8SWei Liu     {X86_DECODE_CMD_NOT, exec_not},
1202*27458df8SWei Liu     {X86_DECODE_CMD_MOVZX, exec_movzx},
1203*27458df8SWei Liu     {X86_DECODE_CMD_OUT, exec_out},
1204*27458df8SWei Liu     {X86_DECODE_CMD_IN, exec_in},
1205*27458df8SWei Liu     {X86_DECODE_CMD_INS, exec_ins},
1206*27458df8SWei Liu     {X86_DECODE_CMD_OUTS, exec_outs},
1207*27458df8SWei Liu     {X86_DECODE_CMD_RDMSR, exec_rdmsr},
1208*27458df8SWei Liu     {X86_DECODE_CMD_WRMSR, exec_wrmsr},
1209*27458df8SWei Liu     {X86_DECODE_CMD_BT, exec_bt},
1210*27458df8SWei Liu     {X86_DECODE_CMD_BTR, exec_btr},
1211*27458df8SWei Liu     {X86_DECODE_CMD_BTC, exec_btc},
1212*27458df8SWei Liu     {X86_DECODE_CMD_BTS, exec_bts},
1213*27458df8SWei Liu     {X86_DECODE_CMD_SHL, exec_shl},
1214*27458df8SWei Liu     {X86_DECODE_CMD_ROL, exec_rol},
1215*27458df8SWei Liu     {X86_DECODE_CMD_ROR, exec_ror},
1216*27458df8SWei Liu     {X86_DECODE_CMD_RCR, exec_rcr},
1217*27458df8SWei Liu     {X86_DECODE_CMD_RCL, exec_rcl},
1218*27458df8SWei Liu     /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
1219*27458df8SWei Liu     {X86_DECODE_CMD_MOVS, exec_movs},
1220*27458df8SWei Liu     {X86_DECODE_CMD_CMPS, exec_cmps},
1221*27458df8SWei Liu     {X86_DECODE_CMD_STOS, exec_stos},
1222*27458df8SWei Liu     {X86_DECODE_CMD_SCAS, exec_scas},
1223*27458df8SWei Liu     {X86_DECODE_CMD_LODS, exec_lods},
1224*27458df8SWei Liu     {X86_DECODE_CMD_MOVSX, exec_movsx},
1225*27458df8SWei Liu     {X86_DECODE_CMD_XCHG, exec_xchg},
1226*27458df8SWei Liu     {X86_DECODE_CMD_XADD, exec_xadd},
1227*27458df8SWei Liu };
1228*27458df8SWei Liu 
1229*27458df8SWei Liu static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
1230*27458df8SWei Liu 
1231*27458df8SWei Liu const struct x86_emul_ops *emul_ops;
1232*27458df8SWei Liu 
1233*27458df8SWei Liu static void init_cmd_handler(void)
1234*27458df8SWei Liu {
1235*27458df8SWei Liu     int i;
1236*27458df8SWei Liu     for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1237*27458df8SWei Liu         _cmd_handler[handlers[i].cmd] = handlers[i];
1238*27458df8SWei Liu     }
1239*27458df8SWei Liu }
1240*27458df8SWei Liu 
1241*27458df8SWei Liu bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
1242*27458df8SWei Liu {
1243*27458df8SWei Liu     if (!_cmd_handler[ins->cmd].handler) {
1244*27458df8SWei Liu         printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip,
1245*27458df8SWei Liu                 ins->cmd, ins->opcode[0],
1246*27458df8SWei Liu                 ins->opcode_len > 1 ? ins->opcode[1] : 0);
1247*27458df8SWei Liu         env->eip += ins->len;
1248*27458df8SWei Liu         return true;
1249*27458df8SWei Liu     }
1250*27458df8SWei Liu 
1251*27458df8SWei Liu     _cmd_handler[ins->cmd].handler(env, ins);
1252*27458df8SWei Liu     return true;
1253*27458df8SWei Liu }
1254*27458df8SWei Liu 
1255*27458df8SWei Liu void init_emu(const struct x86_emul_ops *o)
1256*27458df8SWei Liu {
1257*27458df8SWei Liu     emul_ops = o;
1258*27458df8SWei Liu     init_cmd_handler();
1259*27458df8SWei Liu }
1260