1706f2543Smrg/**************************************************************************** 2706f2543Smrg* 3706f2543Smrg* Realmode X86 Emulator Library 4706f2543Smrg* 5706f2543Smrg* Copyright (C) 1996-1999 SciTech Software, Inc. 6706f2543Smrg* Copyright (C) David Mosberger-Tang 7706f2543Smrg* Copyright (C) 1999 Egbert Eich 8706f2543Smrg* 9706f2543Smrg* ======================================================================== 10706f2543Smrg* 11706f2543Smrg* Permission to use, copy, modify, distribute, and sell this software and 12706f2543Smrg* its documentation for any purpose is hereby granted without fee, 13706f2543Smrg* provided that the above copyright notice appear in all copies and that 14706f2543Smrg* both that copyright notice and this permission notice appear in 15706f2543Smrg* supporting documentation, and that the name of the authors not be used 16706f2543Smrg* in advertising or publicity pertaining to distribution of the software 17706f2543Smrg* without specific, written prior permission. The authors makes no 18706f2543Smrg* representations about the suitability of this software for any purpose. 19706f2543Smrg* It is provided "as is" without express or implied warranty. 20706f2543Smrg* 21706f2543Smrg* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22706f2543Smrg* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23706f2543Smrg* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24706f2543Smrg* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25706f2543Smrg* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26706f2543Smrg* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27706f2543Smrg* PERFORMANCE OF THIS SOFTWARE. 28706f2543Smrg* 29706f2543Smrg* ======================================================================== 30706f2543Smrg* 31706f2543Smrg* Language: ANSI C 32706f2543Smrg* Environment: Any 33706f2543Smrg* Developer: Kendall Bennett 34706f2543Smrg* 35706f2543Smrg* Description: This file includes subroutines to implement the decoding 36706f2543Smrg* and emulation of all the x86 extended two-byte processor 37706f2543Smrg* instructions. 38706f2543Smrg* 39706f2543Smrg****************************************************************************/ 40706f2543Smrg 41706f2543Smrg#include "x86emu/x86emui.h" 42706f2543Smrg 43706f2543Smrg#undef bswap_32 44706f2543Smrg#define bswap_32(x) (((x & 0xff000000) >> 24) | \ 45706f2543Smrg ((x & 0x00ff0000) >> 8) | \ 46706f2543Smrg ((x & 0x0000ff00) << 8) | \ 47706f2543Smrg ((x & 0x000000ff) << 24)) 48706f2543Smrg 49706f2543Smrg/*----------------------------- Implementation ----------------------------*/ 50706f2543Smrg 51706f2543Smrg/**************************************************************************** 52706f2543SmrgPARAMETERS: 53706f2543Smrgop1 - Instruction op code 54706f2543Smrg 55706f2543SmrgREMARKS: 56706f2543SmrgHandles illegal opcodes. 57706f2543Smrg****************************************************************************/ 58706f2543Smrgstatic void x86emuOp2_illegal_op( 59706f2543Smrg u8 op2) 60706f2543Smrg{ 61706f2543Smrg START_OF_INSTR(); 62706f2543Smrg DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); 63706f2543Smrg TRACE_REGS(); 64706f2543Smrg printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n", 65706f2543Smrg M.x86.R_CS, M.x86.R_IP-2,op2); 66706f2543Smrg HALT_SYS(); 67706f2543Smrg END_OF_INSTR(); 68706f2543Smrg} 69706f2543Smrg 70706f2543Smrg#define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) 71706f2543Smrg 72706f2543Smrg/**************************************************************************** 73706f2543SmrgREMARKS: 74706f2543SmrgHandles opcode 0x0f,0x31 75706f2543Smrg****************************************************************************/ 76706f2543Smrgstatic void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2)) 77706f2543Smrg{ 78706f2543Smrg#ifdef __HAS_LONG_LONG__ 79706f2543Smrg static u64 counter = 0; 80706f2543Smrg#else 81706f2543Smrg static u32 counter = 0; 82706f2543Smrg#endif 83706f2543Smrg 84706f2543Smrg counter += 0x10000; 85706f2543Smrg 86706f2543Smrg /* read timestamp counter */ 87706f2543Smrg /* 88706f2543Smrg * Note that instead of actually trying to accurately measure this, we just 89706f2543Smrg * increase the counter by a fixed amount every time we hit one of these 90706f2543Smrg * instructions. Feel free to come up with a better method. 91706f2543Smrg */ 92706f2543Smrg START_OF_INSTR(); 93706f2543Smrg DECODE_PRINTF("RDTSC\n"); 94706f2543Smrg TRACE_AND_STEP(); 95706f2543Smrg#ifdef __HAS_LONG_LONG__ 96706f2543Smrg M.x86.R_EAX = counter & 0xffffffff; 97706f2543Smrg M.x86.R_EDX = counter >> 32; 98706f2543Smrg#else 99706f2543Smrg M.x86.R_EAX = counter; 100706f2543Smrg M.x86.R_EDX = 0; 101706f2543Smrg#endif 102706f2543Smrg DECODE_CLEAR_SEGOVR(); 103706f2543Smrg END_OF_INSTR(); 104706f2543Smrg} 105706f2543Smrg 106706f2543Smrg/**************************************************************************** 107706f2543SmrgREMARKS: 108706f2543SmrgHandles opcode 0x0f,0x80-0x8F 109706f2543Smrg****************************************************************************/ 110706f2543Smrgstatic void x86emuOp2_long_jump(u8 op2) 111706f2543Smrg{ 112706f2543Smrg s32 target; 113706f2543Smrg char *name = NULL; 114706f2543Smrg int cond = 0; 115706f2543Smrg 116706f2543Smrg /* conditional jump to word offset. */ 117706f2543Smrg START_OF_INSTR(); 118706f2543Smrg switch (op2) { 119706f2543Smrg case 0x80: 120706f2543Smrg name = "JO\t"; 121706f2543Smrg cond = ACCESS_FLAG(F_OF); 122706f2543Smrg break; 123706f2543Smrg case 0x81: 124706f2543Smrg name = "JNO\t"; 125706f2543Smrg cond = !ACCESS_FLAG(F_OF); 126706f2543Smrg break; 127706f2543Smrg case 0x82: 128706f2543Smrg name = "JB\t"; 129706f2543Smrg cond = ACCESS_FLAG(F_CF); 130706f2543Smrg break; 131706f2543Smrg case 0x83: 132706f2543Smrg name = "JNB\t"; 133706f2543Smrg cond = !ACCESS_FLAG(F_CF); 134706f2543Smrg break; 135706f2543Smrg case 0x84: 136706f2543Smrg name = "JZ\t"; 137706f2543Smrg cond = ACCESS_FLAG(F_ZF); 138706f2543Smrg break; 139706f2543Smrg case 0x85: 140706f2543Smrg name = "JNZ\t"; 141706f2543Smrg cond = !ACCESS_FLAG(F_ZF); 142706f2543Smrg break; 143706f2543Smrg case 0x86: 144706f2543Smrg name = "JBE\t"; 145706f2543Smrg cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); 146706f2543Smrg break; 147706f2543Smrg case 0x87: 148706f2543Smrg name = "JNBE\t"; 149706f2543Smrg cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 150706f2543Smrg break; 151706f2543Smrg case 0x88: 152706f2543Smrg name = "JS\t"; 153706f2543Smrg cond = ACCESS_FLAG(F_SF); 154706f2543Smrg break; 155706f2543Smrg case 0x89: 156706f2543Smrg name = "JNS\t"; 157706f2543Smrg cond = !ACCESS_FLAG(F_SF); 158706f2543Smrg break; 159706f2543Smrg case 0x8a: 160706f2543Smrg name = "JP\t"; 161706f2543Smrg cond = ACCESS_FLAG(F_PF); 162706f2543Smrg break; 163706f2543Smrg case 0x8b: 164706f2543Smrg name = "JNP\t"; 165706f2543Smrg cond = !ACCESS_FLAG(F_PF); 166706f2543Smrg break; 167706f2543Smrg case 0x8c: 168706f2543Smrg name = "JL\t"; 169706f2543Smrg cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); 170706f2543Smrg break; 171706f2543Smrg case 0x8d: 172706f2543Smrg name = "JNL\t"; 173706f2543Smrg cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); 174706f2543Smrg break; 175706f2543Smrg case 0x8e: 176706f2543Smrg name = "JLE\t"; 177706f2543Smrg cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 178706f2543Smrg ACCESS_FLAG(F_ZF)); 179706f2543Smrg break; 180706f2543Smrg case 0x8f: 181706f2543Smrg name = "JNLE\t"; 182706f2543Smrg cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 183706f2543Smrg ACCESS_FLAG(F_ZF)); 184706f2543Smrg break; 185706f2543Smrg } 186706f2543Smrg DECODE_PRINTF(name); 187706f2543Smrg (void)name; 188706f2543Smrg target = (s16) fetch_word_imm(); 189706f2543Smrg target += (s16) M.x86.R_IP; 190706f2543Smrg DECODE_PRINTF2("%04x\n", target); 191706f2543Smrg TRACE_AND_STEP(); 192706f2543Smrg if (cond) 193706f2543Smrg M.x86.R_IP = (u16)target; 194706f2543Smrg DECODE_CLEAR_SEGOVR(); 195706f2543Smrg END_OF_INSTR(); 196706f2543Smrg} 197706f2543Smrg 198706f2543Smrg/**************************************************************************** 199706f2543SmrgREMARKS: 200706f2543SmrgHandles opcode 0x0f,0x90-0x9F 201706f2543Smrg****************************************************************************/ 202706f2543Smrgstatic void x86emuOp2_set_byte(u8 op2) 203706f2543Smrg{ 204706f2543Smrg int mod, rl, rh; 205706f2543Smrg uint destoffset; 206706f2543Smrg u8 *destreg; 207706f2543Smrg char *name = NULL; 208706f2543Smrg int cond = 0; 209706f2543Smrg 210706f2543Smrg START_OF_INSTR(); 211706f2543Smrg switch (op2) { 212706f2543Smrg case 0x90: 213706f2543Smrg name = "SETO\t"; 214706f2543Smrg cond = ACCESS_FLAG(F_OF); 215706f2543Smrg break; 216706f2543Smrg case 0x91: 217706f2543Smrg name = "SETNO\t"; 218706f2543Smrg cond = !ACCESS_FLAG(F_OF); 219706f2543Smrg break; 220706f2543Smrg case 0x92: 221706f2543Smrg name = "SETB\t"; 222706f2543Smrg cond = ACCESS_FLAG(F_CF); 223706f2543Smrg break; 224706f2543Smrg case 0x93: 225706f2543Smrg name = "SETNB\t"; 226706f2543Smrg cond = !ACCESS_FLAG(F_CF); 227706f2543Smrg break; 228706f2543Smrg case 0x94: 229706f2543Smrg name = "SETZ\t"; 230706f2543Smrg cond = ACCESS_FLAG(F_ZF); 231706f2543Smrg break; 232706f2543Smrg case 0x95: 233706f2543Smrg name = "SETNZ\t"; 234706f2543Smrg cond = !ACCESS_FLAG(F_ZF); 235706f2543Smrg break; 236706f2543Smrg case 0x96: 237706f2543Smrg name = "SETBE\t"; 238706f2543Smrg cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); 239706f2543Smrg break; 240706f2543Smrg case 0x97: 241706f2543Smrg name = "SETNBE\t"; 242706f2543Smrg cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); 243706f2543Smrg break; 244706f2543Smrg case 0x98: 245706f2543Smrg name = "SETS\t"; 246706f2543Smrg cond = ACCESS_FLAG(F_SF); 247706f2543Smrg break; 248706f2543Smrg case 0x99: 249706f2543Smrg name = "SETNS\t"; 250706f2543Smrg cond = !ACCESS_FLAG(F_SF); 251706f2543Smrg break; 252706f2543Smrg case 0x9a: 253706f2543Smrg name = "SETP\t"; 254706f2543Smrg cond = ACCESS_FLAG(F_PF); 255706f2543Smrg break; 256706f2543Smrg case 0x9b: 257706f2543Smrg name = "SETNP\t"; 258706f2543Smrg cond = !ACCESS_FLAG(F_PF); 259706f2543Smrg break; 260706f2543Smrg case 0x9c: 261706f2543Smrg name = "SETL\t"; 262706f2543Smrg cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); 263706f2543Smrg break; 264706f2543Smrg case 0x9d: 265706f2543Smrg name = "SETNL\t"; 266706f2543Smrg cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); 267706f2543Smrg break; 268706f2543Smrg case 0x9e: 269706f2543Smrg name = "SETLE\t"; 270706f2543Smrg cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 271706f2543Smrg ACCESS_FLAG(F_ZF)); 272706f2543Smrg break; 273706f2543Smrg case 0x9f: 274706f2543Smrg name = "SETNLE\t"; 275706f2543Smrg cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || 276706f2543Smrg ACCESS_FLAG(F_ZF)); 277706f2543Smrg break; 278706f2543Smrg } 279706f2543Smrg DECODE_PRINTF(name); 280706f2543Smrg (void)name; 281706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 282706f2543Smrg switch (mod) { 283706f2543Smrg case 0: 284706f2543Smrg destoffset = decode_rm00_address(rl); 285706f2543Smrg TRACE_AND_STEP(); 286706f2543Smrg store_data_byte(destoffset, cond ? 0x01 : 0x00); 287706f2543Smrg break; 288706f2543Smrg case 1: 289706f2543Smrg destoffset = decode_rm01_address(rl); 290706f2543Smrg TRACE_AND_STEP(); 291706f2543Smrg store_data_byte(destoffset, cond ? 0x01 : 0x00); 292706f2543Smrg break; 293706f2543Smrg case 2: 294706f2543Smrg destoffset = decode_rm10_address(rl); 295706f2543Smrg TRACE_AND_STEP(); 296706f2543Smrg store_data_byte(destoffset, cond ? 0x01 : 0x00); 297706f2543Smrg break; 298706f2543Smrg case 3: /* register to register */ 299706f2543Smrg destreg = DECODE_RM_BYTE_REGISTER(rl); 300706f2543Smrg TRACE_AND_STEP(); 301706f2543Smrg *destreg = cond ? 0x01 : 0x00; 302706f2543Smrg break; 303706f2543Smrg } 304706f2543Smrg DECODE_CLEAR_SEGOVR(); 305706f2543Smrg END_OF_INSTR(); 306706f2543Smrg} 307706f2543Smrg 308706f2543Smrg/**************************************************************************** 309706f2543SmrgREMARKS: 310706f2543SmrgHandles opcode 0x0f,0xa0 311706f2543Smrg****************************************************************************/ 312706f2543Smrgstatic void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2)) 313706f2543Smrg{ 314706f2543Smrg START_OF_INSTR(); 315706f2543Smrg DECODE_PRINTF("PUSH\tFS\n"); 316706f2543Smrg TRACE_AND_STEP(); 317706f2543Smrg push_word(M.x86.R_FS); 318706f2543Smrg DECODE_CLEAR_SEGOVR(); 319706f2543Smrg END_OF_INSTR(); 320706f2543Smrg} 321706f2543Smrg 322706f2543Smrg/**************************************************************************** 323706f2543SmrgREMARKS: 324706f2543SmrgHandles opcode 0x0f,0xa1 325706f2543Smrg****************************************************************************/ 326706f2543Smrgstatic void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2)) 327706f2543Smrg{ 328706f2543Smrg START_OF_INSTR(); 329706f2543Smrg DECODE_PRINTF("POP\tFS\n"); 330706f2543Smrg TRACE_AND_STEP(); 331706f2543Smrg M.x86.R_FS = pop_word(); 332706f2543Smrg DECODE_CLEAR_SEGOVR(); 333706f2543Smrg END_OF_INSTR(); 334706f2543Smrg} 335706f2543Smrg 336706f2543Smrg/**************************************************************************** 337706f2543SmrgREMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output 338706f2543SmrgHandles opcode 0x0f,0xa2 339706f2543Smrg****************************************************************************/ 340706f2543Smrgstatic void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2)) 341706f2543Smrg{ 342706f2543Smrg START_OF_INSTR(); 343706f2543Smrg DECODE_PRINTF("CPUID\n"); 344706f2543Smrg TRACE_AND_STEP(); 345706f2543Smrg cpuid(); 346706f2543Smrg DECODE_CLEAR_SEGOVR(); 347706f2543Smrg END_OF_INSTR(); 348706f2543Smrg} 349706f2543Smrg 350706f2543Smrg/**************************************************************************** 351706f2543SmrgREMARKS: 352706f2543SmrgHandles opcode 0x0f,0xa3 353706f2543Smrg****************************************************************************/ 354706f2543Smrgstatic void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2)) 355706f2543Smrg{ 356706f2543Smrg int mod, rl, rh; 357706f2543Smrg uint srcoffset; 358706f2543Smrg int bit,disp; 359706f2543Smrg 360706f2543Smrg START_OF_INSTR(); 361706f2543Smrg DECODE_PRINTF("BT\t"); 362706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 363706f2543Smrg switch (mod) { 364706f2543Smrg case 0: 365706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 366706f2543Smrg u32 srcval; 367706f2543Smrg u32 *shiftreg; 368706f2543Smrg 369706f2543Smrg srcoffset = decode_rm00_address(rl); 370706f2543Smrg DECODE_PRINTF(","); 371706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 372706f2543Smrg TRACE_AND_STEP(); 373706f2543Smrg bit = *shiftreg & 0x1F; 374706f2543Smrg disp = (s16)*shiftreg >> 5; 375706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 376706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 377706f2543Smrg } else { 378706f2543Smrg u16 srcval; 379706f2543Smrg u16 *shiftreg; 380706f2543Smrg 381706f2543Smrg srcoffset = decode_rm00_address(rl); 382706f2543Smrg DECODE_PRINTF(","); 383706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 384706f2543Smrg TRACE_AND_STEP(); 385706f2543Smrg bit = *shiftreg & 0xF; 386706f2543Smrg disp = (s16)*shiftreg >> 4; 387706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 388706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 389706f2543Smrg } 390706f2543Smrg break; 391706f2543Smrg case 1: 392706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 393706f2543Smrg u32 srcval; 394706f2543Smrg u32 *shiftreg; 395706f2543Smrg 396706f2543Smrg srcoffset = decode_rm01_address(rl); 397706f2543Smrg DECODE_PRINTF(","); 398706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 399706f2543Smrg TRACE_AND_STEP(); 400706f2543Smrg bit = *shiftreg & 0x1F; 401706f2543Smrg disp = (s16)*shiftreg >> 5; 402706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 403706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 404706f2543Smrg } else { 405706f2543Smrg u16 srcval; 406706f2543Smrg u16 *shiftreg; 407706f2543Smrg 408706f2543Smrg srcoffset = decode_rm01_address(rl); 409706f2543Smrg DECODE_PRINTF(","); 410706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 411706f2543Smrg TRACE_AND_STEP(); 412706f2543Smrg bit = *shiftreg & 0xF; 413706f2543Smrg disp = (s16)*shiftreg >> 4; 414706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 415706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 416706f2543Smrg } 417706f2543Smrg break; 418706f2543Smrg case 2: 419706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 420706f2543Smrg u32 srcval; 421706f2543Smrg u32 *shiftreg; 422706f2543Smrg 423706f2543Smrg srcoffset = decode_rm10_address(rl); 424706f2543Smrg DECODE_PRINTF(","); 425706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 426706f2543Smrg TRACE_AND_STEP(); 427706f2543Smrg bit = *shiftreg & 0x1F; 428706f2543Smrg disp = (s16)*shiftreg >> 5; 429706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 430706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 431706f2543Smrg } else { 432706f2543Smrg u16 srcval; 433706f2543Smrg u16 *shiftreg; 434706f2543Smrg 435706f2543Smrg srcoffset = decode_rm10_address(rl); 436706f2543Smrg DECODE_PRINTF(","); 437706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 438706f2543Smrg TRACE_AND_STEP(); 439706f2543Smrg bit = *shiftreg & 0xF; 440706f2543Smrg disp = (s16)*shiftreg >> 4; 441706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 442706f2543Smrg CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); 443706f2543Smrg } 444706f2543Smrg break; 445706f2543Smrg case 3: /* register to register */ 446706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 447706f2543Smrg u32 *srcreg,*shiftreg; 448706f2543Smrg 449706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 450706f2543Smrg DECODE_PRINTF(","); 451706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 452706f2543Smrg TRACE_AND_STEP(); 453706f2543Smrg bit = *shiftreg & 0x1F; 454706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); 455706f2543Smrg } else { 456706f2543Smrg u16 *srcreg,*shiftreg; 457706f2543Smrg 458706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 459706f2543Smrg DECODE_PRINTF(","); 460706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 461706f2543Smrg TRACE_AND_STEP(); 462706f2543Smrg bit = *shiftreg & 0xF; 463706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); 464706f2543Smrg } 465706f2543Smrg break; 466706f2543Smrg } 467706f2543Smrg DECODE_CLEAR_SEGOVR(); 468706f2543Smrg END_OF_INSTR(); 469706f2543Smrg} 470706f2543Smrg 471706f2543Smrg/**************************************************************************** 472706f2543SmrgREMARKS: 473706f2543SmrgHandles opcode 0x0f,0xa4 474706f2543Smrg****************************************************************************/ 475706f2543Smrgstatic void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2)) 476706f2543Smrg{ 477706f2543Smrg int mod, rl, rh; 478706f2543Smrg uint destoffset; 479706f2543Smrg u8 shift; 480706f2543Smrg 481706f2543Smrg START_OF_INSTR(); 482706f2543Smrg DECODE_PRINTF("SHLD\t"); 483706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 484706f2543Smrg switch (mod) { 485706f2543Smrg case 0: 486706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 487706f2543Smrg u32 destval; 488706f2543Smrg u32 *shiftreg; 489706f2543Smrg 490706f2543Smrg destoffset = decode_rm00_address(rl); 491706f2543Smrg DECODE_PRINTF(","); 492706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 493706f2543Smrg DECODE_PRINTF(","); 494706f2543Smrg shift = fetch_byte_imm(); 495706f2543Smrg DECODE_PRINTF2("%d\n", shift); 496706f2543Smrg TRACE_AND_STEP(); 497706f2543Smrg destval = fetch_data_long(destoffset); 498706f2543Smrg destval = shld_long(destval,*shiftreg,shift); 499706f2543Smrg store_data_long(destoffset, destval); 500706f2543Smrg } else { 501706f2543Smrg u16 destval; 502706f2543Smrg u16 *shiftreg; 503706f2543Smrg 504706f2543Smrg destoffset = decode_rm00_address(rl); 505706f2543Smrg DECODE_PRINTF(","); 506706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 507706f2543Smrg DECODE_PRINTF(","); 508706f2543Smrg shift = fetch_byte_imm(); 509706f2543Smrg DECODE_PRINTF2("%d\n", shift); 510706f2543Smrg TRACE_AND_STEP(); 511706f2543Smrg destval = fetch_data_word(destoffset); 512706f2543Smrg destval = shld_word(destval,*shiftreg,shift); 513706f2543Smrg store_data_word(destoffset, destval); 514706f2543Smrg } 515706f2543Smrg break; 516706f2543Smrg case 1: 517706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 518706f2543Smrg u32 destval; 519706f2543Smrg u32 *shiftreg; 520706f2543Smrg 521706f2543Smrg destoffset = decode_rm01_address(rl); 522706f2543Smrg DECODE_PRINTF(","); 523706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 524706f2543Smrg DECODE_PRINTF(","); 525706f2543Smrg shift = fetch_byte_imm(); 526706f2543Smrg DECODE_PRINTF2("%d\n", shift); 527706f2543Smrg TRACE_AND_STEP(); 528706f2543Smrg destval = fetch_data_long(destoffset); 529706f2543Smrg destval = shld_long(destval,*shiftreg,shift); 530706f2543Smrg store_data_long(destoffset, destval); 531706f2543Smrg } else { 532706f2543Smrg u16 destval; 533706f2543Smrg u16 *shiftreg; 534706f2543Smrg 535706f2543Smrg destoffset = decode_rm01_address(rl); 536706f2543Smrg DECODE_PRINTF(","); 537706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 538706f2543Smrg DECODE_PRINTF(","); 539706f2543Smrg shift = fetch_byte_imm(); 540706f2543Smrg DECODE_PRINTF2("%d\n", shift); 541706f2543Smrg TRACE_AND_STEP(); 542706f2543Smrg destval = fetch_data_word(destoffset); 543706f2543Smrg destval = shld_word(destval,*shiftreg,shift); 544706f2543Smrg store_data_word(destoffset, destval); 545706f2543Smrg } 546706f2543Smrg break; 547706f2543Smrg case 2: 548706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 549706f2543Smrg u32 destval; 550706f2543Smrg u32 *shiftreg; 551706f2543Smrg 552706f2543Smrg destoffset = decode_rm10_address(rl); 553706f2543Smrg DECODE_PRINTF(","); 554706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 555706f2543Smrg DECODE_PRINTF(","); 556706f2543Smrg shift = fetch_byte_imm(); 557706f2543Smrg DECODE_PRINTF2("%d\n", shift); 558706f2543Smrg TRACE_AND_STEP(); 559706f2543Smrg destval = fetch_data_long(destoffset); 560706f2543Smrg destval = shld_long(destval,*shiftreg,shift); 561706f2543Smrg store_data_long(destoffset, destval); 562706f2543Smrg } else { 563706f2543Smrg u16 destval; 564706f2543Smrg u16 *shiftreg; 565706f2543Smrg 566706f2543Smrg destoffset = decode_rm10_address(rl); 567706f2543Smrg DECODE_PRINTF(","); 568706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 569706f2543Smrg DECODE_PRINTF(","); 570706f2543Smrg shift = fetch_byte_imm(); 571706f2543Smrg DECODE_PRINTF2("%d\n", shift); 572706f2543Smrg TRACE_AND_STEP(); 573706f2543Smrg destval = fetch_data_word(destoffset); 574706f2543Smrg destval = shld_word(destval,*shiftreg,shift); 575706f2543Smrg store_data_word(destoffset, destval); 576706f2543Smrg } 577706f2543Smrg break; 578706f2543Smrg case 3: /* register to register */ 579706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 580706f2543Smrg u32 *destreg,*shiftreg; 581706f2543Smrg 582706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rl); 583706f2543Smrg DECODE_PRINTF(","); 584706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 585706f2543Smrg DECODE_PRINTF(","); 586706f2543Smrg shift = fetch_byte_imm(); 587706f2543Smrg DECODE_PRINTF2("%d\n", shift); 588706f2543Smrg TRACE_AND_STEP(); 589706f2543Smrg *destreg = shld_long(*destreg,*shiftreg,shift); 590706f2543Smrg } else { 591706f2543Smrg u16 *destreg,*shiftreg; 592706f2543Smrg 593706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rl); 594706f2543Smrg DECODE_PRINTF(","); 595706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 596706f2543Smrg DECODE_PRINTF(","); 597706f2543Smrg shift = fetch_byte_imm(); 598706f2543Smrg DECODE_PRINTF2("%d\n", shift); 599706f2543Smrg TRACE_AND_STEP(); 600706f2543Smrg *destreg = shld_word(*destreg,*shiftreg,shift); 601706f2543Smrg } 602706f2543Smrg break; 603706f2543Smrg } 604706f2543Smrg DECODE_CLEAR_SEGOVR(); 605706f2543Smrg END_OF_INSTR(); 606706f2543Smrg} 607706f2543Smrg 608706f2543Smrg/**************************************************************************** 609706f2543SmrgREMARKS: 610706f2543SmrgHandles opcode 0x0f,0xa5 611706f2543Smrg****************************************************************************/ 612706f2543Smrgstatic void x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2)) 613706f2543Smrg{ 614706f2543Smrg int mod, rl, rh; 615706f2543Smrg uint destoffset; 616706f2543Smrg 617706f2543Smrg START_OF_INSTR(); 618706f2543Smrg DECODE_PRINTF("SHLD\t"); 619706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 620706f2543Smrg switch (mod) { 621706f2543Smrg case 0: 622706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 623706f2543Smrg u32 destval; 624706f2543Smrg u32 *shiftreg; 625706f2543Smrg 626706f2543Smrg destoffset = decode_rm00_address(rl); 627706f2543Smrg DECODE_PRINTF(","); 628706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 629706f2543Smrg DECODE_PRINTF(",CL\n"); 630706f2543Smrg TRACE_AND_STEP(); 631706f2543Smrg destval = fetch_data_long(destoffset); 632706f2543Smrg destval = shld_long(destval,*shiftreg,M.x86.R_CL); 633706f2543Smrg store_data_long(destoffset, destval); 634706f2543Smrg } else { 635706f2543Smrg u16 destval; 636706f2543Smrg u16 *shiftreg; 637706f2543Smrg 638706f2543Smrg destoffset = decode_rm00_address(rl); 639706f2543Smrg DECODE_PRINTF(","); 640706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 641706f2543Smrg DECODE_PRINTF(",CL\n"); 642706f2543Smrg TRACE_AND_STEP(); 643706f2543Smrg destval = fetch_data_word(destoffset); 644706f2543Smrg destval = shld_word(destval,*shiftreg,M.x86.R_CL); 645706f2543Smrg store_data_word(destoffset, destval); 646706f2543Smrg } 647706f2543Smrg break; 648706f2543Smrg case 1: 649706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 650706f2543Smrg u32 destval; 651706f2543Smrg u32 *shiftreg; 652706f2543Smrg 653706f2543Smrg destoffset = decode_rm01_address(rl); 654706f2543Smrg DECODE_PRINTF(","); 655706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 656706f2543Smrg DECODE_PRINTF(",CL\n"); 657706f2543Smrg TRACE_AND_STEP(); 658706f2543Smrg destval = fetch_data_long(destoffset); 659706f2543Smrg destval = shld_long(destval,*shiftreg,M.x86.R_CL); 660706f2543Smrg store_data_long(destoffset, destval); 661706f2543Smrg } else { 662706f2543Smrg u16 destval; 663706f2543Smrg u16 *shiftreg; 664706f2543Smrg 665706f2543Smrg destoffset = decode_rm01_address(rl); 666706f2543Smrg DECODE_PRINTF(","); 667706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 668706f2543Smrg DECODE_PRINTF(",CL\n"); 669706f2543Smrg TRACE_AND_STEP(); 670706f2543Smrg destval = fetch_data_word(destoffset); 671706f2543Smrg destval = shld_word(destval,*shiftreg,M.x86.R_CL); 672706f2543Smrg store_data_word(destoffset, destval); 673706f2543Smrg } 674706f2543Smrg break; 675706f2543Smrg case 2: 676706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 677706f2543Smrg u32 destval; 678706f2543Smrg u32 *shiftreg; 679706f2543Smrg 680706f2543Smrg destoffset = decode_rm10_address(rl); 681706f2543Smrg DECODE_PRINTF(","); 682706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 683706f2543Smrg DECODE_PRINTF(",CL\n"); 684706f2543Smrg TRACE_AND_STEP(); 685706f2543Smrg destval = fetch_data_long(destoffset); 686706f2543Smrg destval = shld_long(destval,*shiftreg,M.x86.R_CL); 687706f2543Smrg store_data_long(destoffset, destval); 688706f2543Smrg } else { 689706f2543Smrg u16 destval; 690706f2543Smrg u16 *shiftreg; 691706f2543Smrg 692706f2543Smrg destoffset = decode_rm10_address(rl); 693706f2543Smrg DECODE_PRINTF(","); 694706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 695706f2543Smrg DECODE_PRINTF(",CL\n"); 696706f2543Smrg TRACE_AND_STEP(); 697706f2543Smrg destval = fetch_data_word(destoffset); 698706f2543Smrg destval = shld_word(destval,*shiftreg,M.x86.R_CL); 699706f2543Smrg store_data_word(destoffset, destval); 700706f2543Smrg } 701706f2543Smrg break; 702706f2543Smrg case 3: /* register to register */ 703706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 704706f2543Smrg u32 *destreg,*shiftreg; 705706f2543Smrg 706706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rl); 707706f2543Smrg DECODE_PRINTF(","); 708706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 709706f2543Smrg DECODE_PRINTF(",CL\n"); 710706f2543Smrg TRACE_AND_STEP(); 711706f2543Smrg *destreg = shld_long(*destreg,*shiftreg,M.x86.R_CL); 712706f2543Smrg } else { 713706f2543Smrg u16 *destreg,*shiftreg; 714706f2543Smrg 715706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rl); 716706f2543Smrg DECODE_PRINTF(","); 717706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 718706f2543Smrg DECODE_PRINTF(",CL\n"); 719706f2543Smrg TRACE_AND_STEP(); 720706f2543Smrg *destreg = shld_word(*destreg,*shiftreg,M.x86.R_CL); 721706f2543Smrg } 722706f2543Smrg break; 723706f2543Smrg } 724706f2543Smrg DECODE_CLEAR_SEGOVR(); 725706f2543Smrg END_OF_INSTR(); 726706f2543Smrg} 727706f2543Smrg 728706f2543Smrg/**************************************************************************** 729706f2543SmrgREMARKS: 730706f2543SmrgHandles opcode 0x0f,0xa8 731706f2543Smrg****************************************************************************/ 732706f2543Smrgstatic void x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2)) 733706f2543Smrg{ 734706f2543Smrg START_OF_INSTR(); 735706f2543Smrg DECODE_PRINTF("PUSH\tGS\n"); 736706f2543Smrg TRACE_AND_STEP(); 737706f2543Smrg push_word(M.x86.R_GS); 738706f2543Smrg DECODE_CLEAR_SEGOVR(); 739706f2543Smrg END_OF_INSTR(); 740706f2543Smrg} 741706f2543Smrg 742706f2543Smrg/**************************************************************************** 743706f2543SmrgREMARKS: 744706f2543SmrgHandles opcode 0x0f,0xa9 745706f2543Smrg****************************************************************************/ 746706f2543Smrgstatic void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2)) 747706f2543Smrg{ 748706f2543Smrg START_OF_INSTR(); 749706f2543Smrg DECODE_PRINTF("POP\tGS\n"); 750706f2543Smrg TRACE_AND_STEP(); 751706f2543Smrg M.x86.R_GS = pop_word(); 752706f2543Smrg DECODE_CLEAR_SEGOVR(); 753706f2543Smrg END_OF_INSTR(); 754706f2543Smrg} 755706f2543Smrg 756706f2543Smrg/**************************************************************************** 757706f2543SmrgREMARKS: 758706f2543SmrgHandles opcode 0x0f,0xab 759706f2543Smrg****************************************************************************/ 760706f2543Smrgstatic void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2)) 761706f2543Smrg{ 762706f2543Smrg int mod, rl, rh; 763706f2543Smrg uint srcoffset; 764706f2543Smrg int bit,disp; 765706f2543Smrg 766706f2543Smrg START_OF_INSTR(); 767706f2543Smrg DECODE_PRINTF("BTS\t"); 768706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 769706f2543Smrg switch (mod) { 770706f2543Smrg case 0: 771706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 772706f2543Smrg u32 srcval,mask; 773706f2543Smrg u32 *shiftreg; 774706f2543Smrg 775706f2543Smrg srcoffset = decode_rm00_address(rl); 776706f2543Smrg DECODE_PRINTF(","); 777706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 778706f2543Smrg TRACE_AND_STEP(); 779706f2543Smrg bit = *shiftreg & 0x1F; 780706f2543Smrg disp = (s16)*shiftreg >> 5; 781706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 782706f2543Smrg mask = (0x1 << bit); 783706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 784706f2543Smrg store_data_long(srcoffset+disp, srcval | mask); 785706f2543Smrg } else { 786706f2543Smrg u16 srcval,mask; 787706f2543Smrg u16 *shiftreg; 788706f2543Smrg 789706f2543Smrg srcoffset = decode_rm00_address(rl); 790706f2543Smrg DECODE_PRINTF(","); 791706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 792706f2543Smrg TRACE_AND_STEP(); 793706f2543Smrg bit = *shiftreg & 0xF; 794706f2543Smrg disp = (s16)*shiftreg >> 4; 795706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 796706f2543Smrg mask = (u16)(0x1 << bit); 797706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 798706f2543Smrg store_data_word(srcoffset+disp, srcval | mask); 799706f2543Smrg } 800706f2543Smrg break; 801706f2543Smrg case 1: 802706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 803706f2543Smrg u32 srcval,mask; 804706f2543Smrg u32 *shiftreg; 805706f2543Smrg 806706f2543Smrg srcoffset = decode_rm01_address(rl); 807706f2543Smrg DECODE_PRINTF(","); 808706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 809706f2543Smrg TRACE_AND_STEP(); 810706f2543Smrg bit = *shiftreg & 0x1F; 811706f2543Smrg disp = (s16)*shiftreg >> 5; 812706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 813706f2543Smrg mask = (0x1 << bit); 814706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 815706f2543Smrg store_data_long(srcoffset+disp, srcval | mask); 816706f2543Smrg } else { 817706f2543Smrg u16 srcval,mask; 818706f2543Smrg u16 *shiftreg; 819706f2543Smrg 820706f2543Smrg srcoffset = decode_rm01_address(rl); 821706f2543Smrg DECODE_PRINTF(","); 822706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 823706f2543Smrg TRACE_AND_STEP(); 824706f2543Smrg bit = *shiftreg & 0xF; 825706f2543Smrg disp = (s16)*shiftreg >> 4; 826706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 827706f2543Smrg mask = (u16)(0x1 << bit); 828706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 829706f2543Smrg store_data_word(srcoffset+disp, srcval | mask); 830706f2543Smrg } 831706f2543Smrg break; 832706f2543Smrg case 2: 833706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 834706f2543Smrg u32 srcval,mask; 835706f2543Smrg u32 *shiftreg; 836706f2543Smrg 837706f2543Smrg srcoffset = decode_rm10_address(rl); 838706f2543Smrg DECODE_PRINTF(","); 839706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 840706f2543Smrg TRACE_AND_STEP(); 841706f2543Smrg bit = *shiftreg & 0x1F; 842706f2543Smrg disp = (s16)*shiftreg >> 5; 843706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 844706f2543Smrg mask = (0x1 << bit); 845706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 846706f2543Smrg store_data_long(srcoffset+disp, srcval | mask); 847706f2543Smrg } else { 848706f2543Smrg u16 srcval,mask; 849706f2543Smrg u16 *shiftreg; 850706f2543Smrg 851706f2543Smrg srcoffset = decode_rm10_address(rl); 852706f2543Smrg DECODE_PRINTF(","); 853706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 854706f2543Smrg TRACE_AND_STEP(); 855706f2543Smrg bit = *shiftreg & 0xF; 856706f2543Smrg disp = (s16)*shiftreg >> 4; 857706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 858706f2543Smrg mask = (u16)(0x1 << bit); 859706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 860706f2543Smrg store_data_word(srcoffset+disp, srcval | mask); 861706f2543Smrg } 862706f2543Smrg break; 863706f2543Smrg case 3: /* register to register */ 864706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 865706f2543Smrg u32 *srcreg,*shiftreg; 866706f2543Smrg u32 mask; 867706f2543Smrg 868706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 869706f2543Smrg DECODE_PRINTF(","); 870706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 871706f2543Smrg TRACE_AND_STEP(); 872706f2543Smrg bit = *shiftreg & 0x1F; 873706f2543Smrg mask = (0x1 << bit); 874706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 875706f2543Smrg *srcreg |= mask; 876706f2543Smrg } else { 877706f2543Smrg u16 *srcreg,*shiftreg; 878706f2543Smrg u16 mask; 879706f2543Smrg 880706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 881706f2543Smrg DECODE_PRINTF(","); 882706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 883706f2543Smrg TRACE_AND_STEP(); 884706f2543Smrg bit = *shiftreg & 0xF; 885706f2543Smrg mask = (u16)(0x1 << bit); 886706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 887706f2543Smrg *srcreg |= mask; 888706f2543Smrg } 889706f2543Smrg break; 890706f2543Smrg } 891706f2543Smrg DECODE_CLEAR_SEGOVR(); 892706f2543Smrg END_OF_INSTR(); 893706f2543Smrg} 894706f2543Smrg 895706f2543Smrg/**************************************************************************** 896706f2543SmrgREMARKS: 897706f2543SmrgHandles opcode 0x0f,0xac 898706f2543Smrg****************************************************************************/ 899706f2543Smrgstatic void x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2)) 900706f2543Smrg{ 901706f2543Smrg int mod, rl, rh; 902706f2543Smrg uint destoffset; 903706f2543Smrg u8 shift; 904706f2543Smrg 905706f2543Smrg START_OF_INSTR(); 906706f2543Smrg DECODE_PRINTF("SHLD\t"); 907706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 908706f2543Smrg switch (mod) { 909706f2543Smrg case 0: 910706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 911706f2543Smrg u32 destval; 912706f2543Smrg u32 *shiftreg; 913706f2543Smrg 914706f2543Smrg destoffset = decode_rm00_address(rl); 915706f2543Smrg DECODE_PRINTF(","); 916706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 917706f2543Smrg DECODE_PRINTF(","); 918706f2543Smrg shift = fetch_byte_imm(); 919706f2543Smrg DECODE_PRINTF2("%d\n", shift); 920706f2543Smrg TRACE_AND_STEP(); 921706f2543Smrg destval = fetch_data_long(destoffset); 922706f2543Smrg destval = shrd_long(destval,*shiftreg,shift); 923706f2543Smrg store_data_long(destoffset, destval); 924706f2543Smrg } else { 925706f2543Smrg u16 destval; 926706f2543Smrg u16 *shiftreg; 927706f2543Smrg 928706f2543Smrg destoffset = decode_rm00_address(rl); 929706f2543Smrg DECODE_PRINTF(","); 930706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 931706f2543Smrg DECODE_PRINTF(","); 932706f2543Smrg shift = fetch_byte_imm(); 933706f2543Smrg DECODE_PRINTF2("%d\n", shift); 934706f2543Smrg TRACE_AND_STEP(); 935706f2543Smrg destval = fetch_data_word(destoffset); 936706f2543Smrg destval = shrd_word(destval,*shiftreg,shift); 937706f2543Smrg store_data_word(destoffset, destval); 938706f2543Smrg } 939706f2543Smrg break; 940706f2543Smrg case 1: 941706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 942706f2543Smrg u32 destval; 943706f2543Smrg u32 *shiftreg; 944706f2543Smrg 945706f2543Smrg destoffset = decode_rm01_address(rl); 946706f2543Smrg DECODE_PRINTF(","); 947706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 948706f2543Smrg DECODE_PRINTF(","); 949706f2543Smrg shift = fetch_byte_imm(); 950706f2543Smrg DECODE_PRINTF2("%d\n", shift); 951706f2543Smrg TRACE_AND_STEP(); 952706f2543Smrg destval = fetch_data_long(destoffset); 953706f2543Smrg destval = shrd_long(destval,*shiftreg,shift); 954706f2543Smrg store_data_long(destoffset, destval); 955706f2543Smrg } else { 956706f2543Smrg u16 destval; 957706f2543Smrg u16 *shiftreg; 958706f2543Smrg 959706f2543Smrg destoffset = decode_rm01_address(rl); 960706f2543Smrg DECODE_PRINTF(","); 961706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 962706f2543Smrg DECODE_PRINTF(","); 963706f2543Smrg shift = fetch_byte_imm(); 964706f2543Smrg DECODE_PRINTF2("%d\n", shift); 965706f2543Smrg TRACE_AND_STEP(); 966706f2543Smrg destval = fetch_data_word(destoffset); 967706f2543Smrg destval = shrd_word(destval,*shiftreg,shift); 968706f2543Smrg store_data_word(destoffset, destval); 969706f2543Smrg } 970706f2543Smrg break; 971706f2543Smrg case 2: 972706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 973706f2543Smrg u32 destval; 974706f2543Smrg u32 *shiftreg; 975706f2543Smrg 976706f2543Smrg destoffset = decode_rm10_address(rl); 977706f2543Smrg DECODE_PRINTF(","); 978706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 979706f2543Smrg DECODE_PRINTF(","); 980706f2543Smrg shift = fetch_byte_imm(); 981706f2543Smrg DECODE_PRINTF2("%d\n", shift); 982706f2543Smrg TRACE_AND_STEP(); 983706f2543Smrg destval = fetch_data_long(destoffset); 984706f2543Smrg destval = shrd_long(destval,*shiftreg,shift); 985706f2543Smrg store_data_long(destoffset, destval); 986706f2543Smrg } else { 987706f2543Smrg u16 destval; 988706f2543Smrg u16 *shiftreg; 989706f2543Smrg 990706f2543Smrg destoffset = decode_rm10_address(rl); 991706f2543Smrg DECODE_PRINTF(","); 992706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 993706f2543Smrg DECODE_PRINTF(","); 994706f2543Smrg shift = fetch_byte_imm(); 995706f2543Smrg DECODE_PRINTF2("%d\n", shift); 996706f2543Smrg TRACE_AND_STEP(); 997706f2543Smrg destval = fetch_data_word(destoffset); 998706f2543Smrg destval = shrd_word(destval,*shiftreg,shift); 999706f2543Smrg store_data_word(destoffset, destval); 1000706f2543Smrg } 1001706f2543Smrg break; 1002706f2543Smrg case 3: /* register to register */ 1003706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1004706f2543Smrg u32 *destreg,*shiftreg; 1005706f2543Smrg 1006706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rl); 1007706f2543Smrg DECODE_PRINTF(","); 1008706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1009706f2543Smrg DECODE_PRINTF(","); 1010706f2543Smrg shift = fetch_byte_imm(); 1011706f2543Smrg DECODE_PRINTF2("%d\n", shift); 1012706f2543Smrg TRACE_AND_STEP(); 1013706f2543Smrg *destreg = shrd_long(*destreg,*shiftreg,shift); 1014706f2543Smrg } else { 1015706f2543Smrg u16 *destreg,*shiftreg; 1016706f2543Smrg 1017706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rl); 1018706f2543Smrg DECODE_PRINTF(","); 1019706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1020706f2543Smrg DECODE_PRINTF(","); 1021706f2543Smrg shift = fetch_byte_imm(); 1022706f2543Smrg DECODE_PRINTF2("%d\n", shift); 1023706f2543Smrg TRACE_AND_STEP(); 1024706f2543Smrg *destreg = shrd_word(*destreg,*shiftreg,shift); 1025706f2543Smrg } 1026706f2543Smrg break; 1027706f2543Smrg } 1028706f2543Smrg DECODE_CLEAR_SEGOVR(); 1029706f2543Smrg END_OF_INSTR(); 1030706f2543Smrg} 1031706f2543Smrg 1032706f2543Smrg/**************************************************************************** 1033706f2543SmrgREMARKS: 1034706f2543SmrgHandles opcode 0x0f,0xad 1035706f2543Smrg****************************************************************************/ 1036706f2543Smrgstatic void x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2)) 1037706f2543Smrg{ 1038706f2543Smrg int mod, rl, rh; 1039706f2543Smrg uint destoffset; 1040706f2543Smrg 1041706f2543Smrg START_OF_INSTR(); 1042706f2543Smrg DECODE_PRINTF("SHLD\t"); 1043706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1044706f2543Smrg switch (mod) { 1045706f2543Smrg case 0: 1046706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1047706f2543Smrg u32 destval; 1048706f2543Smrg u32 *shiftreg; 1049706f2543Smrg 1050706f2543Smrg destoffset = decode_rm00_address(rl); 1051706f2543Smrg DECODE_PRINTF(","); 1052706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1053706f2543Smrg DECODE_PRINTF(",CL\n"); 1054706f2543Smrg TRACE_AND_STEP(); 1055706f2543Smrg destval = fetch_data_long(destoffset); 1056706f2543Smrg destval = shrd_long(destval,*shiftreg,M.x86.R_CL); 1057706f2543Smrg store_data_long(destoffset, destval); 1058706f2543Smrg } else { 1059706f2543Smrg u16 destval; 1060706f2543Smrg u16 *shiftreg; 1061706f2543Smrg 1062706f2543Smrg destoffset = decode_rm00_address(rl); 1063706f2543Smrg DECODE_PRINTF(","); 1064706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1065706f2543Smrg DECODE_PRINTF(",CL\n"); 1066706f2543Smrg TRACE_AND_STEP(); 1067706f2543Smrg destval = fetch_data_word(destoffset); 1068706f2543Smrg destval = shrd_word(destval,*shiftreg,M.x86.R_CL); 1069706f2543Smrg store_data_word(destoffset, destval); 1070706f2543Smrg } 1071706f2543Smrg break; 1072706f2543Smrg case 1: 1073706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1074706f2543Smrg u32 destval; 1075706f2543Smrg u32 *shiftreg; 1076706f2543Smrg 1077706f2543Smrg destoffset = decode_rm01_address(rl); 1078706f2543Smrg DECODE_PRINTF(","); 1079706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1080706f2543Smrg DECODE_PRINTF(",CL\n"); 1081706f2543Smrg TRACE_AND_STEP(); 1082706f2543Smrg destval = fetch_data_long(destoffset); 1083706f2543Smrg destval = shrd_long(destval,*shiftreg,M.x86.R_CL); 1084706f2543Smrg store_data_long(destoffset, destval); 1085706f2543Smrg } else { 1086706f2543Smrg u16 destval; 1087706f2543Smrg u16 *shiftreg; 1088706f2543Smrg 1089706f2543Smrg destoffset = decode_rm01_address(rl); 1090706f2543Smrg DECODE_PRINTF(","); 1091706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1092706f2543Smrg DECODE_PRINTF(",CL\n"); 1093706f2543Smrg TRACE_AND_STEP(); 1094706f2543Smrg destval = fetch_data_word(destoffset); 1095706f2543Smrg destval = shrd_word(destval,*shiftreg,M.x86.R_CL); 1096706f2543Smrg store_data_word(destoffset, destval); 1097706f2543Smrg } 1098706f2543Smrg break; 1099706f2543Smrg case 2: 1100706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1101706f2543Smrg u32 destval; 1102706f2543Smrg u32 *shiftreg; 1103706f2543Smrg 1104706f2543Smrg destoffset = decode_rm10_address(rl); 1105706f2543Smrg DECODE_PRINTF(","); 1106706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1107706f2543Smrg DECODE_PRINTF(",CL\n"); 1108706f2543Smrg TRACE_AND_STEP(); 1109706f2543Smrg destval = fetch_data_long(destoffset); 1110706f2543Smrg destval = shrd_long(destval,*shiftreg,M.x86.R_CL); 1111706f2543Smrg store_data_long(destoffset, destval); 1112706f2543Smrg } else { 1113706f2543Smrg u16 destval; 1114706f2543Smrg u16 *shiftreg; 1115706f2543Smrg 1116706f2543Smrg destoffset = decode_rm10_address(rl); 1117706f2543Smrg DECODE_PRINTF(","); 1118706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1119706f2543Smrg DECODE_PRINTF(",CL\n"); 1120706f2543Smrg TRACE_AND_STEP(); 1121706f2543Smrg destval = fetch_data_word(destoffset); 1122706f2543Smrg destval = shrd_word(destval,*shiftreg,M.x86.R_CL); 1123706f2543Smrg store_data_word(destoffset, destval); 1124706f2543Smrg } 1125706f2543Smrg break; 1126706f2543Smrg case 3: /* register to register */ 1127706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1128706f2543Smrg u32 *destreg,*shiftreg; 1129706f2543Smrg 1130706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rl); 1131706f2543Smrg DECODE_PRINTF(","); 1132706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1133706f2543Smrg DECODE_PRINTF(",CL\n"); 1134706f2543Smrg TRACE_AND_STEP(); 1135706f2543Smrg *destreg = shrd_long(*destreg,*shiftreg,M.x86.R_CL); 1136706f2543Smrg } else { 1137706f2543Smrg u16 *destreg,*shiftreg; 1138706f2543Smrg 1139706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rl); 1140706f2543Smrg DECODE_PRINTF(","); 1141706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1142706f2543Smrg DECODE_PRINTF(",CL\n"); 1143706f2543Smrg TRACE_AND_STEP(); 1144706f2543Smrg *destreg = shrd_word(*destreg,*shiftreg,M.x86.R_CL); 1145706f2543Smrg } 1146706f2543Smrg break; 1147706f2543Smrg } 1148706f2543Smrg DECODE_CLEAR_SEGOVR(); 1149706f2543Smrg END_OF_INSTR(); 1150706f2543Smrg} 1151706f2543Smrg 1152706f2543Smrg/**************************************************************************** 1153706f2543SmrgREMARKS: 1154706f2543SmrgHandles opcode 0x0f,0xaf 1155706f2543Smrg****************************************************************************/ 1156706f2543Smrgstatic void x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2)) 1157706f2543Smrg{ 1158706f2543Smrg int mod, rl, rh; 1159706f2543Smrg uint srcoffset; 1160706f2543Smrg 1161706f2543Smrg START_OF_INSTR(); 1162706f2543Smrg DECODE_PRINTF("IMUL\t"); 1163706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1164706f2543Smrg switch (mod) { 1165706f2543Smrg case 0: 1166706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1167706f2543Smrg u32 *destreg; 1168706f2543Smrg u32 srcval; 1169706f2543Smrg u32 res_lo,res_hi; 1170706f2543Smrg 1171706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1172706f2543Smrg DECODE_PRINTF(","); 1173706f2543Smrg srcoffset = decode_rm00_address(rl); 1174706f2543Smrg srcval = fetch_data_long(srcoffset); 1175706f2543Smrg TRACE_AND_STEP(); 1176706f2543Smrg imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); 1177706f2543Smrg if (res_hi != 0) { 1178706f2543Smrg SET_FLAG(F_CF); 1179706f2543Smrg SET_FLAG(F_OF); 1180706f2543Smrg } else { 1181706f2543Smrg CLEAR_FLAG(F_CF); 1182706f2543Smrg CLEAR_FLAG(F_OF); 1183706f2543Smrg } 1184706f2543Smrg *destreg = (u32)res_lo; 1185706f2543Smrg } else { 1186706f2543Smrg u16 *destreg; 1187706f2543Smrg u16 srcval; 1188706f2543Smrg u32 res; 1189706f2543Smrg 1190706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1191706f2543Smrg DECODE_PRINTF(","); 1192706f2543Smrg srcoffset = decode_rm00_address(rl); 1193706f2543Smrg srcval = fetch_data_word(srcoffset); 1194706f2543Smrg TRACE_AND_STEP(); 1195706f2543Smrg res = (s16)*destreg * (s16)srcval; 1196706f2543Smrg if (res > 0xFFFF) { 1197706f2543Smrg SET_FLAG(F_CF); 1198706f2543Smrg SET_FLAG(F_OF); 1199706f2543Smrg } else { 1200706f2543Smrg CLEAR_FLAG(F_CF); 1201706f2543Smrg CLEAR_FLAG(F_OF); 1202706f2543Smrg } 1203706f2543Smrg *destreg = (u16)res; 1204706f2543Smrg } 1205706f2543Smrg break; 1206706f2543Smrg case 1: 1207706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1208706f2543Smrg u32 *destreg; 1209706f2543Smrg u32 srcval; 1210706f2543Smrg u32 res_lo,res_hi; 1211706f2543Smrg 1212706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1213706f2543Smrg DECODE_PRINTF(","); 1214706f2543Smrg srcoffset = decode_rm01_address(rl); 1215706f2543Smrg srcval = fetch_data_long(srcoffset); 1216706f2543Smrg TRACE_AND_STEP(); 1217706f2543Smrg imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); 1218706f2543Smrg if (res_hi != 0) { 1219706f2543Smrg SET_FLAG(F_CF); 1220706f2543Smrg SET_FLAG(F_OF); 1221706f2543Smrg } else { 1222706f2543Smrg CLEAR_FLAG(F_CF); 1223706f2543Smrg CLEAR_FLAG(F_OF); 1224706f2543Smrg } 1225706f2543Smrg *destreg = (u32)res_lo; 1226706f2543Smrg } else { 1227706f2543Smrg u16 *destreg; 1228706f2543Smrg u16 srcval; 1229706f2543Smrg u32 res; 1230706f2543Smrg 1231706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1232706f2543Smrg DECODE_PRINTF(","); 1233706f2543Smrg srcoffset = decode_rm01_address(rl); 1234706f2543Smrg srcval = fetch_data_word(srcoffset); 1235706f2543Smrg TRACE_AND_STEP(); 1236706f2543Smrg res = (s16)*destreg * (s16)srcval; 1237706f2543Smrg if (res > 0xFFFF) { 1238706f2543Smrg SET_FLAG(F_CF); 1239706f2543Smrg SET_FLAG(F_OF); 1240706f2543Smrg } else { 1241706f2543Smrg CLEAR_FLAG(F_CF); 1242706f2543Smrg CLEAR_FLAG(F_OF); 1243706f2543Smrg } 1244706f2543Smrg *destreg = (u16)res; 1245706f2543Smrg } 1246706f2543Smrg break; 1247706f2543Smrg case 2: 1248706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1249706f2543Smrg u32 *destreg; 1250706f2543Smrg u32 srcval; 1251706f2543Smrg u32 res_lo,res_hi; 1252706f2543Smrg 1253706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1254706f2543Smrg DECODE_PRINTF(","); 1255706f2543Smrg srcoffset = decode_rm10_address(rl); 1256706f2543Smrg srcval = fetch_data_long(srcoffset); 1257706f2543Smrg TRACE_AND_STEP(); 1258706f2543Smrg imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)srcval); 1259706f2543Smrg if (res_hi != 0) { 1260706f2543Smrg SET_FLAG(F_CF); 1261706f2543Smrg SET_FLAG(F_OF); 1262706f2543Smrg } else { 1263706f2543Smrg CLEAR_FLAG(F_CF); 1264706f2543Smrg CLEAR_FLAG(F_OF); 1265706f2543Smrg } 1266706f2543Smrg *destreg = (u32)res_lo; 1267706f2543Smrg } else { 1268706f2543Smrg u16 *destreg; 1269706f2543Smrg u16 srcval; 1270706f2543Smrg u32 res; 1271706f2543Smrg 1272706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1273706f2543Smrg DECODE_PRINTF(","); 1274706f2543Smrg srcoffset = decode_rm10_address(rl); 1275706f2543Smrg srcval = fetch_data_word(srcoffset); 1276706f2543Smrg TRACE_AND_STEP(); 1277706f2543Smrg res = (s16)*destreg * (s16)srcval; 1278706f2543Smrg if (res > 0xFFFF) { 1279706f2543Smrg SET_FLAG(F_CF); 1280706f2543Smrg SET_FLAG(F_OF); 1281706f2543Smrg } else { 1282706f2543Smrg CLEAR_FLAG(F_CF); 1283706f2543Smrg CLEAR_FLAG(F_OF); 1284706f2543Smrg } 1285706f2543Smrg *destreg = (u16)res; 1286706f2543Smrg } 1287706f2543Smrg break; 1288706f2543Smrg case 3: /* register to register */ 1289706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1290706f2543Smrg u32 *destreg,*srcreg; 1291706f2543Smrg u32 res_lo,res_hi; 1292706f2543Smrg 1293706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1294706f2543Smrg DECODE_PRINTF(","); 1295706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 1296706f2543Smrg TRACE_AND_STEP(); 1297706f2543Smrg imul_long_direct(&res_lo,&res_hi,(s32)*destreg,(s32)*srcreg); 1298706f2543Smrg if (res_hi != 0) { 1299706f2543Smrg SET_FLAG(F_CF); 1300706f2543Smrg SET_FLAG(F_OF); 1301706f2543Smrg } else { 1302706f2543Smrg CLEAR_FLAG(F_CF); 1303706f2543Smrg CLEAR_FLAG(F_OF); 1304706f2543Smrg } 1305706f2543Smrg *destreg = (u32)res_lo; 1306706f2543Smrg } else { 1307706f2543Smrg u16 *destreg,*srcreg; 1308706f2543Smrg u32 res; 1309706f2543Smrg 1310706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1311706f2543Smrg DECODE_PRINTF(","); 1312706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 1313706f2543Smrg res = (s16)*destreg * (s16)*srcreg; 1314706f2543Smrg if (res > 0xFFFF) { 1315706f2543Smrg SET_FLAG(F_CF); 1316706f2543Smrg SET_FLAG(F_OF); 1317706f2543Smrg } else { 1318706f2543Smrg CLEAR_FLAG(F_CF); 1319706f2543Smrg CLEAR_FLAG(F_OF); 1320706f2543Smrg } 1321706f2543Smrg *destreg = (u16)res; 1322706f2543Smrg } 1323706f2543Smrg break; 1324706f2543Smrg } 1325706f2543Smrg DECODE_CLEAR_SEGOVR(); 1326706f2543Smrg END_OF_INSTR(); 1327706f2543Smrg} 1328706f2543Smrg 1329706f2543Smrg/**************************************************************************** 1330706f2543SmrgREMARKS: 1331706f2543SmrgHandles opcode 0x0f,0xb2 1332706f2543Smrg****************************************************************************/ 1333706f2543Smrgstatic void x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2)) 1334706f2543Smrg{ 1335706f2543Smrg int mod, rh, rl; 1336706f2543Smrg u16 *dstreg; 1337706f2543Smrg uint srcoffset; 1338706f2543Smrg 1339706f2543Smrg START_OF_INSTR(); 1340706f2543Smrg DECODE_PRINTF("LSS\t"); 1341706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1342706f2543Smrg switch (mod) { 1343706f2543Smrg case 0: 1344706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1345706f2543Smrg DECODE_PRINTF(","); 1346706f2543Smrg srcoffset = decode_rm00_address(rl); 1347706f2543Smrg DECODE_PRINTF("\n"); 1348706f2543Smrg TRACE_AND_STEP(); 1349706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1350706f2543Smrg M.x86.R_SS = fetch_data_word(srcoffset + 2); 1351706f2543Smrg break; 1352706f2543Smrg case 1: 1353706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1354706f2543Smrg DECODE_PRINTF(","); 1355706f2543Smrg srcoffset = decode_rm01_address(rl); 1356706f2543Smrg DECODE_PRINTF("\n"); 1357706f2543Smrg TRACE_AND_STEP(); 1358706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1359706f2543Smrg M.x86.R_SS = fetch_data_word(srcoffset + 2); 1360706f2543Smrg break; 1361706f2543Smrg case 2: 1362706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1363706f2543Smrg DECODE_PRINTF(","); 1364706f2543Smrg srcoffset = decode_rm10_address(rl); 1365706f2543Smrg DECODE_PRINTF("\n"); 1366706f2543Smrg TRACE_AND_STEP(); 1367706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1368706f2543Smrg M.x86.R_SS = fetch_data_word(srcoffset + 2); 1369706f2543Smrg break; 1370706f2543Smrg case 3: /* register to register */ 1371706f2543Smrg /* UNDEFINED! */ 1372706f2543Smrg TRACE_AND_STEP(); 1373706f2543Smrg } 1374706f2543Smrg DECODE_CLEAR_SEGOVR(); 1375706f2543Smrg END_OF_INSTR(); 1376706f2543Smrg} 1377706f2543Smrg 1378706f2543Smrg/**************************************************************************** 1379706f2543SmrgREMARKS: 1380706f2543SmrgHandles opcode 0x0f,0xb3 1381706f2543Smrg****************************************************************************/ 1382706f2543Smrgstatic void x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2)) 1383706f2543Smrg{ 1384706f2543Smrg int mod, rl, rh; 1385706f2543Smrg uint srcoffset; 1386706f2543Smrg int bit,disp; 1387706f2543Smrg 1388706f2543Smrg START_OF_INSTR(); 1389706f2543Smrg DECODE_PRINTF("BTR\t"); 1390706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1391706f2543Smrg switch (mod) { 1392706f2543Smrg case 0: 1393706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1394706f2543Smrg u32 srcval,mask; 1395706f2543Smrg u32 *shiftreg; 1396706f2543Smrg 1397706f2543Smrg srcoffset = decode_rm00_address(rl); 1398706f2543Smrg DECODE_PRINTF(","); 1399706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1400706f2543Smrg TRACE_AND_STEP(); 1401706f2543Smrg bit = *shiftreg & 0x1F; 1402706f2543Smrg disp = (s16)*shiftreg >> 5; 1403706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 1404706f2543Smrg mask = (0x1 << bit); 1405706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1406706f2543Smrg store_data_long(srcoffset+disp, srcval & ~mask); 1407706f2543Smrg } else { 1408706f2543Smrg u16 srcval,mask; 1409706f2543Smrg u16 *shiftreg; 1410706f2543Smrg 1411706f2543Smrg srcoffset = decode_rm00_address(rl); 1412706f2543Smrg DECODE_PRINTF(","); 1413706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1414706f2543Smrg TRACE_AND_STEP(); 1415706f2543Smrg bit = *shiftreg & 0xF; 1416706f2543Smrg disp = (s16)*shiftreg >> 4; 1417706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 1418706f2543Smrg mask = (u16)(0x1 << bit); 1419706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1420706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); 1421706f2543Smrg } 1422706f2543Smrg break; 1423706f2543Smrg case 1: 1424706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1425706f2543Smrg u32 srcval,mask; 1426706f2543Smrg u32 *shiftreg; 1427706f2543Smrg 1428706f2543Smrg srcoffset = decode_rm01_address(rl); 1429706f2543Smrg DECODE_PRINTF(","); 1430706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1431706f2543Smrg TRACE_AND_STEP(); 1432706f2543Smrg bit = *shiftreg & 0x1F; 1433706f2543Smrg disp = (s16)*shiftreg >> 5; 1434706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 1435706f2543Smrg mask = (0x1 << bit); 1436706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1437706f2543Smrg store_data_long(srcoffset+disp, srcval & ~mask); 1438706f2543Smrg } else { 1439706f2543Smrg u16 srcval,mask; 1440706f2543Smrg u16 *shiftreg; 1441706f2543Smrg 1442706f2543Smrg srcoffset = decode_rm01_address(rl); 1443706f2543Smrg DECODE_PRINTF(","); 1444706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1445706f2543Smrg TRACE_AND_STEP(); 1446706f2543Smrg bit = *shiftreg & 0xF; 1447706f2543Smrg disp = (s16)*shiftreg >> 4; 1448706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 1449706f2543Smrg mask = (u16)(0x1 << bit); 1450706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1451706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); 1452706f2543Smrg } 1453706f2543Smrg break; 1454706f2543Smrg case 2: 1455706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1456706f2543Smrg u32 srcval,mask; 1457706f2543Smrg u32 *shiftreg; 1458706f2543Smrg 1459706f2543Smrg srcoffset = decode_rm10_address(rl); 1460706f2543Smrg DECODE_PRINTF(","); 1461706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1462706f2543Smrg TRACE_AND_STEP(); 1463706f2543Smrg bit = *shiftreg & 0x1F; 1464706f2543Smrg disp = (s16)*shiftreg >> 5; 1465706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 1466706f2543Smrg mask = (0x1 << bit); 1467706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1468706f2543Smrg store_data_long(srcoffset+disp, srcval & ~mask); 1469706f2543Smrg } else { 1470706f2543Smrg u16 srcval,mask; 1471706f2543Smrg u16 *shiftreg; 1472706f2543Smrg 1473706f2543Smrg srcoffset = decode_rm10_address(rl); 1474706f2543Smrg DECODE_PRINTF(","); 1475706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1476706f2543Smrg TRACE_AND_STEP(); 1477706f2543Smrg bit = *shiftreg & 0xF; 1478706f2543Smrg disp = (s16)*shiftreg >> 4; 1479706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 1480706f2543Smrg mask = (u16)(0x1 << bit); 1481706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1482706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval & ~mask)); 1483706f2543Smrg } 1484706f2543Smrg break; 1485706f2543Smrg case 3: /* register to register */ 1486706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1487706f2543Smrg u32 *srcreg,*shiftreg; 1488706f2543Smrg u32 mask; 1489706f2543Smrg 1490706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 1491706f2543Smrg DECODE_PRINTF(","); 1492706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 1493706f2543Smrg TRACE_AND_STEP(); 1494706f2543Smrg bit = *shiftreg & 0x1F; 1495706f2543Smrg mask = (0x1 << bit); 1496706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 1497706f2543Smrg *srcreg &= ~mask; 1498706f2543Smrg } else { 1499706f2543Smrg u16 *srcreg,*shiftreg; 1500706f2543Smrg u16 mask; 1501706f2543Smrg 1502706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 1503706f2543Smrg DECODE_PRINTF(","); 1504706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 1505706f2543Smrg TRACE_AND_STEP(); 1506706f2543Smrg bit = *shiftreg & 0xF; 1507706f2543Smrg mask = (u16)(0x1 << bit); 1508706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 1509706f2543Smrg *srcreg &= ~mask; 1510706f2543Smrg } 1511706f2543Smrg break; 1512706f2543Smrg } 1513706f2543Smrg DECODE_CLEAR_SEGOVR(); 1514706f2543Smrg END_OF_INSTR(); 1515706f2543Smrg} 1516706f2543Smrg 1517706f2543Smrg/**************************************************************************** 1518706f2543SmrgREMARKS: 1519706f2543SmrgHandles opcode 0x0f,0xb4 1520706f2543Smrg****************************************************************************/ 1521706f2543Smrgstatic void x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2)) 1522706f2543Smrg{ 1523706f2543Smrg int mod, rh, rl; 1524706f2543Smrg u16 *dstreg; 1525706f2543Smrg uint srcoffset; 1526706f2543Smrg 1527706f2543Smrg START_OF_INSTR(); 1528706f2543Smrg DECODE_PRINTF("LFS\t"); 1529706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1530706f2543Smrg switch (mod) { 1531706f2543Smrg case 0: 1532706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1533706f2543Smrg DECODE_PRINTF(","); 1534706f2543Smrg srcoffset = decode_rm00_address(rl); 1535706f2543Smrg DECODE_PRINTF("\n"); 1536706f2543Smrg TRACE_AND_STEP(); 1537706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1538706f2543Smrg M.x86.R_FS = fetch_data_word(srcoffset + 2); 1539706f2543Smrg break; 1540706f2543Smrg case 1: 1541706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1542706f2543Smrg DECODE_PRINTF(","); 1543706f2543Smrg srcoffset = decode_rm01_address(rl); 1544706f2543Smrg DECODE_PRINTF("\n"); 1545706f2543Smrg TRACE_AND_STEP(); 1546706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1547706f2543Smrg M.x86.R_FS = fetch_data_word(srcoffset + 2); 1548706f2543Smrg break; 1549706f2543Smrg case 2: 1550706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1551706f2543Smrg DECODE_PRINTF(","); 1552706f2543Smrg srcoffset = decode_rm10_address(rl); 1553706f2543Smrg DECODE_PRINTF("\n"); 1554706f2543Smrg TRACE_AND_STEP(); 1555706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1556706f2543Smrg M.x86.R_FS = fetch_data_word(srcoffset + 2); 1557706f2543Smrg break; 1558706f2543Smrg case 3: /* register to register */ 1559706f2543Smrg /* UNDEFINED! */ 1560706f2543Smrg TRACE_AND_STEP(); 1561706f2543Smrg } 1562706f2543Smrg DECODE_CLEAR_SEGOVR(); 1563706f2543Smrg END_OF_INSTR(); 1564706f2543Smrg} 1565706f2543Smrg 1566706f2543Smrg/**************************************************************************** 1567706f2543SmrgREMARKS: 1568706f2543SmrgHandles opcode 0x0f,0xb5 1569706f2543Smrg****************************************************************************/ 1570706f2543Smrgstatic void x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2)) 1571706f2543Smrg{ 1572706f2543Smrg int mod, rh, rl; 1573706f2543Smrg u16 *dstreg; 1574706f2543Smrg uint srcoffset; 1575706f2543Smrg 1576706f2543Smrg START_OF_INSTR(); 1577706f2543Smrg DECODE_PRINTF("LGS\t"); 1578706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1579706f2543Smrg switch (mod) { 1580706f2543Smrg case 0: 1581706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1582706f2543Smrg DECODE_PRINTF(","); 1583706f2543Smrg srcoffset = decode_rm00_address(rl); 1584706f2543Smrg DECODE_PRINTF("\n"); 1585706f2543Smrg TRACE_AND_STEP(); 1586706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1587706f2543Smrg M.x86.R_GS = fetch_data_word(srcoffset + 2); 1588706f2543Smrg break; 1589706f2543Smrg case 1: 1590706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1591706f2543Smrg DECODE_PRINTF(","); 1592706f2543Smrg srcoffset = decode_rm01_address(rl); 1593706f2543Smrg DECODE_PRINTF("\n"); 1594706f2543Smrg TRACE_AND_STEP(); 1595706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1596706f2543Smrg M.x86.R_GS = fetch_data_word(srcoffset + 2); 1597706f2543Smrg break; 1598706f2543Smrg case 2: 1599706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 1600706f2543Smrg DECODE_PRINTF(","); 1601706f2543Smrg srcoffset = decode_rm10_address(rl); 1602706f2543Smrg DECODE_PRINTF("\n"); 1603706f2543Smrg TRACE_AND_STEP(); 1604706f2543Smrg *dstreg = fetch_data_word(srcoffset); 1605706f2543Smrg M.x86.R_GS = fetch_data_word(srcoffset + 2); 1606706f2543Smrg break; 1607706f2543Smrg case 3: /* register to register */ 1608706f2543Smrg /* UNDEFINED! */ 1609706f2543Smrg TRACE_AND_STEP(); 1610706f2543Smrg } 1611706f2543Smrg DECODE_CLEAR_SEGOVR(); 1612706f2543Smrg END_OF_INSTR(); 1613706f2543Smrg} 1614706f2543Smrg 1615706f2543Smrg/**************************************************************************** 1616706f2543SmrgREMARKS: 1617706f2543SmrgHandles opcode 0x0f,0xb6 1618706f2543Smrg****************************************************************************/ 1619706f2543Smrgstatic void x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2)) 1620706f2543Smrg{ 1621706f2543Smrg int mod, rl, rh; 1622706f2543Smrg uint srcoffset; 1623706f2543Smrg 1624706f2543Smrg START_OF_INSTR(); 1625706f2543Smrg DECODE_PRINTF("MOVZX\t"); 1626706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1627706f2543Smrg switch (mod) { 1628706f2543Smrg case 0: 1629706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1630706f2543Smrg u32 *destreg; 1631706f2543Smrg u32 srcval; 1632706f2543Smrg 1633706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1634706f2543Smrg DECODE_PRINTF(","); 1635706f2543Smrg srcoffset = decode_rm00_address(rl); 1636706f2543Smrg srcval = fetch_data_byte(srcoffset); 1637706f2543Smrg DECODE_PRINTF("\n"); 1638706f2543Smrg TRACE_AND_STEP(); 1639706f2543Smrg *destreg = srcval; 1640706f2543Smrg } else { 1641706f2543Smrg u16 *destreg; 1642706f2543Smrg u16 srcval; 1643706f2543Smrg 1644706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1645706f2543Smrg DECODE_PRINTF(","); 1646706f2543Smrg srcoffset = decode_rm00_address(rl); 1647706f2543Smrg srcval = fetch_data_byte(srcoffset); 1648706f2543Smrg DECODE_PRINTF("\n"); 1649706f2543Smrg TRACE_AND_STEP(); 1650706f2543Smrg *destreg = srcval; 1651706f2543Smrg } 1652706f2543Smrg break; 1653706f2543Smrg case 1: 1654706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1655706f2543Smrg u32 *destreg; 1656706f2543Smrg u32 srcval; 1657706f2543Smrg 1658706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1659706f2543Smrg DECODE_PRINTF(","); 1660706f2543Smrg srcoffset = decode_rm01_address(rl); 1661706f2543Smrg srcval = fetch_data_byte(srcoffset); 1662706f2543Smrg DECODE_PRINTF("\n"); 1663706f2543Smrg TRACE_AND_STEP(); 1664706f2543Smrg *destreg = srcval; 1665706f2543Smrg } else { 1666706f2543Smrg u16 *destreg; 1667706f2543Smrg u16 srcval; 1668706f2543Smrg 1669706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1670706f2543Smrg DECODE_PRINTF(","); 1671706f2543Smrg srcoffset = decode_rm01_address(rl); 1672706f2543Smrg srcval = fetch_data_byte(srcoffset); 1673706f2543Smrg DECODE_PRINTF("\n"); 1674706f2543Smrg TRACE_AND_STEP(); 1675706f2543Smrg *destreg = srcval; 1676706f2543Smrg } 1677706f2543Smrg break; 1678706f2543Smrg case 2: 1679706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1680706f2543Smrg u32 *destreg; 1681706f2543Smrg u32 srcval; 1682706f2543Smrg 1683706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1684706f2543Smrg DECODE_PRINTF(","); 1685706f2543Smrg srcoffset = decode_rm10_address(rl); 1686706f2543Smrg srcval = fetch_data_byte(srcoffset); 1687706f2543Smrg DECODE_PRINTF("\n"); 1688706f2543Smrg TRACE_AND_STEP(); 1689706f2543Smrg *destreg = srcval; 1690706f2543Smrg } else { 1691706f2543Smrg u16 *destreg; 1692706f2543Smrg u16 srcval; 1693706f2543Smrg 1694706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1695706f2543Smrg DECODE_PRINTF(","); 1696706f2543Smrg srcoffset = decode_rm10_address(rl); 1697706f2543Smrg srcval = fetch_data_byte(srcoffset); 1698706f2543Smrg DECODE_PRINTF("\n"); 1699706f2543Smrg TRACE_AND_STEP(); 1700706f2543Smrg *destreg = srcval; 1701706f2543Smrg } 1702706f2543Smrg break; 1703706f2543Smrg case 3: /* register to register */ 1704706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1705706f2543Smrg u32 *destreg; 1706706f2543Smrg u8 *srcreg; 1707706f2543Smrg 1708706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1709706f2543Smrg DECODE_PRINTF(","); 1710706f2543Smrg srcreg = DECODE_RM_BYTE_REGISTER(rl); 1711706f2543Smrg DECODE_PRINTF("\n"); 1712706f2543Smrg TRACE_AND_STEP(); 1713706f2543Smrg *destreg = *srcreg; 1714706f2543Smrg } else { 1715706f2543Smrg u16 *destreg; 1716706f2543Smrg u8 *srcreg; 1717706f2543Smrg 1718706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 1719706f2543Smrg DECODE_PRINTF(","); 1720706f2543Smrg srcreg = DECODE_RM_BYTE_REGISTER(rl); 1721706f2543Smrg DECODE_PRINTF("\n"); 1722706f2543Smrg TRACE_AND_STEP(); 1723706f2543Smrg *destreg = *srcreg; 1724706f2543Smrg } 1725706f2543Smrg break; 1726706f2543Smrg } 1727706f2543Smrg DECODE_CLEAR_SEGOVR(); 1728706f2543Smrg END_OF_INSTR(); 1729706f2543Smrg} 1730706f2543Smrg 1731706f2543Smrg/**************************************************************************** 1732706f2543SmrgREMARKS: 1733706f2543SmrgHandles opcode 0x0f,0xb7 1734706f2543Smrg****************************************************************************/ 1735706f2543Smrgstatic void x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2)) 1736706f2543Smrg{ 1737706f2543Smrg int mod, rl, rh; 1738706f2543Smrg uint srcoffset; 1739706f2543Smrg u32 *destreg; 1740706f2543Smrg u32 srcval; 1741706f2543Smrg u16 *srcreg; 1742706f2543Smrg 1743706f2543Smrg START_OF_INSTR(); 1744706f2543Smrg DECODE_PRINTF("MOVZX\t"); 1745706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1746706f2543Smrg switch (mod) { 1747706f2543Smrg case 0: 1748706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1749706f2543Smrg DECODE_PRINTF(","); 1750706f2543Smrg srcoffset = decode_rm00_address(rl); 1751706f2543Smrg srcval = fetch_data_word(srcoffset); 1752706f2543Smrg DECODE_PRINTF("\n"); 1753706f2543Smrg TRACE_AND_STEP(); 1754706f2543Smrg *destreg = srcval; 1755706f2543Smrg break; 1756706f2543Smrg case 1: 1757706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1758706f2543Smrg DECODE_PRINTF(","); 1759706f2543Smrg srcoffset = decode_rm01_address(rl); 1760706f2543Smrg srcval = fetch_data_word(srcoffset); 1761706f2543Smrg DECODE_PRINTF("\n"); 1762706f2543Smrg TRACE_AND_STEP(); 1763706f2543Smrg *destreg = srcval; 1764706f2543Smrg break; 1765706f2543Smrg case 2: 1766706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1767706f2543Smrg DECODE_PRINTF(","); 1768706f2543Smrg srcoffset = decode_rm10_address(rl); 1769706f2543Smrg srcval = fetch_data_word(srcoffset); 1770706f2543Smrg DECODE_PRINTF("\n"); 1771706f2543Smrg TRACE_AND_STEP(); 1772706f2543Smrg *destreg = srcval; 1773706f2543Smrg break; 1774706f2543Smrg case 3: /* register to register */ 1775706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 1776706f2543Smrg DECODE_PRINTF(","); 1777706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 1778706f2543Smrg DECODE_PRINTF("\n"); 1779706f2543Smrg TRACE_AND_STEP(); 1780706f2543Smrg *destreg = *srcreg; 1781706f2543Smrg break; 1782706f2543Smrg } 1783706f2543Smrg DECODE_CLEAR_SEGOVR(); 1784706f2543Smrg END_OF_INSTR(); 1785706f2543Smrg} 1786706f2543Smrg 1787706f2543Smrg/**************************************************************************** 1788706f2543SmrgREMARKS: 1789706f2543SmrgHandles opcode 0x0f,0xba 1790706f2543Smrg****************************************************************************/ 1791706f2543Smrgstatic void x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2)) 1792706f2543Smrg{ 1793706f2543Smrg int mod, rl, rh; 1794706f2543Smrg uint srcoffset; 1795706f2543Smrg int bit; 1796706f2543Smrg 1797706f2543Smrg START_OF_INSTR(); 1798706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 1799706f2543Smrg switch (rh) { 1800706f2543Smrg case 4: 1801706f2543Smrg DECODE_PRINTF("BT\t"); 1802706f2543Smrg break; 1803706f2543Smrg case 5: 1804706f2543Smrg DECODE_PRINTF("BTS\t"); 1805706f2543Smrg break; 1806706f2543Smrg case 6: 1807706f2543Smrg DECODE_PRINTF("BTR\t"); 1808706f2543Smrg break; 1809706f2543Smrg case 7: 1810706f2543Smrg DECODE_PRINTF("BTC\t"); 1811706f2543Smrg break; 1812706f2543Smrg default: 1813706f2543Smrg DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); 1814706f2543Smrg TRACE_REGS(); 1815706f2543Smrg printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n", 1816706f2543Smrg M.x86.R_CS, M.x86.R_IP-3,op2, (mod<<6)|(rh<<3)|rl); 1817706f2543Smrg HALT_SYS(); 1818706f2543Smrg } 1819706f2543Smrg switch (mod) { 1820706f2543Smrg case 0: 1821706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1822706f2543Smrg u32 srcval, mask; 1823706f2543Smrg u8 shift; 1824706f2543Smrg 1825706f2543Smrg srcoffset = decode_rm00_address(rl); 1826706f2543Smrg DECODE_PRINTF(","); 1827706f2543Smrg shift = fetch_byte_imm(); 1828706f2543Smrg TRACE_AND_STEP(); 1829706f2543Smrg bit = shift & 0x1F; 1830706f2543Smrg srcval = fetch_data_long(srcoffset); 1831706f2543Smrg mask = (0x1 << bit); 1832706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1833706f2543Smrg switch (rh) { 1834706f2543Smrg case 5: 1835706f2543Smrg store_data_long(srcoffset, srcval | mask); 1836706f2543Smrg break; 1837706f2543Smrg case 6: 1838706f2543Smrg store_data_long(srcoffset, srcval & ~mask); 1839706f2543Smrg break; 1840706f2543Smrg case 7: 1841706f2543Smrg store_data_long(srcoffset, srcval ^ mask); 1842706f2543Smrg break; 1843706f2543Smrg default: 1844706f2543Smrg break; 1845706f2543Smrg } 1846706f2543Smrg } else { 1847706f2543Smrg u16 srcval, mask; 1848706f2543Smrg u8 shift; 1849706f2543Smrg 1850706f2543Smrg srcoffset = decode_rm00_address(rl); 1851706f2543Smrg DECODE_PRINTF(","); 1852706f2543Smrg shift = fetch_byte_imm(); 1853706f2543Smrg TRACE_AND_STEP(); 1854706f2543Smrg bit = shift & 0xF; 1855706f2543Smrg srcval = fetch_data_word(srcoffset); 1856706f2543Smrg mask = (0x1 << bit); 1857706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1858706f2543Smrg switch (rh) { 1859706f2543Smrg case 5: 1860706f2543Smrg store_data_word(srcoffset, srcval | mask); 1861706f2543Smrg break; 1862706f2543Smrg case 6: 1863706f2543Smrg store_data_word(srcoffset, srcval & ~mask); 1864706f2543Smrg break; 1865706f2543Smrg case 7: 1866706f2543Smrg store_data_word(srcoffset, srcval ^ mask); 1867706f2543Smrg break; 1868706f2543Smrg default: 1869706f2543Smrg break; 1870706f2543Smrg } 1871706f2543Smrg } 1872706f2543Smrg break; 1873706f2543Smrg case 1: 1874706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1875706f2543Smrg u32 srcval, mask; 1876706f2543Smrg u8 shift; 1877706f2543Smrg 1878706f2543Smrg srcoffset = decode_rm01_address(rl); 1879706f2543Smrg DECODE_PRINTF(","); 1880706f2543Smrg shift = fetch_byte_imm(); 1881706f2543Smrg TRACE_AND_STEP(); 1882706f2543Smrg bit = shift & 0x1F; 1883706f2543Smrg srcval = fetch_data_long(srcoffset); 1884706f2543Smrg mask = (0x1 << bit); 1885706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1886706f2543Smrg switch (rh) { 1887706f2543Smrg case 5: 1888706f2543Smrg store_data_long(srcoffset, srcval | mask); 1889706f2543Smrg break; 1890706f2543Smrg case 6: 1891706f2543Smrg store_data_long(srcoffset, srcval & ~mask); 1892706f2543Smrg break; 1893706f2543Smrg case 7: 1894706f2543Smrg store_data_long(srcoffset, srcval ^ mask); 1895706f2543Smrg break; 1896706f2543Smrg default: 1897706f2543Smrg break; 1898706f2543Smrg } 1899706f2543Smrg } else { 1900706f2543Smrg u16 srcval, mask; 1901706f2543Smrg u8 shift; 1902706f2543Smrg 1903706f2543Smrg srcoffset = decode_rm01_address(rl); 1904706f2543Smrg DECODE_PRINTF(","); 1905706f2543Smrg shift = fetch_byte_imm(); 1906706f2543Smrg TRACE_AND_STEP(); 1907706f2543Smrg bit = shift & 0xF; 1908706f2543Smrg srcval = fetch_data_word(srcoffset); 1909706f2543Smrg mask = (0x1 << bit); 1910706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1911706f2543Smrg switch (rh) { 1912706f2543Smrg case 5: 1913706f2543Smrg store_data_word(srcoffset, srcval | mask); 1914706f2543Smrg break; 1915706f2543Smrg case 6: 1916706f2543Smrg store_data_word(srcoffset, srcval & ~mask); 1917706f2543Smrg break; 1918706f2543Smrg case 7: 1919706f2543Smrg store_data_word(srcoffset, srcval ^ mask); 1920706f2543Smrg break; 1921706f2543Smrg default: 1922706f2543Smrg break; 1923706f2543Smrg } 1924706f2543Smrg } 1925706f2543Smrg break; 1926706f2543Smrg case 2: 1927706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1928706f2543Smrg u32 srcval, mask; 1929706f2543Smrg u8 shift; 1930706f2543Smrg 1931706f2543Smrg srcoffset = decode_rm10_address(rl); 1932706f2543Smrg DECODE_PRINTF(","); 1933706f2543Smrg shift = fetch_byte_imm(); 1934706f2543Smrg TRACE_AND_STEP(); 1935706f2543Smrg bit = shift & 0x1F; 1936706f2543Smrg srcval = fetch_data_long(srcoffset); 1937706f2543Smrg mask = (0x1 << bit); 1938706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1939706f2543Smrg switch (rh) { 1940706f2543Smrg case 5: 1941706f2543Smrg store_data_long(srcoffset, srcval | mask); 1942706f2543Smrg break; 1943706f2543Smrg case 6: 1944706f2543Smrg store_data_long(srcoffset, srcval & ~mask); 1945706f2543Smrg break; 1946706f2543Smrg case 7: 1947706f2543Smrg store_data_long(srcoffset, srcval ^ mask); 1948706f2543Smrg break; 1949706f2543Smrg default: 1950706f2543Smrg break; 1951706f2543Smrg } 1952706f2543Smrg } else { 1953706f2543Smrg u16 srcval, mask; 1954706f2543Smrg u8 shift; 1955706f2543Smrg 1956706f2543Smrg srcoffset = decode_rm10_address(rl); 1957706f2543Smrg DECODE_PRINTF(","); 1958706f2543Smrg shift = fetch_byte_imm(); 1959706f2543Smrg TRACE_AND_STEP(); 1960706f2543Smrg bit = shift & 0xF; 1961706f2543Smrg srcval = fetch_data_word(srcoffset); 1962706f2543Smrg mask = (0x1 << bit); 1963706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 1964706f2543Smrg switch (rh) { 1965706f2543Smrg case 5: 1966706f2543Smrg store_data_word(srcoffset, srcval | mask); 1967706f2543Smrg break; 1968706f2543Smrg case 6: 1969706f2543Smrg store_data_word(srcoffset, srcval & ~mask); 1970706f2543Smrg break; 1971706f2543Smrg case 7: 1972706f2543Smrg store_data_word(srcoffset, srcval ^ mask); 1973706f2543Smrg break; 1974706f2543Smrg default: 1975706f2543Smrg break; 1976706f2543Smrg } 1977706f2543Smrg } 1978706f2543Smrg break; 1979706f2543Smrg case 3: /* register to register */ 1980706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 1981706f2543Smrg u32 *srcreg; 1982706f2543Smrg u32 mask; 1983706f2543Smrg u8 shift; 1984706f2543Smrg 1985706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 1986706f2543Smrg DECODE_PRINTF(","); 1987706f2543Smrg shift = fetch_byte_imm(); 1988706f2543Smrg TRACE_AND_STEP(); 1989706f2543Smrg bit = shift & 0x1F; 1990706f2543Smrg mask = (0x1 << bit); 1991706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 1992706f2543Smrg switch (rh) { 1993706f2543Smrg case 5: 1994706f2543Smrg *srcreg |= mask; 1995706f2543Smrg break; 1996706f2543Smrg case 6: 1997706f2543Smrg *srcreg &= ~mask; 1998706f2543Smrg break; 1999706f2543Smrg case 7: 2000706f2543Smrg *srcreg ^= mask; 2001706f2543Smrg break; 2002706f2543Smrg default: 2003706f2543Smrg break; 2004706f2543Smrg } 2005706f2543Smrg } else { 2006706f2543Smrg u16 *srcreg; 2007706f2543Smrg u16 mask; 2008706f2543Smrg u8 shift; 2009706f2543Smrg 2010706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 2011706f2543Smrg DECODE_PRINTF(","); 2012706f2543Smrg shift = fetch_byte_imm(); 2013706f2543Smrg TRACE_AND_STEP(); 2014706f2543Smrg bit = shift & 0xF; 2015706f2543Smrg mask = (0x1 << bit); 2016706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 2017706f2543Smrg switch (rh) { 2018706f2543Smrg case 5: 2019706f2543Smrg *srcreg |= mask; 2020706f2543Smrg break; 2021706f2543Smrg case 6: 2022706f2543Smrg *srcreg &= ~mask; 2023706f2543Smrg break; 2024706f2543Smrg case 7: 2025706f2543Smrg *srcreg ^= mask; 2026706f2543Smrg break; 2027706f2543Smrg default: 2028706f2543Smrg break; 2029706f2543Smrg } 2030706f2543Smrg } 2031706f2543Smrg break; 2032706f2543Smrg } 2033706f2543Smrg DECODE_CLEAR_SEGOVR(); 2034706f2543Smrg END_OF_INSTR(); 2035706f2543Smrg} 2036706f2543Smrg 2037706f2543Smrg/**************************************************************************** 2038706f2543SmrgREMARKS: 2039706f2543SmrgHandles opcode 0x0f,0xbb 2040706f2543Smrg****************************************************************************/ 2041706f2543Smrgstatic void x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2)) 2042706f2543Smrg{ 2043706f2543Smrg int mod, rl, rh; 2044706f2543Smrg uint srcoffset; 2045706f2543Smrg int bit,disp; 2046706f2543Smrg 2047706f2543Smrg START_OF_INSTR(); 2048706f2543Smrg DECODE_PRINTF("BTC\t"); 2049706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 2050706f2543Smrg switch (mod) { 2051706f2543Smrg case 0: 2052706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2053706f2543Smrg u32 srcval,mask; 2054706f2543Smrg u32 *shiftreg; 2055706f2543Smrg 2056706f2543Smrg srcoffset = decode_rm00_address(rl); 2057706f2543Smrg DECODE_PRINTF(","); 2058706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 2059706f2543Smrg TRACE_AND_STEP(); 2060706f2543Smrg bit = *shiftreg & 0x1F; 2061706f2543Smrg disp = (s16)*shiftreg >> 5; 2062706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 2063706f2543Smrg mask = (0x1 << bit); 2064706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2065706f2543Smrg store_data_long(srcoffset+disp, srcval ^ mask); 2066706f2543Smrg } else { 2067706f2543Smrg u16 srcval,mask; 2068706f2543Smrg u16 *shiftreg; 2069706f2543Smrg 2070706f2543Smrg srcoffset = decode_rm00_address(rl); 2071706f2543Smrg DECODE_PRINTF(","); 2072706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 2073706f2543Smrg TRACE_AND_STEP(); 2074706f2543Smrg bit = *shiftreg & 0xF; 2075706f2543Smrg disp = (s16)*shiftreg >> 4; 2076706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 2077706f2543Smrg mask = (u16)(0x1 << bit); 2078706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2079706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); 2080706f2543Smrg } 2081706f2543Smrg break; 2082706f2543Smrg case 1: 2083706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2084706f2543Smrg u32 srcval,mask; 2085706f2543Smrg u32 *shiftreg; 2086706f2543Smrg 2087706f2543Smrg srcoffset = decode_rm01_address(rl); 2088706f2543Smrg DECODE_PRINTF(","); 2089706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 2090706f2543Smrg TRACE_AND_STEP(); 2091706f2543Smrg bit = *shiftreg & 0x1F; 2092706f2543Smrg disp = (s16)*shiftreg >> 5; 2093706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 2094706f2543Smrg mask = (0x1 << bit); 2095706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2096706f2543Smrg store_data_long(srcoffset+disp, srcval ^ mask); 2097706f2543Smrg } else { 2098706f2543Smrg u16 srcval,mask; 2099706f2543Smrg u16 *shiftreg; 2100706f2543Smrg 2101706f2543Smrg srcoffset = decode_rm01_address(rl); 2102706f2543Smrg DECODE_PRINTF(","); 2103706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 2104706f2543Smrg TRACE_AND_STEP(); 2105706f2543Smrg bit = *shiftreg & 0xF; 2106706f2543Smrg disp = (s16)*shiftreg >> 4; 2107706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 2108706f2543Smrg mask = (u16)(0x1 << bit); 2109706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2110706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); 2111706f2543Smrg } 2112706f2543Smrg break; 2113706f2543Smrg case 2: 2114706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2115706f2543Smrg u32 srcval,mask; 2116706f2543Smrg u32 *shiftreg; 2117706f2543Smrg 2118706f2543Smrg srcoffset = decode_rm10_address(rl); 2119706f2543Smrg DECODE_PRINTF(","); 2120706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 2121706f2543Smrg TRACE_AND_STEP(); 2122706f2543Smrg bit = *shiftreg & 0x1F; 2123706f2543Smrg disp = (s16)*shiftreg >> 5; 2124706f2543Smrg srcval = fetch_data_long(srcoffset+disp); 2125706f2543Smrg mask = (0x1 << bit); 2126706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2127706f2543Smrg store_data_long(srcoffset+disp, srcval ^ mask); 2128706f2543Smrg } else { 2129706f2543Smrg u16 srcval,mask; 2130706f2543Smrg u16 *shiftreg; 2131706f2543Smrg 2132706f2543Smrg srcoffset = decode_rm10_address(rl); 2133706f2543Smrg DECODE_PRINTF(","); 2134706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 2135706f2543Smrg TRACE_AND_STEP(); 2136706f2543Smrg bit = *shiftreg & 0xF; 2137706f2543Smrg disp = (s16)*shiftreg >> 4; 2138706f2543Smrg srcval = fetch_data_word(srcoffset+disp); 2139706f2543Smrg mask = (u16)(0x1 << bit); 2140706f2543Smrg CONDITIONAL_SET_FLAG(srcval & mask,F_CF); 2141706f2543Smrg store_data_word(srcoffset+disp, (u16)(srcval ^ mask)); 2142706f2543Smrg } 2143706f2543Smrg break; 2144706f2543Smrg case 3: /* register to register */ 2145706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2146706f2543Smrg u32 *srcreg,*shiftreg; 2147706f2543Smrg u32 mask; 2148706f2543Smrg 2149706f2543Smrg srcreg = DECODE_RM_LONG_REGISTER(rl); 2150706f2543Smrg DECODE_PRINTF(","); 2151706f2543Smrg shiftreg = DECODE_RM_LONG_REGISTER(rh); 2152706f2543Smrg TRACE_AND_STEP(); 2153706f2543Smrg bit = *shiftreg & 0x1F; 2154706f2543Smrg mask = (0x1 << bit); 2155706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 2156706f2543Smrg *srcreg ^= mask; 2157706f2543Smrg } else { 2158706f2543Smrg u16 *srcreg,*shiftreg; 2159706f2543Smrg u16 mask; 2160706f2543Smrg 2161706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 2162706f2543Smrg DECODE_PRINTF(","); 2163706f2543Smrg shiftreg = DECODE_RM_WORD_REGISTER(rh); 2164706f2543Smrg TRACE_AND_STEP(); 2165706f2543Smrg bit = *shiftreg & 0xF; 2166706f2543Smrg mask = (u16)(0x1 << bit); 2167706f2543Smrg CONDITIONAL_SET_FLAG(*srcreg & mask,F_CF); 2168706f2543Smrg *srcreg ^= mask; 2169706f2543Smrg } 2170706f2543Smrg break; 2171706f2543Smrg } 2172706f2543Smrg DECODE_CLEAR_SEGOVR(); 2173706f2543Smrg END_OF_INSTR(); 2174706f2543Smrg} 2175706f2543Smrg 2176706f2543Smrg/**************************************************************************** 2177706f2543SmrgREMARKS: 2178706f2543SmrgHandles opcode 0x0f,0xbc 2179706f2543Smrg****************************************************************************/ 2180706f2543Smrgstatic void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2)) 2181706f2543Smrg{ 2182706f2543Smrg int mod, rl, rh; 2183706f2543Smrg uint srcoffset; 2184706f2543Smrg 2185706f2543Smrg START_OF_INSTR(); 2186706f2543Smrg DECODE_PRINTF("BSF\t"); 2187706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 2188706f2543Smrg switch(mod) { 2189706f2543Smrg case 0: 2190706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2191706f2543Smrg u32 srcval, *dstreg; 2192706f2543Smrg 2193706f2543Smrg srcoffset = decode_rm00_address(rl); 2194706f2543Smrg DECODE_PRINTF(","); 2195706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2196706f2543Smrg TRACE_AND_STEP(); 2197706f2543Smrg srcval = fetch_data_long(srcoffset); 2198706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2199706f2543Smrg for(*dstreg = 0; *dstreg < 32; (*dstreg)++) 2200706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2201706f2543Smrg } else { 2202706f2543Smrg u16 srcval, *dstreg; 2203706f2543Smrg 2204706f2543Smrg srcoffset = decode_rm00_address(rl); 2205706f2543Smrg DECODE_PRINTF(","); 2206706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2207706f2543Smrg TRACE_AND_STEP(); 2208706f2543Smrg srcval = fetch_data_word(srcoffset); 2209706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2210706f2543Smrg for(*dstreg = 0; *dstreg < 16; (*dstreg)++) 2211706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2212706f2543Smrg } 2213706f2543Smrg break; 2214706f2543Smrg case 1: 2215706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2216706f2543Smrg u32 srcval, *dstreg; 2217706f2543Smrg 2218706f2543Smrg srcoffset = decode_rm01_address(rl); 2219706f2543Smrg DECODE_PRINTF(","); 2220706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2221706f2543Smrg TRACE_AND_STEP(); 2222706f2543Smrg srcval = fetch_data_long(srcoffset); 2223706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2224706f2543Smrg for(*dstreg = 0; *dstreg < 32; (*dstreg)++) 2225706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2226706f2543Smrg } else { 2227706f2543Smrg u16 srcval, *dstreg; 2228706f2543Smrg 2229706f2543Smrg srcoffset = decode_rm01_address(rl); 2230706f2543Smrg DECODE_PRINTF(","); 2231706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2232706f2543Smrg TRACE_AND_STEP(); 2233706f2543Smrg srcval = fetch_data_word(srcoffset); 2234706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2235706f2543Smrg for(*dstreg = 0; *dstreg < 16; (*dstreg)++) 2236706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2237706f2543Smrg } 2238706f2543Smrg break; 2239706f2543Smrg case 2: 2240706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2241706f2543Smrg u32 srcval, *dstreg; 2242706f2543Smrg 2243706f2543Smrg srcoffset = decode_rm10_address(rl); 2244706f2543Smrg DECODE_PRINTF(","); 2245706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2246706f2543Smrg TRACE_AND_STEP(); 2247706f2543Smrg srcval = fetch_data_long(srcoffset); 2248706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2249706f2543Smrg for(*dstreg = 0; *dstreg < 32; (*dstreg)++) 2250706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2251706f2543Smrg } else { 2252706f2543Smrg u16 srcval, *dstreg; 2253706f2543Smrg 2254706f2543Smrg srcoffset = decode_rm10_address(rl); 2255706f2543Smrg DECODE_PRINTF(","); 2256706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2257706f2543Smrg TRACE_AND_STEP(); 2258706f2543Smrg srcval = fetch_data_word(srcoffset); 2259706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2260706f2543Smrg for(*dstreg = 0; *dstreg < 16; (*dstreg)++) 2261706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2262706f2543Smrg } 2263706f2543Smrg break; 2264706f2543Smrg case 3: /* register to register */ 2265706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2266706f2543Smrg u32 srcval, *dstreg; 2267706f2543Smrg 2268706f2543Smrg srcval = *DECODE_RM_LONG_REGISTER(rl); 2269706f2543Smrg DECODE_PRINTF(","); 2270706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2271706f2543Smrg TRACE_AND_STEP(); 2272706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2273706f2543Smrg for(*dstreg = 0; *dstreg < 32; (*dstreg)++) 2274706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2275706f2543Smrg } else { 2276706f2543Smrg u16 srcval, *dstreg; 2277706f2543Smrg 2278706f2543Smrg srcval = *DECODE_RM_WORD_REGISTER(rl); 2279706f2543Smrg DECODE_PRINTF(","); 2280706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2281706f2543Smrg TRACE_AND_STEP(); 2282706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2283706f2543Smrg for(*dstreg = 0; *dstreg < 16; (*dstreg)++) 2284706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2285706f2543Smrg } 2286706f2543Smrg break; 2287706f2543Smrg } 2288706f2543Smrg DECODE_CLEAR_SEGOVR(); 2289706f2543Smrg END_OF_INSTR(); 2290706f2543Smrg} 2291706f2543Smrg 2292706f2543Smrg/**************************************************************************** 2293706f2543SmrgREMARKS: 2294706f2543SmrgHandles opcode 0x0f,0xbd 2295706f2543Smrg****************************************************************************/ 2296706f2543Smrgstatic void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2)) 2297706f2543Smrg{ 2298706f2543Smrg int mod, rl, rh; 2299706f2543Smrg uint srcoffset; 2300706f2543Smrg 2301706f2543Smrg START_OF_INSTR(); 2302706f2543Smrg DECODE_PRINTF("BSR\t"); 2303706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 2304706f2543Smrg switch(mod) { 2305706f2543Smrg case 0: 2306706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2307706f2543Smrg u32 srcval, *dstreg; 2308706f2543Smrg 2309706f2543Smrg srcoffset = decode_rm00_address(rl); 2310706f2543Smrg DECODE_PRINTF(","); 2311706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2312706f2543Smrg TRACE_AND_STEP(); 2313706f2543Smrg srcval = fetch_data_long(srcoffset); 2314706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2315706f2543Smrg for(*dstreg = 31; *dstreg > 0; (*dstreg)--) 2316706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2317706f2543Smrg } else { 2318706f2543Smrg u16 srcval, *dstreg; 2319706f2543Smrg 2320706f2543Smrg srcoffset = decode_rm00_address(rl); 2321706f2543Smrg DECODE_PRINTF(","); 2322706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2323706f2543Smrg TRACE_AND_STEP(); 2324706f2543Smrg srcval = fetch_data_word(srcoffset); 2325706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2326706f2543Smrg for(*dstreg = 15; *dstreg > 0; (*dstreg)--) 2327706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2328706f2543Smrg } 2329706f2543Smrg break; 2330706f2543Smrg case 1: 2331706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2332706f2543Smrg u32 srcval, *dstreg; 2333706f2543Smrg 2334706f2543Smrg srcoffset = decode_rm01_address(rl); 2335706f2543Smrg DECODE_PRINTF(","); 2336706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2337706f2543Smrg TRACE_AND_STEP(); 2338706f2543Smrg srcval = fetch_data_long(srcoffset); 2339706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2340706f2543Smrg for(*dstreg = 31; *dstreg > 0; (*dstreg)--) 2341706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2342706f2543Smrg } else { 2343706f2543Smrg u16 srcval, *dstreg; 2344706f2543Smrg 2345706f2543Smrg srcoffset = decode_rm01_address(rl); 2346706f2543Smrg DECODE_PRINTF(","); 2347706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2348706f2543Smrg TRACE_AND_STEP(); 2349706f2543Smrg srcval = fetch_data_word(srcoffset); 2350706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2351706f2543Smrg for(*dstreg = 15; *dstreg > 0; (*dstreg)--) 2352706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2353706f2543Smrg } 2354706f2543Smrg break; 2355706f2543Smrg case 2: 2356706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2357706f2543Smrg u32 srcval, *dstreg; 2358706f2543Smrg 2359706f2543Smrg srcoffset = decode_rm10_address(rl); 2360706f2543Smrg DECODE_PRINTF(","); 2361706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2362706f2543Smrg TRACE_AND_STEP(); 2363706f2543Smrg srcval = fetch_data_long(srcoffset); 2364706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2365706f2543Smrg for(*dstreg = 31; *dstreg > 0; (*dstreg)--) 2366706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2367706f2543Smrg } else { 2368706f2543Smrg u16 srcval, *dstreg; 2369706f2543Smrg 2370706f2543Smrg srcoffset = decode_rm10_address(rl); 2371706f2543Smrg DECODE_PRINTF(","); 2372706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2373706f2543Smrg TRACE_AND_STEP(); 2374706f2543Smrg srcval = fetch_data_word(srcoffset); 2375706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2376706f2543Smrg for(*dstreg = 15; *dstreg > 0; (*dstreg)--) 2377706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2378706f2543Smrg } 2379706f2543Smrg break; 2380706f2543Smrg case 3: /* register to register */ 2381706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2382706f2543Smrg u32 srcval, *dstreg; 2383706f2543Smrg 2384706f2543Smrg srcval = *DECODE_RM_LONG_REGISTER(rl); 2385706f2543Smrg DECODE_PRINTF(","); 2386706f2543Smrg dstreg = DECODE_RM_LONG_REGISTER(rh); 2387706f2543Smrg TRACE_AND_STEP(); 2388706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2389706f2543Smrg for(*dstreg = 31; *dstreg > 0; (*dstreg)--) 2390706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2391706f2543Smrg } else { 2392706f2543Smrg u16 srcval, *dstreg; 2393706f2543Smrg 2394706f2543Smrg srcval = *DECODE_RM_WORD_REGISTER(rl); 2395706f2543Smrg DECODE_PRINTF(","); 2396706f2543Smrg dstreg = DECODE_RM_WORD_REGISTER(rh); 2397706f2543Smrg TRACE_AND_STEP(); 2398706f2543Smrg CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); 2399706f2543Smrg for(*dstreg = 15; *dstreg > 0; (*dstreg)--) 2400706f2543Smrg if ((srcval >> *dstreg) & 1) break; 2401706f2543Smrg } 2402706f2543Smrg break; 2403706f2543Smrg } 2404706f2543Smrg DECODE_CLEAR_SEGOVR(); 2405706f2543Smrg END_OF_INSTR(); 2406706f2543Smrg} 2407706f2543Smrg 2408706f2543Smrg/**************************************************************************** 2409706f2543SmrgREMARKS: 2410706f2543SmrgHandles opcode 0x0f,0xbe 2411706f2543Smrg****************************************************************************/ 2412706f2543Smrgstatic void x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2)) 2413706f2543Smrg{ 2414706f2543Smrg int mod, rl, rh; 2415706f2543Smrg uint srcoffset; 2416706f2543Smrg 2417706f2543Smrg START_OF_INSTR(); 2418706f2543Smrg DECODE_PRINTF("MOVSX\t"); 2419706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 2420706f2543Smrg switch (mod) { 2421706f2543Smrg case 0: 2422706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2423706f2543Smrg u32 *destreg; 2424706f2543Smrg u32 srcval; 2425706f2543Smrg 2426706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2427706f2543Smrg DECODE_PRINTF(","); 2428706f2543Smrg srcoffset = decode_rm00_address(rl); 2429706f2543Smrg srcval = (s32)((s8)fetch_data_byte(srcoffset)); 2430706f2543Smrg DECODE_PRINTF("\n"); 2431706f2543Smrg TRACE_AND_STEP(); 2432706f2543Smrg *destreg = srcval; 2433706f2543Smrg } else { 2434706f2543Smrg u16 *destreg; 2435706f2543Smrg u16 srcval; 2436706f2543Smrg 2437706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 2438706f2543Smrg DECODE_PRINTF(","); 2439706f2543Smrg srcoffset = decode_rm00_address(rl); 2440706f2543Smrg srcval = (s16)((s8)fetch_data_byte(srcoffset)); 2441706f2543Smrg DECODE_PRINTF("\n"); 2442706f2543Smrg TRACE_AND_STEP(); 2443706f2543Smrg *destreg = srcval; 2444706f2543Smrg } 2445706f2543Smrg break; 2446706f2543Smrg case 1: 2447706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2448706f2543Smrg u32 *destreg; 2449706f2543Smrg u32 srcval; 2450706f2543Smrg 2451706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2452706f2543Smrg DECODE_PRINTF(","); 2453706f2543Smrg srcoffset = decode_rm01_address(rl); 2454706f2543Smrg srcval = (s32)((s8)fetch_data_byte(srcoffset)); 2455706f2543Smrg DECODE_PRINTF("\n"); 2456706f2543Smrg TRACE_AND_STEP(); 2457706f2543Smrg *destreg = srcval; 2458706f2543Smrg } else { 2459706f2543Smrg u16 *destreg; 2460706f2543Smrg u16 srcval; 2461706f2543Smrg 2462706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 2463706f2543Smrg DECODE_PRINTF(","); 2464706f2543Smrg srcoffset = decode_rm01_address(rl); 2465706f2543Smrg srcval = (s16)((s8)fetch_data_byte(srcoffset)); 2466706f2543Smrg DECODE_PRINTF("\n"); 2467706f2543Smrg TRACE_AND_STEP(); 2468706f2543Smrg *destreg = srcval; 2469706f2543Smrg } 2470706f2543Smrg break; 2471706f2543Smrg case 2: 2472706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2473706f2543Smrg u32 *destreg; 2474706f2543Smrg u32 srcval; 2475706f2543Smrg 2476706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2477706f2543Smrg DECODE_PRINTF(","); 2478706f2543Smrg srcoffset = decode_rm10_address(rl); 2479706f2543Smrg srcval = (s32)((s8)fetch_data_byte(srcoffset)); 2480706f2543Smrg DECODE_PRINTF("\n"); 2481706f2543Smrg TRACE_AND_STEP(); 2482706f2543Smrg *destreg = srcval; 2483706f2543Smrg } else { 2484706f2543Smrg u16 *destreg; 2485706f2543Smrg u16 srcval; 2486706f2543Smrg 2487706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 2488706f2543Smrg DECODE_PRINTF(","); 2489706f2543Smrg srcoffset = decode_rm10_address(rl); 2490706f2543Smrg srcval = (s16)((s8)fetch_data_byte(srcoffset)); 2491706f2543Smrg DECODE_PRINTF("\n"); 2492706f2543Smrg TRACE_AND_STEP(); 2493706f2543Smrg *destreg = srcval; 2494706f2543Smrg } 2495706f2543Smrg break; 2496706f2543Smrg case 3: /* register to register */ 2497706f2543Smrg if (M.x86.mode & SYSMODE_PREFIX_DATA) { 2498706f2543Smrg u32 *destreg; 2499706f2543Smrg u8 *srcreg; 2500706f2543Smrg 2501706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2502706f2543Smrg DECODE_PRINTF(","); 2503706f2543Smrg srcreg = DECODE_RM_BYTE_REGISTER(rl); 2504706f2543Smrg DECODE_PRINTF("\n"); 2505706f2543Smrg TRACE_AND_STEP(); 2506706f2543Smrg *destreg = (s32)((s8)*srcreg); 2507706f2543Smrg } else { 2508706f2543Smrg u16 *destreg; 2509706f2543Smrg u8 *srcreg; 2510706f2543Smrg 2511706f2543Smrg destreg = DECODE_RM_WORD_REGISTER(rh); 2512706f2543Smrg DECODE_PRINTF(","); 2513706f2543Smrg srcreg = DECODE_RM_BYTE_REGISTER(rl); 2514706f2543Smrg DECODE_PRINTF("\n"); 2515706f2543Smrg TRACE_AND_STEP(); 2516706f2543Smrg *destreg = (s16)((s8)*srcreg); 2517706f2543Smrg } 2518706f2543Smrg break; 2519706f2543Smrg } 2520706f2543Smrg DECODE_CLEAR_SEGOVR(); 2521706f2543Smrg END_OF_INSTR(); 2522706f2543Smrg} 2523706f2543Smrg 2524706f2543Smrg/**************************************************************************** 2525706f2543SmrgREMARKS: 2526706f2543SmrgHandles opcode 0x0f,0xbf 2527706f2543Smrg****************************************************************************/ 2528706f2543Smrgstatic void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2)) 2529706f2543Smrg{ 2530706f2543Smrg int mod, rl, rh; 2531706f2543Smrg uint srcoffset; 2532706f2543Smrg u32 *destreg; 2533706f2543Smrg u32 srcval; 2534706f2543Smrg u16 *srcreg; 2535706f2543Smrg 2536706f2543Smrg START_OF_INSTR(); 2537706f2543Smrg DECODE_PRINTF("MOVSX\t"); 2538706f2543Smrg FETCH_DECODE_MODRM(mod, rh, rl); 2539706f2543Smrg switch (mod) { 2540706f2543Smrg case 0: 2541706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2542706f2543Smrg DECODE_PRINTF(","); 2543706f2543Smrg srcoffset = decode_rm00_address(rl); 2544706f2543Smrg srcval = (s32)((s16)fetch_data_word(srcoffset)); 2545706f2543Smrg DECODE_PRINTF("\n"); 2546706f2543Smrg TRACE_AND_STEP(); 2547706f2543Smrg *destreg = srcval; 2548706f2543Smrg break; 2549706f2543Smrg case 1: 2550706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2551706f2543Smrg DECODE_PRINTF(","); 2552706f2543Smrg srcoffset = decode_rm01_address(rl); 2553706f2543Smrg srcval = (s32)((s16)fetch_data_word(srcoffset)); 2554706f2543Smrg DECODE_PRINTF("\n"); 2555706f2543Smrg TRACE_AND_STEP(); 2556706f2543Smrg *destreg = srcval; 2557706f2543Smrg break; 2558706f2543Smrg case 2: 2559706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2560706f2543Smrg DECODE_PRINTF(","); 2561706f2543Smrg srcoffset = decode_rm10_address(rl); 2562706f2543Smrg srcval = (s32)((s16)fetch_data_word(srcoffset)); 2563706f2543Smrg DECODE_PRINTF("\n"); 2564706f2543Smrg TRACE_AND_STEP(); 2565706f2543Smrg *destreg = srcval; 2566706f2543Smrg break; 2567706f2543Smrg case 3: /* register to register */ 2568706f2543Smrg destreg = DECODE_RM_LONG_REGISTER(rh); 2569706f2543Smrg DECODE_PRINTF(","); 2570706f2543Smrg srcreg = DECODE_RM_WORD_REGISTER(rl); 2571706f2543Smrg DECODE_PRINTF("\n"); 2572706f2543Smrg TRACE_AND_STEP(); 2573706f2543Smrg *destreg = (s32)((s16)*srcreg); 2574706f2543Smrg break; 2575706f2543Smrg } 2576706f2543Smrg DECODE_CLEAR_SEGOVR(); 2577706f2543Smrg END_OF_INSTR(); 2578706f2543Smrg} 2579706f2543Smrg 2580706f2543Smrg/* Handles opcodes 0xc8-0xcf */ 2581706f2543Smrgstatic void x86emuOp2_bswap(u8 X86EMU_UNUSED(op2)) 2582706f2543Smrg{ 2583706f2543Smrg START_OF_INSTR(); 2584706f2543Smrg DECODE_PRINTF("BSWAP\n"); 2585706f2543Smrg TRACE_AND_STEP(); 2586706f2543Smrg 2587706f2543Smrg switch (op2) { 2588706f2543Smrg case 0xc8: 2589706f2543Smrg M.x86.R_EAX = bswap_32(M.x86.R_EAX); 2590706f2543Smrg break; 2591706f2543Smrg case 0xc9: 2592706f2543Smrg M.x86.R_ECX = bswap_32(M.x86.R_ECX); 2593706f2543Smrg break; 2594706f2543Smrg case 0xca: 2595706f2543Smrg M.x86.R_EDX = bswap_32(M.x86.R_EDX); 2596706f2543Smrg break; 2597706f2543Smrg case 0xcb: 2598706f2543Smrg M.x86.R_EBX = bswap_32(M.x86.R_EBX); 2599706f2543Smrg break; 2600706f2543Smrg case 0xcc: 2601706f2543Smrg M.x86.R_ESP = bswap_32(M.x86.R_ESP); 2602706f2543Smrg break; 2603706f2543Smrg case 0xcd: 2604706f2543Smrg M.x86.R_EBP = bswap_32(M.x86.R_EBP); 2605706f2543Smrg break; 2606706f2543Smrg case 0xce: 2607706f2543Smrg M.x86.R_ESI = bswap_32(M.x86.R_ESI); 2608706f2543Smrg break; 2609706f2543Smrg case 0xcf: 2610706f2543Smrg M.x86.R_EDI = bswap_32(M.x86.R_EDI); 2611706f2543Smrg break; 2612706f2543Smrg default: 2613706f2543Smrg /* can't happen */ 2614706f2543Smrg break; 2615706f2543Smrg } 2616706f2543Smrg 2617706f2543Smrg DECODE_CLEAR_SEGOVR(); 2618706f2543Smrg END_OF_INSTR(); 2619706f2543Smrg} 2620706f2543Smrg 2621706f2543Smrg/*************************************************************************** 2622706f2543Smrg * Double byte operation code table: 2623706f2543Smrg **************************************************************************/ 2624706f2543Smrgvoid (*x86emu_optab2[256])(u8) = 2625706f2543Smrg{ 2626706f2543Smrg/* 0x00 */ x86emuOp2_illegal_op, /* Group F (ring 0 PM) */ 2627706f2543Smrg/* 0x01 */ x86emuOp2_illegal_op, /* Group G (ring 0 PM) */ 2628706f2543Smrg/* 0x02 */ x86emuOp2_illegal_op, /* lar (ring 0 PM) */ 2629706f2543Smrg/* 0x03 */ x86emuOp2_illegal_op, /* lsl (ring 0 PM) */ 2630706f2543Smrg/* 0x04 */ x86emuOp2_illegal_op, 2631706f2543Smrg/* 0x05 */ x86emuOp2_illegal_op, /* loadall (undocumented) */ 2632706f2543Smrg/* 0x06 */ x86emuOp2_illegal_op, /* clts (ring 0 PM) */ 2633706f2543Smrg/* 0x07 */ x86emuOp2_illegal_op, /* loadall (undocumented) */ 2634706f2543Smrg/* 0x08 */ x86emuOp2_illegal_op, /* invd (ring 0 PM) */ 2635706f2543Smrg/* 0x09 */ x86emuOp2_illegal_op, /* wbinvd (ring 0 PM) */ 2636706f2543Smrg/* 0x0a */ x86emuOp2_illegal_op, 2637706f2543Smrg/* 0x0b */ x86emuOp2_illegal_op, 2638706f2543Smrg/* 0x0c */ x86emuOp2_illegal_op, 2639706f2543Smrg/* 0x0d */ x86emuOp2_illegal_op, 2640706f2543Smrg/* 0x0e */ x86emuOp2_illegal_op, 2641706f2543Smrg/* 0x0f */ x86emuOp2_illegal_op, 2642706f2543Smrg 2643706f2543Smrg/* 0x10 */ x86emuOp2_illegal_op, 2644706f2543Smrg/* 0x11 */ x86emuOp2_illegal_op, 2645706f2543Smrg/* 0x12 */ x86emuOp2_illegal_op, 2646706f2543Smrg/* 0x13 */ x86emuOp2_illegal_op, 2647706f2543Smrg/* 0x14 */ x86emuOp2_illegal_op, 2648706f2543Smrg/* 0x15 */ x86emuOp2_illegal_op, 2649706f2543Smrg/* 0x16 */ x86emuOp2_illegal_op, 2650706f2543Smrg/* 0x17 */ x86emuOp2_illegal_op, 2651706f2543Smrg/* 0x18 */ x86emuOp2_illegal_op, 2652706f2543Smrg/* 0x19 */ x86emuOp2_illegal_op, 2653706f2543Smrg/* 0x1a */ x86emuOp2_illegal_op, 2654706f2543Smrg/* 0x1b */ x86emuOp2_illegal_op, 2655706f2543Smrg/* 0x1c */ x86emuOp2_illegal_op, 2656706f2543Smrg/* 0x1d */ x86emuOp2_illegal_op, 2657706f2543Smrg/* 0x1e */ x86emuOp2_illegal_op, 2658706f2543Smrg/* 0x1f */ x86emuOp2_illegal_op, 2659706f2543Smrg 2660706f2543Smrg/* 0x20 */ x86emuOp2_illegal_op, /* mov reg32,creg (ring 0 PM) */ 2661706f2543Smrg/* 0x21 */ x86emuOp2_illegal_op, /* mov reg32,dreg (ring 0 PM) */ 2662706f2543Smrg/* 0x22 */ x86emuOp2_illegal_op, /* mov creg,reg32 (ring 0 PM) */ 2663706f2543Smrg/* 0x23 */ x86emuOp2_illegal_op, /* mov dreg,reg32 (ring 0 PM) */ 2664706f2543Smrg/* 0x24 */ x86emuOp2_illegal_op, /* mov reg32,treg (ring 0 PM) */ 2665706f2543Smrg/* 0x25 */ x86emuOp2_illegal_op, 2666706f2543Smrg/* 0x26 */ x86emuOp2_illegal_op, /* mov treg,reg32 (ring 0 PM) */ 2667706f2543Smrg/* 0x27 */ x86emuOp2_illegal_op, 2668706f2543Smrg/* 0x28 */ x86emuOp2_illegal_op, 2669706f2543Smrg/* 0x29 */ x86emuOp2_illegal_op, 2670706f2543Smrg/* 0x2a */ x86emuOp2_illegal_op, 2671706f2543Smrg/* 0x2b */ x86emuOp2_illegal_op, 2672706f2543Smrg/* 0x2c */ x86emuOp2_illegal_op, 2673706f2543Smrg/* 0x2d */ x86emuOp2_illegal_op, 2674706f2543Smrg/* 0x2e */ x86emuOp2_illegal_op, 2675706f2543Smrg/* 0x2f */ x86emuOp2_illegal_op, 2676706f2543Smrg 2677706f2543Smrg/* 0x30 */ x86emuOp2_illegal_op, 2678706f2543Smrg/* 0x31 */ x86emuOp2_rdtsc, 2679706f2543Smrg/* 0x32 */ x86emuOp2_illegal_op, 2680706f2543Smrg/* 0x33 */ x86emuOp2_illegal_op, 2681706f2543Smrg/* 0x34 */ x86emuOp2_illegal_op, 2682706f2543Smrg/* 0x35 */ x86emuOp2_illegal_op, 2683706f2543Smrg/* 0x36 */ x86emuOp2_illegal_op, 2684706f2543Smrg/* 0x37 */ x86emuOp2_illegal_op, 2685706f2543Smrg/* 0x38 */ x86emuOp2_illegal_op, 2686706f2543Smrg/* 0x39 */ x86emuOp2_illegal_op, 2687706f2543Smrg/* 0x3a */ x86emuOp2_illegal_op, 2688706f2543Smrg/* 0x3b */ x86emuOp2_illegal_op, 2689706f2543Smrg/* 0x3c */ x86emuOp2_illegal_op, 2690706f2543Smrg/* 0x3d */ x86emuOp2_illegal_op, 2691706f2543Smrg/* 0x3e */ x86emuOp2_illegal_op, 2692706f2543Smrg/* 0x3f */ x86emuOp2_illegal_op, 2693706f2543Smrg 2694706f2543Smrg/* 0x40 */ x86emuOp2_illegal_op, 2695706f2543Smrg/* 0x41 */ x86emuOp2_illegal_op, 2696706f2543Smrg/* 0x42 */ x86emuOp2_illegal_op, 2697706f2543Smrg/* 0x43 */ x86emuOp2_illegal_op, 2698706f2543Smrg/* 0x44 */ x86emuOp2_illegal_op, 2699706f2543Smrg/* 0x45 */ x86emuOp2_illegal_op, 2700706f2543Smrg/* 0x46 */ x86emuOp2_illegal_op, 2701706f2543Smrg/* 0x47 */ x86emuOp2_illegal_op, 2702706f2543Smrg/* 0x48 */ x86emuOp2_illegal_op, 2703706f2543Smrg/* 0x49 */ x86emuOp2_illegal_op, 2704706f2543Smrg/* 0x4a */ x86emuOp2_illegal_op, 2705706f2543Smrg/* 0x4b */ x86emuOp2_illegal_op, 2706706f2543Smrg/* 0x4c */ x86emuOp2_illegal_op, 2707706f2543Smrg/* 0x4d */ x86emuOp2_illegal_op, 2708706f2543Smrg/* 0x4e */ x86emuOp2_illegal_op, 2709706f2543Smrg/* 0x4f */ x86emuOp2_illegal_op, 2710706f2543Smrg 2711706f2543Smrg/* 0x50 */ x86emuOp2_illegal_op, 2712706f2543Smrg/* 0x51 */ x86emuOp2_illegal_op, 2713706f2543Smrg/* 0x52 */ x86emuOp2_illegal_op, 2714706f2543Smrg/* 0x53 */ x86emuOp2_illegal_op, 2715706f2543Smrg/* 0x54 */ x86emuOp2_illegal_op, 2716706f2543Smrg/* 0x55 */ x86emuOp2_illegal_op, 2717706f2543Smrg/* 0x56 */ x86emuOp2_illegal_op, 2718706f2543Smrg/* 0x57 */ x86emuOp2_illegal_op, 2719706f2543Smrg/* 0x58 */ x86emuOp2_illegal_op, 2720706f2543Smrg/* 0x59 */ x86emuOp2_illegal_op, 2721706f2543Smrg/* 0x5a */ x86emuOp2_illegal_op, 2722706f2543Smrg/* 0x5b */ x86emuOp2_illegal_op, 2723706f2543Smrg/* 0x5c */ x86emuOp2_illegal_op, 2724706f2543Smrg/* 0x5d */ x86emuOp2_illegal_op, 2725706f2543Smrg/* 0x5e */ x86emuOp2_illegal_op, 2726706f2543Smrg/* 0x5f */ x86emuOp2_illegal_op, 2727706f2543Smrg 2728706f2543Smrg/* 0x60 */ x86emuOp2_illegal_op, 2729706f2543Smrg/* 0x61 */ x86emuOp2_illegal_op, 2730706f2543Smrg/* 0x62 */ x86emuOp2_illegal_op, 2731706f2543Smrg/* 0x63 */ x86emuOp2_illegal_op, 2732706f2543Smrg/* 0x64 */ x86emuOp2_illegal_op, 2733706f2543Smrg/* 0x65 */ x86emuOp2_illegal_op, 2734706f2543Smrg/* 0x66 */ x86emuOp2_illegal_op, 2735706f2543Smrg/* 0x67 */ x86emuOp2_illegal_op, 2736706f2543Smrg/* 0x68 */ x86emuOp2_illegal_op, 2737706f2543Smrg/* 0x69 */ x86emuOp2_illegal_op, 2738706f2543Smrg/* 0x6a */ x86emuOp2_illegal_op, 2739706f2543Smrg/* 0x6b */ x86emuOp2_illegal_op, 2740706f2543Smrg/* 0x6c */ x86emuOp2_illegal_op, 2741706f2543Smrg/* 0x6d */ x86emuOp2_illegal_op, 2742706f2543Smrg/* 0x6e */ x86emuOp2_illegal_op, 2743706f2543Smrg/* 0x6f */ x86emuOp2_illegal_op, 2744706f2543Smrg 2745706f2543Smrg/* 0x70 */ x86emuOp2_illegal_op, 2746706f2543Smrg/* 0x71 */ x86emuOp2_illegal_op, 2747706f2543Smrg/* 0x72 */ x86emuOp2_illegal_op, 2748706f2543Smrg/* 0x73 */ x86emuOp2_illegal_op, 2749706f2543Smrg/* 0x74 */ x86emuOp2_illegal_op, 2750706f2543Smrg/* 0x75 */ x86emuOp2_illegal_op, 2751706f2543Smrg/* 0x76 */ x86emuOp2_illegal_op, 2752706f2543Smrg/* 0x77 */ x86emuOp2_illegal_op, 2753706f2543Smrg/* 0x78 */ x86emuOp2_illegal_op, 2754706f2543Smrg/* 0x79 */ x86emuOp2_illegal_op, 2755706f2543Smrg/* 0x7a */ x86emuOp2_illegal_op, 2756706f2543Smrg/* 0x7b */ x86emuOp2_illegal_op, 2757706f2543Smrg/* 0x7c */ x86emuOp2_illegal_op, 2758706f2543Smrg/* 0x7d */ x86emuOp2_illegal_op, 2759706f2543Smrg/* 0x7e */ x86emuOp2_illegal_op, 2760706f2543Smrg/* 0x7f */ x86emuOp2_illegal_op, 2761706f2543Smrg 2762706f2543Smrg/* 0x80 */ x86emuOp2_long_jump, 2763706f2543Smrg/* 0x81 */ x86emuOp2_long_jump, 2764706f2543Smrg/* 0x82 */ x86emuOp2_long_jump, 2765706f2543Smrg/* 0x83 */ x86emuOp2_long_jump, 2766706f2543Smrg/* 0x84 */ x86emuOp2_long_jump, 2767706f2543Smrg/* 0x85 */ x86emuOp2_long_jump, 2768706f2543Smrg/* 0x86 */ x86emuOp2_long_jump, 2769706f2543Smrg/* 0x87 */ x86emuOp2_long_jump, 2770706f2543Smrg/* 0x88 */ x86emuOp2_long_jump, 2771706f2543Smrg/* 0x89 */ x86emuOp2_long_jump, 2772706f2543Smrg/* 0x8a */ x86emuOp2_long_jump, 2773706f2543Smrg/* 0x8b */ x86emuOp2_long_jump, 2774706f2543Smrg/* 0x8c */ x86emuOp2_long_jump, 2775706f2543Smrg/* 0x8d */ x86emuOp2_long_jump, 2776706f2543Smrg/* 0x8e */ x86emuOp2_long_jump, 2777706f2543Smrg/* 0x8f */ x86emuOp2_long_jump, 2778706f2543Smrg 2779706f2543Smrg/* 0x90 */ x86emuOp2_set_byte, 2780706f2543Smrg/* 0x91 */ x86emuOp2_set_byte, 2781706f2543Smrg/* 0x92 */ x86emuOp2_set_byte, 2782706f2543Smrg/* 0x93 */ x86emuOp2_set_byte, 2783706f2543Smrg/* 0x94 */ x86emuOp2_set_byte, 2784706f2543Smrg/* 0x95 */ x86emuOp2_set_byte, 2785706f2543Smrg/* 0x96 */ x86emuOp2_set_byte, 2786706f2543Smrg/* 0x97 */ x86emuOp2_set_byte, 2787706f2543Smrg/* 0x98 */ x86emuOp2_set_byte, 2788706f2543Smrg/* 0x99 */ x86emuOp2_set_byte, 2789706f2543Smrg/* 0x9a */ x86emuOp2_set_byte, 2790706f2543Smrg/* 0x9b */ x86emuOp2_set_byte, 2791706f2543Smrg/* 0x9c */ x86emuOp2_set_byte, 2792706f2543Smrg/* 0x9d */ x86emuOp2_set_byte, 2793706f2543Smrg/* 0x9e */ x86emuOp2_set_byte, 2794706f2543Smrg/* 0x9f */ x86emuOp2_set_byte, 2795706f2543Smrg 2796706f2543Smrg/* 0xa0 */ x86emuOp2_push_FS, 2797706f2543Smrg/* 0xa1 */ x86emuOp2_pop_FS, 2798706f2543Smrg/* 0xa2 */ x86emuOp2_cpuid, 2799706f2543Smrg/* 0xa3 */ x86emuOp2_bt_R, 2800706f2543Smrg/* 0xa4 */ x86emuOp2_shld_IMM, 2801706f2543Smrg/* 0xa5 */ x86emuOp2_shld_CL, 2802706f2543Smrg/* 0xa6 */ x86emuOp2_illegal_op, 2803706f2543Smrg/* 0xa7 */ x86emuOp2_illegal_op, 2804706f2543Smrg/* 0xa8 */ x86emuOp2_push_GS, 2805706f2543Smrg/* 0xa9 */ x86emuOp2_pop_GS, 2806706f2543Smrg/* 0xaa */ x86emuOp2_illegal_op, 2807706f2543Smrg/* 0xab */ x86emuOp2_bts_R, 2808706f2543Smrg/* 0xac */ x86emuOp2_shrd_IMM, 2809706f2543Smrg/* 0xad */ x86emuOp2_shrd_CL, 2810706f2543Smrg/* 0xae */ x86emuOp2_illegal_op, 2811706f2543Smrg/* 0xaf */ x86emuOp2_imul_R_RM, 2812706f2543Smrg 2813706f2543Smrg/* 0xb0 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */ 2814706f2543Smrg/* 0xb1 */ x86emuOp2_illegal_op, /* TODO: cmpxchg */ 2815706f2543Smrg/* 0xb2 */ x86emuOp2_lss_R_IMM, 2816706f2543Smrg/* 0xb3 */ x86emuOp2_btr_R, 2817706f2543Smrg/* 0xb4 */ x86emuOp2_lfs_R_IMM, 2818706f2543Smrg/* 0xb5 */ x86emuOp2_lgs_R_IMM, 2819706f2543Smrg/* 0xb6 */ x86emuOp2_movzx_byte_R_RM, 2820706f2543Smrg/* 0xb7 */ x86emuOp2_movzx_word_R_RM, 2821706f2543Smrg/* 0xb8 */ x86emuOp2_illegal_op, 2822706f2543Smrg/* 0xb9 */ x86emuOp2_illegal_op, 2823706f2543Smrg/* 0xba */ x86emuOp2_btX_I, 2824706f2543Smrg/* 0xbb */ x86emuOp2_btc_R, 2825706f2543Smrg/* 0xbc */ x86emuOp2_bsf, 2826706f2543Smrg/* 0xbd */ x86emuOp2_bsr, 2827706f2543Smrg/* 0xbe */ x86emuOp2_movsx_byte_R_RM, 2828706f2543Smrg/* 0xbf */ x86emuOp2_movsx_word_R_RM, 2829706f2543Smrg 2830706f2543Smrg/* 0xc0 */ x86emuOp2_illegal_op, /* TODO: xadd */ 2831706f2543Smrg/* 0xc1 */ x86emuOp2_illegal_op, /* TODO: xadd */ 2832706f2543Smrg/* 0xc2 */ x86emuOp2_illegal_op, 2833706f2543Smrg/* 0xc3 */ x86emuOp2_illegal_op, 2834706f2543Smrg/* 0xc4 */ x86emuOp2_illegal_op, 2835706f2543Smrg/* 0xc5 */ x86emuOp2_illegal_op, 2836706f2543Smrg/* 0xc6 */ x86emuOp2_illegal_op, 2837706f2543Smrg/* 0xc7 */ x86emuOp2_illegal_op, 2838706f2543Smrg/* 0xc8 */ x86emuOp2_bswap, 2839706f2543Smrg/* 0xc9 */ x86emuOp2_bswap, 2840706f2543Smrg/* 0xca */ x86emuOp2_bswap, 2841706f2543Smrg/* 0xcb */ x86emuOp2_bswap, 2842706f2543Smrg/* 0xcc */ x86emuOp2_bswap, 2843706f2543Smrg/* 0xcd */ x86emuOp2_bswap, 2844706f2543Smrg/* 0xce */ x86emuOp2_bswap, 2845706f2543Smrg/* 0xcf */ x86emuOp2_bswap, 2846706f2543Smrg 2847706f2543Smrg/* 0xd0 */ x86emuOp2_illegal_op, 2848706f2543Smrg/* 0xd1 */ x86emuOp2_illegal_op, 2849706f2543Smrg/* 0xd2 */ x86emuOp2_illegal_op, 2850706f2543Smrg/* 0xd3 */ x86emuOp2_illegal_op, 2851706f2543Smrg/* 0xd4 */ x86emuOp2_illegal_op, 2852706f2543Smrg/* 0xd5 */ x86emuOp2_illegal_op, 2853706f2543Smrg/* 0xd6 */ x86emuOp2_illegal_op, 2854706f2543Smrg/* 0xd7 */ x86emuOp2_illegal_op, 2855706f2543Smrg/* 0xd8 */ x86emuOp2_illegal_op, 2856706f2543Smrg/* 0xd9 */ x86emuOp2_illegal_op, 2857706f2543Smrg/* 0xda */ x86emuOp2_illegal_op, 2858706f2543Smrg/* 0xdb */ x86emuOp2_illegal_op, 2859706f2543Smrg/* 0xdc */ x86emuOp2_illegal_op, 2860706f2543Smrg/* 0xdd */ x86emuOp2_illegal_op, 2861706f2543Smrg/* 0xde */ x86emuOp2_illegal_op, 2862706f2543Smrg/* 0xdf */ x86emuOp2_illegal_op, 2863706f2543Smrg 2864706f2543Smrg/* 0xe0 */ x86emuOp2_illegal_op, 2865706f2543Smrg/* 0xe1 */ x86emuOp2_illegal_op, 2866706f2543Smrg/* 0xe2 */ x86emuOp2_illegal_op, 2867706f2543Smrg/* 0xe3 */ x86emuOp2_illegal_op, 2868706f2543Smrg/* 0xe4 */ x86emuOp2_illegal_op, 2869706f2543Smrg/* 0xe5 */ x86emuOp2_illegal_op, 2870706f2543Smrg/* 0xe6 */ x86emuOp2_illegal_op, 2871706f2543Smrg/* 0xe7 */ x86emuOp2_illegal_op, 2872706f2543Smrg/* 0xe8 */ x86emuOp2_illegal_op, 2873706f2543Smrg/* 0xe9 */ x86emuOp2_illegal_op, 2874706f2543Smrg/* 0xea */ x86emuOp2_illegal_op, 2875706f2543Smrg/* 0xeb */ x86emuOp2_illegal_op, 2876706f2543Smrg/* 0xec */ x86emuOp2_illegal_op, 2877706f2543Smrg/* 0xed */ x86emuOp2_illegal_op, 2878706f2543Smrg/* 0xee */ x86emuOp2_illegal_op, 2879706f2543Smrg/* 0xef */ x86emuOp2_illegal_op, 2880706f2543Smrg 2881706f2543Smrg/* 0xf0 */ x86emuOp2_illegal_op, 2882706f2543Smrg/* 0xf1 */ x86emuOp2_illegal_op, 2883706f2543Smrg/* 0xf2 */ x86emuOp2_illegal_op, 2884706f2543Smrg/* 0xf3 */ x86emuOp2_illegal_op, 2885706f2543Smrg/* 0xf4 */ x86emuOp2_illegal_op, 2886706f2543Smrg/* 0xf5 */ x86emuOp2_illegal_op, 2887706f2543Smrg/* 0xf6 */ x86emuOp2_illegal_op, 2888706f2543Smrg/* 0xf7 */ x86emuOp2_illegal_op, 2889706f2543Smrg/* 0xf8 */ x86emuOp2_illegal_op, 2890706f2543Smrg/* 0xf9 */ x86emuOp2_illegal_op, 2891706f2543Smrg/* 0xfa */ x86emuOp2_illegal_op, 2892706f2543Smrg/* 0xfb */ x86emuOp2_illegal_op, 2893706f2543Smrg/* 0xfc */ x86emuOp2_illegal_op, 2894706f2543Smrg/* 0xfd */ x86emuOp2_illegal_op, 2895706f2543Smrg/* 0xfe */ x86emuOp2_illegal_op, 2896706f2543Smrg/* 0xff */ x86emuOp2_illegal_op, 2897706f2543Smrg}; 2898