static inline VOID NTAPI Fast486ExecutionControl(PFAST486_STATE State, FAST486_EXEC_CMD Command) { UCHAR Opcode; INT ProcedureCallCount = 0; /* Main execution loop */ do { /* Check if this is a new instruction */ if (State->PrefixFlags == 0) State->SavedInstPtr = State->InstPtr; /* Perform an instruction fetch */ if (!Fast486FetchByte(State, &Opcode)) { /* Exception occurred */ State->PrefixFlags = 0; continue; } // TODO: Check for CALL/RET to update ProcedureCallCount. if (Fast486OpcodeHandlers[Opcode] != NULL) { /* Call the opcode handler */ Fast486OpcodeHandlers[Opcode](State, Opcode); } else { /* This is not a valid opcode */ Fast486Exception(State, FAST486_EXCEPTION_UD); } if (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix) { /* This is a prefix, go to the next instruction immediately */ continue; } /* A non-prefix opcode has been executed, reset the prefix flags */ State->PrefixFlags = 0; /* * Check if there is an interrupt to execute, or a hardware interrupt signal * while interrupts are enabled. */ if (State->IntStatus == FAST486_INT_EXECUTE) { FAST486_IDT_ENTRY IdtEntry; /* Get the interrupt vector */ if (Fast486GetIntVector(State, State->PendingIntNum, &IdtEntry)) { /* Perform the interrupt */ Fast486InterruptInternal(State, IdtEntry.Selector, MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh), IdtEntry.Type); /* Restore the prefix flags, which would be set to OPSIZE for 32-bit real mode */ State->PrefixFlags = 0; } /* Clear the interrupt status */ State->IntStatus = FAST486_INT_NONE; } else if (State->Flags.If && (State->IntAckCallback != NULL) && (State->IntStatus == FAST486_INT_SIGNAL)) { /* Acknowledge the interrupt to get the number */ State->PendingIntNum = State->IntAckCallback(State); /* Set the interrupt status to execute on the next instruction */ State->IntStatus = FAST486_INT_EXECUTE; } else if (State->IntStatus == FAST486_INT_DELAYED) { /* Restore the old state */ State->IntStatus = FAST486_INT_EXECUTE; } } while ((Command == FAST486_CONTINUE) || (Command == FAST486_STEP_OVER && ProcedureCallCount > 0) || (Command == FAST486_STEP_OUT && ProcedureCallCount >= 0) || (Fast486OpcodeHandlers[Opcode] == Fast486OpcodePrefix)); }
VOID FASTCALL Fast486ExceptionWithErrorCode(PFAST486_STATE State, FAST486_EXCEPTIONS ExceptionCode, ULONG ErrorCode) { FAST486_IDT_ENTRY IdtEntry; /* Increment the exception count */ State->ExceptionCount++; /* Check if the exception occurred more than once */ if (State->ExceptionCount > 1) { /* Then this is a double fault */ ExceptionCode = FAST486_EXCEPTION_DF; } /* Check if this is a triple fault */ if (State->ExceptionCount == 3) { /* Reset the CPU */ Fast486Reset(State); return; } /* Restore the IP to the saved IP */ State->InstPtr = State->SavedInstPtr; if (!Fast486GetIntVector(State, ExceptionCode, &IdtEntry)) { /* * If this function failed, that means Fast486Exception * was called again, so just return in this case. */ return; } /* Perform the interrupt */ if (!Fast486InterruptInternal(State, IdtEntry.Selector, MAKELONG(IdtEntry.Offset, IdtEntry.OffsetHigh), IdtEntry.Type)) { /* * If this function failed, that means Fast486Exception * was called again, so just return in this case. */ return; } if (EXCEPTION_HAS_ERROR_CODE(ExceptionCode) && (State->ControlRegisters[FAST486_REG_CR0] & FAST486_CR0_PE)) { /* Push the error code */ if (!Fast486StackPush(State, ErrorCode)) { /* * If this function failed, that means Fast486Exception * was called again, so just return in this case. */ return; } } /* Reset the exception count */ State->ExceptionCount = 0; }