BOOLEAN Fast486WriteMemory(PFAST486_STATE State, FAST486_SEG_REGS SegmentReg, ULONG Offset, PVOID Buffer, ULONG Size) { ULONG LinearAddress; PFAST486_SEG_REG CachedDescriptor; ASSERT(SegmentReg < FAST486_NUM_SEG_REGS); /* Get the cached descriptor */ CachedDescriptor = &State->SegmentRegs[SegmentReg]; if ((Offset + Size - 1) > CachedDescriptor->Limit) { /* Write beyond limit */ Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; } /* Check for protected mode */ if (State->ControlRegisters[0] & FAST486_CR0_PE) { /* Privilege checks */ if (!CachedDescriptor->Present) { Fast486Exception(State, FAST486_EXCEPTION_NP); return FALSE; } if ((CachedDescriptor->Rpl > CachedDescriptor->Dpl) || (Fast486GetCurrentPrivLevel(State) > CachedDescriptor->Dpl)) { Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; } if (CachedDescriptor->Executable) { /* Code segment not writable */ Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; } else if (!CachedDescriptor->ReadWrite) { /* Data segment not writeable */ Fast486Exception(State, FAST486_EXCEPTION_GP); return FALSE; } } /* Find the linear address */ LinearAddress = CachedDescriptor->Base + Offset; /* Write to the linear address */ return Fast486WriteLinearMemory(State, LinearAddress, Buffer, Size); }
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)); }