diff options
Diffstat (limited to 'x86emu/ops2.c')
-rw-r--r-- | x86emu/ops2.c | 164 |
1 files changed, 128 insertions, 36 deletions
diff --git a/x86emu/ops2.c b/x86emu/ops2.c index 7cb585b..39bd041 100644 --- a/x86emu/ops2.c +++ b/x86emu/ops2.c @@ -37,10 +37,15 @@ * instructions. * ****************************************************************************/ -/* $XFree86: xc/extras/x86emu/src/x86emu/ops2.c,v 1.6tsi Exp $ */ #include "x86emu/x86emui.h" +#undef bswap_32 +#define bswap_32(x) (((x & 0xff000000) >> 24) | \ + ((x & 0x00ff0000) >> 8) | \ + ((x & 0x0000ff00) << 8) | \ + ((x & 0x000000ff) << 24)) + /*----------------------------- Implementation ----------------------------*/ /**************************************************************************** @@ -66,12 +71,46 @@ static void x86emuOp2_illegal_op( /**************************************************************************** REMARKS: +Handles opcode 0x0f,0x31 +****************************************************************************/ +static void x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2)) +{ +#ifdef __HAS_LONG_LONG__ + static u64 counter = 0; +#else + static u32 counter = 0; +#endif + + counter += 0x10000; + + /* read timestamp counter */ + /* + * Note that instead of actually trying to accurately measure this, we just + * increase the counter by a fixed amount every time we hit one of these + * instructions. Feel free to come up with a better method. + */ + START_OF_INSTR(); + DECODE_PRINTF("RDTSC\n"); + TRACE_AND_STEP(); +#ifdef __HAS_LONG_LONG__ + M.x86.R_EAX = counter & 0xffffffff; + M.x86.R_EDX = counter >> 32; +#else + M.x86.R_EAX = counter; + M.x86.R_EDX = 0; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: Handles opcode 0x0f,0x80-0x8F ****************************************************************************/ static void x86emuOp2_long_jump(u8 op2) { s32 target; - char *name = 0; + char *name = NULL; int cond = 0; /* conditional jump to word offset. */ @@ -131,7 +170,7 @@ static void x86emuOp2_long_jump(u8 op2) break; case 0x8d: name = "JNL\t"; - cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); + cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); break; case 0x8e: name = "JLE\t"; @@ -165,7 +204,7 @@ static void x86emuOp2_set_byte(u8 op2) int mod, rl, rh; uint destoffset; u8 *destreg; - char *name = 0; + char *name = NULL; int cond = 0; START_OF_INSTR(); @@ -295,6 +334,20 @@ static void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2)) } /**************************************************************************** +REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output +Handles opcode 0x0f,0xa2 +****************************************************************************/ +static void x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("CPUID\n"); + TRACE_AND_STEP(); + cpuid(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** REMARKS: Handles opcode 0x0f,0xa3 ****************************************************************************/ @@ -700,10 +753,9 @@ static void x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2)) END_OF_INSTR(); } -#if 0 /**************************************************************************** REMARKS: -Handles opcode 0x0f,0xaa +Handles opcode 0x0f,0xab ****************************************************************************/ static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2)) { @@ -839,7 +891,6 @@ static void x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2)) DECODE_CLEAR_SEGOVR(); END_OF_INSTR(); } -#endif /**************************************************************************** REMARKS: @@ -2132,7 +2183,7 @@ static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2)) uint srcoffset; START_OF_INSTR(); - DECODE_PRINTF("BSF\n"); + DECODE_PRINTF("BSF\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch(mod) { case 0: @@ -2212,25 +2263,25 @@ static void x86emuOp2_bsf(u8 X86EMU_UNUSED(op2)) break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { - u32 *srcreg, *dstreg; + u32 srcval, *dstreg; - srcreg = DECODE_RM_LONG_REGISTER(rl); + srcval = *DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); - CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 32; (*dstreg)++) - if ((*srcreg >> *dstreg) & 1) break; + if ((srcval >> *dstreg) & 1) break; } else { - u16 *srcreg, *dstreg; + u16 srcval, *dstreg; - srcreg = DECODE_RM_WORD_REGISTER(rl); + srcval = *DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); - CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 0; *dstreg < 16; (*dstreg)++) - if ((*srcreg >> *dstreg) & 1) break; + if ((srcval >> *dstreg) & 1) break; } break; } @@ -2248,7 +2299,7 @@ static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2)) uint srcoffset; START_OF_INSTR(); - DECODE_PRINTF("BSF\n"); + DECODE_PRINTF("BSR\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch(mod) { case 0: @@ -2328,25 +2379,25 @@ static void x86emuOp2_bsr(u8 X86EMU_UNUSED(op2)) break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { - u32 *srcreg, *dstreg; + u32 srcval, *dstreg; - srcreg = DECODE_RM_LONG_REGISTER(rl); + srcval = *DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); - CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 31; *dstreg > 0; (*dstreg)--) - if ((*srcreg >> *dstreg) & 1) break; + if ((srcval >> *dstreg) & 1) break; } else { - u16 *srcreg, *dstreg; + u16 srcval, *dstreg; - srcreg = DECODE_RM_WORD_REGISTER(rl); + srcval = *DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); dstreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); - CONDITIONAL_SET_FLAG(*srcreg == 0, F_ZF); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); for(*dstreg = 15; *dstreg > 0; (*dstreg)--) - if ((*srcreg >> *dstreg) & 1) break; + if ((srcval >> *dstreg) & 1) break; } break; } @@ -2526,6 +2577,47 @@ static void x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2)) END_OF_INSTR(); } +/* Handles opcodes 0xc8-0xcf */ +static void x86emuOp2_bswap(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("BSWAP\n"); + TRACE_AND_STEP(); + + switch (op2) { + case 0xc8: + M.x86.R_EAX = bswap_32(M.x86.R_EAX); + break; + case 0xc9: + M.x86.R_ECX = bswap_32(M.x86.R_ECX); + break; + case 0xca: + M.x86.R_EDX = bswap_32(M.x86.R_EDX); + break; + case 0xcb: + M.x86.R_EBX = bswap_32(M.x86.R_EBX); + break; + case 0xcc: + M.x86.R_ESP = bswap_32(M.x86.R_ESP); + break; + case 0xcd: + M.x86.R_EBP = bswap_32(M.x86.R_EBP); + break; + case 0xce: + M.x86.R_ESI = bswap_32(M.x86.R_ESI); + break; + case 0xcf: + M.x86.R_EDI = bswap_32(M.x86.R_EDI); + break; + default: + /* can't happen */ + break; + } + + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + /*************************************************************************** * Double byte operation code table: **************************************************************************/ @@ -2583,7 +2675,7 @@ void (*x86emu_optab2[256])(u8) = /* 0x2f */ x86emuOp2_illegal_op, /* 0x30 */ x86emuOp2_illegal_op, -/* 0x31 */ x86emuOp2_illegal_op, +/* 0x31 */ x86emuOp2_rdtsc, /* 0x32 */ x86emuOp2_illegal_op, /* 0x33 */ x86emuOp2_illegal_op, /* 0x34 */ x86emuOp2_illegal_op, @@ -2703,7 +2795,7 @@ void (*x86emu_optab2[256])(u8) = /* 0xa0 */ x86emuOp2_push_FS, /* 0xa1 */ x86emuOp2_pop_FS, -/* 0xa2 */ x86emuOp2_illegal_op, +/* 0xa2 */ x86emuOp2_cpuid, /* 0xa3 */ x86emuOp2_bt_R, /* 0xa4 */ x86emuOp2_shld_IMM, /* 0xa5 */ x86emuOp2_shld_CL, @@ -2712,7 +2804,7 @@ void (*x86emu_optab2[256])(u8) = /* 0xa8 */ x86emuOp2_push_GS, /* 0xa9 */ x86emuOp2_pop_GS, /* 0xaa */ x86emuOp2_illegal_op, -/* 0xab */ x86emuOp2_bt_R, +/* 0xab */ x86emuOp2_bts_R, /* 0xac */ x86emuOp2_shrd_IMM, /* 0xad */ x86emuOp2_shrd_CL, /* 0xae */ x86emuOp2_illegal_op, @@ -2743,14 +2835,14 @@ void (*x86emu_optab2[256])(u8) = /* 0xc5 */ x86emuOp2_illegal_op, /* 0xc6 */ x86emuOp2_illegal_op, /* 0xc7 */ x86emuOp2_illegal_op, -/* 0xc8 */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xc9 */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xca */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xcb */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xcc */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xcd */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xce */ x86emuOp2_illegal_op, /* TODO: bswap */ -/* 0xcf */ x86emuOp2_illegal_op, /* TODO: bswap */ +/* 0xc8 */ x86emuOp2_bswap, +/* 0xc9 */ x86emuOp2_bswap, +/* 0xca */ x86emuOp2_bswap, +/* 0xcb */ x86emuOp2_bswap, +/* 0xcc */ x86emuOp2_bswap, +/* 0xcd */ x86emuOp2_bswap, +/* 0xce */ x86emuOp2_bswap, +/* 0xcf */ x86emuOp2_bswap, /* 0xd0 */ x86emuOp2_illegal_op, /* 0xd1 */ x86emuOp2_illegal_op, |