Leaked source code of windows server 2003
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.

557 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. utility.c
  5. Abstract:
  6. This module implements utility functions.
  7. Author:
  8. David N. Cutler (davec) 7-Sep-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "nthal.h"
  14. #include "emulate.h"
  15. //
  16. // Define bit count array.
  17. //
  18. UCHAR XmBitCount[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
  19. ULONG
  20. XmComputeParity (
  21. IN ULONG Result
  22. )
  23. /*++
  24. Routine Description:
  25. This function computes the parity of the low byte of the specified
  26. result.
  27. Arguments:
  28. Result - Supplies the result for which the parity flag is computed.
  29. Return Value:
  30. The parity flag value.
  31. --*/
  32. {
  33. ULONG Count;
  34. //
  35. // Sum the bits in the result and return the complement of the low bit.
  36. //
  37. Count = XmBitCount[Result & 0xf];
  38. Count += XmBitCount[(Result >> 4) & 0xf];
  39. return (~Count) & 1;
  40. }
  41. UCHAR
  42. XmGetCodeByte (
  43. IN PRXM_CONTEXT P
  44. )
  45. /*++
  46. Routine Description:
  47. This function gets the next code byte from the instruction stream.
  48. Arguments:
  49. P - Supplies a pointer to an emulator context structure.
  50. Return Value:
  51. The next byte form the instruction stream.
  52. --*/
  53. {
  54. ULONG Offset;
  55. //
  56. // If the current IP is within the code segment, then return the
  57. // next byte from the instrcution stream and increment the IP value.
  58. // Otherwise, raise an exception.
  59. //
  60. Offset = P->Eip;
  61. if (Offset > P->SegmentLimit[CS]) {
  62. longjmp(&P->JumpBuffer[0], XM_SEGMENT_LIMIT_VIOLATION);
  63. }
  64. P->Ip += 1;
  65. return *(PUCHAR)((P->TranslateAddress)(P->SegmentRegister[CS], (USHORT)Offset));
  66. }
  67. UCHAR
  68. XmGetByteImmediate (
  69. IN PRXM_CONTEXT P
  70. )
  71. /*++
  72. Routine Description:
  73. This function gets an unsigned immediate byte operand from the
  74. code stream and returns a byte value.
  75. Arguments:
  76. P - Supplies a pointer to an emulator context structure.
  77. Return Value:
  78. The next byte from the instruction stream.
  79. --*/
  80. {
  81. UCHAR Byte;
  82. //
  83. // Get immediate byte from the code stream.
  84. //
  85. Byte = XmGetCodeByte(P);
  86. XmTraceInstruction(BYTE_DATA, (ULONG)Byte);
  87. return Byte;
  88. }
  89. USHORT
  90. XmGetByteImmediateToWord (
  91. IN PRXM_CONTEXT P
  92. )
  93. /*++
  94. Routine Description:
  95. This function gets an unsigned immediate byte operand from the
  96. code stream and returns a zero extended byte to word value.
  97. Arguments:
  98. P - Supplies a pointer to an emulator context structure.
  99. Return Value:
  100. The next byte from the instruction stream zero extended to a word.
  101. --*/
  102. {
  103. USHORT Word;
  104. //
  105. // Get immediate byte from the code stream.
  106. //
  107. Word = XmGetCodeByte(P);
  108. XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
  109. return Word;
  110. }
  111. ULONG
  112. XmGetByteImmediateToLong (
  113. IN PRXM_CONTEXT P
  114. )
  115. /*++
  116. Routine Description:
  117. This function gets an unsigned immediate byte operand from the
  118. code stream and returns a zero extended byte to long value.
  119. Arguments:
  120. P - Supplies a pointer to an emulator context structure.
  121. Return Value:
  122. The next byte from the instruction stream zero extended to a long.
  123. --*/
  124. {
  125. ULONG Long;
  126. //
  127. // Get immediate byte from the code stream.
  128. //
  129. Long = XmGetCodeByte(P);
  130. XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
  131. return Long;
  132. }
  133. USHORT
  134. XmGetSignedByteImmediateToWord (
  135. IN PRXM_CONTEXT P
  136. )
  137. /*++
  138. Routine Description:
  139. This function gets an unsigned immediate byte operand from the
  140. code stream and returns a sign extended byte to word value.
  141. Arguments:
  142. P - Supplies a pointer to an emulator context structure.
  143. Return Value:
  144. The next byte from the instruction stream sign extended to a word.
  145. --*/
  146. {
  147. USHORT Word;
  148. //
  149. // Get immediate byte from the code stream.
  150. //
  151. Word = (USHORT)((SHORT)((SCHAR)XmGetCodeByte(P)));
  152. XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Word));
  153. return Word;
  154. }
  155. ULONG
  156. XmGetSignedByteImmediateToLong (
  157. IN PRXM_CONTEXT P
  158. )
  159. /*++
  160. Routine Description:
  161. This function gets an unsigned immediate byte operand from the
  162. code stream and returns a sign extended byte to long value.
  163. Arguments:
  164. P - Supplies a pointer to an emulator context structure.
  165. Return Value:
  166. The next byte from the instruction stream sign extended to a long.
  167. --*/
  168. {
  169. ULONG Long;
  170. //
  171. // Get immediate byte from the code stream.
  172. //
  173. Long = (ULONG)((LONG)((SCHAR)XmGetCodeByte(P)));
  174. XmTraceInstruction(BYTE_DATA, (ULONG)((UCHAR)Long));
  175. return Long;
  176. }
  177. USHORT
  178. XmGetWordImmediate (
  179. IN PRXM_CONTEXT P
  180. )
  181. /*++
  182. Routine Description:
  183. This function gets an unsigned immediate word operand from the
  184. code stream and returns a word value.
  185. Arguments:
  186. P - Supplies a pointer to an emulator context structure.
  187. Return Value:
  188. The next word from the instruction stream.
  189. --*/
  190. {
  191. USHORT Word;
  192. //
  193. // Get immediate word from the code stream.
  194. //
  195. Word = XmGetCodeByte(P);
  196. Word += XmGetCodeByte(P) << 8;
  197. XmTraceInstruction(WORD_DATA, (ULONG)Word);
  198. return Word;
  199. }
  200. ULONG
  201. XmGetLongImmediate (
  202. IN PRXM_CONTEXT P
  203. )
  204. /*++
  205. Routine Description:
  206. This function gets an unsigned immediate long operand from the
  207. code stream and returns a long value.
  208. Arguments:
  209. P - Supplies a pointer to an emulator context structure.
  210. Return Value:
  211. The next long from the instruction stream.
  212. --*/
  213. {
  214. ULONG Long;
  215. //
  216. // Get immediate long from the code stream.
  217. //
  218. Long = XmGetCodeByte(P);
  219. Long += XmGetCodeByte(P) << 8;
  220. Long += XmGetCodeByte(P) << 16;
  221. Long += XmGetCodeByte(P) << 24;
  222. XmTraceInstruction(LONG_DATA, Long);
  223. return Long;
  224. }
  225. ULONG
  226. XmPopStack (
  227. IN PRXM_CONTEXT P
  228. )
  229. /*++
  230. Routine Description:
  231. This function pops an operand from the stack.
  232. Arguments:
  233. P - Supplies a pointer to the emulation context structure.
  234. Return Value:
  235. None.
  236. --*/
  237. {
  238. ULONG Offset;
  239. //
  240. // Compute the new stack address and compare against the segment limit.
  241. // If the new address is greater than the limit, then raise an exception.
  242. // Otherwise, perform the push operation.
  243. //
  244. Offset = P->Gpr[ESP].Exx;
  245. if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
  246. longjmp(&P->JumpBuffer[0], XM_STACK_UNDERFLOW);
  247. }
  248. P->Gpr[ESP].Exx += (P->DataType + 1);
  249. XmSetSourceValue(P, (P->TranslateAddress)(P->SegmentRegister[SS], (USHORT)Offset));
  250. return P->SrcValue.Long;
  251. }
  252. VOID
  253. XmPushStack (
  254. IN PRXM_CONTEXT P,
  255. IN ULONG Value
  256. )
  257. /*++
  258. Routine Description:
  259. This function pushes an operand on the stack.
  260. Arguments:
  261. P - Supplies a pointer to the emulation context structure.
  262. Value - Supplies the value to be pushed.
  263. Return Value:
  264. None.
  265. --*/
  266. {
  267. ULONG Offset;
  268. //
  269. // Compute the new stack address and compare against the segment limit.
  270. // If the new address is greater than the limit, then raise an exception.
  271. // Otherwise, perform the push operation.
  272. //
  273. Offset = P->Gpr[ESP].Exx - P->DataType - 1;
  274. if (Offset > (ULONG)(P->SegmentLimit[SS] - P->DataType)) {
  275. longjmp(&P->JumpBuffer[0], XM_STACK_OVERFLOW);
  276. }
  277. P->Gpr[ESP].Exx = Offset;
  278. P->DstLong = (ULONG UNALIGNED *)((P->TranslateAddress)(P->SegmentRegister[SS],
  279. (USHORT)Offset));
  280. XmStoreResult(P, Value);
  281. return;
  282. }
  283. VOID
  284. XmSetDataType (
  285. IN PRXM_CONTEXT P
  286. )
  287. /*++
  288. Routine Description:
  289. This function sets the data type of the operation based on the width
  290. bit of the current opcode.
  291. Arguments:
  292. P - Supplies a pointer to an emulator context structure.
  293. Return Value:
  294. None.
  295. --*/
  296. {
  297. //
  298. // If the width bit is zero, then the data type is byte. Otherwise,
  299. // the datatype is determined by the presence of absence of a operand
  300. // size prefix.
  301. //
  302. if ((P->CurrentOpcode & WIDTH_BIT) == 0) {
  303. P->DataType = BYTE_DATA;
  304. } else if (P->OpsizePrefixActive != FALSE) {
  305. P->DataType = LONG_DATA;
  306. } else {
  307. P->DataType = WORD_DATA;
  308. }
  309. return;
  310. }
  311. VOID
  312. XmStoreResult (
  313. IN PRXM_CONTEXT P,
  314. IN ULONG Result
  315. )
  316. /*++
  317. Routine Description:
  318. This function stores the result of an operation.
  319. Arguments:
  320. P - Supplies a pointer to an emulator context structure.
  321. Result - Supplies the result value to store.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. //
  327. // Store result of operation.
  328. //
  329. if (P->DataType == BYTE_DATA) {
  330. *P->DstByte = (UCHAR)Result;
  331. } else if (P->DataType == WORD_DATA) {
  332. if (((ULONG_PTR)P->DstWord & 0x1) == 0) {
  333. *((PUSHORT)(P->DstWord)) = (USHORT)Result;
  334. } else {
  335. *P->DstWord = (USHORT)Result;
  336. }
  337. } else {
  338. #ifdef _IA64_
  339. //
  340. // Hack to force the compiler to generate unaligned
  341. // accesses. We can remove it when the compiler is
  342. // fixed.
  343. //
  344. *P->DstLong = Result;
  345. #else
  346. if (((ULONG_PTR)P->DstLong & 0x3) == 0) {
  347. *((PULONG)(P->DstLong)) = Result;
  348. } else {
  349. *P->DstLong = Result;
  350. }
  351. #endif // #ifdef _IA64_
  352. }
  353. XmTraceResult(P, Result);
  354. return;
  355. }