Beispiel #1
0
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);
}
Beispiel #2
0
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));
}