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.

340 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1995 Digital Equipment Corporation
  3. Module Name:
  4. byteem.c
  5. Abstract:
  6. This module implements the code necessary to emulate the new set of Alpha
  7. byte and word instructions defined by ECO 81.
  8. N.B. This file must be compiled without the use of byte/word instructions
  9. to avoid fatal recursive exceptions.
  10. Author:
  11. Wim Colgate (colgate) 18-May-1995
  12. Thomas Van Baak (tvb) 18-May-1995
  13. Environment:
  14. Kernel mode only.
  15. Revision History:
  16. --*/
  17. #include "ki.h"
  18. //
  19. // Define function prototypes for emulation routines written in assembler.
  20. //
  21. VOID
  22. KiInterlockedStoreByte (
  23. IN PUCHAR Address,
  24. IN UCHAR Data
  25. );
  26. VOID
  27. KiInterlockedStoreWord (
  28. IN PUSHORT Address,
  29. IN USHORT Data
  30. );
  31. BOOLEAN
  32. KiEmulateByteWord (
  33. IN OUT PEXCEPTION_RECORD ExceptionRecord,
  34. IN OUT PKEXCEPTION_FRAME ExceptionFrame,
  35. IN OUT PKTRAP_FRAME TrapFrame
  36. )
  37. /*++
  38. Routine Description:
  39. This routine emulates Alpha instructions defined by ECO 81. This includes
  40. the load byte unsigned, store byte, load word unsigned, store word, sign
  41. extend byte, and sign extend word instructions.
  42. If a misaligned word access is detected the illegal instruction exception
  43. record is converted into data misalignment exception record, no emulation
  44. is performed, and a value of FALSE is returned. It is expected that the
  45. call to this function is followed by a check for a data misalignment
  46. exception and a call to the data misalignment emulation function if
  47. appropriate.
  48. Arguments:
  49. ExceptionRecord - Supplies a pointer to the exception record.
  50. ExceptionFrame - Supplies a pointer to an exception frame.
  51. TrapFrame - Supplies a pointer to a trap frame.
  52. Return Value:
  53. A value of TRUE is returned if the instruction is successfully emulated,
  54. otherwise a value of FALSE is returned.
  55. --*/
  56. {
  57. ULONGLONG Data;
  58. ULONGLONG EffectiveAddress;
  59. PVOID ExceptionAddress;
  60. ALPHA_INSTRUCTION Instruction;
  61. KIRQL OldIrql;
  62. KPROCESSOR_MODE PreviousMode;
  63. //
  64. // Save original exception address in case another exception occurs.
  65. //
  66. ExceptionAddress = ExceptionRecord->ExceptionAddress;
  67. //
  68. // Any exception that occurs during the attempted emulation will cause
  69. // the emulation to be aborted. The new exception code and information
  70. // will be copied to the original exception record and FALSE will be
  71. // returned. If the memory access was not from kernel mode then probe
  72. // the effective address before performing the emulation.
  73. //
  74. //
  75. // Capture previous mode from trap frame not current thread.
  76. //
  77. PreviousMode = (KPROCESSOR_MODE)(((PSR *)(&TrapFrame->Psr))->MODE);
  78. try {
  79. //
  80. // Get faulting instruction and case on instruction type.
  81. //
  82. if (PreviousMode != KernelMode) {
  83. ProbeForRead(ExceptionAddress,
  84. sizeof(ALPHA_INSTRUCTION),
  85. sizeof(ALPHA_INSTRUCTION));
  86. }
  87. Instruction = *((PALPHA_INSTRUCTION)ExceptionAddress);
  88. switch (Instruction.Memory.Opcode) {
  89. //
  90. // Load/store operations.
  91. //
  92. case LDBU_OP :
  93. case LDWU_OP :
  94. case STB_OP :
  95. case STW_OP :
  96. //
  97. // Compute effective address and if the address is non-canonical
  98. // then change the exception code to STATUS_ACCESS_VIOLATION and
  99. // return FALSE.
  100. //
  101. EffectiveAddress = (ULONGLONG)Instruction.Memory.MemDisp +
  102. KiGetRegisterValue(Instruction.Memory.Rb,
  103. ExceptionFrame,
  104. TrapFrame);
  105. if (EffectiveAddress != (ULONGLONG)(PVOID)EffectiveAddress) {
  106. ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
  107. ExceptionRecord->NumberParameters = 0;
  108. return FALSE;
  109. }
  110. //
  111. // Case on individual load/store instruction type.
  112. //
  113. switch (Instruction.Memory.Opcode) {
  114. //
  115. // Load byte unsigned.
  116. //
  117. case LDBU_OP :
  118. if (PreviousMode != KernelMode) {
  119. ProbeForRead(EffectiveAddress,
  120. sizeof(UCHAR),
  121. sizeof(UCHAR));
  122. }
  123. Data = (ULONGLONG)*(PUCHAR)EffectiveAddress;
  124. KiSetRegisterValue(Instruction.Memory.Ra,
  125. Data,
  126. ExceptionFrame,
  127. TrapFrame);
  128. break;
  129. //
  130. // Load word unsigned.
  131. //
  132. case LDWU_OP :
  133. if (EffectiveAddress & 0x1) {
  134. goto AlignmentFault;
  135. }
  136. if (PreviousMode != KernelMode) {
  137. ProbeForRead((PUSHORT)EffectiveAddress,
  138. sizeof(USHORT),
  139. sizeof(UCHAR));
  140. }
  141. Data = (ULONGLONG)*(PUSHORT)EffectiveAddress;
  142. KiSetRegisterValue(Instruction.Memory.Ra,
  143. Data,
  144. ExceptionFrame,
  145. TrapFrame);
  146. break;
  147. //
  148. // Store byte.
  149. //
  150. case STB_OP :
  151. if (PreviousMode != KernelMode) {
  152. ProbeForWrite((PUCHAR)EffectiveAddress,
  153. sizeof(UCHAR),
  154. sizeof(UCHAR));
  155. }
  156. Data = KiGetRegisterValue(Instruction.Memory.Ra,
  157. ExceptionFrame,
  158. TrapFrame);
  159. KiInterlockedStoreByte((PUCHAR)EffectiveAddress,
  160. (UCHAR)Data);
  161. break;
  162. //
  163. // Store word.
  164. //
  165. case STW_OP :
  166. if (EffectiveAddress & 0x1) {
  167. goto AlignmentFault;
  168. }
  169. if (PreviousMode != KernelMode) {
  170. ProbeForWrite((PUSHORT)EffectiveAddress,
  171. sizeof(USHORT),
  172. sizeof(UCHAR));
  173. }
  174. Data = KiGetRegisterValue(Instruction.Memory.Ra,
  175. ExceptionFrame,
  176. TrapFrame);
  177. KiInterlockedStoreWord((PUSHORT)EffectiveAddress,
  178. (USHORT)Data);
  179. break;
  180. }
  181. break;
  182. //
  183. // Sign extend operations.
  184. //
  185. case SEXT_OP :
  186. switch (Instruction.OpReg.Function) {
  187. //
  188. // Sign extend byte.
  189. //
  190. case SEXTB_FUNC :
  191. Data = KiGetRegisterValue(Instruction.OpReg.Rb,
  192. ExceptionFrame,
  193. TrapFrame);
  194. KiSetRegisterValue(Instruction.OpReg.Rc,
  195. (ULONGLONG)(CHAR)Data,
  196. ExceptionFrame,
  197. TrapFrame);
  198. break;
  199. //
  200. // Sign extend word.
  201. //
  202. case SEXTW_FUNC :
  203. Data = KiGetRegisterValue(Instruction.OpReg.Rb,
  204. ExceptionFrame,
  205. TrapFrame);
  206. KiSetRegisterValue(Instruction.OpReg.Rc,
  207. (ULONGLONG)(SHORT)Data,
  208. ExceptionFrame,
  209. TrapFrame);
  210. break;
  211. //
  212. // All other functions are not emulated.
  213. //
  214. default :
  215. return FALSE;
  216. }
  217. break;
  218. //
  219. // All other instructions are not emulated.
  220. //
  221. default :
  222. return FALSE;
  223. }
  224. #if 0
  225. //
  226. // Call out to profile interrupt if byte/word emulation profiling is
  227. // active.
  228. //
  229. if (KiProfileByteWordEmulation != FALSE) {
  230. if (++KiProfileByteWordEmulationCount >=
  231. KiProfileByteWordEmulationInterval) {
  232. KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
  233. KiProfileByteWordEmulationCount = 0;
  234. KeProfileInterruptWithSource(TrapFrame,
  235. ProfileByteWordEmulation);
  236. KeLowerIrql(OldIrql);
  237. }
  238. }
  239. #endif
  240. TrapFrame->Fir += 4;
  241. return TRUE;
  242. } except (KiCopyInformation(ExceptionRecord,
  243. (GetExceptionInformation())->ExceptionRecord)) {
  244. //
  245. // Preserve the original exception address.
  246. //
  247. ExceptionRecord->ExceptionAddress = ExceptionAddress;
  248. return FALSE;
  249. }
  250. AlignmentFault :
  251. //
  252. // A misaligned word access has been encountered. Change the illegal
  253. // instruction exception record into data misalignment exception record
  254. // (the format is defined by PALcode) and return FALSE.
  255. //
  256. ExceptionRecord->ExceptionCode = STATUS_DATATYPE_MISALIGNMENT;
  257. ExceptionRecord->NumberParameters = 3;
  258. ExceptionRecord->ExceptionInformation[0] = Instruction.Memory.Opcode;
  259. ExceptionRecord->ExceptionInformation[1] = Instruction.Memory.Ra;
  260. ExceptionRecord->ExceptionInformation[2] = (ULONG)EffectiveAddress;
  261. return FALSE;
  262. }