169e0a03cSPaolo Bonzini /*
269e0a03cSPaolo Bonzini * Copyright (C) 2016 Veertu Inc,
369e0a03cSPaolo Bonzini * Copyright (C) 2017 Google Inc,
469e0a03cSPaolo Bonzini *
569e0a03cSPaolo Bonzini * This program is free software; you can redistribute it and/or
669e0a03cSPaolo Bonzini * modify it under the terms of the GNU Lesser General Public
769e0a03cSPaolo Bonzini * License as published by the Free Software Foundation; either
88af82b8eSChetan Pant * version 2.1 of the License, or (at your option) any later version.
969e0a03cSPaolo Bonzini *
1069e0a03cSPaolo Bonzini * This program is distributed in the hope that it will be useful,
1169e0a03cSPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of
1269e0a03cSPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1369e0a03cSPaolo Bonzini * Lesser General Public License for more details.
1469e0a03cSPaolo Bonzini *
1569e0a03cSPaolo Bonzini * You should have received a copy of the GNU Lesser General Public
1669e0a03cSPaolo Bonzini * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1769e0a03cSPaolo Bonzini */
1869e0a03cSPaolo Bonzini
1969e0a03cSPaolo Bonzini /////////////////////////////////////////////////////////////////////////
2069e0a03cSPaolo Bonzini //
2169e0a03cSPaolo Bonzini // Copyright (C) 2001-2012 The Bochs Project
2269e0a03cSPaolo Bonzini //
2369e0a03cSPaolo Bonzini // This library is free software; you can redistribute it and/or
2469e0a03cSPaolo Bonzini // modify it under the terms of the GNU Lesser General Public
2569e0a03cSPaolo Bonzini // License as published by the Free Software Foundation; either
268af82b8eSChetan Pant // version 2.1 of the License, or (at your option) any later version.
2769e0a03cSPaolo Bonzini //
2869e0a03cSPaolo Bonzini // This library is distributed in the hope that it will be useful,
2969e0a03cSPaolo Bonzini // but WITHOUT ANY WARRANTY; without even the implied warranty of
3069e0a03cSPaolo Bonzini // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3169e0a03cSPaolo Bonzini // Lesser General Public License for more details.
3269e0a03cSPaolo Bonzini //
3369e0a03cSPaolo Bonzini // You should have received a copy of the GNU Lesser General Public
3469e0a03cSPaolo Bonzini // License along with this library; if not, write to the Free Software
3569e0a03cSPaolo Bonzini // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
3669e0a03cSPaolo Bonzini /////////////////////////////////////////////////////////////////////////
3769e0a03cSPaolo Bonzini
3869e0a03cSPaolo Bonzini #include "qemu/osdep.h"
39895f9fdfSPaolo Bonzini #include "panic.h"
4069e0a03cSPaolo Bonzini #include "x86_decode.h"
4169e0a03cSPaolo Bonzini #include "x86.h"
4269e0a03cSPaolo Bonzini #include "x86_emu.h"
4369e0a03cSPaolo Bonzini #include "x86_mmu.h"
4469e0a03cSPaolo Bonzini #include "x86_flags.h"
4569e0a03cSPaolo Bonzini #include "vmcs.h"
4669e0a03cSPaolo Bonzini #include "vmx.h"
4769e0a03cSPaolo Bonzini
485366a064SPhilippe Mathieu-Daudé void hvf_handle_io(CPUState *cs, uint16_t port, void *data,
4969e0a03cSPaolo Bonzini int direction, int size, uint32_t count);
5069e0a03cSPaolo Bonzini
51e8a63257SPaolo Bonzini #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
5269e0a03cSPaolo Bonzini { \
5369e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false); \
5469e0a03cSPaolo Bonzini switch (decode->operand_size) { \
5569e0a03cSPaolo Bonzini case 1: \
5669e0a03cSPaolo Bonzini { \
5769e0a03cSPaolo Bonzini uint8_t v1 = (uint8_t)decode->op[0].val; \
5869e0a03cSPaolo Bonzini uint8_t v2 = (uint8_t)decode->op[1].val; \
5969e0a03cSPaolo Bonzini uint8_t diff = v1 cmd v2; \
6069e0a03cSPaolo Bonzini if (save_res) { \
6169e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, diff, 1); \
6269e0a03cSPaolo Bonzini } \
63e8a63257SPaolo Bonzini FLAGS_FUNC##8(env, v1, v2, diff); \
6469e0a03cSPaolo Bonzini break; \
6569e0a03cSPaolo Bonzini } \
6669e0a03cSPaolo Bonzini case 2: \
6769e0a03cSPaolo Bonzini { \
6869e0a03cSPaolo Bonzini uint16_t v1 = (uint16_t)decode->op[0].val; \
6969e0a03cSPaolo Bonzini uint16_t v2 = (uint16_t)decode->op[1].val; \
7069e0a03cSPaolo Bonzini uint16_t diff = v1 cmd v2; \
7169e0a03cSPaolo Bonzini if (save_res) { \
7269e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, diff, 2); \
7369e0a03cSPaolo Bonzini } \
74e8a63257SPaolo Bonzini FLAGS_FUNC##16(env, v1, v2, diff); \
7569e0a03cSPaolo Bonzini break; \
7669e0a03cSPaolo Bonzini } \
7769e0a03cSPaolo Bonzini case 4: \
7869e0a03cSPaolo Bonzini { \
7969e0a03cSPaolo Bonzini uint32_t v1 = (uint32_t)decode->op[0].val; \
8069e0a03cSPaolo Bonzini uint32_t v2 = (uint32_t)decode->op[1].val; \
8169e0a03cSPaolo Bonzini uint32_t diff = v1 cmd v2; \
8269e0a03cSPaolo Bonzini if (save_res) { \
8369e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, diff, 4); \
8469e0a03cSPaolo Bonzini } \
85e8a63257SPaolo Bonzini FLAGS_FUNC##32(env, v1, v2, diff); \
8669e0a03cSPaolo Bonzini break; \
8769e0a03cSPaolo Bonzini } \
8869e0a03cSPaolo Bonzini default: \
8969e0a03cSPaolo Bonzini VM_PANIC("bad size\n"); \
9069e0a03cSPaolo Bonzini } \
9169e0a03cSPaolo Bonzini } \
9269e0a03cSPaolo Bonzini
read_reg(CPUX86State * env,int reg,int size)93ff2de166SPaolo Bonzini target_ulong read_reg(CPUX86State *env, int reg, int size)
9469e0a03cSPaolo Bonzini {
9569e0a03cSPaolo Bonzini switch (size) {
9669e0a03cSPaolo Bonzini case 1:
97167c6aefSRoman Bolshakov return x86_reg(env, reg)->lx;
9869e0a03cSPaolo Bonzini case 2:
99167c6aefSRoman Bolshakov return x86_reg(env, reg)->rx;
10069e0a03cSPaolo Bonzini case 4:
101167c6aefSRoman Bolshakov return x86_reg(env, reg)->erx;
10269e0a03cSPaolo Bonzini case 8:
103167c6aefSRoman Bolshakov return x86_reg(env, reg)->rrx;
10469e0a03cSPaolo Bonzini default:
105e62963bfSPaolo Bonzini abort();
10669e0a03cSPaolo Bonzini }
10769e0a03cSPaolo Bonzini return 0;
10869e0a03cSPaolo Bonzini }
10969e0a03cSPaolo Bonzini
write_reg(CPUX86State * env,int reg,target_ulong val,int size)110ff2de166SPaolo Bonzini void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
11169e0a03cSPaolo Bonzini {
11269e0a03cSPaolo Bonzini switch (size) {
11369e0a03cSPaolo Bonzini case 1:
114167c6aefSRoman Bolshakov x86_reg(env, reg)->lx = val;
11569e0a03cSPaolo Bonzini break;
11669e0a03cSPaolo Bonzini case 2:
117167c6aefSRoman Bolshakov x86_reg(env, reg)->rx = val;
11869e0a03cSPaolo Bonzini break;
11969e0a03cSPaolo Bonzini case 4:
120167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = (uint32_t)val;
12169e0a03cSPaolo Bonzini break;
12269e0a03cSPaolo Bonzini case 8:
123167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = val;
12469e0a03cSPaolo Bonzini break;
12569e0a03cSPaolo Bonzini default:
126e62963bfSPaolo Bonzini abort();
12769e0a03cSPaolo Bonzini }
12869e0a03cSPaolo Bonzini }
12969e0a03cSPaolo Bonzini
read_val_from_reg(target_ulong reg_ptr,int size)130ff2de166SPaolo Bonzini target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
13169e0a03cSPaolo Bonzini {
132ff2de166SPaolo Bonzini target_ulong val;
13369e0a03cSPaolo Bonzini
13469e0a03cSPaolo Bonzini switch (size) {
13569e0a03cSPaolo Bonzini case 1:
13669e0a03cSPaolo Bonzini val = *(uint8_t *)reg_ptr;
13769e0a03cSPaolo Bonzini break;
13869e0a03cSPaolo Bonzini case 2:
13969e0a03cSPaolo Bonzini val = *(uint16_t *)reg_ptr;
14069e0a03cSPaolo Bonzini break;
14169e0a03cSPaolo Bonzini case 4:
14269e0a03cSPaolo Bonzini val = *(uint32_t *)reg_ptr;
14369e0a03cSPaolo Bonzini break;
14469e0a03cSPaolo Bonzini case 8:
14569e0a03cSPaolo Bonzini val = *(uint64_t *)reg_ptr;
14669e0a03cSPaolo Bonzini break;
14769e0a03cSPaolo Bonzini default:
148e62963bfSPaolo Bonzini abort();
14969e0a03cSPaolo Bonzini }
15069e0a03cSPaolo Bonzini return val;
15169e0a03cSPaolo Bonzini }
15269e0a03cSPaolo Bonzini
write_val_to_reg(target_ulong reg_ptr,target_ulong val,int size)153ff2de166SPaolo Bonzini void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
15469e0a03cSPaolo Bonzini {
15569e0a03cSPaolo Bonzini switch (size) {
15669e0a03cSPaolo Bonzini case 1:
15769e0a03cSPaolo Bonzini *(uint8_t *)reg_ptr = val;
15869e0a03cSPaolo Bonzini break;
15969e0a03cSPaolo Bonzini case 2:
16069e0a03cSPaolo Bonzini *(uint16_t *)reg_ptr = val;
16169e0a03cSPaolo Bonzini break;
16269e0a03cSPaolo Bonzini case 4:
16369e0a03cSPaolo Bonzini *(uint64_t *)reg_ptr = (uint32_t)val;
16469e0a03cSPaolo Bonzini break;
16569e0a03cSPaolo Bonzini case 8:
16669e0a03cSPaolo Bonzini *(uint64_t *)reg_ptr = val;
16769e0a03cSPaolo Bonzini break;
16869e0a03cSPaolo Bonzini default:
169e62963bfSPaolo Bonzini abort();
17069e0a03cSPaolo Bonzini }
17169e0a03cSPaolo Bonzini }
17269e0a03cSPaolo Bonzini
is_host_reg(CPUX86State * env,target_ulong ptr)17336861198SPhilippe Mathieu-Daudé static bool is_host_reg(CPUX86State *env, target_ulong ptr)
17469e0a03cSPaolo Bonzini {
175167c6aefSRoman Bolshakov return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
17669e0a03cSPaolo Bonzini }
17769e0a03cSPaolo Bonzini
write_val_ext(CPUX86State * env,target_ulong ptr,target_ulong val,int size)17836861198SPhilippe Mathieu-Daudé void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
17969e0a03cSPaolo Bonzini {
18069e0a03cSPaolo Bonzini if (is_host_reg(env, ptr)) {
18169e0a03cSPaolo Bonzini write_val_to_reg(ptr, val, size);
18269e0a03cSPaolo Bonzini return;
18369e0a03cSPaolo Bonzini }
18429a0af61SRichard Henderson vmx_write_mem(env_cpu(env), ptr, &val, size);
18569e0a03cSPaolo Bonzini }
18669e0a03cSPaolo Bonzini
read_mmio(CPUX86State * env,target_ulong ptr,int bytes)18736861198SPhilippe Mathieu-Daudé uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
18869e0a03cSPaolo Bonzini {
189fe76b09cSRoman Bolshakov vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes);
190fe76b09cSRoman Bolshakov return env->hvf_mmio_buf;
19169e0a03cSPaolo Bonzini }
19269e0a03cSPaolo Bonzini
19369e0a03cSPaolo Bonzini
read_val_ext(CPUX86State * env,target_ulong ptr,int size)19436861198SPhilippe Mathieu-Daudé target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
19569e0a03cSPaolo Bonzini {
196ff2de166SPaolo Bonzini target_ulong val;
19769e0a03cSPaolo Bonzini uint8_t *mmio_ptr;
19869e0a03cSPaolo Bonzini
19969e0a03cSPaolo Bonzini if (is_host_reg(env, ptr)) {
20069e0a03cSPaolo Bonzini return read_val_from_reg(ptr, size);
20169e0a03cSPaolo Bonzini }
20269e0a03cSPaolo Bonzini
20369e0a03cSPaolo Bonzini mmio_ptr = read_mmio(env, ptr, size);
20469e0a03cSPaolo Bonzini switch (size) {
20569e0a03cSPaolo Bonzini case 1:
20669e0a03cSPaolo Bonzini val = *(uint8_t *)mmio_ptr;
20769e0a03cSPaolo Bonzini break;
20869e0a03cSPaolo Bonzini case 2:
20969e0a03cSPaolo Bonzini val = *(uint16_t *)mmio_ptr;
21069e0a03cSPaolo Bonzini break;
21169e0a03cSPaolo Bonzini case 4:
21269e0a03cSPaolo Bonzini val = *(uint32_t *)mmio_ptr;
21369e0a03cSPaolo Bonzini break;
21469e0a03cSPaolo Bonzini case 8:
21569e0a03cSPaolo Bonzini val = *(uint64_t *)mmio_ptr;
21669e0a03cSPaolo Bonzini break;
21769e0a03cSPaolo Bonzini default:
21869e0a03cSPaolo Bonzini VM_PANIC("bad size\n");
21969e0a03cSPaolo Bonzini break;
22069e0a03cSPaolo Bonzini }
22169e0a03cSPaolo Bonzini return val;
22269e0a03cSPaolo Bonzini }
22369e0a03cSPaolo Bonzini
fetch_operands(CPUX86State * env,struct x86_decode * decode,int n,bool val_op0,bool val_op1,bool val_op2)22436861198SPhilippe Mathieu-Daudé static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
22569e0a03cSPaolo Bonzini int n, bool val_op0, bool val_op1, bool val_op2)
22669e0a03cSPaolo Bonzini {
22769e0a03cSPaolo Bonzini int i;
22869e0a03cSPaolo Bonzini bool calc_val[3] = {val_op0, val_op1, val_op2};
22969e0a03cSPaolo Bonzini
23069e0a03cSPaolo Bonzini for (i = 0; i < n; i++) {
23169e0a03cSPaolo Bonzini switch (decode->op[i].type) {
23269e0a03cSPaolo Bonzini case X86_VAR_IMMEDIATE:
23369e0a03cSPaolo Bonzini break;
23469e0a03cSPaolo Bonzini case X86_VAR_REG:
23569e0a03cSPaolo Bonzini VM_PANIC_ON(!decode->op[i].ptr);
23669e0a03cSPaolo Bonzini if (calc_val[i]) {
23769e0a03cSPaolo Bonzini decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
23869e0a03cSPaolo Bonzini decode->operand_size);
23969e0a03cSPaolo Bonzini }
24069e0a03cSPaolo Bonzini break;
24169e0a03cSPaolo Bonzini case X86_VAR_RM:
24269e0a03cSPaolo Bonzini calc_modrm_operand(env, decode, &decode->op[i]);
24369e0a03cSPaolo Bonzini if (calc_val[i]) {
24469e0a03cSPaolo Bonzini decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
24569e0a03cSPaolo Bonzini decode->operand_size);
24669e0a03cSPaolo Bonzini }
24769e0a03cSPaolo Bonzini break;
24869e0a03cSPaolo Bonzini case X86_VAR_OFFSET:
24969e0a03cSPaolo Bonzini decode->op[i].ptr = decode_linear_addr(env, decode,
25069e0a03cSPaolo Bonzini decode->op[i].ptr,
2516701d81dSPaolo Bonzini R_DS);
25269e0a03cSPaolo Bonzini if (calc_val[i]) {
25369e0a03cSPaolo Bonzini decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
25469e0a03cSPaolo Bonzini decode->operand_size);
25569e0a03cSPaolo Bonzini }
25669e0a03cSPaolo Bonzini break;
25769e0a03cSPaolo Bonzini default:
25869e0a03cSPaolo Bonzini break;
25969e0a03cSPaolo Bonzini }
26069e0a03cSPaolo Bonzini }
26169e0a03cSPaolo Bonzini }
26269e0a03cSPaolo Bonzini
exec_mov(CPUX86State * env,struct x86_decode * decode)26336861198SPhilippe Mathieu-Daudé static void exec_mov(CPUX86State *env, struct x86_decode *decode)
26469e0a03cSPaolo Bonzini {
26569e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, false, true, false);
26669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
26769e0a03cSPaolo Bonzini decode->operand_size);
26869e0a03cSPaolo Bonzini
2695d32173fSRoman Bolshakov env->eip += decode->len;
27069e0a03cSPaolo Bonzini }
27169e0a03cSPaolo Bonzini
exec_add(CPUX86State * env,struct x86_decode * decode)27236861198SPhilippe Mathieu-Daudé static void exec_add(CPUX86State *env, struct x86_decode *decode)
27369e0a03cSPaolo Bonzini {
274e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
2755d32173fSRoman Bolshakov env->eip += decode->len;
27669e0a03cSPaolo Bonzini }
27769e0a03cSPaolo Bonzini
exec_or(CPUX86State * env,struct x86_decode * decode)27836861198SPhilippe Mathieu-Daudé static void exec_or(CPUX86State *env, struct x86_decode *decode)
27969e0a03cSPaolo Bonzini {
280e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
2815d32173fSRoman Bolshakov env->eip += decode->len;
28269e0a03cSPaolo Bonzini }
28369e0a03cSPaolo Bonzini
exec_adc(CPUX86State * env,struct x86_decode * decode)28436861198SPhilippe Mathieu-Daudé static void exec_adc(CPUX86State *env, struct x86_decode *decode)
28569e0a03cSPaolo Bonzini {
286e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
2875d32173fSRoman Bolshakov env->eip += decode->len;
28869e0a03cSPaolo Bonzini }
28969e0a03cSPaolo Bonzini
exec_sbb(CPUX86State * env,struct x86_decode * decode)29036861198SPhilippe Mathieu-Daudé static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
29169e0a03cSPaolo Bonzini {
292e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
2935d32173fSRoman Bolshakov env->eip += decode->len;
29469e0a03cSPaolo Bonzini }
29569e0a03cSPaolo Bonzini
exec_and(CPUX86State * env,struct x86_decode * decode)29636861198SPhilippe Mathieu-Daudé static void exec_and(CPUX86State *env, struct x86_decode *decode)
29769e0a03cSPaolo Bonzini {
298e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
2995d32173fSRoman Bolshakov env->eip += decode->len;
30069e0a03cSPaolo Bonzini }
30169e0a03cSPaolo Bonzini
exec_sub(CPUX86State * env,struct x86_decode * decode)30236861198SPhilippe Mathieu-Daudé static void exec_sub(CPUX86State *env, struct x86_decode *decode)
30369e0a03cSPaolo Bonzini {
304e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
3055d32173fSRoman Bolshakov env->eip += decode->len;
30669e0a03cSPaolo Bonzini }
30769e0a03cSPaolo Bonzini
exec_xor(CPUX86State * env,struct x86_decode * decode)30836861198SPhilippe Mathieu-Daudé static void exec_xor(CPUX86State *env, struct x86_decode *decode)
30969e0a03cSPaolo Bonzini {
310e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
3115d32173fSRoman Bolshakov env->eip += decode->len;
31269e0a03cSPaolo Bonzini }
31369e0a03cSPaolo Bonzini
exec_neg(CPUX86State * env,struct x86_decode * decode)31436861198SPhilippe Mathieu-Daudé static void exec_neg(CPUX86State *env, struct x86_decode *decode)
31569e0a03cSPaolo Bonzini {
316e8a63257SPaolo Bonzini /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
31769e0a03cSPaolo Bonzini int32_t val;
31869e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
31969e0a03cSPaolo Bonzini
32069e0a03cSPaolo Bonzini val = 0 - sign(decode->op[1].val, decode->operand_size);
32169e0a03cSPaolo Bonzini write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
32269e0a03cSPaolo Bonzini
32369e0a03cSPaolo Bonzini if (4 == decode->operand_size) {
324e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
32569e0a03cSPaolo Bonzini } else if (2 == decode->operand_size) {
326e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
32769e0a03cSPaolo Bonzini } else if (1 == decode->operand_size) {
328e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
32969e0a03cSPaolo Bonzini } else {
33069e0a03cSPaolo Bonzini VM_PANIC("bad op size\n");
33169e0a03cSPaolo Bonzini }
33269e0a03cSPaolo Bonzini
33369e0a03cSPaolo Bonzini /*lflags_to_rflags(env);*/
3345d32173fSRoman Bolshakov env->eip += decode->len;
33569e0a03cSPaolo Bonzini }
33669e0a03cSPaolo Bonzini
exec_cmp(CPUX86State * env,struct x86_decode * decode)33736861198SPhilippe Mathieu-Daudé static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
33869e0a03cSPaolo Bonzini {
339e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
3405d32173fSRoman Bolshakov env->eip += decode->len;
34169e0a03cSPaolo Bonzini }
34269e0a03cSPaolo Bonzini
exec_inc(CPUX86State * env,struct x86_decode * decode)34336861198SPhilippe Mathieu-Daudé static void exec_inc(CPUX86State *env, struct x86_decode *decode)
34469e0a03cSPaolo Bonzini {
34569e0a03cSPaolo Bonzini decode->op[1].type = X86_VAR_IMMEDIATE;
34669e0a03cSPaolo Bonzini decode->op[1].val = 0;
34769e0a03cSPaolo Bonzini
348e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
34969e0a03cSPaolo Bonzini
3505d32173fSRoman Bolshakov env->eip += decode->len;
35169e0a03cSPaolo Bonzini }
35269e0a03cSPaolo Bonzini
exec_dec(CPUX86State * env,struct x86_decode * decode)35336861198SPhilippe Mathieu-Daudé static void exec_dec(CPUX86State *env, struct x86_decode *decode)
35469e0a03cSPaolo Bonzini {
35569e0a03cSPaolo Bonzini decode->op[1].type = X86_VAR_IMMEDIATE;
35669e0a03cSPaolo Bonzini decode->op[1].val = 0;
35769e0a03cSPaolo Bonzini
358e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
3595d32173fSRoman Bolshakov env->eip += decode->len;
36069e0a03cSPaolo Bonzini }
36169e0a03cSPaolo Bonzini
exec_tst(CPUX86State * env,struct x86_decode * decode)36236861198SPhilippe Mathieu-Daudé static void exec_tst(CPUX86State *env, struct x86_decode *decode)
36369e0a03cSPaolo Bonzini {
364e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
3655d32173fSRoman Bolshakov env->eip += decode->len;
36669e0a03cSPaolo Bonzini }
36769e0a03cSPaolo Bonzini
exec_not(CPUX86State * env,struct x86_decode * decode)36836861198SPhilippe Mathieu-Daudé static void exec_not(CPUX86State *env, struct x86_decode *decode)
36969e0a03cSPaolo Bonzini {
37069e0a03cSPaolo Bonzini fetch_operands(env, decode, 1, true, false, false);
37169e0a03cSPaolo Bonzini
37269e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
37369e0a03cSPaolo Bonzini decode->operand_size);
3745d32173fSRoman Bolshakov env->eip += decode->len;
37569e0a03cSPaolo Bonzini }
37669e0a03cSPaolo Bonzini
exec_movzx(CPUX86State * env,struct x86_decode * decode)37736861198SPhilippe Mathieu-Daudé void exec_movzx(CPUX86State *env, struct x86_decode *decode)
37869e0a03cSPaolo Bonzini {
37969e0a03cSPaolo Bonzini int src_op_size;
38069e0a03cSPaolo Bonzini int op_size = decode->operand_size;
38169e0a03cSPaolo Bonzini
38269e0a03cSPaolo Bonzini fetch_operands(env, decode, 1, false, false, false);
38369e0a03cSPaolo Bonzini
38469e0a03cSPaolo Bonzini if (0xb6 == decode->opcode[1]) {
38569e0a03cSPaolo Bonzini src_op_size = 1;
38669e0a03cSPaolo Bonzini } else {
38769e0a03cSPaolo Bonzini src_op_size = 2;
38869e0a03cSPaolo Bonzini }
38969e0a03cSPaolo Bonzini decode->operand_size = src_op_size;
39069e0a03cSPaolo Bonzini calc_modrm_operand(env, decode, &decode->op[1]);
39169e0a03cSPaolo Bonzini decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
39269e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
39369e0a03cSPaolo Bonzini
3945d32173fSRoman Bolshakov env->eip += decode->len;
39569e0a03cSPaolo Bonzini }
39669e0a03cSPaolo Bonzini
exec_out(CPUX86State * env,struct x86_decode * decode)39736861198SPhilippe Mathieu-Daudé static void exec_out(CPUX86State *env, struct x86_decode *decode)
39869e0a03cSPaolo Bonzini {
39969e0a03cSPaolo Bonzini switch (decode->opcode[0]) {
40069e0a03cSPaolo Bonzini case 0xe6:
40129a0af61SRichard Henderson hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
40269e0a03cSPaolo Bonzini break;
40369e0a03cSPaolo Bonzini case 0xe7:
40429a0af61SRichard Henderson hvf_handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
40569e0a03cSPaolo Bonzini decode->operand_size, 1);
40669e0a03cSPaolo Bonzini break;
40769e0a03cSPaolo Bonzini case 0xee:
40829a0af61SRichard Henderson hvf_handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
40969e0a03cSPaolo Bonzini break;
41069e0a03cSPaolo Bonzini case 0xef:
41129a0af61SRichard Henderson hvf_handle_io(env_cpu(env), DX(env), &RAX(env), 1,
41229a0af61SRichard Henderson decode->operand_size, 1);
41369e0a03cSPaolo Bonzini break;
41469e0a03cSPaolo Bonzini default:
41569e0a03cSPaolo Bonzini VM_PANIC("Bad out opcode\n");
41669e0a03cSPaolo Bonzini break;
41769e0a03cSPaolo Bonzini }
4185d32173fSRoman Bolshakov env->eip += decode->len;
41969e0a03cSPaolo Bonzini }
42069e0a03cSPaolo Bonzini
exec_in(CPUX86State * env,struct x86_decode * decode)42136861198SPhilippe Mathieu-Daudé static void exec_in(CPUX86State *env, struct x86_decode *decode)
42269e0a03cSPaolo Bonzini {
423ff2de166SPaolo Bonzini target_ulong val = 0;
42469e0a03cSPaolo Bonzini switch (decode->opcode[0]) {
42569e0a03cSPaolo Bonzini case 0xe4:
42629a0af61SRichard Henderson hvf_handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
42769e0a03cSPaolo Bonzini break;
42869e0a03cSPaolo Bonzini case 0xe5:
42929a0af61SRichard Henderson hvf_handle_io(env_cpu(env), decode->op[0].val, &val, 0,
43029a0af61SRichard Henderson decode->operand_size, 1);
43169e0a03cSPaolo Bonzini if (decode->operand_size == 2) {
43269e0a03cSPaolo Bonzini AX(env) = val;
43369e0a03cSPaolo Bonzini } else {
43469e0a03cSPaolo Bonzini RAX(env) = (uint32_t)val;
43569e0a03cSPaolo Bonzini }
43669e0a03cSPaolo Bonzini break;
43769e0a03cSPaolo Bonzini case 0xec:
43829a0af61SRichard Henderson hvf_handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
43969e0a03cSPaolo Bonzini break;
44069e0a03cSPaolo Bonzini case 0xed:
44129a0af61SRichard Henderson hvf_handle_io(env_cpu(env), DX(env), &val, 0, decode->operand_size, 1);
44269e0a03cSPaolo Bonzini if (decode->operand_size == 2) {
44369e0a03cSPaolo Bonzini AX(env) = val;
44469e0a03cSPaolo Bonzini } else {
44569e0a03cSPaolo Bonzini RAX(env) = (uint32_t)val;
44669e0a03cSPaolo Bonzini }
44769e0a03cSPaolo Bonzini
44869e0a03cSPaolo Bonzini break;
44969e0a03cSPaolo Bonzini default:
45069e0a03cSPaolo Bonzini VM_PANIC("Bad in opcode\n");
45169e0a03cSPaolo Bonzini break;
45269e0a03cSPaolo Bonzini }
45369e0a03cSPaolo Bonzini
4545d32173fSRoman Bolshakov env->eip += decode->len;
45569e0a03cSPaolo Bonzini }
45669e0a03cSPaolo Bonzini
string_increment_reg(CPUX86State * env,int reg,struct x86_decode * decode)45736861198SPhilippe Mathieu-Daudé static inline void string_increment_reg(CPUX86State *env, int reg,
45869e0a03cSPaolo Bonzini struct x86_decode *decode)
45969e0a03cSPaolo Bonzini {
460ff2de166SPaolo Bonzini target_ulong val = read_reg(env, reg, decode->addressing_size);
461967f4da2SRoman Bolshakov if (env->eflags & DF_MASK) {
46269e0a03cSPaolo Bonzini val -= decode->operand_size;
46369e0a03cSPaolo Bonzini } else {
46469e0a03cSPaolo Bonzini val += decode->operand_size;
46569e0a03cSPaolo Bonzini }
46669e0a03cSPaolo Bonzini write_reg(env, reg, val, decode->addressing_size);
46769e0a03cSPaolo Bonzini }
46869e0a03cSPaolo Bonzini
string_rep(CPUX86State * env,struct x86_decode * decode,void (* func)(CPUX86State * env,struct x86_decode * ins),int rep)46936861198SPhilippe Mathieu-Daudé static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
47036861198SPhilippe Mathieu-Daudé void (*func)(CPUX86State *env,
47169e0a03cSPaolo Bonzini struct x86_decode *ins), int rep)
47269e0a03cSPaolo Bonzini {
473ff2de166SPaolo Bonzini target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
47469e0a03cSPaolo Bonzini while (rcx--) {
47569e0a03cSPaolo Bonzini func(env, decode);
4766701d81dSPaolo Bonzini write_reg(env, R_ECX, rcx, decode->addressing_size);
47769e0a03cSPaolo Bonzini if ((PREFIX_REP == rep) && !get_ZF(env)) {
47869e0a03cSPaolo Bonzini break;
47969e0a03cSPaolo Bonzini }
48069e0a03cSPaolo Bonzini if ((PREFIX_REPN == rep) && get_ZF(env)) {
48169e0a03cSPaolo Bonzini break;
48269e0a03cSPaolo Bonzini }
48369e0a03cSPaolo Bonzini }
48469e0a03cSPaolo Bonzini }
48569e0a03cSPaolo Bonzini
exec_ins_single(CPUX86State * env,struct x86_decode * decode)48636861198SPhilippe Mathieu-Daudé static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
48769e0a03cSPaolo Bonzini {
48829a0af61SRichard Henderson target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
48929a0af61SRichard Henderson decode->addressing_size, R_ES);
49069e0a03cSPaolo Bonzini
491fe76b09cSRoman Bolshakov hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 0,
49269e0a03cSPaolo Bonzini decode->operand_size, 1);
493fe76b09cSRoman Bolshakov vmx_write_mem(env_cpu(env), addr, env->hvf_mmio_buf,
49429a0af61SRichard Henderson decode->operand_size);
49569e0a03cSPaolo Bonzini
4966701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode);
49769e0a03cSPaolo Bonzini }
49869e0a03cSPaolo Bonzini
exec_ins(CPUX86State * env,struct x86_decode * decode)49936861198SPhilippe Mathieu-Daudé static void exec_ins(CPUX86State *env, struct x86_decode *decode)
50069e0a03cSPaolo Bonzini {
50169e0a03cSPaolo Bonzini if (decode->rep) {
50269e0a03cSPaolo Bonzini string_rep(env, decode, exec_ins_single, 0);
50369e0a03cSPaolo Bonzini } else {
50469e0a03cSPaolo Bonzini exec_ins_single(env, decode);
50569e0a03cSPaolo Bonzini }
50669e0a03cSPaolo Bonzini
5075d32173fSRoman Bolshakov env->eip += decode->len;
50869e0a03cSPaolo Bonzini }
50969e0a03cSPaolo Bonzini
exec_outs_single(CPUX86State * env,struct x86_decode * decode)51036861198SPhilippe Mathieu-Daudé static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
51169e0a03cSPaolo Bonzini {
512ff2de166SPaolo Bonzini target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
51369e0a03cSPaolo Bonzini
514fe76b09cSRoman Bolshakov vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, addr,
51529a0af61SRichard Henderson decode->operand_size);
516fe76b09cSRoman Bolshakov hvf_handle_io(env_cpu(env), DX(env), env->hvf_mmio_buf, 1,
51769e0a03cSPaolo Bonzini decode->operand_size, 1);
51869e0a03cSPaolo Bonzini
5196701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode);
52069e0a03cSPaolo Bonzini }
52169e0a03cSPaolo Bonzini
exec_outs(CPUX86State * env,struct x86_decode * decode)52236861198SPhilippe Mathieu-Daudé static void exec_outs(CPUX86State *env, struct x86_decode *decode)
52369e0a03cSPaolo Bonzini {
52469e0a03cSPaolo Bonzini if (decode->rep) {
52569e0a03cSPaolo Bonzini string_rep(env, decode, exec_outs_single, 0);
52669e0a03cSPaolo Bonzini } else {
52769e0a03cSPaolo Bonzini exec_outs_single(env, decode);
52869e0a03cSPaolo Bonzini }
52969e0a03cSPaolo Bonzini
5305d32173fSRoman Bolshakov env->eip += decode->len;
53169e0a03cSPaolo Bonzini }
53269e0a03cSPaolo Bonzini
exec_movs_single(CPUX86State * env,struct x86_decode * decode)53336861198SPhilippe Mathieu-Daudé static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
53469e0a03cSPaolo Bonzini {
535ff2de166SPaolo Bonzini target_ulong src_addr;
536ff2de166SPaolo Bonzini target_ulong dst_addr;
537ff2de166SPaolo Bonzini target_ulong val;
53869e0a03cSPaolo Bonzini
5396701d81dSPaolo Bonzini src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
54029a0af61SRichard Henderson dst_addr = linear_addr_size(env_cpu(env), RDI(env),
54129a0af61SRichard Henderson decode->addressing_size, R_ES);
54269e0a03cSPaolo Bonzini
54369e0a03cSPaolo Bonzini val = read_val_ext(env, src_addr, decode->operand_size);
54469e0a03cSPaolo Bonzini write_val_ext(env, dst_addr, val, decode->operand_size);
54569e0a03cSPaolo Bonzini
5466701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode);
5476701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode);
54869e0a03cSPaolo Bonzini }
54969e0a03cSPaolo Bonzini
exec_movs(CPUX86State * env,struct x86_decode * decode)55036861198SPhilippe Mathieu-Daudé static void exec_movs(CPUX86State *env, struct x86_decode *decode)
55169e0a03cSPaolo Bonzini {
55269e0a03cSPaolo Bonzini if (decode->rep) {
55369e0a03cSPaolo Bonzini string_rep(env, decode, exec_movs_single, 0);
55469e0a03cSPaolo Bonzini } else {
55569e0a03cSPaolo Bonzini exec_movs_single(env, decode);
55669e0a03cSPaolo Bonzini }
55769e0a03cSPaolo Bonzini
5585d32173fSRoman Bolshakov env->eip += decode->len;
55969e0a03cSPaolo Bonzini }
56069e0a03cSPaolo Bonzini
exec_cmps_single(CPUX86State * env,struct x86_decode * decode)56136861198SPhilippe Mathieu-Daudé static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
56269e0a03cSPaolo Bonzini {
563ff2de166SPaolo Bonzini target_ulong src_addr;
564ff2de166SPaolo Bonzini target_ulong dst_addr;
56569e0a03cSPaolo Bonzini
5666701d81dSPaolo Bonzini src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
56729a0af61SRichard Henderson dst_addr = linear_addr_size(env_cpu(env), RDI(env),
56829a0af61SRichard Henderson decode->addressing_size, R_ES);
56969e0a03cSPaolo Bonzini
57069e0a03cSPaolo Bonzini decode->op[0].type = X86_VAR_IMMEDIATE;
57169e0a03cSPaolo Bonzini decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
57269e0a03cSPaolo Bonzini decode->op[1].type = X86_VAR_IMMEDIATE;
57369e0a03cSPaolo Bonzini decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
57469e0a03cSPaolo Bonzini
575e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
57669e0a03cSPaolo Bonzini
5776701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode);
5786701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode);
57969e0a03cSPaolo Bonzini }
58069e0a03cSPaolo Bonzini
exec_cmps(CPUX86State * env,struct x86_decode * decode)58136861198SPhilippe Mathieu-Daudé static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
58269e0a03cSPaolo Bonzini {
58369e0a03cSPaolo Bonzini if (decode->rep) {
58469e0a03cSPaolo Bonzini string_rep(env, decode, exec_cmps_single, decode->rep);
58569e0a03cSPaolo Bonzini } else {
58669e0a03cSPaolo Bonzini exec_cmps_single(env, decode);
58769e0a03cSPaolo Bonzini }
5885d32173fSRoman Bolshakov env->eip += decode->len;
58969e0a03cSPaolo Bonzini }
59069e0a03cSPaolo Bonzini
59169e0a03cSPaolo Bonzini
exec_stos_single(CPUX86State * env,struct x86_decode * decode)59236861198SPhilippe Mathieu-Daudé static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
59369e0a03cSPaolo Bonzini {
594ff2de166SPaolo Bonzini target_ulong addr;
595ff2de166SPaolo Bonzini target_ulong val;
59669e0a03cSPaolo Bonzini
59729a0af61SRichard Henderson addr = linear_addr_size(env_cpu(env), RDI(env),
59829a0af61SRichard Henderson decode->addressing_size, R_ES);
5996701d81dSPaolo Bonzini val = read_reg(env, R_EAX, decode->operand_size);
60029a0af61SRichard Henderson vmx_write_mem(env_cpu(env), addr, &val, decode->operand_size);
60169e0a03cSPaolo Bonzini
6026701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode);
60369e0a03cSPaolo Bonzini }
60469e0a03cSPaolo Bonzini
60569e0a03cSPaolo Bonzini
exec_stos(CPUX86State * env,struct x86_decode * decode)60636861198SPhilippe Mathieu-Daudé static void exec_stos(CPUX86State *env, struct x86_decode *decode)
60769e0a03cSPaolo Bonzini {
60869e0a03cSPaolo Bonzini if (decode->rep) {
60969e0a03cSPaolo Bonzini string_rep(env, decode, exec_stos_single, 0);
61069e0a03cSPaolo Bonzini } else {
61169e0a03cSPaolo Bonzini exec_stos_single(env, decode);
61269e0a03cSPaolo Bonzini }
61369e0a03cSPaolo Bonzini
6145d32173fSRoman Bolshakov env->eip += decode->len;
61569e0a03cSPaolo Bonzini }
61669e0a03cSPaolo Bonzini
exec_scas_single(CPUX86State * env,struct x86_decode * decode)61736861198SPhilippe Mathieu-Daudé static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
61869e0a03cSPaolo Bonzini {
619ff2de166SPaolo Bonzini target_ulong addr;
62069e0a03cSPaolo Bonzini
62129a0af61SRichard Henderson addr = linear_addr_size(env_cpu(env), RDI(env),
62229a0af61SRichard Henderson decode->addressing_size, R_ES);
62369e0a03cSPaolo Bonzini decode->op[1].type = X86_VAR_IMMEDIATE;
62429a0af61SRichard Henderson vmx_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
62569e0a03cSPaolo Bonzini
626e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
6276701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode);
62869e0a03cSPaolo Bonzini }
62969e0a03cSPaolo Bonzini
exec_scas(CPUX86State * env,struct x86_decode * decode)63036861198SPhilippe Mathieu-Daudé static void exec_scas(CPUX86State *env, struct x86_decode *decode)
63169e0a03cSPaolo Bonzini {
63269e0a03cSPaolo Bonzini decode->op[0].type = X86_VAR_REG;
6336701d81dSPaolo Bonzini decode->op[0].reg = R_EAX;
63469e0a03cSPaolo Bonzini if (decode->rep) {
63569e0a03cSPaolo Bonzini string_rep(env, decode, exec_scas_single, decode->rep);
63669e0a03cSPaolo Bonzini } else {
63769e0a03cSPaolo Bonzini exec_scas_single(env, decode);
63869e0a03cSPaolo Bonzini }
63969e0a03cSPaolo Bonzini
6405d32173fSRoman Bolshakov env->eip += decode->len;
64169e0a03cSPaolo Bonzini }
64269e0a03cSPaolo Bonzini
exec_lods_single(CPUX86State * env,struct x86_decode * decode)64336861198SPhilippe Mathieu-Daudé static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
64469e0a03cSPaolo Bonzini {
645ff2de166SPaolo Bonzini target_ulong addr;
646ff2de166SPaolo Bonzini target_ulong val = 0;
64769e0a03cSPaolo Bonzini
6486701d81dSPaolo Bonzini addr = decode_linear_addr(env, decode, RSI(env), R_DS);
64929a0af61SRichard Henderson vmx_read_mem(env_cpu(env), &val, addr, decode->operand_size);
6506701d81dSPaolo Bonzini write_reg(env, R_EAX, val, decode->operand_size);
65169e0a03cSPaolo Bonzini
6526701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode);
65369e0a03cSPaolo Bonzini }
65469e0a03cSPaolo Bonzini
exec_lods(CPUX86State * env,struct x86_decode * decode)65536861198SPhilippe Mathieu-Daudé static void exec_lods(CPUX86State *env, struct x86_decode *decode)
65669e0a03cSPaolo Bonzini {
65769e0a03cSPaolo Bonzini if (decode->rep) {
65869e0a03cSPaolo Bonzini string_rep(env, decode, exec_lods_single, 0);
65969e0a03cSPaolo Bonzini } else {
66069e0a03cSPaolo Bonzini exec_lods_single(env, decode);
66169e0a03cSPaolo Bonzini }
66269e0a03cSPaolo Bonzini
6635d32173fSRoman Bolshakov env->eip += decode->len;
66469e0a03cSPaolo Bonzini }
66569e0a03cSPaolo Bonzini
raise_exception(CPUX86State * env,int exception_index,int error_code)6660e27f3a5SPhil Dennis-Jordan static void raise_exception(CPUX86State *env, int exception_index,
6670e27f3a5SPhil Dennis-Jordan int error_code)
6680e27f3a5SPhil Dennis-Jordan {
6690e27f3a5SPhil Dennis-Jordan env->exception_nr = exception_index;
6700e27f3a5SPhil Dennis-Jordan env->error_code = error_code;
6710e27f3a5SPhil Dennis-Jordan env->has_error_code = true;
6720e27f3a5SPhil Dennis-Jordan env->exception_injected = 1;
6730e27f3a5SPhil Dennis-Jordan }
6740e27f3a5SPhil Dennis-Jordan
simulate_rdmsr(CPUX86State * env)675a9e445dfSPhilippe Mathieu-Daudé void simulate_rdmsr(CPUX86State *env)
67669e0a03cSPaolo Bonzini {
6773152e954SPhilippe Mathieu-Daudé X86CPU *cpu = env_archcpu(env);
6785366a064SPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
67969e0a03cSPaolo Bonzini uint32_t msr = ECX(env);
68069e0a03cSPaolo Bonzini uint64_t val = 0;
68169e0a03cSPaolo Bonzini
68269e0a03cSPaolo Bonzini switch (msr) {
68369e0a03cSPaolo Bonzini case MSR_IA32_TSC:
6845366a064SPhilippe Mathieu-Daudé val = rdtscp() + rvmcs(cs->accel->fd, VMCS_TSC_OFFSET);
68569e0a03cSPaolo Bonzini break;
68669e0a03cSPaolo Bonzini case MSR_IA32_APICBASE:
6873152e954SPhilippe Mathieu-Daudé val = cpu_get_apic_base(cpu->apic_state);
68869e0a03cSPaolo Bonzini break;
6890e27f3a5SPhil Dennis-Jordan case MSR_APIC_START ... MSR_APIC_END: {
6900e27f3a5SPhil Dennis-Jordan int ret;
6910e27f3a5SPhil Dennis-Jordan int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
6920e27f3a5SPhil Dennis-Jordan
6930e27f3a5SPhil Dennis-Jordan ret = apic_msr_read(index, &val);
6940e27f3a5SPhil Dennis-Jordan if (ret < 0) {
6950e27f3a5SPhil Dennis-Jordan raise_exception(env, EXCP0D_GPF, 0);
6960e27f3a5SPhil Dennis-Jordan }
6970e27f3a5SPhil Dennis-Jordan
6980e27f3a5SPhil Dennis-Jordan break;
6990e27f3a5SPhil Dennis-Jordan }
70069e0a03cSPaolo Bonzini case MSR_IA32_UCODE_REV:
7013152e954SPhilippe Mathieu-Daudé val = cpu->ucode_rev;
70269e0a03cSPaolo Bonzini break;
70369e0a03cSPaolo Bonzini case MSR_EFER:
7045366a064SPhilippe Mathieu-Daudé val = rvmcs(cs->accel->fd, VMCS_GUEST_IA32_EFER);
70569e0a03cSPaolo Bonzini break;
70669e0a03cSPaolo Bonzini case MSR_FSBASE:
7075366a064SPhilippe Mathieu-Daudé val = rvmcs(cs->accel->fd, VMCS_GUEST_FS_BASE);
70869e0a03cSPaolo Bonzini break;
70969e0a03cSPaolo Bonzini case MSR_GSBASE:
7105366a064SPhilippe Mathieu-Daudé val = rvmcs(cs->accel->fd, VMCS_GUEST_GS_BASE);
71169e0a03cSPaolo Bonzini break;
71269e0a03cSPaolo Bonzini case MSR_KERNELGSBASE:
7135366a064SPhilippe Mathieu-Daudé val = rvmcs(cs->accel->fd, VMCS_HOST_FS_BASE);
71469e0a03cSPaolo Bonzini break;
71569e0a03cSPaolo Bonzini case MSR_STAR:
71669e0a03cSPaolo Bonzini abort();
71769e0a03cSPaolo Bonzini break;
71869e0a03cSPaolo Bonzini case MSR_LSTAR:
71969e0a03cSPaolo Bonzini abort();
72069e0a03cSPaolo Bonzini break;
72169e0a03cSPaolo Bonzini case MSR_CSTAR:
72269e0a03cSPaolo Bonzini abort();
72369e0a03cSPaolo Bonzini break;
72469e0a03cSPaolo Bonzini case MSR_IA32_MISC_ENABLE:
72569e0a03cSPaolo Bonzini val = env->msr_ia32_misc_enable;
72669e0a03cSPaolo Bonzini break;
72769e0a03cSPaolo Bonzini case MSR_MTRRphysBase(0):
72869e0a03cSPaolo Bonzini case MSR_MTRRphysBase(1):
72969e0a03cSPaolo Bonzini case MSR_MTRRphysBase(2):
73069e0a03cSPaolo Bonzini case MSR_MTRRphysBase(3):
73169e0a03cSPaolo Bonzini case MSR_MTRRphysBase(4):
73269e0a03cSPaolo Bonzini case MSR_MTRRphysBase(5):
73369e0a03cSPaolo Bonzini case MSR_MTRRphysBase(6):
73469e0a03cSPaolo Bonzini case MSR_MTRRphysBase(7):
73569e0a03cSPaolo Bonzini val = env->mtrr_var[(ECX(env) - MSR_MTRRphysBase(0)) / 2].base;
73669e0a03cSPaolo Bonzini break;
73769e0a03cSPaolo Bonzini case MSR_MTRRphysMask(0):
73869e0a03cSPaolo Bonzini case MSR_MTRRphysMask(1):
73969e0a03cSPaolo Bonzini case MSR_MTRRphysMask(2):
74069e0a03cSPaolo Bonzini case MSR_MTRRphysMask(3):
74169e0a03cSPaolo Bonzini case MSR_MTRRphysMask(4):
74269e0a03cSPaolo Bonzini case MSR_MTRRphysMask(5):
74369e0a03cSPaolo Bonzini case MSR_MTRRphysMask(6):
74469e0a03cSPaolo Bonzini case MSR_MTRRphysMask(7):
74569e0a03cSPaolo Bonzini val = env->mtrr_var[(ECX(env) - MSR_MTRRphysMask(0)) / 2].mask;
74669e0a03cSPaolo Bonzini break;
74769e0a03cSPaolo Bonzini case MSR_MTRRfix64K_00000:
74869e0a03cSPaolo Bonzini val = env->mtrr_fixed[0];
74969e0a03cSPaolo Bonzini break;
75069e0a03cSPaolo Bonzini case MSR_MTRRfix16K_80000:
75169e0a03cSPaolo Bonzini case MSR_MTRRfix16K_A0000:
75269e0a03cSPaolo Bonzini val = env->mtrr_fixed[ECX(env) - MSR_MTRRfix16K_80000 + 1];
75369e0a03cSPaolo Bonzini break;
75469e0a03cSPaolo Bonzini case MSR_MTRRfix4K_C0000:
75569e0a03cSPaolo Bonzini case MSR_MTRRfix4K_C8000:
75669e0a03cSPaolo Bonzini case MSR_MTRRfix4K_D0000:
75769e0a03cSPaolo Bonzini case MSR_MTRRfix4K_D8000:
75869e0a03cSPaolo Bonzini case MSR_MTRRfix4K_E0000:
75969e0a03cSPaolo Bonzini case MSR_MTRRfix4K_E8000:
76069e0a03cSPaolo Bonzini case MSR_MTRRfix4K_F0000:
76169e0a03cSPaolo Bonzini case MSR_MTRRfix4K_F8000:
76269e0a03cSPaolo Bonzini val = env->mtrr_fixed[ECX(env) - MSR_MTRRfix4K_C0000 + 3];
76369e0a03cSPaolo Bonzini break;
76469e0a03cSPaolo Bonzini case MSR_MTRRdefType:
76569e0a03cSPaolo Bonzini val = env->mtrr_deftype;
76669e0a03cSPaolo Bonzini break;
767027ac0cbSVladislav Yaroshchuk case MSR_CORE_THREAD_COUNT:
7685366a064SPhilippe Mathieu-Daudé val = cs->nr_threads * cs->nr_cores; /* thread count, bits 15..0 */
7695366a064SPhilippe Mathieu-Daudé val |= ((uint32_t)cs->nr_cores << 16); /* core count, bits 31..16 */
770027ac0cbSVladislav Yaroshchuk break;
77169e0a03cSPaolo Bonzini default:
77269e0a03cSPaolo Bonzini /* fprintf(stderr, "%s: unknown msr 0x%x\n", __func__, msr); */
77369e0a03cSPaolo Bonzini val = 0;
77469e0a03cSPaolo Bonzini break;
77569e0a03cSPaolo Bonzini }
77669e0a03cSPaolo Bonzini
77769e0a03cSPaolo Bonzini RAX(env) = (uint32_t)val;
77869e0a03cSPaolo Bonzini RDX(env) = (uint32_t)(val >> 32);
77969e0a03cSPaolo Bonzini }
78069e0a03cSPaolo Bonzini
exec_rdmsr(CPUX86State * env,struct x86_decode * decode)78136861198SPhilippe Mathieu-Daudé static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
78269e0a03cSPaolo Bonzini {
783a9e445dfSPhilippe Mathieu-Daudé simulate_rdmsr(env);
7845d32173fSRoman Bolshakov env->eip += decode->len;
78569e0a03cSPaolo Bonzini }
78669e0a03cSPaolo Bonzini
simulate_wrmsr(CPUX86State * env)787a9e445dfSPhilippe Mathieu-Daudé void simulate_wrmsr(CPUX86State *env)
78869e0a03cSPaolo Bonzini {
7893152e954SPhilippe Mathieu-Daudé X86CPU *cpu = env_archcpu(env);
7905366a064SPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
79169e0a03cSPaolo Bonzini uint32_t msr = ECX(env);
79269e0a03cSPaolo Bonzini uint64_t data = ((uint64_t)EDX(env) << 32) | EAX(env);
79369e0a03cSPaolo Bonzini
79469e0a03cSPaolo Bonzini switch (msr) {
79569e0a03cSPaolo Bonzini case MSR_IA32_TSC:
79669e0a03cSPaolo Bonzini break;
797*04858f95SPhil Dennis-Jordan case MSR_IA32_APICBASE: {
798*04858f95SPhil Dennis-Jordan int r;
799*04858f95SPhil Dennis-Jordan
800*04858f95SPhil Dennis-Jordan r = cpu_set_apic_base(cpu->apic_state, data);
801*04858f95SPhil Dennis-Jordan if (r < 0) {
802*04858f95SPhil Dennis-Jordan raise_exception(env, EXCP0D_GPF, 0);
803*04858f95SPhil Dennis-Jordan }
804*04858f95SPhil Dennis-Jordan
80569e0a03cSPaolo Bonzini break;
806*04858f95SPhil Dennis-Jordan }
8070e27f3a5SPhil Dennis-Jordan case MSR_APIC_START ... MSR_APIC_END: {
8080e27f3a5SPhil Dennis-Jordan int ret;
8090e27f3a5SPhil Dennis-Jordan int index = (uint32_t)env->regs[R_ECX] - MSR_APIC_START;
8100e27f3a5SPhil Dennis-Jordan
8110e27f3a5SPhil Dennis-Jordan ret = apic_msr_write(index, data);
8120e27f3a5SPhil Dennis-Jordan if (ret < 0) {
8130e27f3a5SPhil Dennis-Jordan raise_exception(env, EXCP0D_GPF, 0);
8140e27f3a5SPhil Dennis-Jordan }
8150e27f3a5SPhil Dennis-Jordan
8160e27f3a5SPhil Dennis-Jordan break;
8170e27f3a5SPhil Dennis-Jordan }
81869e0a03cSPaolo Bonzini case MSR_FSBASE:
8195366a064SPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_GUEST_FS_BASE, data);
82069e0a03cSPaolo Bonzini break;
82169e0a03cSPaolo Bonzini case MSR_GSBASE:
8225366a064SPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_GUEST_GS_BASE, data);
82369e0a03cSPaolo Bonzini break;
82469e0a03cSPaolo Bonzini case MSR_KERNELGSBASE:
8255366a064SPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_HOST_FS_BASE, data);
82669e0a03cSPaolo Bonzini break;
82769e0a03cSPaolo Bonzini case MSR_STAR:
82869e0a03cSPaolo Bonzini abort();
82969e0a03cSPaolo Bonzini break;
83069e0a03cSPaolo Bonzini case MSR_LSTAR:
83169e0a03cSPaolo Bonzini abort();
83269e0a03cSPaolo Bonzini break;
83369e0a03cSPaolo Bonzini case MSR_CSTAR:
83469e0a03cSPaolo Bonzini abort();
83569e0a03cSPaolo Bonzini break;
83669e0a03cSPaolo Bonzini case MSR_EFER:
8375366a064SPhilippe Mathieu-Daudé /*printf("new efer %llx\n", EFER(cs));*/
8385366a064SPhilippe Mathieu-Daudé wvmcs(cs->accel->fd, VMCS_GUEST_IA32_EFER, data);
8396701d81dSPaolo Bonzini if (data & MSR_EFER_NXE) {
8405366a064SPhilippe Mathieu-Daudé hv_vcpu_invalidate_tlb(cs->accel->fd);
84169e0a03cSPaolo Bonzini }
84269e0a03cSPaolo Bonzini break;
84369e0a03cSPaolo Bonzini case MSR_MTRRphysBase(0):
84469e0a03cSPaolo Bonzini case MSR_MTRRphysBase(1):
84569e0a03cSPaolo Bonzini case MSR_MTRRphysBase(2):
84669e0a03cSPaolo Bonzini case MSR_MTRRphysBase(3):
84769e0a03cSPaolo Bonzini case MSR_MTRRphysBase(4):
84869e0a03cSPaolo Bonzini case MSR_MTRRphysBase(5):
84969e0a03cSPaolo Bonzini case MSR_MTRRphysBase(6):
85069e0a03cSPaolo Bonzini case MSR_MTRRphysBase(7):
85169e0a03cSPaolo Bonzini env->mtrr_var[(ECX(env) - MSR_MTRRphysBase(0)) / 2].base = data;
85269e0a03cSPaolo Bonzini break;
85369e0a03cSPaolo Bonzini case MSR_MTRRphysMask(0):
85469e0a03cSPaolo Bonzini case MSR_MTRRphysMask(1):
85569e0a03cSPaolo Bonzini case MSR_MTRRphysMask(2):
85669e0a03cSPaolo Bonzini case MSR_MTRRphysMask(3):
85769e0a03cSPaolo Bonzini case MSR_MTRRphysMask(4):
85869e0a03cSPaolo Bonzini case MSR_MTRRphysMask(5):
85969e0a03cSPaolo Bonzini case MSR_MTRRphysMask(6):
86069e0a03cSPaolo Bonzini case MSR_MTRRphysMask(7):
86169e0a03cSPaolo Bonzini env->mtrr_var[(ECX(env) - MSR_MTRRphysMask(0)) / 2].mask = data;
86269e0a03cSPaolo Bonzini break;
86369e0a03cSPaolo Bonzini case MSR_MTRRfix64K_00000:
86469e0a03cSPaolo Bonzini env->mtrr_fixed[ECX(env) - MSR_MTRRfix64K_00000] = data;
86569e0a03cSPaolo Bonzini break;
86669e0a03cSPaolo Bonzini case MSR_MTRRfix16K_80000:
86769e0a03cSPaolo Bonzini case MSR_MTRRfix16K_A0000:
86869e0a03cSPaolo Bonzini env->mtrr_fixed[ECX(env) - MSR_MTRRfix16K_80000 + 1] = data;
86969e0a03cSPaolo Bonzini break;
87069e0a03cSPaolo Bonzini case MSR_MTRRfix4K_C0000:
87169e0a03cSPaolo Bonzini case MSR_MTRRfix4K_C8000:
87269e0a03cSPaolo Bonzini case MSR_MTRRfix4K_D0000:
87369e0a03cSPaolo Bonzini case MSR_MTRRfix4K_D8000:
87469e0a03cSPaolo Bonzini case MSR_MTRRfix4K_E0000:
87569e0a03cSPaolo Bonzini case MSR_MTRRfix4K_E8000:
87669e0a03cSPaolo Bonzini case MSR_MTRRfix4K_F0000:
87769e0a03cSPaolo Bonzini case MSR_MTRRfix4K_F8000:
87869e0a03cSPaolo Bonzini env->mtrr_fixed[ECX(env) - MSR_MTRRfix4K_C0000 + 3] = data;
87969e0a03cSPaolo Bonzini break;
88069e0a03cSPaolo Bonzini case MSR_MTRRdefType:
88169e0a03cSPaolo Bonzini env->mtrr_deftype = data;
88269e0a03cSPaolo Bonzini break;
88369e0a03cSPaolo Bonzini default:
88469e0a03cSPaolo Bonzini break;
88569e0a03cSPaolo Bonzini }
88669e0a03cSPaolo Bonzini
88769e0a03cSPaolo Bonzini /* Related to support known hypervisor interface */
88869e0a03cSPaolo Bonzini /* if (g_hypervisor_iface)
8895366a064SPhilippe Mathieu-Daudé g_hypervisor_iface->wrmsr_handler(cs, msr, data);
89069e0a03cSPaolo Bonzini
8915366a064SPhilippe Mathieu-Daudé printf("write msr %llx\n", RCX(cs));*/
89269e0a03cSPaolo Bonzini }
89369e0a03cSPaolo Bonzini
exec_wrmsr(CPUX86State * env,struct x86_decode * decode)89436861198SPhilippe Mathieu-Daudé static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
89569e0a03cSPaolo Bonzini {
896a9e445dfSPhilippe Mathieu-Daudé simulate_wrmsr(env);
8975d32173fSRoman Bolshakov env->eip += decode->len;
89869e0a03cSPaolo Bonzini }
89969e0a03cSPaolo Bonzini
90069e0a03cSPaolo Bonzini /*
90169e0a03cSPaolo Bonzini * flag:
90269e0a03cSPaolo Bonzini * 0 - bt, 1 - btc, 2 - bts, 3 - btr
90369e0a03cSPaolo Bonzini */
do_bt(CPUX86State * env,struct x86_decode * decode,int flag)90436861198SPhilippe Mathieu-Daudé static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
90569e0a03cSPaolo Bonzini {
90669e0a03cSPaolo Bonzini int32_t displacement;
90769e0a03cSPaolo Bonzini uint8_t index;
90869e0a03cSPaolo Bonzini bool cf;
90969e0a03cSPaolo Bonzini int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
91069e0a03cSPaolo Bonzini
91169e0a03cSPaolo Bonzini VM_PANIC_ON(decode->rex.rex);
91269e0a03cSPaolo Bonzini
91369e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, false, true, false);
91469e0a03cSPaolo Bonzini index = decode->op[1].val & mask;
91569e0a03cSPaolo Bonzini
91669e0a03cSPaolo Bonzini if (decode->op[0].type != X86_VAR_REG) {
91769e0a03cSPaolo Bonzini if (4 == decode->operand_size) {
91869e0a03cSPaolo Bonzini displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
91969e0a03cSPaolo Bonzini decode->op[0].ptr += 4 * displacement;
92069e0a03cSPaolo Bonzini } else if (2 == decode->operand_size) {
92169e0a03cSPaolo Bonzini displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
92269e0a03cSPaolo Bonzini decode->op[0].ptr += 2 * displacement;
92369e0a03cSPaolo Bonzini } else {
92469e0a03cSPaolo Bonzini VM_PANIC("bt 64bit\n");
92569e0a03cSPaolo Bonzini }
92669e0a03cSPaolo Bonzini }
92769e0a03cSPaolo Bonzini decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
92869e0a03cSPaolo Bonzini decode->operand_size);
92969e0a03cSPaolo Bonzini cf = (decode->op[0].val >> index) & 0x01;
93069e0a03cSPaolo Bonzini
93169e0a03cSPaolo Bonzini switch (flag) {
93269e0a03cSPaolo Bonzini case 0:
93369e0a03cSPaolo Bonzini set_CF(env, cf);
93469e0a03cSPaolo Bonzini return;
93569e0a03cSPaolo Bonzini case 1:
93669e0a03cSPaolo Bonzini decode->op[0].val ^= (1u << index);
93769e0a03cSPaolo Bonzini break;
93869e0a03cSPaolo Bonzini case 2:
93969e0a03cSPaolo Bonzini decode->op[0].val |= (1u << index);
94069e0a03cSPaolo Bonzini break;
94169e0a03cSPaolo Bonzini case 3:
94269e0a03cSPaolo Bonzini decode->op[0].val &= ~(1u << index);
94369e0a03cSPaolo Bonzini break;
94469e0a03cSPaolo Bonzini }
94569e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
94669e0a03cSPaolo Bonzini decode->operand_size);
94769e0a03cSPaolo Bonzini set_CF(env, cf);
94869e0a03cSPaolo Bonzini }
94969e0a03cSPaolo Bonzini
exec_bt(CPUX86State * env,struct x86_decode * decode)95036861198SPhilippe Mathieu-Daudé static void exec_bt(CPUX86State *env, struct x86_decode *decode)
95169e0a03cSPaolo Bonzini {
95269e0a03cSPaolo Bonzini do_bt(env, decode, 0);
9535d32173fSRoman Bolshakov env->eip += decode->len;
95469e0a03cSPaolo Bonzini }
95569e0a03cSPaolo Bonzini
exec_btc(CPUX86State * env,struct x86_decode * decode)95636861198SPhilippe Mathieu-Daudé static void exec_btc(CPUX86State *env, struct x86_decode *decode)
95769e0a03cSPaolo Bonzini {
95869e0a03cSPaolo Bonzini do_bt(env, decode, 1);
9595d32173fSRoman Bolshakov env->eip += decode->len;
96069e0a03cSPaolo Bonzini }
96169e0a03cSPaolo Bonzini
exec_btr(CPUX86State * env,struct x86_decode * decode)96236861198SPhilippe Mathieu-Daudé static void exec_btr(CPUX86State *env, struct x86_decode *decode)
96369e0a03cSPaolo Bonzini {
96469e0a03cSPaolo Bonzini do_bt(env, decode, 3);
9655d32173fSRoman Bolshakov env->eip += decode->len;
96669e0a03cSPaolo Bonzini }
96769e0a03cSPaolo Bonzini
exec_bts(CPUX86State * env,struct x86_decode * decode)96836861198SPhilippe Mathieu-Daudé static void exec_bts(CPUX86State *env, struct x86_decode *decode)
96969e0a03cSPaolo Bonzini {
97069e0a03cSPaolo Bonzini do_bt(env, decode, 2);
9715d32173fSRoman Bolshakov env->eip += decode->len;
97269e0a03cSPaolo Bonzini }
97369e0a03cSPaolo Bonzini
exec_shl(CPUX86State * env,struct x86_decode * decode)97436861198SPhilippe Mathieu-Daudé void exec_shl(CPUX86State *env, struct x86_decode *decode)
97569e0a03cSPaolo Bonzini {
97669e0a03cSPaolo Bonzini uint8_t count;
97769e0a03cSPaolo Bonzini int of = 0, cf = 0;
97869e0a03cSPaolo Bonzini
97969e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
98069e0a03cSPaolo Bonzini
98169e0a03cSPaolo Bonzini count = decode->op[1].val;
98269e0a03cSPaolo Bonzini count &= 0x1f; /* count is masked to 5 bits*/
98369e0a03cSPaolo Bonzini if (!count) {
98469e0a03cSPaolo Bonzini goto exit;
98569e0a03cSPaolo Bonzini }
98669e0a03cSPaolo Bonzini
98769e0a03cSPaolo Bonzini switch (decode->operand_size) {
98869e0a03cSPaolo Bonzini case 1:
98969e0a03cSPaolo Bonzini {
99069e0a03cSPaolo Bonzini uint8_t res = 0;
99169e0a03cSPaolo Bonzini if (count <= 8) {
99269e0a03cSPaolo Bonzini res = (decode->op[0].val << count);
99369e0a03cSPaolo Bonzini cf = (decode->op[0].val >> (8 - count)) & 0x1;
99469e0a03cSPaolo Bonzini of = cf ^ (res >> 7);
99569e0a03cSPaolo Bonzini }
99669e0a03cSPaolo Bonzini
99769e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 1);
998e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
99969e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
100069e0a03cSPaolo Bonzini break;
100169e0a03cSPaolo Bonzini }
100269e0a03cSPaolo Bonzini case 2:
100369e0a03cSPaolo Bonzini {
100469e0a03cSPaolo Bonzini uint16_t res = 0;
100569e0a03cSPaolo Bonzini
100669e0a03cSPaolo Bonzini /* from bochs */
100769e0a03cSPaolo Bonzini if (count <= 16) {
100869e0a03cSPaolo Bonzini res = (decode->op[0].val << count);
100969e0a03cSPaolo Bonzini cf = (decode->op[0].val >> (16 - count)) & 0x1;
101069e0a03cSPaolo Bonzini of = cf ^ (res >> 15); /* of = cf ^ result15 */
101169e0a03cSPaolo Bonzini }
101269e0a03cSPaolo Bonzini
101369e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 2);
1014e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
101569e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
101669e0a03cSPaolo Bonzini break;
101769e0a03cSPaolo Bonzini }
101869e0a03cSPaolo Bonzini case 4:
101969e0a03cSPaolo Bonzini {
102069e0a03cSPaolo Bonzini uint32_t res = decode->op[0].val << count;
102169e0a03cSPaolo Bonzini
102269e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 4);
1023e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
102469e0a03cSPaolo Bonzini cf = (decode->op[0].val >> (32 - count)) & 0x1;
102569e0a03cSPaolo Bonzini of = cf ^ (res >> 31); /* of = cf ^ result31 */
102669e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
102769e0a03cSPaolo Bonzini break;
102869e0a03cSPaolo Bonzini }
102969e0a03cSPaolo Bonzini default:
103069e0a03cSPaolo Bonzini abort();
103169e0a03cSPaolo Bonzini }
103269e0a03cSPaolo Bonzini
103369e0a03cSPaolo Bonzini exit:
103469e0a03cSPaolo Bonzini /* lflags_to_rflags(env); */
10355d32173fSRoman Bolshakov env->eip += decode->len;
103669e0a03cSPaolo Bonzini }
103769e0a03cSPaolo Bonzini
exec_movsx(CPUX86State * env,struct x86_decode * decode)103869e0a03cSPaolo Bonzini void exec_movsx(CPUX86State *env, struct x86_decode *decode)
103969e0a03cSPaolo Bonzini {
104069e0a03cSPaolo Bonzini int src_op_size;
104169e0a03cSPaolo Bonzini int op_size = decode->operand_size;
104269e0a03cSPaolo Bonzini
104369e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, false, false, false);
104469e0a03cSPaolo Bonzini
104569e0a03cSPaolo Bonzini if (0xbe == decode->opcode[1]) {
104669e0a03cSPaolo Bonzini src_op_size = 1;
104769e0a03cSPaolo Bonzini } else {
104869e0a03cSPaolo Bonzini src_op_size = 2;
104969e0a03cSPaolo Bonzini }
105069e0a03cSPaolo Bonzini
105169e0a03cSPaolo Bonzini decode->operand_size = src_op_size;
105269e0a03cSPaolo Bonzini calc_modrm_operand(env, decode, &decode->op[1]);
105369e0a03cSPaolo Bonzini decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
105469e0a03cSPaolo Bonzini src_op_size);
105569e0a03cSPaolo Bonzini
105669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
105769e0a03cSPaolo Bonzini
10585d32173fSRoman Bolshakov env->eip += decode->len;
105969e0a03cSPaolo Bonzini }
106069e0a03cSPaolo Bonzini
exec_ror(CPUX86State * env,struct x86_decode * decode)106136861198SPhilippe Mathieu-Daudé void exec_ror(CPUX86State *env, struct x86_decode *decode)
106269e0a03cSPaolo Bonzini {
106369e0a03cSPaolo Bonzini uint8_t count;
106469e0a03cSPaolo Bonzini
106569e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
106669e0a03cSPaolo Bonzini count = decode->op[1].val;
106769e0a03cSPaolo Bonzini
106869e0a03cSPaolo Bonzini switch (decode->operand_size) {
106969e0a03cSPaolo Bonzini case 1:
107069e0a03cSPaolo Bonzini {
107169e0a03cSPaolo Bonzini uint32_t bit6, bit7;
107269e0a03cSPaolo Bonzini uint8_t res;
107369e0a03cSPaolo Bonzini
107469e0a03cSPaolo Bonzini if ((count & 0x07) == 0) {
107569e0a03cSPaolo Bonzini if (count & 0x18) {
107669e0a03cSPaolo Bonzini bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
107769e0a03cSPaolo Bonzini bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
107869e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
107969e0a03cSPaolo Bonzini }
108069e0a03cSPaolo Bonzini } else {
108169e0a03cSPaolo Bonzini count &= 0x7; /* use only bottom 3 bits */
108269e0a03cSPaolo Bonzini res = ((uint8_t)decode->op[0].val >> count) |
108369e0a03cSPaolo Bonzini ((uint8_t)decode->op[0].val << (8 - count));
108469e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 1);
108569e0a03cSPaolo Bonzini bit6 = (res >> 6) & 1;
108669e0a03cSPaolo Bonzini bit7 = (res >> 7) & 1;
108769e0a03cSPaolo Bonzini /* set eflags: ROR count affects the following flags: C, O */
108869e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
108969e0a03cSPaolo Bonzini }
109069e0a03cSPaolo Bonzini break;
109169e0a03cSPaolo Bonzini }
109269e0a03cSPaolo Bonzini case 2:
109369e0a03cSPaolo Bonzini {
109469e0a03cSPaolo Bonzini uint32_t bit14, bit15;
109569e0a03cSPaolo Bonzini uint16_t res;
109669e0a03cSPaolo Bonzini
109769e0a03cSPaolo Bonzini if ((count & 0x0f) == 0) {
109869e0a03cSPaolo Bonzini if (count & 0x10) {
109969e0a03cSPaolo Bonzini bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
110069e0a03cSPaolo Bonzini bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
110169e0a03cSPaolo Bonzini /* of = result14 ^ result15 */
110269e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
110369e0a03cSPaolo Bonzini }
110469e0a03cSPaolo Bonzini } else {
110569e0a03cSPaolo Bonzini count &= 0x0f; /* use only 4 LSB's */
110669e0a03cSPaolo Bonzini res = ((uint16_t)decode->op[0].val >> count) |
110769e0a03cSPaolo Bonzini ((uint16_t)decode->op[0].val << (16 - count));
110869e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 2);
110969e0a03cSPaolo Bonzini
111069e0a03cSPaolo Bonzini bit14 = (res >> 14) & 1;
111169e0a03cSPaolo Bonzini bit15 = (res >> 15) & 1;
111269e0a03cSPaolo Bonzini /* of = result14 ^ result15 */
111369e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
111469e0a03cSPaolo Bonzini }
111569e0a03cSPaolo Bonzini break;
111669e0a03cSPaolo Bonzini }
111769e0a03cSPaolo Bonzini case 4:
111869e0a03cSPaolo Bonzini {
111969e0a03cSPaolo Bonzini uint32_t bit31, bit30;
112069e0a03cSPaolo Bonzini uint32_t res;
112169e0a03cSPaolo Bonzini
112269e0a03cSPaolo Bonzini count &= 0x1f;
112369e0a03cSPaolo Bonzini if (count) {
112469e0a03cSPaolo Bonzini res = ((uint32_t)decode->op[0].val >> count) |
112569e0a03cSPaolo Bonzini ((uint32_t)decode->op[0].val << (32 - count));
112669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 4);
112769e0a03cSPaolo Bonzini
112869e0a03cSPaolo Bonzini bit31 = (res >> 31) & 1;
112969e0a03cSPaolo Bonzini bit30 = (res >> 30) & 1;
113069e0a03cSPaolo Bonzini /* of = result30 ^ result31 */
113169e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
113269e0a03cSPaolo Bonzini }
113369e0a03cSPaolo Bonzini break;
113469e0a03cSPaolo Bonzini }
113569e0a03cSPaolo Bonzini }
11365d32173fSRoman Bolshakov env->eip += decode->len;
113769e0a03cSPaolo Bonzini }
113869e0a03cSPaolo Bonzini
exec_rol(CPUX86State * env,struct x86_decode * decode)113936861198SPhilippe Mathieu-Daudé void exec_rol(CPUX86State *env, struct x86_decode *decode)
114069e0a03cSPaolo Bonzini {
114169e0a03cSPaolo Bonzini uint8_t count;
114269e0a03cSPaolo Bonzini
114369e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
114469e0a03cSPaolo Bonzini count = decode->op[1].val;
114569e0a03cSPaolo Bonzini
114669e0a03cSPaolo Bonzini switch (decode->operand_size) {
114769e0a03cSPaolo Bonzini case 1:
114869e0a03cSPaolo Bonzini {
114969e0a03cSPaolo Bonzini uint32_t bit0, bit7;
115069e0a03cSPaolo Bonzini uint8_t res;
115169e0a03cSPaolo Bonzini
115269e0a03cSPaolo Bonzini if ((count & 0x07) == 0) {
115369e0a03cSPaolo Bonzini if (count & 0x18) {
115469e0a03cSPaolo Bonzini bit0 = ((uint8_t)decode->op[0].val & 1);
115569e0a03cSPaolo Bonzini bit7 = ((uint8_t)decode->op[0].val >> 7);
115669e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
115769e0a03cSPaolo Bonzini }
115869e0a03cSPaolo Bonzini } else {
115969e0a03cSPaolo Bonzini count &= 0x7; /* use only lowest 3 bits */
116069e0a03cSPaolo Bonzini res = ((uint8_t)decode->op[0].val << count) |
116169e0a03cSPaolo Bonzini ((uint8_t)decode->op[0].val >> (8 - count));
116269e0a03cSPaolo Bonzini
116369e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 1);
116469e0a03cSPaolo Bonzini /* set eflags:
116569e0a03cSPaolo Bonzini * ROL count affects the following flags: C, O
116669e0a03cSPaolo Bonzini */
116769e0a03cSPaolo Bonzini bit0 = (res & 1);
116869e0a03cSPaolo Bonzini bit7 = (res >> 7);
116969e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
117069e0a03cSPaolo Bonzini }
117169e0a03cSPaolo Bonzini break;
117269e0a03cSPaolo Bonzini }
117369e0a03cSPaolo Bonzini case 2:
117469e0a03cSPaolo Bonzini {
117569e0a03cSPaolo Bonzini uint32_t bit0, bit15;
117669e0a03cSPaolo Bonzini uint16_t res;
117769e0a03cSPaolo Bonzini
117869e0a03cSPaolo Bonzini if ((count & 0x0f) == 0) {
117969e0a03cSPaolo Bonzini if (count & 0x10) {
118069e0a03cSPaolo Bonzini bit0 = ((uint16_t)decode->op[0].val & 0x1);
118169e0a03cSPaolo Bonzini bit15 = ((uint16_t)decode->op[0].val >> 15);
118269e0a03cSPaolo Bonzini /* of = cf ^ result15 */
118369e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
118469e0a03cSPaolo Bonzini }
118569e0a03cSPaolo Bonzini } else {
118669e0a03cSPaolo Bonzini count &= 0x0f; /* only use bottom 4 bits */
118769e0a03cSPaolo Bonzini res = ((uint16_t)decode->op[0].val << count) |
118869e0a03cSPaolo Bonzini ((uint16_t)decode->op[0].val >> (16 - count));
118969e0a03cSPaolo Bonzini
119069e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 2);
119169e0a03cSPaolo Bonzini bit0 = (res & 0x1);
119269e0a03cSPaolo Bonzini bit15 = (res >> 15);
119369e0a03cSPaolo Bonzini /* of = cf ^ result15 */
119469e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
119569e0a03cSPaolo Bonzini }
119669e0a03cSPaolo Bonzini break;
119769e0a03cSPaolo Bonzini }
119869e0a03cSPaolo Bonzini case 4:
119969e0a03cSPaolo Bonzini {
120069e0a03cSPaolo Bonzini uint32_t bit0, bit31;
120169e0a03cSPaolo Bonzini uint32_t res;
120269e0a03cSPaolo Bonzini
120369e0a03cSPaolo Bonzini count &= 0x1f;
120469e0a03cSPaolo Bonzini if (count) {
120569e0a03cSPaolo Bonzini res = ((uint32_t)decode->op[0].val << count) |
120669e0a03cSPaolo Bonzini ((uint32_t)decode->op[0].val >> (32 - count));
120769e0a03cSPaolo Bonzini
120869e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 4);
120969e0a03cSPaolo Bonzini bit0 = (res & 0x1);
121069e0a03cSPaolo Bonzini bit31 = (res >> 31);
121169e0a03cSPaolo Bonzini /* of = cf ^ result31 */
121269e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
121369e0a03cSPaolo Bonzini }
121469e0a03cSPaolo Bonzini break;
121569e0a03cSPaolo Bonzini }
121669e0a03cSPaolo Bonzini }
12175d32173fSRoman Bolshakov env->eip += decode->len;
121869e0a03cSPaolo Bonzini }
121969e0a03cSPaolo Bonzini
122069e0a03cSPaolo Bonzini
exec_rcl(CPUX86State * env,struct x86_decode * decode)122136861198SPhilippe Mathieu-Daudé void exec_rcl(CPUX86State *env, struct x86_decode *decode)
122269e0a03cSPaolo Bonzini {
122369e0a03cSPaolo Bonzini uint8_t count;
122469e0a03cSPaolo Bonzini int of = 0, cf = 0;
122569e0a03cSPaolo Bonzini
122669e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
122769e0a03cSPaolo Bonzini count = decode->op[1].val & 0x1f;
122869e0a03cSPaolo Bonzini
122969e0a03cSPaolo Bonzini switch (decode->operand_size) {
123069e0a03cSPaolo Bonzini case 1:
123169e0a03cSPaolo Bonzini {
123269e0a03cSPaolo Bonzini uint8_t op1_8 = decode->op[0].val;
123369e0a03cSPaolo Bonzini uint8_t res;
123469e0a03cSPaolo Bonzini count %= 9;
123569e0a03cSPaolo Bonzini if (!count) {
123669e0a03cSPaolo Bonzini break;
123769e0a03cSPaolo Bonzini }
123869e0a03cSPaolo Bonzini
123969e0a03cSPaolo Bonzini if (1 == count) {
124069e0a03cSPaolo Bonzini res = (op1_8 << 1) | get_CF(env);
124169e0a03cSPaolo Bonzini } else {
124269e0a03cSPaolo Bonzini res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
124369e0a03cSPaolo Bonzini (op1_8 >> (9 - count));
124469e0a03cSPaolo Bonzini }
124569e0a03cSPaolo Bonzini
124669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 1);
124769e0a03cSPaolo Bonzini
124869e0a03cSPaolo Bonzini cf = (op1_8 >> (8 - count)) & 0x01;
124969e0a03cSPaolo Bonzini of = cf ^ (res >> 7); /* of = cf ^ result7 */
125069e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
125169e0a03cSPaolo Bonzini break;
125269e0a03cSPaolo Bonzini }
125369e0a03cSPaolo Bonzini case 2:
125469e0a03cSPaolo Bonzini {
125569e0a03cSPaolo Bonzini uint16_t res;
125669e0a03cSPaolo Bonzini uint16_t op1_16 = decode->op[0].val;
125769e0a03cSPaolo Bonzini
125869e0a03cSPaolo Bonzini count %= 17;
125969e0a03cSPaolo Bonzini if (!count) {
126069e0a03cSPaolo Bonzini break;
126169e0a03cSPaolo Bonzini }
126269e0a03cSPaolo Bonzini
126369e0a03cSPaolo Bonzini if (1 == count) {
126469e0a03cSPaolo Bonzini res = (op1_16 << 1) | get_CF(env);
126569e0a03cSPaolo Bonzini } else if (count == 16) {
126669e0a03cSPaolo Bonzini res = (get_CF(env) << 15) | (op1_16 >> 1);
126769e0a03cSPaolo Bonzini } else { /* 2..15 */
126869e0a03cSPaolo Bonzini res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
126969e0a03cSPaolo Bonzini (op1_16 >> (17 - count));
127069e0a03cSPaolo Bonzini }
127169e0a03cSPaolo Bonzini
127269e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 2);
127369e0a03cSPaolo Bonzini
127469e0a03cSPaolo Bonzini cf = (op1_16 >> (16 - count)) & 0x1;
127569e0a03cSPaolo Bonzini of = cf ^ (res >> 15); /* of = cf ^ result15 */
127669e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
127769e0a03cSPaolo Bonzini break;
127869e0a03cSPaolo Bonzini }
127969e0a03cSPaolo Bonzini case 4:
128069e0a03cSPaolo Bonzini {
128169e0a03cSPaolo Bonzini uint32_t res;
128269e0a03cSPaolo Bonzini uint32_t op1_32 = decode->op[0].val;
128369e0a03cSPaolo Bonzini
128469e0a03cSPaolo Bonzini if (!count) {
128569e0a03cSPaolo Bonzini break;
128669e0a03cSPaolo Bonzini }
128769e0a03cSPaolo Bonzini
128869e0a03cSPaolo Bonzini if (1 == count) {
128969e0a03cSPaolo Bonzini res = (op1_32 << 1) | get_CF(env);
129069e0a03cSPaolo Bonzini } else {
129169e0a03cSPaolo Bonzini res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
129269e0a03cSPaolo Bonzini (op1_32 >> (33 - count));
129369e0a03cSPaolo Bonzini }
129469e0a03cSPaolo Bonzini
129569e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 4);
129669e0a03cSPaolo Bonzini
129769e0a03cSPaolo Bonzini cf = (op1_32 >> (32 - count)) & 0x1;
129869e0a03cSPaolo Bonzini of = cf ^ (res >> 31); /* of = cf ^ result31 */
129969e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
130069e0a03cSPaolo Bonzini break;
130169e0a03cSPaolo Bonzini }
130269e0a03cSPaolo Bonzini }
13035d32173fSRoman Bolshakov env->eip += decode->len;
130469e0a03cSPaolo Bonzini }
130569e0a03cSPaolo Bonzini
exec_rcr(CPUX86State * env,struct x86_decode * decode)130636861198SPhilippe Mathieu-Daudé void exec_rcr(CPUX86State *env, struct x86_decode *decode)
130769e0a03cSPaolo Bonzini {
130869e0a03cSPaolo Bonzini uint8_t count;
130969e0a03cSPaolo Bonzini int of = 0, cf = 0;
131069e0a03cSPaolo Bonzini
131169e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
131269e0a03cSPaolo Bonzini count = decode->op[1].val & 0x1f;
131369e0a03cSPaolo Bonzini
131469e0a03cSPaolo Bonzini switch (decode->operand_size) {
131569e0a03cSPaolo Bonzini case 1:
131669e0a03cSPaolo Bonzini {
131769e0a03cSPaolo Bonzini uint8_t op1_8 = decode->op[0].val;
131869e0a03cSPaolo Bonzini uint8_t res;
131969e0a03cSPaolo Bonzini
132069e0a03cSPaolo Bonzini count %= 9;
132169e0a03cSPaolo Bonzini if (!count) {
132269e0a03cSPaolo Bonzini break;
132369e0a03cSPaolo Bonzini }
132469e0a03cSPaolo Bonzini res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
132569e0a03cSPaolo Bonzini (op1_8 << (9 - count));
132669e0a03cSPaolo Bonzini
132769e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 1);
132869e0a03cSPaolo Bonzini
132969e0a03cSPaolo Bonzini cf = (op1_8 >> (count - 1)) & 0x1;
133069e0a03cSPaolo Bonzini of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
133169e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
133269e0a03cSPaolo Bonzini break;
133369e0a03cSPaolo Bonzini }
133469e0a03cSPaolo Bonzini case 2:
133569e0a03cSPaolo Bonzini {
133669e0a03cSPaolo Bonzini uint16_t op1_16 = decode->op[0].val;
133769e0a03cSPaolo Bonzini uint16_t res;
133869e0a03cSPaolo Bonzini
133969e0a03cSPaolo Bonzini count %= 17;
134069e0a03cSPaolo Bonzini if (!count) {
134169e0a03cSPaolo Bonzini break;
134269e0a03cSPaolo Bonzini }
134369e0a03cSPaolo Bonzini res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
134469e0a03cSPaolo Bonzini (op1_16 << (17 - count));
134569e0a03cSPaolo Bonzini
134669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 2);
134769e0a03cSPaolo Bonzini
134869e0a03cSPaolo Bonzini cf = (op1_16 >> (count - 1)) & 0x1;
134969e0a03cSPaolo Bonzini of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
135069e0a03cSPaolo Bonzini result14 */
135169e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
135269e0a03cSPaolo Bonzini break;
135369e0a03cSPaolo Bonzini }
135469e0a03cSPaolo Bonzini case 4:
135569e0a03cSPaolo Bonzini {
135669e0a03cSPaolo Bonzini uint32_t res;
135769e0a03cSPaolo Bonzini uint32_t op1_32 = decode->op[0].val;
135869e0a03cSPaolo Bonzini
135969e0a03cSPaolo Bonzini if (!count) {
136069e0a03cSPaolo Bonzini break;
136169e0a03cSPaolo Bonzini }
136269e0a03cSPaolo Bonzini
136369e0a03cSPaolo Bonzini if (1 == count) {
136469e0a03cSPaolo Bonzini res = (op1_32 >> 1) | (get_CF(env) << 31);
136569e0a03cSPaolo Bonzini } else {
136669e0a03cSPaolo Bonzini res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
136769e0a03cSPaolo Bonzini (op1_32 << (33 - count));
136869e0a03cSPaolo Bonzini }
136969e0a03cSPaolo Bonzini
137069e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, res, 4);
137169e0a03cSPaolo Bonzini
137269e0a03cSPaolo Bonzini cf = (op1_32 >> (count - 1)) & 0x1;
137369e0a03cSPaolo Bonzini of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
137469e0a03cSPaolo Bonzini SET_FLAGS_OxxxxC(env, of, cf);
137569e0a03cSPaolo Bonzini break;
137669e0a03cSPaolo Bonzini }
137769e0a03cSPaolo Bonzini }
13785d32173fSRoman Bolshakov env->eip += decode->len;
137969e0a03cSPaolo Bonzini }
138069e0a03cSPaolo Bonzini
exec_xchg(CPUX86State * env,struct x86_decode * decode)138136861198SPhilippe Mathieu-Daudé static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
138269e0a03cSPaolo Bonzini {
138369e0a03cSPaolo Bonzini fetch_operands(env, decode, 2, true, true, false);
138469e0a03cSPaolo Bonzini
138569e0a03cSPaolo Bonzini write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
138669e0a03cSPaolo Bonzini decode->operand_size);
138769e0a03cSPaolo Bonzini write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
138869e0a03cSPaolo Bonzini decode->operand_size);
138969e0a03cSPaolo Bonzini
13905d32173fSRoman Bolshakov env->eip += decode->len;
139169e0a03cSPaolo Bonzini }
139269e0a03cSPaolo Bonzini
exec_xadd(CPUX86State * env,struct x86_decode * decode)139336861198SPhilippe Mathieu-Daudé static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
139469e0a03cSPaolo Bonzini {
1395e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
139669e0a03cSPaolo Bonzini write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
139769e0a03cSPaolo Bonzini decode->operand_size);
139869e0a03cSPaolo Bonzini
13995d32173fSRoman Bolshakov env->eip += decode->len;
140069e0a03cSPaolo Bonzini }
140169e0a03cSPaolo Bonzini
140269e0a03cSPaolo Bonzini static struct cmd_handler {
140369e0a03cSPaolo Bonzini enum x86_decode_cmd cmd;
140436861198SPhilippe Mathieu-Daudé void (*handler)(CPUX86State *env, struct x86_decode *ins);
140569e0a03cSPaolo Bonzini } handlers[] = {
140669e0a03cSPaolo Bonzini {X86_DECODE_CMD_INVL, NULL,},
140769e0a03cSPaolo Bonzini {X86_DECODE_CMD_MOV, exec_mov},
140869e0a03cSPaolo Bonzini {X86_DECODE_CMD_ADD, exec_add},
140969e0a03cSPaolo Bonzini {X86_DECODE_CMD_OR, exec_or},
141069e0a03cSPaolo Bonzini {X86_DECODE_CMD_ADC, exec_adc},
141169e0a03cSPaolo Bonzini {X86_DECODE_CMD_SBB, exec_sbb},
141269e0a03cSPaolo Bonzini {X86_DECODE_CMD_AND, exec_and},
141369e0a03cSPaolo Bonzini {X86_DECODE_CMD_SUB, exec_sub},
141469e0a03cSPaolo Bonzini {X86_DECODE_CMD_NEG, exec_neg},
141569e0a03cSPaolo Bonzini {X86_DECODE_CMD_XOR, exec_xor},
141669e0a03cSPaolo Bonzini {X86_DECODE_CMD_CMP, exec_cmp},
141769e0a03cSPaolo Bonzini {X86_DECODE_CMD_INC, exec_inc},
141869e0a03cSPaolo Bonzini {X86_DECODE_CMD_DEC, exec_dec},
141969e0a03cSPaolo Bonzini {X86_DECODE_CMD_TST, exec_tst},
142069e0a03cSPaolo Bonzini {X86_DECODE_CMD_NOT, exec_not},
142169e0a03cSPaolo Bonzini {X86_DECODE_CMD_MOVZX, exec_movzx},
142269e0a03cSPaolo Bonzini {X86_DECODE_CMD_OUT, exec_out},
142369e0a03cSPaolo Bonzini {X86_DECODE_CMD_IN, exec_in},
142469e0a03cSPaolo Bonzini {X86_DECODE_CMD_INS, exec_ins},
142569e0a03cSPaolo Bonzini {X86_DECODE_CMD_OUTS, exec_outs},
142669e0a03cSPaolo Bonzini {X86_DECODE_CMD_RDMSR, exec_rdmsr},
142769e0a03cSPaolo Bonzini {X86_DECODE_CMD_WRMSR, exec_wrmsr},
142869e0a03cSPaolo Bonzini {X86_DECODE_CMD_BT, exec_bt},
142969e0a03cSPaolo Bonzini {X86_DECODE_CMD_BTR, exec_btr},
143069e0a03cSPaolo Bonzini {X86_DECODE_CMD_BTC, exec_btc},
143169e0a03cSPaolo Bonzini {X86_DECODE_CMD_BTS, exec_bts},
143269e0a03cSPaolo Bonzini {X86_DECODE_CMD_SHL, exec_shl},
143369e0a03cSPaolo Bonzini {X86_DECODE_CMD_ROL, exec_rol},
143469e0a03cSPaolo Bonzini {X86_DECODE_CMD_ROR, exec_ror},
143569e0a03cSPaolo Bonzini {X86_DECODE_CMD_RCR, exec_rcr},
143669e0a03cSPaolo Bonzini {X86_DECODE_CMD_RCL, exec_rcl},
143769e0a03cSPaolo Bonzini /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
143869e0a03cSPaolo Bonzini {X86_DECODE_CMD_MOVS, exec_movs},
143969e0a03cSPaolo Bonzini {X86_DECODE_CMD_CMPS, exec_cmps},
144069e0a03cSPaolo Bonzini {X86_DECODE_CMD_STOS, exec_stos},
144169e0a03cSPaolo Bonzini {X86_DECODE_CMD_SCAS, exec_scas},
144269e0a03cSPaolo Bonzini {X86_DECODE_CMD_LODS, exec_lods},
144369e0a03cSPaolo Bonzini {X86_DECODE_CMD_MOVSX, exec_movsx},
144469e0a03cSPaolo Bonzini {X86_DECODE_CMD_XCHG, exec_xchg},
144569e0a03cSPaolo Bonzini {X86_DECODE_CMD_XADD, exec_xadd},
144669e0a03cSPaolo Bonzini };
144769e0a03cSPaolo Bonzini
144869e0a03cSPaolo Bonzini static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
144969e0a03cSPaolo Bonzini
init_cmd_handler(void)14500e4e622eSPhil Dennis-Jordan static void init_cmd_handler(void)
145169e0a03cSPaolo Bonzini {
145269e0a03cSPaolo Bonzini int i;
145369e0a03cSPaolo Bonzini for (i = 0; i < ARRAY_SIZE(handlers); i++) {
145469e0a03cSPaolo Bonzini _cmd_handler[handlers[i].cmd] = handlers[i];
145569e0a03cSPaolo Bonzini }
145669e0a03cSPaolo Bonzini }
145769e0a03cSPaolo Bonzini
load_regs(CPUState * cs)14585366a064SPhilippe Mathieu-Daudé void load_regs(CPUState *cs)
145969e0a03cSPaolo Bonzini {
14603152e954SPhilippe Mathieu-Daudé X86CPU *cpu = X86_CPU(cs);
14613152e954SPhilippe Mathieu-Daudé CPUX86State *env = &cpu->env;
146269e0a03cSPaolo Bonzini
146369e0a03cSPaolo Bonzini int i = 0;
14645366a064SPhilippe Mathieu-Daudé RRX(env, R_EAX) = rreg(cs->accel->fd, HV_X86_RAX);
14655366a064SPhilippe Mathieu-Daudé RRX(env, R_EBX) = rreg(cs->accel->fd, HV_X86_RBX);
14665366a064SPhilippe Mathieu-Daudé RRX(env, R_ECX) = rreg(cs->accel->fd, HV_X86_RCX);
14675366a064SPhilippe Mathieu-Daudé RRX(env, R_EDX) = rreg(cs->accel->fd, HV_X86_RDX);
14685366a064SPhilippe Mathieu-Daudé RRX(env, R_ESI) = rreg(cs->accel->fd, HV_X86_RSI);
14695366a064SPhilippe Mathieu-Daudé RRX(env, R_EDI) = rreg(cs->accel->fd, HV_X86_RDI);
14705366a064SPhilippe Mathieu-Daudé RRX(env, R_ESP) = rreg(cs->accel->fd, HV_X86_RSP);
14715366a064SPhilippe Mathieu-Daudé RRX(env, R_EBP) = rreg(cs->accel->fd, HV_X86_RBP);
147269e0a03cSPaolo Bonzini for (i = 8; i < 16; i++) {
14735366a064SPhilippe Mathieu-Daudé RRX(env, i) = rreg(cs->accel->fd, HV_X86_RAX + i);
147469e0a03cSPaolo Bonzini }
147569e0a03cSPaolo Bonzini
14765366a064SPhilippe Mathieu-Daudé env->eflags = rreg(cs->accel->fd, HV_X86_RFLAGS);
147769e0a03cSPaolo Bonzini rflags_to_lflags(env);
14785366a064SPhilippe Mathieu-Daudé env->eip = rreg(cs->accel->fd, HV_X86_RIP);
147969e0a03cSPaolo Bonzini }
148069e0a03cSPaolo Bonzini
store_regs(CPUState * cs)14815366a064SPhilippe Mathieu-Daudé void store_regs(CPUState *cs)
148269e0a03cSPaolo Bonzini {
14833152e954SPhilippe Mathieu-Daudé X86CPU *cpu = X86_CPU(cs);
14843152e954SPhilippe Mathieu-Daudé CPUX86State *env = &cpu->env;
148569e0a03cSPaolo Bonzini
148669e0a03cSPaolo Bonzini int i = 0;
14875366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RAX, RAX(env));
14885366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RBX, RBX(env));
14895366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RCX, RCX(env));
14905366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RDX, RDX(env));
14915366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RSI, RSI(env));
14925366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RDI, RDI(env));
14935366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RBP, RBP(env));
14945366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RSP, RSP(env));
149569e0a03cSPaolo Bonzini for (i = 8; i < 16; i++) {
14965366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RAX + i, RRX(env, i));
149769e0a03cSPaolo Bonzini }
149869e0a03cSPaolo Bonzini
149969e0a03cSPaolo Bonzini lflags_to_rflags(env);
15005366a064SPhilippe Mathieu-Daudé wreg(cs->accel->fd, HV_X86_RFLAGS, env->eflags);
15015366a064SPhilippe Mathieu-Daudé macvm_set_rip(cs, env->eip);
150269e0a03cSPaolo Bonzini }
150369e0a03cSPaolo Bonzini
exec_instruction(CPUX86State * env,struct x86_decode * ins)150436861198SPhilippe Mathieu-Daudé bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
150569e0a03cSPaolo Bonzini {
15065366a064SPhilippe Mathieu-Daudé /*if (hvf_vcpu_id(cs))
15075366a064SPhilippe Mathieu-Daudé printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cs), env->eip,
150869e0a03cSPaolo Bonzini decode_cmd_to_string(ins->cmd));*/
150969e0a03cSPaolo Bonzini
151069e0a03cSPaolo Bonzini if (!_cmd_handler[ins->cmd].handler) {
15115d32173fSRoman Bolshakov printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip,
151269e0a03cSPaolo Bonzini ins->cmd, ins->opcode[0],
151369e0a03cSPaolo Bonzini ins->opcode_len > 1 ? ins->opcode[1] : 0);
15145d32173fSRoman Bolshakov env->eip += ins->len;
151569e0a03cSPaolo Bonzini return true;
151669e0a03cSPaolo Bonzini }
151769e0a03cSPaolo Bonzini
151869e0a03cSPaolo Bonzini _cmd_handler[ins->cmd].handler(env, ins);
151969e0a03cSPaolo Bonzini return true;
152069e0a03cSPaolo Bonzini }
152169e0a03cSPaolo Bonzini
init_emu(void)15220e4e622eSPhil Dennis-Jordan void init_emu(void)
152369e0a03cSPaolo Bonzini {
152469e0a03cSPaolo Bonzini init_cmd_handler();
152569e0a03cSPaolo Bonzini }
1526