[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:
Aleksandar Andrejevic 2013-07-07 20:53:23 +00:00
parent 1f4d89e7d7
commit 59e28c4f15
4 changed files with 196 additions and 14 deletions

View file

@ -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;

View file

@ -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:
{

View file

@ -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)

View file

@ -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();