mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:05:42 +00:00
[X86EMU]
Beginning of a real mode x86 emulator for BIOS calls. svn path=/branches/ros-amd64-bringup/; revision=45464
This commit is contained in:
parent
6bfc56886a
commit
b63bed2d38
8 changed files with 850 additions and 0 deletions
12
reactos/lib/x86emu/op_cmp.h
Normal file
12
reactos/lib/x86emu/op_cmp.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_3D_CMP(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
USHORT Value;
|
||||
|
||||
Value = *(USHORT*)(IntructionPointer + 1);
|
||||
VmState_CMP16(VmState, VmState->Registers.Eax, Value);
|
||||
VmState_AdvanceIp(VmState, 3);
|
||||
DPRINT("CMP AX, 0x%x\n", Value);
|
||||
}
|
39
reactos/lib/x86emu/op_jump.h
Normal file
39
reactos/lib/x86emu/op_jump.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_E9_JMP16(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
SHORT Offset;
|
||||
|
||||
Offset = *(PSHORT)(IntructionPointer + 1);
|
||||
DPRINT("JMP %04x\n", VmState->Registers.Ip + Offset + 3);
|
||||
VmState_AdvanceIp(VmState, Offset + 3);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_75_JNZ8(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("JNZ %04x\n", VmState->Registers.Ip + IntructionPointer[1] + 2);
|
||||
|
||||
if (!VmState->Registers.Eflags.Zf)
|
||||
{
|
||||
VmState_AdvanceIp(VmState, IntructionPointer[1] + 2);
|
||||
}
|
||||
else
|
||||
VmState_AdvanceIp(VmState, 2);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_74_JZ8(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("JZ %04x\n", VmState->Registers.Ip + IntructionPointer[1] + 2);
|
||||
|
||||
if (VmState->Registers.Eflags.Zf)
|
||||
{
|
||||
VmState_AdvanceIp(VmState, IntructionPointer[1] + 2);
|
||||
}
|
||||
else
|
||||
VmState_AdvanceIp(VmState, 2);
|
||||
}
|
45
reactos/lib/x86emu/op_mov.h
Normal file
45
reactos/lib/x86emu/op_mov.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_BB_MOV(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
USHORT Value;
|
||||
|
||||
Value = *(USHORT*)(IntructionPointer + 1);
|
||||
VmState->Registers.Bx = Value;
|
||||
VmState_AdvanceIp(VmState, 3);
|
||||
DPRINT("MOV BX, 0x%x\n", Value);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_8E_MOV(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
MODRM ModRm;
|
||||
UCHAR Value;
|
||||
|
||||
ModRm.Byte = IntructionPointer[1];
|
||||
|
||||
if (ModRm.mod == 3)
|
||||
{
|
||||
DPRINT("MOV ??, ??\n", IntructionPointer[2]);
|
||||
Value = VmState_GetVal8(VmState, ModRm);
|
||||
// ...
|
||||
VmState_AdvanceIp(VmState, 2);
|
||||
return;
|
||||
}
|
||||
DPRINT1("UNKNOWN\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_89_MOV(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
MODRM ModRm;
|
||||
USHORT Value;
|
||||
|
||||
ModRm.Byte = IntructionPointer[1];
|
||||
Value = VmState_GetRegVal16(VmState, ModRm);
|
||||
|
||||
VmState_AdvanceIp(VmState, 2);
|
||||
}
|
110
reactos/lib/x86emu/op_stack.h
Normal file
110
reactos/lib/x86emu/op_stack.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_9C_PUSHF(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("PUSHF\n");
|
||||
VmState_Push(VmState, VmState->Registers.Eflags.Short);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_9D_POPF(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("POPF\n");
|
||||
VmState->Registers.Eflags.Short = VmState_Pop(VmState);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_1E_PUSH_DS(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("PUSH DS\n");
|
||||
VmState_Push(VmState, VmState->Registers.SegDs);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_1F_POP_DS(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("POP DS\n");
|
||||
VmState->Registers.SegDs = VmState_Pop(VmState);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_06_PUSH_ES(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("PUSH ES\n");
|
||||
VmState_Push(VmState, VmState->Registers.SegEs);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_07_POP_ES(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("POP ES\n");
|
||||
VmState->Registers.SegEs = VmState_Pop(VmState);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_60_PUSHA(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
USHORT OrigSp;
|
||||
DPRINT("PUSHA\n");
|
||||
|
||||
OrigSp = VmState->Registers.Sp;
|
||||
VmState_Push(VmState, VmState->Registers.Ax);
|
||||
VmState_Push(VmState, VmState->Registers.Cx);
|
||||
VmState_Push(VmState, VmState->Registers.Dx);
|
||||
VmState_Push(VmState, VmState->Registers.Bx);
|
||||
VmState_Push(VmState, OrigSp);
|
||||
VmState_Push(VmState, VmState->Registers.Bp);
|
||||
VmState_Push(VmState, VmState->Registers.Si);
|
||||
VmState_Push(VmState, VmState->Registers.Di);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_61_POPA(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
USHORT OrigSp;
|
||||
DPRINT("POPA\n");
|
||||
|
||||
VmState->Registers.Di = VmState_Pop(VmState);
|
||||
VmState->Registers.Si = VmState_Pop(VmState);
|
||||
VmState->Registers.Bp = VmState_Pop(VmState);
|
||||
OrigSp = VmState_Pop(VmState);
|
||||
VmState->Registers.Bx = VmState_Pop(VmState);
|
||||
VmState->Registers.Dx = VmState_Pop(VmState);
|
||||
VmState->Registers.Cx = VmState_Pop(VmState);
|
||||
VmState->Registers.Ax = VmState_Pop(VmState);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_55_PUSH_BP(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("PUSH BP\n");
|
||||
VmState_Push(VmState, VmState->Registers.Bp);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_xx_POP_BP(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
DPRINT("POP BP\n");
|
||||
VmState->Registers.Bp = VmState_Pop(VmState);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
}
|
108
reactos/lib/x86emu/vmstate.h
Normal file
108
reactos/lib/x86emu/vmstate.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
|
||||
UCHAR
|
||||
FORCEINLINE
|
||||
VmState_GetRegVal8(PX86_VM_STATE VmState, MODRM ModRm)
|
||||
{
|
||||
PUCHAR Pointer;
|
||||
|
||||
Pointer = (PUCHAR)&VmState->Registers + RegisterTable[0][ModRm.reg];
|
||||
return *Pointer;
|
||||
}
|
||||
|
||||
UCHAR
|
||||
FORCEINLINE
|
||||
VmState_GetRegVal16(PX86_VM_STATE VmState, MODRM ModRm)
|
||||
{
|
||||
return VmState->IndexedRegisters[ModRm.reg].Word;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
VmState_EnablePrefix(PX86_VM_STATE VmState, ULONG Prefix)
|
||||
{
|
||||
//DPRINT("_EnablePrefix\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
VmState_ClearPrefixes(PX86_VM_STATE VmState)
|
||||
{
|
||||
//DPRINT1("_ClearPrefixes\n");
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
VmState_AdvanceIp(PX86_VM_STATE VmState, SHORT Advance)
|
||||
{
|
||||
VmState->Registers.Ip += Advance;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
VmState_SetIp(PX86_VM_STATE VmState, USHORT Value)
|
||||
{
|
||||
VmState->Registers.Ip = Value;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PCHAR
|
||||
VmState_GetIp(PX86_VM_STATE VmState)
|
||||
{
|
||||
return (PCHAR)VmState->MemBuffer +
|
||||
VmState->Registers.ShiftedCs +
|
||||
VmState->Registers.Eip;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
VmState_Push(PX86_VM_STATE VmState, USHORT Value)
|
||||
{
|
||||
PUSHORT StackPointer;
|
||||
//DPRINT1("Pushing %x %x %x\n", Value, VmState->Registers.ShiftedSs, VmState->Registers.Sp);
|
||||
StackPointer = (PVOID)((PCHAR)VmState->MemBuffer +
|
||||
VmState->Registers.ShiftedSs +
|
||||
VmState->Registers.Sp); // FIXME: overflow
|
||||
*StackPointer = Value;
|
||||
VmState->Registers.Sp--;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
USHORT
|
||||
VmState_Pop(PX86_VM_STATE VmState)
|
||||
{
|
||||
PUSHORT StackPointer;
|
||||
//DPRINT1("Popping %x\n", Value);
|
||||
StackPointer = (PVOID)((PCHAR)VmState->MemBuffer +
|
||||
VmState->Registers.ShiftedSs +
|
||||
VmState->Registers.Sp);
|
||||
VmState->Registers.Sp--;
|
||||
return *StackPointer;
|
||||
}
|
||||
|
||||
UCHAR
|
||||
FORCEINLINE
|
||||
VmState_GetVal8(PX86_VM_STATE VmState, MODRM ModRm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
VmState_CMP8(PX86_VM_STATE VmState, UCHAR Value1, UCHAR Value2)
|
||||
{
|
||||
VmState->Registers.Eflags.Zf = ((Value1 - Value2) == 0);
|
||||
VmState->Registers.Eflags.Cf = ((Value1 - Value2) > Value1);
|
||||
VmState->Registers.Eflags.Sf = ((CHAR)(Value1 - Value2) < 0);
|
||||
VmState->Registers.Eflags.Of = ((CHAR)(Value1 - Value2) > (CHAR)Value1);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
VOID
|
||||
VmState_CMP16(PX86_VM_STATE VmState, USHORT Value1, USHORT Value2)
|
||||
{
|
||||
VmState->Registers.Eflags.Zf = ((Value1 - Value2) == 0);
|
||||
VmState->Registers.Eflags.Cf = ((Value1 - Value2) > Value1);
|
||||
VmState->Registers.Eflags.Sf = ((SHORT)(Value1 - Value2) < 0);
|
||||
VmState->Registers.Eflags.Of = ((SHORT)(Value1 - Value2) > (SHORT)Value1);
|
||||
}
|
299
reactos/lib/x86emu/x86emu.c
Normal file
299
reactos/lib/x86emu/x86emu.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* PROJECT: x86 CPU emulator
|
||||
* LICENSE: GPL, See COPYING in the top level directory
|
||||
* FILE: lib/x86emu/x86emu.c
|
||||
* PURPOSE:
|
||||
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <x86emu.h>
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#undef DPRINT
|
||||
#define DPRINT DbgPrint
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
static const ULONG RegisterTable[3][8] =
|
||||
{
|
||||
{
|
||||
FIELD_OFFSET(X86_REGISTERS, Al),
|
||||
FIELD_OFFSET(X86_REGISTERS, Cl),
|
||||
FIELD_OFFSET(X86_REGISTERS, Dl),
|
||||
FIELD_OFFSET(X86_REGISTERS, Bl),
|
||||
FIELD_OFFSET(X86_REGISTERS, Ah),
|
||||
FIELD_OFFSET(X86_REGISTERS, Ch),
|
||||
FIELD_OFFSET(X86_REGISTERS, Dh),
|
||||
FIELD_OFFSET(X86_REGISTERS, Bh),
|
||||
},
|
||||
{
|
||||
FIELD_OFFSET(X86_REGISTERS, Ax),
|
||||
FIELD_OFFSET(X86_REGISTERS, Cx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Dx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Bx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Sp),
|
||||
FIELD_OFFSET(X86_REGISTERS, Bp),
|
||||
FIELD_OFFSET(X86_REGISTERS, Si),
|
||||
FIELD_OFFSET(X86_REGISTERS, Di),
|
||||
},
|
||||
{
|
||||
FIELD_OFFSET(X86_REGISTERS, Eax),
|
||||
FIELD_OFFSET(X86_REGISTERS, Ecx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Edx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Ebx),
|
||||
FIELD_OFFSET(X86_REGISTERS, Esp),
|
||||
FIELD_OFFSET(X86_REGISTERS, Ebp),
|
||||
FIELD_OFFSET(X86_REGISTERS, Esi),
|
||||
FIELD_OFFSET(X86_REGISTERS, Edi),
|
||||
}
|
||||
};
|
||||
|
||||
/* INLINE FUNCTONS ***********************************************************/
|
||||
|
||||
#include "vmstate.h"
|
||||
#include "op_cmp.h"
|
||||
#include "op_stack.h"
|
||||
#include "op_jump.h"
|
||||
#include "op_mov.h"
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_E8_CALL16(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
SHORT Offset;
|
||||
|
||||
Offset = *(PSHORT)(IntructionPointer + 1) + 3;
|
||||
DPRINT("CALL %x\n", VmState->Registers.Ip + Offset);
|
||||
VmState_Push(VmState, VmState->Registers.Ip + 3);
|
||||
VmState_AdvanceIp(VmState, Offset);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_80(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
MODRM ModRm;
|
||||
UCHAR Value;
|
||||
|
||||
ModRm.Byte = IntructionPointer[1];
|
||||
|
||||
if (ModRm.reg == 7)
|
||||
{
|
||||
/* We have an 8 bit CMP */
|
||||
DPRINT("CMP ??. 0x%x\n", IntructionPointer[2]);
|
||||
Value = VmState_GetVal8(VmState, ModRm);
|
||||
VmState_CMP8(VmState, Value, IntructionPointer[2]);
|
||||
VmState_AdvanceIp(VmState, 3);
|
||||
return;
|
||||
}
|
||||
DPRINT1("UNKNOWN\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
Opcode_F3_REP(PX86_VM_STATE VmState, PCHAR IntructionPointer)
|
||||
{
|
||||
UCHAR ByteVal;
|
||||
|
||||
ByteVal = IntructionPointer[1];
|
||||
switch (ByteVal)
|
||||
{
|
||||
case 0x6C: /* REP INSB */
|
||||
case 0x6D: /* REP INSW/D */
|
||||
case 0xAC: /* REP LODSB */
|
||||
case 0xAD: /* REP LODSWDQ */
|
||||
case 0xA4: /* REP MOVSB */
|
||||
case 0xA5: /* REP MOVSW/D/Q */
|
||||
case 0x6E: /* REP OUTSB */
|
||||
case 0x6F: /* REP OUTSW/D */
|
||||
case 0xAA: /* REP STOSB */
|
||||
case 0xAB: /* REP STOSW/D/Q */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
x86Emulator(PX86_VM_STATE VmState)
|
||||
{
|
||||
PCHAR InstructionPointer;
|
||||
UCHAR ByteVal;
|
||||
|
||||
// x86EmuInitializeState();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
InstructionPointer = VmState_GetIp(VmState);
|
||||
ByteVal = *InstructionPointer;
|
||||
|
||||
DPRINT("%04x:%04x %02x ", VmState->Registers.SegCs, VmState->Registers.Eip, ByteVal);
|
||||
|
||||
switch (ByteVal)
|
||||
{
|
||||
case 0x06: /* PUSH ES */
|
||||
Opcode_06_PUSH_ES(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x07: /* POP ES */
|
||||
Opcode_07_POP_ES(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
// case 0x14: /* ADC AL, imm8 */
|
||||
// VmState_AdvanceIp(VmState, 2);
|
||||
// break;
|
||||
|
||||
case 0x15: /* ADC AX, imm16 */
|
||||
//_OpcodeADC16(&VmState->Registers.Al, WORD(&InstructionPointer[1]));
|
||||
VmState_AdvanceIp(VmState, 3);
|
||||
break;
|
||||
|
||||
case 0x1E: /* PUSH DS */
|
||||
Opcode_1E_PUSH_DS(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x1F: /* POP DS */
|
||||
Opcode_1F_POP_DS(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x26: /* Force ES segment */
|
||||
case 0x2e: /* Force CS segment */
|
||||
VmState_EnablePrefix(VmState, PREFIX_SEGMENT_CS);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0x36: /* Force SS segment */
|
||||
VmState->Registers.ShiftedMs = VmState->Registers.ShiftedSs;
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0x37: /* AAA */
|
||||
|
||||
case 0x3D: /* CMP (E)AX, imm16/32 */
|
||||
Opcode_3D_CMP(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x3E: /* Force DS segment */
|
||||
VmState->Registers.ShiftedMs = VmState->Registers.ShiftedDs;
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0x3F: /* AAS */
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
break;
|
||||
|
||||
/* 0x40 ... 0x4F are REX prefixes */
|
||||
|
||||
case 0x55: /* PUSH BP */
|
||||
Opcode_55_PUSH_BP(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x60: /* PUSHA */
|
||||
Opcode_60_PUSHA(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x61: /* POPA */
|
||||
Opcode_61_POPA(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x64: /* Force FS segment */
|
||||
case 0x65: /* Force GS segment */
|
||||
|
||||
case 0x66: /* Operand size override */
|
||||
VmState_EnablePrefix(VmState, PREFIX_SIZE_OVERRIDE);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0x67: /* Address size prefix */
|
||||
VmState_EnablePrefix(VmState, PREFIX_ADDRESS_OVERRIDE);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0x74: /* JZ */
|
||||
Opcode_74_JZ8(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x75: /* JNZ */
|
||||
Opcode_75_JNZ8(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x80: /* ... */
|
||||
Opcode_80(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x89: /* MOV regmem16, reg16 */
|
||||
Opcode_89_MOV(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x8E: /* MOV seg, reg16 */
|
||||
Opcode_8E_MOV(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x9C: /* PUSHF */
|
||||
Opcode_9C_PUSHF(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0x9D: /* POPF */
|
||||
Opcode_9D_POPF(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0xBB: /* MOV BX, imm16 */
|
||||
Opcode_BB_MOV(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0xCF: /* IRET */
|
||||
DPRINT("IRET\n");
|
||||
return;
|
||||
|
||||
case 0xD4: /* AAM */
|
||||
/* Check for D4 0A */
|
||||
|
||||
case 0xD5: /* AAD */
|
||||
/* Check for D5 0A */
|
||||
|
||||
case 0xE8:
|
||||
Opcode_E8_CALL16(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0xE9: /* JMP off16 */
|
||||
Opcode_E9_JMP16(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
case 0xF0: /* LOCK (ignored) */
|
||||
DPRINT("LOCK ");
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0xF2: /* REPNZ/REPNE */
|
||||
DPRINT("REPNE ");
|
||||
VmState_EnablePrefix(VmState, PREFIX_REP);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
continue;
|
||||
|
||||
case 0xF3: /* REP */
|
||||
Opcode_F3_REP(VmState, InstructionPointer);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
DPRINT("Unknown opcode 0x%x\n", ByteVal);
|
||||
VmState_AdvanceIp(VmState, 1);
|
||||
//x86EmuRaiseException(EXCEPTION_INVALID_OPCODE, ByteVal);
|
||||
//return;
|
||||
}
|
||||
|
||||
/* Clear prefixes and continue with next intruction */
|
||||
VmState_ClearPrefixes(VmState);
|
||||
|
||||
//ResetMs:
|
||||
VmState->Registers.ShiftedMs = VmState->Registers.ShiftedDs;
|
||||
|
||||
}
|
||||
}
|
230
reactos/lib/x86emu/x86emu.h
Normal file
230
reactos/lib/x86emu/x86emu.h
Normal file
|
@ -0,0 +1,230 @@
|
|||
|
||||
|
||||
#ifndef _X86EMU_H_
|
||||
#define _X86EMU_H_
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <ntndk.h>
|
||||
|
||||
typedef union
|
||||
{
|
||||
USHORT Short;
|
||||
ULONG Long;
|
||||
struct
|
||||
{
|
||||
ULONG Cf:1;
|
||||
ULONG Pf:1;
|
||||
ULONG Af:1;
|
||||
ULONG Zf:1;
|
||||
ULONG Sf:1;
|
||||
ULONG Tf:1;
|
||||
ULONG If:1;
|
||||
ULONG Df:1;
|
||||
ULONG Of:1;
|
||||
ULONG Iopl:3;
|
||||
ULONG Nt:1;
|
||||
ULONG Rf:1;
|
||||
ULONG Vm:1;
|
||||
ULONG Ac:1;
|
||||
ULONG Vif:1;
|
||||
ULONG Vip:1;
|
||||
ULONG Id:1;
|
||||
};
|
||||
} EFLAGS;
|
||||
|
||||
typedef union
|
||||
{
|
||||
ULONG Dword;
|
||||
USHORT Word;
|
||||
UCHAR Byte;
|
||||
struct
|
||||
{
|
||||
UCHAR Low;
|
||||
UCHAR High;
|
||||
};
|
||||
} REGU;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR mod:2;
|
||||
UCHAR reg:3;
|
||||
UCHAR rm:3;
|
||||
};
|
||||
UCHAR Byte;
|
||||
} MODRM;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
ULONG Eax;
|
||||
USHORT Ax;
|
||||
struct
|
||||
{
|
||||
UCHAR Al;
|
||||
UCHAR Ah;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Ecx;
|
||||
USHORT Cx;
|
||||
struct
|
||||
{
|
||||
UCHAR Cl;
|
||||
UCHAR Ch;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Edx;
|
||||
USHORT Dx;
|
||||
struct
|
||||
{
|
||||
UCHAR Dl;
|
||||
UCHAR Dh;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Ebx;
|
||||
USHORT Bx;
|
||||
struct
|
||||
{
|
||||
UCHAR Bl;
|
||||
UCHAR Bh;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Ebp;
|
||||
USHORT Bp;
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Esi;
|
||||
USHORT Si;
|
||||
};
|
||||
union
|
||||
{
|
||||
ULONG Edi;
|
||||
USHORT Di;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ReservedDsMBZ:4;
|
||||
ULONG SegDs:16;
|
||||
};
|
||||
ULONG ShiftedDs;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ReservedEsMBZ:4;
|
||||
ULONG SegEs:16;
|
||||
};
|
||||
ULONG ShiftedEs;
|
||||
};
|
||||
|
||||
/* Extended */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ReservedCsMBZ:4;
|
||||
ULONG SegCs:16;
|
||||
};
|
||||
ULONG ShiftedCs;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ReservedSsMBZ:4;
|
||||
ULONG SegSs:16;
|
||||
};
|
||||
ULONG ShiftedSs;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ReservedMsMBZ:4;
|
||||
ULONG SegMs:16;
|
||||
};
|
||||
ULONG ShiftedMs;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
ULONG Eip;
|
||||
USHORT Ip;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
ULONG Esp;
|
||||
USHORT Sp;
|
||||
};
|
||||
|
||||
EFLAGS Eflags;
|
||||
|
||||
} X86_REGISTERS, *PX86_REGISTERS;
|
||||
|
||||
enum
|
||||
{
|
||||
X86_VMFLAGS_RETURN_ON_IRET = 1,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
X86_BIOS_REGISTERS BiosRegisters;
|
||||
X86_REGISTERS Registers;
|
||||
REGU IndexedRegisters[8];
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG ReturnOnIret:1;
|
||||
} Flags;
|
||||
|
||||
PVOID MemBuffer;
|
||||
|
||||
#if 1
|
||||
PCHAR Mnemonic;
|
||||
PCHAR DstReg;
|
||||
PCHAR SrcReg;
|
||||
ULONG SrcEncodung;
|
||||
ULONG DstEncoding;
|
||||
ULONG Length;
|
||||
#endif
|
||||
} X86_VM_STATE, *PX86_VM_STATE;
|
||||
|
||||
enum
|
||||
{
|
||||
PREFIX_SIZE_OVERRIDE = 0x010001,
|
||||
PREFIX_ADDRESS_OVERRIDE = 0x020002,
|
||||
PREFIX_SEGMENT_CS = 0x040004,
|
||||
PREFIX_SEGMENT_DS = 0x040008,
|
||||
PREFIX_SEGMENT_ES = 0x040010,
|
||||
PREFIX_SEGMNET_FS = 0x040020,
|
||||
PREFIX_SEGMENT_GS = 0x040040,
|
||||
PREFIX_SEGMENT_SS = 0x040080,
|
||||
PREFIX_LOCK = 0x080100,
|
||||
PREFIX_REP = 0x100200,
|
||||
} PREFIX_STATE;
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
x86Emulator(PX86_VM_STATE VmState);
|
||||
|
||||
#endif
|
7
reactos/lib/x86emu/x86emu.rbuild
Normal file
7
reactos/lib/x86emu/x86emu.rbuild
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../tools/rbuild/project.dtd">
|
||||
<module name="x86emu" type="staticlibrary">
|
||||
<define name="_X86BIOS_" />
|
||||
<include base="x86emu">.</include>
|
||||
<file>x86emu.c</file>
|
||||
</module>
|
Loading…
Add table
Add a link
Reference in a new issue