📄 op.c
字号:
/* * i386 micro operations * * Copyright (c) 2003 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#define ASM_SOFTMMU#include "exec.h"/* n must be a constant to be efficient */static inline target_long lshift(target_long x, int n){ if (n >= 0) return x << n; else return x >> (-n);}/* we define the various pieces of code used by the JIT */#define REG EAX#define REGNAME _EAX#include "opreg_template.h"#undef REG#undef REGNAME#define REG ECX#define REGNAME _ECX#include "opreg_template.h"#undef REG#undef REGNAME#define REG EDX#define REGNAME _EDX#include "opreg_template.h"#undef REG#undef REGNAME#define REG EBX#define REGNAME _EBX#include "opreg_template.h"#undef REG#undef REGNAME#define REG ESP#define REGNAME _ESP#include "opreg_template.h"#undef REG#undef REGNAME#define REG EBP#define REGNAME _EBP#include "opreg_template.h"#undef REG#undef REGNAME#define REG ESI#define REGNAME _ESI#include "opreg_template.h"#undef REG#undef REGNAME#define REG EDI#define REGNAME _EDI#include "opreg_template.h"#undef REG#undef REGNAME#ifdef TARGET_X86_64#define REG (env->regs[8])#define REGNAME _R8#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[9])#define REGNAME _R9#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[10])#define REGNAME _R10#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[11])#define REGNAME _R11#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[12])#define REGNAME _R12#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[13])#define REGNAME _R13#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[14])#define REGNAME _R14#include "opreg_template.h"#undef REG#undef REGNAME#define REG (env->regs[15])#define REGNAME _R15#include "opreg_template.h"#undef REG#undef REGNAME#endif/* operations with flags *//* update flags with T0 and T1 (add/sub case) */void OPPROTO op_update2_cc(void){ CC_SRC = T1; CC_DST = T0;}/* update flags with T0 (logic operation case) */void OPPROTO op_update1_cc(void){ CC_DST = T0;}void OPPROTO op_update_neg_cc(void){ CC_SRC = -T0; CC_DST = T0;}void OPPROTO op_cmpl_T0_T1_cc(void){ CC_SRC = T1; CC_DST = T0 - T1;}void OPPROTO op_update_inc_cc(void){ CC_SRC = cc_table[CC_OP].compute_c(); CC_DST = T0;}void OPPROTO op_testl_T0_T1_cc(void){ CC_DST = T0 & T1;}/* operations without flags */void OPPROTO op_addl_T0_T1(void){ T0 += T1;}void OPPROTO op_orl_T0_T1(void){ T0 |= T1;}void OPPROTO op_andl_T0_T1(void){ T0 &= T1;}void OPPROTO op_subl_T0_T1(void){ T0 -= T1;}void OPPROTO op_xorl_T0_T1(void){ T0 ^= T1;}void OPPROTO op_negl_T0(void){ T0 = -T0;}void OPPROTO op_incl_T0(void){ T0++;}void OPPROTO op_decl_T0(void){ T0--;}void OPPROTO op_notl_T0(void){ T0 = ~T0;}void OPPROTO op_bswapl_T0(void){ T0 = bswap32(T0);}#ifdef TARGET_X86_64void OPPROTO op_bswapq_T0(void){ helper_bswapq_T0();}#endif/* multiply/divide *//* XXX: add eflags optimizations *//* XXX: add non P4 style flags */void OPPROTO op_mulb_AL_T0(void){ unsigned int res; res = (uint8_t)EAX * (uint8_t)T0; EAX = (EAX & ~0xffff) | res; CC_DST = res; CC_SRC = (res & 0xff00);}void OPPROTO op_imulb_AL_T0(void){ int res; res = (int8_t)EAX * (int8_t)T0; EAX = (EAX & ~0xffff) | (res & 0xffff); CC_DST = res; CC_SRC = (res != (int8_t)res);}void OPPROTO op_mulw_AX_T0(void){ unsigned int res; res = (uint16_t)EAX * (uint16_t)T0; EAX = (EAX & ~0xffff) | (res & 0xffff); EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); CC_DST = res; CC_SRC = res >> 16;}void OPPROTO op_imulw_AX_T0(void){ int res; res = (int16_t)EAX * (int16_t)T0; EAX = (EAX & ~0xffff) | (res & 0xffff); EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); CC_DST = res; CC_SRC = (res != (int16_t)res);}void OPPROTO op_mull_EAX_T0(void){ uint64_t res; res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); EAX = (uint32_t)res; EDX = (uint32_t)(res >> 32); CC_DST = (uint32_t)res; CC_SRC = (uint32_t)(res >> 32);}void OPPROTO op_imull_EAX_T0(void){ int64_t res; res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); EAX = (uint32_t)(res); EDX = (uint32_t)(res >> 32); CC_DST = res; CC_SRC = (res != (int32_t)res);}void OPPROTO op_imulw_T0_T1(void){ int res; res = (int16_t)T0 * (int16_t)T1; T0 = res; CC_DST = res; CC_SRC = (res != (int16_t)res);}void OPPROTO op_imull_T0_T1(void){ int64_t res; res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); T0 = res; CC_DST = res; CC_SRC = (res != (int32_t)res);}#ifdef TARGET_X86_64void OPPROTO op_mulq_EAX_T0(void){ helper_mulq_EAX_T0();}void OPPROTO op_imulq_EAX_T0(void){ helper_imulq_EAX_T0();}void OPPROTO op_imulq_T0_T1(void){ helper_imulq_T0_T1();}#endif/* division, flags are undefined */void OPPROTO op_divb_AL_T0(void){ unsigned int num, den, q, r; num = (EAX & 0xffff); den = (T0 & 0xff); if (den == 0) { raise_exception(EXCP00_DIVZ); } q = (num / den); if (q > 0xff) raise_exception(EXCP00_DIVZ); q &= 0xff; r = (num % den) & 0xff; EAX = (EAX & ~0xffff) | (r << 8) | q;}void OPPROTO op_idivb_AL_T0(void){ int num, den, q, r; num = (int16_t)EAX; den = (int8_t)T0; if (den == 0) { raise_exception(EXCP00_DIVZ); } q = (num / den); if (q != (int8_t)q) raise_exception(EXCP00_DIVZ); q &= 0xff; r = (num % den) & 0xff; EAX = (EAX & ~0xffff) | (r << 8) | q;}void OPPROTO op_divw_AX_T0(void){ unsigned int num, den, q, r; num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); den = (T0 & 0xffff); if (den == 0) { raise_exception(EXCP00_DIVZ); } q = (num / den); if (q > 0xffff) raise_exception(EXCP00_DIVZ); q &= 0xffff; r = (num % den) & 0xffff; EAX = (EAX & ~0xffff) | q; EDX = (EDX & ~0xffff) | r;}void OPPROTO op_idivw_AX_T0(void){ int num, den, q, r; num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); den = (int16_t)T0; if (den == 0) { raise_exception(EXCP00_DIVZ); } q = (num / den); if (q != (int16_t)q) raise_exception(EXCP00_DIVZ); q &= 0xffff; r = (num % den) & 0xffff; EAX = (EAX & ~0xffff) | q; EDX = (EDX & ~0xffff) | r;}void OPPROTO op_divl_EAX_T0(void){ helper_divl_EAX_T0();}void OPPROTO op_idivl_EAX_T0(void){ helper_idivl_EAX_T0();}#ifdef TARGET_X86_64void OPPROTO op_divq_EAX_T0(void){ helper_divq_EAX_T0();}void OPPROTO op_idivq_EAX_T0(void){ helper_idivq_EAX_T0();}#endif/* constant load & misc op *//* XXX: consistent names */void OPPROTO op_movl_T0_imu(void){ T0 = (uint32_t)PARAM1;}void OPPROTO op_movl_T0_im(void){ T0 = (int32_t)PARAM1;}void OPPROTO op_addl_T0_im(void){ T0 += PARAM1;}void OPPROTO op_andl_T0_ffff(void){ T0 = T0 & 0xffff;}void OPPROTO op_andl_T0_im(void){ T0 = T0 & PARAM1;}void OPPROTO op_movl_T0_T1(void){ T0 = T1;}void OPPROTO op_movl_T1_imu(void){ T1 = (uint32_t)PARAM1;}void OPPROTO op_movl_T1_im(void){ T1 = (int32_t)PARAM1;}void OPPROTO op_addl_T1_im(void){ T1 += PARAM1;}void OPPROTO op_movl_T1_A0(void){ T1 = A0;}void OPPROTO op_movl_A0_im(void){ A0 = (uint32_t)PARAM1;}void OPPROTO op_addl_A0_im(void){ A0 = (uint32_t)(A0 + PARAM1);}void OPPROTO op_movl_A0_seg(void){ A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1);}void OPPROTO op_addl_A0_seg(void){ A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1));}void OPPROTO op_addl_A0_AL(void){ A0 = (uint32_t)(A0 + (EAX & 0xff));}#ifdef WORDS_BIGENDIANtypedef union UREG64 { struct { uint16_t v3, v2, v1, v0; } w; struct { uint32_t v1, v0; } l; uint64_t q;} UREG64;#elsetypedef union UREG64 { struct { uint16_t v0, v1, v2, v3; } w; struct { uint32_t v0, v1; } l; uint64_t q;} UREG64;#endif#ifdef TARGET_X86_64#define PARAMQ1 \({\ UREG64 __p;\ __p.l.v1 = PARAM1;\ __p.l.v0 = PARAM2;\ __p.q;\}) void OPPROTO op_movq_T0_im64(void){ T0 = PARAMQ1;}void OPPROTO op_movq_T1_im64(void){ T1 = PARAMQ1;}void OPPROTO op_movq_A0_im(void){ A0 = (int32_t)PARAM1;}void OPPROTO op_movq_A0_im64(void){ A0 = PARAMQ1;}void OPPROTO op_addq_A0_im(void){ A0 = (A0 + (int32_t)PARAM1);}void OPPROTO op_addq_A0_im64(void){ A0 = (A0 + PARAMQ1);}void OPPROTO op_movq_A0_seg(void){ A0 = *(target_ulong *)((char *)env + PARAM1);}void OPPROTO op_addq_A0_seg(void){ A0 += *(target_ulong *)((char *)env + PARAM1);}void OPPROTO op_addq_A0_AL(void){ A0 = (A0 + (EAX & 0xff));}#endifvoid OPPROTO op_andl_A0_ffff(void){ A0 = A0 & 0xffff;}/* memory access */#define MEMSUFFIX _raw#include "ops_mem.h"#if !defined(CONFIG_USER_ONLY)#define MEMSUFFIX _kernel#include "ops_mem.h"#define MEMSUFFIX _user#include "ops_mem.h"#endif/* indirect jump */void OPPROTO op_jmp_T0(void){ EIP = T0;}void OPPROTO op_movl_eip_im(void){ EIP = (uint32_t)PARAM1;}#ifdef TARGET_X86_64void OPPROTO op_movq_eip_im(void){ EIP = (int32_t)PARAM1;}void OPPROTO op_movq_eip_im64(void){ EIP = PARAMQ1;}#endifvoid OPPROTO op_hlt(void){ helper_hlt();}void OPPROTO op_monitor(void){ helper_monitor();}void OPPROTO op_mwait(void){ helper_mwait();}void OPPROTO op_debug(void){ env->exception_index = EXCP_DEBUG; cpu_loop_exit();}void OPPROTO op_raise_interrupt(void){ int intno, next_eip_addend; intno = PARAM1; next_eip_addend = PARAM2; raise_interrupt(intno, 1, 0, next_eip_addend);}void OPPROTO op_raise_exception(void){ int exception_index; exception_index = PARAM1; raise_exception(exception_index);}void OPPROTO op_into(void){ int eflags; eflags = cc_table[CC_OP].compute_all(); if (eflags & CC_O) { raise_interrupt(EXCP04_INTO, 1, 0, PARAM1); } FORCE_RET();}void OPPROTO op_cli(void){ env->eflags &= ~IF_MASK;}void OPPROTO op_sti(void){ env->eflags |= IF_MASK;}void OPPROTO op_set_inhibit_irq(void){ env->hflags |= HF_INHIBIT_IRQ_MASK;}void OPPROTO op_reset_inhibit_irq(void){ env->hflags &= ~HF_INHIBIT_IRQ_MASK;}void OPPROTO op_rsm(void){ helper_rsm();}#if 0/* vm86plus instructions */void OPPROTO op_cli_vm(void){ env->eflags &= ~VIF_MASK;}void OPPROTO op_sti_vm(void){ env->eflags |= VIF_MASK; if (env->eflags & VIP_MASK) { EIP = PARAM1; raise_exception(EXCP0D_GPF); } FORCE_RET();}#endifvoid OPPROTO op_boundw(void){ int low, high, v; low = ldsw(A0); high = ldsw(A0 + 2); v = (int16_t)T0; if (v < low || v > high) { raise_exception(EXCP05_BOUND); } FORCE_RET();}void OPPROTO op_boundl(void){ int low, high, v; low = ldl(A0); high = ldl(A0 + 4); v = T0; if (v < low || v > high) { raise_exception(EXCP05_BOUND); } FORCE_RET();}void OPPROTO op_cmpxchg8b(void){ helper_cmpxchg8b();}void OPPROTO op_movl_T0_0(void){ T0 = 0;}void OPPROTO op_exit_tb(void){ EXIT_TB();}/* multiple size ops */#define ldul ldl#define SHIFT 0#include "ops_template.h"#undef SHIFT#define SHIFT 1#include "ops_template.h"#undef SHIFT#define SHIFT 2#include "ops_template.h"#undef SHIFT#ifdef TARGET_X86_64#define SHIFT 3#include "ops_template.h"#undef SHIFT#endif/* sign extend */void OPPROTO op_movsbl_T0_T0(void){ T0 = (int8_t)T0;}void OPPROTO op_movzbl_T0_T0(void){ T0 = (uint8_t)T0;}void OPPROTO op_movswl_T0_T0(void){ T0 = (int16_t)T0;}void OPPROTO op_movzwl_T0_T0(void){ T0 = (uint16_t)T0;}void OPPROTO op_movswl_EAX_AX(void){ EAX = (uint32_t)((int16_t)EAX);}#ifdef TARGET_X86_64void OPPROTO op_movslq_T0_T0(void){ T0 = (int32_t)T0;}void OPPROTO op_movslq_RAX_EAX(void){ EAX = (int32_t)EAX;}#endifvoid OPPROTO op_movsbw_AX_AL(void){ EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);}void OPPROTO op_movslq_EDX_EAX(void){ EDX = (uint32_t)((int32_t)EAX >> 31);}void OPPROTO op_movswl_DX_AX(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -