/*
- * COPYRIGHT: GPL - See COPYING in the top level directory
- * PROJECT: 386/486 CPU Emulation Library
- * FILE: soft386.c
- * PURPOSE: Functions meant for use by the host.
- * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ * Soft386 386/486 CPU Emulation Library
+ * soft386.c
+ *
+ * Copyright (C) 2013 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* INCLUDES *******************************************************************/
// #define _INC_WINDOWS
#include <windef.h>
+// #define NDEBUG
+#include <debug.h>
+
#include <soft386.h>
#include "common.h"
#include "opcodes.h"
-// #define NDEBUG
-#include <debug.h>
-
/* DEFINES ********************************************************************/
typedef enum
NTAPI
Soft386ExecutionControl(PSOFT386_STATE State, INT Command)
{
- BYTE Opcode;
+ UCHAR Opcode;
INT ProcedureCallCount = 0;
/* Main execution loop */
do
{
+ /* Check if this is a new instruction */
+ if (State->PrefixFlags == 0)
+ {
+ State->SavedInstPtr = State->InstPtr;
+
+ /* Check if interrupts are enabled and there is an interrupt pending */
+ if (State->Flags.If && State->HardwareInt)
+ {
+ SOFT386_IDT_ENTRY IdtEntry;
+
+ /* Get the interrupt vector */
+ if (Soft386GetIntVector(State, State->PendingIntNum, &IdtEntry))
+ {
+ /* Perform the interrupt */
+ Soft386InterruptInternal(State,
+ IdtEntry.Selector,
+ MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh),
+ IdtEntry.Type);
+ }
+
+ /* Clear the interrupt pending flag */
+ State->HardwareInt = FALSE;
+ }
+ }
+
/* Perform an instruction fetch */
if (!Soft386FetchByte(State, &Opcode)) continue;
if (Soft386OpcodeHandlers[Opcode] != NULL)
{
/* Call the opcode handler */
- Soft386OpcodeHandlers[Opcode](State);
+ Soft386OpcodeHandlers[Opcode](State, Opcode);
}
else
{
/* This is not a valid opcode */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
}
+
+ if (Soft386OpcodeHandlers[Opcode] != Soft386OpcodePrefix)
+ {
+ /* A non-prefix opcode has been executed, reset the prefix flags */
+ State->PrefixFlags = 0;
+ }
+ else
+ {
+ /* This is a prefix, go to the next instruction immediately */
+ continue;
+ }
+
+ /* Increment the time stamp counter */
+ State->TimeStampCounter++;
}
while ((Command == SOFT386_CONTINUE)
|| (Command == SOFT386_STEP_OVER && ProcedureCallCount > 0)
- || (Command == SOFT386_STEP_OUT && ProcedureCallCount >= 0));
+ || (Command == SOFT386_STEP_OUT && ProcedureCallCount >= 0)
+ || (Soft386OpcodeHandlers[Opcode] == Soft386OpcodePrefix));
}
/* PUBLIC FUNCTIONS ***********************************************************/
SOFT386_MEM_WRITE_PROC MemWriteCallback = State->MemWriteCallback;
SOFT386_IO_READ_PROC IoReadCallback = State->IoReadCallback;
SOFT386_IO_WRITE_PROC IoWriteCallback = State->IoWriteCallback;
+ SOFT386_IDLE_PROC IdleCallback = State->IdleCallback;
+ SOFT386_BOP_PROC BopCallback = State->BopCallback;
/* Clear the entire structure */
RtlZeroMemory(State, sizeof(*State));
/* Initialize CR0 */
State->ControlRegisters[SOFT386_REG_CR0] |= SOFT386_CR0_ET;
-
+
/* Restore the callbacks */
State->MemReadCallback = MemReadCallback;
State->MemWriteCallback = MemWriteCallback;
State->IoReadCallback = IoReadCallback;
State->IoWriteCallback = IoWriteCallback;
+ State->IdleCallback = IdleCallback;
+ State->BopCallback = BopCallback;
}
VOID
NTAPI
Soft386Interrupt(PSOFT386_STATE State, UCHAR Number)
{
- // TODO: NOT IMPLEMENTED!!!
- UNIMPLEMENTED;
+ /* Set the hardware interrupt flag */
+ State->HardwareInt = TRUE;
+ State->PendingIntNum = Number;
+}
+
+VOID
+NTAPI
+Soft386ExecuteAt(PSOFT386_STATE State, USHORT Segment, ULONG Offset)
+{
+ /* Load the new CS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
+ {
+ /* An exception occurred, let the handler execute instead */
+ return;
+ }
+
+ /* Set the new IP */
+ State->InstPtr.Long = Offset;
+}
+
+VOID
+NTAPI
+Soft386SetStack(PSOFT386_STATE State, USHORT Segment, ULONG Offset)
+{
+ /* Load the new SS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_SS, Segment))
+ {
+ /* An exception occurred, let the handler execute instead */
+ return;
+ }
+
+ /* Set the new SP */
+ State->GeneralRegs[SOFT386_REG_ESP].Long = Offset;
+}
+
+VOID
+NTAPI
+Soft386SetSegment(PSOFT386_STATE State,
+ SOFT386_SEG_REGS Segment,
+ USHORT Selector)
+{
+ /* Call the internal function */
+ Soft386LoadSegment(State, Segment, Selector);
}
/* EOF */