From: Aleksandar Andrejevic Date: Sun, 7 Jul 2013 20:53:23 +0000 (+0000) Subject: [SOFTX86] X-Git-Tag: backups/0.3.17@66124~1365^2~560 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=59e28c4f15a7ca6f326c25409b1bad1d712d2663 [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 --- diff --git a/lib/3rdparty/softx86/softx86/jumpy.c b/lib/3rdparty/softx86/softx86/jumpy.c index 11c41d90b08..038ab064b11 100644 --- a/lib/3rdparty/softx86/softx86/jumpy.c +++ b/lib/3rdparty/softx86/softx86/jumpy.c @@ -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; diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index 6d1de0ccf57..dd7cfc5aeec 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -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: { diff --git a/subsystems/ntvdm/emulator.c b/subsystems/ntvdm/emulator.c index af4a727ae58..f49e9823994 100644 --- a/subsystems/ntvdm/emulator.c +++ b/subsystems/ntvdm/emulator.c @@ -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) diff --git a/subsystems/ntvdm/emulator.h b/subsystems/ntvdm/emulator.h index 8a24d3ae763..69471a117c9 100644 --- a/subsystems/ntvdm/emulator.h +++ b/subsystems/ntvdm/emulator.h @@ -12,11 +12,15 @@ /* INCLUDES *******************************************************************/ #include "ntvdm.h" + +#ifndef NEW_EMULATOR #include #include +#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();