xref: /openbmc/qemu/target/i386/emulate/x86_emu.c (revision 1721fe75df1cbabf2665a2b76a6e7b5bc0fc036b)
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
34*fd68168eSSean Wei //  License along with this library; if not, see
35*fd68168eSSean Wei //  <https://www.gnu.org/licenses/>.
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) {                              \
5577a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], 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) {                              \
6677a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], 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) {                              \
7777a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], 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 
read_reg(CPUX86State * env,int reg,int size)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 
write_reg(CPUX86State * env,int reg,target_ulong val,int size)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 
read_val_from_reg(void * reg_ptr,int size)12477a2dba4SPaolo Bonzini target_ulong read_val_from_reg(void *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 
write_val_to_reg(void * reg_ptr,target_ulong val,int size)14777a2dba4SPaolo Bonzini void write_val_to_reg(void *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 
write_val_to_mem(CPUX86State * env,target_ulong ptr,target_ulong val,int size)16777a2dba4SPaolo Bonzini static void write_val_to_mem(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
16827458df8SWei Liu {
16977a2dba4SPaolo Bonzini     emul_ops->write_mem(env_cpu(env), &val, ptr, size);
17027458df8SWei Liu }
17127458df8SWei Liu 
write_val_ext(CPUX86State * env,struct x86_decode_op * decode,target_ulong val,int size)17277a2dba4SPaolo Bonzini void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size)
17327458df8SWei Liu {
17477a2dba4SPaolo Bonzini     if (decode->type == X86_VAR_REG) {
17577a2dba4SPaolo Bonzini         write_val_to_reg(decode->regptr, val, size);
17677a2dba4SPaolo Bonzini     } else {
17777a2dba4SPaolo Bonzini         write_val_to_mem(env, decode->addr, val, size);
17827458df8SWei Liu     }
17927458df8SWei Liu }
18027458df8SWei Liu 
read_mmio(CPUX86State * env,target_ulong ptr,int bytes)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 
read_val_from_mem(CPUX86State * env,target_long ptr,int size)18877a2dba4SPaolo Bonzini static target_ulong read_val_from_mem(CPUX86State *env, target_long ptr, int size)
18927458df8SWei Liu {
19027458df8SWei Liu     target_ulong val;
19127458df8SWei Liu     uint8_t *mmio_ptr;
19227458df8SWei Liu 
19327458df8SWei Liu     mmio_ptr = read_mmio(env, ptr, size);
19427458df8SWei Liu     switch (size) {
19527458df8SWei Liu     case 1:
19627458df8SWei Liu         val = *(uint8_t *)mmio_ptr;
19727458df8SWei Liu         break;
19827458df8SWei Liu     case 2:
19927458df8SWei Liu         val = *(uint16_t *)mmio_ptr;
20027458df8SWei Liu         break;
20127458df8SWei Liu     case 4:
20227458df8SWei Liu         val = *(uint32_t *)mmio_ptr;
20327458df8SWei Liu         break;
20427458df8SWei Liu     case 8:
20527458df8SWei Liu         val = *(uint64_t *)mmio_ptr;
20627458df8SWei Liu         break;
20727458df8SWei Liu     default:
20827458df8SWei Liu         VM_PANIC("bad size\n");
20927458df8SWei Liu         break;
21027458df8SWei Liu     }
21127458df8SWei Liu     return val;
21227458df8SWei Liu }
21327458df8SWei Liu 
read_val_ext(CPUX86State * env,struct x86_decode_op * decode,int size)21477a2dba4SPaolo Bonzini target_ulong read_val_ext(CPUX86State *env, struct x86_decode_op *decode, int size)
21577a2dba4SPaolo Bonzini {
21677a2dba4SPaolo Bonzini     if (decode->type == X86_VAR_REG) {
21777a2dba4SPaolo Bonzini         return read_val_from_reg(decode->regptr, size);
21877a2dba4SPaolo Bonzini     } else {
21977a2dba4SPaolo Bonzini         return read_val_from_mem(env, decode->addr, size);
22077a2dba4SPaolo Bonzini     }
22177a2dba4SPaolo Bonzini }
22277a2dba4SPaolo Bonzini 
fetch_operands(CPUX86State * env,struct x86_decode * decode,int n,bool val_op0,bool val_op1,bool val_op2)22327458df8SWei Liu static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
22427458df8SWei Liu                            int n, bool val_op0, bool val_op1, bool val_op2)
22527458df8SWei Liu {
22627458df8SWei Liu     int i;
22727458df8SWei Liu     bool calc_val[3] = {val_op0, val_op1, val_op2};
22827458df8SWei Liu 
22927458df8SWei Liu     for (i = 0; i < n; i++) {
23027458df8SWei Liu         switch (decode->op[i].type) {
23127458df8SWei Liu         case X86_VAR_IMMEDIATE:
23227458df8SWei Liu             break;
23327458df8SWei Liu         case X86_VAR_REG:
23477a2dba4SPaolo Bonzini             VM_PANIC_ON(!decode->op[i].regptr);
23527458df8SWei Liu             if (calc_val[i]) {
23677a2dba4SPaolo Bonzini                 decode->op[i].val = read_val_from_reg(decode->op[i].regptr,
23727458df8SWei Liu                                                       decode->operand_size);
23827458df8SWei Liu             }
23927458df8SWei Liu             break;
24027458df8SWei Liu         case X86_VAR_RM:
24127458df8SWei Liu             calc_modrm_operand(env, decode, &decode->op[i]);
24227458df8SWei Liu             if (calc_val[i]) {
24377a2dba4SPaolo Bonzini                 decode->op[i].val = read_val_ext(env, &decode->op[i],
24427458df8SWei Liu                                                  decode->operand_size);
24527458df8SWei Liu             }
24627458df8SWei Liu             break;
24727458df8SWei Liu         case X86_VAR_OFFSET:
24877a2dba4SPaolo Bonzini             decode->op[i].addr = decode_linear_addr(env, decode,
24977a2dba4SPaolo Bonzini                                                     decode->op[i].addr,
25027458df8SWei Liu                                                     R_DS);
25127458df8SWei Liu             if (calc_val[i]) {
25277a2dba4SPaolo Bonzini                 decode->op[i].val = read_val_ext(env, &decode->op[i],
25327458df8SWei Liu                                                  decode->operand_size);
25427458df8SWei Liu             }
25527458df8SWei Liu             break;
25627458df8SWei Liu         default:
25727458df8SWei Liu             break;
25827458df8SWei Liu         }
25927458df8SWei Liu     }
26027458df8SWei Liu }
26127458df8SWei Liu 
exec_mov(CPUX86State * env,struct x86_decode * decode)26227458df8SWei Liu static void exec_mov(CPUX86State *env, struct x86_decode *decode)
26327458df8SWei Liu {
26427458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
26577a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], decode->op[1].val,
26627458df8SWei Liu                   decode->operand_size);
26727458df8SWei Liu 
26827458df8SWei Liu     env->eip += decode->len;
26927458df8SWei Liu }
27027458df8SWei Liu 
exec_add(CPUX86State * env,struct x86_decode * decode)27127458df8SWei Liu static void exec_add(CPUX86State *env, struct x86_decode *decode)
27227458df8SWei Liu {
27327458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
27427458df8SWei Liu     env->eip += decode->len;
27527458df8SWei Liu }
27627458df8SWei Liu 
exec_or(CPUX86State * env,struct x86_decode * decode)27727458df8SWei Liu static void exec_or(CPUX86State *env, struct x86_decode *decode)
27827458df8SWei Liu {
27927458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
28027458df8SWei Liu     env->eip += decode->len;
28127458df8SWei Liu }
28227458df8SWei Liu 
exec_adc(CPUX86State * env,struct x86_decode * decode)28327458df8SWei Liu static void exec_adc(CPUX86State *env, struct x86_decode *decode)
28427458df8SWei Liu {
28527458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
28627458df8SWei Liu     env->eip += decode->len;
28727458df8SWei Liu }
28827458df8SWei Liu 
exec_sbb(CPUX86State * env,struct x86_decode * decode)28927458df8SWei Liu static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
29027458df8SWei Liu {
29127458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
29227458df8SWei Liu     env->eip += decode->len;
29327458df8SWei Liu }
29427458df8SWei Liu 
exec_and(CPUX86State * env,struct x86_decode * decode)29527458df8SWei Liu static void exec_and(CPUX86State *env, struct x86_decode *decode)
29627458df8SWei Liu {
29727458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
29827458df8SWei Liu     env->eip += decode->len;
29927458df8SWei Liu }
30027458df8SWei Liu 
exec_sub(CPUX86State * env,struct x86_decode * decode)30127458df8SWei Liu static void exec_sub(CPUX86State *env, struct x86_decode *decode)
30227458df8SWei Liu {
30327458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
30427458df8SWei Liu     env->eip += decode->len;
30527458df8SWei Liu }
30627458df8SWei Liu 
exec_xor(CPUX86State * env,struct x86_decode * decode)30727458df8SWei Liu static void exec_xor(CPUX86State *env, struct x86_decode *decode)
30827458df8SWei Liu {
30927458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
31027458df8SWei Liu     env->eip += decode->len;
31127458df8SWei Liu }
31227458df8SWei Liu 
exec_neg(CPUX86State * env,struct x86_decode * decode)31327458df8SWei Liu static void exec_neg(CPUX86State *env, struct x86_decode *decode)
31427458df8SWei Liu {
31527458df8SWei Liu     /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
31627458df8SWei Liu     int32_t val;
31727458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
31827458df8SWei Liu 
31927458df8SWei Liu     val = 0 - sign(decode->op[1].val, decode->operand_size);
32077a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[1], val, decode->operand_size);
32127458df8SWei Liu 
32227458df8SWei Liu     if (4 == decode->operand_size) {
32327458df8SWei Liu         SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
32427458df8SWei Liu     } else if (2 == decode->operand_size) {
32527458df8SWei Liu         SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
32627458df8SWei Liu     } else if (1 == decode->operand_size) {
32727458df8SWei Liu         SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
32827458df8SWei Liu     } else {
32927458df8SWei Liu         VM_PANIC("bad op size\n");
33027458df8SWei Liu     }
33127458df8SWei Liu 
33227458df8SWei Liu     /*lflags_to_rflags(env);*/
33327458df8SWei Liu     env->eip += decode->len;
33427458df8SWei Liu }
33527458df8SWei Liu 
exec_cmp(CPUX86State * env,struct x86_decode * decode)33627458df8SWei Liu static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
33727458df8SWei Liu {
33827458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
33927458df8SWei Liu     env->eip += decode->len;
34027458df8SWei Liu }
34127458df8SWei Liu 
exec_inc(CPUX86State * env,struct x86_decode * decode)34227458df8SWei Liu static void exec_inc(CPUX86State *env, struct x86_decode *decode)
34327458df8SWei Liu {
34427458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
34527458df8SWei Liu     decode->op[1].val = 0;
34627458df8SWei Liu 
34727458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
34827458df8SWei Liu 
34927458df8SWei Liu     env->eip += decode->len;
35027458df8SWei Liu }
35127458df8SWei Liu 
exec_dec(CPUX86State * env,struct x86_decode * decode)35227458df8SWei Liu static void exec_dec(CPUX86State *env, struct x86_decode *decode)
35327458df8SWei Liu {
35427458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
35527458df8SWei Liu     decode->op[1].val = 0;
35627458df8SWei Liu 
35727458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
35827458df8SWei Liu     env->eip += decode->len;
35927458df8SWei Liu }
36027458df8SWei Liu 
exec_tst(CPUX86State * env,struct x86_decode * decode)36127458df8SWei Liu static void exec_tst(CPUX86State *env, struct x86_decode *decode)
36227458df8SWei Liu {
36327458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
36427458df8SWei Liu     env->eip += decode->len;
36527458df8SWei Liu }
36627458df8SWei Liu 
exec_not(CPUX86State * env,struct x86_decode * decode)36727458df8SWei Liu static void exec_not(CPUX86State *env, struct x86_decode *decode)
36827458df8SWei Liu {
36927458df8SWei Liu     fetch_operands(env, decode, 1, true, false, false);
37027458df8SWei Liu 
37177a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], ~decode->op[0].val,
37227458df8SWei Liu                   decode->operand_size);
37327458df8SWei Liu     env->eip += decode->len;
37427458df8SWei Liu }
37527458df8SWei Liu 
exec_movzx(CPUX86State * env,struct x86_decode * decode)37627458df8SWei Liu void exec_movzx(CPUX86State *env, struct x86_decode *decode)
37727458df8SWei Liu {
37827458df8SWei Liu     int src_op_size;
37927458df8SWei Liu     int op_size = decode->operand_size;
38027458df8SWei Liu 
38127458df8SWei Liu     fetch_operands(env, decode, 1, false, false, false);
38227458df8SWei Liu 
38327458df8SWei Liu     if (0xb6 == decode->opcode[1]) {
38427458df8SWei Liu         src_op_size = 1;
38527458df8SWei Liu     } else {
38627458df8SWei Liu         src_op_size = 2;
38727458df8SWei Liu     }
38827458df8SWei Liu     decode->operand_size = src_op_size;
38927458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
39077a2dba4SPaolo Bonzini     decode->op[1].val = read_val_ext(env, &decode->op[1], src_op_size);
39177a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], decode->op[1].val, op_size);
39227458df8SWei Liu 
39327458df8SWei Liu     env->eip += decode->len;
39427458df8SWei Liu }
39527458df8SWei Liu 
exec_out(CPUX86State * env,struct x86_decode * decode)39627458df8SWei Liu static void exec_out(CPUX86State *env, struct x86_decode *decode)
39727458df8SWei Liu {
39827458df8SWei Liu     switch (decode->opcode[0]) {
39927458df8SWei Liu     case 0xe6:
40027458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
40127458df8SWei Liu         break;
40227458df8SWei Liu     case 0xe7:
40327458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
40427458df8SWei Liu                             decode->operand_size, 1);
40527458df8SWei Liu         break;
40627458df8SWei Liu     case 0xee:
40727458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
40827458df8SWei Liu         break;
40927458df8SWei Liu     case 0xef:
41027458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
41127458df8SWei Liu                             decode->operand_size, 1);
41227458df8SWei Liu         break;
41327458df8SWei Liu     default:
41427458df8SWei Liu         VM_PANIC("Bad out opcode\n");
41527458df8SWei Liu         break;
41627458df8SWei Liu     }
41727458df8SWei Liu     env->eip += decode->len;
41827458df8SWei Liu }
41927458df8SWei Liu 
exec_in(CPUX86State * env,struct x86_decode * decode)42027458df8SWei Liu static void exec_in(CPUX86State *env, struct x86_decode *decode)
42127458df8SWei Liu {
42227458df8SWei Liu     target_ulong val = 0;
42327458df8SWei Liu     switch (decode->opcode[0]) {
42427458df8SWei Liu     case 0xe4:
42527458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
42627458df8SWei Liu         break;
42727458df8SWei Liu     case 0xe5:
42827458df8SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
42927458df8SWei Liu                       decode->operand_size, 1);
43027458df8SWei Liu         if (decode->operand_size == 2) {
43127458df8SWei Liu             AX(env) = val;
43227458df8SWei Liu         } else {
43327458df8SWei Liu             RAX(env) = (uint32_t)val;
43427458df8SWei Liu         }
43527458df8SWei Liu         break;
43627458df8SWei Liu     case 0xec:
43727458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
43827458df8SWei Liu         break;
43927458df8SWei Liu     case 0xed:
44027458df8SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
44127458df8SWei Liu                             decode->operand_size, 1);
44227458df8SWei Liu         if (decode->operand_size == 2) {
44327458df8SWei Liu             AX(env) = val;
44427458df8SWei Liu         } else {
44527458df8SWei Liu             RAX(env) = (uint32_t)val;
44627458df8SWei Liu         }
44727458df8SWei Liu 
44827458df8SWei Liu         break;
44927458df8SWei Liu     default:
45027458df8SWei Liu         VM_PANIC("Bad in opcode\n");
45127458df8SWei Liu         break;
45227458df8SWei Liu     }
45327458df8SWei Liu 
45427458df8SWei Liu     env->eip += decode->len;
45527458df8SWei Liu }
45627458df8SWei Liu 
string_increment_reg(CPUX86State * env,int reg,struct x86_decode * decode)45727458df8SWei Liu static inline void string_increment_reg(CPUX86State *env, int reg,
45827458df8SWei Liu                                         struct x86_decode *decode)
45927458df8SWei Liu {
46027458df8SWei Liu     target_ulong val = read_reg(env, reg, decode->addressing_size);
46127458df8SWei Liu     if (env->eflags & DF_MASK) {
46227458df8SWei Liu         val -= decode->operand_size;
46327458df8SWei Liu     } else {
46427458df8SWei Liu         val += decode->operand_size;
46527458df8SWei Liu     }
46627458df8SWei Liu     write_reg(env, reg, val, decode->addressing_size);
46727458df8SWei Liu }
46827458df8SWei Liu 
string_rep(CPUX86State * env,struct x86_decode * decode,void (* func)(CPUX86State * env,struct x86_decode * ins),int rep)46927458df8SWei Liu static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
47027458df8SWei Liu                               void (*func)(CPUX86State *env,
47127458df8SWei Liu                                            struct x86_decode *ins), int rep)
47227458df8SWei Liu {
47327458df8SWei Liu     target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
47427458df8SWei Liu     while (rcx--) {
47527458df8SWei Liu         func(env, decode);
47627458df8SWei Liu         write_reg(env, R_ECX, rcx, decode->addressing_size);
477d521fdc7SPaolo Bonzini         if ((PREFIX_REP == rep) && !env->cc_dst) {
47827458df8SWei Liu             break;
47927458df8SWei Liu         }
480d521fdc7SPaolo Bonzini         if ((PREFIX_REPN == rep) && env->cc_dst) {
48127458df8SWei Liu             break;
48227458df8SWei Liu         }
48327458df8SWei Liu     }
48427458df8SWei Liu }
48527458df8SWei Liu 
exec_ins_single(CPUX86State * env,struct x86_decode * decode)48627458df8SWei Liu static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
48727458df8SWei Liu {
48827458df8SWei Liu     target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
48927458df8SWei Liu                                          decode->addressing_size, R_ES);
49027458df8SWei Liu 
49127458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
49227458df8SWei Liu                         decode->operand_size, 1);
49327458df8SWei Liu     emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
49427458df8SWei Liu                         decode->operand_size);
49527458df8SWei Liu 
49627458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
49727458df8SWei Liu }
49827458df8SWei Liu 
exec_ins(CPUX86State * env,struct x86_decode * decode)49927458df8SWei Liu static void exec_ins(CPUX86State *env, struct x86_decode *decode)
50027458df8SWei Liu {
50127458df8SWei Liu     if (decode->rep) {
50227458df8SWei Liu         string_rep(env, decode, exec_ins_single, 0);
50327458df8SWei Liu     } else {
50427458df8SWei Liu         exec_ins_single(env, decode);
50527458df8SWei Liu     }
50627458df8SWei Liu 
50727458df8SWei Liu     env->eip += decode->len;
50827458df8SWei Liu }
50927458df8SWei Liu 
exec_outs_single(CPUX86State * env,struct x86_decode * decode)51027458df8SWei Liu static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
51127458df8SWei Liu {
51227458df8SWei Liu     target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
51327458df8SWei Liu 
51427458df8SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
51527458df8SWei Liu                        decode->operand_size);
51627458df8SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
51727458df8SWei Liu                         decode->operand_size, 1);
51827458df8SWei Liu 
51927458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
52027458df8SWei Liu }
52127458df8SWei Liu 
exec_outs(CPUX86State * env,struct x86_decode * decode)52227458df8SWei Liu static void exec_outs(CPUX86State *env, struct x86_decode *decode)
52327458df8SWei Liu {
52427458df8SWei Liu     if (decode->rep) {
52527458df8SWei Liu         string_rep(env, decode, exec_outs_single, 0);
52627458df8SWei Liu     } else {
52727458df8SWei Liu         exec_outs_single(env, decode);
52827458df8SWei Liu     }
52927458df8SWei Liu 
53027458df8SWei Liu     env->eip += decode->len;
53127458df8SWei Liu }
53227458df8SWei Liu 
exec_movs_single(CPUX86State * env,struct x86_decode * decode)53327458df8SWei Liu static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
53427458df8SWei Liu {
53527458df8SWei Liu     target_ulong src_addr;
53627458df8SWei Liu     target_ulong dst_addr;
53727458df8SWei Liu     target_ulong val;
53827458df8SWei Liu 
53927458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
54027458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
54127458df8SWei Liu                                 decode->addressing_size, R_ES);
54227458df8SWei Liu 
54377a2dba4SPaolo Bonzini     val = read_val_from_mem(env, src_addr, decode->operand_size);
54477a2dba4SPaolo Bonzini     write_val_to_mem(env, dst_addr, val, decode->operand_size);
54527458df8SWei Liu 
54627458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
54727458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
54827458df8SWei Liu }
54927458df8SWei Liu 
exec_movs(CPUX86State * env,struct x86_decode * decode)55027458df8SWei Liu static void exec_movs(CPUX86State *env, struct x86_decode *decode)
55127458df8SWei Liu {
55227458df8SWei Liu     if (decode->rep) {
55327458df8SWei Liu         string_rep(env, decode, exec_movs_single, 0);
55427458df8SWei Liu     } else {
55527458df8SWei Liu         exec_movs_single(env, decode);
55627458df8SWei Liu     }
55727458df8SWei Liu 
55827458df8SWei Liu     env->eip += decode->len;
55927458df8SWei Liu }
56027458df8SWei Liu 
exec_cmps_single(CPUX86State * env,struct x86_decode * decode)56127458df8SWei Liu static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
56227458df8SWei Liu {
56327458df8SWei Liu     target_ulong src_addr;
56427458df8SWei Liu     target_ulong dst_addr;
56527458df8SWei Liu 
56627458df8SWei Liu     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
56727458df8SWei Liu     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
56827458df8SWei Liu                                 decode->addressing_size, R_ES);
56927458df8SWei Liu 
57027458df8SWei Liu     decode->op[0].type = X86_VAR_IMMEDIATE;
57177a2dba4SPaolo Bonzini     decode->op[0].val = read_val_from_mem(env, src_addr, decode->operand_size);
57227458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
57377a2dba4SPaolo Bonzini     decode->op[1].val = read_val_from_mem(env, dst_addr, decode->operand_size);
57427458df8SWei Liu 
57527458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
57627458df8SWei Liu 
57727458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
57827458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
57927458df8SWei Liu }
58027458df8SWei Liu 
exec_cmps(CPUX86State * env,struct x86_decode * decode)58127458df8SWei Liu static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
58227458df8SWei Liu {
58327458df8SWei Liu     if (decode->rep) {
58427458df8SWei Liu         string_rep(env, decode, exec_cmps_single, decode->rep);
58527458df8SWei Liu     } else {
58627458df8SWei Liu         exec_cmps_single(env, decode);
58727458df8SWei Liu     }
58827458df8SWei Liu     env->eip += decode->len;
58927458df8SWei Liu }
59027458df8SWei Liu 
59127458df8SWei Liu 
exec_stos_single(CPUX86State * env,struct x86_decode * decode)59227458df8SWei Liu static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
59327458df8SWei Liu {
59427458df8SWei Liu     target_ulong addr;
59527458df8SWei Liu     target_ulong val;
59627458df8SWei Liu 
59727458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
59827458df8SWei Liu                             decode->addressing_size, R_ES);
59927458df8SWei Liu     val = read_reg(env, R_EAX, decode->operand_size);
60027458df8SWei Liu     emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
60127458df8SWei Liu 
60227458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
60327458df8SWei Liu }
60427458df8SWei Liu 
60527458df8SWei Liu 
exec_stos(CPUX86State * env,struct x86_decode * decode)60627458df8SWei Liu static void exec_stos(CPUX86State *env, struct x86_decode *decode)
60727458df8SWei Liu {
60827458df8SWei Liu     if (decode->rep) {
60927458df8SWei Liu         string_rep(env, decode, exec_stos_single, 0);
61027458df8SWei Liu     } else {
61127458df8SWei Liu         exec_stos_single(env, decode);
61227458df8SWei Liu     }
61327458df8SWei Liu 
61427458df8SWei Liu     env->eip += decode->len;
61527458df8SWei Liu }
61627458df8SWei Liu 
exec_scas_single(CPUX86State * env,struct x86_decode * decode)61727458df8SWei Liu static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
61827458df8SWei Liu {
61927458df8SWei Liu     target_ulong addr;
62027458df8SWei Liu 
62127458df8SWei Liu     addr = linear_addr_size(env_cpu(env), RDI(env),
62227458df8SWei Liu                             decode->addressing_size, R_ES);
62327458df8SWei Liu     decode->op[1].type = X86_VAR_IMMEDIATE;
62427458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
62527458df8SWei Liu 
62627458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
62727458df8SWei Liu     string_increment_reg(env, R_EDI, decode);
62827458df8SWei Liu }
62927458df8SWei Liu 
exec_scas(CPUX86State * env,struct x86_decode * decode)63027458df8SWei Liu static void exec_scas(CPUX86State *env, struct x86_decode *decode)
63127458df8SWei Liu {
63227458df8SWei Liu     decode->op[0].type = X86_VAR_REG;
63327458df8SWei Liu     decode->op[0].reg = R_EAX;
63427458df8SWei Liu     if (decode->rep) {
63527458df8SWei Liu         string_rep(env, decode, exec_scas_single, decode->rep);
63627458df8SWei Liu     } else {
63727458df8SWei Liu         exec_scas_single(env, decode);
63827458df8SWei Liu     }
63927458df8SWei Liu 
64027458df8SWei Liu     env->eip += decode->len;
64127458df8SWei Liu }
64227458df8SWei Liu 
exec_lods_single(CPUX86State * env,struct x86_decode * decode)64327458df8SWei Liu static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
64427458df8SWei Liu {
64527458df8SWei Liu     target_ulong addr;
64627458df8SWei Liu     target_ulong val = 0;
64727458df8SWei Liu 
64827458df8SWei Liu     addr = decode_linear_addr(env, decode, RSI(env), R_DS);
64927458df8SWei Liu     emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
65027458df8SWei Liu     write_reg(env, R_EAX, val, decode->operand_size);
65127458df8SWei Liu 
65227458df8SWei Liu     string_increment_reg(env, R_ESI, decode);
65327458df8SWei Liu }
65427458df8SWei Liu 
exec_lods(CPUX86State * env,struct x86_decode * decode)65527458df8SWei Liu static void exec_lods(CPUX86State *env, struct x86_decode *decode)
65627458df8SWei Liu {
65727458df8SWei Liu     if (decode->rep) {
65827458df8SWei Liu         string_rep(env, decode, exec_lods_single, 0);
65927458df8SWei Liu     } else {
66027458df8SWei Liu         exec_lods_single(env, decode);
66127458df8SWei Liu     }
66227458df8SWei Liu 
66327458df8SWei Liu     env->eip += decode->len;
66427458df8SWei Liu }
66527458df8SWei Liu 
x86_emul_raise_exception(CPUX86State * env,int exception_index,int error_code)66627458df8SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
66727458df8SWei Liu {
66827458df8SWei Liu     env->exception_nr = exception_index;
66927458df8SWei Liu     env->error_code = error_code;
67027458df8SWei Liu     env->has_error_code = true;
67127458df8SWei Liu     env->exception_injected = 1;
67227458df8SWei Liu }
67327458df8SWei Liu 
exec_rdmsr(CPUX86State * env,struct x86_decode * decode)67427458df8SWei Liu static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
67527458df8SWei Liu {
67627458df8SWei Liu     emul_ops->simulate_rdmsr(env_cpu(env));
67727458df8SWei Liu     env->eip += decode->len;
67827458df8SWei Liu }
67927458df8SWei Liu 
exec_wrmsr(CPUX86State * env,struct x86_decode * decode)68027458df8SWei Liu static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
68127458df8SWei Liu {
68227458df8SWei Liu     emul_ops->simulate_wrmsr(env_cpu(env));
68327458df8SWei Liu     env->eip += decode->len;
68427458df8SWei Liu }
68527458df8SWei Liu 
68627458df8SWei Liu /*
68727458df8SWei Liu  * flag:
68827458df8SWei Liu  * 0 - bt, 1 - btc, 2 - bts, 3 - btr
68927458df8SWei Liu  */
do_bt(CPUX86State * env,struct x86_decode * decode,int flag)69027458df8SWei Liu static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
69127458df8SWei Liu {
69227458df8SWei Liu     int32_t displacement;
69327458df8SWei Liu     uint8_t index;
69427458df8SWei Liu     bool cf;
69527458df8SWei Liu     int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
69627458df8SWei Liu 
69727458df8SWei Liu     VM_PANIC_ON(decode->rex.rex);
69827458df8SWei Liu 
69927458df8SWei Liu     fetch_operands(env, decode, 2, false, true, false);
70027458df8SWei Liu     index = decode->op[1].val & mask;
70127458df8SWei Liu 
70227458df8SWei Liu     if (decode->op[0].type != X86_VAR_REG) {
70327458df8SWei Liu         if (4 == decode->operand_size) {
70427458df8SWei Liu             displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
70577a2dba4SPaolo Bonzini             decode->op[0].addr += 4 * displacement;
70627458df8SWei Liu         } else if (2 == decode->operand_size) {
70727458df8SWei Liu             displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
70877a2dba4SPaolo Bonzini             decode->op[0].addr += 2 * displacement;
70927458df8SWei Liu         } else {
71027458df8SWei Liu             VM_PANIC("bt 64bit\n");
71127458df8SWei Liu         }
71227458df8SWei Liu     }
71377a2dba4SPaolo Bonzini     decode->op[0].val = read_val_ext(env, &decode->op[0],
71427458df8SWei Liu                                      decode->operand_size);
71527458df8SWei Liu     cf = (decode->op[0].val >> index) & 0x01;
71627458df8SWei Liu 
71727458df8SWei Liu     switch (flag) {
71827458df8SWei Liu     case 0:
71927458df8SWei Liu         set_CF(env, cf);
72027458df8SWei Liu         return;
72127458df8SWei Liu     case 1:
72227458df8SWei Liu         decode->op[0].val ^= (1u << index);
72327458df8SWei Liu         break;
72427458df8SWei Liu     case 2:
72527458df8SWei Liu         decode->op[0].val |= (1u << index);
72627458df8SWei Liu         break;
72727458df8SWei Liu     case 3:
72827458df8SWei Liu         decode->op[0].val &= ~(1u << index);
72927458df8SWei Liu         break;
73027458df8SWei Liu     }
73177a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], decode->op[0].val,
73227458df8SWei Liu                   decode->operand_size);
73327458df8SWei Liu     set_CF(env, cf);
73427458df8SWei Liu }
73527458df8SWei Liu 
exec_bt(CPUX86State * env,struct x86_decode * decode)73627458df8SWei Liu static void exec_bt(CPUX86State *env, struct x86_decode *decode)
73727458df8SWei Liu {
73827458df8SWei Liu     do_bt(env, decode, 0);
73927458df8SWei Liu     env->eip += decode->len;
74027458df8SWei Liu }
74127458df8SWei Liu 
exec_btc(CPUX86State * env,struct x86_decode * decode)74227458df8SWei Liu static void exec_btc(CPUX86State *env, struct x86_decode *decode)
74327458df8SWei Liu {
74427458df8SWei Liu     do_bt(env, decode, 1);
74527458df8SWei Liu     env->eip += decode->len;
74627458df8SWei Liu }
74727458df8SWei Liu 
exec_btr(CPUX86State * env,struct x86_decode * decode)74827458df8SWei Liu static void exec_btr(CPUX86State *env, struct x86_decode *decode)
74927458df8SWei Liu {
75027458df8SWei Liu     do_bt(env, decode, 3);
75127458df8SWei Liu     env->eip += decode->len;
75227458df8SWei Liu }
75327458df8SWei Liu 
exec_bts(CPUX86State * env,struct x86_decode * decode)75427458df8SWei Liu static void exec_bts(CPUX86State *env, struct x86_decode *decode)
75527458df8SWei Liu {
75627458df8SWei Liu     do_bt(env, decode, 2);
75727458df8SWei Liu     env->eip += decode->len;
75827458df8SWei Liu }
75927458df8SWei Liu 
exec_shl(CPUX86State * env,struct x86_decode * decode)76027458df8SWei Liu void exec_shl(CPUX86State *env, struct x86_decode *decode)
76127458df8SWei Liu {
76227458df8SWei Liu     uint8_t count;
76327458df8SWei Liu     int of = 0, cf = 0;
76427458df8SWei Liu 
76527458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
76627458df8SWei Liu 
76727458df8SWei Liu     count = decode->op[1].val;
76827458df8SWei Liu     count &= 0x1f;      /* count is masked to 5 bits*/
76927458df8SWei Liu     if (!count) {
77027458df8SWei Liu         goto exit;
77127458df8SWei Liu     }
77227458df8SWei Liu 
77327458df8SWei Liu     switch (decode->operand_size) {
77427458df8SWei Liu     case 1:
77527458df8SWei Liu     {
77627458df8SWei Liu         uint8_t res = 0;
77727458df8SWei Liu         if (count <= 8) {
77827458df8SWei Liu             res = (decode->op[0].val << count);
77927458df8SWei Liu             cf = (decode->op[0].val >> (8 - count)) & 0x1;
78027458df8SWei Liu             of = cf ^ (res >> 7);
78127458df8SWei Liu         }
78227458df8SWei Liu 
78377a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 1);
78427458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
78527458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
78627458df8SWei Liu         break;
78727458df8SWei Liu     }
78827458df8SWei Liu     case 2:
78927458df8SWei Liu     {
79027458df8SWei Liu         uint16_t res = 0;
79127458df8SWei Liu 
79227458df8SWei Liu         /* from bochs */
79327458df8SWei Liu         if (count <= 16) {
79427458df8SWei Liu             res = (decode->op[0].val << count);
79527458df8SWei Liu             cf = (decode->op[0].val >> (16 - count)) & 0x1;
79627458df8SWei Liu             of = cf ^ (res >> 15); /* of = cf ^ result15 */
79727458df8SWei Liu         }
79827458df8SWei Liu 
79977a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 2);
80027458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
80127458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
80227458df8SWei Liu         break;
80327458df8SWei Liu     }
80427458df8SWei Liu     case 4:
80527458df8SWei Liu     {
80627458df8SWei Liu         uint32_t res = decode->op[0].val << count;
80727458df8SWei Liu 
80877a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 4);
80927458df8SWei Liu         SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
81027458df8SWei Liu         cf = (decode->op[0].val >> (32 - count)) & 0x1;
81127458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
81227458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
81327458df8SWei Liu         break;
81427458df8SWei Liu     }
81527458df8SWei Liu     default:
81627458df8SWei Liu         abort();
81727458df8SWei Liu     }
81827458df8SWei Liu 
81927458df8SWei Liu exit:
82027458df8SWei Liu     /* lflags_to_rflags(env); */
82127458df8SWei Liu     env->eip += decode->len;
82227458df8SWei Liu }
82327458df8SWei Liu 
exec_movsx(CPUX86State * env,struct x86_decode * decode)82427458df8SWei Liu void exec_movsx(CPUX86State *env, struct x86_decode *decode)
82527458df8SWei Liu {
82627458df8SWei Liu     int src_op_size;
82727458df8SWei Liu     int op_size = decode->operand_size;
82827458df8SWei Liu 
82927458df8SWei Liu     fetch_operands(env, decode, 2, false, false, false);
83027458df8SWei Liu 
83127458df8SWei Liu     if (0xbe == decode->opcode[1]) {
83227458df8SWei Liu         src_op_size = 1;
83327458df8SWei Liu     } else {
83427458df8SWei Liu         src_op_size = 2;
83527458df8SWei Liu     }
83627458df8SWei Liu 
83727458df8SWei Liu     decode->operand_size = src_op_size;
83827458df8SWei Liu     calc_modrm_operand(env, decode, &decode->op[1]);
83977a2dba4SPaolo Bonzini     decode->op[1].val = sign(read_val_ext(env, &decode->op[1], src_op_size),
84027458df8SWei Liu                              src_op_size);
84127458df8SWei Liu 
84277a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], decode->op[1].val, op_size);
84327458df8SWei Liu 
84427458df8SWei Liu     env->eip += decode->len;
84527458df8SWei Liu }
84627458df8SWei Liu 
exec_ror(CPUX86State * env,struct x86_decode * decode)84727458df8SWei Liu void exec_ror(CPUX86State *env, struct x86_decode *decode)
84827458df8SWei Liu {
84927458df8SWei Liu     uint8_t count;
85027458df8SWei Liu 
85127458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
85227458df8SWei Liu     count = decode->op[1].val;
85327458df8SWei Liu 
85427458df8SWei Liu     switch (decode->operand_size) {
85527458df8SWei Liu     case 1:
85627458df8SWei Liu     {
85727458df8SWei Liu         uint32_t bit6, bit7;
85827458df8SWei Liu         uint8_t res;
85927458df8SWei Liu 
86027458df8SWei Liu         if ((count & 0x07) == 0) {
86127458df8SWei Liu             if (count & 0x18) {
86227458df8SWei Liu                 bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
86327458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
86427458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
86527458df8SWei Liu              }
86627458df8SWei Liu         } else {
86727458df8SWei Liu             count &= 0x7; /* use only bottom 3 bits */
86827458df8SWei Liu             res = ((uint8_t)decode->op[0].val >> count) |
86927458df8SWei Liu                    ((uint8_t)decode->op[0].val << (8 - count));
87077a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 1);
87127458df8SWei Liu             bit6 = (res >> 6) & 1;
87227458df8SWei Liu             bit7 = (res >> 7) & 1;
87327458df8SWei Liu             /* set eflags: ROR count affects the following flags: C, O */
87427458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
87527458df8SWei Liu         }
87627458df8SWei Liu         break;
87727458df8SWei Liu     }
87827458df8SWei Liu     case 2:
87927458df8SWei Liu     {
88027458df8SWei Liu         uint32_t bit14, bit15;
88127458df8SWei Liu         uint16_t res;
88227458df8SWei Liu 
88327458df8SWei Liu         if ((count & 0x0f) == 0) {
88427458df8SWei Liu             if (count & 0x10) {
88527458df8SWei Liu                 bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
88627458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
88727458df8SWei Liu                 /* of = result14 ^ result15 */
88827458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
88927458df8SWei Liu             }
89027458df8SWei Liu         } else {
89127458df8SWei Liu             count &= 0x0f;  /* use only 4 LSB's */
89227458df8SWei Liu             res = ((uint16_t)decode->op[0].val >> count) |
89327458df8SWei Liu                    ((uint16_t)decode->op[0].val << (16 - count));
89477a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 2);
89527458df8SWei Liu 
89627458df8SWei Liu             bit14 = (res >> 14) & 1;
89727458df8SWei Liu             bit15 = (res >> 15) & 1;
89827458df8SWei Liu             /* of = result14 ^ result15 */
89927458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
90027458df8SWei Liu         }
90127458df8SWei Liu         break;
90227458df8SWei Liu     }
90327458df8SWei Liu     case 4:
90427458df8SWei Liu     {
90527458df8SWei Liu         uint32_t bit31, bit30;
90627458df8SWei Liu         uint32_t res;
90727458df8SWei Liu 
90827458df8SWei Liu         count &= 0x1f;
90927458df8SWei Liu         if (count) {
91027458df8SWei Liu             res = ((uint32_t)decode->op[0].val >> count) |
91127458df8SWei Liu                    ((uint32_t)decode->op[0].val << (32 - count));
91277a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 4);
91327458df8SWei Liu 
91427458df8SWei Liu             bit31 = (res >> 31) & 1;
91527458df8SWei Liu             bit30 = (res >> 30) & 1;
91627458df8SWei Liu             /* of = result30 ^ result31 */
91727458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
91827458df8SWei Liu         }
91927458df8SWei Liu         break;
92027458df8SWei Liu         }
92127458df8SWei Liu     }
92227458df8SWei Liu     env->eip += decode->len;
92327458df8SWei Liu }
92427458df8SWei Liu 
exec_rol(CPUX86State * env,struct x86_decode * decode)92527458df8SWei Liu void exec_rol(CPUX86State *env, struct x86_decode *decode)
92627458df8SWei Liu {
92727458df8SWei Liu     uint8_t count;
92827458df8SWei Liu 
92927458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
93027458df8SWei Liu     count = decode->op[1].val;
93127458df8SWei Liu 
93227458df8SWei Liu     switch (decode->operand_size) {
93327458df8SWei Liu     case 1:
93427458df8SWei Liu     {
93527458df8SWei Liu         uint32_t bit0, bit7;
93627458df8SWei Liu         uint8_t res;
93727458df8SWei Liu 
93827458df8SWei Liu         if ((count & 0x07) == 0) {
93927458df8SWei Liu             if (count & 0x18) {
94027458df8SWei Liu                 bit0 = ((uint8_t)decode->op[0].val & 1);
94127458df8SWei Liu                 bit7 = ((uint8_t)decode->op[0].val >> 7);
94227458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
94327458df8SWei Liu             }
94427458df8SWei Liu         }  else {
94527458df8SWei Liu             count &= 0x7; /* use only lowest 3 bits */
94627458df8SWei Liu             res = ((uint8_t)decode->op[0].val << count) |
94727458df8SWei Liu                    ((uint8_t)decode->op[0].val >> (8 - count));
94827458df8SWei Liu 
94977a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 1);
95027458df8SWei Liu             /* set eflags:
95127458df8SWei Liu              * ROL count affects the following flags: C, O
95227458df8SWei Liu              */
95327458df8SWei Liu             bit0 = (res &  1);
95427458df8SWei Liu             bit7 = (res >> 7);
95527458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
95627458df8SWei Liu         }
95727458df8SWei Liu         break;
95827458df8SWei Liu     }
95927458df8SWei Liu     case 2:
96027458df8SWei Liu     {
96127458df8SWei Liu         uint32_t bit0, bit15;
96227458df8SWei Liu         uint16_t res;
96327458df8SWei Liu 
96427458df8SWei Liu         if ((count & 0x0f) == 0) {
96527458df8SWei Liu             if (count & 0x10) {
96627458df8SWei Liu                 bit0  = ((uint16_t)decode->op[0].val & 0x1);
96727458df8SWei Liu                 bit15 = ((uint16_t)decode->op[0].val >> 15);
96827458df8SWei Liu                 /* of = cf ^ result15 */
96927458df8SWei Liu                 SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
97027458df8SWei Liu             }
97127458df8SWei Liu         } else {
97227458df8SWei Liu             count &= 0x0f; /* only use bottom 4 bits */
97327458df8SWei Liu             res = ((uint16_t)decode->op[0].val << count) |
97427458df8SWei Liu                    ((uint16_t)decode->op[0].val >> (16 - count));
97527458df8SWei Liu 
97677a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 2);
97727458df8SWei Liu             bit0  = (res & 0x1);
97827458df8SWei Liu             bit15 = (res >> 15);
97927458df8SWei Liu             /* of = cf ^ result15 */
98027458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
98127458df8SWei Liu         }
98227458df8SWei Liu         break;
98327458df8SWei Liu     }
98427458df8SWei Liu     case 4:
98527458df8SWei Liu     {
98627458df8SWei Liu         uint32_t bit0, bit31;
98727458df8SWei Liu         uint32_t res;
98827458df8SWei Liu 
98927458df8SWei Liu         count &= 0x1f;
99027458df8SWei Liu         if (count) {
99127458df8SWei Liu             res = ((uint32_t)decode->op[0].val << count) |
99227458df8SWei Liu                    ((uint32_t)decode->op[0].val >> (32 - count));
99327458df8SWei Liu 
99477a2dba4SPaolo Bonzini             write_val_ext(env, &decode->op[0], res, 4);
99527458df8SWei Liu             bit0  = (res & 0x1);
99627458df8SWei Liu             bit31 = (res >> 31);
99727458df8SWei Liu             /* of = cf ^ result31 */
99827458df8SWei Liu             SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
99927458df8SWei Liu         }
100027458df8SWei Liu         break;
100127458df8SWei Liu         }
100227458df8SWei Liu     }
100327458df8SWei Liu     env->eip += decode->len;
100427458df8SWei Liu }
100527458df8SWei Liu 
100627458df8SWei Liu 
exec_rcl(CPUX86State * env,struct x86_decode * decode)100727458df8SWei Liu void exec_rcl(CPUX86State *env, struct x86_decode *decode)
100827458df8SWei Liu {
100927458df8SWei Liu     uint8_t count;
101027458df8SWei Liu     int of = 0, cf = 0;
101127458df8SWei Liu 
101227458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
101327458df8SWei Liu     count = decode->op[1].val & 0x1f;
101427458df8SWei Liu 
101527458df8SWei Liu     switch (decode->operand_size) {
101627458df8SWei Liu     case 1:
101727458df8SWei Liu     {
101827458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
101927458df8SWei Liu         uint8_t res;
102027458df8SWei Liu         count %= 9;
102127458df8SWei Liu         if (!count) {
102227458df8SWei Liu             break;
102327458df8SWei Liu         }
102427458df8SWei Liu 
102527458df8SWei Liu         if (1 == count) {
102627458df8SWei Liu             res = (op1_8 << 1) | get_CF(env);
102727458df8SWei Liu         } else {
102827458df8SWei Liu             res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
102927458df8SWei Liu                    (op1_8 >> (9 - count));
103027458df8SWei Liu         }
103127458df8SWei Liu 
103277a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 1);
103327458df8SWei Liu 
103427458df8SWei Liu         cf = (op1_8 >> (8 - count)) & 0x01;
103527458df8SWei Liu         of = cf ^ (res >> 7); /* of = cf ^ result7 */
103627458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
103727458df8SWei Liu         break;
103827458df8SWei Liu     }
103927458df8SWei Liu     case 2:
104027458df8SWei Liu     {
104127458df8SWei Liu         uint16_t res;
104227458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
104327458df8SWei Liu 
104427458df8SWei Liu         count %= 17;
104527458df8SWei Liu         if (!count) {
104627458df8SWei Liu             break;
104727458df8SWei Liu         }
104827458df8SWei Liu 
104927458df8SWei Liu         if (1 == count) {
105027458df8SWei Liu             res = (op1_16 << 1) | get_CF(env);
105127458df8SWei Liu         } else if (count == 16) {
105227458df8SWei Liu             res = (get_CF(env) << 15) | (op1_16 >> 1);
105327458df8SWei Liu         } else { /* 2..15 */
105427458df8SWei Liu             res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
105527458df8SWei Liu                    (op1_16 >> (17 - count));
105627458df8SWei Liu         }
105727458df8SWei Liu 
105877a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 2);
105927458df8SWei Liu 
106027458df8SWei Liu         cf = (op1_16 >> (16 - count)) & 0x1;
106127458df8SWei Liu         of = cf ^ (res >> 15); /* of = cf ^ result15 */
106227458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
106327458df8SWei Liu         break;
106427458df8SWei Liu     }
106527458df8SWei Liu     case 4:
106627458df8SWei Liu     {
106727458df8SWei Liu         uint32_t res;
106827458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
106927458df8SWei Liu 
107027458df8SWei Liu         if (!count) {
107127458df8SWei Liu             break;
107227458df8SWei Liu         }
107327458df8SWei Liu 
107427458df8SWei Liu         if (1 == count) {
107527458df8SWei Liu             res = (op1_32 << 1) | get_CF(env);
107627458df8SWei Liu         } else {
107727458df8SWei Liu             res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
107827458df8SWei Liu                    (op1_32 >> (33 - count));
107927458df8SWei Liu         }
108027458df8SWei Liu 
108177a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 4);
108227458df8SWei Liu 
108327458df8SWei Liu         cf = (op1_32 >> (32 - count)) & 0x1;
108427458df8SWei Liu         of = cf ^ (res >> 31); /* of = cf ^ result31 */
108527458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
108627458df8SWei Liu         break;
108727458df8SWei Liu         }
108827458df8SWei Liu     }
108927458df8SWei Liu     env->eip += decode->len;
109027458df8SWei Liu }
109127458df8SWei Liu 
exec_rcr(CPUX86State * env,struct x86_decode * decode)109227458df8SWei Liu void exec_rcr(CPUX86State *env, struct x86_decode *decode)
109327458df8SWei Liu {
109427458df8SWei Liu     uint8_t count;
109527458df8SWei Liu     int of = 0, cf = 0;
109627458df8SWei Liu 
109727458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
109827458df8SWei Liu     count = decode->op[1].val & 0x1f;
109927458df8SWei Liu 
110027458df8SWei Liu     switch (decode->operand_size) {
110127458df8SWei Liu     case 1:
110227458df8SWei Liu     {
110327458df8SWei Liu         uint8_t op1_8 = decode->op[0].val;
110427458df8SWei Liu         uint8_t res;
110527458df8SWei Liu 
110627458df8SWei Liu         count %= 9;
110727458df8SWei Liu         if (!count) {
110827458df8SWei Liu             break;
110927458df8SWei Liu         }
111027458df8SWei Liu         res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
111127458df8SWei Liu                (op1_8 << (9 - count));
111227458df8SWei Liu 
111377a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 1);
111427458df8SWei Liu 
111527458df8SWei Liu         cf = (op1_8 >> (count - 1)) & 0x1;
111627458df8SWei Liu         of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
111727458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
111827458df8SWei Liu         break;
111927458df8SWei Liu     }
112027458df8SWei Liu     case 2:
112127458df8SWei Liu     {
112227458df8SWei Liu         uint16_t op1_16 = decode->op[0].val;
112327458df8SWei Liu         uint16_t res;
112427458df8SWei Liu 
112527458df8SWei Liu         count %= 17;
112627458df8SWei Liu         if (!count) {
112727458df8SWei Liu             break;
112827458df8SWei Liu         }
112927458df8SWei Liu         res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
113027458df8SWei Liu                (op1_16 << (17 - count));
113127458df8SWei Liu 
113277a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 2);
113327458df8SWei Liu 
113427458df8SWei Liu         cf = (op1_16 >> (count - 1)) & 0x1;
113527458df8SWei Liu         of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
113627458df8SWei Liu                                                             result14 */
113727458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
113827458df8SWei Liu         break;
113927458df8SWei Liu     }
114027458df8SWei Liu     case 4:
114127458df8SWei Liu     {
114227458df8SWei Liu         uint32_t res;
114327458df8SWei Liu         uint32_t op1_32 = decode->op[0].val;
114427458df8SWei Liu 
114527458df8SWei Liu         if (!count) {
114627458df8SWei Liu             break;
114727458df8SWei Liu         }
114827458df8SWei Liu 
114927458df8SWei Liu         if (1 == count) {
115027458df8SWei Liu             res = (op1_32 >> 1) | (get_CF(env) << 31);
115127458df8SWei Liu         } else {
115227458df8SWei Liu             res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
115327458df8SWei Liu                    (op1_32 << (33 - count));
115427458df8SWei Liu         }
115527458df8SWei Liu 
115677a2dba4SPaolo Bonzini         write_val_ext(env, &decode->op[0], res, 4);
115727458df8SWei Liu 
115827458df8SWei Liu         cf = (op1_32 >> (count - 1)) & 0x1;
115927458df8SWei Liu         of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
116027458df8SWei Liu         SET_FLAGS_OxxxxC(env, of, cf);
116127458df8SWei Liu         break;
116227458df8SWei Liu         }
116327458df8SWei Liu     }
116427458df8SWei Liu     env->eip += decode->len;
116527458df8SWei Liu }
116627458df8SWei Liu 
exec_xchg(CPUX86State * env,struct x86_decode * decode)116727458df8SWei Liu static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
116827458df8SWei Liu {
116927458df8SWei Liu     fetch_operands(env, decode, 2, true, true, false);
117027458df8SWei Liu 
117177a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[0], decode->op[1].val,
117227458df8SWei Liu                   decode->operand_size);
117377a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[1], decode->op[0].val,
117427458df8SWei Liu                   decode->operand_size);
117527458df8SWei Liu 
117627458df8SWei Liu     env->eip += decode->len;
117727458df8SWei Liu }
117827458df8SWei Liu 
exec_xadd(CPUX86State * env,struct x86_decode * decode)117927458df8SWei Liu static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
118027458df8SWei Liu {
118127458df8SWei Liu     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
118277a2dba4SPaolo Bonzini     write_val_ext(env, &decode->op[1], decode->op[0].val,
118327458df8SWei Liu                   decode->operand_size);
118427458df8SWei Liu 
118527458df8SWei Liu     env->eip += decode->len;
118627458df8SWei Liu }
118727458df8SWei Liu 
118827458df8SWei Liu static struct cmd_handler {
118927458df8SWei Liu     enum x86_decode_cmd cmd;
119027458df8SWei Liu     void (*handler)(CPUX86State *env, struct x86_decode *ins);
119127458df8SWei Liu } handlers[] = {
119227458df8SWei Liu     {X86_DECODE_CMD_INVL, NULL,},
119327458df8SWei Liu     {X86_DECODE_CMD_MOV, exec_mov},
119427458df8SWei Liu     {X86_DECODE_CMD_ADD, exec_add},
119527458df8SWei Liu     {X86_DECODE_CMD_OR, exec_or},
119627458df8SWei Liu     {X86_DECODE_CMD_ADC, exec_adc},
119727458df8SWei Liu     {X86_DECODE_CMD_SBB, exec_sbb},
119827458df8SWei Liu     {X86_DECODE_CMD_AND, exec_and},
119927458df8SWei Liu     {X86_DECODE_CMD_SUB, exec_sub},
120027458df8SWei Liu     {X86_DECODE_CMD_NEG, exec_neg},
120127458df8SWei Liu     {X86_DECODE_CMD_XOR, exec_xor},
120227458df8SWei Liu     {X86_DECODE_CMD_CMP, exec_cmp},
120327458df8SWei Liu     {X86_DECODE_CMD_INC, exec_inc},
120427458df8SWei Liu     {X86_DECODE_CMD_DEC, exec_dec},
120527458df8SWei Liu     {X86_DECODE_CMD_TST, exec_tst},
120627458df8SWei Liu     {X86_DECODE_CMD_NOT, exec_not},
120727458df8SWei Liu     {X86_DECODE_CMD_MOVZX, exec_movzx},
120827458df8SWei Liu     {X86_DECODE_CMD_OUT, exec_out},
120927458df8SWei Liu     {X86_DECODE_CMD_IN, exec_in},
121027458df8SWei Liu     {X86_DECODE_CMD_INS, exec_ins},
121127458df8SWei Liu     {X86_DECODE_CMD_OUTS, exec_outs},
121227458df8SWei Liu     {X86_DECODE_CMD_RDMSR, exec_rdmsr},
121327458df8SWei Liu     {X86_DECODE_CMD_WRMSR, exec_wrmsr},
121427458df8SWei Liu     {X86_DECODE_CMD_BT, exec_bt},
121527458df8SWei Liu     {X86_DECODE_CMD_BTR, exec_btr},
121627458df8SWei Liu     {X86_DECODE_CMD_BTC, exec_btc},
121727458df8SWei Liu     {X86_DECODE_CMD_BTS, exec_bts},
121827458df8SWei Liu     {X86_DECODE_CMD_SHL, exec_shl},
121927458df8SWei Liu     {X86_DECODE_CMD_ROL, exec_rol},
122027458df8SWei Liu     {X86_DECODE_CMD_ROR, exec_ror},
122127458df8SWei Liu     {X86_DECODE_CMD_RCR, exec_rcr},
122227458df8SWei Liu     {X86_DECODE_CMD_RCL, exec_rcl},
122327458df8SWei Liu     /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
122427458df8SWei Liu     {X86_DECODE_CMD_MOVS, exec_movs},
122527458df8SWei Liu     {X86_DECODE_CMD_CMPS, exec_cmps},
122627458df8SWei Liu     {X86_DECODE_CMD_STOS, exec_stos},
122727458df8SWei Liu     {X86_DECODE_CMD_SCAS, exec_scas},
122827458df8SWei Liu     {X86_DECODE_CMD_LODS, exec_lods},
122927458df8SWei Liu     {X86_DECODE_CMD_MOVSX, exec_movsx},
123027458df8SWei Liu     {X86_DECODE_CMD_XCHG, exec_xchg},
123127458df8SWei Liu     {X86_DECODE_CMD_XADD, exec_xadd},
123227458df8SWei Liu };
123327458df8SWei Liu 
123427458df8SWei Liu static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
123527458df8SWei Liu 
123627458df8SWei Liu const struct x86_emul_ops *emul_ops;
123727458df8SWei Liu 
init_cmd_handler(void)123827458df8SWei Liu static void init_cmd_handler(void)
123927458df8SWei Liu {
124027458df8SWei Liu     int i;
124127458df8SWei Liu     for (i = 0; i < ARRAY_SIZE(handlers); i++) {
124227458df8SWei Liu         _cmd_handler[handlers[i].cmd] = handlers[i];
124327458df8SWei Liu     }
124427458df8SWei Liu }
124527458df8SWei Liu 
exec_instruction(CPUX86State * env,struct x86_decode * ins)124627458df8SWei Liu bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
124727458df8SWei Liu {
124827458df8SWei Liu     if (!_cmd_handler[ins->cmd].handler) {
12497abf0d95SPaolo Bonzini         printf("Unimplemented handler (" TARGET_FMT_lx ") for %d (%x %x) \n", env->eip,
125027458df8SWei Liu                 ins->cmd, ins->opcode[0],
125127458df8SWei Liu                 ins->opcode_len > 1 ? ins->opcode[1] : 0);
125227458df8SWei Liu         env->eip += ins->len;
125327458df8SWei Liu         return true;
125427458df8SWei Liu     }
125527458df8SWei Liu 
125627458df8SWei Liu     _cmd_handler[ins->cmd].handler(env, ins);
125727458df8SWei Liu     return true;
125827458df8SWei Liu }
125927458df8SWei Liu 
init_emu(const struct x86_emul_ops * o)126027458df8SWei Liu void init_emu(const struct x86_emul_ops *o)
126127458df8SWei Liu {
126227458df8SWei Liu     emul_ops = o;
126327458df8SWei Liu     init_cmd_handler();
126427458df8SWei Liu }
1265