Windows NT 4.0 source code leak
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.

496 lines
8.8 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. stringop.c
  5. Abstract:
  6. This module implements the code to emulate the string 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. //
  16. // Define forward referenced prototypes.
  17. //
  18. VOID
  19. XmCompareOperands (
  20. IN PRXM_CONTEXT P
  21. );
  22. VOID
  23. XmCmpsOp (
  24. IN PRXM_CONTEXT P
  25. )
  26. /*++
  27. Routine Description:
  28. This function emulates a cmpsb/w/d opcode.
  29. Arguments:
  30. P - Supplies a pointer to the emulation context structure.
  31. Return Value:
  32. None.
  33. --*/
  34. {
  35. ULONG Count;
  36. //
  37. // If a repeat prefix is active, then the loop count is specified
  38. // by eCX. Otherwise, the loop count is one.
  39. //
  40. Count = 1;
  41. if (P->RepeatPrefixActive != FALSE) {
  42. if (P->OpaddrPrefixActive != FALSE) {
  43. Count = P->Gpr[ECX].Exx;
  44. } else {
  45. Count = P->Gpr[CX].Xx;
  46. }
  47. }
  48. //
  49. // Compare items from source and destination.
  50. //
  51. while (Count != 0) {
  52. //
  53. // Set source and destination values.
  54. //
  55. XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
  56. XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
  57. //
  58. // Compare source with destination operand and decrement loop count.
  59. // If ZF is not equal to the repeat Z flag condition, then terminate
  60. // the loop.
  61. //
  62. XmCompareOperands(P);
  63. Count -= 1;
  64. if (P->Eflags.ZF != P->RepeatZflag) {
  65. break;
  66. }
  67. }
  68. //
  69. // If a repeat prefix is active, then set the final count value.
  70. //
  71. if (P->RepeatPrefixActive != FALSE) {
  72. if (P->OpaddrPrefixActive != FALSE) {
  73. P->Gpr[ECX].Exx = Count;
  74. } else {
  75. P->Gpr[CX].Xx = (USHORT)Count;
  76. }
  77. }
  78. return;
  79. }
  80. VOID
  81. XmLodsOp (
  82. IN PRXM_CONTEXT P
  83. )
  84. /*++
  85. Routine Description:
  86. This function emulates a lodsb/w/d opcode.
  87. Arguments:
  88. P - Supplies a pointer to the emulation context structure.
  89. Return Value:
  90. None.
  91. --*/
  92. {
  93. ULONG Count;
  94. //
  95. // If a repeat prefix is active, then the loop count is specified
  96. // by eCX. Otherwise, the loop count is one.
  97. //
  98. Count = 1;
  99. if (P->RepeatPrefixActive != FALSE) {
  100. if (P->OpaddrPrefixActive != FALSE) {
  101. Count = P->Gpr[ECX].Exx;
  102. P->Gpr[ECX].Exx = 0;
  103. } else {
  104. Count = P->Gpr[CX].Xx;
  105. P->Gpr[CX].Xx = 0;
  106. }
  107. }
  108. //
  109. // Set destination address.
  110. //
  111. P->DstLong = (ULONG UNALIGNED *)&P->Gpr[EAX].Exx;
  112. //
  113. // Move items from source to destination.
  114. //
  115. while (Count != 0) {
  116. //
  117. // Set source value and store result.
  118. //
  119. XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
  120. XmStoreResult(P, P->SrcValue.Long);
  121. Count -= 1;
  122. }
  123. return;
  124. }
  125. VOID
  126. XmMovsOp (
  127. IN PRXM_CONTEXT P
  128. )
  129. /*++
  130. Routine Description:
  131. This function emulates a movsb/w/d opcode.
  132. Arguments:
  133. P - Supplies a pointer to the emulation context structure.
  134. Return Value:
  135. None.
  136. --*/
  137. {
  138. ULONG Count;
  139. //
  140. // If a repeat prefix is active, then the loop count is specified
  141. // by eCX. Otherwise, the loop count is one.
  142. //
  143. Count = 1;
  144. if (P->RepeatPrefixActive != FALSE) {
  145. if (P->OpaddrPrefixActive != FALSE) {
  146. Count = P->Gpr[ECX].Exx;
  147. P->Gpr[ECX].Exx = 0;
  148. } else {
  149. Count = P->Gpr[CX].Xx;
  150. P->Gpr[CX].Xx = 0;
  151. }
  152. }
  153. //
  154. // Move items from source to destination.
  155. //
  156. while (Count != 0) {
  157. //
  158. // Set source value, set destination address, and store result.
  159. //
  160. XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
  161. P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
  162. XmStoreResult(P, P->SrcValue.Long);
  163. Count -= 1;
  164. }
  165. return;
  166. }
  167. VOID
  168. XmScasOp (
  169. IN PRXM_CONTEXT P
  170. )
  171. /*++
  172. Routine Description:
  173. This function emulates a scasb/w/d opcode.
  174. Arguments:
  175. P - Supplies a pointer to the emulation context structure.
  176. Return Value:
  177. None.
  178. --*/
  179. {
  180. ULONG Count;
  181. //
  182. // If a repeat prefix is active, then the loop count is specified
  183. // by eCX. Otherwise, the loop count is one.
  184. //
  185. Count = 1;
  186. if (P->RepeatPrefixActive != FALSE) {
  187. if (P->OpaddrPrefixActive != FALSE) {
  188. Count = P->Gpr[ECX].Exx;
  189. } else {
  190. Count = P->Gpr[CX].Xx;
  191. }
  192. }
  193. //
  194. // Set source value.
  195. //
  196. XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
  197. //
  198. // Compare items from source and destination.
  199. //
  200. while (Count != 0) {
  201. //
  202. // Set destination value.
  203. //
  204. XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
  205. //
  206. // Compare source with destination operand and decrement loop count.
  207. // If ZF is not equal to the repeat Z flag condition, then terminate
  208. // the loop.
  209. //
  210. XmCompareOperands(P);
  211. Count -= 1;
  212. if (P->Eflags.ZF != P->RepeatZflag) {
  213. break;
  214. }
  215. }
  216. //
  217. // If a repeat prefix is active, then set the final count value.
  218. //
  219. if (P->RepeatPrefixActive != FALSE) {
  220. if (P->OpaddrPrefixActive != FALSE) {
  221. P->Gpr[ECX].Exx = Count;
  222. } else {
  223. P->Gpr[CX].Xx = (USHORT)Count;
  224. }
  225. }
  226. return;
  227. }
  228. VOID
  229. XmStosOp (
  230. IN PRXM_CONTEXT P
  231. )
  232. /*++
  233. Routine Description:
  234. This function emulates a stosb/w/d opcode.
  235. Arguments:
  236. P - Supplies a pointer to the emulation context structure.
  237. Return Value:
  238. None.
  239. --*/
  240. {
  241. ULONG Count;
  242. //
  243. // If a repeat prefix is active, then the loop count is specified
  244. // by eCX. Otherwise, the loop count is one.
  245. //
  246. Count = 1;
  247. if (P->RepeatPrefixActive != FALSE) {
  248. if (P->OpaddrPrefixActive != FALSE) {
  249. Count = P->Gpr[ECX].Exx;
  250. P->Gpr[ECX].Exx = 0;
  251. } else {
  252. Count = P->Gpr[CX].Xx;
  253. P->Gpr[CX].Xx = 0;
  254. }
  255. }
  256. //
  257. // Set source value.
  258. //
  259. XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
  260. //
  261. // Move items from source to destination.
  262. //
  263. while (Count != 0) {
  264. //
  265. // Set destination address and store result.
  266. //
  267. P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
  268. XmStoreResult(P, P->SrcValue.Long);
  269. Count -= 1;
  270. }
  271. return;
  272. }
  273. VOID
  274. XmCompareOperands (
  275. IN PRXM_CONTEXT P
  276. )
  277. /*++
  278. Routine Description:
  279. This function compares two operands and computes the resulting condition
  280. codes.
  281. Arguments:
  282. P - Supplies a pointer to the emulation context structure.
  283. Return Value:
  284. None.
  285. --*/
  286. {
  287. ULONG CarryFlag;
  288. ULONG OverflowFlag;
  289. ULONG SignFlag;
  290. ULONG ZeroFlag;
  291. union {
  292. UCHAR ResultByte;
  293. ULONG ResultLong;
  294. USHORT ResultWord;
  295. } u;
  296. //
  297. // Switch on data type.
  298. //
  299. switch (P->DataType) {
  300. //
  301. // The operation datatype is byte.
  302. //
  303. case BYTE_DATA:
  304. CarryFlag = (P->SrcValue.Byte < P->DstValue.Byte);
  305. u.ResultByte = P->SrcValue.Byte - P->DstValue.Byte;
  306. OverflowFlag = (((u.ResultByte ^ P->SrcValue.Byte) &
  307. (u.ResultByte ^ P->DstValue.Byte)) >> 7) & 0x1;
  308. SignFlag = (u.ResultByte >> 7) & 0x1;
  309. ZeroFlag = (u.ResultByte == 0);
  310. u.ResultLong = u.ResultByte;
  311. break;
  312. //
  313. // The operation datatype is word.
  314. //
  315. case WORD_DATA:
  316. CarryFlag = (P->SrcValue.Word < P->DstValue.Word);
  317. u.ResultWord = P->SrcValue.Word - P->DstValue.Word;
  318. OverflowFlag = (((u.ResultWord ^ P->SrcValue.Word) &
  319. (u.ResultWord ^ P->DstValue.Word)) >> 15) & 0x1;
  320. SignFlag = (u.ResultWord >> 15) & 0x1;
  321. ZeroFlag = (u.ResultWord == 0);
  322. u.ResultLong = u.ResultWord;
  323. break;
  324. //
  325. // The operation datatype is long.
  326. //
  327. case LONG_DATA:
  328. CarryFlag = (P->SrcValue.Long < P->DstValue.Long);
  329. u.ResultLong = P->SrcValue.Long - P->DstValue.Long;
  330. OverflowFlag = (((u.ResultLong ^ P->SrcValue.Long) &
  331. (u.ResultLong ^ P->DstValue.Long)) >> 31) & 0x1;
  332. SignFlag = (u.ResultLong >> 31) & 0x1;
  333. ZeroFlag = (u.ResultLong == 0);
  334. break;
  335. }
  336. //
  337. // Compute auxilary carry flag, parity flag, and store all flags in
  338. // the flags register.
  339. //
  340. P->Eflags.CF = CarryFlag;
  341. P->Eflags.PF = XmComputeParity(u.ResultLong);
  342. P->Eflags.AF = ((P->DstValue.Byte & 0xf) + (P->SrcValue.Byte & 0xf)) >> 4;
  343. P->Eflags.ZF = ZeroFlag;
  344. P->Eflags.SF = SignFlag;
  345. P->Eflags.OF = OverflowFlag;
  346. return;
  347. }