xref: /openbmc/qemu/target/i386/emulate/x86_emu.c (revision 7abf0d95ac6437b38437ad75711c081363995285)
127458df8SWei Liu /*
227458df8SWei Liu  * Copyright (C) 2016 Veertu Inc,
327458df8SWei Liu  * Copyright (C) 2017 Google Inc,
427458df8SWei Liu  *
527458df8SWei Liu  * This program is free software; you can redistribute it and/or
627458df8SWei Liu  * modify it under the terms of the GNU Lesser General Public
727458df8SWei Liu  * License as published by the Free Software Foundation; either
827458df8SWei Liu  * version 2.1 of the License, or (at your option) any later version.
927458df8SWei Liu  *
1027458df8SWei Liu  * This program is distributed in the hope that it will be useful,
1127458df8SWei Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1227458df8SWei Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1327458df8SWei Liu  * Lesser General Public License for more details.
1427458df8SWei Liu  *
1527458df8SWei Liu  * You should have received a copy of the GNU Lesser General Public
1627458df8SWei Liu  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1727458df8SWei Liu  */
1827458df8SWei Liu 
1927458df8SWei Liu /////////////////////////////////////////////////////////////////////////
2027458df8SWei Liu //
2127458df8SWei Liu //  Copyright (C) 2001-2012  The Bochs Project
2227458df8SWei Liu //
2327458df8SWei Liu //  This library is free software; you can redistribute it and/or
2427458df8SWei Liu //  modify it under the terms of the GNU Lesser General Public
2527458df8SWei Liu //  License as published by the Free Software Foundation; either
2627458df8SWei Liu //  version 2.1 of the License, or (at your option) any later version.
2727458df8SWei Liu //
2827458df8SWei Liu //  This library is distributed in the hope that it will be useful,
2927458df8SWei Liu //  but WITHOUT ANY WARRANTY; without even the implied warranty of
3027458df8SWei Liu //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3127458df8SWei Liu //  Lesser General Public License for more details.
3227458df8SWei Liu //
3327458df8SWei Liu //  You should have received a copy of the GNU Lesser General Public
3427458df8SWei Liu //  License along with this library; if not, write to the Free Software
3527458df8SWei Liu //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
3627458df8SWei Liu /////////////////////////////////////////////////////////////////////////
3727458df8SWei Liu 
3827458df8SWei Liu #include "qemu/osdep.h"
3927458df8SWei Liu #include "panic.h"
4027458df8SWei Liu #include "x86_decode.h"
4127458df8SWei Liu #include "x86.h"
4227458df8SWei Liu #include "x86_emu.h"
4327458df8SWei Liu #include "x86_flags.h"
4427458df8SWei Liu 
4527458df8SWei Liu #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
4627458df8SWei Liu {                                                       \
4727458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);  \
4827458df8SWei Liu     switch (decode->operand_size) {                     \
4927458df8SWei Liu     case 1:                                         \
5027458df8SWei Liu     {                                               \
5127458df8SWei Liu         uint8_t v1 = (uint8_t)decode->op[0].val;    \
5227458df8SWei Liu         uint8_t v2 = (uint8_t)decode->op[1].val;    \
5327458df8SWei Liu         uint8_t diff = v1 cmd v2;                   \
5427458df8SWei Liu         if (save_res) {                              \
5527458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 1);  \
5627458df8SWei Liu         } \
5727458df8SWei Liu         FLAGS_FUNC##8(env, v1, v2, diff);           \
5827458df8SWei Liu         break;                                      \
5927458df8SWei Liu     }                                               \
6027458df8SWei Liu     case 2:                                        \
6127458df8SWei Liu     {                                               \
6227458df8SWei Liu         uint16_t v1 = (uint16_t)decode->op[0].val;  \
6327458df8SWei Liu         uint16_t v2 = (uint16_t)decode->op[1].val;  \
6427458df8SWei Liu         uint16_t diff = v1 cmd v2;                  \
6527458df8SWei Liu         if (save_res) {                              \
6627458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 2); \
6727458df8SWei Liu         } \
6827458df8SWei Liu         FLAGS_FUNC##16(env, v1, v2, diff);          \
6927458df8SWei Liu         break;                                      \
7027458df8SWei Liu     }                                               \
7127458df8SWei Liu     case 4:                                        \
7227458df8SWei Liu     {                                               \
7327458df8SWei Liu         uint32_t v1 = (uint32_t)decode->op[0].val;  \
7427458df8SWei Liu         uint32_t v2 = (uint32_t)decode->op[1].val;  \
7527458df8SWei Liu         uint32_t diff = v1 cmd v2;                  \
7627458df8SWei Liu         if (save_res) {                              \
7727458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, diff, 4); \
7827458df8SWei Liu         } \
7927458df8SWei Liu         FLAGS_FUNC##32(env, v1, v2, diff);          \
8027458df8SWei Liu         break;                                      \
8127458df8SWei Liu     }                                               \
8227458df8SWei Liu     default:                                        \
8327458df8SWei Liu         VM_PANIC("bad size\n");                    \
8427458df8SWei Liu     }                                                   \
8527458df8SWei Liu }                                                       \
8627458df8SWei Liu 
8727458df8SWei Liu target_ulong read_reg(CPUX86State *env, int reg, int size)
8827458df8SWei Liu {
8927458df8SWei Liu     switch (size) {
9027458df8SWei Liu     case 1:
9127458df8SWei Liu         return x86_reg(env, reg)->lx;
9227458df8SWei Liu     case 2:
9327458df8SWei Liu         return x86_reg(env, reg)->rx;
9427458df8SWei Liu     case 4:
9527458df8SWei Liu         return x86_reg(env, reg)->erx;
9627458df8SWei Liu     case 8:
9727458df8SWei Liu         return x86_reg(env, reg)->rrx;
9827458df8SWei Liu     default:
9927458df8SWei Liu         abort();
10027458df8SWei Liu     }
10127458df8SWei Liu     return 0;
10227458df8SWei Liu }
10327458df8SWei Liu 
10427458df8SWei Liu void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
10527458df8SWei Liu {
10627458df8SWei Liu     switch (size) {
10727458df8SWei Liu     case 1:
10827458df8SWei Liu         x86_reg(env, reg)->lx = val;
10927458df8SWei Liu         break;
11027458df8SWei Liu     case 2:
11127458df8SWei Liu         x86_reg(env, reg)->rx = val;
11227458df8SWei Liu         break;
11327458df8SWei Liu     case 4:
11427458df8SWei Liu         x86_reg(env, reg)->rrx = (uint32_t)val;
11527458df8SWei Liu         break;
11627458df8SWei Liu     case 8:
11727458df8SWei Liu         x86_reg(env, reg)->rrx = val;
11827458df8SWei Liu         break;
11927458df8SWei Liu     default:
12027458df8SWei Liu         abort();
12127458df8SWei Liu     }
12227458df8SWei Liu }
12327458df8SWei Liu 
12427458df8SWei Liu target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
12527458df8SWei Liu {
12627458df8SWei Liu     target_ulong val;
12727458df8SWei Liu 
12827458df8SWei Liu     switch (size) {
12927458df8SWei Liu     case 1:
13027458df8SWei Liu         val = *(uint8_t *)reg_ptr;
13127458df8SWei Liu         break;
13227458df8SWei Liu     case 2:
13327458df8SWei Liu         val = *(uint16_t *)reg_ptr;
13427458df8SWei Liu         break;
13527458df8SWei Liu     case 4:
13627458df8SWei Liu         val = *(uint32_t *)reg_ptr;
13727458df8SWei Liu         break;
13827458df8SWei Liu     case 8:
13927458df8SWei Liu         val = *(uint64_t *)reg_ptr;
14027458df8SWei Liu         break;
14127458df8SWei Liu     default:
14227458df8SWei Liu         abort();
14327458df8SWei Liu     }
14427458df8SWei Liu     return val;
14527458df8SWei Liu }
14627458df8SWei Liu 
14727458df8SWei Liu void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
14827458df8SWei Liu {
14927458df8SWei Liu     switch (size) {
15027458df8SWei Liu     case 1:
15127458df8SWei Liu         *(uint8_t *)reg_ptr = val;
15227458df8SWei Liu         break;
15327458df8SWei Liu     case 2:
15427458df8SWei Liu         *(uint16_t *)reg_ptr = val;
15527458df8SWei Liu         break;
15627458df8SWei Liu     case 4:
15727458df8SWei Liu         *(uint64_t *)reg_ptr = (uint32_t)val;
15827458df8SWei Liu         break;
15927458df8SWei Liu     case 8:
16027458df8SWei Liu         *(uint64_t *)reg_ptr = val;
16127458df8SWei Liu         break;
16227458df8SWei Liu     default:
16327458df8SWei Liu         abort();
16427458df8SWei Liu     }
16527458df8SWei Liu }
16627458df8SWei Liu 
16727458df8SWei Liu static bool is_host_reg(CPUX86State *env, target_ulong ptr)
16827458df8SWei Liu {
16927458df8SWei Liu     return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
17027458df8SWei Liu }
17127458df8SWei Liu 
17227458df8SWei Liu void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
17327458df8SWei Liu {
17427458df8SWei Liu     if (is_host_reg(env, ptr)) {
17527458df8SWei Liu         write_val_to_reg(ptr, val, size);
17627458df8SWei Liu         return;
17727458df8SWei Liu     }
17827458df8SWei Liu     emul_ops->write_mem(env_cpu(env), &val, ptr, size);
17927458df8SWei Liu }
18027458df8SWei Liu 
18127458df8SWei Liu uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
18227458df8SWei Liu {
18327458df8SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
18427458df8SWei Liu     return env->emu_mmio_buf;
18527458df8SWei Liu }
18627458df8SWei Liu 
18727458df8SWei Liu 
18827458df8SWei Liu target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
18927458df8SWei Liu {
19027458df8SWei Liu     target_ulong val;
19127458df8SWei Liu     uint8_t *mmio_ptr;
19227458df8SWei Liu 
19327458df8SWei Liu     if (is_host_reg(env, ptr)) {
19427458df8SWei Liu         return read_val_from_reg(ptr, size);
19527458df8SWei Liu     }
19627458df8SWei Liu 
19727458df8SWei Liu     mmio_ptr = read_mmio(env, ptr, size);
19827458df8SWei Liu     switch (size) {
19927458df8SWei Liu     case 1:
20027458df8SWei Liu         val = *(uint8_t *)mmio_ptr;
20127458df8SWei Liu         break;
20227458df8SWei Liu     case 2:
20327458df8SWei Liu         val = *(uint16_t *)mmio_ptr;
20427458df8SWei Liu         break;
20527458df8SWei Liu     case 4:
20627458df8SWei Liu         val = *(uint32_t *)mmio_ptr;
20727458df8SWei Liu         break;
20827458df8SWei Liu     case 8:
20927458df8SWei Liu         val = *(uint64_t *)mmio_ptr;
21027458df8SWei Liu         break;
21127458df8SWei Liu     default:
21227458df8SWei Liu         VM_PANIC("bad size\n");
21327458df8SWei Liu         break;
21427458df8SWei Liu     }
21527458df8SWei Liu     return val;
21627458df8SWei Liu }
21727458df8SWei Liu 
21827458df8SWei Liu static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
21927458df8SWei Liu                            int n, bool val_op0, bool val_op1, bool val_op2)
22027458df8SWei Liu {
22127458df8SWei Liu     int i;
22227458df8SWei Liu     bool calc_val[3] = {val_op0, val_op1, val_op2};
22327458df8SWei Liu 
22427458df8SWei Liu     for (i = 0; i < n; i++) {
22527458df8SWei Liu         switch (decode->op[i].type) {
22627458df8SWei Liu         case X86_VAR_IMMEDIATE:
22727458df8SWei Liu             break;
22827458df8SWei Liu         case X86_VAR_REG:
22927458df8SWei Liu             VM_PANIC_ON(!decode->op[i].ptr);
23027458df8SWei Liu             if (calc_val[i]) {
23127458df8SWei Liu                 decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
23227458df8SWei Liu                                                       decode->operand_size);
23327458df8SWei Liu             }
23427458df8SWei Liu             break;
23527458df8SWei Liu         case X86_VAR_RM:
23627458df8SWei Liu             calc_modrm_operand(env, decode, &decode->op[i]);
23727458df8SWei Liu             if (calc_val[i]) {
23827458df8SWei Liu                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
23927458df8SWei Liu                                                  decode->operand_size);
24027458df8SWei Liu             }
24127458df8SWei Liu             break;
24227458df8SWei Liu         case X86_VAR_OFFSET:
24327458df8SWei Liu             decode->op[i].ptr = decode_linear_addr(env, decode,
24427458df8SWei Liu                                                    decode->op[i].ptr,
24527458df8SWei Liu                                                    R_DS);
24627458df8SWei Liu             if (calc_val[i]) {
24727458df8SWei Liu                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
24827458df8SWei Liu                                                  decode->operand_size);
24927458df8SWei Liu             }
25027458df8SWei Liu             break;
25127458df8SWei Liu         default:
25227458df8SWei Liu             break;
25327458df8SWei Liu         }
25427458df8SWei Liu     }
25527458df8SWei Liu }
25627458df8SWei Liu 
25727458df8SWei Liu static void exec_mov(CPUX86State *env, struct x86_decode *decode)
25827458df8SWei Liu {
25927458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
26027458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
26127458df8SWei Liu                   decode->operand_size);
26227458df8SWei Liu 
26327458df8SWei Liu     env->eip += decode->len;
26427458df8SWei Liu }
26527458df8SWei Liu 
26627458df8SWei Liu static void exec_add(CPUX86State *env, struct x86_decode *decode)
26727458df8SWei Liu {
26827458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
26927458df8SWei Liu     env->eip += decode->len;
27027458df8SWei Liu }
27127458df8SWei Liu 
27227458df8SWei Liu static void exec_or(CPUX86State *env, struct x86_decode *decode)
27327458df8SWei Liu {
27427458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
27527458df8SWei Liu     env->eip += decode->len;
27627458df8SWei Liu }
27727458df8SWei Liu 
27827458df8SWei Liu static void exec_adc(CPUX86State *env, struct x86_decode *decode)
27927458df8SWei Liu {
28027458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
28127458df8SWei Liu     env->eip += decode->len;
28227458df8SWei Liu }
28327458df8SWei Liu 
28427458df8SWei Liu static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
28527458df8SWei Liu {
28627458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
28727458df8SWei Liu     env->eip += decode->len;
28827458df8SWei Liu }
28927458df8SWei Liu 
29027458df8SWei Liu static void exec_and(CPUX86State *env, struct x86_decode *decode)
29127458df8SWei Liu {
29227458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
29327458df8SWei Liu     env->eip += decode->len;
29427458df8SWei Liu }
29527458df8SWei Liu 
29627458df8SWei Liu static void exec_sub(CPUX86State *env, struct x86_decode *decode)
29727458df8SWei Liu {
29827458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
29927458df8SWei Liu     env->eip += decode->len;
30027458df8SWei Liu }
30127458df8SWei Liu 
30227458df8SWei Liu static void exec_xor(CPUX86State *env, struct x86_decode *decode)
30327458df8SWei Liu {
30427458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
30527458df8SWei Liu     env->eip += decode->len;
30627458df8SWei Liu }
30727458df8SWei Liu 
30827458df8SWei Liu static void exec_neg(CPUX86State *env, struct x86_decode *decode)
30927458df8SWei Liu {
31027458df8SWei Liu     /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
31127458df8SWei Liu     int32_t val;
31227458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
31327458df8SWei Liu 
31427458df8SWei Liu     val = 0 - sign(decode->op[1].val, decode->operand_size);
31527458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
31627458df8SWei Liu 
31727458df8SWei Liu     if (4 == decode->operand_size) {
31827458df8SWei Liu         SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
31927458df8SWei Liu     } else if (2 == decode->operand_size) {
32027458df8SWei Liu         SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
32127458df8SWei Liu     } else if (1 == decode->operand_size) {
32227458df8SWei Liu         SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
32327458df8SWei Liu     } else {
32427458df8SWei Liu         VM_PANIC("bad op size\n");
32527458df8SWei Liu     }
32627458df8SWei Liu 
32727458df8SWei Liu     /*lflags_to_rflags(env);*/
32827458df8SWei Liu     env->eip += decode->len;
32927458df8SWei Liu }
33027458df8SWei Liu 
33127458df8SWei Liu static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
33227458df8SWei Liu {
33327458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
33427458df8SWei Liu     env->eip += decode->len;
33527458df8SWei Liu }
33627458df8SWei Liu 
33727458df8SWei Liu static void exec_inc(CPUX86State *env, struct x86_decode *decode)
33827458df8SWei Liu {
33927458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
34027458df8SWei Liu     decode->op[1].val = 0;
34127458df8SWei Liu 
34227458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
34327458df8SWei Liu 
34427458df8SWei Liu     env->eip += decode->len;
34527458df8SWei Liu }
34627458df8SWei Liu 
34727458df8SWei Liu static void exec_dec(CPUX86State *env, struct x86_decode *decode)
34827458df8SWei Liu {
34927458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
35027458df8SWei Liu     decode->op[1].val = 0;
35127458df8SWei Liu 
35227458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
35327458df8SWei Liu     env->eip += decode->len;
35427458df8SWei Liu }
35527458df8SWei Liu 
35627458df8SWei Liu static void exec_tst(CPUX86State *env, struct x86_decode *decode)
35727458df8SWei Liu {
35827458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
35927458df8SWei Liu     env->eip += decode->len;
36027458df8SWei Liu }
36127458df8SWei Liu 
36227458df8SWei Liu static void exec_not(CPUX86State *env, struct x86_decode *decode)
36327458df8SWei Liu {
36427458df8SWei Liu     fetch_operands(env, decode, 1, true, false, false);
36527458df8SWei Liu 
36627458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
36727458df8SWei Liu                   decode->operand_size);
36827458df8SWei Liu     env->eip += decode->len;
36927458df8SWei Liu }
37027458df8SWei Liu 
37127458df8SWei Liu void exec_movzx(CPUX86State *env, struct x86_decode *decode)
37227458df8SWei Liu {
37327458df8SWei Liu     int src_op_size;
37427458df8SWei Liu     int op_size = decode->operand_size;
37527458df8SWei Liu 
37627458df8SWei Liu     fetch_operands(env, decode, 1, false, false, false);
37727458df8SWei Liu 
37827458df8SWei Liu     if (0xb6 == decode->opcode[1]) {
37927458df8SWei Liu         src_op_size = 1;
38027458df8SWei Liu     } else {
38127458df8SWei Liu         src_op_size = 2;
38227458df8SWei Liu     }
38327458df8SWei Liu     decode->operand_size = src_op_size;
38427458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
38527458df8SWei Liu     decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
38627458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
38727458df8SWei Liu 
38827458df8SWei Liu     env->eip += decode->len;
38927458df8SWei Liu }
39027458df8SWei Liu 
39127458df8SWei Liu static void exec_out(CPUX86State *env, struct x86_decode *decode)
39227458df8SWei Liu {
39327458df8SWei Liu     switch (decode->opcode[0]) {
39427458df8SWei Liu     case 0xe6:
39527458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
39627458df8SWei Liu         break;
39727458df8SWei Liu     case 0xe7:
39827458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
39927458df8SWei Liu                             decode->operand_size, 1);
40027458df8SWei Liu         break;
40127458df8SWei Liu     case 0xee:
40227458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
40327458df8SWei Liu         break;
40427458df8SWei Liu     case 0xef:
40527458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
40627458df8SWei Liu                             decode->operand_size, 1);
40727458df8SWei Liu         break;
40827458df8SWei Liu     default:
40927458df8SWei Liu         VM_PANIC("Bad out opcode\n");
41027458df8SWei Liu         break;
41127458df8SWei Liu     }
41227458df8SWei Liu     env->eip += decode->len;
41327458df8SWei Liu }
41427458df8SWei Liu 
41527458df8SWei Liu static void exec_in(CPUX86State *env, struct x86_decode *decode)
41627458df8SWei Liu {
41727458df8SWei Liu     target_ulong val = 0;
41827458df8SWei Liu     switch (decode->opcode[0]) {
41927458df8SWei Liu     case 0xe4:
42027458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
42127458df8SWei Liu         break;
42227458df8SWei Liu     case 0xe5:
42327458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
42427458df8SWei Liu                       decode->operand_size, 1);
42527458df8SWei Liu         if (decode->operand_size == 2) {
42627458df8SWei Liu             AX(env) = val;
42727458df8SWei Liu         } else {
42827458df8SWei Liu             RAX(env) = (uint32_t)val;
42927458df8SWei Liu         }
43027458df8SWei Liu         break;
43127458df8SWei Liu     case 0xec:
43227458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
43327458df8SWei Liu         break;
43427458df8SWei Liu     case 0xed:
43527458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
43627458df8SWei Liu                             decode->operand_size, 1);
43727458df8SWei Liu         if (decode->operand_size == 2) {
43827458df8SWei Liu             AX(env) = val;
43927458df8SWei Liu         } else {
44027458df8SWei Liu             RAX(env) = (uint32_t)val;
44127458df8SWei Liu         }
44227458df8SWei Liu 
44327458df8SWei Liu         break;
44427458df8SWei Liu     default:
44527458df8SWei Liu         VM_PANIC("Bad in opcode\n");
44627458df8SWei Liu         break;
44727458df8SWei Liu     }
44827458df8SWei Liu 
44927458df8SWei Liu     env->eip += decode->len;
45027458df8SWei Liu }
45127458df8SWei Liu 
45227458df8SWei Liu static inline void string_increment_reg(CPUX86State *env, int reg,
45327458df8SWei Liu                                         struct x86_decode *decode)
45427458df8SWei Liu {
45527458df8SWei Liu     target_ulong val = read_reg(env, reg, decode->addressing_size);
45627458df8SWei Liu     if (env->eflags & DF_MASK) {
45727458df8SWei Liu         val -= decode->operand_size;
45827458df8SWei Liu     } else {
45927458df8SWei Liu         val += decode->operand_size;
46027458df8SWei Liu     }
46127458df8SWei Liu     write_reg(env, reg, val, decode->addressing_size);
46227458df8SWei Liu }
46327458df8SWei Liu 
46427458df8SWei Liu static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
46527458df8SWei Liu                               void (*func)(CPUX86State *env,
46627458df8SWei Liu                                            struct x86_decode *ins), int rep)
46727458df8SWei Liu {
46827458df8SWei Liu     target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
46927458df8SWei Liu     while (rcx--) {
47027458df8SWei Liu         func(env, decode);
47127458df8SWei Liu         write_reg(env, R_ECX, rcx, decode->addressing_size);
47227458df8SWei Liu         if ((PREFIX_REP == rep) && !get_ZF(env)) {
47327458df8SWei Liu             break;
47427458df8SWei Liu         }
47527458df8SWei Liu         if ((PREFIX_REPN == rep) && get_ZF(env)) {
47627458df8SWei Liu             break;
47727458df8SWei Liu         }
47827458df8SWei Liu     }
47927458df8SWei Liu }
48027458df8SWei Liu 
48127458df8SWei Liu static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
48227458df8SWei Liu {
48327458df8SWei Liu     target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
48427458df8SWei Liu                                          decode->addressing_size, R_ES);
48527458df8SWei Liu 
48627458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
48727458df8SWei Liu                         decode->operand_size, 1);
48827458df8SWei Liu     emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
48927458df8SWei Liu                         decode->operand_size);
49027458df8SWei Liu 
49127458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
49227458df8SWei Liu }
49327458df8SWei Liu 
49427458df8SWei Liu static void exec_ins(CPUX86State *env, struct x86_decode *decode)
49527458df8SWei Liu {
49627458df8SWei Liu     if (decode->rep) {
49727458df8SWei Liu         string_rep(env, decode, exec_ins_single, 0);
49827458df8SWei Liu     } else {
49927458df8SWei Liu         exec_ins_single(env, decode);
50027458df8SWei Liu     }
50127458df8SWei Liu 
50227458df8SWei Liu     env->eip += decode->len;
50327458df8SWei Liu }
50427458df8SWei Liu 
50527458df8SWei Liu static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
50627458df8SWei Liu {
50727458df8SWei Liu     target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
50827458df8SWei Liu 
50927458df8SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
51027458df8SWei Liu                        decode->operand_size);
51127458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
51227458df8SWei Liu                         decode->operand_size, 1);
51327458df8SWei Liu 
51427458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
51527458df8SWei Liu }
51627458df8SWei Liu 
51727458df8SWei Liu static void exec_outs(CPUX86State *env, struct x86_decode *decode)
51827458df8SWei Liu {
51927458df8SWei Liu     if (decode->rep) {
52027458df8SWei Liu         string_rep(env, decode, exec_outs_single, 0);
52127458df8SWei Liu     } else {
52227458df8SWei Liu         exec_outs_single(env, decode);
52327458df8SWei Liu     }
52427458df8SWei Liu 
52527458df8SWei Liu     env->eip += decode->len;
52627458df8SWei Liu }
52727458df8SWei Liu 
52827458df8SWei Liu static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
52927458df8SWei Liu {
53027458df8SWei Liu     target_ulong src_addr;
53127458df8SWei Liu     target_ulong dst_addr;
53227458df8SWei Liu     target_ulong val;
53327458df8SWei Liu 
53427458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
53527458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
53627458df8SWei Liu                                 decode->addressing_size, R_ES);
53727458df8SWei Liu 
53827458df8SWei Liu     val = read_val_ext(env, src_addr, decode->operand_size);
53927458df8SWei Liu     write_val_ext(env, dst_addr, val, decode->operand_size);
54027458df8SWei Liu 
54127458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
54227458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
54327458df8SWei Liu }
54427458df8SWei Liu 
54527458df8SWei Liu static void exec_movs(CPUX86State *env, struct x86_decode *decode)
54627458df8SWei Liu {
54727458df8SWei Liu     if (decode->rep) {
54827458df8SWei Liu         string_rep(env, decode, exec_movs_single, 0);
54927458df8SWei Liu     } else {
55027458df8SWei Liu         exec_movs_single(env, decode);
55127458df8SWei Liu     }
55227458df8SWei Liu 
55327458df8SWei Liu     env->eip += decode->len;
55427458df8SWei Liu }
55527458df8SWei Liu 
55627458df8SWei Liu static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
55727458df8SWei Liu {
55827458df8SWei Liu     target_ulong src_addr;
55927458df8SWei Liu     target_ulong dst_addr;
56027458df8SWei Liu 
56127458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
56227458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
56327458df8SWei Liu                                 decode->addressing_size, R_ES);
56427458df8SWei Liu 
56527458df8SWei Liu     decode->op[0].type = X86_VAR_IMMEDIATE;
56627458df8SWei Liu     decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
56727458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
56827458df8SWei Liu     decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
56927458df8SWei Liu 
57027458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
57127458df8SWei Liu 
57227458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
57327458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
57427458df8SWei Liu }
57527458df8SWei Liu 
57627458df8SWei Liu static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
57727458df8SWei Liu {
57827458df8SWei Liu     if (decode->rep) {
57927458df8SWei Liu         string_rep(env, decode, exec_cmps_single, decode->rep);
58027458df8SWei Liu     } else {
58127458df8SWei Liu         exec_cmps_single(env, decode);
58227458df8SWei Liu     }
58327458df8SWei Liu     env->eip += decode->len;
58427458df8SWei Liu }
58527458df8SWei Liu 
58627458df8SWei Liu 
58727458df8SWei Liu static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
58827458df8SWei Liu {
58927458df8SWei Liu     target_ulong addr;
59027458df8SWei Liu     target_ulong val;
59127458df8SWei Liu 
59227458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
59327458df8SWei Liu                             decode->addressing_size, R_ES);
59427458df8SWei Liu     val = read_reg(env, R_EAX, decode->operand_size);
59527458df8SWei Liu     emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
59627458df8SWei Liu 
59727458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
59827458df8SWei Liu }
59927458df8SWei Liu 
60027458df8SWei Liu 
60127458df8SWei Liu static void exec_stos(CPUX86State *env, struct x86_decode *decode)
60227458df8SWei Liu {
60327458df8SWei Liu     if (decode->rep) {
60427458df8SWei Liu         string_rep(env, decode, exec_stos_single, 0);
60527458df8SWei Liu     } else {
60627458df8SWei Liu         exec_stos_single(env, decode);
60727458df8SWei Liu     }
60827458df8SWei Liu 
60927458df8SWei Liu     env->eip += decode->len;
61027458df8SWei Liu }
61127458df8SWei Liu 
61227458df8SWei Liu static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
61327458df8SWei Liu {
61427458df8SWei Liu     target_ulong addr;
61527458df8SWei Liu 
61627458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
61727458df8SWei Liu                             decode->addressing_size, R_ES);
61827458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
61927458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
62027458df8SWei Liu 
62127458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
62227458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
62327458df8SWei Liu }
62427458df8SWei Liu 
62527458df8SWei Liu static void exec_scas(CPUX86State *env, struct x86_decode *decode)
62627458df8SWei Liu {
62727458df8SWei Liu     decode->op[0].type = X86_VAR_REG;
62827458df8SWei Liu     decode->op[0].reg = R_EAX;
62927458df8SWei Liu     if (decode->rep) {
63027458df8SWei Liu         string_rep(env, decode, exec_scas_single, decode->rep);
63127458df8SWei Liu     } else {
63227458df8SWei Liu         exec_scas_single(env, decode);
63327458df8SWei Liu     }
63427458df8SWei Liu 
63527458df8SWei Liu     env->eip += decode->len;
63627458df8SWei Liu }
63727458df8SWei Liu 
63827458df8SWei Liu static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
63927458df8SWei Liu {
64027458df8SWei Liu     target_ulong addr;
64127458df8SWei Liu     target_ulong val = 0;
64227458df8SWei Liu 
64327458df8SWei Liu     addr = decode_linear_addr(env, decode, RSI(env), R_DS);
64427458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
64527458df8SWei Liu     write_reg(env, R_EAX, val, decode->operand_size);
64627458df8SWei Liu 
64727458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
64827458df8SWei Liu }
64927458df8SWei Liu 
65027458df8SWei Liu static void exec_lods(CPUX86State *env, struct x86_decode *decode)
65127458df8SWei Liu {
65227458df8SWei Liu     if (decode->rep) {
65327458df8SWei Liu         string_rep(env, decode, exec_lods_single, 0);
65427458df8SWei Liu     } else {
65527458df8SWei Liu         exec_lods_single(env, decode);
65627458df8SWei Liu     }
65727458df8SWei Liu 
65827458df8SWei Liu     env->eip += decode->len;
65927458df8SWei Liu }
66027458df8SWei Liu 
66127458df8SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
66227458df8SWei Liu {
66327458df8SWei Liu     env->exception_nr = exception_index;
66427458df8SWei Liu     env->error_code = error_code;
66527458df8SWei Liu     env->has_error_code = true;
66627458df8SWei Liu     env->exception_injected = 1;
66727458df8SWei Liu }
66827458df8SWei Liu 
66927458df8SWei Liu static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
67027458df8SWei Liu {
67127458df8SWei Liu     emul_ops->simulate_rdmsr(env_cpu(env));
67227458df8SWei Liu     env->eip += decode->len;
67327458df8SWei Liu }
67427458df8SWei Liu 
67527458df8SWei Liu static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
67627458df8SWei Liu {
67727458df8SWei Liu     emul_ops->simulate_wrmsr(env_cpu(env));
67827458df8SWei Liu     env->eip += decode->len;
67927458df8SWei Liu }
68027458df8SWei Liu 
68127458df8SWei Liu /*
68227458df8SWei Liu  * flag:
68327458df8SWei Liu  * 0 - bt, 1 - btc, 2 - bts, 3 - btr
68427458df8SWei Liu  */
68527458df8SWei Liu static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
68627458df8SWei Liu {
68727458df8SWei Liu     int32_t displacement;
68827458df8SWei Liu     uint8_t index;
68927458df8SWei Liu     bool cf;
69027458df8SWei Liu     int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
69127458df8SWei Liu 
69227458df8SWei Liu     VM_PANIC_ON(decode->rex.rex);
69327458df8SWei Liu 
69427458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
69527458df8SWei Liu     index = decode->op[1].val & mask;
69627458df8SWei Liu 
69727458df8SWei Liu     if (decode->op[0].type != X86_VAR_REG) {
69827458df8SWei Liu         if (4 == decode->operand_size) {
69927458df8SWei Liu             displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
70027458df8SWei Liu             decode->op[0].ptr += 4 * displacement;
70127458df8SWei Liu         } else if (2 == decode->operand_size) {
70227458df8SWei Liu             displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
70327458df8SWei Liu             decode->op[0].ptr += 2 * displacement;
70427458df8SWei Liu         } else {
70527458df8SWei Liu             VM_PANIC("bt 64bit\n");
70627458df8SWei Liu         }
70727458df8SWei Liu     }
70827458df8SWei Liu     decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
70927458df8SWei Liu                                      decode->operand_size);
71027458df8SWei Liu     cf = (decode->op[0].val >> index) & 0x01;
71127458df8SWei Liu 
71227458df8SWei Liu     switch (flag) {
71327458df8SWei Liu     case 0:
71427458df8SWei Liu         set_CF(env, cf);
71527458df8SWei Liu         return;
71627458df8SWei Liu     case 1:
71727458df8SWei Liu         decode->op[0].val ^= (1u << index);
71827458df8SWei Liu         break;
71927458df8SWei Liu     case 2:
72027458df8SWei Liu         decode->op[0].val |= (1u << index);
72127458df8SWei Liu         break;
72227458df8SWei Liu     case 3:
72327458df8SWei Liu         decode->op[0].val &= ~(1u << index);
72427458df8SWei Liu         break;
72527458df8SWei Liu     }
72627458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
72727458df8SWei Liu                   decode->operand_size);
72827458df8SWei Liu     set_CF(env, cf);
72927458df8SWei Liu }
73027458df8SWei Liu 
73127458df8SWei Liu static void exec_bt(CPUX86State *env, struct x86_decode *decode)
73227458df8SWei Liu {
73327458df8SWei Liu     do_bt(env, decode, 0);
73427458df8SWei Liu     env->eip += decode->len;
73527458df8SWei Liu }
73627458df8SWei Liu 
73727458df8SWei Liu static void exec_btc(CPUX86State *env, struct x86_decode *decode)
73827458df8SWei Liu {
73927458df8SWei Liu     do_bt(env, decode, 1);
74027458df8SWei Liu     env->eip += decode->len;
74127458df8SWei Liu }
74227458df8SWei Liu 
74327458df8SWei Liu static void exec_btr(CPUX86State *env, struct x86_decode *decode)
74427458df8SWei Liu {
74527458df8SWei Liu     do_bt(env, decode, 3);
74627458df8SWei Liu     env->eip += decode->len;
74727458df8SWei Liu }
74827458df8SWei Liu 
74927458df8SWei Liu static void exec_bts(CPUX86State *env, struct x86_decode *decode)
75027458df8SWei Liu {
75127458df8SWei Liu     do_bt(env, decode, 2);
75227458df8SWei Liu     env->eip += decode->len;
75327458df8SWei Liu }
75427458df8SWei Liu 
75527458df8SWei Liu void exec_shl(CPUX86State *env, struct x86_decode *decode)
75627458df8SWei Liu {
75727458df8SWei Liu     uint8_t count;
75827458df8SWei Liu     int of = 0, cf = 0;
75927458df8SWei Liu 
76027458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
76127458df8SWei Liu 
76227458df8SWei Liu     count = decode->op[1].val;
76327458df8SWei Liu     count &= 0x1f;      /* count is masked to 5 bits*/
76427458df8SWei Liu     if (!count) {
76527458df8SWei Liu         goto exit;
76627458df8SWei Liu     }
76727458df8SWei Liu 
76827458df8SWei Liu     switch (decode->operand_size) {
76927458df8SWei Liu     case 1:
77027458df8SWei Liu     {
77127458df8SWei Liu         uint8_t res = 0;
77227458df8SWei Liu         if (count <= 8) {
77327458df8SWei Liu             res = (decode->op[0].val << count);
77427458df8SWei Liu             cf = (decode->op[0].val >> (8 - count)) & 0x1;
77527458df8SWei Liu             of = cf ^ (res >> 7);
77627458df8SWei Liu         }
77727458df8SWei Liu 
77827458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
77927458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
78027458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
78127458df8SWei Liu         break;
78227458df8SWei Liu     }
78327458df8SWei Liu     case 2:
78427458df8SWei Liu     {
78527458df8SWei Liu         uint16_t res = 0;
78627458df8SWei Liu 
78727458df8SWei Liu         /* from bochs */
78827458df8SWei Liu         if (count <= 16) {
78927458df8SWei Liu             res = (decode->op[0].val << count);
79027458df8SWei Liu             cf = (decode->op[0].val >> (16 - count)) & 0x1;
79127458df8SWei Liu             of = cf ^ (res >> 15); /* of = cf ^ result15 */
79227458df8SWei Liu         }
79327458df8SWei Liu 
79427458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
79527458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
79627458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
79727458df8SWei Liu         break;
79827458df8SWei Liu     }
79927458df8SWei Liu     case 4:
80027458df8SWei Liu     {
80127458df8SWei Liu         uint32_t res = decode->op[0].val << count;
80227458df8SWei Liu 
80327458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
80427458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
80527458df8SWei Liu         cf = (decode->op[0].val >> (32 - count)) & 0x1;
80627458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
80727458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
80827458df8SWei Liu         break;
80927458df8SWei Liu     }
81027458df8SWei Liu     default:
81127458df8SWei Liu         abort();
81227458df8SWei Liu     }
81327458df8SWei Liu 
81427458df8SWei Liu exit:
81527458df8SWei Liu     /* lflags_to_rflags(env); */
81627458df8SWei Liu     env->eip += decode->len;
81727458df8SWei Liu }
81827458df8SWei Liu 
81927458df8SWei Liu void exec_movsx(CPUX86State *env, struct x86_decode *decode)
82027458df8SWei Liu {
82127458df8SWei Liu     int src_op_size;
82227458df8SWei Liu     int op_size = decode->operand_size;
82327458df8SWei Liu 
82427458df8SWei Liu     fetch_operands(env, decode, 2, false, false, false);
82527458df8SWei Liu 
82627458df8SWei Liu     if (0xbe == decode->opcode[1]) {
82727458df8SWei Liu         src_op_size = 1;
82827458df8SWei Liu     } else {
82927458df8SWei Liu         src_op_size = 2;
83027458df8SWei Liu     }
83127458df8SWei Liu 
83227458df8SWei Liu     decode->operand_size = src_op_size;
83327458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
83427458df8SWei Liu     decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
83527458df8SWei Liu                              src_op_size);
83627458df8SWei Liu 
83727458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
83827458df8SWei Liu 
83927458df8SWei Liu     env->eip += decode->len;
84027458df8SWei Liu }
84127458df8SWei Liu 
84227458df8SWei Liu void exec_ror(CPUX86State *env, struct x86_decode *decode)
84327458df8SWei Liu {
84427458df8SWei Liu     uint8_t count;
84527458df8SWei Liu 
84627458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
84727458df8SWei Liu     count = decode->op[1].val;
84827458df8SWei Liu 
84927458df8SWei Liu     switch (decode->operand_size) {
85027458df8SWei Liu     case 1:
85127458df8SWei Liu     {
85227458df8SWei Liu         uint32_t bit6, bit7;
85327458df8SWei Liu         uint8_t res;
85427458df8SWei Liu 
85527458df8SWei Liu         if ((count & 0x07) == 0) {
85627458df8SWei Liu             if (count & 0x18) {
85727458df8SWei Liu                 bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
85827458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
85927458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
86027458df8SWei Liu              }
86127458df8SWei Liu         } else {
86227458df8SWei Liu             count &= 0x7; /* use only bottom 3 bits */
86327458df8SWei Liu             res = ((uint8_t)decode->op[0].val >> count) |
86427458df8SWei Liu                    ((uint8_t)decode->op[0].val << (8 - count));
86527458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 1);
86627458df8SWei Liu             bit6 = (res >> 6) & 1;
86727458df8SWei Liu             bit7 = (res >> 7) & 1;
86827458df8SWei Liu             /* set eflags: ROR count affects the following flags: C, O */
86927458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
87027458df8SWei Liu         }
87127458df8SWei Liu         break;
87227458df8SWei Liu     }
87327458df8SWei Liu     case 2:
87427458df8SWei Liu     {
87527458df8SWei Liu         uint32_t bit14, bit15;
87627458df8SWei Liu         uint16_t res;
87727458df8SWei Liu 
87827458df8SWei Liu         if ((count & 0x0f) == 0) {
87927458df8SWei Liu             if (count & 0x10) {
88027458df8SWei Liu                 bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
88127458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
88227458df8SWei Liu                 /* of = result14 ^ result15 */
88327458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
88427458df8SWei Liu             }
88527458df8SWei Liu         } else {
88627458df8SWei Liu             count &= 0x0f;  /* use only 4 LSB's */
88727458df8SWei Liu             res = ((uint16_t)decode->op[0].val >> count) |
88827458df8SWei Liu                    ((uint16_t)decode->op[0].val << (16 - count));
88927458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 2);
89027458df8SWei Liu 
89127458df8SWei Liu             bit14 = (res >> 14) & 1;
89227458df8SWei Liu             bit15 = (res >> 15) & 1;
89327458df8SWei Liu             /* of = result14 ^ result15 */
89427458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
89527458df8SWei Liu         }
89627458df8SWei Liu         break;
89727458df8SWei Liu     }
89827458df8SWei Liu     case 4:
89927458df8SWei Liu     {
90027458df8SWei Liu         uint32_t bit31, bit30;
90127458df8SWei Liu         uint32_t res;
90227458df8SWei Liu 
90327458df8SWei Liu         count &= 0x1f;
90427458df8SWei Liu         if (count) {
90527458df8SWei Liu             res = ((uint32_t)decode->op[0].val >> count) |
90627458df8SWei Liu                    ((uint32_t)decode->op[0].val << (32 - count));
90727458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 4);
90827458df8SWei Liu 
90927458df8SWei Liu             bit31 = (res >> 31) & 1;
91027458df8SWei Liu             bit30 = (res >> 30) & 1;
91127458df8SWei Liu             /* of = result30 ^ result31 */
91227458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
91327458df8SWei Liu         }
91427458df8SWei Liu         break;
91527458df8SWei Liu         }
91627458df8SWei Liu     }
91727458df8SWei Liu     env->eip += decode->len;
91827458df8SWei Liu }
91927458df8SWei Liu 
92027458df8SWei Liu void exec_rol(CPUX86State *env, struct x86_decode *decode)
92127458df8SWei Liu {
92227458df8SWei Liu     uint8_t count;
92327458df8SWei Liu 
92427458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
92527458df8SWei Liu     count = decode->op[1].val;
92627458df8SWei Liu 
92727458df8SWei Liu     switch (decode->operand_size) {
92827458df8SWei Liu     case 1:
92927458df8SWei Liu     {
93027458df8SWei Liu         uint32_t bit0, bit7;
93127458df8SWei Liu         uint8_t res;
93227458df8SWei Liu 
93327458df8SWei Liu         if ((count & 0x07) == 0) {
93427458df8SWei Liu             if (count & 0x18) {
93527458df8SWei Liu                 bit0 = ((uint8_t)decode->op[0].val & 1);
93627458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7);
93727458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
93827458df8SWei Liu             }
93927458df8SWei Liu         }  else {
94027458df8SWei Liu             count &= 0x7; /* use only lowest 3 bits */
94127458df8SWei Liu             res = ((uint8_t)decode->op[0].val << count) |
94227458df8SWei Liu                    ((uint8_t)decode->op[0].val >> (8 - count));
94327458df8SWei Liu 
94427458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 1);
94527458df8SWei Liu             /* set eflags:
94627458df8SWei Liu              * ROL count affects the following flags: C, O
94727458df8SWei Liu              */
94827458df8SWei Liu             bit0 = (res &  1);
94927458df8SWei Liu             bit7 = (res >> 7);
95027458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
95127458df8SWei Liu         }
95227458df8SWei Liu         break;
95327458df8SWei Liu     }
95427458df8SWei Liu     case 2:
95527458df8SWei Liu     {
95627458df8SWei Liu         uint32_t bit0, bit15;
95727458df8SWei Liu         uint16_t res;
95827458df8SWei Liu 
95927458df8SWei Liu         if ((count & 0x0f) == 0) {
96027458df8SWei Liu             if (count & 0x10) {
96127458df8SWei Liu                 bit0  = ((uint16_t)decode->op[0].val & 0x1);
96227458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15);
96327458df8SWei Liu                 /* of = cf ^ result15 */
96427458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
96527458df8SWei Liu             }
96627458df8SWei Liu         } else {
96727458df8SWei Liu             count &= 0x0f; /* only use bottom 4 bits */
96827458df8SWei Liu             res = ((uint16_t)decode->op[0].val << count) |
96927458df8SWei Liu                    ((uint16_t)decode->op[0].val >> (16 - count));
97027458df8SWei Liu 
97127458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 2);
97227458df8SWei Liu             bit0  = (res & 0x1);
97327458df8SWei Liu             bit15 = (res >> 15);
97427458df8SWei Liu             /* of = cf ^ result15 */
97527458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
97627458df8SWei Liu         }
97727458df8SWei Liu         break;
97827458df8SWei Liu     }
97927458df8SWei Liu     case 4:
98027458df8SWei Liu     {
98127458df8SWei Liu         uint32_t bit0, bit31;
98227458df8SWei Liu         uint32_t res;
98327458df8SWei Liu 
98427458df8SWei Liu         count &= 0x1f;
98527458df8SWei Liu         if (count) {
98627458df8SWei Liu             res = ((uint32_t)decode->op[0].val << count) |
98727458df8SWei Liu                    ((uint32_t)decode->op[0].val >> (32 - count));
98827458df8SWei Liu 
98927458df8SWei Liu             write_val_ext(env, decode->op[0].ptr, res, 4);
99027458df8SWei Liu             bit0  = (res & 0x1);
99127458df8SWei Liu             bit31 = (res >> 31);
99227458df8SWei Liu             /* of = cf ^ result31 */
99327458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
99427458df8SWei Liu         }
99527458df8SWei Liu         break;
99627458df8SWei Liu         }
99727458df8SWei Liu     }
99827458df8SWei Liu     env->eip += decode->len;
99927458df8SWei Liu }
100027458df8SWei Liu 
100127458df8SWei Liu 
100227458df8SWei Liu void exec_rcl(CPUX86State *env, struct x86_decode *decode)
100327458df8SWei Liu {
100427458df8SWei Liu     uint8_t count;
100527458df8SWei Liu     int of = 0, cf = 0;
100627458df8SWei Liu 
100727458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
100827458df8SWei Liu     count = decode->op[1].val & 0x1f;
100927458df8SWei Liu 
101027458df8SWei Liu     switch (decode->operand_size) {
101127458df8SWei Liu     case 1:
101227458df8SWei Liu     {
101327458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
101427458df8SWei Liu         uint8_t res;
101527458df8SWei Liu         count %= 9;
101627458df8SWei Liu         if (!count) {
101727458df8SWei Liu             break;
101827458df8SWei Liu         }
101927458df8SWei Liu 
102027458df8SWei Liu         if (1 == count) {
102127458df8SWei Liu             res = (op1_8 << 1) | get_CF(env);
102227458df8SWei Liu         } else {
102327458df8SWei Liu             res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
102427458df8SWei Liu                    (op1_8 >> (9 - count));
102527458df8SWei Liu         }
102627458df8SWei Liu 
102727458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
102827458df8SWei Liu 
102927458df8SWei Liu         cf = (op1_8 >> (8 - count)) & 0x01;
103027458df8SWei Liu         of = cf ^ (res >> 7); /* of = cf ^ result7 */
103127458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
103227458df8SWei Liu         break;
103327458df8SWei Liu     }
103427458df8SWei Liu     case 2:
103527458df8SWei Liu     {
103627458df8SWei Liu         uint16_t res;
103727458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
103827458df8SWei Liu 
103927458df8SWei Liu         count %= 17;
104027458df8SWei Liu         if (!count) {
104127458df8SWei Liu             break;
104227458df8SWei Liu         }
104327458df8SWei Liu 
104427458df8SWei Liu         if (1 == count) {
104527458df8SWei Liu             res = (op1_16 << 1) | get_CF(env);
104627458df8SWei Liu         } else if (count == 16) {
104727458df8SWei Liu             res = (get_CF(env) << 15) | (op1_16 >> 1);
104827458df8SWei Liu         } else { /* 2..15 */
104927458df8SWei Liu             res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
105027458df8SWei Liu                    (op1_16 >> (17 - count));
105127458df8SWei Liu         }
105227458df8SWei Liu 
105327458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
105427458df8SWei Liu 
105527458df8SWei Liu         cf = (op1_16 >> (16 - count)) & 0x1;
105627458df8SWei Liu         of = cf ^ (res >> 15); /* of = cf ^ result15 */
105727458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
105827458df8SWei Liu         break;
105927458df8SWei Liu     }
106027458df8SWei Liu     case 4:
106127458df8SWei Liu     {
106227458df8SWei Liu         uint32_t res;
106327458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
106427458df8SWei Liu 
106527458df8SWei Liu         if (!count) {
106627458df8SWei Liu             break;
106727458df8SWei Liu         }
106827458df8SWei Liu 
106927458df8SWei Liu         if (1 == count) {
107027458df8SWei Liu             res = (op1_32 << 1) | get_CF(env);
107127458df8SWei Liu         } else {
107227458df8SWei Liu             res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
107327458df8SWei Liu                    (op1_32 >> (33 - count));
107427458df8SWei Liu         }
107527458df8SWei Liu 
107627458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
107727458df8SWei Liu 
107827458df8SWei Liu         cf = (op1_32 >> (32 - count)) & 0x1;
107927458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
108027458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
108127458df8SWei Liu         break;
108227458df8SWei Liu         }
108327458df8SWei Liu     }
108427458df8SWei Liu     env->eip += decode->len;
108527458df8SWei Liu }
108627458df8SWei Liu 
108727458df8SWei Liu void exec_rcr(CPUX86State *env, struct x86_decode *decode)
108827458df8SWei Liu {
108927458df8SWei Liu     uint8_t count;
109027458df8SWei Liu     int of = 0, cf = 0;
109127458df8SWei Liu 
109227458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
109327458df8SWei Liu     count = decode->op[1].val & 0x1f;
109427458df8SWei Liu 
109527458df8SWei Liu     switch (decode->operand_size) {
109627458df8SWei Liu     case 1:
109727458df8SWei Liu     {
109827458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
109927458df8SWei Liu         uint8_t res;
110027458df8SWei Liu 
110127458df8SWei Liu         count %= 9;
110227458df8SWei Liu         if (!count) {
110327458df8SWei Liu             break;
110427458df8SWei Liu         }
110527458df8SWei Liu         res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
110627458df8SWei Liu                (op1_8 << (9 - count));
110727458df8SWei Liu 
110827458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 1);
110927458df8SWei Liu 
111027458df8SWei Liu         cf = (op1_8 >> (count - 1)) & 0x1;
111127458df8SWei Liu         of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
111227458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
111327458df8SWei Liu         break;
111427458df8SWei Liu     }
111527458df8SWei Liu     case 2:
111627458df8SWei Liu     {
111727458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
111827458df8SWei Liu         uint16_t res;
111927458df8SWei Liu 
112027458df8SWei Liu         count %= 17;
112127458df8SWei Liu         if (!count) {
112227458df8SWei Liu             break;
112327458df8SWei Liu         }
112427458df8SWei Liu         res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
112527458df8SWei Liu                (op1_16 << (17 - count));
112627458df8SWei Liu 
112727458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 2);
112827458df8SWei Liu 
112927458df8SWei Liu         cf = (op1_16 >> (count - 1)) & 0x1;
113027458df8SWei Liu         of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
113127458df8SWei Liu                                                             result14 */
113227458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
113327458df8SWei Liu         break;
113427458df8SWei Liu     }
113527458df8SWei Liu     case 4:
113627458df8SWei Liu     {
113727458df8SWei Liu         uint32_t res;
113827458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
113927458df8SWei Liu 
114027458df8SWei Liu         if (!count) {
114127458df8SWei Liu             break;
114227458df8SWei Liu         }
114327458df8SWei Liu 
114427458df8SWei Liu         if (1 == count) {
114527458df8SWei Liu             res = (op1_32 >> 1) | (get_CF(env) << 31);
114627458df8SWei Liu         } else {
114727458df8SWei Liu             res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
114827458df8SWei Liu                    (op1_32 << (33 - count));
114927458df8SWei Liu         }
115027458df8SWei Liu 
115127458df8SWei Liu         write_val_ext(env, decode->op[0].ptr, res, 4);
115227458df8SWei Liu 
115327458df8SWei Liu         cf = (op1_32 >> (count - 1)) & 0x1;
115427458df8SWei Liu         of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
115527458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
115627458df8SWei Liu         break;
115727458df8SWei Liu         }
115827458df8SWei Liu     }
115927458df8SWei Liu     env->eip += decode->len;
116027458df8SWei Liu }
116127458df8SWei Liu 
116227458df8SWei Liu static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
116327458df8SWei Liu {
116427458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
116527458df8SWei Liu 
116627458df8SWei Liu     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
116727458df8SWei Liu                   decode->operand_size);
116827458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
116927458df8SWei Liu                   decode->operand_size);
117027458df8SWei Liu 
117127458df8SWei Liu     env->eip += decode->len;
117227458df8SWei Liu }
117327458df8SWei Liu 
117427458df8SWei Liu static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
117527458df8SWei Liu {
117627458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
117727458df8SWei Liu     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
117827458df8SWei Liu                   decode->operand_size);
117927458df8SWei Liu 
118027458df8SWei Liu     env->eip += decode->len;
118127458df8SWei Liu }
118227458df8SWei Liu 
118327458df8SWei Liu static struct cmd_handler {
118427458df8SWei Liu     enum x86_decode_cmd cmd;
118527458df8SWei Liu     void (*handler)(CPUX86State *env, struct x86_decode *ins);
118627458df8SWei Liu } handlers[] = {
118727458df8SWei Liu     {X86_DECODE_CMD_INVL, NULL,},
118827458df8SWei Liu     {X86_DECODE_CMD_MOV, exec_mov},
118927458df8SWei Liu     {X86_DECODE_CMD_ADD, exec_add},
119027458df8SWei Liu     {X86_DECODE_CMD_OR, exec_or},
119127458df8SWei Liu     {X86_DECODE_CMD_ADC, exec_adc},
119227458df8SWei Liu     {X86_DECODE_CMD_SBB, exec_sbb},
119327458df8SWei Liu     {X86_DECODE_CMD_AND, exec_and},
119427458df8SWei Liu     {X86_DECODE_CMD_SUB, exec_sub},
119527458df8SWei Liu     {X86_DECODE_CMD_NEG, exec_neg},
119627458df8SWei Liu     {X86_DECODE_CMD_XOR, exec_xor},
119727458df8SWei Liu     {X86_DECODE_CMD_CMP, exec_cmp},
119827458df8SWei Liu     {X86_DECODE_CMD_INC, exec_inc},
119927458df8SWei Liu     {X86_DECODE_CMD_DEC, exec_dec},
120027458df8SWei Liu     {X86_DECODE_CMD_TST, exec_tst},
120127458df8SWei Liu     {X86_DECODE_CMD_NOT, exec_not},
120227458df8SWei Liu     {X86_DECODE_CMD_MOVZX, exec_movzx},
120327458df8SWei Liu     {X86_DECODE_CMD_OUT, exec_out},
120427458df8SWei Liu     {X86_DECODE_CMD_IN, exec_in},
120527458df8SWei Liu     {X86_DECODE_CMD_INS, exec_ins},
120627458df8SWei Liu     {X86_DECODE_CMD_OUTS, exec_outs},
120727458df8SWei Liu     {X86_DECODE_CMD_RDMSR, exec_rdmsr},
120827458df8SWei Liu     {X86_DECODE_CMD_WRMSR, exec_wrmsr},
120927458df8SWei Liu     {X86_DECODE_CMD_BT, exec_bt},
121027458df8SWei Liu     {X86_DECODE_CMD_BTR, exec_btr},
121127458df8SWei Liu     {X86_DECODE_CMD_BTC, exec_btc},
121227458df8SWei Liu     {X86_DECODE_CMD_BTS, exec_bts},
121327458df8SWei Liu     {X86_DECODE_CMD_SHL, exec_shl},
121427458df8SWei Liu     {X86_DECODE_CMD_ROL, exec_rol},
121527458df8SWei Liu     {X86_DECODE_CMD_ROR, exec_ror},
121627458df8SWei Liu     {X86_DECODE_CMD_RCR, exec_rcr},
121727458df8SWei Liu     {X86_DECODE_CMD_RCL, exec_rcl},
121827458df8SWei Liu     /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
121927458df8SWei Liu     {X86_DECODE_CMD_MOVS, exec_movs},
122027458df8SWei Liu     {X86_DECODE_CMD_CMPS, exec_cmps},
122127458df8SWei Liu     {X86_DECODE_CMD_STOS, exec_stos},
122227458df8SWei Liu     {X86_DECODE_CMD_SCAS, exec_scas},
122327458df8SWei Liu     {X86_DECODE_CMD_LODS, exec_lods},
122427458df8SWei Liu     {X86_DECODE_CMD_MOVSX, exec_movsx},
122527458df8SWei Liu     {X86_DECODE_CMD_XCHG, exec_xchg},
122627458df8SWei Liu     {X86_DECODE_CMD_XADD, exec_xadd},
122727458df8SWei Liu };
122827458df8SWei Liu 
122927458df8SWei Liu static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
123027458df8SWei Liu 
123127458df8SWei Liu const struct x86_emul_ops *emul_ops;
123227458df8SWei Liu 
123327458df8SWei Liu static void init_cmd_handler(void)
123427458df8SWei Liu {
123527458df8SWei Liu     int i;
123627458df8SWei Liu     for (i = 0; i < ARRAY_SIZE(handlers); i++) {
123727458df8SWei Liu         _cmd_handler[handlers[i].cmd] = handlers[i];
123827458df8SWei Liu     }
123927458df8SWei Liu }
124027458df8SWei Liu 
124127458df8SWei Liu bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
124227458df8SWei Liu {
124327458df8SWei Liu     if (!_cmd_handler[ins->cmd].handler) {
1244*7abf0d95SPaolo Bonzini         printf("Unimplemented handler (" TARGET_FMT_lx ") for %d (%x %x) \n", env->eip,
124527458df8SWei Liu                 ins->cmd, ins->opcode[0],
124627458df8SWei Liu                 ins->opcode_len > 1 ? ins->opcode[1] : 0);
124727458df8SWei Liu         env->eip += ins->len;
124827458df8SWei Liu         return true;
124927458df8SWei Liu     }
125027458df8SWei Liu 
125127458df8SWei Liu     _cmd_handler[ins->cmd].handler(env, ins);
125227458df8SWei Liu     return true;
125327458df8SWei Liu }
125427458df8SWei Liu 
125527458df8SWei Liu void init_emu(const struct x86_emul_ops *o)
125627458df8SWei Liu {
125727458df8SWei Liu     emul_ops = o;
125827458df8SWei Liu     init_cmd_handler();
125927458df8SWei Liu }
1260