1*27458df8SWei Liu /* 2*27458df8SWei Liu * Copyright (C) 2016 Veertu Inc, 3*27458df8SWei Liu * Copyright (C) 2017 Google Inc, 4*27458df8SWei Liu * 5*27458df8SWei Liu * This program is free software; you can redistribute it and/or 6*27458df8SWei Liu * modify it under the terms of the GNU Lesser General Public 7*27458df8SWei Liu * License as published by the Free Software Foundation; either 8*27458df8SWei Liu * version 2.1 of the License, or (at your option) any later version. 9*27458df8SWei Liu * 10*27458df8SWei Liu * This program is distributed in the hope that it will be useful, 11*27458df8SWei Liu * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*27458df8SWei Liu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13*27458df8SWei Liu * Lesser General Public License for more details. 14*27458df8SWei Liu * 15*27458df8SWei Liu * You should have received a copy of the GNU Lesser General Public 16*27458df8SWei Liu * License along with this program; if not, see <http://www.gnu.org/licenses/>. 17*27458df8SWei Liu */ 18*27458df8SWei Liu 19*27458df8SWei Liu ///////////////////////////////////////////////////////////////////////// 20*27458df8SWei Liu // 21*27458df8SWei Liu // Copyright (C) 2001-2012 The Bochs Project 22*27458df8SWei Liu // 23*27458df8SWei Liu // This library is free software; you can redistribute it and/or 24*27458df8SWei Liu // modify it under the terms of the GNU Lesser General Public 25*27458df8SWei Liu // License as published by the Free Software Foundation; either 26*27458df8SWei Liu // version 2.1 of the License, or (at your option) any later version. 27*27458df8SWei Liu // 28*27458df8SWei Liu // This library is distributed in the hope that it will be useful, 29*27458df8SWei Liu // but WITHOUT ANY WARRANTY; without even the implied warranty of 30*27458df8SWei Liu // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31*27458df8SWei Liu // Lesser General Public License for more details. 32*27458df8SWei Liu // 33*27458df8SWei Liu // You should have received a copy of the GNU Lesser General Public 34*27458df8SWei Liu // License along with this library; if not, write to the Free Software 35*27458df8SWei Liu // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA 36*27458df8SWei Liu ///////////////////////////////////////////////////////////////////////// 37*27458df8SWei Liu 38*27458df8SWei Liu #include "qemu/osdep.h" 39*27458df8SWei Liu #include "panic.h" 40*27458df8SWei Liu #include "x86_decode.h" 41*27458df8SWei Liu #include "x86.h" 42*27458df8SWei Liu #include "x86_emu.h" 43*27458df8SWei Liu #include "x86_flags.h" 44*27458df8SWei Liu 45*27458df8SWei Liu #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \ 46*27458df8SWei Liu { \ 47*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); \ 48*27458df8SWei Liu switch (decode->operand_size) { \ 49*27458df8SWei Liu case 1: \ 50*27458df8SWei Liu { \ 51*27458df8SWei Liu uint8_t v1 = (uint8_t)decode->op[0].val; \ 52*27458df8SWei Liu uint8_t v2 = (uint8_t)decode->op[1].val; \ 53*27458df8SWei Liu uint8_t diff = v1 cmd v2; \ 54*27458df8SWei Liu if (save_res) { \ 55*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, diff, 1); \ 56*27458df8SWei Liu } \ 57*27458df8SWei Liu FLAGS_FUNC##8(env, v1, v2, diff); \ 58*27458df8SWei Liu break; \ 59*27458df8SWei Liu } \ 60*27458df8SWei Liu case 2: \ 61*27458df8SWei Liu { \ 62*27458df8SWei Liu uint16_t v1 = (uint16_t)decode->op[0].val; \ 63*27458df8SWei Liu uint16_t v2 = (uint16_t)decode->op[1].val; \ 64*27458df8SWei Liu uint16_t diff = v1 cmd v2; \ 65*27458df8SWei Liu if (save_res) { \ 66*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, diff, 2); \ 67*27458df8SWei Liu } \ 68*27458df8SWei Liu FLAGS_FUNC##16(env, v1, v2, diff); \ 69*27458df8SWei Liu break; \ 70*27458df8SWei Liu } \ 71*27458df8SWei Liu case 4: \ 72*27458df8SWei Liu { \ 73*27458df8SWei Liu uint32_t v1 = (uint32_t)decode->op[0].val; \ 74*27458df8SWei Liu uint32_t v2 = (uint32_t)decode->op[1].val; \ 75*27458df8SWei Liu uint32_t diff = v1 cmd v2; \ 76*27458df8SWei Liu if (save_res) { \ 77*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, diff, 4); \ 78*27458df8SWei Liu } \ 79*27458df8SWei Liu FLAGS_FUNC##32(env, v1, v2, diff); \ 80*27458df8SWei Liu break; \ 81*27458df8SWei Liu } \ 82*27458df8SWei Liu default: \ 83*27458df8SWei Liu VM_PANIC("bad size\n"); \ 84*27458df8SWei Liu } \ 85*27458df8SWei Liu } \ 86*27458df8SWei Liu 87*27458df8SWei Liu target_ulong read_reg(CPUX86State *env, int reg, int size) 88*27458df8SWei Liu { 89*27458df8SWei Liu switch (size) { 90*27458df8SWei Liu case 1: 91*27458df8SWei Liu return x86_reg(env, reg)->lx; 92*27458df8SWei Liu case 2: 93*27458df8SWei Liu return x86_reg(env, reg)->rx; 94*27458df8SWei Liu case 4: 95*27458df8SWei Liu return x86_reg(env, reg)->erx; 96*27458df8SWei Liu case 8: 97*27458df8SWei Liu return x86_reg(env, reg)->rrx; 98*27458df8SWei Liu default: 99*27458df8SWei Liu abort(); 100*27458df8SWei Liu } 101*27458df8SWei Liu return 0; 102*27458df8SWei Liu } 103*27458df8SWei Liu 104*27458df8SWei Liu void write_reg(CPUX86State *env, int reg, target_ulong val, int size) 105*27458df8SWei Liu { 106*27458df8SWei Liu switch (size) { 107*27458df8SWei Liu case 1: 108*27458df8SWei Liu x86_reg(env, reg)->lx = val; 109*27458df8SWei Liu break; 110*27458df8SWei Liu case 2: 111*27458df8SWei Liu x86_reg(env, reg)->rx = val; 112*27458df8SWei Liu break; 113*27458df8SWei Liu case 4: 114*27458df8SWei Liu x86_reg(env, reg)->rrx = (uint32_t)val; 115*27458df8SWei Liu break; 116*27458df8SWei Liu case 8: 117*27458df8SWei Liu x86_reg(env, reg)->rrx = val; 118*27458df8SWei Liu break; 119*27458df8SWei Liu default: 120*27458df8SWei Liu abort(); 121*27458df8SWei Liu } 122*27458df8SWei Liu } 123*27458df8SWei Liu 124*27458df8SWei Liu target_ulong read_val_from_reg(target_ulong reg_ptr, int size) 125*27458df8SWei Liu { 126*27458df8SWei Liu target_ulong val; 127*27458df8SWei Liu 128*27458df8SWei Liu switch (size) { 129*27458df8SWei Liu case 1: 130*27458df8SWei Liu val = *(uint8_t *)reg_ptr; 131*27458df8SWei Liu break; 132*27458df8SWei Liu case 2: 133*27458df8SWei Liu val = *(uint16_t *)reg_ptr; 134*27458df8SWei Liu break; 135*27458df8SWei Liu case 4: 136*27458df8SWei Liu val = *(uint32_t *)reg_ptr; 137*27458df8SWei Liu break; 138*27458df8SWei Liu case 8: 139*27458df8SWei Liu val = *(uint64_t *)reg_ptr; 140*27458df8SWei Liu break; 141*27458df8SWei Liu default: 142*27458df8SWei Liu abort(); 143*27458df8SWei Liu } 144*27458df8SWei Liu return val; 145*27458df8SWei Liu } 146*27458df8SWei Liu 147*27458df8SWei Liu void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size) 148*27458df8SWei Liu { 149*27458df8SWei Liu switch (size) { 150*27458df8SWei Liu case 1: 151*27458df8SWei Liu *(uint8_t *)reg_ptr = val; 152*27458df8SWei Liu break; 153*27458df8SWei Liu case 2: 154*27458df8SWei Liu *(uint16_t *)reg_ptr = val; 155*27458df8SWei Liu break; 156*27458df8SWei Liu case 4: 157*27458df8SWei Liu *(uint64_t *)reg_ptr = (uint32_t)val; 158*27458df8SWei Liu break; 159*27458df8SWei Liu case 8: 160*27458df8SWei Liu *(uint64_t *)reg_ptr = val; 161*27458df8SWei Liu break; 162*27458df8SWei Liu default: 163*27458df8SWei Liu abort(); 164*27458df8SWei Liu } 165*27458df8SWei Liu } 166*27458df8SWei Liu 167*27458df8SWei Liu static bool is_host_reg(CPUX86State *env, target_ulong ptr) 168*27458df8SWei Liu { 169*27458df8SWei Liu return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs); 170*27458df8SWei Liu } 171*27458df8SWei Liu 172*27458df8SWei Liu void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size) 173*27458df8SWei Liu { 174*27458df8SWei Liu if (is_host_reg(env, ptr)) { 175*27458df8SWei Liu write_val_to_reg(ptr, val, size); 176*27458df8SWei Liu return; 177*27458df8SWei Liu } 178*27458df8SWei Liu emul_ops->write_mem(env_cpu(env), &val, ptr, size); 179*27458df8SWei Liu } 180*27458df8SWei Liu 181*27458df8SWei Liu uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes) 182*27458df8SWei Liu { 183*27458df8SWei Liu emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes); 184*27458df8SWei Liu return env->emu_mmio_buf; 185*27458df8SWei Liu } 186*27458df8SWei Liu 187*27458df8SWei Liu 188*27458df8SWei Liu target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size) 189*27458df8SWei Liu { 190*27458df8SWei Liu target_ulong val; 191*27458df8SWei Liu uint8_t *mmio_ptr; 192*27458df8SWei Liu 193*27458df8SWei Liu if (is_host_reg(env, ptr)) { 194*27458df8SWei Liu return read_val_from_reg(ptr, size); 195*27458df8SWei Liu } 196*27458df8SWei Liu 197*27458df8SWei Liu mmio_ptr = read_mmio(env, ptr, size); 198*27458df8SWei Liu switch (size) { 199*27458df8SWei Liu case 1: 200*27458df8SWei Liu val = *(uint8_t *)mmio_ptr; 201*27458df8SWei Liu break; 202*27458df8SWei Liu case 2: 203*27458df8SWei Liu val = *(uint16_t *)mmio_ptr; 204*27458df8SWei Liu break; 205*27458df8SWei Liu case 4: 206*27458df8SWei Liu val = *(uint32_t *)mmio_ptr; 207*27458df8SWei Liu break; 208*27458df8SWei Liu case 8: 209*27458df8SWei Liu val = *(uint64_t *)mmio_ptr; 210*27458df8SWei Liu break; 211*27458df8SWei Liu default: 212*27458df8SWei Liu VM_PANIC("bad size\n"); 213*27458df8SWei Liu break; 214*27458df8SWei Liu } 215*27458df8SWei Liu return val; 216*27458df8SWei Liu } 217*27458df8SWei Liu 218*27458df8SWei Liu static void fetch_operands(CPUX86State *env, struct x86_decode *decode, 219*27458df8SWei Liu int n, bool val_op0, bool val_op1, bool val_op2) 220*27458df8SWei Liu { 221*27458df8SWei Liu int i; 222*27458df8SWei Liu bool calc_val[3] = {val_op0, val_op1, val_op2}; 223*27458df8SWei Liu 224*27458df8SWei Liu for (i = 0; i < n; i++) { 225*27458df8SWei Liu switch (decode->op[i].type) { 226*27458df8SWei Liu case X86_VAR_IMMEDIATE: 227*27458df8SWei Liu break; 228*27458df8SWei Liu case X86_VAR_REG: 229*27458df8SWei Liu VM_PANIC_ON(!decode->op[i].ptr); 230*27458df8SWei Liu if (calc_val[i]) { 231*27458df8SWei Liu decode->op[i].val = read_val_from_reg(decode->op[i].ptr, 232*27458df8SWei Liu decode->operand_size); 233*27458df8SWei Liu } 234*27458df8SWei Liu break; 235*27458df8SWei Liu case X86_VAR_RM: 236*27458df8SWei Liu calc_modrm_operand(env, decode, &decode->op[i]); 237*27458df8SWei Liu if (calc_val[i]) { 238*27458df8SWei Liu decode->op[i].val = read_val_ext(env, decode->op[i].ptr, 239*27458df8SWei Liu decode->operand_size); 240*27458df8SWei Liu } 241*27458df8SWei Liu break; 242*27458df8SWei Liu case X86_VAR_OFFSET: 243*27458df8SWei Liu decode->op[i].ptr = decode_linear_addr(env, decode, 244*27458df8SWei Liu decode->op[i].ptr, 245*27458df8SWei Liu R_DS); 246*27458df8SWei Liu if (calc_val[i]) { 247*27458df8SWei Liu decode->op[i].val = read_val_ext(env, decode->op[i].ptr, 248*27458df8SWei Liu decode->operand_size); 249*27458df8SWei Liu } 250*27458df8SWei Liu break; 251*27458df8SWei Liu default: 252*27458df8SWei Liu break; 253*27458df8SWei Liu } 254*27458df8SWei Liu } 255*27458df8SWei Liu } 256*27458df8SWei Liu 257*27458df8SWei Liu static void exec_mov(CPUX86State *env, struct x86_decode *decode) 258*27458df8SWei Liu { 259*27458df8SWei Liu fetch_operands(env, decode, 2, false, true, false); 260*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, decode->op[1].val, 261*27458df8SWei Liu decode->operand_size); 262*27458df8SWei Liu 263*27458df8SWei Liu env->eip += decode->len; 264*27458df8SWei Liu } 265*27458df8SWei Liu 266*27458df8SWei Liu static void exec_add(CPUX86State *env, struct x86_decode *decode) 267*27458df8SWei Liu { 268*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 269*27458df8SWei Liu env->eip += decode->len; 270*27458df8SWei Liu } 271*27458df8SWei Liu 272*27458df8SWei Liu static void exec_or(CPUX86State *env, struct x86_decode *decode) 273*27458df8SWei Liu { 274*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true); 275*27458df8SWei Liu env->eip += decode->len; 276*27458df8SWei Liu } 277*27458df8SWei Liu 278*27458df8SWei Liu static void exec_adc(CPUX86State *env, struct x86_decode *decode) 279*27458df8SWei Liu { 280*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true); 281*27458df8SWei Liu env->eip += decode->len; 282*27458df8SWei Liu } 283*27458df8SWei Liu 284*27458df8SWei Liu static void exec_sbb(CPUX86State *env, struct x86_decode *decode) 285*27458df8SWei Liu { 286*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true); 287*27458df8SWei Liu env->eip += decode->len; 288*27458df8SWei Liu } 289*27458df8SWei Liu 290*27458df8SWei Liu static void exec_and(CPUX86State *env, struct x86_decode *decode) 291*27458df8SWei Liu { 292*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true); 293*27458df8SWei Liu env->eip += decode->len; 294*27458df8SWei Liu } 295*27458df8SWei Liu 296*27458df8SWei Liu static void exec_sub(CPUX86State *env, struct x86_decode *decode) 297*27458df8SWei Liu { 298*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true); 299*27458df8SWei Liu env->eip += decode->len; 300*27458df8SWei Liu } 301*27458df8SWei Liu 302*27458df8SWei Liu static void exec_xor(CPUX86State *env, struct x86_decode *decode) 303*27458df8SWei Liu { 304*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true); 305*27458df8SWei Liu env->eip += decode->len; 306*27458df8SWei Liu } 307*27458df8SWei Liu 308*27458df8SWei Liu static void exec_neg(CPUX86State *env, struct x86_decode *decode) 309*27458df8SWei Liu { 310*27458df8SWei Liu /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/ 311*27458df8SWei Liu int32_t val; 312*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 313*27458df8SWei Liu 314*27458df8SWei Liu val = 0 - sign(decode->op[1].val, decode->operand_size); 315*27458df8SWei Liu write_val_ext(env, decode->op[1].ptr, val, decode->operand_size); 316*27458df8SWei Liu 317*27458df8SWei Liu if (4 == decode->operand_size) { 318*27458df8SWei Liu SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val); 319*27458df8SWei Liu } else if (2 == decode->operand_size) { 320*27458df8SWei Liu SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val); 321*27458df8SWei Liu } else if (1 == decode->operand_size) { 322*27458df8SWei Liu SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val); 323*27458df8SWei Liu } else { 324*27458df8SWei Liu VM_PANIC("bad op size\n"); 325*27458df8SWei Liu } 326*27458df8SWei Liu 327*27458df8SWei Liu /*lflags_to_rflags(env);*/ 328*27458df8SWei Liu env->eip += decode->len; 329*27458df8SWei Liu } 330*27458df8SWei Liu 331*27458df8SWei Liu static void exec_cmp(CPUX86State *env, struct x86_decode *decode) 332*27458df8SWei Liu { 333*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 334*27458df8SWei Liu env->eip += decode->len; 335*27458df8SWei Liu } 336*27458df8SWei Liu 337*27458df8SWei Liu static void exec_inc(CPUX86State *env, struct x86_decode *decode) 338*27458df8SWei Liu { 339*27458df8SWei Liu decode->op[1].type = X86_VAR_IMMEDIATE; 340*27458df8SWei Liu decode->op[1].val = 0; 341*27458df8SWei Liu 342*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true); 343*27458df8SWei Liu 344*27458df8SWei Liu env->eip += decode->len; 345*27458df8SWei Liu } 346*27458df8SWei Liu 347*27458df8SWei Liu static void exec_dec(CPUX86State *env, struct x86_decode *decode) 348*27458df8SWei Liu { 349*27458df8SWei Liu decode->op[1].type = X86_VAR_IMMEDIATE; 350*27458df8SWei Liu decode->op[1].val = 0; 351*27458df8SWei Liu 352*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true); 353*27458df8SWei Liu env->eip += decode->len; 354*27458df8SWei Liu } 355*27458df8SWei Liu 356*27458df8SWei Liu static void exec_tst(CPUX86State *env, struct x86_decode *decode) 357*27458df8SWei Liu { 358*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false); 359*27458df8SWei Liu env->eip += decode->len; 360*27458df8SWei Liu } 361*27458df8SWei Liu 362*27458df8SWei Liu static void exec_not(CPUX86State *env, struct x86_decode *decode) 363*27458df8SWei Liu { 364*27458df8SWei Liu fetch_operands(env, decode, 1, true, false, false); 365*27458df8SWei Liu 366*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val, 367*27458df8SWei Liu decode->operand_size); 368*27458df8SWei Liu env->eip += decode->len; 369*27458df8SWei Liu } 370*27458df8SWei Liu 371*27458df8SWei Liu void exec_movzx(CPUX86State *env, struct x86_decode *decode) 372*27458df8SWei Liu { 373*27458df8SWei Liu int src_op_size; 374*27458df8SWei Liu int op_size = decode->operand_size; 375*27458df8SWei Liu 376*27458df8SWei Liu fetch_operands(env, decode, 1, false, false, false); 377*27458df8SWei Liu 378*27458df8SWei Liu if (0xb6 == decode->opcode[1]) { 379*27458df8SWei Liu src_op_size = 1; 380*27458df8SWei Liu } else { 381*27458df8SWei Liu src_op_size = 2; 382*27458df8SWei Liu } 383*27458df8SWei Liu decode->operand_size = src_op_size; 384*27458df8SWei Liu calc_modrm_operand(env, decode, &decode->op[1]); 385*27458df8SWei Liu decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size); 386*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); 387*27458df8SWei Liu 388*27458df8SWei Liu env->eip += decode->len; 389*27458df8SWei Liu } 390*27458df8SWei Liu 391*27458df8SWei Liu static void exec_out(CPUX86State *env, struct x86_decode *decode) 392*27458df8SWei Liu { 393*27458df8SWei Liu switch (decode->opcode[0]) { 394*27458df8SWei Liu case 0xe6: 395*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1); 396*27458df8SWei Liu break; 397*27458df8SWei Liu case 0xe7: 398*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1, 399*27458df8SWei Liu decode->operand_size, 1); 400*27458df8SWei Liu break; 401*27458df8SWei Liu case 0xee: 402*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1); 403*27458df8SWei Liu break; 404*27458df8SWei Liu case 0xef: 405*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1, 406*27458df8SWei Liu decode->operand_size, 1); 407*27458df8SWei Liu break; 408*27458df8SWei Liu default: 409*27458df8SWei Liu VM_PANIC("Bad out opcode\n"); 410*27458df8SWei Liu break; 411*27458df8SWei Liu } 412*27458df8SWei Liu env->eip += decode->len; 413*27458df8SWei Liu } 414*27458df8SWei Liu 415*27458df8SWei Liu static void exec_in(CPUX86State *env, struct x86_decode *decode) 416*27458df8SWei Liu { 417*27458df8SWei Liu target_ulong val = 0; 418*27458df8SWei Liu switch (decode->opcode[0]) { 419*27458df8SWei Liu case 0xe4: 420*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1); 421*27458df8SWei Liu break; 422*27458df8SWei Liu case 0xe5: 423*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0, 424*27458df8SWei Liu decode->operand_size, 1); 425*27458df8SWei Liu if (decode->operand_size == 2) { 426*27458df8SWei Liu AX(env) = val; 427*27458df8SWei Liu } else { 428*27458df8SWei Liu RAX(env) = (uint32_t)val; 429*27458df8SWei Liu } 430*27458df8SWei Liu break; 431*27458df8SWei Liu case 0xec: 432*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1); 433*27458df8SWei Liu break; 434*27458df8SWei Liu case 0xed: 435*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), &val, 0, 436*27458df8SWei Liu decode->operand_size, 1); 437*27458df8SWei Liu if (decode->operand_size == 2) { 438*27458df8SWei Liu AX(env) = val; 439*27458df8SWei Liu } else { 440*27458df8SWei Liu RAX(env) = (uint32_t)val; 441*27458df8SWei Liu } 442*27458df8SWei Liu 443*27458df8SWei Liu break; 444*27458df8SWei Liu default: 445*27458df8SWei Liu VM_PANIC("Bad in opcode\n"); 446*27458df8SWei Liu break; 447*27458df8SWei Liu } 448*27458df8SWei Liu 449*27458df8SWei Liu env->eip += decode->len; 450*27458df8SWei Liu } 451*27458df8SWei Liu 452*27458df8SWei Liu static inline void string_increment_reg(CPUX86State *env, int reg, 453*27458df8SWei Liu struct x86_decode *decode) 454*27458df8SWei Liu { 455*27458df8SWei Liu target_ulong val = read_reg(env, reg, decode->addressing_size); 456*27458df8SWei Liu if (env->eflags & DF_MASK) { 457*27458df8SWei Liu val -= decode->operand_size; 458*27458df8SWei Liu } else { 459*27458df8SWei Liu val += decode->operand_size; 460*27458df8SWei Liu } 461*27458df8SWei Liu write_reg(env, reg, val, decode->addressing_size); 462*27458df8SWei Liu } 463*27458df8SWei Liu 464*27458df8SWei Liu static inline void string_rep(CPUX86State *env, struct x86_decode *decode, 465*27458df8SWei Liu void (*func)(CPUX86State *env, 466*27458df8SWei Liu struct x86_decode *ins), int rep) 467*27458df8SWei Liu { 468*27458df8SWei Liu target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size); 469*27458df8SWei Liu while (rcx--) { 470*27458df8SWei Liu func(env, decode); 471*27458df8SWei Liu write_reg(env, R_ECX, rcx, decode->addressing_size); 472*27458df8SWei Liu if ((PREFIX_REP == rep) && !get_ZF(env)) { 473*27458df8SWei Liu break; 474*27458df8SWei Liu } 475*27458df8SWei Liu if ((PREFIX_REPN == rep) && get_ZF(env)) { 476*27458df8SWei Liu break; 477*27458df8SWei Liu } 478*27458df8SWei Liu } 479*27458df8SWei Liu } 480*27458df8SWei Liu 481*27458df8SWei Liu static void exec_ins_single(CPUX86State *env, struct x86_decode *decode) 482*27458df8SWei Liu { 483*27458df8SWei Liu target_ulong addr = linear_addr_size(env_cpu(env), RDI(env), 484*27458df8SWei Liu decode->addressing_size, R_ES); 485*27458df8SWei Liu 486*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0, 487*27458df8SWei Liu decode->operand_size, 1); 488*27458df8SWei Liu emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr, 489*27458df8SWei Liu decode->operand_size); 490*27458df8SWei Liu 491*27458df8SWei Liu string_increment_reg(env, R_EDI, decode); 492*27458df8SWei Liu } 493*27458df8SWei Liu 494*27458df8SWei Liu static void exec_ins(CPUX86State *env, struct x86_decode *decode) 495*27458df8SWei Liu { 496*27458df8SWei Liu if (decode->rep) { 497*27458df8SWei Liu string_rep(env, decode, exec_ins_single, 0); 498*27458df8SWei Liu } else { 499*27458df8SWei Liu exec_ins_single(env, decode); 500*27458df8SWei Liu } 501*27458df8SWei Liu 502*27458df8SWei Liu env->eip += decode->len; 503*27458df8SWei Liu } 504*27458df8SWei Liu 505*27458df8SWei Liu static void exec_outs_single(CPUX86State *env, struct x86_decode *decode) 506*27458df8SWei Liu { 507*27458df8SWei Liu target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS); 508*27458df8SWei Liu 509*27458df8SWei Liu emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr, 510*27458df8SWei Liu decode->operand_size); 511*27458df8SWei Liu emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1, 512*27458df8SWei Liu decode->operand_size, 1); 513*27458df8SWei Liu 514*27458df8SWei Liu string_increment_reg(env, R_ESI, decode); 515*27458df8SWei Liu } 516*27458df8SWei Liu 517*27458df8SWei Liu static void exec_outs(CPUX86State *env, struct x86_decode *decode) 518*27458df8SWei Liu { 519*27458df8SWei Liu if (decode->rep) { 520*27458df8SWei Liu string_rep(env, decode, exec_outs_single, 0); 521*27458df8SWei Liu } else { 522*27458df8SWei Liu exec_outs_single(env, decode); 523*27458df8SWei Liu } 524*27458df8SWei Liu 525*27458df8SWei Liu env->eip += decode->len; 526*27458df8SWei Liu } 527*27458df8SWei Liu 528*27458df8SWei Liu static void exec_movs_single(CPUX86State *env, struct x86_decode *decode) 529*27458df8SWei Liu { 530*27458df8SWei Liu target_ulong src_addr; 531*27458df8SWei Liu target_ulong dst_addr; 532*27458df8SWei Liu target_ulong val; 533*27458df8SWei Liu 534*27458df8SWei Liu src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); 535*27458df8SWei Liu dst_addr = linear_addr_size(env_cpu(env), RDI(env), 536*27458df8SWei Liu decode->addressing_size, R_ES); 537*27458df8SWei Liu 538*27458df8SWei Liu val = read_val_ext(env, src_addr, decode->operand_size); 539*27458df8SWei Liu write_val_ext(env, dst_addr, val, decode->operand_size); 540*27458df8SWei Liu 541*27458df8SWei Liu string_increment_reg(env, R_ESI, decode); 542*27458df8SWei Liu string_increment_reg(env, R_EDI, decode); 543*27458df8SWei Liu } 544*27458df8SWei Liu 545*27458df8SWei Liu static void exec_movs(CPUX86State *env, struct x86_decode *decode) 546*27458df8SWei Liu { 547*27458df8SWei Liu if (decode->rep) { 548*27458df8SWei Liu string_rep(env, decode, exec_movs_single, 0); 549*27458df8SWei Liu } else { 550*27458df8SWei Liu exec_movs_single(env, decode); 551*27458df8SWei Liu } 552*27458df8SWei Liu 553*27458df8SWei Liu env->eip += decode->len; 554*27458df8SWei Liu } 555*27458df8SWei Liu 556*27458df8SWei Liu static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode) 557*27458df8SWei Liu { 558*27458df8SWei Liu target_ulong src_addr; 559*27458df8SWei Liu target_ulong dst_addr; 560*27458df8SWei Liu 561*27458df8SWei Liu src_addr = decode_linear_addr(env, decode, RSI(env), R_DS); 562*27458df8SWei Liu dst_addr = linear_addr_size(env_cpu(env), RDI(env), 563*27458df8SWei Liu decode->addressing_size, R_ES); 564*27458df8SWei Liu 565*27458df8SWei Liu decode->op[0].type = X86_VAR_IMMEDIATE; 566*27458df8SWei Liu decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size); 567*27458df8SWei Liu decode->op[1].type = X86_VAR_IMMEDIATE; 568*27458df8SWei Liu decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size); 569*27458df8SWei Liu 570*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 571*27458df8SWei Liu 572*27458df8SWei Liu string_increment_reg(env, R_ESI, decode); 573*27458df8SWei Liu string_increment_reg(env, R_EDI, decode); 574*27458df8SWei Liu } 575*27458df8SWei Liu 576*27458df8SWei Liu static void exec_cmps(CPUX86State *env, struct x86_decode *decode) 577*27458df8SWei Liu { 578*27458df8SWei Liu if (decode->rep) { 579*27458df8SWei Liu string_rep(env, decode, exec_cmps_single, decode->rep); 580*27458df8SWei Liu } else { 581*27458df8SWei Liu exec_cmps_single(env, decode); 582*27458df8SWei Liu } 583*27458df8SWei Liu env->eip += decode->len; 584*27458df8SWei Liu } 585*27458df8SWei Liu 586*27458df8SWei Liu 587*27458df8SWei Liu static void exec_stos_single(CPUX86State *env, struct x86_decode *decode) 588*27458df8SWei Liu { 589*27458df8SWei Liu target_ulong addr; 590*27458df8SWei Liu target_ulong val; 591*27458df8SWei Liu 592*27458df8SWei Liu addr = linear_addr_size(env_cpu(env), RDI(env), 593*27458df8SWei Liu decode->addressing_size, R_ES); 594*27458df8SWei Liu val = read_reg(env, R_EAX, decode->operand_size); 595*27458df8SWei Liu emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size); 596*27458df8SWei Liu 597*27458df8SWei Liu string_increment_reg(env, R_EDI, decode); 598*27458df8SWei Liu } 599*27458df8SWei Liu 600*27458df8SWei Liu 601*27458df8SWei Liu static void exec_stos(CPUX86State *env, struct x86_decode *decode) 602*27458df8SWei Liu { 603*27458df8SWei Liu if (decode->rep) { 604*27458df8SWei Liu string_rep(env, decode, exec_stos_single, 0); 605*27458df8SWei Liu } else { 606*27458df8SWei Liu exec_stos_single(env, decode); 607*27458df8SWei Liu } 608*27458df8SWei Liu 609*27458df8SWei Liu env->eip += decode->len; 610*27458df8SWei Liu } 611*27458df8SWei Liu 612*27458df8SWei Liu static void exec_scas_single(CPUX86State *env, struct x86_decode *decode) 613*27458df8SWei Liu { 614*27458df8SWei Liu target_ulong addr; 615*27458df8SWei Liu 616*27458df8SWei Liu addr = linear_addr_size(env_cpu(env), RDI(env), 617*27458df8SWei Liu decode->addressing_size, R_ES); 618*27458df8SWei Liu decode->op[1].type = X86_VAR_IMMEDIATE; 619*27458df8SWei Liu emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size); 620*27458df8SWei Liu 621*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false); 622*27458df8SWei Liu string_increment_reg(env, R_EDI, decode); 623*27458df8SWei Liu } 624*27458df8SWei Liu 625*27458df8SWei Liu static void exec_scas(CPUX86State *env, struct x86_decode *decode) 626*27458df8SWei Liu { 627*27458df8SWei Liu decode->op[0].type = X86_VAR_REG; 628*27458df8SWei Liu decode->op[0].reg = R_EAX; 629*27458df8SWei Liu if (decode->rep) { 630*27458df8SWei Liu string_rep(env, decode, exec_scas_single, decode->rep); 631*27458df8SWei Liu } else { 632*27458df8SWei Liu exec_scas_single(env, decode); 633*27458df8SWei Liu } 634*27458df8SWei Liu 635*27458df8SWei Liu env->eip += decode->len; 636*27458df8SWei Liu } 637*27458df8SWei Liu 638*27458df8SWei Liu static void exec_lods_single(CPUX86State *env, struct x86_decode *decode) 639*27458df8SWei Liu { 640*27458df8SWei Liu target_ulong addr; 641*27458df8SWei Liu target_ulong val = 0; 642*27458df8SWei Liu 643*27458df8SWei Liu addr = decode_linear_addr(env, decode, RSI(env), R_DS); 644*27458df8SWei Liu emul_ops->read_mem(env_cpu(env), &val, addr, decode->operand_size); 645*27458df8SWei Liu write_reg(env, R_EAX, val, decode->operand_size); 646*27458df8SWei Liu 647*27458df8SWei Liu string_increment_reg(env, R_ESI, decode); 648*27458df8SWei Liu } 649*27458df8SWei Liu 650*27458df8SWei Liu static void exec_lods(CPUX86State *env, struct x86_decode *decode) 651*27458df8SWei Liu { 652*27458df8SWei Liu if (decode->rep) { 653*27458df8SWei Liu string_rep(env, decode, exec_lods_single, 0); 654*27458df8SWei Liu } else { 655*27458df8SWei Liu exec_lods_single(env, decode); 656*27458df8SWei Liu } 657*27458df8SWei Liu 658*27458df8SWei Liu env->eip += decode->len; 659*27458df8SWei Liu } 660*27458df8SWei Liu 661*27458df8SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code) 662*27458df8SWei Liu { 663*27458df8SWei Liu env->exception_nr = exception_index; 664*27458df8SWei Liu env->error_code = error_code; 665*27458df8SWei Liu env->has_error_code = true; 666*27458df8SWei Liu env->exception_injected = 1; 667*27458df8SWei Liu } 668*27458df8SWei Liu 669*27458df8SWei Liu static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode) 670*27458df8SWei Liu { 671*27458df8SWei Liu emul_ops->simulate_rdmsr(env_cpu(env)); 672*27458df8SWei Liu env->eip += decode->len; 673*27458df8SWei Liu } 674*27458df8SWei Liu 675*27458df8SWei Liu static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode) 676*27458df8SWei Liu { 677*27458df8SWei Liu emul_ops->simulate_wrmsr(env_cpu(env)); 678*27458df8SWei Liu env->eip += decode->len; 679*27458df8SWei Liu } 680*27458df8SWei Liu 681*27458df8SWei Liu /* 682*27458df8SWei Liu * flag: 683*27458df8SWei Liu * 0 - bt, 1 - btc, 2 - bts, 3 - btr 684*27458df8SWei Liu */ 685*27458df8SWei Liu static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag) 686*27458df8SWei Liu { 687*27458df8SWei Liu int32_t displacement; 688*27458df8SWei Liu uint8_t index; 689*27458df8SWei Liu bool cf; 690*27458df8SWei Liu int mask = (4 == decode->operand_size) ? 0x1f : 0xf; 691*27458df8SWei Liu 692*27458df8SWei Liu VM_PANIC_ON(decode->rex.rex); 693*27458df8SWei Liu 694*27458df8SWei Liu fetch_operands(env, decode, 2, false, true, false); 695*27458df8SWei Liu index = decode->op[1].val & mask; 696*27458df8SWei Liu 697*27458df8SWei Liu if (decode->op[0].type != X86_VAR_REG) { 698*27458df8SWei Liu if (4 == decode->operand_size) { 699*27458df8SWei Liu displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32; 700*27458df8SWei Liu decode->op[0].ptr += 4 * displacement; 701*27458df8SWei Liu } else if (2 == decode->operand_size) { 702*27458df8SWei Liu displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16; 703*27458df8SWei Liu decode->op[0].ptr += 2 * displacement; 704*27458df8SWei Liu } else { 705*27458df8SWei Liu VM_PANIC("bt 64bit\n"); 706*27458df8SWei Liu } 707*27458df8SWei Liu } 708*27458df8SWei Liu decode->op[0].val = read_val_ext(env, decode->op[0].ptr, 709*27458df8SWei Liu decode->operand_size); 710*27458df8SWei Liu cf = (decode->op[0].val >> index) & 0x01; 711*27458df8SWei Liu 712*27458df8SWei Liu switch (flag) { 713*27458df8SWei Liu case 0: 714*27458df8SWei Liu set_CF(env, cf); 715*27458df8SWei Liu return; 716*27458df8SWei Liu case 1: 717*27458df8SWei Liu decode->op[0].val ^= (1u << index); 718*27458df8SWei Liu break; 719*27458df8SWei Liu case 2: 720*27458df8SWei Liu decode->op[0].val |= (1u << index); 721*27458df8SWei Liu break; 722*27458df8SWei Liu case 3: 723*27458df8SWei Liu decode->op[0].val &= ~(1u << index); 724*27458df8SWei Liu break; 725*27458df8SWei Liu } 726*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, decode->op[0].val, 727*27458df8SWei Liu decode->operand_size); 728*27458df8SWei Liu set_CF(env, cf); 729*27458df8SWei Liu } 730*27458df8SWei Liu 731*27458df8SWei Liu static void exec_bt(CPUX86State *env, struct x86_decode *decode) 732*27458df8SWei Liu { 733*27458df8SWei Liu do_bt(env, decode, 0); 734*27458df8SWei Liu env->eip += decode->len; 735*27458df8SWei Liu } 736*27458df8SWei Liu 737*27458df8SWei Liu static void exec_btc(CPUX86State *env, struct x86_decode *decode) 738*27458df8SWei Liu { 739*27458df8SWei Liu do_bt(env, decode, 1); 740*27458df8SWei Liu env->eip += decode->len; 741*27458df8SWei Liu } 742*27458df8SWei Liu 743*27458df8SWei Liu static void exec_btr(CPUX86State *env, struct x86_decode *decode) 744*27458df8SWei Liu { 745*27458df8SWei Liu do_bt(env, decode, 3); 746*27458df8SWei Liu env->eip += decode->len; 747*27458df8SWei Liu } 748*27458df8SWei Liu 749*27458df8SWei Liu static void exec_bts(CPUX86State *env, struct x86_decode *decode) 750*27458df8SWei Liu { 751*27458df8SWei Liu do_bt(env, decode, 2); 752*27458df8SWei Liu env->eip += decode->len; 753*27458df8SWei Liu } 754*27458df8SWei Liu 755*27458df8SWei Liu void exec_shl(CPUX86State *env, struct x86_decode *decode) 756*27458df8SWei Liu { 757*27458df8SWei Liu uint8_t count; 758*27458df8SWei Liu int of = 0, cf = 0; 759*27458df8SWei Liu 760*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 761*27458df8SWei Liu 762*27458df8SWei Liu count = decode->op[1].val; 763*27458df8SWei Liu count &= 0x1f; /* count is masked to 5 bits*/ 764*27458df8SWei Liu if (!count) { 765*27458df8SWei Liu goto exit; 766*27458df8SWei Liu } 767*27458df8SWei Liu 768*27458df8SWei Liu switch (decode->operand_size) { 769*27458df8SWei Liu case 1: 770*27458df8SWei Liu { 771*27458df8SWei Liu uint8_t res = 0; 772*27458df8SWei Liu if (count <= 8) { 773*27458df8SWei Liu res = (decode->op[0].val << count); 774*27458df8SWei Liu cf = (decode->op[0].val >> (8 - count)) & 0x1; 775*27458df8SWei Liu of = cf ^ (res >> 7); 776*27458df8SWei Liu } 777*27458df8SWei Liu 778*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 1); 779*27458df8SWei Liu SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res); 780*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 781*27458df8SWei Liu break; 782*27458df8SWei Liu } 783*27458df8SWei Liu case 2: 784*27458df8SWei Liu { 785*27458df8SWei Liu uint16_t res = 0; 786*27458df8SWei Liu 787*27458df8SWei Liu /* from bochs */ 788*27458df8SWei Liu if (count <= 16) { 789*27458df8SWei Liu res = (decode->op[0].val << count); 790*27458df8SWei Liu cf = (decode->op[0].val >> (16 - count)) & 0x1; 791*27458df8SWei Liu of = cf ^ (res >> 15); /* of = cf ^ result15 */ 792*27458df8SWei Liu } 793*27458df8SWei Liu 794*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 2); 795*27458df8SWei Liu SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res); 796*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 797*27458df8SWei Liu break; 798*27458df8SWei Liu } 799*27458df8SWei Liu case 4: 800*27458df8SWei Liu { 801*27458df8SWei Liu uint32_t res = decode->op[0].val << count; 802*27458df8SWei Liu 803*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 4); 804*27458df8SWei Liu SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res); 805*27458df8SWei Liu cf = (decode->op[0].val >> (32 - count)) & 0x1; 806*27458df8SWei Liu of = cf ^ (res >> 31); /* of = cf ^ result31 */ 807*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 808*27458df8SWei Liu break; 809*27458df8SWei Liu } 810*27458df8SWei Liu default: 811*27458df8SWei Liu abort(); 812*27458df8SWei Liu } 813*27458df8SWei Liu 814*27458df8SWei Liu exit: 815*27458df8SWei Liu /* lflags_to_rflags(env); */ 816*27458df8SWei Liu env->eip += decode->len; 817*27458df8SWei Liu } 818*27458df8SWei Liu 819*27458df8SWei Liu void exec_movsx(CPUX86State *env, struct x86_decode *decode) 820*27458df8SWei Liu { 821*27458df8SWei Liu int src_op_size; 822*27458df8SWei Liu int op_size = decode->operand_size; 823*27458df8SWei Liu 824*27458df8SWei Liu fetch_operands(env, decode, 2, false, false, false); 825*27458df8SWei Liu 826*27458df8SWei Liu if (0xbe == decode->opcode[1]) { 827*27458df8SWei Liu src_op_size = 1; 828*27458df8SWei Liu } else { 829*27458df8SWei Liu src_op_size = 2; 830*27458df8SWei Liu } 831*27458df8SWei Liu 832*27458df8SWei Liu decode->operand_size = src_op_size; 833*27458df8SWei Liu calc_modrm_operand(env, decode, &decode->op[1]); 834*27458df8SWei Liu decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size), 835*27458df8SWei Liu src_op_size); 836*27458df8SWei Liu 837*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size); 838*27458df8SWei Liu 839*27458df8SWei Liu env->eip += decode->len; 840*27458df8SWei Liu } 841*27458df8SWei Liu 842*27458df8SWei Liu void exec_ror(CPUX86State *env, struct x86_decode *decode) 843*27458df8SWei Liu { 844*27458df8SWei Liu uint8_t count; 845*27458df8SWei Liu 846*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 847*27458df8SWei Liu count = decode->op[1].val; 848*27458df8SWei Liu 849*27458df8SWei Liu switch (decode->operand_size) { 850*27458df8SWei Liu case 1: 851*27458df8SWei Liu { 852*27458df8SWei Liu uint32_t bit6, bit7; 853*27458df8SWei Liu uint8_t res; 854*27458df8SWei Liu 855*27458df8SWei Liu if ((count & 0x07) == 0) { 856*27458df8SWei Liu if (count & 0x18) { 857*27458df8SWei Liu bit6 = ((uint8_t)decode->op[0].val >> 6) & 1; 858*27458df8SWei Liu bit7 = ((uint8_t)decode->op[0].val >> 7) & 1; 859*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 860*27458df8SWei Liu } 861*27458df8SWei Liu } else { 862*27458df8SWei Liu count &= 0x7; /* use only bottom 3 bits */ 863*27458df8SWei Liu res = ((uint8_t)decode->op[0].val >> count) | 864*27458df8SWei Liu ((uint8_t)decode->op[0].val << (8 - count)); 865*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 1); 866*27458df8SWei Liu bit6 = (res >> 6) & 1; 867*27458df8SWei Liu bit7 = (res >> 7) & 1; 868*27458df8SWei Liu /* set eflags: ROR count affects the following flags: C, O */ 869*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7); 870*27458df8SWei Liu } 871*27458df8SWei Liu break; 872*27458df8SWei Liu } 873*27458df8SWei Liu case 2: 874*27458df8SWei Liu { 875*27458df8SWei Liu uint32_t bit14, bit15; 876*27458df8SWei Liu uint16_t res; 877*27458df8SWei Liu 878*27458df8SWei Liu if ((count & 0x0f) == 0) { 879*27458df8SWei Liu if (count & 0x10) { 880*27458df8SWei Liu bit14 = ((uint16_t)decode->op[0].val >> 14) & 1; 881*27458df8SWei Liu bit15 = ((uint16_t)decode->op[0].val >> 15) & 1; 882*27458df8SWei Liu /* of = result14 ^ result15 */ 883*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 884*27458df8SWei Liu } 885*27458df8SWei Liu } else { 886*27458df8SWei Liu count &= 0x0f; /* use only 4 LSB's */ 887*27458df8SWei Liu res = ((uint16_t)decode->op[0].val >> count) | 888*27458df8SWei Liu ((uint16_t)decode->op[0].val << (16 - count)); 889*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 2); 890*27458df8SWei Liu 891*27458df8SWei Liu bit14 = (res >> 14) & 1; 892*27458df8SWei Liu bit15 = (res >> 15) & 1; 893*27458df8SWei Liu /* of = result14 ^ result15 */ 894*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15); 895*27458df8SWei Liu } 896*27458df8SWei Liu break; 897*27458df8SWei Liu } 898*27458df8SWei Liu case 4: 899*27458df8SWei Liu { 900*27458df8SWei Liu uint32_t bit31, bit30; 901*27458df8SWei Liu uint32_t res; 902*27458df8SWei Liu 903*27458df8SWei Liu count &= 0x1f; 904*27458df8SWei Liu if (count) { 905*27458df8SWei Liu res = ((uint32_t)decode->op[0].val >> count) | 906*27458df8SWei Liu ((uint32_t)decode->op[0].val << (32 - count)); 907*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 4); 908*27458df8SWei Liu 909*27458df8SWei Liu bit31 = (res >> 31) & 1; 910*27458df8SWei Liu bit30 = (res >> 30) & 1; 911*27458df8SWei Liu /* of = result30 ^ result31 */ 912*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31); 913*27458df8SWei Liu } 914*27458df8SWei Liu break; 915*27458df8SWei Liu } 916*27458df8SWei Liu } 917*27458df8SWei Liu env->eip += decode->len; 918*27458df8SWei Liu } 919*27458df8SWei Liu 920*27458df8SWei Liu void exec_rol(CPUX86State *env, struct x86_decode *decode) 921*27458df8SWei Liu { 922*27458df8SWei Liu uint8_t count; 923*27458df8SWei Liu 924*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 925*27458df8SWei Liu count = decode->op[1].val; 926*27458df8SWei Liu 927*27458df8SWei Liu switch (decode->operand_size) { 928*27458df8SWei Liu case 1: 929*27458df8SWei Liu { 930*27458df8SWei Liu uint32_t bit0, bit7; 931*27458df8SWei Liu uint8_t res; 932*27458df8SWei Liu 933*27458df8SWei Liu if ((count & 0x07) == 0) { 934*27458df8SWei Liu if (count & 0x18) { 935*27458df8SWei Liu bit0 = ((uint8_t)decode->op[0].val & 1); 936*27458df8SWei Liu bit7 = ((uint8_t)decode->op[0].val >> 7); 937*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 938*27458df8SWei Liu } 939*27458df8SWei Liu } else { 940*27458df8SWei Liu count &= 0x7; /* use only lowest 3 bits */ 941*27458df8SWei Liu res = ((uint8_t)decode->op[0].val << count) | 942*27458df8SWei Liu ((uint8_t)decode->op[0].val >> (8 - count)); 943*27458df8SWei Liu 944*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 1); 945*27458df8SWei Liu /* set eflags: 946*27458df8SWei Liu * ROL count affects the following flags: C, O 947*27458df8SWei Liu */ 948*27458df8SWei Liu bit0 = (res & 1); 949*27458df8SWei Liu bit7 = (res >> 7); 950*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0); 951*27458df8SWei Liu } 952*27458df8SWei Liu break; 953*27458df8SWei Liu } 954*27458df8SWei Liu case 2: 955*27458df8SWei Liu { 956*27458df8SWei Liu uint32_t bit0, bit15; 957*27458df8SWei Liu uint16_t res; 958*27458df8SWei Liu 959*27458df8SWei Liu if ((count & 0x0f) == 0) { 960*27458df8SWei Liu if (count & 0x10) { 961*27458df8SWei Liu bit0 = ((uint16_t)decode->op[0].val & 0x1); 962*27458df8SWei Liu bit15 = ((uint16_t)decode->op[0].val >> 15); 963*27458df8SWei Liu /* of = cf ^ result15 */ 964*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 965*27458df8SWei Liu } 966*27458df8SWei Liu } else { 967*27458df8SWei Liu count &= 0x0f; /* only use bottom 4 bits */ 968*27458df8SWei Liu res = ((uint16_t)decode->op[0].val << count) | 969*27458df8SWei Liu ((uint16_t)decode->op[0].val >> (16 - count)); 970*27458df8SWei Liu 971*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 2); 972*27458df8SWei Liu bit0 = (res & 0x1); 973*27458df8SWei Liu bit15 = (res >> 15); 974*27458df8SWei Liu /* of = cf ^ result15 */ 975*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0); 976*27458df8SWei Liu } 977*27458df8SWei Liu break; 978*27458df8SWei Liu } 979*27458df8SWei Liu case 4: 980*27458df8SWei Liu { 981*27458df8SWei Liu uint32_t bit0, bit31; 982*27458df8SWei Liu uint32_t res; 983*27458df8SWei Liu 984*27458df8SWei Liu count &= 0x1f; 985*27458df8SWei Liu if (count) { 986*27458df8SWei Liu res = ((uint32_t)decode->op[0].val << count) | 987*27458df8SWei Liu ((uint32_t)decode->op[0].val >> (32 - count)); 988*27458df8SWei Liu 989*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 4); 990*27458df8SWei Liu bit0 = (res & 0x1); 991*27458df8SWei Liu bit31 = (res >> 31); 992*27458df8SWei Liu /* of = cf ^ result31 */ 993*27458df8SWei Liu SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0); 994*27458df8SWei Liu } 995*27458df8SWei Liu break; 996*27458df8SWei Liu } 997*27458df8SWei Liu } 998*27458df8SWei Liu env->eip += decode->len; 999*27458df8SWei Liu } 1000*27458df8SWei Liu 1001*27458df8SWei Liu 1002*27458df8SWei Liu void exec_rcl(CPUX86State *env, struct x86_decode *decode) 1003*27458df8SWei Liu { 1004*27458df8SWei Liu uint8_t count; 1005*27458df8SWei Liu int of = 0, cf = 0; 1006*27458df8SWei Liu 1007*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 1008*27458df8SWei Liu count = decode->op[1].val & 0x1f; 1009*27458df8SWei Liu 1010*27458df8SWei Liu switch (decode->operand_size) { 1011*27458df8SWei Liu case 1: 1012*27458df8SWei Liu { 1013*27458df8SWei Liu uint8_t op1_8 = decode->op[0].val; 1014*27458df8SWei Liu uint8_t res; 1015*27458df8SWei Liu count %= 9; 1016*27458df8SWei Liu if (!count) { 1017*27458df8SWei Liu break; 1018*27458df8SWei Liu } 1019*27458df8SWei Liu 1020*27458df8SWei Liu if (1 == count) { 1021*27458df8SWei Liu res = (op1_8 << 1) | get_CF(env); 1022*27458df8SWei Liu } else { 1023*27458df8SWei Liu res = (op1_8 << count) | (get_CF(env) << (count - 1)) | 1024*27458df8SWei Liu (op1_8 >> (9 - count)); 1025*27458df8SWei Liu } 1026*27458df8SWei Liu 1027*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 1); 1028*27458df8SWei Liu 1029*27458df8SWei Liu cf = (op1_8 >> (8 - count)) & 0x01; 1030*27458df8SWei Liu of = cf ^ (res >> 7); /* of = cf ^ result7 */ 1031*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1032*27458df8SWei Liu break; 1033*27458df8SWei Liu } 1034*27458df8SWei Liu case 2: 1035*27458df8SWei Liu { 1036*27458df8SWei Liu uint16_t res; 1037*27458df8SWei Liu uint16_t op1_16 = decode->op[0].val; 1038*27458df8SWei Liu 1039*27458df8SWei Liu count %= 17; 1040*27458df8SWei Liu if (!count) { 1041*27458df8SWei Liu break; 1042*27458df8SWei Liu } 1043*27458df8SWei Liu 1044*27458df8SWei Liu if (1 == count) { 1045*27458df8SWei Liu res = (op1_16 << 1) | get_CF(env); 1046*27458df8SWei Liu } else if (count == 16) { 1047*27458df8SWei Liu res = (get_CF(env) << 15) | (op1_16 >> 1); 1048*27458df8SWei Liu } else { /* 2..15 */ 1049*27458df8SWei Liu res = (op1_16 << count) | (get_CF(env) << (count - 1)) | 1050*27458df8SWei Liu (op1_16 >> (17 - count)); 1051*27458df8SWei Liu } 1052*27458df8SWei Liu 1053*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 2); 1054*27458df8SWei Liu 1055*27458df8SWei Liu cf = (op1_16 >> (16 - count)) & 0x1; 1056*27458df8SWei Liu of = cf ^ (res >> 15); /* of = cf ^ result15 */ 1057*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1058*27458df8SWei Liu break; 1059*27458df8SWei Liu } 1060*27458df8SWei Liu case 4: 1061*27458df8SWei Liu { 1062*27458df8SWei Liu uint32_t res; 1063*27458df8SWei Liu uint32_t op1_32 = decode->op[0].val; 1064*27458df8SWei Liu 1065*27458df8SWei Liu if (!count) { 1066*27458df8SWei Liu break; 1067*27458df8SWei Liu } 1068*27458df8SWei Liu 1069*27458df8SWei Liu if (1 == count) { 1070*27458df8SWei Liu res = (op1_32 << 1) | get_CF(env); 1071*27458df8SWei Liu } else { 1072*27458df8SWei Liu res = (op1_32 << count) | (get_CF(env) << (count - 1)) | 1073*27458df8SWei Liu (op1_32 >> (33 - count)); 1074*27458df8SWei Liu } 1075*27458df8SWei Liu 1076*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 4); 1077*27458df8SWei Liu 1078*27458df8SWei Liu cf = (op1_32 >> (32 - count)) & 0x1; 1079*27458df8SWei Liu of = cf ^ (res >> 31); /* of = cf ^ result31 */ 1080*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1081*27458df8SWei Liu break; 1082*27458df8SWei Liu } 1083*27458df8SWei Liu } 1084*27458df8SWei Liu env->eip += decode->len; 1085*27458df8SWei Liu } 1086*27458df8SWei Liu 1087*27458df8SWei Liu void exec_rcr(CPUX86State *env, struct x86_decode *decode) 1088*27458df8SWei Liu { 1089*27458df8SWei Liu uint8_t count; 1090*27458df8SWei Liu int of = 0, cf = 0; 1091*27458df8SWei Liu 1092*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 1093*27458df8SWei Liu count = decode->op[1].val & 0x1f; 1094*27458df8SWei Liu 1095*27458df8SWei Liu switch (decode->operand_size) { 1096*27458df8SWei Liu case 1: 1097*27458df8SWei Liu { 1098*27458df8SWei Liu uint8_t op1_8 = decode->op[0].val; 1099*27458df8SWei Liu uint8_t res; 1100*27458df8SWei Liu 1101*27458df8SWei Liu count %= 9; 1102*27458df8SWei Liu if (!count) { 1103*27458df8SWei Liu break; 1104*27458df8SWei Liu } 1105*27458df8SWei Liu res = (op1_8 >> count) | (get_CF(env) << (8 - count)) | 1106*27458df8SWei Liu (op1_8 << (9 - count)); 1107*27458df8SWei Liu 1108*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 1); 1109*27458df8SWei Liu 1110*27458df8SWei Liu cf = (op1_8 >> (count - 1)) & 0x1; 1111*27458df8SWei Liu of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */ 1112*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1113*27458df8SWei Liu break; 1114*27458df8SWei Liu } 1115*27458df8SWei Liu case 2: 1116*27458df8SWei Liu { 1117*27458df8SWei Liu uint16_t op1_16 = decode->op[0].val; 1118*27458df8SWei Liu uint16_t res; 1119*27458df8SWei Liu 1120*27458df8SWei Liu count %= 17; 1121*27458df8SWei Liu if (!count) { 1122*27458df8SWei Liu break; 1123*27458df8SWei Liu } 1124*27458df8SWei Liu res = (op1_16 >> count) | (get_CF(env) << (16 - count)) | 1125*27458df8SWei Liu (op1_16 << (17 - count)); 1126*27458df8SWei Liu 1127*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 2); 1128*27458df8SWei Liu 1129*27458df8SWei Liu cf = (op1_16 >> (count - 1)) & 0x1; 1130*27458df8SWei Liu of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^ 1131*27458df8SWei Liu result14 */ 1132*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1133*27458df8SWei Liu break; 1134*27458df8SWei Liu } 1135*27458df8SWei Liu case 4: 1136*27458df8SWei Liu { 1137*27458df8SWei Liu uint32_t res; 1138*27458df8SWei Liu uint32_t op1_32 = decode->op[0].val; 1139*27458df8SWei Liu 1140*27458df8SWei Liu if (!count) { 1141*27458df8SWei Liu break; 1142*27458df8SWei Liu } 1143*27458df8SWei Liu 1144*27458df8SWei Liu if (1 == count) { 1145*27458df8SWei Liu res = (op1_32 >> 1) | (get_CF(env) << 31); 1146*27458df8SWei Liu } else { 1147*27458df8SWei Liu res = (op1_32 >> count) | (get_CF(env) << (32 - count)) | 1148*27458df8SWei Liu (op1_32 << (33 - count)); 1149*27458df8SWei Liu } 1150*27458df8SWei Liu 1151*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, res, 4); 1152*27458df8SWei Liu 1153*27458df8SWei Liu cf = (op1_32 >> (count - 1)) & 0x1; 1154*27458df8SWei Liu of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */ 1155*27458df8SWei Liu SET_FLAGS_OxxxxC(env, of, cf); 1156*27458df8SWei Liu break; 1157*27458df8SWei Liu } 1158*27458df8SWei Liu } 1159*27458df8SWei Liu env->eip += decode->len; 1160*27458df8SWei Liu } 1161*27458df8SWei Liu 1162*27458df8SWei Liu static void exec_xchg(CPUX86State *env, struct x86_decode *decode) 1163*27458df8SWei Liu { 1164*27458df8SWei Liu fetch_operands(env, decode, 2, true, true, false); 1165*27458df8SWei Liu 1166*27458df8SWei Liu write_val_ext(env, decode->op[0].ptr, decode->op[1].val, 1167*27458df8SWei Liu decode->operand_size); 1168*27458df8SWei Liu write_val_ext(env, decode->op[1].ptr, decode->op[0].val, 1169*27458df8SWei Liu decode->operand_size); 1170*27458df8SWei Liu 1171*27458df8SWei Liu env->eip += decode->len; 1172*27458df8SWei Liu } 1173*27458df8SWei Liu 1174*27458df8SWei Liu static void exec_xadd(CPUX86State *env, struct x86_decode *decode) 1175*27458df8SWei Liu { 1176*27458df8SWei Liu EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true); 1177*27458df8SWei Liu write_val_ext(env, decode->op[1].ptr, decode->op[0].val, 1178*27458df8SWei Liu decode->operand_size); 1179*27458df8SWei Liu 1180*27458df8SWei Liu env->eip += decode->len; 1181*27458df8SWei Liu } 1182*27458df8SWei Liu 1183*27458df8SWei Liu static struct cmd_handler { 1184*27458df8SWei Liu enum x86_decode_cmd cmd; 1185*27458df8SWei Liu void (*handler)(CPUX86State *env, struct x86_decode *ins); 1186*27458df8SWei Liu } handlers[] = { 1187*27458df8SWei Liu {X86_DECODE_CMD_INVL, NULL,}, 1188*27458df8SWei Liu {X86_DECODE_CMD_MOV, exec_mov}, 1189*27458df8SWei Liu {X86_DECODE_CMD_ADD, exec_add}, 1190*27458df8SWei Liu {X86_DECODE_CMD_OR, exec_or}, 1191*27458df8SWei Liu {X86_DECODE_CMD_ADC, exec_adc}, 1192*27458df8SWei Liu {X86_DECODE_CMD_SBB, exec_sbb}, 1193*27458df8SWei Liu {X86_DECODE_CMD_AND, exec_and}, 1194*27458df8SWei Liu {X86_DECODE_CMD_SUB, exec_sub}, 1195*27458df8SWei Liu {X86_DECODE_CMD_NEG, exec_neg}, 1196*27458df8SWei Liu {X86_DECODE_CMD_XOR, exec_xor}, 1197*27458df8SWei Liu {X86_DECODE_CMD_CMP, exec_cmp}, 1198*27458df8SWei Liu {X86_DECODE_CMD_INC, exec_inc}, 1199*27458df8SWei Liu {X86_DECODE_CMD_DEC, exec_dec}, 1200*27458df8SWei Liu {X86_DECODE_CMD_TST, exec_tst}, 1201*27458df8SWei Liu {X86_DECODE_CMD_NOT, exec_not}, 1202*27458df8SWei Liu {X86_DECODE_CMD_MOVZX, exec_movzx}, 1203*27458df8SWei Liu {X86_DECODE_CMD_OUT, exec_out}, 1204*27458df8SWei Liu {X86_DECODE_CMD_IN, exec_in}, 1205*27458df8SWei Liu {X86_DECODE_CMD_INS, exec_ins}, 1206*27458df8SWei Liu {X86_DECODE_CMD_OUTS, exec_outs}, 1207*27458df8SWei Liu {X86_DECODE_CMD_RDMSR, exec_rdmsr}, 1208*27458df8SWei Liu {X86_DECODE_CMD_WRMSR, exec_wrmsr}, 1209*27458df8SWei Liu {X86_DECODE_CMD_BT, exec_bt}, 1210*27458df8SWei Liu {X86_DECODE_CMD_BTR, exec_btr}, 1211*27458df8SWei Liu {X86_DECODE_CMD_BTC, exec_btc}, 1212*27458df8SWei Liu {X86_DECODE_CMD_BTS, exec_bts}, 1213*27458df8SWei Liu {X86_DECODE_CMD_SHL, exec_shl}, 1214*27458df8SWei Liu {X86_DECODE_CMD_ROL, exec_rol}, 1215*27458df8SWei Liu {X86_DECODE_CMD_ROR, exec_ror}, 1216*27458df8SWei Liu {X86_DECODE_CMD_RCR, exec_rcr}, 1217*27458df8SWei Liu {X86_DECODE_CMD_RCL, exec_rcl}, 1218*27458df8SWei Liu /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/ 1219*27458df8SWei Liu {X86_DECODE_CMD_MOVS, exec_movs}, 1220*27458df8SWei Liu {X86_DECODE_CMD_CMPS, exec_cmps}, 1221*27458df8SWei Liu {X86_DECODE_CMD_STOS, exec_stos}, 1222*27458df8SWei Liu {X86_DECODE_CMD_SCAS, exec_scas}, 1223*27458df8SWei Liu {X86_DECODE_CMD_LODS, exec_lods}, 1224*27458df8SWei Liu {X86_DECODE_CMD_MOVSX, exec_movsx}, 1225*27458df8SWei Liu {X86_DECODE_CMD_XCHG, exec_xchg}, 1226*27458df8SWei Liu {X86_DECODE_CMD_XADD, exec_xadd}, 1227*27458df8SWei Liu }; 1228*27458df8SWei Liu 1229*27458df8SWei Liu static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST]; 1230*27458df8SWei Liu 1231*27458df8SWei Liu const struct x86_emul_ops *emul_ops; 1232*27458df8SWei Liu 1233*27458df8SWei Liu static void init_cmd_handler(void) 1234*27458df8SWei Liu { 1235*27458df8SWei Liu int i; 1236*27458df8SWei Liu for (i = 0; i < ARRAY_SIZE(handlers); i++) { 1237*27458df8SWei Liu _cmd_handler[handlers[i].cmd] = handlers[i]; 1238*27458df8SWei Liu } 1239*27458df8SWei Liu } 1240*27458df8SWei Liu 1241*27458df8SWei Liu bool exec_instruction(CPUX86State *env, struct x86_decode *ins) 1242*27458df8SWei Liu { 1243*27458df8SWei Liu if (!_cmd_handler[ins->cmd].handler) { 1244*27458df8SWei Liu printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip, 1245*27458df8SWei Liu ins->cmd, ins->opcode[0], 1246*27458df8SWei Liu ins->opcode_len > 1 ? ins->opcode[1] : 0); 1247*27458df8SWei Liu env->eip += ins->len; 1248*27458df8SWei Liu return true; 1249*27458df8SWei Liu } 1250*27458df8SWei Liu 1251*27458df8SWei Liu _cmd_handler[ins->cmd].handler(env, ins); 1252*27458df8SWei Liu return true; 1253*27458df8SWei Liu } 1254*27458df8SWei Liu 1255*27458df8SWei Liu void init_emu(const struct x86_emul_ops *o) 1256*27458df8SWei Liu { 1257*27458df8SWei Liu emul_ops = o; 1258*27458df8SWei Liu init_cmd_handler(); 1259*27458df8SWei Liu } 1260