windows-nt/Source/XPSP1/NT/base/wow64/mscpu/decoder/comm1632.c
2020-09-26 16:20:57 +08:00

962 lines
24 KiB
C

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
comm1632.c
Abstract:
Instructions with common (shared) WORD, and DWORD flavors (but not BYTE).
Author:
29-Jun-1995 BarryBo
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#include "wx86.h"
#include "config.h"
#include "threadst.h"
#include "instr.h"
#include "decoderp.h"
#include "comm1632.h"
extern OPERATION MANGLENAME(Group1Map)[];
// ---------------- single-byte functions -------------------------------
DISPATCHCOMMON(dispatch2)
{
eipTemp++;
#if MSB==0x8000
((pfnDispatchInstruction)(Dispatch216[GET_BYTE(eipTemp)]))(State, Instr);
#else
((pfnDispatchInstruction)(Dispatch232[GET_BYTE(eipTemp)]))(State, Instr);
#endif
}
DISPATCHCOMMON(LOCKdispatch2)
{
eipTemp++;
#if MSB==0x8000
((pfnDispatchInstruction)(LockDispatch216[GET_BYTE(eipTemp)]))(State, Instr);
#else
((pfnDispatchInstruction)(LockDispatch232[GET_BYTE(eipTemp)]))(State, Instr);
#endif
}
DISPATCHCOMMON(pushf)
{
Instr->Operation = OPNAME(Pushf);
}
DISPATCHCOMMON(popf)
{
Instr->Operation = OPNAME(Popf);
}
DISPATCHCOMMON(pusha)
{
Instr->Operation = OPNAME(PushA);
}
DISPATCHCOMMON(popa)
{
Instr->Operation = OPNAME(PopA);
}
DISPATCHCOMMON(push_iw)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = GET_VAL(eipTemp+1);
Instr->Size = 1+sizeof(UTYPE);
}
DISPATCHCOMMON(push_ibs)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = (UTYPE)(STYPE)(char)GET_BYTE(eipTemp+1);
Instr->Size = 2;
}
DISPATCHCOMMON(GROUP_1WS)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
BYTE g = GET_BYTE(eipTemp+1);
g = (g >> 3) & 0x07;
Instr->Operation = MANGLENAME(Group1Map)[g];
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = (UTYPE)(STYPE)(char)GET_BYTE(eipTemp + cbInstr + 1);
if (g == 7) {
// Cmp takes both params as byval
DEREF(Instr->Operand1);
}
Instr->Size = cbInstr+2;
}
DISPATCHCOMMON(LOCKGROUP_1WS)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
BYTE g = GET_BYTE(eipTemp+1);
g = (g >> 3) & 0x07;
Instr->Operation = MANGLENAME(Group1LockMap)[g];
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = (UTYPE)(STYPE)(char)GET_BYTE(eipTemp + cbInstr + 1);
if (g == 7) {
// Cmp takes both params as byval
DEREF(Instr->Operand1);
}
Instr->Size = cbInstr+2;
}
DISPATCHCOMMON(mov_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Mov);
DEREF(Instr->Operand2);
Instr->Size = cbInstr+1;
}
DISPATCHCOMMON(lea_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Mov);
Instr->Size = cbInstr+1;
}
DISPATCHCOMMON(pop_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(Pop);
Instr->Size = 1+cbInstr;
}
DISPATCHCOMMON(xchg_ax_cx)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = CREG;
}
DISPATCHCOMMON(xchg_ax_dx)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = DREG;
}
DISPATCHCOMMON(xchg_ax_bx)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = BREG;
}
DISPATCHCOMMON(xchg_ax_sp)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = SPREG;
}
DISPATCHCOMMON(xchg_ax_bp)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = BPREG;
}
DISPATCHCOMMON(xchg_ax_si)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = SIREG;
}
DISPATCHCOMMON(xchg_ax_di)
{
Instr->Operation = OPNAME(Xchg);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
Instr->Operand2.Type = OPND_REGREF;
Instr->Operand2.Reg = DIREG;
}
DISPATCHCOMMON(cbw)
{
Instr->Operation = OPNAME(Cbw);
}
DISPATCHCOMMON(cwd)
{
Instr->Operation = OPNAME(Cwd);
}
DISPATCHCOMMON(mov_sp_iw)
{
Instr->Operation = OPNAME(Mov);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SPREG;
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_VAL(eipTemp+1);
Instr->Size = 1+sizeof(UTYPE);
}
DISPATCHCOMMON(mov_bp_iw)
{
Instr->Operation = OPNAME(Mov);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BPREG;
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_VAL(eipTemp+1);
Instr->Size = 1+sizeof(UTYPE);
}
DISPATCHCOMMON(mov_si_iw)
{
Instr->Operation = OPNAME(Mov);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SIREG;
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_VAL(eipTemp+1);
Instr->Size = 1+sizeof(UTYPE);
}
DISPATCHCOMMON(mov_di_iw)
{
Instr->Operation = OPNAME(Mov);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DIREG;
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_VAL(eipTemp+1);
Instr->Size = 1+sizeof(UTYPE);
}
DISPATCHCOMMON(loopne_b)
{
Instr->Operand1.Type = OPND_NOCODEGEN;
Instr->Operand1.Immed = (CHAR)GET_BYTE(eipTemp+1)+2+eipTemp;
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OPNAME(CTRL_COND_Loopne_bFwd);
} else {
Instr->Operation = OPNAME(CTRL_COND_Loopne_b);
}
Instr->Size = 2;
}
DISPATCHCOMMON(loope_b)
{
Instr->Operand1.Type = OPND_NOCODEGEN;
Instr->Operand1.Immed = (CHAR)GET_BYTE(eipTemp+1)+2+eipTemp;
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OPNAME(CTRL_COND_Loope_bFwd);
} else {
Instr->Operation = OPNAME(CTRL_COND_Loope_b);
}
Instr->Size = 2;
}
DISPATCHCOMMON(loop_b)
{
Instr->Operand1.Type = OPND_NOCODEGEN;
Instr->Operand1.Immed = (CHAR)GET_BYTE(eipTemp+1)+2+eipTemp;
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OPNAME(CTRL_COND_Loop_bFwd);
} else {
Instr->Operation = OPNAME(CTRL_COND_Loop_b);
}
Instr->Size = 2;
}
DISPATCHCOMMON(jcxz_b)
{
Instr->Operand1.Type = OPND_NOCODEGEN;
if (State->AdrPrefix) {
// "ADR: jecxz" is the same as "DATA: jecxz"... which is "jcxz"
Instr->Operand1.Immed = MAKELONG((char)GET_BYTE(eipTemp+1)+2+(short)LOWORD(eipTemp), HIWORD(eipTemp));
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OP_CTRL_COND_Jcxz_bFwd16;
} else {
Instr->Operation = OP_CTRL_COND_Jcxz_b16;
}
#if DBG
State->AdrPrefix = FALSE;
#endif
} else {
Instr->Operand1.Immed = (CHAR)GET_BYTE(eipTemp+1)+2+eipTemp;
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OPNAME(CTRL_COND_Jcxz_bFwd);
} else {
Instr->Operation = OPNAME(CTRL_COND_Jcxz_b);
}
}
Instr->Size = 2;
}
DISPATCHCOMMON(GROUP_5)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
BYTE g = GET_BYTE(eipTemp+1);
switch ((g >> 3) & 0x07) {
case 0: // inc modrmW
Instr->Operation = OPNAME(Inc);
break;
case 1: // dec modrmW
Instr->Operation = OPNAME(Dec);
break;
case 2: // call indirmodrmW
DEREF(Instr->Operand1);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = eipTemp + cbInstr + 1;
Instr->Operation = OP_CTRL_INDIR_Call;
break;
case 3: // call indirFARmodrmW
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = eipTemp + cbInstr + 1;
Instr->Operation = OP_CTRL_INDIR_Callf;
break;
case 4: // jmp indirmodrmW
DEREF(Instr->Operand1);
Instr->Operation = OP_CTRL_INDIR_Jmp;
break;
case 5: // jmp indirFARmodrmW
Instr->Operation = OP_CTRL_INDIR_Jmpf;
break;
case 6: // push modrmW
DEREF(Instr->Operand1);
Instr->Operation = OPNAME(Push);
break;
case 7: // bad
BAD_INSTR;
break;
}
Instr->Size = cbInstr+1;
}
DISPATCHCOMMON(LOCKGROUP_5)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
BYTE g = GET_BYTE(eipTemp+1);
switch ((g >> 3) & 0x07) {
case 0: // inc modrmW
Instr->Operation = LOCKOPNAME(Inc);
break;
case 1: // dec modrmW
Instr->Operation = LOCKOPNAME(Dec);
break;
default:
BAD_INSTR;
break;
}
Instr->Size = cbInstr+1;
}
DISPATCHCOMMON(inc_ax)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
}
DISPATCHCOMMON(inc_cx)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = CREG;
}
DISPATCHCOMMON(inc_dx)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DREG;
}
DISPATCHCOMMON(inc_bx)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BREG;
}
DISPATCHCOMMON(inc_sp)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SPREG;
}
DISPATCHCOMMON(inc_bp)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BPREG;
}
DISPATCHCOMMON(inc_si)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SIREG;
}
DISPATCHCOMMON(inc_di)
{
Instr->Operation = OPNAME(Inc);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DIREG;
}
DISPATCHCOMMON(dec_ax)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
}
DISPATCHCOMMON(dec_cx)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = CREG;
}
DISPATCHCOMMON(dec_dx)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DREG;
}
DISPATCHCOMMON(dec_bx)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BREG;
}
DISPATCHCOMMON(dec_sp)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SPREG;
}
DISPATCHCOMMON(dec_bp)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BPREG;
}
DISPATCHCOMMON(dec_si)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SIREG;
}
DISPATCHCOMMON(dec_di)
{
Instr->Operation = OPNAME(Dec);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DIREG;
}
DISPATCHCOMMON(push_ax)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = AREG;
}
DISPATCHCOMMON(push_cx)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = CREG;
}
DISPATCHCOMMON(push_dx)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = DREG;
}
DISPATCHCOMMON(push_bx)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = BREG;
}
DISPATCHCOMMON(push_sp)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = SPREG;
}
DISPATCHCOMMON(push_bp)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = BPREG;
}
DISPATCHCOMMON(push_si)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = SIREG;
}
DISPATCHCOMMON(push_di)
{
Instr->Operation = OPNAME(Push);
Instr->Operand1.Type = OPND_REGVALUE;
Instr->Operand1.Reg = DIREG;
}
DISPATCHCOMMON(pop_ax)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = AREG;
}
DISPATCHCOMMON(pop_cx)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = CREG;
}
DISPATCHCOMMON(pop_dx)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DREG;
}
DISPATCHCOMMON(pop_bx)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BREG;
}
DISPATCHCOMMON(pop_sp)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SPREG;
}
DISPATCHCOMMON(pop_bp)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = BPREG;
}
DISPATCHCOMMON(pop_si)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = SIREG;
}
DISPATCHCOMMON(pop_di)
{
Instr->Operation = OPNAME(Pop);
Instr->Operand1.Type = OPND_REGREF;
Instr->Operand1.Reg = DIREG;
}
DISPATCHCOMMON(bound)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
Instr->Operation = OPNAME(Bound);
Instr->Operand2.Type = OPND_REGVALUE;
Instr->Size = 1+cbInstr;
}
DISPATCHCOMMON(retn_i)
{
Instr->Operation = OPNAME(CTRL_INDIR_Retn_i);
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = (DWORD)GET_SHORT(eipTemp+1);
Instr->Size = 3;
}
DISPATCHCOMMON(retn)
{
Instr->Operation = OPNAME(CTRL_INDIR_Retn);
}
DISPATCHCOMMON(retf_i)
{
Instr->Operation = OPNAME(CTRL_INDIR_Retf_i);
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = (DWORD)GET_SHORT(eipTemp+1);
Instr->Size = 3;
}
DISPATCHCOMMON(retf)
{
Instr->Operation = OPNAME(CTRL_INDIR_Retf);
}
DISPATCHCOMMON(enter)
{
Instr->Operation = OPNAME(Enter);
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = GET_BYTE(eipTemp+3); // Nesting Level
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_SHORT(eipTemp+1); // Stack bytes to alloc
Instr->Size = 4;
}
DISPATCHCOMMON(leave)
{
Instr->Operation = OPNAME(Leave);
}
//-------- double-byte functions -----------------------------------------------
DISPATCHCOMMON(GROUP_8)
{
BYTE g = GET_BYTE(eipTemp+1);
int cbInstr;
switch ((g >> 3) & 0x07) {
case 0: // bad
case 1: // bad
case 2: // bad
case 3: // bad
BAD_INSTR;
break;
case 4: // bt modrmw immb
// Note: the difference between the Reg and Mem version of the btx
// fragments is that the Reg version completely ignores any bits in the
// second operand beyond the fifth bit. In contrast, the Mem version uses
// them together with the first operand to determine the memory address.
// When the second operand is an immediate, the correct thing to do is to
// ignore them, and so we call the Reg version all the time.
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(BtReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
case 5: // bts modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(BtsReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
case 6: // btr modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(BtrReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
case 7: // btc modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(BtcReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
}
}
DISPATCHCOMMON(LOCKGROUP_8)
{
BYTE g = GET_BYTE(eipTemp+1);
int cbInstr;
switch ((g >> 3) & 0x07) {
case 0: // bad
case 1: // bad
case 2: // bad
case 3: // bad
case 4: // bt modrmw immb
BAD_INSTR;
break;
case 5: // bts modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = LOCKOPNAME(BtsReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
case 6: // btr modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = LOCKOPNAME(BtrReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
case 7: // btc modrmw immb
cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
Instr->Operation = LOCKOPNAME(BtcReg);
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = cbInstr+3;
break;
}
}
DISPATCHCOMMON(movzx_regw_modrmb)
{
int cbInstr = mod_rm_reg8(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(Movzx8To);
Instr->Operand2.Type = OPND_NOCODEGEN;
Instr->Operand2.Reg = GET_REG(eipTemp+1);
DEREF8(Instr->Operand1);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(movsx_regw_modrmb)
{
int cbInstr = mod_rm_reg8(State, &Instr->Operand1, NULL);
Instr->Operation = OPNAME(Movsx8To);
Instr->Operand2.Type = OPND_NOCODEGEN;
Instr->Operand2.Reg = GET_REG(eipTemp+1);
DEREF8(Instr->Operand1);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(les_rw_mw)
{
if ((GET_BYTE(eipTemp+1) & 0xc7) == 0xc4) {
//
// BOP instruction
//
PBOPINSTR Bop = (PBOPINSTR)eipTemp;
Instr->Size = sizeof(BOPINSTR);
if (Bop->BopNum == 0xfe) {
//
// BOP FE - Unsimulate
//
Instr->Operation = OP_Unsimulate;
} else {
//
// Generate a BOP.
//
if (Bop->Flags & BOPFL_ENDCODE) {
//
// This BOP is flagged as being the end of Intel code.
// This is typically BOP FD in x86-to-Risc callbacks.
//
Instr->Operation = OP_BOP_STOP_DECODE;
} else {
Instr->Operation = OP_BOP;
}
}
} else {
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Les);
Instr->Size = 1+cbInstr;
}
}
DISPATCHCOMMON(lds_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lds);
Instr->Size = 1+cbInstr;
}
DISPATCHCOMMON(lss_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lss);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(lfs_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lfs);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(lgs_rw_mw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lgs);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(bts_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
Instr->Operation = OPNAME(BtsReg);
} else {
Instr->Operation = OPNAME(BtsMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(btr_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
Instr->Operation = OPNAME(BtrReg);
} else {
Instr->Operation = OPNAME(BtrMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(btc_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
Instr->Operation = OPNAME(BtcReg);
} else {
Instr->Operation = OPNAME(BtcMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(LOCKbts_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
BAD_INSTR;
} else {
Instr->Operation = LOCKOPNAME(BtsMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(LOCKbtr_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
BAD_INSTR;
} else {
Instr->Operation = LOCKOPNAME(BtrMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(LOCKbtc_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
BAD_INSTR;
} else {
Instr->Operation = LOCKOPNAME(BtcMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(bt_m_r)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
DEREF(Instr->Operand2);
if (Instr->Operand1.Type == OPND_REGREF){
Instr->Operation = OPNAME(BtReg);
} else {
Instr->Operation = OPNAME(BtMem);
}
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(call_rel)
{
Instr->Operation = OP_CTRL_UNCOND_Call;
Instr->Operand1.Type = OPND_IMM;
Instr->Operand1.Immed = (STYPE)GET_VAL(eipTemp+1) + sizeof(UTYPE) + 1 + eipTemp;
Instr->Operand2.Type = OPND_IMM;
Instr->Operand2.Immed = eipTemp + sizeof(UTYPE) + 1;
Instr->Size = sizeof(UTYPE) + 1;
}
DISPATCHCOMMON(jmp_rel)
{
Instr->Operand1.Type = OPND_NOCODEGEN;
if (State->AdrPrefix) {
short IP;
// get the 16-bit loword from the 32-bit immediate value following
// the JMP instruction, and add that value to the loword of EIP, and
// use that value as the new IP register.
IP = (short)GET_SHORT(eipTemp+1) +
sizeof(UTYPE) + 1 + (short)LOWORD(eipTemp);
Instr->Operand1.Immed = MAKELONG(IP, HIWORD(eipTemp));
#if DBG
State->AdrPrefix = FALSE;
#endif
} else {
Instr->Operand1.Immed = (STYPE)GET_VAL(eipTemp+1) +
sizeof(UTYPE) + 1 + eipTemp;
}
if (Instr->Operand1.Immed > eipTemp) {
Instr->Operation = OP_CTRL_UNCOND_JmpFwd;
} else {
Instr->Operation = OP_CTRL_UNCOND_Jmp;
}
Instr->Size = sizeof(UTYPE) + 1;
}
DISPATCHCOMMON(shld_regw_modrmw_immb)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
Instr->Operation = OPNAME(Shld);
DEREF(Instr->Operand2);
Instr->Operand3.Type = OPND_IMM;
Instr->Operand3.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = 3+cbInstr;
}
DISPATCHCOMMON(shld_regw_modrmw_cl)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
Instr->Operation = OPNAME(Shld);
DEREF(Instr->Operand2);
Instr->Operand3.Type = OPND_REGVALUE;
Instr->Operand3.Reg = GP_CL;
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(shrd_regw_modrmw_immb)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
Instr->Operation = OPNAME(Shrd);
DEREF(Instr->Operand2);
Instr->Operand3.Type = OPND_IMM;
Instr->Operand3.Immed = GET_BYTE(eipTemp+cbInstr+1);
Instr->Size = 3+cbInstr;
}
DISPATCHCOMMON(shrd_regw_modrmw_cl)
{
int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
Instr->Operation = OPNAME(Shrd);
DEREF(Instr->Operand2);
Instr->Operand3.Type = OPND_REGVALUE;
Instr->Operand3.Reg = GP_CL;
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(bsr_modrmw_regw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Bsr);
DEREF(Instr->Operand2);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(bsf_modrmw_regw)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Bsf);
DEREF(Instr->Operand2);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(lar)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lar);
DEREF(Instr->Operand2);
Instr->Size = 2+cbInstr;
}
DISPATCHCOMMON(lsl)
{
int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
Instr->Operation = OPNAME(Lsl);
DEREF(Instr->Operand2);
Instr->Size = 2+cbInstr;
}