1c97d6d2cSSergio Andres Gomez Del Real /* 2c97d6d2cSSergio Andres Gomez Del Real * Copyright (C) 2016 Veertu Inc, 3c97d6d2cSSergio Andres Gomez Del Real * Copyright (C) 2017 Google Inc, 4c97d6d2cSSergio Andres Gomez Del Real * 5c97d6d2cSSergio Andres Gomez Del Real * This program is free software; you can redistribute it and/or 6996feed4SSergio Andres Gomez Del Real * modify it under the terms of the GNU Lesser General Public 7996feed4SSergio Andres Gomez Del Real * License as published by the Free Software Foundation; either 88af82b8eSChetan Pant * version 2.1 of the License, or (at your option) any later version. 9c97d6d2cSSergio Andres Gomez Del Real * 10c97d6d2cSSergio Andres Gomez Del Real * This program is distributed in the hope that it will be useful, 11c97d6d2cSSergio Andres Gomez Del Real * but WITHOUT ANY WARRANTY; without even the implied warranty of 12996feed4SSergio Andres Gomez Del Real * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13996feed4SSergio Andres Gomez Del Real * Lesser General Public License for more details. 14c97d6d2cSSergio Andres Gomez Del Real * 15996feed4SSergio Andres Gomez Del Real * You should have received a copy of the GNU Lesser General Public 16996feed4SSergio Andres Gomez Del Real * License along with this program; if not, see <http://www.gnu.org/licenses/>. 17c97d6d2cSSergio Andres Gomez Del Real */ 18c97d6d2cSSergio Andres Gomez Del Real 19c97d6d2cSSergio Andres Gomez Del Real ///////////////////////////////////////////////////////////////////////// 20c97d6d2cSSergio Andres Gomez Del Real // 21c97d6d2cSSergio Andres Gomez Del Real // Copyright (C) 2001-2012 The Bochs Project 22c97d6d2cSSergio Andres Gomez Del Real // 23c97d6d2cSSergio Andres Gomez Del Real // This library is free software; you can redistribute it and/or 24c97d6d2cSSergio Andres Gomez Del Real // modify it under the terms of the GNU Lesser General Public 25c97d6d2cSSergio Andres Gomez Del Real // License as published by the Free Software Foundation; either 268af82b8eSChetan Pant // version 2.1 of the License, or (at your option) any later version. 27c97d6d2cSSergio Andres Gomez Del Real // 28c97d6d2cSSergio Andres Gomez Del Real // This library is distributed in the hope that it will be useful, 29c97d6d2cSSergio Andres Gomez Del Real // but WITHOUT ANY WARRANTY; without even the implied warranty of 30c97d6d2cSSergio Andres Gomez Del Real // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31c97d6d2cSSergio Andres Gomez Del Real // Lesser General Public License for more details. 32c97d6d2cSSergio Andres Gomez Del Real // 33c97d6d2cSSergio Andres Gomez Del Real // You should have received a copy of the GNU Lesser General Public 34c97d6d2cSSergio Andres Gomez Del Real // License along with this library; if not, write to the Free Software 35c97d6d2cSSergio Andres Gomez Del Real // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA 36c97d6d2cSSergio Andres Gomez Del Real ///////////////////////////////////////////////////////////////////////// 37c97d6d2cSSergio Andres Gomez Del Real 38c97d6d2cSSergio Andres Gomez Del Real #include "qemu/osdep.h" 39895f9fdfSPaolo Bonzini #include "panic.h" 40c97d6d2cSSergio Andres Gomez Del Real #include "x86_decode.h" 41c97d6d2cSSergio Andres Gomez Del Real #include "x86.h" 42c97d6d2cSSergio Andres Gomez Del Real #include "x86_emu.h" 43c97d6d2cSSergio Andres Gomez Del Real #include "x86_mmu.h" 44c97d6d2cSSergio Andres Gomez Del Real #include "x86_flags.h" 45c97d6d2cSSergio Andres Gomez Del Real #include "vmcs.h" 46c97d6d2cSSergio Andres Gomez Del Real #include "vmx.h" 47bc4fa8c3SWei Liu #include "hvf-i386.h" 48c97d6d2cSSergio Andres Gomez Del Real 49e8a63257SPaolo Bonzini #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ 50c97d6d2cSSergio Andres Gomez Del Real { \ 51c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); \ 52c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { \ 53c97d6d2cSSergio Andres Gomez Del Real case 1: \ 54c97d6d2cSSergio Andres Gomez Del Real { \ 55c97d6d2cSSergio Andres Gomez Del Real uint8_t v1 = (uint8_t)decode->op[0].val; \ 56c97d6d2cSSergio Andres Gomez Del Real uint8_t v2 = (uint8_t)decode->op[1].val; \ 57c97d6d2cSSergio Andres Gomez Del Real uint8_t diff = v1 cmd v2; \ 58c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 59c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, diff, 1); \ 60c97d6d2cSSergio Andres Gomez Del Real } \ 61e8a63257SPaolo Bonzini FLAGS_FUNC##8(env, v1, v2, diff); \ 62c97d6d2cSSergio Andres Gomez Del Real break; \ 63c97d6d2cSSergio Andres Gomez Del Real } \ 64c97d6d2cSSergio Andres Gomez Del Real case 2: \ 65c97d6d2cSSergio Andres Gomez Del Real { \ 66c97d6d2cSSergio Andres Gomez Del Real uint16_t v1 = (uint16_t)decode->op[0].val; \ 67c97d6d2cSSergio Andres Gomez Del Real uint16_t v2 = (uint16_t)decode->op[1].val; \ 68c97d6d2cSSergio Andres Gomez Del Real uint16_t diff = v1 cmd v2; \ 69c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 70c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, diff, 2); \ 71c97d6d2cSSergio Andres Gomez Del Real } \ 72e8a63257SPaolo Bonzini FLAGS_FUNC##16(env, v1, v2, diff); \ 73c97d6d2cSSergio Andres Gomez Del Real break; \ 74c97d6d2cSSergio Andres Gomez Del Real } \ 75c97d6d2cSSergio Andres Gomez Del Real case 4: \ 76c97d6d2cSSergio Andres Gomez Del Real { \ 77c97d6d2cSSergio Andres Gomez Del Real uint32_t v1 = (uint32_t)decode->op[0].val; \ 78c97d6d2cSSergio Andres Gomez Del Real uint32_t v2 = (uint32_t)decode->op[1].val; \ 79c97d6d2cSSergio Andres Gomez Del Real uint32_t diff = v1 cmd v2; \ 80c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 81c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, diff, 4); \ 82c97d6d2cSSergio Andres Gomez Del Real } \ 83e8a63257SPaolo Bonzini FLAGS_FUNC##32(env, v1, v2, diff); \ 84c97d6d2cSSergio Andres Gomez Del Real break; \ 85c97d6d2cSSergio Andres Gomez Del Real } \ 86c97d6d2cSSergio Andres Gomez Del Real default: \ 87c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad size\n"); \ 88c97d6d2cSSergio Andres Gomez Del Real } \ 89c97d6d2cSSergio Andres Gomez Del Real } \ 90c97d6d2cSSergio Andres Gomez Del Real 91ff2de166SPaolo Bonzini target_ulong read_reg(CPUX86State *env, int reg, int size) 92c97d6d2cSSergio Andres Gomez Del Real { 93c97d6d2cSSergio Andres Gomez Del Real switch (size) { 94c97d6d2cSSergio Andres Gomez Del Real case 1: 95167c6aefSRoman Bolshakov return x86_reg(env, reg)->lx; 96c97d6d2cSSergio Andres Gomez Del Real case 2: 97167c6aefSRoman Bolshakov return x86_reg(env, reg)->rx; 98c97d6d2cSSergio Andres Gomez Del Real case 4: 99167c6aefSRoman Bolshakov return x86_reg(env, reg)->erx; 100c97d6d2cSSergio Andres Gomez Del Real case 8: 101167c6aefSRoman Bolshakov return x86_reg(env, reg)->rrx; 102c97d6d2cSSergio Andres Gomez Del Real default: 103e62963bfSPaolo Bonzini abort(); 104c97d6d2cSSergio Andres Gomez Del Real } 105c97d6d2cSSergio Andres Gomez Del Real return 0; 106c97d6d2cSSergio Andres Gomez Del Real } 107c97d6d2cSSergio Andres Gomez Del Real 108ff2de166SPaolo Bonzini void write_reg(CPUX86State *env, int reg, target_ulong val, int size) 109c97d6d2cSSergio Andres Gomez Del Real { 110c97d6d2cSSergio Andres Gomez Del Real switch (size) { 111c97d6d2cSSergio Andres Gomez Del Real case 1: 112167c6aefSRoman Bolshakov x86_reg(env, reg)->lx = val; 113c97d6d2cSSergio Andres Gomez Del Real break; 114c97d6d2cSSergio Andres Gomez Del Real case 2: 115167c6aefSRoman Bolshakov x86_reg(env, reg)->rx = val; 116c97d6d2cSSergio Andres Gomez Del Real break; 117c97d6d2cSSergio Andres Gomez Del Real case 4: 118167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = (uint32_t)val; 119c97d6d2cSSergio Andres Gomez Del Real break; 120c97d6d2cSSergio Andres Gomez Del Real case 8: 121167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = val; 122c97d6d2cSSergio Andres Gomez Del Real break; 123c97d6d2cSSergio Andres Gomez Del Real default: 124e62963bfSPaolo Bonzini abort(); 125c97d6d2cSSergio Andres Gomez Del Real } 126c97d6d2cSSergio Andres Gomez Del Real } 127c97d6d2cSSergio Andres Gomez Del Real 128ff2de166SPaolo Bonzini target_ulong read_val_from_reg(target_ulong reg_ptr, int size) 129c97d6d2cSSergio Andres Gomez Del Real { 130ff2de166SPaolo Bonzini target_ulong val; 131c97d6d2cSSergio Andres Gomez Del Real 132c97d6d2cSSergio Andres Gomez Del Real switch (size) { 133c97d6d2cSSergio Andres Gomez Del Real case 1: 134c97d6d2cSSergio Andres Gomez Del Real val = *(uint8_t *)reg_ptr; 135c97d6d2cSSergio Andres Gomez Del Real break; 136c97d6d2cSSergio Andres Gomez Del Real case 2: 137c97d6d2cSSergio Andres Gomez Del Real val = *(uint16_t *)reg_ptr; 138c97d6d2cSSergio Andres Gomez Del Real break; 139c97d6d2cSSergio Andres Gomez Del Real case 4: 140c97d6d2cSSergio Andres Gomez Del Real val = *(uint32_t *)reg_ptr; 141c97d6d2cSSergio Andres Gomez Del Real break; 142c97d6d2cSSergio Andres Gomez Del Real case 8: 143c97d6d2cSSergio Andres Gomez Del Real val = *(uint64_t *)reg_ptr; 144c97d6d2cSSergio Andres Gomez Del Real break; 145c97d6d2cSSergio Andres Gomez Del Real default: 146e62963bfSPaolo Bonzini abort(); 147c97d6d2cSSergio Andres Gomez Del Real } 148c97d6d2cSSergio Andres Gomez Del Real return val; 149c97d6d2cSSergio Andres Gomez Del Real } 150c97d6d2cSSergio Andres Gomez Del Real 151ff2de166SPaolo Bonzini void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) 152c97d6d2cSSergio Andres Gomez Del Real { 153c97d6d2cSSergio Andres Gomez Del Real switch (size) { 154c97d6d2cSSergio Andres Gomez Del Real case 1: 155c97d6d2cSSergio Andres Gomez Del Real *(uint8_t *)reg_ptr = val; 156c97d6d2cSSergio Andres Gomez Del Real break; 157c97d6d2cSSergio Andres Gomez Del Real case 2: 158c97d6d2cSSergio Andres Gomez Del Real *(uint16_t *)reg_ptr = val; 159c97d6d2cSSergio Andres Gomez Del Real break; 160c97d6d2cSSergio Andres Gomez Del Real case 4: 161c97d6d2cSSergio Andres Gomez Del Real *(uint64_t *)reg_ptr = (uint32_t)val; 162c97d6d2cSSergio Andres Gomez Del Real break; 163c97d6d2cSSergio Andres Gomez Del Real case 8: 164c97d6d2cSSergio Andres Gomez Del Real *(uint64_t *)reg_ptr = val; 165c97d6d2cSSergio Andres Gomez Del Real break; 166c97d6d2cSSergio Andres Gomez Del Real default: 167e62963bfSPaolo Bonzini abort(); 168c97d6d2cSSergio Andres Gomez Del Real } 169c97d6d2cSSergio Andres Gomez Del Real } 170c97d6d2cSSergio Andres Gomez Del Real 17136861198SPhilippe Mathieu-Daudé static bool is_host_reg(CPUX86State *env, target_ulong ptr) 172c97d6d2cSSergio Andres Gomez Del Real { 173167c6aefSRoman Bolshakov return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); 174c97d6d2cSSergio Andres Gomez Del Real } 175c97d6d2cSSergio Andres Gomez Del Real 17636861198SPhilippe Mathieu-Daudé void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size) 177c97d6d2cSSergio Andres Gomez Del Real { 178c97d6d2cSSergio Andres Gomez Del Real if (is_host_reg(env, ptr)) { 179c97d6d2cSSergio Andres Gomez Del Real write_val_to_reg(ptr, val, size); 180c97d6d2cSSergio Andres Gomez Del Real return; 181c97d6d2cSSergio Andres Gomez Del Real } 18229a0af61SRichard Henderson vmx_write_mem(env_cpu(env), ptr, &val, size); 183c97d6d2cSSergio Andres Gomez Del Real } 184c97d6d2cSSergio Andres Gomez Del Real 18536861198SPhilippe Mathieu-Daudé uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) 186c97d6d2cSSergio Andres Gomez Del Real { 187*e9c40026SWei Liu vmx_read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); 188*e9c40026SWei Liu return env->emu_mmio_buf; 189c97d6d2cSSergio Andres Gomez Del Real } 190c97d6d2cSSergio Andres Gomez Del Real 191c97d6d2cSSergio Andres Gomez Del Real 19236861198SPhilippe Mathieu-Daudé target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size) 193c97d6d2cSSergio Andres Gomez Del Real { 194ff2de166SPaolo Bonzini target_ulong val; 195c97d6d2cSSergio Andres Gomez Del Real uint8_t *mmio_ptr; 196c97d6d2cSSergio Andres Gomez Del Real 197c97d6d2cSSergio Andres Gomez Del Real if (is_host_reg(env, ptr)) { 198c97d6d2cSSergio Andres Gomez Del Real return read_val_from_reg(ptr, size); 199c97d6d2cSSergio Andres Gomez Del Real } 200c97d6d2cSSergio Andres Gomez Del Real 201c97d6d2cSSergio Andres Gomez Del Real mmio_ptr = read_mmio(env, ptr, size); 202c97d6d2cSSergio Andres Gomez Del Real switch (size) { 203c97d6d2cSSergio Andres Gomez Del Real case 1: 204c97d6d2cSSergio Andres Gomez Del Real val = *(uint8_t *)mmio_ptr; 205c97d6d2cSSergio Andres Gomez Del Real break; 206c97d6d2cSSergio Andres Gomez Del Real case 2: 207c97d6d2cSSergio Andres Gomez Del Real val = *(uint16_t *)mmio_ptr; 208c97d6d2cSSergio Andres Gomez Del Real break; 209c97d6d2cSSergio Andres Gomez Del Real case 4: 210c97d6d2cSSergio Andres Gomez Del Real val = *(uint32_t *)mmio_ptr; 211c97d6d2cSSergio Andres Gomez Del Real break; 212c97d6d2cSSergio Andres Gomez Del Real case 8: 213c97d6d2cSSergio Andres Gomez Del Real val = *(uint64_t *)mmio_ptr; 214c97d6d2cSSergio Andres Gomez Del Real break; 215c97d6d2cSSergio Andres Gomez Del Real default: 216c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad size\n"); 217c97d6d2cSSergio Andres Gomez Del Real break; 218c97d6d2cSSergio Andres Gomez Del Real } 219c97d6d2cSSergio Andres Gomez Del Real return val; 220c97d6d2cSSergio Andres Gomez Del Real } 221c97d6d2cSSergio Andres Gomez Del Real 22236861198SPhilippe Mathieu-Daudé static void fetch_operands(CPUX86State *env, struct x86_decode *decode, 223c97d6d2cSSergio Andres Gomez Del Real int n, bool val_op0, bool val_op1, bool val_op2) 224c97d6d2cSSergio Andres Gomez Del Real { 225c97d6d2cSSergio Andres Gomez Del Real int i; 226c97d6d2cSSergio Andres Gomez Del Real bool calc_val[3] = {val_op0, val_op1, val_op2}; 227c97d6d2cSSergio Andres Gomez Del Real 228c97d6d2cSSergio Andres Gomez Del Real for (i = 0; i < n; i++) { 229c97d6d2cSSergio Andres Gomez Del Real switch (decode->op[i].type) { 230c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_IMMEDIATE: 231c97d6d2cSSergio Andres Gomez Del Real break; 232c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_REG: 233c97d6d2cSSergio Andres Gomez Del Real VM_PANIC_ON(!decode->op[i].ptr); 234c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 235c97d6d2cSSergio Andres Gomez Del Real decode->op[i].val = read_val_from_reg(decode->op[i].ptr, 236c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 237c97d6d2cSSergio Andres Gomez Del Real } 238c97d6d2cSSergio Andres Gomez Del Real break; 239c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_RM: 240c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[i]); 241c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 242c97d6d2cSSergio Andres Gomez Del Real decode->op[i].val = read_val_ext(env, decode->op[i].ptr, 243c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 244c97d6d2cSSergio Andres Gomez Del Real } 245c97d6d2cSSergio Andres Gomez Del Real break; 246c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_OFFSET: 247c97d6d2cSSergio Andres Gomez Del Real decode->op[i].ptr = decode_linear_addr(env, decode, 248c97d6d2cSSergio Andres Gomez Del Real decode->op[i].ptr, 2496701d81dSPaolo Bonzini R_DS); 250c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 251c97d6d2cSSergio Andres Gomez Del Real decode->op[i].val = read_val_ext(env, decode->op[i].ptr, 252c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 253c97d6d2cSSergio Andres Gomez Del Real } 254c97d6d2cSSergio Andres Gomez Del Real break; 255c97d6d2cSSergio Andres Gomez Del Real default: 256c97d6d2cSSergio Andres Gomez Del Real break; 257c97d6d2cSSergio Andres Gomez Del Real } 258c97d6d2cSSergio Andres Gomez Del Real } 259c97d6d2cSSergio Andres Gomez Del Real } 260c97d6d2cSSergio Andres Gomez Del Real 26136861198SPhilippe Mathieu-Daudé static void exec_mov(CPUX86State *env, struct x86_decode *decode) 262c97d6d2cSSergio Andres Gomez Del Real { 263c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, true, false); 264c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, decode->op[1].val, 265c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 266c97d6d2cSSergio Andres Gomez Del Real 2675d32173fSRoman Bolshakov env->eip += decode->len; 268c97d6d2cSSergio Andres Gomez Del Real } 269c97d6d2cSSergio Andres Gomez Del Real 27036861198SPhilippe Mathieu-Daudé static void exec_add(CPUX86State *env, struct x86_decode *decode) 271c97d6d2cSSergio Andres Gomez Del Real { 272e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 2735d32173fSRoman Bolshakov env->eip += decode->len; 274c97d6d2cSSergio Andres Gomez Del Real } 275c97d6d2cSSergio Andres Gomez Del Real 27636861198SPhilippe Mathieu-Daudé static void exec_or(CPUX86State *env, struct x86_decode *decode) 277c97d6d2cSSergio Andres Gomez Del Real { 278e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); 2795d32173fSRoman Bolshakov env->eip += decode->len; 280c97d6d2cSSergio Andres Gomez Del Real } 281c97d6d2cSSergio Andres Gomez Del Real 28236861198SPhilippe Mathieu-Daudé static void exec_adc(CPUX86State *env, struct x86_decode *decode) 283c97d6d2cSSergio Andres Gomez Del Real { 284e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); 2855d32173fSRoman Bolshakov env->eip += decode->len; 286c97d6d2cSSergio Andres Gomez Del Real } 287c97d6d2cSSergio Andres Gomez Del Real 28836861198SPhilippe Mathieu-Daudé static void exec_sbb(CPUX86State *env, struct x86_decode *decode) 289c97d6d2cSSergio Andres Gomez Del Real { 290e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); 2915d32173fSRoman Bolshakov env->eip += decode->len; 292c97d6d2cSSergio Andres Gomez Del Real } 293c97d6d2cSSergio Andres Gomez Del Real 29436861198SPhilippe Mathieu-Daudé static void exec_and(CPUX86State *env, struct x86_decode *decode) 295c97d6d2cSSergio Andres Gomez Del Real { 296e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); 2975d32173fSRoman Bolshakov env->eip += decode->len; 298c97d6d2cSSergio Andres Gomez Del Real } 299c97d6d2cSSergio Andres Gomez Del Real 30036861198SPhilippe Mathieu-Daudé static void exec_sub(CPUX86State *env, struct x86_decode *decode) 301c97d6d2cSSergio Andres Gomez Del Real { 302e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); 3035d32173fSRoman Bolshakov env->eip += decode->len; 304c97d6d2cSSergio Andres Gomez Del Real } 305c97d6d2cSSergio Andres Gomez Del Real 30636861198SPhilippe Mathieu-Daudé static void exec_xor(CPUX86State *env, struct x86_decode *decode) 307c97d6d2cSSergio Andres Gomez Del Real { 308e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); 3095d32173fSRoman Bolshakov env->eip += decode->len; 310c97d6d2cSSergio Andres Gomez Del Real } 311c97d6d2cSSergio Andres Gomez Del Real 31236861198SPhilippe Mathieu-Daudé static void exec_neg(CPUX86State *env, struct x86_decode *decode) 313c97d6d2cSSergio Andres Gomez Del Real { 314e8a63257SPaolo Bonzini /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ 315c97d6d2cSSergio Andres Gomez Del Real int32_t val; 316c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 317c97d6d2cSSergio Andres Gomez Del Real 318c97d6d2cSSergio Andres Gomez Del Real val = 0 - sign(decode->op[1].val, decode->operand_size); 319c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[1].ptr, val, decode->operand_size); 320c97d6d2cSSergio Andres Gomez Del Real 321c97d6d2cSSergio Andres Gomez Del Real if (4 == decode->operand_size) { 322e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); 323c97d6d2cSSergio Andres Gomez Del Real } else if (2 == decode->operand_size) { 324e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val); 325c97d6d2cSSergio Andres Gomez Del Real } else if (1 == decode->operand_size) { 326e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val); 327c97d6d2cSSergio Andres Gomez Del Real } else { 328c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad op size\n"); 329c97d6d2cSSergio Andres Gomez Del Real } 330c97d6d2cSSergio Andres Gomez Del Real 331c97d6d2cSSergio Andres Gomez Del Real /*lflags_to_rflags(env);*/ 3325d32173fSRoman Bolshakov env->eip += decode->len; 333c97d6d2cSSergio Andres Gomez Del Real } 334c97d6d2cSSergio Andres Gomez Del Real 33536861198SPhilippe Mathieu-Daudé static void exec_cmp(CPUX86State *env, struct x86_decode *decode) 336c97d6d2cSSergio Andres Gomez Del Real { 337e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 3385d32173fSRoman Bolshakov env->eip += decode->len; 339c97d6d2cSSergio Andres Gomez Del Real } 340c97d6d2cSSergio Andres Gomez Del Real 34136861198SPhilippe Mathieu-Daudé static void exec_inc(CPUX86State *env, struct x86_decode *decode) 342c97d6d2cSSergio Andres Gomez Del Real { 343c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 344c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = 0; 345c97d6d2cSSergio Andres Gomez Del Real 346e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); 347c97d6d2cSSergio Andres Gomez Del Real 3485d32173fSRoman Bolshakov env->eip += decode->len; 349c97d6d2cSSergio Andres Gomez Del Real } 350c97d6d2cSSergio Andres Gomez Del Real 35136861198SPhilippe Mathieu-Daudé static void exec_dec(CPUX86State *env, struct x86_decode *decode) 352c97d6d2cSSergio Andres Gomez Del Real { 353c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 354c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = 0; 355c97d6d2cSSergio Andres Gomez Del Real 356e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); 3575d32173fSRoman Bolshakov env->eip += decode->len; 358c97d6d2cSSergio Andres Gomez Del Real } 359c97d6d2cSSergio Andres Gomez Del Real 36036861198SPhilippe Mathieu-Daudé static void exec_tst(CPUX86State *env, struct x86_decode *decode) 361c97d6d2cSSergio Andres Gomez Del Real { 362e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); 3635d32173fSRoman Bolshakov env->eip += decode->len; 364c97d6d2cSSergio Andres Gomez Del Real } 365c97d6d2cSSergio Andres Gomez Del Real 36636861198SPhilippe Mathieu-Daudé static void exec_not(CPUX86State *env, struct x86_decode *decode) 367c97d6d2cSSergio Andres Gomez Del Real { 368c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 1, true, false, false); 369c97d6d2cSSergio Andres Gomez Del Real 370c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, 371c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 3725d32173fSRoman Bolshakov env->eip += decode->len; 373c97d6d2cSSergio Andres Gomez Del Real } 374c97d6d2cSSergio Andres Gomez Del Real 37536861198SPhilippe Mathieu-Daudé void exec_movzx(CPUX86State *env, struct x86_decode *decode) 376c97d6d2cSSergio Andres Gomez Del Real { 377c97d6d2cSSergio Andres Gomez Del Real int src_op_size; 378c97d6d2cSSergio Andres Gomez Del Real int op_size = decode->operand_size; 379c97d6d2cSSergio Andres Gomez Del Real 380c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 1, false, false, false); 381c97d6d2cSSergio Andres Gomez Del Real 382c97d6d2cSSergio Andres Gomez Del Real if (0xb6 == decode->opcode[1]) { 383c97d6d2cSSergio Andres Gomez Del Real src_op_size = 1; 384c97d6d2cSSergio Andres Gomez Del Real } else { 385c97d6d2cSSergio Andres Gomez Del Real src_op_size = 2; 386c97d6d2cSSergio Andres Gomez Del Real } 387c97d6d2cSSergio Andres Gomez Del Real decode->operand_size = src_op_size; 388c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[1]); 389c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); 390c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); 391c97d6d2cSSergio Andres Gomez Del Real 3925d32173fSRoman Bolshakov env->eip += decode->len; 393c97d6d2cSSergio Andres Gomez Del Real } 394c97d6d2cSSergio Andres Gomez Del Real 39536861198SPhilippe Mathieu-Daudé static void exec_out(CPUX86State *env, struct x86_decode *decode) 396c97d6d2cSSergio Andres Gomez Del Real { 397c97d6d2cSSergio Andres Gomez Del Real switch (decode->opcode[0]) { 398c97d6d2cSSergio Andres Gomez Del Real case 0xe6: 399444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); 400c97d6d2cSSergio Andres Gomez Del Real break; 401c97d6d2cSSergio Andres Gomez Del Real case 0xe7: 402444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, 403c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 404c97d6d2cSSergio Andres Gomez Del Real break; 405c97d6d2cSSergio Andres Gomez Del Real case 0xee: 406444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); 407c97d6d2cSSergio Andres Gomez Del Real break; 408c97d6d2cSSergio Andres Gomez Del Real case 0xef: 409444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, 41029a0af61SRichard Henderson decode->operand_size, 1); 411c97d6d2cSSergio Andres Gomez Del Real break; 412c97d6d2cSSergio Andres Gomez Del Real default: 413c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("Bad out opcode\n"); 414c97d6d2cSSergio Andres Gomez Del Real break; 415c97d6d2cSSergio Andres Gomez Del Real } 4165d32173fSRoman Bolshakov env->eip += decode->len; 417c97d6d2cSSergio Andres Gomez Del Real } 418c97d6d2cSSergio Andres Gomez Del Real 41936861198SPhilippe Mathieu-Daudé static void exec_in(CPUX86State *env, struct x86_decode *decode) 420c97d6d2cSSergio Andres Gomez Del Real { 421ff2de166SPaolo Bonzini target_ulong val = 0; 422c97d6d2cSSergio Andres Gomez Del Real switch (decode->opcode[0]) { 423c97d6d2cSSergio Andres Gomez Del Real case 0xe4: 424444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); 425c97d6d2cSSergio Andres Gomez Del Real break; 426c97d6d2cSSergio Andres Gomez Del Real case 0xe5: 427444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, 42829a0af61SRichard Henderson decode->operand_size, 1); 429c97d6d2cSSergio Andres Gomez Del Real if (decode->operand_size == 2) { 430c97d6d2cSSergio Andres Gomez Del Real AX(env) = val; 431c97d6d2cSSergio Andres Gomez Del Real } else { 432c97d6d2cSSergio Andres Gomez Del Real RAX(env) = (uint32_t)val; 433c97d6d2cSSergio Andres Gomez Del Real } 434c97d6d2cSSergio Andres Gomez Del Real break; 435c97d6d2cSSergio Andres Gomez Del Real case 0xec: 436444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); 437c97d6d2cSSergio Andres Gomez Del Real break; 438c97d6d2cSSergio Andres Gomez Del Real case 0xed: 439444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, 440444bae08SWei Liu decode->operand_size, 1); 441c97d6d2cSSergio Andres Gomez Del Real if (decode->operand_size == 2) { 442c97d6d2cSSergio Andres Gomez Del Real AX(env) = val; 443c97d6d2cSSergio Andres Gomez Del Real } else { 444c97d6d2cSSergio Andres Gomez Del Real RAX(env) = (uint32_t)val; 445c97d6d2cSSergio Andres Gomez Del Real } 446c97d6d2cSSergio Andres Gomez Del Real 447c97d6d2cSSergio Andres Gomez Del Real break; 448c97d6d2cSSergio Andres Gomez Del Real default: 449c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("Bad in opcode\n"); 450c97d6d2cSSergio Andres Gomez Del Real break; 451c97d6d2cSSergio Andres Gomez Del Real } 452c97d6d2cSSergio Andres Gomez Del Real 4535d32173fSRoman Bolshakov env->eip += decode->len; 454c97d6d2cSSergio Andres Gomez Del Real } 455c97d6d2cSSergio Andres Gomez Del Real 45636861198SPhilippe Mathieu-Daudé static inline void string_increment_reg(CPUX86State *env, int reg, 457c97d6d2cSSergio Andres Gomez Del Real struct x86_decode *decode) 458c97d6d2cSSergio Andres Gomez Del Real { 459ff2de166SPaolo Bonzini target_ulong val = read_reg(env, reg, decode->addressing_size); 460967f4da2SRoman Bolshakov if (env->eflags & DF_MASK) { 461c97d6d2cSSergio Andres Gomez Del Real val -= decode->operand_size; 462c97d6d2cSSergio Andres Gomez Del Real } else { 463c97d6d2cSSergio Andres Gomez Del Real val += decode->operand_size; 464c97d6d2cSSergio Andres Gomez Del Real } 465c97d6d2cSSergio Andres Gomez Del Real write_reg(env, reg, val, decode->addressing_size); 466c97d6d2cSSergio Andres Gomez Del Real } 467c97d6d2cSSergio Andres Gomez Del Real 46836861198SPhilippe Mathieu-Daudé static inline void string_rep(CPUX86State *env, struct x86_decode *decode, 46936861198SPhilippe Mathieu-Daudé void (*func)(CPUX86State *env, 470c97d6d2cSSergio Andres Gomez Del Real struct x86_decode *ins), int rep) 471c97d6d2cSSergio Andres Gomez Del Real { 472ff2de166SPaolo Bonzini target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size); 473c97d6d2cSSergio Andres Gomez Del Real while (rcx--) { 474c97d6d2cSSergio Andres Gomez Del Real func(env, decode); 4756701d81dSPaolo Bonzini write_reg(env, R_ECX, rcx, decode->addressing_size); 476c97d6d2cSSergio Andres Gomez Del Real if ((PREFIX_REP == rep) && !get_ZF(env)) { 477c97d6d2cSSergio Andres Gomez Del Real break; 478c97d6d2cSSergio Andres Gomez Del Real } 479c97d6d2cSSergio Andres Gomez Del Real if ((PREFIX_REPN == rep) && get_ZF(env)) { 480c97d6d2cSSergio Andres Gomez Del Real break; 481c97d6d2cSSergio Andres Gomez Del Real } 482c97d6d2cSSergio Andres Gomez Del Real } 483c97d6d2cSSergio Andres Gomez Del Real } 484c97d6d2cSSergio Andres Gomez Del Real 48536861198SPhilippe Mathieu-Daudé static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) 486c97d6d2cSSergio Andres Gomez Del Real { 48729a0af61SRichard Henderson target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), 48829a0af61SRichard Henderson decode->addressing_size, R_ES); 489c97d6d2cSSergio Andres Gomez Del Real 490*e9c40026SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, 491c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 492*e9c40026SWei Liu vmx_write_mem(env_cpu(env), addr, env->emu_mmio_buf, 49329a0af61SRichard Henderson decode->operand_size); 494c97d6d2cSSergio Andres Gomez Del Real 4956701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 496c97d6d2cSSergio Andres Gomez Del Real } 497c97d6d2cSSergio Andres Gomez Del Real 49836861198SPhilippe Mathieu-Daudé static void exec_ins(CPUX86State *env, struct x86_decode *decode) 499c97d6d2cSSergio Andres Gomez Del Real { 500c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 501c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_ins_single, 0); 502c97d6d2cSSergio Andres Gomez Del Real } else { 503c97d6d2cSSergio Andres Gomez Del Real exec_ins_single(env, decode); 504c97d6d2cSSergio Andres Gomez Del Real } 505c97d6d2cSSergio Andres Gomez Del Real 5065d32173fSRoman Bolshakov env->eip += decode->len; 507c97d6d2cSSergio Andres Gomez Del Real } 508c97d6d2cSSergio Andres Gomez Del Real 50936861198SPhilippe Mathieu-Daudé static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) 510c97d6d2cSSergio Andres Gomez Del Real { 511ff2de166SPaolo Bonzini target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); 512c97d6d2cSSergio Andres Gomez Del Real 513*e9c40026SWei Liu vmx_read_mem(env_cpu(env), env->emu_mmio_buf, addr, 51429a0af61SRichard Henderson decode->operand_size); 515*e9c40026SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, 516c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 517c97d6d2cSSergio Andres Gomez Del Real 5186701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 519c97d6d2cSSergio Andres Gomez Del Real } 520c97d6d2cSSergio Andres Gomez Del Real 52136861198SPhilippe Mathieu-Daudé static void exec_outs(CPUX86State *env, struct x86_decode *decode) 522c97d6d2cSSergio Andres Gomez Del Real { 523c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 524c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_outs_single, 0); 525c97d6d2cSSergio Andres Gomez Del Real } else { 526c97d6d2cSSergio Andres Gomez Del Real exec_outs_single(env, decode); 527c97d6d2cSSergio Andres Gomez Del Real } 528c97d6d2cSSergio Andres Gomez Del Real 5295d32173fSRoman Bolshakov env->eip += decode->len; 530c97d6d2cSSergio Andres Gomez Del Real } 531c97d6d2cSSergio Andres Gomez Del Real 53236861198SPhilippe Mathieu-Daudé static void exec_movs_single(CPUX86State *env, struct x86_decode *decode) 533c97d6d2cSSergio Andres Gomez Del Real { 534ff2de166SPaolo Bonzini target_ulong src_addr; 535ff2de166SPaolo Bonzini target_ulong dst_addr; 536ff2de166SPaolo Bonzini target_ulong val; 537c97d6d2cSSergio Andres Gomez Del Real 5386701d81dSPaolo Bonzini src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); 53929a0af61SRichard Henderson dst_addr = linear_addr_size(env_cpu(env), RDI(env), 54029a0af61SRichard Henderson decode->addressing_size, R_ES); 541c97d6d2cSSergio Andres Gomez Del Real 542c97d6d2cSSergio Andres Gomez Del Real val = read_val_ext(env, src_addr, decode->operand_size); 543c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, dst_addr, val, decode->operand_size); 544c97d6d2cSSergio Andres Gomez Del Real 5456701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 5466701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 547c97d6d2cSSergio Andres Gomez Del Real } 548c97d6d2cSSergio Andres Gomez Del Real 54936861198SPhilippe Mathieu-Daudé static void exec_movs(CPUX86State *env, struct x86_decode *decode) 550c97d6d2cSSergio Andres Gomez Del Real { 551c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 552c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_movs_single, 0); 553c97d6d2cSSergio Andres Gomez Del Real } else { 554c97d6d2cSSergio Andres Gomez Del Real exec_movs_single(env, decode); 555c97d6d2cSSergio Andres Gomez Del Real } 556c97d6d2cSSergio Andres Gomez Del Real 5575d32173fSRoman Bolshakov env->eip += decode->len; 558c97d6d2cSSergio Andres Gomez Del Real } 559c97d6d2cSSergio Andres Gomez Del Real 56036861198SPhilippe Mathieu-Daudé static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode) 561c97d6d2cSSergio Andres Gomez Del Real { 562ff2de166SPaolo Bonzini target_ulong src_addr; 563ff2de166SPaolo Bonzini target_ulong dst_addr; 564c97d6d2cSSergio Andres Gomez Del Real 5656701d81dSPaolo Bonzini src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); 56629a0af61SRichard Henderson dst_addr = linear_addr_size(env_cpu(env), RDI(env), 56729a0af61SRichard Henderson decode->addressing_size, R_ES); 568c97d6d2cSSergio Andres Gomez Del Real 569c97d6d2cSSergio Andres Gomez Del Real decode->op[0].type = X86_VAR_IMMEDIATE; 570c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size); 571c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 572c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size); 573c97d6d2cSSergio Andres Gomez Del Real 574e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 575c97d6d2cSSergio Andres Gomez Del Real 5766701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 5776701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 578c97d6d2cSSergio Andres Gomez Del Real } 579c97d6d2cSSergio Andres Gomez Del Real 58036861198SPhilippe Mathieu-Daudé static void exec_cmps(CPUX86State *env, struct x86_decode *decode) 581c97d6d2cSSergio Andres Gomez Del Real { 582c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 583c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_cmps_single, decode->rep); 584c97d6d2cSSergio Andres Gomez Del Real } else { 585c97d6d2cSSergio Andres Gomez Del Real exec_cmps_single(env, decode); 586c97d6d2cSSergio Andres Gomez Del Real } 5875d32173fSRoman Bolshakov env->eip += decode->len; 588c97d6d2cSSergio Andres Gomez Del Real } 589c97d6d2cSSergio Andres Gomez Del Real 590c97d6d2cSSergio Andres Gomez Del Real 59136861198SPhilippe Mathieu-Daudé static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) 592c97d6d2cSSergio Andres Gomez Del Real { 593ff2de166SPaolo Bonzini target_ulong addr; 594ff2de166SPaolo Bonzini target_ulong val; 595c97d6d2cSSergio Andres Gomez Del Real 59629a0af61SRichard Henderson addr = linear_addr_size(env_cpu(env), RDI(env), 59729a0af61SRichard Henderson decode->addressing_size, R_ES); 5986701d81dSPaolo Bonzini val = read_reg(env, R_EAX, decode->operand_size); 59929a0af61SRichard Henderson vmx_write_mem(env_cpu(env), addr, &val, decode->operand_size); 600c97d6d2cSSergio Andres Gomez Del Real 6016701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 602c97d6d2cSSergio Andres Gomez Del Real } 603c97d6d2cSSergio Andres Gomez Del Real 604c97d6d2cSSergio Andres Gomez Del Real 60536861198SPhilippe Mathieu-Daudé static void exec_stos(CPUX86State *env, struct x86_decode *decode) 606c97d6d2cSSergio Andres Gomez Del Real { 607c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 608c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_stos_single, 0); 609c97d6d2cSSergio Andres Gomez Del Real } else { 610c97d6d2cSSergio Andres Gomez Del Real exec_stos_single(env, decode); 611c97d6d2cSSergio Andres Gomez Del Real } 612c97d6d2cSSergio Andres Gomez Del Real 6135d32173fSRoman Bolshakov env->eip += decode->len; 614c97d6d2cSSergio Andres Gomez Del Real } 615c97d6d2cSSergio Andres Gomez Del Real 61636861198SPhilippe Mathieu-Daudé static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) 617c97d6d2cSSergio Andres Gomez Del Real { 618ff2de166SPaolo Bonzini target_ulong addr; 619c97d6d2cSSergio Andres Gomez Del Real 62029a0af61SRichard Henderson addr = linear_addr_size(env_cpu(env), RDI(env), 62129a0af61SRichard Henderson decode->addressing_size, R_ES); 622c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 62329a0af61SRichard Henderson vmx_read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); 624c97d6d2cSSergio Andres Gomez Del Real 625e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 6266701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 627c97d6d2cSSergio Andres Gomez Del Real } 628c97d6d2cSSergio Andres Gomez Del Real 62936861198SPhilippe Mathieu-Daudé static void exec_scas(CPUX86State *env, struct x86_decode *decode) 630c97d6d2cSSergio Andres Gomez Del Real { 631c97d6d2cSSergio Andres Gomez Del Real decode->op[0].type = X86_VAR_REG; 6326701d81dSPaolo Bonzini decode->op[0].reg = R_EAX; 633c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 634c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_scas_single, decode->rep); 635c97d6d2cSSergio Andres Gomez Del Real } else { 636c97d6d2cSSergio Andres Gomez Del Real exec_scas_single(env, decode); 637c97d6d2cSSergio Andres Gomez Del Real } 638c97d6d2cSSergio Andres Gomez Del Real 6395d32173fSRoman Bolshakov env->eip += decode->len; 640c97d6d2cSSergio Andres Gomez Del Real } 641c97d6d2cSSergio Andres Gomez Del Real 64236861198SPhilippe Mathieu-Daudé static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) 643c97d6d2cSSergio Andres Gomez Del Real { 644ff2de166SPaolo Bonzini target_ulong addr; 645ff2de166SPaolo Bonzini target_ulong val = 0; 646c97d6d2cSSergio Andres Gomez Del Real 6476701d81dSPaolo Bonzini addr = decode_linear_addr(env, decode, RSI(env), R_DS); 64829a0af61SRichard Henderson vmx_read_mem(env_cpu(env), &val, addr, decode->operand_size); 6496701d81dSPaolo Bonzini write_reg(env, R_EAX, val, decode->operand_size); 650c97d6d2cSSergio Andres Gomez Del Real 6516701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 652c97d6d2cSSergio Andres Gomez Del Real } 653c97d6d2cSSergio Andres Gomez Del Real 65436861198SPhilippe Mathieu-Daudé static void exec_lods(CPUX86State *env, struct x86_decode *decode) 655c97d6d2cSSergio Andres Gomez Del Real { 656c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 657c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_lods_single, 0); 658c97d6d2cSSergio Andres Gomez Del Real } else { 659c97d6d2cSSergio Andres Gomez Del Real exec_lods_single(env, decode); 660c97d6d2cSSergio Andres Gomez Del Real } 661c97d6d2cSSergio Andres Gomez Del Real 6625d32173fSRoman Bolshakov env->eip += decode->len; 663c97d6d2cSSergio Andres Gomez Del Real } 664c97d6d2cSSergio Andres Gomez Del Real 66599e5aaf9SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code) 6660e27f3a5SPhil Dennis-Jordan { 6670e27f3a5SPhil Dennis-Jordan env->exception_nr = exception_index; 6680e27f3a5SPhil Dennis-Jordan env->error_code = error_code; 6690e27f3a5SPhil Dennis-Jordan env->has_error_code = true; 6700e27f3a5SPhil Dennis-Jordan env->exception_injected = 1; 6710e27f3a5SPhil Dennis-Jordan } 6720e27f3a5SPhil Dennis-Jordan 67336861198SPhilippe Mathieu-Daudé static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) 674c97d6d2cSSergio Andres Gomez Del Real { 67599e5aaf9SWei Liu hvf_simulate_rdmsr(env); 6765d32173fSRoman Bolshakov env->eip += decode->len; 677c97d6d2cSSergio Andres Gomez Del Real } 678c97d6d2cSSergio Andres Gomez Del Real 67936861198SPhilippe Mathieu-Daudé static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) 680c97d6d2cSSergio Andres Gomez Del Real { 68199e5aaf9SWei Liu hvf_simulate_wrmsr(env); 6825d32173fSRoman Bolshakov env->eip += decode->len; 683c97d6d2cSSergio Andres Gomez Del Real } 684c97d6d2cSSergio Andres Gomez Del Real 685c97d6d2cSSergio Andres Gomez Del Real /* 686c97d6d2cSSergio Andres Gomez Del Real * flag: 687c97d6d2cSSergio Andres Gomez Del Real * 0 - bt, 1 - btc, 2 - bts, 3 - btr 688c97d6d2cSSergio Andres Gomez Del Real */ 68936861198SPhilippe Mathieu-Daudé static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag) 690c97d6d2cSSergio Andres Gomez Del Real { 691c97d6d2cSSergio Andres Gomez Del Real int32_t displacement; 692c97d6d2cSSergio Andres Gomez Del Real uint8_t index; 693c97d6d2cSSergio Andres Gomez Del Real bool cf; 694c97d6d2cSSergio Andres Gomez Del Real int mask = (4 == decode->operand_size) ? 0x1f : 0xf; 695c97d6d2cSSergio Andres Gomez Del Real 696c97d6d2cSSergio Andres Gomez Del Real VM_PANIC_ON(decode->rex.rex); 697c97d6d2cSSergio Andres Gomez Del Real 698c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, true, false); 699c97d6d2cSSergio Andres Gomez Del Real index = decode->op[1].val & mask; 700c97d6d2cSSergio Andres Gomez Del Real 701c97d6d2cSSergio Andres Gomez Del Real if (decode->op[0].type != X86_VAR_REG) { 702c97d6d2cSSergio Andres Gomez Del Real if (4 == decode->operand_size) { 703c97d6d2cSSergio Andres Gomez Del Real displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; 704c97d6d2cSSergio Andres Gomez Del Real decode->op[0].ptr += 4 * displacement; 705c97d6d2cSSergio Andres Gomez Del Real } else if (2 == decode->operand_size) { 706c97d6d2cSSergio Andres Gomez Del Real displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; 707c97d6d2cSSergio Andres Gomez Del Real decode->op[0].ptr += 2 * displacement; 708c97d6d2cSSergio Andres Gomez Del Real } else { 709c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bt 64bit\n"); 710c97d6d2cSSergio Andres Gomez Del Real } 711c97d6d2cSSergio Andres Gomez Del Real } 712c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val = read_val_ext(env, decode->op[0].ptr, 713c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 714c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> index) & 0x01; 715c97d6d2cSSergio Andres Gomez Del Real 716c97d6d2cSSergio Andres Gomez Del Real switch (flag) { 717c97d6d2cSSergio Andres Gomez Del Real case 0: 718c97d6d2cSSergio Andres Gomez Del Real set_CF(env, cf); 719c97d6d2cSSergio Andres Gomez Del Real return; 720c97d6d2cSSergio Andres Gomez Del Real case 1: 721c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val ^= (1u << index); 722c97d6d2cSSergio Andres Gomez Del Real break; 723c97d6d2cSSergio Andres Gomez Del Real case 2: 724c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val |= (1u << index); 725c97d6d2cSSergio Andres Gomez Del Real break; 726c97d6d2cSSergio Andres Gomez Del Real case 3: 727c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val &= ~(1u << index); 728c97d6d2cSSergio Andres Gomez Del Real break; 729c97d6d2cSSergio Andres Gomez Del Real } 730c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, decode->op[0].val, 731c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 732c97d6d2cSSergio Andres Gomez Del Real set_CF(env, cf); 733c97d6d2cSSergio Andres Gomez Del Real } 734c97d6d2cSSergio Andres Gomez Del Real 73536861198SPhilippe Mathieu-Daudé static void exec_bt(CPUX86State *env, struct x86_decode *decode) 736c97d6d2cSSergio Andres Gomez Del Real { 737c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 0); 7385d32173fSRoman Bolshakov env->eip += decode->len; 739c97d6d2cSSergio Andres Gomez Del Real } 740c97d6d2cSSergio Andres Gomez Del Real 74136861198SPhilippe Mathieu-Daudé static void exec_btc(CPUX86State *env, struct x86_decode *decode) 742c97d6d2cSSergio Andres Gomez Del Real { 743c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 1); 7445d32173fSRoman Bolshakov env->eip += decode->len; 745c97d6d2cSSergio Andres Gomez Del Real } 746c97d6d2cSSergio Andres Gomez Del Real 74736861198SPhilippe Mathieu-Daudé static void exec_btr(CPUX86State *env, struct x86_decode *decode) 748c97d6d2cSSergio Andres Gomez Del Real { 749c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 3); 7505d32173fSRoman Bolshakov env->eip += decode->len; 751c97d6d2cSSergio Andres Gomez Del Real } 752c97d6d2cSSergio Andres Gomez Del Real 75336861198SPhilippe Mathieu-Daudé static void exec_bts(CPUX86State *env, struct x86_decode *decode) 754c97d6d2cSSergio Andres Gomez Del Real { 755c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 2); 7565d32173fSRoman Bolshakov env->eip += decode->len; 757c97d6d2cSSergio Andres Gomez Del Real } 758c97d6d2cSSergio Andres Gomez Del Real 75936861198SPhilippe Mathieu-Daudé void exec_shl(CPUX86State *env, struct x86_decode *decode) 760c97d6d2cSSergio Andres Gomez Del Real { 761c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 762c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 763c97d6d2cSSergio Andres Gomez Del Real 764c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 765c97d6d2cSSergio Andres Gomez Del Real 766c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 767c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; /* count is masked to 5 bits*/ 768c97d6d2cSSergio Andres Gomez Del Real if (!count) { 769c97d6d2cSSergio Andres Gomez Del Real goto exit; 770c97d6d2cSSergio Andres Gomez Del Real } 771c97d6d2cSSergio Andres Gomez Del Real 772c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 773c97d6d2cSSergio Andres Gomez Del Real case 1: 774c97d6d2cSSergio Andres Gomez Del Real { 775c97d6d2cSSergio Andres Gomez Del Real uint8_t res = 0; 776c97d6d2cSSergio Andres Gomez Del Real if (count <= 8) { 777c97d6d2cSSergio Andres Gomez Del Real res = (decode->op[0].val << count); 778c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (8 - count)) & 0x1; 779c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 7); 780c97d6d2cSSergio Andres Gomez Del Real } 781c97d6d2cSSergio Andres Gomez Del Real 782c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 1); 783e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); 784c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 785c97d6d2cSSergio Andres Gomez Del Real break; 786c97d6d2cSSergio Andres Gomez Del Real } 787c97d6d2cSSergio Andres Gomez Del Real case 2: 788c97d6d2cSSergio Andres Gomez Del Real { 789c97d6d2cSSergio Andres Gomez Del Real uint16_t res = 0; 790c97d6d2cSSergio Andres Gomez Del Real 791c97d6d2cSSergio Andres Gomez Del Real /* from bochs */ 792c97d6d2cSSergio Andres Gomez Del Real if (count <= 16) { 793c97d6d2cSSergio Andres Gomez Del Real res = (decode->op[0].val << count); 794c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (16 - count)) & 0x1; 795c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 15); /* of = cf ^ result15 */ 796c97d6d2cSSergio Andres Gomez Del Real } 797c97d6d2cSSergio Andres Gomez Del Real 798c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 2); 799e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); 800c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 801c97d6d2cSSergio Andres Gomez Del Real break; 802c97d6d2cSSergio Andres Gomez Del Real } 803c97d6d2cSSergio Andres Gomez Del Real case 4: 804c97d6d2cSSergio Andres Gomez Del Real { 805c97d6d2cSSergio Andres Gomez Del Real uint32_t res = decode->op[0].val << count; 806c97d6d2cSSergio Andres Gomez Del Real 807c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 4); 808e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); 809c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (32 - count)) & 0x1; 810c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 31); /* of = cf ^ result31 */ 811c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 812c97d6d2cSSergio Andres Gomez Del Real break; 813c97d6d2cSSergio Andres Gomez Del Real } 814c97d6d2cSSergio Andres Gomez Del Real default: 815c97d6d2cSSergio Andres Gomez Del Real abort(); 816c97d6d2cSSergio Andres Gomez Del Real } 817c97d6d2cSSergio Andres Gomez Del Real 818c97d6d2cSSergio Andres Gomez Del Real exit: 819c97d6d2cSSergio Andres Gomez Del Real /* lflags_to_rflags(env); */ 8205d32173fSRoman Bolshakov env->eip += decode->len; 821c97d6d2cSSergio Andres Gomez Del Real } 822c97d6d2cSSergio Andres Gomez Del Real 823c97d6d2cSSergio Andres Gomez Del Real void exec_movsx(CPUX86State *env, struct x86_decode *decode) 824c97d6d2cSSergio Andres Gomez Del Real { 825c97d6d2cSSergio Andres Gomez Del Real int src_op_size; 826c97d6d2cSSergio Andres Gomez Del Real int op_size = decode->operand_size; 827c97d6d2cSSergio Andres Gomez Del Real 828c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, false, false); 829c97d6d2cSSergio Andres Gomez Del Real 830c97d6d2cSSergio Andres Gomez Del Real if (0xbe == decode->opcode[1]) { 831c97d6d2cSSergio Andres Gomez Del Real src_op_size = 1; 832c97d6d2cSSergio Andres Gomez Del Real } else { 833c97d6d2cSSergio Andres Gomez Del Real src_op_size = 2; 834c97d6d2cSSergio Andres Gomez Del Real } 835c97d6d2cSSergio Andres Gomez Del Real 836c97d6d2cSSergio Andres Gomez Del Real decode->operand_size = src_op_size; 837c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[1]); 838c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size), 839c97d6d2cSSergio Andres Gomez Del Real src_op_size); 840c97d6d2cSSergio Andres Gomez Del Real 841c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); 842c97d6d2cSSergio Andres Gomez Del Real 8435d32173fSRoman Bolshakov env->eip += decode->len; 844c97d6d2cSSergio Andres Gomez Del Real } 845c97d6d2cSSergio Andres Gomez Del Real 84636861198SPhilippe Mathieu-Daudé void exec_ror(CPUX86State *env, struct x86_decode *decode) 847c97d6d2cSSergio Andres Gomez Del Real { 848c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 849c97d6d2cSSergio Andres Gomez Del Real 850c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 851c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 852c97d6d2cSSergio Andres Gomez Del Real 853c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 854c97d6d2cSSergio Andres Gomez Del Real case 1: 855c97d6d2cSSergio Andres Gomez Del Real { 856c97d6d2cSSergio Andres Gomez Del Real uint32_t bit6, bit7; 857c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 858c97d6d2cSSergio Andres Gomez Del Real 859c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x07) == 0) { 860c97d6d2cSSergio Andres Gomez Del Real if (count & 0x18) { 861c97d6d2cSSergio Andres Gomez Del Real bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; 862c97d6d2cSSergio Andres Gomez Del Real bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; 863c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 864c97d6d2cSSergio Andres Gomez Del Real } 865c97d6d2cSSergio Andres Gomez Del Real } else { 866c97d6d2cSSergio Andres Gomez Del Real count &= 0x7; /* use only bottom 3 bits */ 867c97d6d2cSSergio Andres Gomez Del Real res = ((uint8_t)decode->op[0].val >> count) | 868c97d6d2cSSergio Andres Gomez Del Real ((uint8_t)decode->op[0].val << (8 - count)); 869c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 1); 870c97d6d2cSSergio Andres Gomez Del Real bit6 = (res >> 6) & 1; 871c97d6d2cSSergio Andres Gomez Del Real bit7 = (res >> 7) & 1; 872c97d6d2cSSergio Andres Gomez Del Real /* set eflags: ROR count affects the following flags: C, O */ 873c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 874c97d6d2cSSergio Andres Gomez Del Real } 875c97d6d2cSSergio Andres Gomez Del Real break; 876c97d6d2cSSergio Andres Gomez Del Real } 877c97d6d2cSSergio Andres Gomez Del Real case 2: 878c97d6d2cSSergio Andres Gomez Del Real { 879c97d6d2cSSergio Andres Gomez Del Real uint32_t bit14, bit15; 880c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 881c97d6d2cSSergio Andres Gomez Del Real 882c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x0f) == 0) { 883c97d6d2cSSergio Andres Gomez Del Real if (count & 0x10) { 884c97d6d2cSSergio Andres Gomez Del Real bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; 885c97d6d2cSSergio Andres Gomez Del Real bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; 886c97d6d2cSSergio Andres Gomez Del Real /* of = result14 ^ result15 */ 887c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 888c97d6d2cSSergio Andres Gomez Del Real } 889c97d6d2cSSergio Andres Gomez Del Real } else { 890c97d6d2cSSergio Andres Gomez Del Real count &= 0x0f; /* use only 4 LSB's */ 891c97d6d2cSSergio Andres Gomez Del Real res = ((uint16_t)decode->op[0].val >> count) | 892c97d6d2cSSergio Andres Gomez Del Real ((uint16_t)decode->op[0].val << (16 - count)); 893c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 2); 894c97d6d2cSSergio Andres Gomez Del Real 895c97d6d2cSSergio Andres Gomez Del Real bit14 = (res >> 14) & 1; 896c97d6d2cSSergio Andres Gomez Del Real bit15 = (res >> 15) & 1; 897c97d6d2cSSergio Andres Gomez Del Real /* of = result14 ^ result15 */ 898c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 899c97d6d2cSSergio Andres Gomez Del Real } 900c97d6d2cSSergio Andres Gomez Del Real break; 901c97d6d2cSSergio Andres Gomez Del Real } 902c97d6d2cSSergio Andres Gomez Del Real case 4: 903c97d6d2cSSergio Andres Gomez Del Real { 904c97d6d2cSSergio Andres Gomez Del Real uint32_t bit31, bit30; 905c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 906c97d6d2cSSergio Andres Gomez Del Real 907c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; 908c97d6d2cSSergio Andres Gomez Del Real if (count) { 909c97d6d2cSSergio Andres Gomez Del Real res = ((uint32_t)decode->op[0].val >> count) | 910c97d6d2cSSergio Andres Gomez Del Real ((uint32_t)decode->op[0].val << (32 - count)); 911c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 4); 912c97d6d2cSSergio Andres Gomez Del Real 913c97d6d2cSSergio Andres Gomez Del Real bit31 = (res >> 31) & 1; 914c97d6d2cSSergio Andres Gomez Del Real bit30 = (res >> 30) & 1; 915c97d6d2cSSergio Andres Gomez Del Real /* of = result30 ^ result31 */ 916c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31); 917c97d6d2cSSergio Andres Gomez Del Real } 918c97d6d2cSSergio Andres Gomez Del Real break; 919c97d6d2cSSergio Andres Gomez Del Real } 920c97d6d2cSSergio Andres Gomez Del Real } 9215d32173fSRoman Bolshakov env->eip += decode->len; 922c97d6d2cSSergio Andres Gomez Del Real } 923c97d6d2cSSergio Andres Gomez Del Real 92436861198SPhilippe Mathieu-Daudé void exec_rol(CPUX86State *env, struct x86_decode *decode) 925c97d6d2cSSergio Andres Gomez Del Real { 926c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 927c97d6d2cSSergio Andres Gomez Del Real 928c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 929c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 930c97d6d2cSSergio Andres Gomez Del Real 931c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 932c97d6d2cSSergio Andres Gomez Del Real case 1: 933c97d6d2cSSergio Andres Gomez Del Real { 934c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit7; 935c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 936c97d6d2cSSergio Andres Gomez Del Real 937c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x07) == 0) { 938c97d6d2cSSergio Andres Gomez Del Real if (count & 0x18) { 939c97d6d2cSSergio Andres Gomez Del Real bit0 = ((uint8_t)decode->op[0].val & 1); 940c97d6d2cSSergio Andres Gomez Del Real bit7 = ((uint8_t)decode->op[0].val >> 7); 941c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 942c97d6d2cSSergio Andres Gomez Del Real } 943c97d6d2cSSergio Andres Gomez Del Real } else { 944c97d6d2cSSergio Andres Gomez Del Real count &= 0x7; /* use only lowest 3 bits */ 945c97d6d2cSSergio Andres Gomez Del Real res = ((uint8_t)decode->op[0].val << count) | 946c97d6d2cSSergio Andres Gomez Del Real ((uint8_t)decode->op[0].val >> (8 - count)); 947c97d6d2cSSergio Andres Gomez Del Real 948c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 1); 949c97d6d2cSSergio Andres Gomez Del Real /* set eflags: 950c97d6d2cSSergio Andres Gomez Del Real * ROL count affects the following flags: C, O 951c97d6d2cSSergio Andres Gomez Del Real */ 952c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 1); 953c97d6d2cSSergio Andres Gomez Del Real bit7 = (res >> 7); 954c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 955c97d6d2cSSergio Andres Gomez Del Real } 956c97d6d2cSSergio Andres Gomez Del Real break; 957c97d6d2cSSergio Andres Gomez Del Real } 958c97d6d2cSSergio Andres Gomez Del Real case 2: 959c97d6d2cSSergio Andres Gomez Del Real { 960c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit15; 961c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 962c97d6d2cSSergio Andres Gomez Del Real 963c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x0f) == 0) { 964c97d6d2cSSergio Andres Gomez Del Real if (count & 0x10) { 965c97d6d2cSSergio Andres Gomez Del Real bit0 = ((uint16_t)decode->op[0].val & 0x1); 966c97d6d2cSSergio Andres Gomez Del Real bit15 = ((uint16_t)decode->op[0].val >> 15); 967c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result15 */ 968c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 969c97d6d2cSSergio Andres Gomez Del Real } 970c97d6d2cSSergio Andres Gomez Del Real } else { 971c97d6d2cSSergio Andres Gomez Del Real count &= 0x0f; /* only use bottom 4 bits */ 972c97d6d2cSSergio Andres Gomez Del Real res = ((uint16_t)decode->op[0].val << count) | 973c97d6d2cSSergio Andres Gomez Del Real ((uint16_t)decode->op[0].val >> (16 - count)); 974c97d6d2cSSergio Andres Gomez Del Real 975c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 2); 976c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 0x1); 977c97d6d2cSSergio Andres Gomez Del Real bit15 = (res >> 15); 978c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result15 */ 979c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 980c97d6d2cSSergio Andres Gomez Del Real } 981c97d6d2cSSergio Andres Gomez Del Real break; 982c97d6d2cSSergio Andres Gomez Del Real } 983c97d6d2cSSergio Andres Gomez Del Real case 4: 984c97d6d2cSSergio Andres Gomez Del Real { 985c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit31; 986c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 987c97d6d2cSSergio Andres Gomez Del Real 988c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; 989c97d6d2cSSergio Andres Gomez Del Real if (count) { 990c97d6d2cSSergio Andres Gomez Del Real res = ((uint32_t)decode->op[0].val << count) | 991c97d6d2cSSergio Andres Gomez Del Real ((uint32_t)decode->op[0].val >> (32 - count)); 992c97d6d2cSSergio Andres Gomez Del Real 993c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 4); 994c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 0x1); 995c97d6d2cSSergio Andres Gomez Del Real bit31 = (res >> 31); 996c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result31 */ 997c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0); 998c97d6d2cSSergio Andres Gomez Del Real } 999c97d6d2cSSergio Andres Gomez Del Real break; 1000c97d6d2cSSergio Andres Gomez Del Real } 1001c97d6d2cSSergio Andres Gomez Del Real } 10025d32173fSRoman Bolshakov env->eip += decode->len; 1003c97d6d2cSSergio Andres Gomez Del Real } 1004c97d6d2cSSergio Andres Gomez Del Real 1005c97d6d2cSSergio Andres Gomez Del Real 100636861198SPhilippe Mathieu-Daudé void exec_rcl(CPUX86State *env, struct x86_decode *decode) 1007c97d6d2cSSergio Andres Gomez Del Real { 1008c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 1009c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 1010c97d6d2cSSergio Andres Gomez Del Real 1011c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1012c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val & 0x1f; 1013c97d6d2cSSergio Andres Gomez Del Real 1014c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 1015c97d6d2cSSergio Andres Gomez Del Real case 1: 1016c97d6d2cSSergio Andres Gomez Del Real { 1017c97d6d2cSSergio Andres Gomez Del Real uint8_t op1_8 = decode->op[0].val; 1018c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 1019c97d6d2cSSergio Andres Gomez Del Real count %= 9; 1020c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1021c97d6d2cSSergio Andres Gomez Del Real break; 1022c97d6d2cSSergio Andres Gomez Del Real } 1023c97d6d2cSSergio Andres Gomez Del Real 1024c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1025c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 << 1) | get_CF(env); 1026c97d6d2cSSergio Andres Gomez Del Real } else { 1027c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 << count) | (get_CF(env) << (count - 1)) | 1028c97d6d2cSSergio Andres Gomez Del Real (op1_8 >> (9 - count)); 1029c97d6d2cSSergio Andres Gomez Del Real } 1030c97d6d2cSSergio Andres Gomez Del Real 1031c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 1); 1032c97d6d2cSSergio Andres Gomez Del Real 1033c97d6d2cSSergio Andres Gomez Del Real cf = (op1_8 >> (8 - count)) & 0x01; 1034c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 7); /* of = cf ^ result7 */ 1035c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1036c97d6d2cSSergio Andres Gomez Del Real break; 1037c97d6d2cSSergio Andres Gomez Del Real } 1038c97d6d2cSSergio Andres Gomez Del Real case 2: 1039c97d6d2cSSergio Andres Gomez Del Real { 1040c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 1041c97d6d2cSSergio Andres Gomez Del Real uint16_t op1_16 = decode->op[0].val; 1042c97d6d2cSSergio Andres Gomez Del Real 1043c97d6d2cSSergio Andres Gomez Del Real count %= 17; 1044c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1045c97d6d2cSSergio Andres Gomez Del Real break; 1046c97d6d2cSSergio Andres Gomez Del Real } 1047c97d6d2cSSergio Andres Gomez Del Real 1048c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1049c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 << 1) | get_CF(env); 1050c97d6d2cSSergio Andres Gomez Del Real } else if (count == 16) { 1051c97d6d2cSSergio Andres Gomez Del Real res = (get_CF(env) << 15) | (op1_16 >> 1); 1052c97d6d2cSSergio Andres Gomez Del Real } else { /* 2..15 */ 1053c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 << count) | (get_CF(env) << (count - 1)) | 1054c97d6d2cSSergio Andres Gomez Del Real (op1_16 >> (17 - count)); 1055c97d6d2cSSergio Andres Gomez Del Real } 1056c97d6d2cSSergio Andres Gomez Del Real 1057c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 2); 1058c97d6d2cSSergio Andres Gomez Del Real 1059c97d6d2cSSergio Andres Gomez Del Real cf = (op1_16 >> (16 - count)) & 0x1; 1060c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 15); /* of = cf ^ result15 */ 1061c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1062c97d6d2cSSergio Andres Gomez Del Real break; 1063c97d6d2cSSergio Andres Gomez Del Real } 1064c97d6d2cSSergio Andres Gomez Del Real case 4: 1065c97d6d2cSSergio Andres Gomez Del Real { 1066c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 1067c97d6d2cSSergio Andres Gomez Del Real uint32_t op1_32 = decode->op[0].val; 1068c97d6d2cSSergio Andres Gomez Del Real 1069c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1070c97d6d2cSSergio Andres Gomez Del Real break; 1071c97d6d2cSSergio Andres Gomez Del Real } 1072c97d6d2cSSergio Andres Gomez Del Real 1073c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1074c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 << 1) | get_CF(env); 1075c97d6d2cSSergio Andres Gomez Del Real } else { 1076c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 << count) | (get_CF(env) << (count - 1)) | 1077c97d6d2cSSergio Andres Gomez Del Real (op1_32 >> (33 - count)); 1078c97d6d2cSSergio Andres Gomez Del Real } 1079c97d6d2cSSergio Andres Gomez Del Real 1080c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 4); 1081c97d6d2cSSergio Andres Gomez Del Real 1082c97d6d2cSSergio Andres Gomez Del Real cf = (op1_32 >> (32 - count)) & 0x1; 1083c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 31); /* of = cf ^ result31 */ 1084c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1085c97d6d2cSSergio Andres Gomez Del Real break; 1086c97d6d2cSSergio Andres Gomez Del Real } 1087c97d6d2cSSergio Andres Gomez Del Real } 10885d32173fSRoman Bolshakov env->eip += decode->len; 1089c97d6d2cSSergio Andres Gomez Del Real } 1090c97d6d2cSSergio Andres Gomez Del Real 109136861198SPhilippe Mathieu-Daudé void exec_rcr(CPUX86State *env, struct x86_decode *decode) 1092c97d6d2cSSergio Andres Gomez Del Real { 1093c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 1094c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 1095c97d6d2cSSergio Andres Gomez Del Real 1096c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1097c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val & 0x1f; 1098c97d6d2cSSergio Andres Gomez Del Real 1099c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 1100c97d6d2cSSergio Andres Gomez Del Real case 1: 1101c97d6d2cSSergio Andres Gomez Del Real { 1102c97d6d2cSSergio Andres Gomez Del Real uint8_t op1_8 = decode->op[0].val; 1103c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 1104c97d6d2cSSergio Andres Gomez Del Real 1105c97d6d2cSSergio Andres Gomez Del Real count %= 9; 1106c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1107c97d6d2cSSergio Andres Gomez Del Real break; 1108c97d6d2cSSergio Andres Gomez Del Real } 1109c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | 1110c97d6d2cSSergio Andres Gomez Del Real (op1_8 << (9 - count)); 1111c97d6d2cSSergio Andres Gomez Del Real 1112c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 1); 1113c97d6d2cSSergio Andres Gomez Del Real 1114c97d6d2cSSergio Andres Gomez Del Real cf = (op1_8 >> (count - 1)) & 0x1; 1115c97d6d2cSSergio Andres Gomez Del Real of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ 1116c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1117c97d6d2cSSergio Andres Gomez Del Real break; 1118c97d6d2cSSergio Andres Gomez Del Real } 1119c97d6d2cSSergio Andres Gomez Del Real case 2: 1120c97d6d2cSSergio Andres Gomez Del Real { 1121c97d6d2cSSergio Andres Gomez Del Real uint16_t op1_16 = decode->op[0].val; 1122c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 1123c97d6d2cSSergio Andres Gomez Del Real 1124c97d6d2cSSergio Andres Gomez Del Real count %= 17; 1125c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1126c97d6d2cSSergio Andres Gomez Del Real break; 1127c97d6d2cSSergio Andres Gomez Del Real } 1128c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | 1129c97d6d2cSSergio Andres Gomez Del Real (op1_16 << (17 - count)); 1130c97d6d2cSSergio Andres Gomez Del Real 1131c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 2); 1132c97d6d2cSSergio Andres Gomez Del Real 1133c97d6d2cSSergio Andres Gomez Del Real cf = (op1_16 >> (count - 1)) & 0x1; 1134c97d6d2cSSergio Andres Gomez Del Real of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ 1135c97d6d2cSSergio Andres Gomez Del Real result14 */ 1136c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1137c97d6d2cSSergio Andres Gomez Del Real break; 1138c97d6d2cSSergio Andres Gomez Del Real } 1139c97d6d2cSSergio Andres Gomez Del Real case 4: 1140c97d6d2cSSergio Andres Gomez Del Real { 1141c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 1142c97d6d2cSSergio Andres Gomez Del Real uint32_t op1_32 = decode->op[0].val; 1143c97d6d2cSSergio Andres Gomez Del Real 1144c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1145c97d6d2cSSergio Andres Gomez Del Real break; 1146c97d6d2cSSergio Andres Gomez Del Real } 1147c97d6d2cSSergio Andres Gomez Del Real 1148c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1149c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 >> 1) | (get_CF(env) << 31); 1150c97d6d2cSSergio Andres Gomez Del Real } else { 1151c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 >> count) | (get_CF(env) << (32 - count)) | 1152c97d6d2cSSergio Andres Gomez Del Real (op1_32 << (33 - count)); 1153c97d6d2cSSergio Andres Gomez Del Real } 1154c97d6d2cSSergio Andres Gomez Del Real 1155c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, res, 4); 1156c97d6d2cSSergio Andres Gomez Del Real 1157c97d6d2cSSergio Andres Gomez Del Real cf = (op1_32 >> (count - 1)) & 0x1; 1158c97d6d2cSSergio Andres Gomez Del Real of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ 1159c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1160c97d6d2cSSergio Andres Gomez Del Real break; 1161c97d6d2cSSergio Andres Gomez Del Real } 1162c97d6d2cSSergio Andres Gomez Del Real } 11635d32173fSRoman Bolshakov env->eip += decode->len; 1164c97d6d2cSSergio Andres Gomez Del Real } 1165c97d6d2cSSergio Andres Gomez Del Real 116636861198SPhilippe Mathieu-Daudé static void exec_xchg(CPUX86State *env, struct x86_decode *decode) 1167c97d6d2cSSergio Andres Gomez Del Real { 1168c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1169c97d6d2cSSergio Andres Gomez Del Real 1170c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[0].ptr, decode->op[1].val, 1171c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1172c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[1].ptr, decode->op[0].val, 1173c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1174c97d6d2cSSergio Andres Gomez Del Real 11755d32173fSRoman Bolshakov env->eip += decode->len; 1176c97d6d2cSSergio Andres Gomez Del Real } 1177c97d6d2cSSergio Andres Gomez Del Real 117836861198SPhilippe Mathieu-Daudé static void exec_xadd(CPUX86State *env, struct x86_decode *decode) 1179c97d6d2cSSergio Andres Gomez Del Real { 1180e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 1181c97d6d2cSSergio Andres Gomez Del Real write_val_ext(env, decode->op[1].ptr, decode->op[0].val, 1182c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1183c97d6d2cSSergio Andres Gomez Del Real 11845d32173fSRoman Bolshakov env->eip += decode->len; 1185c97d6d2cSSergio Andres Gomez Del Real } 1186c97d6d2cSSergio Andres Gomez Del Real 1187c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler { 1188c97d6d2cSSergio Andres Gomez Del Real enum x86_decode_cmd cmd; 118936861198SPhilippe Mathieu-Daudé void (*handler)(CPUX86State *env, struct x86_decode *ins); 1190c97d6d2cSSergio Andres Gomez Del Real } handlers[] = { 1191c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INVL, NULL,}, 1192c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOV, exec_mov}, 1193c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ADD, exec_add}, 1194c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OR, exec_or}, 1195c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ADC, exec_adc}, 1196c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SBB, exec_sbb}, 1197c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_AND, exec_and}, 1198c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SUB, exec_sub}, 1199c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_NEG, exec_neg}, 1200c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XOR, exec_xor}, 1201c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_CMP, exec_cmp}, 1202c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INC, exec_inc}, 1203c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_DEC, exec_dec}, 1204c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_TST, exec_tst}, 1205c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_NOT, exec_not}, 1206c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVZX, exec_movzx}, 1207c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OUT, exec_out}, 1208c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_IN, exec_in}, 1209c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INS, exec_ins}, 1210c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OUTS, exec_outs}, 1211c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RDMSR, exec_rdmsr}, 1212c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_WRMSR, exec_wrmsr}, 1213c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BT, exec_bt}, 1214c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTR, exec_btr}, 1215c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTC, exec_btc}, 1216c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTS, exec_bts}, 1217c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SHL, exec_shl}, 1218c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ROL, exec_rol}, 1219c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ROR, exec_ror}, 1220c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RCR, exec_rcr}, 1221c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RCL, exec_rcl}, 1222c97d6d2cSSergio Andres Gomez Del Real /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/ 1223c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVS, exec_movs}, 1224c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_CMPS, exec_cmps}, 1225c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_STOS, exec_stos}, 1226c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SCAS, exec_scas}, 1227c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_LODS, exec_lods}, 1228c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVSX, exec_movsx}, 1229c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XCHG, exec_xchg}, 1230c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XADD, exec_xadd}, 1231c97d6d2cSSergio Andres Gomez Del Real }; 1232c97d6d2cSSergio Andres Gomez Del Real 1233c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; 1234c97d6d2cSSergio Andres Gomez Del Real 123526a44d9dSWei Liu const struct x86_emul_ops *emul_ops; 123626a44d9dSWei Liu 12370e4e622eSPhil Dennis-Jordan static void init_cmd_handler(void) 1238c97d6d2cSSergio Andres Gomez Del Real { 1239c97d6d2cSSergio Andres Gomez Del Real int i; 1240c97d6d2cSSergio Andres Gomez Del Real for (i = 0; i < ARRAY_SIZE(handlers); i++) { 1241c97d6d2cSSergio Andres Gomez Del Real _cmd_handler[handlers[i].cmd] = handlers[i]; 1242c97d6d2cSSergio Andres Gomez Del Real } 1243c97d6d2cSSergio Andres Gomez Del Real } 1244c97d6d2cSSergio Andres Gomez Del Real 124536861198SPhilippe Mathieu-Daudé bool exec_instruction(CPUX86State *env, struct x86_decode *ins) 1246c97d6d2cSSergio Andres Gomez Del Real { 1247c97d6d2cSSergio Andres Gomez Del Real if (!_cmd_handler[ins->cmd].handler) { 12485d32173fSRoman Bolshakov printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, 1249c97d6d2cSSergio Andres Gomez Del Real ins->cmd, ins->opcode[0], 1250c97d6d2cSSergio Andres Gomez Del Real ins->opcode_len > 1 ? ins->opcode[1] : 0); 12515d32173fSRoman Bolshakov env->eip += ins->len; 1252c97d6d2cSSergio Andres Gomez Del Real return true; 1253c97d6d2cSSergio Andres Gomez Del Real } 1254c97d6d2cSSergio Andres Gomez Del Real 1255c97d6d2cSSergio Andres Gomez Del Real _cmd_handler[ins->cmd].handler(env, ins); 1256c97d6d2cSSergio Andres Gomez Del Real return true; 1257c97d6d2cSSergio Andres Gomez Del Real } 1258c97d6d2cSSergio Andres Gomez Del Real 125926a44d9dSWei Liu void init_emu(const struct x86_emul_ops *o) 1260c97d6d2cSSergio Andres Gomez Del Real { 126126a44d9dSWei Liu emul_ops = o; 1262c97d6d2cSSergio Andres Gomez Del Real init_cmd_handler(); 1263c97d6d2cSSergio Andres Gomez Del Real } 1264