windows-nt/Source/XPSP1/NT/base/hals/x86new/inoutops.c
2020-09-26 16:20:57 +08:00

236 lines
3.8 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
inoutops.c
Abstract:
This module implements the code to emulate the in and out opcodes.
Author:
David N. Cutler (davec) 7-Nov-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "nthal.h"
#include "emulate.h"
VOID
XmInOp (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function emulates a inb/w/d opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
//
// Check if the I/O port number is valid.
//
if ((P->SrcValue.Long + P->DataType) > 0xffff) {
longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
}
//
// Set the destination address, input from the specified port, and
// store the result.
//
P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
XmStoreResult(P, (P->ReadIoSpace)(P->DataType, P->SrcValue.Word));
return;
}
VOID
XmInsOp (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function emulates a insb/w/d opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
ULONG Count;
USHORT PortNumber;
//
// If a repeat prefix is active, then the loop count is specified
// by eCX. Otherwise, the loop count is one.
//
Count = 1;
if (P->RepeatPrefixActive != FALSE) {
if (P->OpaddrPrefixActive != FALSE) {
Count = P->Gpr[ECX].Exx;
P->Gpr[ECX].Exx = 0;
} else {
Count = P->Gpr[CX].Xx;
P->Gpr[CX].Xx = 0;
}
}
//
// Move items from the input port to the destination string.
//
PortNumber = P->SrcValue.Word;
while (Count != 0) {
//
// Set the destination address, input from the specified port, and
// store the result.
//
P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
XmStoreResult(P, (P->ReadIoSpace)(P->DataType, PortNumber));
Count -= 1;
}
return;
}
VOID
XmOutOp (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function emulates a outb/w/d opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
USHORT PortNumber;
//
// Check if the I/O port number is valid.
//
if ((P->SrcValue.Long + P->DataType) > 0xffff) {
longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
}
//
// Save the port number, get the source value, and output to the port.
//
PortNumber = P->SrcValue.Word;
XmSetSourceValue(P, &P->Gpr[EAX].Exx);
(P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
return;
}
VOID
XmOutsOp (
IN PRXM_CONTEXT P
)
/*++
Routine Description:
This function emulates a outsb/w/d opcode.
Arguments:
P - Supplies a pointer to the emulation context structure.
Return Value:
None.
--*/
{
ULONG Count;
USHORT PortNumber;
//
// If a repeat prefix is active, then the loop count is specified
// by eCX. Otherwise, the loop count is one.
//
Count = 1;
if (P->RepeatPrefixActive != FALSE) {
if (P->OpaddrPrefixActive != FALSE) {
Count = P->Gpr[ECX].Exx;
P->Gpr[ECX].Exx = 0;
} else {
Count = P->Gpr[CX].Xx;
P->Gpr[CX].Xx = 0;
}
}
//
// Move items from the source string to the output port.
//
PortNumber = P->SrcValue.Word;
while (Count != 0) {
//
// Set the source value and output to the specified port.
//
XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
(P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
Count -= 1;
}
return;
}