📄 ops2.c
字号:
/****************************************************************************** Realmode X86 Emulator Library** Copyright (C) 1996-1999 SciTech Software, Inc.* Copyright (C) David Mosberger-Tang* Copyright (C) 1999 Egbert Eich** ========================================================================** Permission to use, copy, modify, distribute, and sell this software and* its documentation for any purpose is hereby granted without fee,* provided that the above copyright notice appear in all copies and that* both that copyright notice and this permission notice appear in* supporting documentation, and that the name of the authors not be used* in advertising or publicity pertaining to distribution of the software* without specific, written prior permission. The authors makes no* representations about the suitability of this software for any purpose.* It is provided "as is" without express or implied warranty.** THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR* PERFORMANCE OF THIS SOFTWARE.** ========================================================================** Language: ANSI C* Environment: Any* Developer: Kendall Bennett** Description: This file includes subroutines to implement the decoding* and emulation of all the x86 extended two-byte processor* instructions.*****************************************************************************/#include "x86emu/x86emui.h"/*----------------------------- Implementation ----------------------------*//****************************************************************************PARAMETERS:op1 - Instruction op codeREMARKS:Handles illegal opcodes.****************************************************************************/void x86emuOp2_illegal_op( u8 op2){ START_OF_INSTR(); DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); TRACE_REGS(); printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n", M.x86.R_CS, M.x86.R_IP-2,op2); HALT_SYS(); END_OF_INSTR();}#define xorl(a,b) ((a) && !(b)) || (!(a) && (b))/****************************************************************************REMARKS:Handles opcode 0x0f,0x80-0x8F****************************************************************************/void x86emuOp2_long_jump(u8 op2){ s32 target; char *name = 0; int cond = 0; /* conditional jump to word offset. */ START_OF_INSTR(); switch (op2) { case 0x80: name = "JO\t"; cond = ACCESS_FLAG(F_OF); break; case 0x81: name = "JNO\t"; cond = !ACCESS_FLAG(F_OF); break; case 0x82: name = "JB\t"; cond = ACCESS_FLAG(F_CF); break; case 0x83: name = "JNB\t"; cond = !ACCESS_FLAG(F_CF); break; case 0x84: name = "JZ\t"; cond = ACCESS_FLAG(F_ZF); break; case 0x85: name = "JNZ\t"; cond = !ACCESS_FLAG(F_ZF); break; case 0x86: name = "JBE\t"; cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); break; case 0x87: name = "JNBE\t"; cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); break; case 0x88: name = "JS\t"; cond = ACCESS_FLAG(F_SF); break; case 0x89: name = "JNS\t"; cond = !ACCESS_FLAG(F_SF); break; case 0x8a: name = "JP\t"; cond = ACCESS_FLAG(F_PF); break; case 0x8b: name = "JNP\t"; cond = !ACCESS_FLAG(F_PF); break; case 0x8c: name = "JL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x8d: name = "JNL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x8e: name = "JLE\t"; cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; case 0x8f: name = "JNLE\t"; cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; } DECODE_PRINTF(name); target = (s16) fetch_word_imm(); target += (s16) M.x86.R_IP; DECODE_PRINTF2("%04x\n", target); TRACE_AND_STEP(); if (cond) M.x86.R_IP = (u16)target; DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x0f,0x90-0x9F****************************************************************************/void x86emuOp2_set_byte(u8 op2){ int mod, rl, rh; uint destoffset; u8 *destreg; char *name = 0; int cond = 0; START_OF_INSTR(); switch (op2) { case 0x90: name = "SETO\t"; cond = ACCESS_FLAG(F_OF); break; case 0x91: name = "SETNO\t"; cond = !ACCESS_FLAG(F_OF); break; case 0x92: name = "SETB\t"; cond = ACCESS_FLAG(F_CF); break; case 0x93: name = "SETNB\t"; cond = !ACCESS_FLAG(F_CF); break; case 0x94: name = "SETZ\t"; cond = ACCESS_FLAG(F_ZF); break; case 0x95: name = "SETNZ\t"; cond = !ACCESS_FLAG(F_ZF); break; case 0x96: name = "SETBE\t"; cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); break; case 0x97: name = "SETNBE\t"; cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); break; case 0x98: name = "SETS\t"; cond = ACCESS_FLAG(F_SF); break; case 0x99: name = "SETNS\t"; cond = !ACCESS_FLAG(F_SF); break; case 0x9a: name = "SETP\t"; cond = ACCESS_FLAG(F_PF); break; case 0x9b: name = "SETNP\t"; cond = !ACCESS_FLAG(F_PF); break; case 0x9c: name = "SETL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x9d: name = "SETNL\t"; cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); break; case 0x9e: name = "SETLE\t"; cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; case 0x9f: name = "SETNLE\t"; cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || ACCESS_FLAG(F_ZF)); break; } DECODE_PRINTF(name); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: destoffset = decode_rm00_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 1: destoffset = decode_rm01_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 2: destoffset = decode_rm10_address(rl); TRACE_AND_STEP(); store_data_byte(destoffset, cond ? 0x01 : 0x00); break; case 3: /* register to register */ destreg = DECODE_RM_BYTE_REGISTER(rl); TRACE_AND_STEP(); *destreg = cond ? 0x01 : 0x00; break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x0f,0xa0****************************************************************************/void x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2)){ START_OF_INSTR(); DECODE_PRINTF("PUSH\tFS\n"); TRACE_AND_STEP(); push_word(M.x86.R_FS); DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x0f,0xa1****************************************************************************/void x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2)){ START_OF_INSTR(); DECODE_PRINTF("POP\tFS\n"); TRACE_AND_STEP(); M.x86.R_FS = pop_word(); DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x0f,0xa3****************************************************************************/void x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2)){ int mod, rl, rh; uint srcoffset; int bit,disp; START_OF_INSTR(); DECODE_PRINTF("BT\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 srcval; u32 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; disp = (s16)*shiftreg >> 5; srcval = fetch_data_long(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } else { u16 srcval; u16 *shiftreg; srcoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; disp = (s16)*shiftreg >> 4; srcval = fetch_data_word(srcoffset+disp); CONDITIONAL_SET_FLAG(srcval & (0x1 << bit),F_CF); } break; case 3: /* register to register */ if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 *srcreg,*shiftreg; srcreg = DECODE_RM_LONG_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0x1F; CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); } else { u16 *srcreg,*shiftreg; srcreg = DECODE_RM_WORD_REGISTER(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); TRACE_AND_STEP(); bit = *shiftreg & 0xF; CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit),F_CF); } break; } DECODE_CLEAR_SEGOVR(); END_OF_INSTR();}/****************************************************************************REMARKS:Handles opcode 0x0f,0xa4****************************************************************************/void x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2)){ int mod, rl, rh; uint destoffset; u8 shift; START_OF_INSTR(); DECODE_PRINTF("SHLD\t"); FETCH_DECODE_MODRM(mod, rh, rl); switch (mod) { case 0: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm00_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 1: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_long(destoffset); destval = shld_long(destval,*shiftreg,shift); store_data_long(destoffset, destval); } else { u16 destval; u16 *shiftreg; destoffset = decode_rm01_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_WORD_REGISTER(rh); DECODE_PRINTF(","); shift = fetch_byte_imm(); DECODE_PRINTF2("%d\n", shift); TRACE_AND_STEP(); destval = fetch_data_word(destoffset); destval = shld_word(destval,*shiftreg,shift); store_data_word(destoffset, destval); } break; case 2: if (M.x86.mode & SYSMODE_PREFIX_DATA) { u32 destval; u32 *shiftreg; destoffset = decode_rm10_address(rl); DECODE_PRINTF(","); shiftreg = DECODE_RM_LONG_REGISTER(rh); DECODE_PRINTF(",");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -