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_flags.h" 44c97d6d2cSSergio Andres Gomez Del Real 45e8a63257SPaolo Bonzini #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ 46c97d6d2cSSergio Andres Gomez Del Real { \ 47c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); \ 48c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { \ 49c97d6d2cSSergio Andres Gomez Del Real case 1: \ 50c97d6d2cSSergio Andres Gomez Del Real { \ 51c97d6d2cSSergio Andres Gomez Del Real uint8_t v1 = (uint8_t)decode->op[0].val; \ 52c97d6d2cSSergio Andres Gomez Del Real uint8_t v2 = (uint8_t)decode->op[1].val; \ 53c97d6d2cSSergio Andres Gomez Del Real uint8_t diff = v1 cmd v2; \ 54c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 55*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], diff, 1); \ 56c97d6d2cSSergio Andres Gomez Del Real } \ 57e8a63257SPaolo Bonzini FLAGS_FUNC##8(env, v1, v2, diff); \ 58c97d6d2cSSergio Andres Gomez Del Real break; \ 59c97d6d2cSSergio Andres Gomez Del Real } \ 60c97d6d2cSSergio Andres Gomez Del Real case 2: \ 61c97d6d2cSSergio Andres Gomez Del Real { \ 62c97d6d2cSSergio Andres Gomez Del Real uint16_t v1 = (uint16_t)decode->op[0].val; \ 63c97d6d2cSSergio Andres Gomez Del Real uint16_t v2 = (uint16_t)decode->op[1].val; \ 64c97d6d2cSSergio Andres Gomez Del Real uint16_t diff = v1 cmd v2; \ 65c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 66*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], diff, 2); \ 67c97d6d2cSSergio Andres Gomez Del Real } \ 68e8a63257SPaolo Bonzini FLAGS_FUNC##16(env, v1, v2, diff); \ 69c97d6d2cSSergio Andres Gomez Del Real break; \ 70c97d6d2cSSergio Andres Gomez Del Real } \ 71c97d6d2cSSergio Andres Gomez Del Real case 4: \ 72c97d6d2cSSergio Andres Gomez Del Real { \ 73c97d6d2cSSergio Andres Gomez Del Real uint32_t v1 = (uint32_t)decode->op[0].val; \ 74c97d6d2cSSergio Andres Gomez Del Real uint32_t v2 = (uint32_t)decode->op[1].val; \ 75c97d6d2cSSergio Andres Gomez Del Real uint32_t diff = v1 cmd v2; \ 76c97d6d2cSSergio Andres Gomez Del Real if (save_res) { \ 77*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], diff, 4); \ 78c97d6d2cSSergio Andres Gomez Del Real } \ 79e8a63257SPaolo Bonzini FLAGS_FUNC##32(env, v1, v2, diff); \ 80c97d6d2cSSergio Andres Gomez Del Real break; \ 81c97d6d2cSSergio Andres Gomez Del Real } \ 82c97d6d2cSSergio Andres Gomez Del Real default: \ 83c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad size\n"); \ 84c97d6d2cSSergio Andres Gomez Del Real } \ 85c97d6d2cSSergio Andres Gomez Del Real } \ 86c97d6d2cSSergio Andres Gomez Del Real 87ff2de166SPaolo Bonzini target_ulong read_reg(CPUX86State *env, int reg, int size) 88c97d6d2cSSergio Andres Gomez Del Real { 89c97d6d2cSSergio Andres Gomez Del Real switch (size) { 90c97d6d2cSSergio Andres Gomez Del Real case 1: 91167c6aefSRoman Bolshakov return x86_reg(env, reg)->lx; 92c97d6d2cSSergio Andres Gomez Del Real case 2: 93167c6aefSRoman Bolshakov return x86_reg(env, reg)->rx; 94c97d6d2cSSergio Andres Gomez Del Real case 4: 95167c6aefSRoman Bolshakov return x86_reg(env, reg)->erx; 96c97d6d2cSSergio Andres Gomez Del Real case 8: 97167c6aefSRoman Bolshakov return x86_reg(env, reg)->rrx; 98c97d6d2cSSergio Andres Gomez Del Real default: 99e62963bfSPaolo Bonzini abort(); 100c97d6d2cSSergio Andres Gomez Del Real } 101c97d6d2cSSergio Andres Gomez Del Real return 0; 102c97d6d2cSSergio Andres Gomez Del Real } 103c97d6d2cSSergio Andres Gomez Del Real 104ff2de166SPaolo Bonzini void write_reg(CPUX86State *env, int reg, target_ulong val, int size) 105c97d6d2cSSergio Andres Gomez Del Real { 106c97d6d2cSSergio Andres Gomez Del Real switch (size) { 107c97d6d2cSSergio Andres Gomez Del Real case 1: 108167c6aefSRoman Bolshakov x86_reg(env, reg)->lx = val; 109c97d6d2cSSergio Andres Gomez Del Real break; 110c97d6d2cSSergio Andres Gomez Del Real case 2: 111167c6aefSRoman Bolshakov x86_reg(env, reg)->rx = val; 112c97d6d2cSSergio Andres Gomez Del Real break; 113c97d6d2cSSergio Andres Gomez Del Real case 4: 114167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = (uint32_t)val; 115c97d6d2cSSergio Andres Gomez Del Real break; 116c97d6d2cSSergio Andres Gomez Del Real case 8: 117167c6aefSRoman Bolshakov x86_reg(env, reg)->rrx = val; 118c97d6d2cSSergio Andres Gomez Del Real break; 119c97d6d2cSSergio Andres Gomez Del Real default: 120e62963bfSPaolo Bonzini abort(); 121c97d6d2cSSergio Andres Gomez Del Real } 122c97d6d2cSSergio Andres Gomez Del Real } 123c97d6d2cSSergio Andres Gomez Del Real 124*77a2dba4SPaolo Bonzini target_ulong read_val_from_reg(void *reg_ptr, int size) 125c97d6d2cSSergio Andres Gomez Del Real { 126ff2de166SPaolo Bonzini target_ulong val; 127c97d6d2cSSergio Andres Gomez Del Real 128c97d6d2cSSergio Andres Gomez Del Real switch (size) { 129c97d6d2cSSergio Andres Gomez Del Real case 1: 130c97d6d2cSSergio Andres Gomez Del Real val = *(uint8_t *)reg_ptr; 131c97d6d2cSSergio Andres Gomez Del Real break; 132c97d6d2cSSergio Andres Gomez Del Real case 2: 133c97d6d2cSSergio Andres Gomez Del Real val = *(uint16_t *)reg_ptr; 134c97d6d2cSSergio Andres Gomez Del Real break; 135c97d6d2cSSergio Andres Gomez Del Real case 4: 136c97d6d2cSSergio Andres Gomez Del Real val = *(uint32_t *)reg_ptr; 137c97d6d2cSSergio Andres Gomez Del Real break; 138c97d6d2cSSergio Andres Gomez Del Real case 8: 139c97d6d2cSSergio Andres Gomez Del Real val = *(uint64_t *)reg_ptr; 140c97d6d2cSSergio Andres Gomez Del Real break; 141c97d6d2cSSergio Andres Gomez Del Real default: 142e62963bfSPaolo Bonzini abort(); 143c97d6d2cSSergio Andres Gomez Del Real } 144c97d6d2cSSergio Andres Gomez Del Real return val; 145c97d6d2cSSergio Andres Gomez Del Real } 146c97d6d2cSSergio Andres Gomez Del Real 147*77a2dba4SPaolo Bonzini void write_val_to_reg(void *reg_ptr, target_ulong val, int size) 148c97d6d2cSSergio Andres Gomez Del Real { 149c97d6d2cSSergio Andres Gomez Del Real switch (size) { 150c97d6d2cSSergio Andres Gomez Del Real case 1: 151c97d6d2cSSergio Andres Gomez Del Real *(uint8_t *)reg_ptr = val; 152c97d6d2cSSergio Andres Gomez Del Real break; 153c97d6d2cSSergio Andres Gomez Del Real case 2: 154c97d6d2cSSergio Andres Gomez Del Real *(uint16_t *)reg_ptr = val; 155c97d6d2cSSergio Andres Gomez Del Real break; 156c97d6d2cSSergio Andres Gomez Del Real case 4: 157c97d6d2cSSergio Andres Gomez Del Real *(uint64_t *)reg_ptr = (uint32_t)val; 158c97d6d2cSSergio Andres Gomez Del Real break; 159c97d6d2cSSergio Andres Gomez Del Real case 8: 160c97d6d2cSSergio Andres Gomez Del Real *(uint64_t *)reg_ptr = val; 161c97d6d2cSSergio Andres Gomez Del Real break; 162c97d6d2cSSergio Andres Gomez Del Real default: 163e62963bfSPaolo Bonzini abort(); 164c97d6d2cSSergio Andres Gomez Del Real } 165c97d6d2cSSergio Andres Gomez Del Real } 166c97d6d2cSSergio Andres Gomez Del Real 167*77a2dba4SPaolo Bonzini static void write_val_to_mem(CPUX86State *env, target_ulong ptr, target_ulong val, int size) 168c97d6d2cSSergio Andres Gomez Del Real { 169*77a2dba4SPaolo Bonzini emul_ops->write_mem(env_cpu(env), &val, ptr, size); 170c97d6d2cSSergio Andres Gomez Del Real } 171c97d6d2cSSergio Andres Gomez Del Real 172*77a2dba4SPaolo Bonzini void write_val_ext(CPUX86State *env, struct x86_decode_op *decode, target_ulong val, int size) 173c97d6d2cSSergio Andres Gomez Del Real { 174*77a2dba4SPaolo Bonzini if (decode->type == X86_VAR_REG) { 175*77a2dba4SPaolo Bonzini write_val_to_reg(decode->regptr, val, size); 176*77a2dba4SPaolo Bonzini } else { 177*77a2dba4SPaolo Bonzini write_val_to_mem(env, decode->addr, val, size); 178c97d6d2cSSergio Andres Gomez Del Real } 179c97d6d2cSSergio Andres Gomez Del Real } 180c97d6d2cSSergio Andres Gomez Del Real 18136861198SPhilippe Mathieu-Daudé uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) 182c97d6d2cSSergio Andres Gomez Del Real { 183ae3c6134SWei Liu emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); 184e9c40026SWei Liu return env->emu_mmio_buf; 185c97d6d2cSSergio Andres Gomez Del Real } 186c97d6d2cSSergio Andres Gomez Del Real 187c97d6d2cSSergio Andres Gomez Del Real 188*77a2dba4SPaolo Bonzini static target_ulong read_val_from_mem(CPUX86State *env, target_long ptr, int size) 189c97d6d2cSSergio Andres Gomez Del Real { 190ff2de166SPaolo Bonzini target_ulong val; 191c97d6d2cSSergio Andres Gomez Del Real uint8_t *mmio_ptr; 192c97d6d2cSSergio Andres Gomez Del Real 193c97d6d2cSSergio Andres Gomez Del Real mmio_ptr = read_mmio(env, ptr, size); 194c97d6d2cSSergio Andres Gomez Del Real switch (size) { 195c97d6d2cSSergio Andres Gomez Del Real case 1: 196c97d6d2cSSergio Andres Gomez Del Real val = *(uint8_t *)mmio_ptr; 197c97d6d2cSSergio Andres Gomez Del Real break; 198c97d6d2cSSergio Andres Gomez Del Real case 2: 199c97d6d2cSSergio Andres Gomez Del Real val = *(uint16_t *)mmio_ptr; 200c97d6d2cSSergio Andres Gomez Del Real break; 201c97d6d2cSSergio Andres Gomez Del Real case 4: 202c97d6d2cSSergio Andres Gomez Del Real val = *(uint32_t *)mmio_ptr; 203c97d6d2cSSergio Andres Gomez Del Real break; 204c97d6d2cSSergio Andres Gomez Del Real case 8: 205c97d6d2cSSergio Andres Gomez Del Real val = *(uint64_t *)mmio_ptr; 206c97d6d2cSSergio Andres Gomez Del Real break; 207c97d6d2cSSergio Andres Gomez Del Real default: 208c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad size\n"); 209c97d6d2cSSergio Andres Gomez Del Real break; 210c97d6d2cSSergio Andres Gomez Del Real } 211c97d6d2cSSergio Andres Gomez Del Real return val; 212c97d6d2cSSergio Andres Gomez Del Real } 213c97d6d2cSSergio Andres Gomez Del Real 214*77a2dba4SPaolo Bonzini target_ulong read_val_ext(CPUX86State *env, struct x86_decode_op *decode, int size) 215*77a2dba4SPaolo Bonzini { 216*77a2dba4SPaolo Bonzini if (decode->type == X86_VAR_REG) { 217*77a2dba4SPaolo Bonzini return read_val_from_reg(decode->regptr, size); 218*77a2dba4SPaolo Bonzini } else { 219*77a2dba4SPaolo Bonzini return read_val_from_mem(env, decode->addr, size); 220*77a2dba4SPaolo Bonzini } 221*77a2dba4SPaolo Bonzini } 222*77a2dba4SPaolo Bonzini 22336861198SPhilippe Mathieu-Daudé static void fetch_operands(CPUX86State *env, struct x86_decode *decode, 224c97d6d2cSSergio Andres Gomez Del Real int n, bool val_op0, bool val_op1, bool val_op2) 225c97d6d2cSSergio Andres Gomez Del Real { 226c97d6d2cSSergio Andres Gomez Del Real int i; 227c97d6d2cSSergio Andres Gomez Del Real bool calc_val[3] = {val_op0, val_op1, val_op2}; 228c97d6d2cSSergio Andres Gomez Del Real 229c97d6d2cSSergio Andres Gomez Del Real for (i = 0; i < n; i++) { 230c97d6d2cSSergio Andres Gomez Del Real switch (decode->op[i].type) { 231c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_IMMEDIATE: 232c97d6d2cSSergio Andres Gomez Del Real break; 233c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_REG: 234*77a2dba4SPaolo Bonzini VM_PANIC_ON(!decode->op[i].regptr); 235c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 236*77a2dba4SPaolo Bonzini decode->op[i].val = read_val_from_reg(decode->op[i].regptr, 237c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 238c97d6d2cSSergio Andres Gomez Del Real } 239c97d6d2cSSergio Andres Gomez Del Real break; 240c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_RM: 241c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[i]); 242c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 243*77a2dba4SPaolo Bonzini decode->op[i].val = read_val_ext(env, &decode->op[i], 244c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 245c97d6d2cSSergio Andres Gomez Del Real } 246c97d6d2cSSergio Andres Gomez Del Real break; 247c97d6d2cSSergio Andres Gomez Del Real case X86_VAR_OFFSET: 248*77a2dba4SPaolo Bonzini decode->op[i].addr = decode_linear_addr(env, decode, 249*77a2dba4SPaolo Bonzini decode->op[i].addr, 2506701d81dSPaolo Bonzini R_DS); 251c97d6d2cSSergio Andres Gomez Del Real if (calc_val[i]) { 252*77a2dba4SPaolo Bonzini decode->op[i].val = read_val_ext(env, &decode->op[i], 253c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 254c97d6d2cSSergio Andres Gomez Del Real } 255c97d6d2cSSergio Andres Gomez Del Real break; 256c97d6d2cSSergio Andres Gomez Del Real default: 257c97d6d2cSSergio Andres Gomez Del Real break; 258c97d6d2cSSergio Andres Gomez Del Real } 259c97d6d2cSSergio Andres Gomez Del Real } 260c97d6d2cSSergio Andres Gomez Del Real } 261c97d6d2cSSergio Andres Gomez Del Real 26236861198SPhilippe Mathieu-Daudé static void exec_mov(CPUX86State *env, struct x86_decode *decode) 263c97d6d2cSSergio Andres Gomez Del Real { 264c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, true, false); 265*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], decode->op[1].val, 266c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 267c97d6d2cSSergio Andres Gomez Del Real 2685d32173fSRoman Bolshakov env->eip += decode->len; 269c97d6d2cSSergio Andres Gomez Del Real } 270c97d6d2cSSergio Andres Gomez Del Real 27136861198SPhilippe Mathieu-Daudé static void exec_add(CPUX86State *env, struct x86_decode *decode) 272c97d6d2cSSergio Andres Gomez Del Real { 273e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 2745d32173fSRoman Bolshakov env->eip += decode->len; 275c97d6d2cSSergio Andres Gomez Del Real } 276c97d6d2cSSergio Andres Gomez Del Real 27736861198SPhilippe Mathieu-Daudé static void exec_or(CPUX86State *env, struct x86_decode *decode) 278c97d6d2cSSergio Andres Gomez Del Real { 279e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); 2805d32173fSRoman Bolshakov env->eip += decode->len; 281c97d6d2cSSergio Andres Gomez Del Real } 282c97d6d2cSSergio Andres Gomez Del Real 28336861198SPhilippe Mathieu-Daudé static void exec_adc(CPUX86State *env, struct x86_decode *decode) 284c97d6d2cSSergio Andres Gomez Del Real { 285e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); 2865d32173fSRoman Bolshakov env->eip += decode->len; 287c97d6d2cSSergio Andres Gomez Del Real } 288c97d6d2cSSergio Andres Gomez Del Real 28936861198SPhilippe Mathieu-Daudé static void exec_sbb(CPUX86State *env, struct x86_decode *decode) 290c97d6d2cSSergio Andres Gomez Del Real { 291e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); 2925d32173fSRoman Bolshakov env->eip += decode->len; 293c97d6d2cSSergio Andres Gomez Del Real } 294c97d6d2cSSergio Andres Gomez Del Real 29536861198SPhilippe Mathieu-Daudé static void exec_and(CPUX86State *env, struct x86_decode *decode) 296c97d6d2cSSergio Andres Gomez Del Real { 297e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); 2985d32173fSRoman Bolshakov env->eip += decode->len; 299c97d6d2cSSergio Andres Gomez Del Real } 300c97d6d2cSSergio Andres Gomez Del Real 30136861198SPhilippe Mathieu-Daudé static void exec_sub(CPUX86State *env, struct x86_decode *decode) 302c97d6d2cSSergio Andres Gomez Del Real { 303e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); 3045d32173fSRoman Bolshakov env->eip += decode->len; 305c97d6d2cSSergio Andres Gomez Del Real } 306c97d6d2cSSergio Andres Gomez Del Real 30736861198SPhilippe Mathieu-Daudé static void exec_xor(CPUX86State *env, struct x86_decode *decode) 308c97d6d2cSSergio Andres Gomez Del Real { 309e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); 3105d32173fSRoman Bolshakov env->eip += decode->len; 311c97d6d2cSSergio Andres Gomez Del Real } 312c97d6d2cSSergio Andres Gomez Del Real 31336861198SPhilippe Mathieu-Daudé static void exec_neg(CPUX86State *env, struct x86_decode *decode) 314c97d6d2cSSergio Andres Gomez Del Real { 315e8a63257SPaolo Bonzini /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ 316c97d6d2cSSergio Andres Gomez Del Real int32_t val; 317c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 318c97d6d2cSSergio Andres Gomez Del Real 319c97d6d2cSSergio Andres Gomez Del Real val = 0 - sign(decode->op[1].val, decode->operand_size); 320*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[1], val, decode->operand_size); 321c97d6d2cSSergio Andres Gomez Del Real 322c97d6d2cSSergio Andres Gomez Del Real if (4 == decode->operand_size) { 323e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); 324c97d6d2cSSergio Andres Gomez Del Real } else if (2 == decode->operand_size) { 325e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val); 326c97d6d2cSSergio Andres Gomez Del Real } else if (1 == decode->operand_size) { 327e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val); 328c97d6d2cSSergio Andres Gomez Del Real } else { 329c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bad op size\n"); 330c97d6d2cSSergio Andres Gomez Del Real } 331c97d6d2cSSergio Andres Gomez Del Real 332c97d6d2cSSergio Andres Gomez Del Real /*lflags_to_rflags(env);*/ 3335d32173fSRoman Bolshakov env->eip += decode->len; 334c97d6d2cSSergio Andres Gomez Del Real } 335c97d6d2cSSergio Andres Gomez Del Real 33636861198SPhilippe Mathieu-Daudé static void exec_cmp(CPUX86State *env, struct x86_decode *decode) 337c97d6d2cSSergio Andres Gomez Del Real { 338e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 3395d32173fSRoman Bolshakov env->eip += decode->len; 340c97d6d2cSSergio Andres Gomez Del Real } 341c97d6d2cSSergio Andres Gomez Del Real 34236861198SPhilippe Mathieu-Daudé static void exec_inc(CPUX86State *env, struct x86_decode *decode) 343c97d6d2cSSergio Andres Gomez Del Real { 344c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 345c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = 0; 346c97d6d2cSSergio Andres Gomez Del Real 347e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); 348c97d6d2cSSergio Andres Gomez Del Real 3495d32173fSRoman Bolshakov env->eip += decode->len; 350c97d6d2cSSergio Andres Gomez Del Real } 351c97d6d2cSSergio Andres Gomez Del Real 35236861198SPhilippe Mathieu-Daudé static void exec_dec(CPUX86State *env, struct x86_decode *decode) 353c97d6d2cSSergio Andres Gomez Del Real { 354c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 355c97d6d2cSSergio Andres Gomez Del Real decode->op[1].val = 0; 356c97d6d2cSSergio Andres Gomez Del Real 357e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); 3585d32173fSRoman Bolshakov env->eip += decode->len; 359c97d6d2cSSergio Andres Gomez Del Real } 360c97d6d2cSSergio Andres Gomez Del Real 36136861198SPhilippe Mathieu-Daudé static void exec_tst(CPUX86State *env, struct x86_decode *decode) 362c97d6d2cSSergio Andres Gomez Del Real { 363e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); 3645d32173fSRoman Bolshakov env->eip += decode->len; 365c97d6d2cSSergio Andres Gomez Del Real } 366c97d6d2cSSergio Andres Gomez Del Real 36736861198SPhilippe Mathieu-Daudé static void exec_not(CPUX86State *env, struct x86_decode *decode) 368c97d6d2cSSergio Andres Gomez Del Real { 369c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 1, true, false, false); 370c97d6d2cSSergio Andres Gomez Del Real 371*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], ~decode->op[0].val, 372c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 3735d32173fSRoman Bolshakov env->eip += decode->len; 374c97d6d2cSSergio Andres Gomez Del Real } 375c97d6d2cSSergio Andres Gomez Del Real 37636861198SPhilippe Mathieu-Daudé void exec_movzx(CPUX86State *env, struct x86_decode *decode) 377c97d6d2cSSergio Andres Gomez Del Real { 378c97d6d2cSSergio Andres Gomez Del Real int src_op_size; 379c97d6d2cSSergio Andres Gomez Del Real int op_size = decode->operand_size; 380c97d6d2cSSergio Andres Gomez Del Real 381c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 1, false, false, false); 382c97d6d2cSSergio Andres Gomez Del Real 383c97d6d2cSSergio Andres Gomez Del Real if (0xb6 == decode->opcode[1]) { 384c97d6d2cSSergio Andres Gomez Del Real src_op_size = 1; 385c97d6d2cSSergio Andres Gomez Del Real } else { 386c97d6d2cSSergio Andres Gomez Del Real src_op_size = 2; 387c97d6d2cSSergio Andres Gomez Del Real } 388c97d6d2cSSergio Andres Gomez Del Real decode->operand_size = src_op_size; 389c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[1]); 390*77a2dba4SPaolo Bonzini decode->op[1].val = read_val_ext(env, &decode->op[1], src_op_size); 391*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], decode->op[1].val, op_size); 392c97d6d2cSSergio Andres Gomez Del Real 3935d32173fSRoman Bolshakov env->eip += decode->len; 394c97d6d2cSSergio Andres Gomez Del Real } 395c97d6d2cSSergio Andres Gomez Del Real 39636861198SPhilippe Mathieu-Daudé static void exec_out(CPUX86State *env, struct x86_decode *decode) 397c97d6d2cSSergio Andres Gomez Del Real { 398c97d6d2cSSergio Andres Gomez Del Real switch (decode->opcode[0]) { 399c97d6d2cSSergio Andres Gomez Del Real case 0xe6: 400444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); 401c97d6d2cSSergio Andres Gomez Del Real break; 402c97d6d2cSSergio Andres Gomez Del Real case 0xe7: 403444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, 404c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 405c97d6d2cSSergio Andres Gomez Del Real break; 406c97d6d2cSSergio Andres Gomez Del Real case 0xee: 407444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); 408c97d6d2cSSergio Andres Gomez Del Real break; 409c97d6d2cSSergio Andres Gomez Del Real case 0xef: 410444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, 41129a0af61SRichard Henderson decode->operand_size, 1); 412c97d6d2cSSergio Andres Gomez Del Real break; 413c97d6d2cSSergio Andres Gomez Del Real default: 414c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("Bad out opcode\n"); 415c97d6d2cSSergio Andres Gomez Del Real break; 416c97d6d2cSSergio Andres Gomez Del Real } 4175d32173fSRoman Bolshakov env->eip += decode->len; 418c97d6d2cSSergio Andres Gomez Del Real } 419c97d6d2cSSergio Andres Gomez Del Real 42036861198SPhilippe Mathieu-Daudé static void exec_in(CPUX86State *env, struct x86_decode *decode) 421c97d6d2cSSergio Andres Gomez Del Real { 422ff2de166SPaolo Bonzini target_ulong val = 0; 423c97d6d2cSSergio Andres Gomez Del Real switch (decode->opcode[0]) { 424c97d6d2cSSergio Andres Gomez Del Real case 0xe4: 425444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); 426c97d6d2cSSergio Andres Gomez Del Real break; 427c97d6d2cSSergio Andres Gomez Del Real case 0xe5: 428444bae08SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, 42929a0af61SRichard Henderson decode->operand_size, 1); 430c97d6d2cSSergio Andres Gomez Del Real if (decode->operand_size == 2) { 431c97d6d2cSSergio Andres Gomez Del Real AX(env) = val; 432c97d6d2cSSergio Andres Gomez Del Real } else { 433c97d6d2cSSergio Andres Gomez Del Real RAX(env) = (uint32_t)val; 434c97d6d2cSSergio Andres Gomez Del Real } 435c97d6d2cSSergio Andres Gomez Del Real break; 436c97d6d2cSSergio Andres Gomez Del Real case 0xec: 437444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); 438c97d6d2cSSergio Andres Gomez Del Real break; 439c97d6d2cSSergio Andres Gomez Del Real case 0xed: 440444bae08SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, 441444bae08SWei Liu decode->operand_size, 1); 442c97d6d2cSSergio Andres Gomez Del Real if (decode->operand_size == 2) { 443c97d6d2cSSergio Andres Gomez Del Real AX(env) = val; 444c97d6d2cSSergio Andres Gomez Del Real } else { 445c97d6d2cSSergio Andres Gomez Del Real RAX(env) = (uint32_t)val; 446c97d6d2cSSergio Andres Gomez Del Real } 447c97d6d2cSSergio Andres Gomez Del Real 448c97d6d2cSSergio Andres Gomez Del Real break; 449c97d6d2cSSergio Andres Gomez Del Real default: 450c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("Bad in opcode\n"); 451c97d6d2cSSergio Andres Gomez Del Real break; 452c97d6d2cSSergio Andres Gomez Del Real } 453c97d6d2cSSergio Andres Gomez Del Real 4545d32173fSRoman Bolshakov env->eip += decode->len; 455c97d6d2cSSergio Andres Gomez Del Real } 456c97d6d2cSSergio Andres Gomez Del Real 45736861198SPhilippe Mathieu-Daudé static inline void string_increment_reg(CPUX86State *env, int reg, 458c97d6d2cSSergio Andres Gomez Del Real struct x86_decode *decode) 459c97d6d2cSSergio Andres Gomez Del Real { 460ff2de166SPaolo Bonzini target_ulong val = read_reg(env, reg, decode->addressing_size); 461967f4da2SRoman Bolshakov if (env->eflags & DF_MASK) { 462c97d6d2cSSergio Andres Gomez Del Real val -= decode->operand_size; 463c97d6d2cSSergio Andres Gomez Del Real } else { 464c97d6d2cSSergio Andres Gomez Del Real val += decode->operand_size; 465c97d6d2cSSergio Andres Gomez Del Real } 466c97d6d2cSSergio Andres Gomez Del Real write_reg(env, reg, val, decode->addressing_size); 467c97d6d2cSSergio Andres Gomez Del Real } 468c97d6d2cSSergio Andres Gomez Del Real 46936861198SPhilippe Mathieu-Daudé static inline void string_rep(CPUX86State *env, struct x86_decode *decode, 47036861198SPhilippe Mathieu-Daudé void (*func)(CPUX86State *env, 471c97d6d2cSSergio Andres Gomez Del Real struct x86_decode *ins), int rep) 472c97d6d2cSSergio Andres Gomez Del Real { 473ff2de166SPaolo Bonzini target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size); 474c97d6d2cSSergio Andres Gomez Del Real while (rcx--) { 475c97d6d2cSSergio Andres Gomez Del Real func(env, decode); 4766701d81dSPaolo Bonzini write_reg(env, R_ECX, rcx, decode->addressing_size); 477c97d6d2cSSergio Andres Gomez Del Real if ((PREFIX_REP == rep) && !get_ZF(env)) { 478c97d6d2cSSergio Andres Gomez Del Real break; 479c97d6d2cSSergio Andres Gomez Del Real } 480c97d6d2cSSergio Andres Gomez Del Real if ((PREFIX_REPN == rep) && get_ZF(env)) { 481c97d6d2cSSergio Andres Gomez Del Real break; 482c97d6d2cSSergio Andres Gomez Del Real } 483c97d6d2cSSergio Andres Gomez Del Real } 484c97d6d2cSSergio Andres Gomez Del Real } 485c97d6d2cSSergio Andres Gomez Del Real 48636861198SPhilippe Mathieu-Daudé static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) 487c97d6d2cSSergio Andres Gomez Del Real { 48829a0af61SRichard Henderson target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), 48929a0af61SRichard Henderson decode->addressing_size, R_ES); 490c97d6d2cSSergio Andres Gomez Del Real 491e9c40026SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, 492c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 49363d8bc66SWei Liu emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr, 49429a0af61SRichard Henderson decode->operand_size); 495c97d6d2cSSergio Andres Gomez Del Real 4966701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 497c97d6d2cSSergio Andres Gomez Del Real } 498c97d6d2cSSergio Andres Gomez Del Real 49936861198SPhilippe Mathieu-Daudé static void exec_ins(CPUX86State *env, struct x86_decode *decode) 500c97d6d2cSSergio Andres Gomez Del Real { 501c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 502c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_ins_single, 0); 503c97d6d2cSSergio Andres Gomez Del Real } else { 504c97d6d2cSSergio Andres Gomez Del Real exec_ins_single(env, decode); 505c97d6d2cSSergio Andres Gomez Del Real } 506c97d6d2cSSergio Andres Gomez Del Real 5075d32173fSRoman Bolshakov env->eip += decode->len; 508c97d6d2cSSergio Andres Gomez Del Real } 509c97d6d2cSSergio Andres Gomez Del Real 51036861198SPhilippe Mathieu-Daudé static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) 511c97d6d2cSSergio Andres Gomez Del Real { 512ff2de166SPaolo Bonzini target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); 513c97d6d2cSSergio Andres Gomez Del Real 514ae3c6134SWei Liu emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr, 51529a0af61SRichard Henderson decode->operand_size); 516e9c40026SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, 517c97d6d2cSSergio Andres Gomez Del Real decode->operand_size, 1); 518c97d6d2cSSergio Andres Gomez Del Real 5196701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 520c97d6d2cSSergio Andres Gomez Del Real } 521c97d6d2cSSergio Andres Gomez Del Real 52236861198SPhilippe Mathieu-Daudé static void exec_outs(CPUX86State *env, struct x86_decode *decode) 523c97d6d2cSSergio Andres Gomez Del Real { 524c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 525c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_outs_single, 0); 526c97d6d2cSSergio Andres Gomez Del Real } else { 527c97d6d2cSSergio Andres Gomez Del Real exec_outs_single(env, decode); 528c97d6d2cSSergio Andres Gomez Del Real } 529c97d6d2cSSergio Andres Gomez Del Real 5305d32173fSRoman Bolshakov env->eip += decode->len; 531c97d6d2cSSergio Andres Gomez Del Real } 532c97d6d2cSSergio Andres Gomez Del Real 53336861198SPhilippe Mathieu-Daudé static void exec_movs_single(CPUX86State *env, struct x86_decode *decode) 534c97d6d2cSSergio Andres Gomez Del Real { 535ff2de166SPaolo Bonzini target_ulong src_addr; 536ff2de166SPaolo Bonzini target_ulong dst_addr; 537ff2de166SPaolo Bonzini target_ulong val; 538c97d6d2cSSergio Andres Gomez Del Real 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); 542c97d6d2cSSergio Andres Gomez Del Real 543*77a2dba4SPaolo Bonzini val = read_val_from_mem(env, src_addr, decode->operand_size); 544*77a2dba4SPaolo Bonzini write_val_to_mem(env, dst_addr, val, decode->operand_size); 545c97d6d2cSSergio Andres Gomez Del Real 5466701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 5476701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 548c97d6d2cSSergio Andres Gomez Del Real } 549c97d6d2cSSergio Andres Gomez Del Real 55036861198SPhilippe Mathieu-Daudé static void exec_movs(CPUX86State *env, struct x86_decode *decode) 551c97d6d2cSSergio Andres Gomez Del Real { 552c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 553c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_movs_single, 0); 554c97d6d2cSSergio Andres Gomez Del Real } else { 555c97d6d2cSSergio Andres Gomez Del Real exec_movs_single(env, decode); 556c97d6d2cSSergio Andres Gomez Del Real } 557c97d6d2cSSergio Andres Gomez Del Real 5585d32173fSRoman Bolshakov env->eip += decode->len; 559c97d6d2cSSergio Andres Gomez Del Real } 560c97d6d2cSSergio Andres Gomez Del Real 56136861198SPhilippe Mathieu-Daudé static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode) 562c97d6d2cSSergio Andres Gomez Del Real { 563ff2de166SPaolo Bonzini target_ulong src_addr; 564ff2de166SPaolo Bonzini target_ulong dst_addr; 565c97d6d2cSSergio Andres Gomez Del Real 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); 569c97d6d2cSSergio Andres Gomez Del Real 570c97d6d2cSSergio Andres Gomez Del Real decode->op[0].type = X86_VAR_IMMEDIATE; 571*77a2dba4SPaolo Bonzini decode->op[0].val = read_val_from_mem(env, src_addr, decode->operand_size); 572c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 573*77a2dba4SPaolo Bonzini decode->op[1].val = read_val_from_mem(env, dst_addr, decode->operand_size); 574c97d6d2cSSergio Andres Gomez Del Real 575e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 576c97d6d2cSSergio Andres Gomez Del Real 5776701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 5786701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 579c97d6d2cSSergio Andres Gomez Del Real } 580c97d6d2cSSergio Andres Gomez Del Real 58136861198SPhilippe Mathieu-Daudé static void exec_cmps(CPUX86State *env, struct x86_decode *decode) 582c97d6d2cSSergio Andres Gomez Del Real { 583c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 584c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_cmps_single, decode->rep); 585c97d6d2cSSergio Andres Gomez Del Real } else { 586c97d6d2cSSergio Andres Gomez Del Real exec_cmps_single(env, decode); 587c97d6d2cSSergio Andres Gomez Del Real } 5885d32173fSRoman Bolshakov env->eip += decode->len; 589c97d6d2cSSergio Andres Gomez Del Real } 590c97d6d2cSSergio Andres Gomez Del Real 591c97d6d2cSSergio Andres Gomez Del Real 59236861198SPhilippe Mathieu-Daudé static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) 593c97d6d2cSSergio Andres Gomez Del Real { 594ff2de166SPaolo Bonzini target_ulong addr; 595ff2de166SPaolo Bonzini target_ulong val; 596c97d6d2cSSergio Andres Gomez Del Real 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); 60063d8bc66SWei Liu emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size); 601c97d6d2cSSergio Andres Gomez Del Real 6026701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 603c97d6d2cSSergio Andres Gomez Del Real } 604c97d6d2cSSergio Andres Gomez Del Real 605c97d6d2cSSergio Andres Gomez Del Real 60636861198SPhilippe Mathieu-Daudé static void exec_stos(CPUX86State *env, struct x86_decode *decode) 607c97d6d2cSSergio Andres Gomez Del Real { 608c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 609c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_stos_single, 0); 610c97d6d2cSSergio Andres Gomez Del Real } else { 611c97d6d2cSSergio Andres Gomez Del Real exec_stos_single(env, decode); 612c97d6d2cSSergio Andres Gomez Del Real } 613c97d6d2cSSergio Andres Gomez Del Real 6145d32173fSRoman Bolshakov env->eip += decode->len; 615c97d6d2cSSergio Andres Gomez Del Real } 616c97d6d2cSSergio Andres Gomez Del Real 61736861198SPhilippe Mathieu-Daudé static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) 618c97d6d2cSSergio Andres Gomez Del Real { 619ff2de166SPaolo Bonzini target_ulong addr; 620c97d6d2cSSergio Andres Gomez Del Real 62129a0af61SRichard Henderson addr = linear_addr_size(env_cpu(env), RDI(env), 62229a0af61SRichard Henderson decode->addressing_size, R_ES); 623c97d6d2cSSergio Andres Gomez Del Real decode->op[1].type = X86_VAR_IMMEDIATE; 624ae3c6134SWei Liu emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); 625c97d6d2cSSergio Andres Gomez Del Real 626e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 6276701d81dSPaolo Bonzini string_increment_reg(env, R_EDI, decode); 628c97d6d2cSSergio Andres Gomez Del Real } 629c97d6d2cSSergio Andres Gomez Del Real 63036861198SPhilippe Mathieu-Daudé static void exec_scas(CPUX86State *env, struct x86_decode *decode) 631c97d6d2cSSergio Andres Gomez Del Real { 632c97d6d2cSSergio Andres Gomez Del Real decode->op[0].type = X86_VAR_REG; 6336701d81dSPaolo Bonzini decode->op[0].reg = R_EAX; 634c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 635c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_scas_single, decode->rep); 636c97d6d2cSSergio Andres Gomez Del Real } else { 637c97d6d2cSSergio Andres Gomez Del Real exec_scas_single(env, decode); 638c97d6d2cSSergio Andres Gomez Del Real } 639c97d6d2cSSergio Andres Gomez Del Real 6405d32173fSRoman Bolshakov env->eip += decode->len; 641c97d6d2cSSergio Andres Gomez Del Real } 642c97d6d2cSSergio Andres Gomez Del Real 64336861198SPhilippe Mathieu-Daudé static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) 644c97d6d2cSSergio Andres Gomez Del Real { 645ff2de166SPaolo Bonzini target_ulong addr; 646ff2de166SPaolo Bonzini target_ulong val = 0; 647c97d6d2cSSergio Andres Gomez Del Real 6486701d81dSPaolo Bonzini addr = decode_linear_addr(env, decode, RSI(env), R_DS); 649ae3c6134SWei Liu emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size); 6506701d81dSPaolo Bonzini write_reg(env, R_EAX, val, decode->operand_size); 651c97d6d2cSSergio Andres Gomez Del Real 6526701d81dSPaolo Bonzini string_increment_reg(env, R_ESI, decode); 653c97d6d2cSSergio Andres Gomez Del Real } 654c97d6d2cSSergio Andres Gomez Del Real 65536861198SPhilippe Mathieu-Daudé static void exec_lods(CPUX86State *env, struct x86_decode *decode) 656c97d6d2cSSergio Andres Gomez Del Real { 657c97d6d2cSSergio Andres Gomez Del Real if (decode->rep) { 658c97d6d2cSSergio Andres Gomez Del Real string_rep(env, decode, exec_lods_single, 0); 659c97d6d2cSSergio Andres Gomez Del Real } else { 660c97d6d2cSSergio Andres Gomez Del Real exec_lods_single(env, decode); 661c97d6d2cSSergio Andres Gomez Del Real } 662c97d6d2cSSergio Andres Gomez Del Real 6635d32173fSRoman Bolshakov env->eip += decode->len; 664c97d6d2cSSergio Andres Gomez Del Real } 665c97d6d2cSSergio Andres Gomez Del Real 66699e5aaf9SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code) 6670e27f3a5SPhil Dennis-Jordan { 6680e27f3a5SPhil Dennis-Jordan env->exception_nr = exception_index; 6690e27f3a5SPhil Dennis-Jordan env->error_code = error_code; 6700e27f3a5SPhil Dennis-Jordan env->has_error_code = true; 6710e27f3a5SPhil Dennis-Jordan env->exception_injected = 1; 6720e27f3a5SPhil Dennis-Jordan } 6730e27f3a5SPhil Dennis-Jordan 67436861198SPhilippe Mathieu-Daudé static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) 675c97d6d2cSSergio Andres Gomez Del Real { 67658567864SWei Liu emul_ops->simulate_rdmsr(env_cpu(env)); 6775d32173fSRoman Bolshakov env->eip += decode->len; 678c97d6d2cSSergio Andres Gomez Del Real } 679c97d6d2cSSergio Andres Gomez Del Real 68036861198SPhilippe Mathieu-Daudé static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) 681c97d6d2cSSergio Andres Gomez Del Real { 68258567864SWei Liu emul_ops->simulate_wrmsr(env_cpu(env)); 6835d32173fSRoman Bolshakov env->eip += decode->len; 684c97d6d2cSSergio Andres Gomez Del Real } 685c97d6d2cSSergio Andres Gomez Del Real 686c97d6d2cSSergio Andres Gomez Del Real /* 687c97d6d2cSSergio Andres Gomez Del Real * flag: 688c97d6d2cSSergio Andres Gomez Del Real * 0 - bt, 1 - btc, 2 - bts, 3 - btr 689c97d6d2cSSergio Andres Gomez Del Real */ 69036861198SPhilippe Mathieu-Daudé static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag) 691c97d6d2cSSergio Andres Gomez Del Real { 692c97d6d2cSSergio Andres Gomez Del Real int32_t displacement; 693c97d6d2cSSergio Andres Gomez Del Real uint8_t index; 694c97d6d2cSSergio Andres Gomez Del Real bool cf; 695c97d6d2cSSergio Andres Gomez Del Real int mask = (4 == decode->operand_size) ? 0x1f : 0xf; 696c97d6d2cSSergio Andres Gomez Del Real 697c97d6d2cSSergio Andres Gomez Del Real VM_PANIC_ON(decode->rex.rex); 698c97d6d2cSSergio Andres Gomez Del Real 699c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, true, false); 700c97d6d2cSSergio Andres Gomez Del Real index = decode->op[1].val & mask; 701c97d6d2cSSergio Andres Gomez Del Real 702c97d6d2cSSergio Andres Gomez Del Real if (decode->op[0].type != X86_VAR_REG) { 703c97d6d2cSSergio Andres Gomez Del Real if (4 == decode->operand_size) { 704c97d6d2cSSergio Andres Gomez Del Real displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; 705*77a2dba4SPaolo Bonzini decode->op[0].addr += 4 * displacement; 706c97d6d2cSSergio Andres Gomez Del Real } else if (2 == decode->operand_size) { 707c97d6d2cSSergio Andres Gomez Del Real displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; 708*77a2dba4SPaolo Bonzini decode->op[0].addr += 2 * displacement; 709c97d6d2cSSergio Andres Gomez Del Real } else { 710c97d6d2cSSergio Andres Gomez Del Real VM_PANIC("bt 64bit\n"); 711c97d6d2cSSergio Andres Gomez Del Real } 712c97d6d2cSSergio Andres Gomez Del Real } 713*77a2dba4SPaolo Bonzini decode->op[0].val = read_val_ext(env, &decode->op[0], 714c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 715c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> index) & 0x01; 716c97d6d2cSSergio Andres Gomez Del Real 717c97d6d2cSSergio Andres Gomez Del Real switch (flag) { 718c97d6d2cSSergio Andres Gomez Del Real case 0: 719c97d6d2cSSergio Andres Gomez Del Real set_CF(env, cf); 720c97d6d2cSSergio Andres Gomez Del Real return; 721c97d6d2cSSergio Andres Gomez Del Real case 1: 722c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val ^= (1u << index); 723c97d6d2cSSergio Andres Gomez Del Real break; 724c97d6d2cSSergio Andres Gomez Del Real case 2: 725c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val |= (1u << index); 726c97d6d2cSSergio Andres Gomez Del Real break; 727c97d6d2cSSergio Andres Gomez Del Real case 3: 728c97d6d2cSSergio Andres Gomez Del Real decode->op[0].val &= ~(1u << index); 729c97d6d2cSSergio Andres Gomez Del Real break; 730c97d6d2cSSergio Andres Gomez Del Real } 731*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], decode->op[0].val, 732c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 733c97d6d2cSSergio Andres Gomez Del Real set_CF(env, cf); 734c97d6d2cSSergio Andres Gomez Del Real } 735c97d6d2cSSergio Andres Gomez Del Real 73636861198SPhilippe Mathieu-Daudé static void exec_bt(CPUX86State *env, struct x86_decode *decode) 737c97d6d2cSSergio Andres Gomez Del Real { 738c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 0); 7395d32173fSRoman Bolshakov env->eip += decode->len; 740c97d6d2cSSergio Andres Gomez Del Real } 741c97d6d2cSSergio Andres Gomez Del Real 74236861198SPhilippe Mathieu-Daudé static void exec_btc(CPUX86State *env, struct x86_decode *decode) 743c97d6d2cSSergio Andres Gomez Del Real { 744c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 1); 7455d32173fSRoman Bolshakov env->eip += decode->len; 746c97d6d2cSSergio Andres Gomez Del Real } 747c97d6d2cSSergio Andres Gomez Del Real 74836861198SPhilippe Mathieu-Daudé static void exec_btr(CPUX86State *env, struct x86_decode *decode) 749c97d6d2cSSergio Andres Gomez Del Real { 750c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 3); 7515d32173fSRoman Bolshakov env->eip += decode->len; 752c97d6d2cSSergio Andres Gomez Del Real } 753c97d6d2cSSergio Andres Gomez Del Real 75436861198SPhilippe Mathieu-Daudé static void exec_bts(CPUX86State *env, struct x86_decode *decode) 755c97d6d2cSSergio Andres Gomez Del Real { 756c97d6d2cSSergio Andres Gomez Del Real do_bt(env, decode, 2); 7575d32173fSRoman Bolshakov env->eip += decode->len; 758c97d6d2cSSergio Andres Gomez Del Real } 759c97d6d2cSSergio Andres Gomez Del Real 76036861198SPhilippe Mathieu-Daudé void exec_shl(CPUX86State *env, struct x86_decode *decode) 761c97d6d2cSSergio Andres Gomez Del Real { 762c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 763c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 764c97d6d2cSSergio Andres Gomez Del Real 765c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 766c97d6d2cSSergio Andres Gomez Del Real 767c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 768c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; /* count is masked to 5 bits*/ 769c97d6d2cSSergio Andres Gomez Del Real if (!count) { 770c97d6d2cSSergio Andres Gomez Del Real goto exit; 771c97d6d2cSSergio Andres Gomez Del Real } 772c97d6d2cSSergio Andres Gomez Del Real 773c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 774c97d6d2cSSergio Andres Gomez Del Real case 1: 775c97d6d2cSSergio Andres Gomez Del Real { 776c97d6d2cSSergio Andres Gomez Del Real uint8_t res = 0; 777c97d6d2cSSergio Andres Gomez Del Real if (count <= 8) { 778c97d6d2cSSergio Andres Gomez Del Real res = (decode->op[0].val << count); 779c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (8 - count)) & 0x1; 780c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 7); 781c97d6d2cSSergio Andres Gomez Del Real } 782c97d6d2cSSergio Andres Gomez Del Real 783*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 1); 784e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); 785c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 786c97d6d2cSSergio Andres Gomez Del Real break; 787c97d6d2cSSergio Andres Gomez Del Real } 788c97d6d2cSSergio Andres Gomez Del Real case 2: 789c97d6d2cSSergio Andres Gomez Del Real { 790c97d6d2cSSergio Andres Gomez Del Real uint16_t res = 0; 791c97d6d2cSSergio Andres Gomez Del Real 792c97d6d2cSSergio Andres Gomez Del Real /* from bochs */ 793c97d6d2cSSergio Andres Gomez Del Real if (count <= 16) { 794c97d6d2cSSergio Andres Gomez Del Real res = (decode->op[0].val << count); 795c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (16 - count)) & 0x1; 796c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 15); /* of = cf ^ result15 */ 797c97d6d2cSSergio Andres Gomez Del Real } 798c97d6d2cSSergio Andres Gomez Del Real 799*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 2); 800e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); 801c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 802c97d6d2cSSergio Andres Gomez Del Real break; 803c97d6d2cSSergio Andres Gomez Del Real } 804c97d6d2cSSergio Andres Gomez Del Real case 4: 805c97d6d2cSSergio Andres Gomez Del Real { 806c97d6d2cSSergio Andres Gomez Del Real uint32_t res = decode->op[0].val << count; 807c97d6d2cSSergio Andres Gomez Del Real 808*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 4); 809e8a63257SPaolo Bonzini SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); 810c97d6d2cSSergio Andres Gomez Del Real cf = (decode->op[0].val >> (32 - count)) & 0x1; 811c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 31); /* of = cf ^ result31 */ 812c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 813c97d6d2cSSergio Andres Gomez Del Real break; 814c97d6d2cSSergio Andres Gomez Del Real } 815c97d6d2cSSergio Andres Gomez Del Real default: 816c97d6d2cSSergio Andres Gomez Del Real abort(); 817c97d6d2cSSergio Andres Gomez Del Real } 818c97d6d2cSSergio Andres Gomez Del Real 819c97d6d2cSSergio Andres Gomez Del Real exit: 820c97d6d2cSSergio Andres Gomez Del Real /* lflags_to_rflags(env); */ 8215d32173fSRoman Bolshakov env->eip += decode->len; 822c97d6d2cSSergio Andres Gomez Del Real } 823c97d6d2cSSergio Andres Gomez Del Real 824c97d6d2cSSergio Andres Gomez Del Real void exec_movsx(CPUX86State *env, struct x86_decode *decode) 825c97d6d2cSSergio Andres Gomez Del Real { 826c97d6d2cSSergio Andres Gomez Del Real int src_op_size; 827c97d6d2cSSergio Andres Gomez Del Real int op_size = decode->operand_size; 828c97d6d2cSSergio Andres Gomez Del Real 829c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, false, false, false); 830c97d6d2cSSergio Andres Gomez Del Real 831c97d6d2cSSergio Andres Gomez Del Real if (0xbe == decode->opcode[1]) { 832c97d6d2cSSergio Andres Gomez Del Real src_op_size = 1; 833c97d6d2cSSergio Andres Gomez Del Real } else { 834c97d6d2cSSergio Andres Gomez Del Real src_op_size = 2; 835c97d6d2cSSergio Andres Gomez Del Real } 836c97d6d2cSSergio Andres Gomez Del Real 837c97d6d2cSSergio Andres Gomez Del Real decode->operand_size = src_op_size; 838c97d6d2cSSergio Andres Gomez Del Real calc_modrm_operand(env, decode, &decode->op[1]); 839*77a2dba4SPaolo Bonzini decode->op[1].val = sign(read_val_ext(env, &decode->op[1], src_op_size), 840c97d6d2cSSergio Andres Gomez Del Real src_op_size); 841c97d6d2cSSergio Andres Gomez Del Real 842*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], decode->op[1].val, op_size); 843c97d6d2cSSergio Andres Gomez Del Real 8445d32173fSRoman Bolshakov env->eip += decode->len; 845c97d6d2cSSergio Andres Gomez Del Real } 846c97d6d2cSSergio Andres Gomez Del Real 84736861198SPhilippe Mathieu-Daudé void exec_ror(CPUX86State *env, struct x86_decode *decode) 848c97d6d2cSSergio Andres Gomez Del Real { 849c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 850c97d6d2cSSergio Andres Gomez Del Real 851c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 852c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 853c97d6d2cSSergio Andres Gomez Del Real 854c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 855c97d6d2cSSergio Andres Gomez Del Real case 1: 856c97d6d2cSSergio Andres Gomez Del Real { 857c97d6d2cSSergio Andres Gomez Del Real uint32_t bit6, bit7; 858c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 859c97d6d2cSSergio Andres Gomez Del Real 860c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x07) == 0) { 861c97d6d2cSSergio Andres Gomez Del Real if (count & 0x18) { 862c97d6d2cSSergio Andres Gomez Del Real bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; 863c97d6d2cSSergio Andres Gomez Del Real bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; 864c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 865c97d6d2cSSergio Andres Gomez Del Real } 866c97d6d2cSSergio Andres Gomez Del Real } else { 867c97d6d2cSSergio Andres Gomez Del Real count &= 0x7; /* use only bottom 3 bits */ 868c97d6d2cSSergio Andres Gomez Del Real res = ((uint8_t)decode->op[0].val >> count) | 869c97d6d2cSSergio Andres Gomez Del Real ((uint8_t)decode->op[0].val << (8 - count)); 870*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 1); 871c97d6d2cSSergio Andres Gomez Del Real bit6 = (res >> 6) & 1; 872c97d6d2cSSergio Andres Gomez Del Real bit7 = (res >> 7) & 1; 873c97d6d2cSSergio Andres Gomez Del Real /* set eflags: ROR count affects the following flags: C, O */ 874c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 875c97d6d2cSSergio Andres Gomez Del Real } 876c97d6d2cSSergio Andres Gomez Del Real break; 877c97d6d2cSSergio Andres Gomez Del Real } 878c97d6d2cSSergio Andres Gomez Del Real case 2: 879c97d6d2cSSergio Andres Gomez Del Real { 880c97d6d2cSSergio Andres Gomez Del Real uint32_t bit14, bit15; 881c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 882c97d6d2cSSergio Andres Gomez Del Real 883c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x0f) == 0) { 884c97d6d2cSSergio Andres Gomez Del Real if (count & 0x10) { 885c97d6d2cSSergio Andres Gomez Del Real bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; 886c97d6d2cSSergio Andres Gomez Del Real bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; 887c97d6d2cSSergio Andres Gomez Del Real /* of = result14 ^ result15 */ 888c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 889c97d6d2cSSergio Andres Gomez Del Real } 890c97d6d2cSSergio Andres Gomez Del Real } else { 891c97d6d2cSSergio Andres Gomez Del Real count &= 0x0f; /* use only 4 LSB's */ 892c97d6d2cSSergio Andres Gomez Del Real res = ((uint16_t)decode->op[0].val >> count) | 893c97d6d2cSSergio Andres Gomez Del Real ((uint16_t)decode->op[0].val << (16 - count)); 894*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 2); 895c97d6d2cSSergio Andres Gomez Del Real 896c97d6d2cSSergio Andres Gomez Del Real bit14 = (res >> 14) & 1; 897c97d6d2cSSergio Andres Gomez Del Real bit15 = (res >> 15) & 1; 898c97d6d2cSSergio Andres Gomez Del Real /* of = result14 ^ result15 */ 899c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 900c97d6d2cSSergio Andres Gomez Del Real } 901c97d6d2cSSergio Andres Gomez Del Real break; 902c97d6d2cSSergio Andres Gomez Del Real } 903c97d6d2cSSergio Andres Gomez Del Real case 4: 904c97d6d2cSSergio Andres Gomez Del Real { 905c97d6d2cSSergio Andres Gomez Del Real uint32_t bit31, bit30; 906c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 907c97d6d2cSSergio Andres Gomez Del Real 908c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; 909c97d6d2cSSergio Andres Gomez Del Real if (count) { 910c97d6d2cSSergio Andres Gomez Del Real res = ((uint32_t)decode->op[0].val >> count) | 911c97d6d2cSSergio Andres Gomez Del Real ((uint32_t)decode->op[0].val << (32 - count)); 912*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 4); 913c97d6d2cSSergio Andres Gomez Del Real 914c97d6d2cSSergio Andres Gomez Del Real bit31 = (res >> 31) & 1; 915c97d6d2cSSergio Andres Gomez Del Real bit30 = (res >> 30) & 1; 916c97d6d2cSSergio Andres Gomez Del Real /* of = result30 ^ result31 */ 917c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31); 918c97d6d2cSSergio Andres Gomez Del Real } 919c97d6d2cSSergio Andres Gomez Del Real break; 920c97d6d2cSSergio Andres Gomez Del Real } 921c97d6d2cSSergio Andres Gomez Del Real } 9225d32173fSRoman Bolshakov env->eip += decode->len; 923c97d6d2cSSergio Andres Gomez Del Real } 924c97d6d2cSSergio Andres Gomez Del Real 92536861198SPhilippe Mathieu-Daudé void exec_rol(CPUX86State *env, struct x86_decode *decode) 926c97d6d2cSSergio Andres Gomez Del Real { 927c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 928c97d6d2cSSergio Andres Gomez Del Real 929c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 930c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val; 931c97d6d2cSSergio Andres Gomez Del Real 932c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 933c97d6d2cSSergio Andres Gomez Del Real case 1: 934c97d6d2cSSergio Andres Gomez Del Real { 935c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit7; 936c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 937c97d6d2cSSergio Andres Gomez Del Real 938c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x07) == 0) { 939c97d6d2cSSergio Andres Gomez Del Real if (count & 0x18) { 940c97d6d2cSSergio Andres Gomez Del Real bit0 = ((uint8_t)decode->op[0].val & 1); 941c97d6d2cSSergio Andres Gomez Del Real bit7 = ((uint8_t)decode->op[0].val >> 7); 942c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 943c97d6d2cSSergio Andres Gomez Del Real } 944c97d6d2cSSergio Andres Gomez Del Real } else { 945c97d6d2cSSergio Andres Gomez Del Real count &= 0x7; /* use only lowest 3 bits */ 946c97d6d2cSSergio Andres Gomez Del Real res = ((uint8_t)decode->op[0].val << count) | 947c97d6d2cSSergio Andres Gomez Del Real ((uint8_t)decode->op[0].val >> (8 - count)); 948c97d6d2cSSergio Andres Gomez Del Real 949*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 1); 950c97d6d2cSSergio Andres Gomez Del Real /* set eflags: 951c97d6d2cSSergio Andres Gomez Del Real * ROL count affects the following flags: C, O 952c97d6d2cSSergio Andres Gomez Del Real */ 953c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 1); 954c97d6d2cSSergio Andres Gomez Del Real bit7 = (res >> 7); 955c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 956c97d6d2cSSergio Andres Gomez Del Real } 957c97d6d2cSSergio Andres Gomez Del Real break; 958c97d6d2cSSergio Andres Gomez Del Real } 959c97d6d2cSSergio Andres Gomez Del Real case 2: 960c97d6d2cSSergio Andres Gomez Del Real { 961c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit15; 962c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 963c97d6d2cSSergio Andres Gomez Del Real 964c97d6d2cSSergio Andres Gomez Del Real if ((count & 0x0f) == 0) { 965c97d6d2cSSergio Andres Gomez Del Real if (count & 0x10) { 966c97d6d2cSSergio Andres Gomez Del Real bit0 = ((uint16_t)decode->op[0].val & 0x1); 967c97d6d2cSSergio Andres Gomez Del Real bit15 = ((uint16_t)decode->op[0].val >> 15); 968c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result15 */ 969c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 970c97d6d2cSSergio Andres Gomez Del Real } 971c97d6d2cSSergio Andres Gomez Del Real } else { 972c97d6d2cSSergio Andres Gomez Del Real count &= 0x0f; /* only use bottom 4 bits */ 973c97d6d2cSSergio Andres Gomez Del Real res = ((uint16_t)decode->op[0].val << count) | 974c97d6d2cSSergio Andres Gomez Del Real ((uint16_t)decode->op[0].val >> (16 - count)); 975c97d6d2cSSergio Andres Gomez Del Real 976*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 2); 977c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 0x1); 978c97d6d2cSSergio Andres Gomez Del Real bit15 = (res >> 15); 979c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result15 */ 980c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 981c97d6d2cSSergio Andres Gomez Del Real } 982c97d6d2cSSergio Andres Gomez Del Real break; 983c97d6d2cSSergio Andres Gomez Del Real } 984c97d6d2cSSergio Andres Gomez Del Real case 4: 985c97d6d2cSSergio Andres Gomez Del Real { 986c97d6d2cSSergio Andres Gomez Del Real uint32_t bit0, bit31; 987c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 988c97d6d2cSSergio Andres Gomez Del Real 989c97d6d2cSSergio Andres Gomez Del Real count &= 0x1f; 990c97d6d2cSSergio Andres Gomez Del Real if (count) { 991c97d6d2cSSergio Andres Gomez Del Real res = ((uint32_t)decode->op[0].val << count) | 992c97d6d2cSSergio Andres Gomez Del Real ((uint32_t)decode->op[0].val >> (32 - count)); 993c97d6d2cSSergio Andres Gomez Del Real 994*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 4); 995c97d6d2cSSergio Andres Gomez Del Real bit0 = (res & 0x1); 996c97d6d2cSSergio Andres Gomez Del Real bit31 = (res >> 31); 997c97d6d2cSSergio Andres Gomez Del Real /* of = cf ^ result31 */ 998c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0); 999c97d6d2cSSergio Andres Gomez Del Real } 1000c97d6d2cSSergio Andres Gomez Del Real break; 1001c97d6d2cSSergio Andres Gomez Del Real } 1002c97d6d2cSSergio Andres Gomez Del Real } 10035d32173fSRoman Bolshakov env->eip += decode->len; 1004c97d6d2cSSergio Andres Gomez Del Real } 1005c97d6d2cSSergio Andres Gomez Del Real 1006c97d6d2cSSergio Andres Gomez Del Real 100736861198SPhilippe Mathieu-Daudé void exec_rcl(CPUX86State *env, struct x86_decode *decode) 1008c97d6d2cSSergio Andres Gomez Del Real { 1009c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 1010c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 1011c97d6d2cSSergio Andres Gomez Del Real 1012c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1013c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val & 0x1f; 1014c97d6d2cSSergio Andres Gomez Del Real 1015c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 1016c97d6d2cSSergio Andres Gomez Del Real case 1: 1017c97d6d2cSSergio Andres Gomez Del Real { 1018c97d6d2cSSergio Andres Gomez Del Real uint8_t op1_8 = decode->op[0].val; 1019c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 1020c97d6d2cSSergio Andres Gomez Del Real count %= 9; 1021c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1022c97d6d2cSSergio Andres Gomez Del Real break; 1023c97d6d2cSSergio Andres Gomez Del Real } 1024c97d6d2cSSergio Andres Gomez Del Real 1025c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1026c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 << 1) | get_CF(env); 1027c97d6d2cSSergio Andres Gomez Del Real } else { 1028c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 << count) | (get_CF(env) << (count - 1)) | 1029c97d6d2cSSergio Andres Gomez Del Real (op1_8 >> (9 - count)); 1030c97d6d2cSSergio Andres Gomez Del Real } 1031c97d6d2cSSergio Andres Gomez Del Real 1032*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 1); 1033c97d6d2cSSergio Andres Gomez Del Real 1034c97d6d2cSSergio Andres Gomez Del Real cf = (op1_8 >> (8 - count)) & 0x01; 1035c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 7); /* of = cf ^ result7 */ 1036c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1037c97d6d2cSSergio Andres Gomez Del Real break; 1038c97d6d2cSSergio Andres Gomez Del Real } 1039c97d6d2cSSergio Andres Gomez Del Real case 2: 1040c97d6d2cSSergio Andres Gomez Del Real { 1041c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 1042c97d6d2cSSergio Andres Gomez Del Real uint16_t op1_16 = decode->op[0].val; 1043c97d6d2cSSergio Andres Gomez Del Real 1044c97d6d2cSSergio Andres Gomez Del Real count %= 17; 1045c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1046c97d6d2cSSergio Andres Gomez Del Real break; 1047c97d6d2cSSergio Andres Gomez Del Real } 1048c97d6d2cSSergio Andres Gomez Del Real 1049c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1050c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 << 1) | get_CF(env); 1051c97d6d2cSSergio Andres Gomez Del Real } else if (count == 16) { 1052c97d6d2cSSergio Andres Gomez Del Real res = (get_CF(env) << 15) | (op1_16 >> 1); 1053c97d6d2cSSergio Andres Gomez Del Real } else { /* 2..15 */ 1054c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 << count) | (get_CF(env) << (count - 1)) | 1055c97d6d2cSSergio Andres Gomez Del Real (op1_16 >> (17 - count)); 1056c97d6d2cSSergio Andres Gomez Del Real } 1057c97d6d2cSSergio Andres Gomez Del Real 1058*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 2); 1059c97d6d2cSSergio Andres Gomez Del Real 1060c97d6d2cSSergio Andres Gomez Del Real cf = (op1_16 >> (16 - count)) & 0x1; 1061c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 15); /* of = cf ^ result15 */ 1062c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1063c97d6d2cSSergio Andres Gomez Del Real break; 1064c97d6d2cSSergio Andres Gomez Del Real } 1065c97d6d2cSSergio Andres Gomez Del Real case 4: 1066c97d6d2cSSergio Andres Gomez Del Real { 1067c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 1068c97d6d2cSSergio Andres Gomez Del Real uint32_t op1_32 = decode->op[0].val; 1069c97d6d2cSSergio Andres Gomez Del Real 1070c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1071c97d6d2cSSergio Andres Gomez Del Real break; 1072c97d6d2cSSergio Andres Gomez Del Real } 1073c97d6d2cSSergio Andres Gomez Del Real 1074c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1075c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 << 1) | get_CF(env); 1076c97d6d2cSSergio Andres Gomez Del Real } else { 1077c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 << count) | (get_CF(env) << (count - 1)) | 1078c97d6d2cSSergio Andres Gomez Del Real (op1_32 >> (33 - count)); 1079c97d6d2cSSergio Andres Gomez Del Real } 1080c97d6d2cSSergio Andres Gomez Del Real 1081*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 4); 1082c97d6d2cSSergio Andres Gomez Del Real 1083c97d6d2cSSergio Andres Gomez Del Real cf = (op1_32 >> (32 - count)) & 0x1; 1084c97d6d2cSSergio Andres Gomez Del Real of = cf ^ (res >> 31); /* of = cf ^ result31 */ 1085c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1086c97d6d2cSSergio Andres Gomez Del Real break; 1087c97d6d2cSSergio Andres Gomez Del Real } 1088c97d6d2cSSergio Andres Gomez Del Real } 10895d32173fSRoman Bolshakov env->eip += decode->len; 1090c97d6d2cSSergio Andres Gomez Del Real } 1091c97d6d2cSSergio Andres Gomez Del Real 109236861198SPhilippe Mathieu-Daudé void exec_rcr(CPUX86State *env, struct x86_decode *decode) 1093c97d6d2cSSergio Andres Gomez Del Real { 1094c97d6d2cSSergio Andres Gomez Del Real uint8_t count; 1095c97d6d2cSSergio Andres Gomez Del Real int of = 0, cf = 0; 1096c97d6d2cSSergio Andres Gomez Del Real 1097c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1098c97d6d2cSSergio Andres Gomez Del Real count = decode->op[1].val & 0x1f; 1099c97d6d2cSSergio Andres Gomez Del Real 1100c97d6d2cSSergio Andres Gomez Del Real switch (decode->operand_size) { 1101c97d6d2cSSergio Andres Gomez Del Real case 1: 1102c97d6d2cSSergio Andres Gomez Del Real { 1103c97d6d2cSSergio Andres Gomez Del Real uint8_t op1_8 = decode->op[0].val; 1104c97d6d2cSSergio Andres Gomez Del Real uint8_t res; 1105c97d6d2cSSergio Andres Gomez Del Real 1106c97d6d2cSSergio Andres Gomez Del Real count %= 9; 1107c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1108c97d6d2cSSergio Andres Gomez Del Real break; 1109c97d6d2cSSergio Andres Gomez Del Real } 1110c97d6d2cSSergio Andres Gomez Del Real res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | 1111c97d6d2cSSergio Andres Gomez Del Real (op1_8 << (9 - count)); 1112c97d6d2cSSergio Andres Gomez Del Real 1113*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 1); 1114c97d6d2cSSergio Andres Gomez Del Real 1115c97d6d2cSSergio Andres Gomez Del Real cf = (op1_8 >> (count - 1)) & 0x1; 1116c97d6d2cSSergio Andres Gomez Del Real of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ 1117c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1118c97d6d2cSSergio Andres Gomez Del Real break; 1119c97d6d2cSSergio Andres Gomez Del Real } 1120c97d6d2cSSergio Andres Gomez Del Real case 2: 1121c97d6d2cSSergio Andres Gomez Del Real { 1122c97d6d2cSSergio Andres Gomez Del Real uint16_t op1_16 = decode->op[0].val; 1123c97d6d2cSSergio Andres Gomez Del Real uint16_t res; 1124c97d6d2cSSergio Andres Gomez Del Real 1125c97d6d2cSSergio Andres Gomez Del Real count %= 17; 1126c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1127c97d6d2cSSergio Andres Gomez Del Real break; 1128c97d6d2cSSergio Andres Gomez Del Real } 1129c97d6d2cSSergio Andres Gomez Del Real res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | 1130c97d6d2cSSergio Andres Gomez Del Real (op1_16 << (17 - count)); 1131c97d6d2cSSergio Andres Gomez Del Real 1132*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 2); 1133c97d6d2cSSergio Andres Gomez Del Real 1134c97d6d2cSSergio Andres Gomez Del Real cf = (op1_16 >> (count - 1)) & 0x1; 1135c97d6d2cSSergio Andres Gomez Del Real of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ 1136c97d6d2cSSergio Andres Gomez Del Real result14 */ 1137c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1138c97d6d2cSSergio Andres Gomez Del Real break; 1139c97d6d2cSSergio Andres Gomez Del Real } 1140c97d6d2cSSergio Andres Gomez Del Real case 4: 1141c97d6d2cSSergio Andres Gomez Del Real { 1142c97d6d2cSSergio Andres Gomez Del Real uint32_t res; 1143c97d6d2cSSergio Andres Gomez Del Real uint32_t op1_32 = decode->op[0].val; 1144c97d6d2cSSergio Andres Gomez Del Real 1145c97d6d2cSSergio Andres Gomez Del Real if (!count) { 1146c97d6d2cSSergio Andres Gomez Del Real break; 1147c97d6d2cSSergio Andres Gomez Del Real } 1148c97d6d2cSSergio Andres Gomez Del Real 1149c97d6d2cSSergio Andres Gomez Del Real if (1 == count) { 1150c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 >> 1) | (get_CF(env) << 31); 1151c97d6d2cSSergio Andres Gomez Del Real } else { 1152c97d6d2cSSergio Andres Gomez Del Real res = (op1_32 >> count) | (get_CF(env) << (32 - count)) | 1153c97d6d2cSSergio Andres Gomez Del Real (op1_32 << (33 - count)); 1154c97d6d2cSSergio Andres Gomez Del Real } 1155c97d6d2cSSergio Andres Gomez Del Real 1156*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], res, 4); 1157c97d6d2cSSergio Andres Gomez Del Real 1158c97d6d2cSSergio Andres Gomez Del Real cf = (op1_32 >> (count - 1)) & 0x1; 1159c97d6d2cSSergio Andres Gomez Del Real of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ 1160c97d6d2cSSergio Andres Gomez Del Real SET_FLAGS_OxxxxC(env, of, cf); 1161c97d6d2cSSergio Andres Gomez Del Real break; 1162c97d6d2cSSergio Andres Gomez Del Real } 1163c97d6d2cSSergio Andres Gomez Del Real } 11645d32173fSRoman Bolshakov env->eip += decode->len; 1165c97d6d2cSSergio Andres Gomez Del Real } 1166c97d6d2cSSergio Andres Gomez Del Real 116736861198SPhilippe Mathieu-Daudé static void exec_xchg(CPUX86State *env, struct x86_decode *decode) 1168c97d6d2cSSergio Andres Gomez Del Real { 1169c97d6d2cSSergio Andres Gomez Del Real fetch_operands(env, decode, 2, true, true, false); 1170c97d6d2cSSergio Andres Gomez Del Real 1171*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[0], decode->op[1].val, 1172c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1173*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[1], decode->op[0].val, 1174c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1175c97d6d2cSSergio Andres Gomez Del Real 11765d32173fSRoman Bolshakov env->eip += decode->len; 1177c97d6d2cSSergio Andres Gomez Del Real } 1178c97d6d2cSSergio Andres Gomez Del Real 117936861198SPhilippe Mathieu-Daudé static void exec_xadd(CPUX86State *env, struct x86_decode *decode) 1180c97d6d2cSSergio Andres Gomez Del Real { 1181e8a63257SPaolo Bonzini EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 1182*77a2dba4SPaolo Bonzini write_val_ext(env, &decode->op[1], decode->op[0].val, 1183c97d6d2cSSergio Andres Gomez Del Real decode->operand_size); 1184c97d6d2cSSergio Andres Gomez Del Real 11855d32173fSRoman Bolshakov env->eip += decode->len; 1186c97d6d2cSSergio Andres Gomez Del Real } 1187c97d6d2cSSergio Andres Gomez Del Real 1188c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler { 1189c97d6d2cSSergio Andres Gomez Del Real enum x86_decode_cmd cmd; 119036861198SPhilippe Mathieu-Daudé void (*handler)(CPUX86State *env, struct x86_decode *ins); 1191c97d6d2cSSergio Andres Gomez Del Real } handlers[] = { 1192c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INVL, NULL,}, 1193c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOV, exec_mov}, 1194c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ADD, exec_add}, 1195c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OR, exec_or}, 1196c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ADC, exec_adc}, 1197c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SBB, exec_sbb}, 1198c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_AND, exec_and}, 1199c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SUB, exec_sub}, 1200c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_NEG, exec_neg}, 1201c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XOR, exec_xor}, 1202c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_CMP, exec_cmp}, 1203c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INC, exec_inc}, 1204c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_DEC, exec_dec}, 1205c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_TST, exec_tst}, 1206c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_NOT, exec_not}, 1207c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVZX, exec_movzx}, 1208c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OUT, exec_out}, 1209c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_IN, exec_in}, 1210c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_INS, exec_ins}, 1211c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_OUTS, exec_outs}, 1212c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RDMSR, exec_rdmsr}, 1213c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_WRMSR, exec_wrmsr}, 1214c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BT, exec_bt}, 1215c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTR, exec_btr}, 1216c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTC, exec_btc}, 1217c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_BTS, exec_bts}, 1218c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SHL, exec_shl}, 1219c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ROL, exec_rol}, 1220c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_ROR, exec_ror}, 1221c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RCR, exec_rcr}, 1222c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_RCL, exec_rcl}, 1223c97d6d2cSSergio Andres Gomez Del Real /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/ 1224c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVS, exec_movs}, 1225c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_CMPS, exec_cmps}, 1226c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_STOS, exec_stos}, 1227c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_SCAS, exec_scas}, 1228c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_LODS, exec_lods}, 1229c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_MOVSX, exec_movsx}, 1230c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XCHG, exec_xchg}, 1231c97d6d2cSSergio Andres Gomez Del Real {X86_DECODE_CMD_XADD, exec_xadd}, 1232c97d6d2cSSergio Andres Gomez Del Real }; 1233c97d6d2cSSergio Andres Gomez Del Real 1234c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; 1235c97d6d2cSSergio Andres Gomez Del Real 123626a44d9dSWei Liu const struct x86_emul_ops *emul_ops; 123726a44d9dSWei Liu 12380e4e622eSPhil Dennis-Jordan static void init_cmd_handler(void) 1239c97d6d2cSSergio Andres Gomez Del Real { 1240c97d6d2cSSergio Andres Gomez Del Real int i; 1241c97d6d2cSSergio Andres Gomez Del Real for (i = 0; i < ARRAY_SIZE(handlers); i++) { 1242c97d6d2cSSergio Andres Gomez Del Real _cmd_handler[handlers[i].cmd] = handlers[i]; 1243c97d6d2cSSergio Andres Gomez Del Real } 1244c97d6d2cSSergio Andres Gomez Del Real } 1245c97d6d2cSSergio Andres Gomez Del Real 124636861198SPhilippe Mathieu-Daudé bool exec_instruction(CPUX86State *env, struct x86_decode *ins) 1247c97d6d2cSSergio Andres Gomez Del Real { 1248c97d6d2cSSergio Andres Gomez Del Real if (!_cmd_handler[ins->cmd].handler) { 12497abf0d95SPaolo Bonzini printf("Unimplemented handler (" TARGET_FMT_lx ") for %d (%x %x) \n", env->eip, 1250c97d6d2cSSergio Andres Gomez Del Real ins->cmd, ins->opcode[0], 1251c97d6d2cSSergio Andres Gomez Del Real ins->opcode_len > 1 ? ins->opcode[1] : 0); 12525d32173fSRoman Bolshakov env->eip += ins->len; 1253c97d6d2cSSergio Andres Gomez Del Real return true; 1254c97d6d2cSSergio Andres Gomez Del Real } 1255c97d6d2cSSergio Andres Gomez Del Real 1256c97d6d2cSSergio Andres Gomez Del Real _cmd_handler[ins->cmd].handler(env, ins); 1257c97d6d2cSSergio Andres Gomez Del Real return true; 1258c97d6d2cSSergio Andres Gomez Del Real } 1259c97d6d2cSSergio Andres Gomez Del Real 126026a44d9dSWei Liu void init_emu(const struct x86_emul_ops *o) 1261c97d6d2cSSergio Andres Gomez Del Real { 126226a44d9dSWei Liu emul_ops = o; 1263c97d6d2cSSergio Andres Gomez Del Real init_cmd_handler(); 1264c97d6d2cSSergio Andres Gomez Del Real } 1265