mirror of
https://github.com/reactos/reactos.git
synced 2025-05-07 02:41:22 +00:00
[SOFTX86]
Fix jump conditions. [NTVDM] Implement BIOS teletype output command. Start implementation of a new CPU emulator to replace softx86. svn path=/branches/ntvdm/; revision=59450
This commit is contained in:
parent
1f4d89e7d7
commit
59e28c4f15
4 changed files with 196 additions and 14 deletions
20
lib/3rdparty/softx86/softx86/jumpy.c
vendored
20
lib/3rdparty/softx86/softx86/jumpy.c
vendored
|
@ -86,22 +86,22 @@ int Sfx86OpcodeExec_jc(sx86_ubyte opcode,softx86_ctx* ctx)
|
|||
tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_PARITY);
|
||||
/* JL */
|
||||
else if (opcode == 0x7C)
|
||||
tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) !=
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW);
|
||||
tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) !=
|
||||
((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0));
|
||||
/* JGE */
|
||||
else if (opcode == 0x7D)
|
||||
tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ==
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW);
|
||||
tf = ((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) ==
|
||||
((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0);
|
||||
/* JLE */
|
||||
else if (opcode == 0x7E)
|
||||
tf = ((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) !=
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW)) ||
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO);
|
||||
tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) !=
|
||||
((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0) ||
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO));
|
||||
/* JG */
|
||||
else if (opcode == 0x7F)
|
||||
tf = ((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ==
|
||||
(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW)) &&
|
||||
(!(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO));
|
||||
tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) ==
|
||||
((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0) &&
|
||||
(!(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO)));
|
||||
/* should NOT be here !*/
|
||||
else
|
||||
return 0;
|
||||
|
|
|
@ -738,6 +738,28 @@ VOID BiosVideoService()
|
|||
break;
|
||||
}
|
||||
|
||||
/* Teletype Output */
|
||||
case 0x0E:
|
||||
{
|
||||
CHAR Character = LOBYTE(Eax);
|
||||
DWORD NumWritten;
|
||||
|
||||
/* Make sure the page exists */
|
||||
if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
|
||||
|
||||
/* Set the attribute */
|
||||
SetConsoleTextAttribute(ConsoleBuffers[HIBYTE(Ebx)], LOBYTE(Ebx));
|
||||
|
||||
/* Write the character */
|
||||
WriteConsoleA(ConsoleBuffers[HIBYTE(Ebx)],
|
||||
&Character,
|
||||
sizeof(CHAR),
|
||||
&NumWritten,
|
||||
NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get Current Video Mode */
|
||||
case 0x0F:
|
||||
{
|
||||
|
|
|
@ -17,12 +17,19 @@
|
|||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
static softx86_ctx EmulatorContext;
|
||||
static softx87_ctx FpuEmulatorContext;
|
||||
#ifndef NEW_EMULATOR
|
||||
softx86_ctx EmulatorContext;
|
||||
softx87_ctx FpuEmulatorContext;
|
||||
#else
|
||||
EMULATOR_CONTEXT EmulatorContext;
|
||||
#endif
|
||||
|
||||
static BOOLEAN A20Line = FALSE;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
|
||||
static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size)
|
||||
{
|
||||
/* If the A20 line is disabled, mask bit 20 */
|
||||
|
@ -165,8 +172,13 @@ static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number)
|
|||
if (Number == SPECIAL_INT_NUM)
|
||||
{
|
||||
/* Get the SS:SP */
|
||||
#ifndef NEW_EMULATOR
|
||||
StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val;
|
||||
StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val;
|
||||
#else
|
||||
StackSegment = EmulatorContext.Registers[EMULATOR_REG_SS].LowWord;
|
||||
StackPointer = EmulatorContext.Registers[EMULATOR_REG_SP].LowWord;
|
||||
#endif
|
||||
|
||||
/* Get the interrupt number */
|
||||
IntNum = *(LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(StackSegment, StackPointer));
|
||||
|
@ -274,6 +286,8 @@ static VOID EmulatorHardwareIntAck(PVOID Context, BYTE Number)
|
|||
/* Do nothing */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
BOOLEAN EmulatorInitialize()
|
||||
|
@ -282,6 +296,7 @@ BOOLEAN EmulatorInitialize()
|
|||
BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
|
||||
if (BaseAddress == NULL) return FALSE;
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Initialize the softx86 CPU emulator */
|
||||
if (!softx86_init(&EmulatorContext, SX86_CPULEVEL_80286))
|
||||
{
|
||||
|
@ -312,6 +327,9 @@ BOOLEAN EmulatorInitialize()
|
|||
|
||||
/* Connect the emulated FPU to the emulated CPU */
|
||||
softx87_connect_to_CPU(&EmulatorContext, &FpuEmulatorContext);
|
||||
#else
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
|
||||
/* Enable interrupts */
|
||||
EmulatorSetFlag(EMULATOR_FLAG_IF);
|
||||
|
@ -321,14 +339,22 @@ BOOLEAN EmulatorInitialize()
|
|||
|
||||
VOID EmulatorSetStack(WORD Segment, WORD Offset)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Call the softx86 API */
|
||||
softx86_set_stack_ptr(&EmulatorContext, Segment, Offset);
|
||||
#else
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorExecute(WORD Segment, WORD Offset)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Call the softx86 API */
|
||||
softx86_set_instruction_ptr(&EmulatorContext, Segment, Offset);
|
||||
#else
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorInterrupt(BYTE Number)
|
||||
|
@ -340,18 +366,27 @@ VOID EmulatorInterrupt(BYTE Number)
|
|||
Segment = HIWORD(IntVecTable[Number]);
|
||||
Offset = LOWORD(IntVecTable[Number]);
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Call the softx86 API */
|
||||
softx86_make_simple_interrupt_call(&EmulatorContext, &Segment, &Offset);
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(Segment);
|
||||
UNREFERENCED_PARAMETER(Offset);
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorExternalInterrupt(BYTE Number)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Call the softx86 API */
|
||||
softx86_ext_hw_signal(&EmulatorContext, Number);
|
||||
#endif
|
||||
}
|
||||
|
||||
ULONG EmulatorGetRegister(ULONG Register)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
if (Register < EMULATOR_REG_ES)
|
||||
{
|
||||
return EmulatorContext.state->general_reg[Register].val;
|
||||
|
@ -360,10 +395,14 @@ ULONG EmulatorGetRegister(ULONG Register)
|
|||
{
|
||||
return EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val;
|
||||
}
|
||||
#else
|
||||
return EmulatorContext.Registers[Register].Long;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorSetRegister(ULONG Register, ULONG Value)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
if (Register < EMULATOR_REG_CS)
|
||||
{
|
||||
EmulatorContext.state->general_reg[Register].val = Value;
|
||||
|
@ -372,25 +411,41 @@ VOID EmulatorSetRegister(ULONG Register, ULONG Value)
|
|||
{
|
||||
EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = Value;
|
||||
}
|
||||
#else
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOLEAN EmulatorGetFlag(ULONG Flag)
|
||||
{
|
||||
return (EmulatorContext.state->reg_flags.val & Flag);
|
||||
#ifndef NEW_EMULATOR
|
||||
return (EmulatorContext.state->reg_flags.val & Flag) ? TRUE : FALSE;
|
||||
#else
|
||||
return (EmulatorContext.Flags.Long & Flag) ? TRUE : FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorSetFlag(ULONG Flag)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
EmulatorContext.state->reg_flags.val |= Flag;
|
||||
#else
|
||||
EmulatorContext.Flags.Long |= Flag;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorClearFlag(ULONG Flag)
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
EmulatorContext.state->reg_flags.val &= ~Flag;
|
||||
#else
|
||||
EmulatorContext.Flags.Long &= ~Flag;
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorStep()
|
||||
{
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Print the current position - useful for debugging */
|
||||
DPRINT("Executing at CS:IP = %04X:%04X\n",
|
||||
EmulatorGetRegister(EMULATOR_REG_CS),
|
||||
|
@ -402,6 +457,9 @@ VOID EmulatorStep()
|
|||
/* Invalid opcode */
|
||||
EmulatorInterrupt(EMULATOR_EXCEPTION_INVALID_OPCODE);
|
||||
}
|
||||
#else
|
||||
// TODO: NOT IMPLEMENTED
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorCleanup()
|
||||
|
@ -409,9 +467,11 @@ VOID EmulatorCleanup()
|
|||
/* Free the memory allocated for the 16-bit address space */
|
||||
if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress);
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
/* Free the softx86 CPU and FPU emulator */
|
||||
softx86_free(&EmulatorContext);
|
||||
softx87_free(&FpuEmulatorContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID EmulatorSetA20(BOOLEAN Enabled)
|
||||
|
|
|
@ -12,11 +12,15 @@
|
|||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "ntvdm.h"
|
||||
|
||||
#ifndef NEW_EMULATOR
|
||||
#include <softx86/softx86.h>
|
||||
#include <softx86/softx87.h>
|
||||
#endif
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* FLAGS */
|
||||
#define EMULATOR_FLAG_CF (1 << 0)
|
||||
#define EMULATOR_FLAG_PF (1 << 2)
|
||||
#define EMULATOR_FLAG_AF (1 << 4)
|
||||
|
@ -33,6 +37,39 @@
|
|||
#define EMULATOR_FLAG_VIF (1 << 19)
|
||||
#define EMULATOR_FLAG_VIP (1 << 20)
|
||||
#define EMULATOR_FLAG_ID (1 << 21)
|
||||
|
||||
/* CR0 */
|
||||
#define EMULATOR_CR0_PE (1 << 0)
|
||||
#define EMULATOR_CR0_MP (1 << 1)
|
||||
#define EMULATOR_CR0_EM (1 << 2)
|
||||
#define EMULATOR_CR0_TS (1 << 3)
|
||||
#define EMULATOR_CR0_ET (1 << 4)
|
||||
#define EMULATOR_CR0_NE (1 << 5)
|
||||
#define EMULATOR_CR0_WP (1 << 16)
|
||||
#define EMULATOR_CR0_AM (1 << 18)
|
||||
#define EMULATOR_CR0_NW (1 << 29)
|
||||
#define EMULATOR_CR0_CD (1 << 30)
|
||||
#define EMULATOR_CR0_PG (1 << 31)
|
||||
|
||||
/* GDT Access byte */
|
||||
#define GDT_SEG_ACCESSED (1 << 0)
|
||||
#define GDT_DATA_WRITEABLE (1 << 1)
|
||||
#define GDT_CODE_READABLE (1 << 1)
|
||||
#define GDT_CONFORMING (1 << 2)
|
||||
#define GDT_DIRECTION (1 << 2)
|
||||
#define GDT_CODE_SEGMENT (1 << 3)
|
||||
#define GDT_PRESENT (1 << 7)
|
||||
|
||||
/* GDT flags */
|
||||
#define GDT_32BIT_SEGMENT (1 << 2)
|
||||
#define GDT_PAGE_GRANULARITY (1 << 3)
|
||||
|
||||
/* Common definitions */
|
||||
#define EMULATOR_NUM_GENERAL_REGS 8
|
||||
#define EMULATOR_NUM_SEGMENT_REGS 6
|
||||
#define EMULATOR_NUM_CONTROL_REGS 8
|
||||
#define EMULATOR_NUM_DEBUG_REGS 8
|
||||
#define MAX_GDT_ENTRIES 8192
|
||||
#define SPECIAL_INT_NUM 0xFF
|
||||
|
||||
enum
|
||||
|
@ -44,7 +81,14 @@ enum
|
|||
EMULATOR_EXCEPTION_OVERFLOW,
|
||||
EMULATOR_EXCEPTION_BOUND,
|
||||
EMULATOR_EXCEPTION_INVALID_OPCODE,
|
||||
EMULATOR_EXCEPTION_NO_FPU
|
||||
EMULATOR_EXCEPTION_NO_FPU,
|
||||
EMULATOR_EXCEPTION_DOUBLE_FAULT,
|
||||
EMULATOR_EXCEPTION_FPU_SEGMENT,
|
||||
EMULATOR_EXCEPTION_INVALID_TSS,
|
||||
EMULATOR_EXCEPTION_NO_SEGMENT,
|
||||
EMULATOR_EXCEPTION_STACK_SEGMENT,
|
||||
EMULATOR_EXCEPTION_GPF,
|
||||
EMULATOR_EXCEPTION_PAGE_FAULT
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -61,8 +105,64 @@ enum
|
|||
EMULATOR_REG_CS,
|
||||
EMULATOR_REG_SS,
|
||||
EMULATOR_REG_DS,
|
||||
EMULATOR_REG_FS,
|
||||
EMULATOR_REG_GS
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE LowByte;
|
||||
BYTE HighByte;
|
||||
};
|
||||
WORD LowWord;
|
||||
DWORD Long;
|
||||
} EMULATOR_REGISTER, *PEMULATOR_REGISTER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Limit : 16;
|
||||
ULONG Base : 24;
|
||||
ULONG AccessByte : 8;
|
||||
ULONG LimitHigh : 4;
|
||||
ULONG Flags : 4;
|
||||
ULONG BaseHigh : 8;
|
||||
} EMULATOR_GDT_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Offset : 16;
|
||||
ULONG Selector : 16;
|
||||
ULONG Zero : 8;
|
||||
ULONG TypeAndAttributes : 8;
|
||||
ULONG OffsetHigh : 16;
|
||||
} EMULATOR_IDT_ENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD Size;
|
||||
DWORD Address;
|
||||
} EMULATOR_TABLE_REGISTER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EMULATOR_REGISTER Registers[EMULATOR_NUM_GENERAL_REGS
|
||||
+ EMULATOR_NUM_SEGMENT_REGS];
|
||||
EMULATOR_REGISTER Flags;
|
||||
EMULATOR_REGISTER InstructionPointer;
|
||||
EMULATOR_REGISTER ControlRegisters[EMULATOR_NUM_CONTROL_REGS];
|
||||
EMULATOR_REGISTER DebugRegisters[EMULATOR_NUM_DEBUG_REGS];
|
||||
ULONGLONG TimeStampCounter;
|
||||
BOOLEAN OperandSizeOverload;
|
||||
BOOLEAN AddressSizeOverload;
|
||||
EMULATOR_TABLE_REGISTER Gdtr, Idtr;
|
||||
EMULATOR_GDT_ENTRY CachedDescriptors[EMULATOR_NUM_SEGMENT_REGS];
|
||||
UINT ExceptionCount;
|
||||
} EMULATOR_CONTEXT, *PEMULATOR_CONTEXT;
|
||||
|
||||
typedef VOID (*EMULATOR_OPCODE_HANDLER)(PEMULATOR_CONTEXT Context, BYTE Opcode);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
BOOLEAN EmulatorInitialize();
|
||||
|
|
Loading…
Reference in a new issue