Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
3.8 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. inoutops.c
  5. Abstract:
  6. This module implements the code to emulate the in and out opcodes.
  7. Author:
  8. David N. Cutler (davec) 7-Nov-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "nthal.h"
  14. #include "emulate.h"
  15. VOID
  16. XmInOp (
  17. IN PRXM_CONTEXT P
  18. )
  19. /*++
  20. Routine Description:
  21. This function emulates a inb/w/d opcode.
  22. Arguments:
  23. P - Supplies a pointer to the emulation context structure.
  24. Return Value:
  25. None.
  26. --*/
  27. {
  28. //
  29. // Check if the I/O port number is valid.
  30. //
  31. if ((P->SrcValue.Long + P->DataType) > 0xffff) {
  32. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
  33. }
  34. //
  35. // Set the destination address, input from the specified port, and
  36. // store the result.
  37. //
  38. P->DstLong = (ULONG UNALIGNED *)(&P->Gpr[EAX].Exx);
  39. XmStoreResult(P, (P->ReadIoSpace)(P->DataType, P->SrcValue.Word));
  40. return;
  41. }
  42. VOID
  43. XmInsOp (
  44. IN PRXM_CONTEXT P
  45. )
  46. /*++
  47. Routine Description:
  48. This function emulates a insb/w/d opcode.
  49. Arguments:
  50. P - Supplies a pointer to the emulation context structure.
  51. Return Value:
  52. None.
  53. --*/
  54. {
  55. ULONG Count;
  56. USHORT PortNumber;
  57. //
  58. // If a repeat prefix is active, then the loop count is specified
  59. // by eCX. Otherwise, the loop count is one.
  60. //
  61. Count = 1;
  62. if (P->RepeatPrefixActive != FALSE) {
  63. if (P->OpaddrPrefixActive != FALSE) {
  64. Count = P->Gpr[ECX].Exx;
  65. P->Gpr[ECX].Exx = 0;
  66. } else {
  67. Count = P->Gpr[CX].Xx;
  68. P->Gpr[CX].Xx = 0;
  69. }
  70. }
  71. //
  72. // Move items from the input port to the destination string.
  73. //
  74. PortNumber = P->SrcValue.Word;
  75. while (Count != 0) {
  76. //
  77. // Set the destination address, input from the specified port, and
  78. // store the result.
  79. //
  80. P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
  81. XmStoreResult(P, (P->ReadIoSpace)(P->DataType, PortNumber));
  82. Count -= 1;
  83. }
  84. return;
  85. }
  86. VOID
  87. XmOutOp (
  88. IN PRXM_CONTEXT P
  89. )
  90. /*++
  91. Routine Description:
  92. This function emulates a outb/w/d opcode.
  93. Arguments:
  94. P - Supplies a pointer to the emulation context structure.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. USHORT PortNumber;
  100. //
  101. // Check if the I/O port number is valid.
  102. //
  103. if ((P->SrcValue.Long + P->DataType) > 0xffff) {
  104. longjmp(&P->JumpBuffer[0], XM_ILLEGAL_PORT_NUMBER);
  105. }
  106. //
  107. // Save the port number, get the source value, and output to the port.
  108. //
  109. PortNumber = P->SrcValue.Word;
  110. XmSetSourceValue(P, &P->Gpr[EAX].Exx);
  111. (P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
  112. return;
  113. }
  114. VOID
  115. XmOutsOp (
  116. IN PRXM_CONTEXT P
  117. )
  118. /*++
  119. Routine Description:
  120. This function emulates a outsb/w/d opcode.
  121. Arguments:
  122. P - Supplies a pointer to the emulation context structure.
  123. Return Value:
  124. None.
  125. --*/
  126. {
  127. ULONG Count;
  128. USHORT PortNumber;
  129. //
  130. // If a repeat prefix is active, then the loop count is specified
  131. // by eCX. Otherwise, the loop count is one.
  132. //
  133. Count = 1;
  134. if (P->RepeatPrefixActive != FALSE) {
  135. if (P->OpaddrPrefixActive != FALSE) {
  136. Count = P->Gpr[ECX].Exx;
  137. P->Gpr[ECX].Exx = 0;
  138. } else {
  139. Count = P->Gpr[CX].Xx;
  140. P->Gpr[CX].Xx = 0;
  141. }
  142. }
  143. //
  144. // Move items from the source string to the output port.
  145. //
  146. PortNumber = P->SrcValue.Word;
  147. while (Count != 0) {
  148. //
  149. // Set the source value and output to the specified port.
  150. //
  151. XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
  152. (P->WriteIoSpace)(P->DataType, PortNumber, P->SrcValue.Long);
  153. Count -= 1;
  154. }
  155. return;
  156. }