[SOFTX86]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 7 Jul 2013 20:53:23 +0000 (20:53 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 7 Jul 2013 20:53:23 +0000 (20:53 +0000)
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

lib/3rdparty/softx86/softx86/jumpy.c
subsystems/ntvdm/bios.c
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h

index 11c41d9..038ab06 100644 (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;
index 6d1de0c..dd7cfc5 100644 (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:
         {
index af4a727..f49e982 100644 (file)
 
 /* 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)
index 8a24d3a..69471a1 100644 (file)
 /* 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)
 #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();