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.

580 lines
11 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. mulops.c
  5. Abstract:
  6. This module implements the code to emulate the shift opcodes.
  7. Author:
  8. David N. Cutler (davec) 21-Sep-1994
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "nthal.h"
  14. #include "emulate.h"
  15. VOID
  16. XmRolOp (
  17. IN PRXM_CONTEXT P
  18. )
  19. /*++
  20. Routine Description:
  21. This function emulates a rol opcode.
  22. Arguments:
  23. P - Supplies a pointer to the emulation context structure.
  24. Return Value:
  25. None.
  26. --*/
  27. {
  28. ULONG Carry;
  29. ULONG Count;
  30. ULONG Mask;
  31. ULONG Shift;
  32. ULONG Value;
  33. //
  34. // Rotate destination left and store result.
  35. //
  36. Shift = ((P->DataType + 1) << 3) - 1;
  37. Mask = ((1 << Shift) - 1) | (1 << Shift);
  38. Value = P->DstValue.Long;
  39. Count = P->SrcValue.Long & Shift;
  40. if (Count != 0) {
  41. if (Count == 1) {
  42. P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value >> (Shift - 1));
  43. }
  44. do {
  45. Carry = Value >> Shift;
  46. Value = Carry | ((Value << 1) & Mask);
  47. Count -= 1;
  48. } while (Count != 0);
  49. P->Eflags.EFLAG_CF = Carry;
  50. }
  51. XmStoreResult(P, Value);
  52. return;
  53. }
  54. VOID
  55. XmRorOp (
  56. IN PRXM_CONTEXT P
  57. )
  58. /*++
  59. Routine Description:
  60. This function emulates a ror opcode.
  61. Arguments:
  62. P - Supplies a pointer to the emulation context structure.
  63. Return Value:
  64. None.
  65. --*/
  66. {
  67. ULONG Carry;
  68. ULONG Count;
  69. ULONG Shift;
  70. ULONG Value;
  71. //
  72. // Rotate destination right and store result.
  73. //
  74. Shift = ((P->DataType + 1) << 3) - 1;
  75. Value = P->DstValue.Long;
  76. Count = P->SrcValue.Long & Shift;
  77. if (Count != 0) {
  78. if (Count == 1) {
  79. P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value & 0x1);
  80. }
  81. do {
  82. Carry = Value & 1;
  83. Value = (Carry << Shift) | (Value >> 1);
  84. Count -= 1;
  85. } while (Count != 0 );
  86. P->Eflags.EFLAG_CF = Carry;
  87. }
  88. XmStoreResult(P, Value);
  89. return;
  90. }
  91. VOID
  92. XmRclOp (
  93. IN PRXM_CONTEXT P
  94. )
  95. /*++
  96. Routine Description:
  97. This function emulates a rcl opcode.
  98. Arguments:
  99. P - Supplies a pointer to the emulation context structure.
  100. Return Value:
  101. None.
  102. --*/
  103. {
  104. ULONG Carry;
  105. ULONG Count;
  106. ULONG Mask;
  107. ULONG Shift;
  108. ULONG Temp;
  109. ULONG Value;
  110. //
  111. // Rotate destination left through carry and store result.
  112. //
  113. Shift = ((P->DataType + 1) << 3) - 1;
  114. Mask = ((1 << Shift) - 1) | (1 << Shift);
  115. Value = P->DstValue.Long;
  116. Count = P->SrcValue.Long & Shift;
  117. Carry = P->Eflags.EFLAG_CF;
  118. if (Count != 0) {
  119. if (Count == 1) {
  120. P->Eflags.EFLAG_OF = (Value >> Shift) ^ (Value >> (Shift - 1));
  121. }
  122. do {
  123. Temp = Value >> Shift;
  124. Value = ((Value << 1) & Mask) | Carry;
  125. Carry = Temp;
  126. Count -= 1;
  127. } while (Count != 0);
  128. }
  129. XmStoreResult(P, Value);
  130. P->Eflags.EFLAG_CF = Carry;
  131. return;
  132. }
  133. VOID
  134. XmRcrOp (
  135. IN PRXM_CONTEXT P
  136. )
  137. /*++
  138. Routine Description:
  139. This function emulates a rcr opcode.
  140. Arguments:
  141. P - Supplies a pointer to the emulation context structure.
  142. Return Value:
  143. None.
  144. --*/
  145. {
  146. ULONG Carry;
  147. ULONG Count;
  148. ULONG Shift;
  149. ULONG Temp;
  150. ULONG Value;
  151. //
  152. // Rotate destination right through carry and store result.
  153. //
  154. Shift = ((P->DataType + 1) << 3) - 1;
  155. Value = P->DstValue.Long;
  156. Count = P->SrcValue.Long & Shift;
  157. Carry = P->Eflags.EFLAG_CF;
  158. if (Count != 0) {
  159. if (Count == 1) {
  160. P->Eflags.EFLAG_OF = (Value >> Shift) ^ Carry;
  161. }
  162. do {
  163. Temp = Value & 1;
  164. Value = (Carry << Shift) | (Value >> 1);
  165. Carry = Temp;
  166. Count -= 1;
  167. } while (Count != 0);
  168. }
  169. XmStoreResult(P, Value);
  170. P->Eflags.EFLAG_CF = Carry;
  171. return;
  172. }
  173. VOID
  174. XmShlOp (
  175. IN PRXM_CONTEXT P
  176. )
  177. /*++
  178. Routine Description:
  179. This function emulates a shl opcode.
  180. Arguments:
  181. P - Supplies a pointer to the emulation context structure.
  182. Return Value:
  183. None.
  184. --*/
  185. {
  186. ULONG Carry;
  187. ULONG Count;
  188. ULONG Overflow;
  189. ULONG Shift;
  190. ULONG Value;
  191. //
  192. // Shift destination left logical and store result.
  193. //
  194. Shift = ((P->DataType + 1) << 3) - 1;
  195. Value = P->DstValue.Long;
  196. Count = P->SrcValue.Long;
  197. if (Count != 0) {
  198. if (P->DataType == LONG_DATA) {
  199. Overflow = (Value ^ (Value << 1)) >> 31;
  200. Carry = Value >> (32 - Count);
  201. Value <<= Count;
  202. } else if (P->DataType == WORD_DATA) {
  203. Overflow = (Value ^ (Value << 1)) >> 15;
  204. Carry = Value >> (16 - Count);
  205. Value = (Value << Count) & 0xffff;
  206. } else {
  207. Overflow = (Value ^ (Value << 1)) >> 7;
  208. Carry = Value >> (8 - Count);
  209. Value = (Value << Count) & 0xff;
  210. }
  211. P->Eflags.EFLAG_CF = Carry;
  212. P->Eflags.EFLAG_OF = Overflow;
  213. P->Eflags.EFLAG_PF = XmComputeParity(Value);
  214. P->Eflags.EFLAG_ZF = (Value == 0);
  215. P->Eflags.EFLAG_SF = Value >> Shift;
  216. }
  217. XmStoreResult(P, Value);
  218. return;
  219. }
  220. VOID
  221. XmShrOp (
  222. IN PRXM_CONTEXT P
  223. )
  224. /*++
  225. Routine Description:
  226. This function emulates a shr opcode.
  227. Arguments:
  228. P - Supplies a pointer to the emulation context structure.
  229. Return Value:
  230. None.
  231. --*/
  232. {
  233. ULONG Carry;
  234. ULONG Count;
  235. ULONG Overflow;
  236. ULONG Shift;
  237. ULONG Value;
  238. //
  239. // Shift destination right logical and store result.
  240. //
  241. Shift = ((P->DataType + 1) << 3) - 1;
  242. Value = P->DstValue.Long;
  243. Count = P->SrcValue.Long;
  244. if (Count != 0) {
  245. if (P->DataType == LONG_DATA) {
  246. Overflow = Value >> 31;
  247. Carry = Value >> (Count - 1);
  248. Value >>= Count;
  249. } else if (P->DataType == WORD_DATA) {
  250. Overflow = Value >> 15;
  251. Carry = Value >> (Count - 1);
  252. Value >>= Count;
  253. } else {
  254. Overflow = Value >> 7;
  255. Carry = Value >> (Count - 1);
  256. Value >>= Count;
  257. }
  258. P->Eflags.EFLAG_CF = Carry;
  259. P->Eflags.EFLAG_OF = Overflow;
  260. P->Eflags.EFLAG_PF = XmComputeParity(Value);
  261. P->Eflags.EFLAG_ZF = (Value == 0);
  262. P->Eflags.EFLAG_SF = Value >> Shift;
  263. }
  264. XmStoreResult(P, Value);
  265. return;
  266. }
  267. VOID
  268. XmSarOp (
  269. IN PRXM_CONTEXT P
  270. )
  271. /*++
  272. Routine Description:
  273. This function emulates a sar opcode.
  274. Arguments:
  275. P - Supplies a pointer to the emulation context structure.
  276. Return Value:
  277. None.
  278. --*/
  279. {
  280. ULONG Carry;
  281. ULONG Count;
  282. ULONG Shift;
  283. LONG Value;
  284. //
  285. // Shift destination right arithmetic and store result.
  286. //
  287. Shift = ((P->DataType + 1) << 3) - 1;
  288. Value = (LONG)P->DstValue.Long;
  289. Count = P->SrcValue.Long;
  290. if (Count != 0) {
  291. if (P->DataType == LONG_DATA) {
  292. Carry = Value >> (Count - 1);
  293. Value >>= Count;
  294. } else if (P->DataType == WORD_DATA) {
  295. Carry = Value >> (Count - 1);
  296. Value = ((Value << 16) >> (Count + 16)) & 0xffff;
  297. } else {
  298. Carry = Value >> (Count - 1);
  299. Value = ((Value << 24) >> (Count + 24)) & 0xff;
  300. }
  301. P->Eflags.EFLAG_CF = Carry;
  302. P->Eflags.EFLAG_OF = 0;
  303. P->Eflags.EFLAG_PF = XmComputeParity(Value);
  304. P->Eflags.EFLAG_ZF = (Value == 0);
  305. P->Eflags.EFLAG_SF = Value >> Shift;
  306. }
  307. XmStoreResult(P, (ULONG)Value);
  308. return;
  309. }
  310. VOID
  311. XmShldOp (
  312. IN PRXM_CONTEXT P
  313. )
  314. /*++
  315. Routine Description:
  316. This function emulates a shld opcode.
  317. Arguments:
  318. P - Supplies a pointer to the emulation context structure.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. ULONG Carry;
  324. ULONG Count;
  325. ULONG High;
  326. ULONG Low;
  327. ULONG Sign;
  328. //
  329. // Double shift left logical and store result.
  330. //
  331. // The low 32-bits of the shift are the source.
  332. // The high 32-bits of the shift are the destination.
  333. // The shift count has been masked modulo the datatype.
  334. //
  335. // This shift is equivalent to extracting the high 32-bits of the left
  336. // shifted result.
  337. //
  338. Low = P->SrcValue.Long;
  339. High = P->DstValue.Long;
  340. Count = P->Shift;
  341. if (Count != 0) {
  342. if (P->DataType == LONG_DATA) {
  343. if (Count == 1) {
  344. P->Eflags.EFLAG_OF = (High ^ (High << 1)) >> 31;
  345. }
  346. Carry = High >> (32 - Count);
  347. High = (High << Count) | (Low >> (32 - Count));
  348. Sign = High >> 31;
  349. } else {
  350. if (Count == 1) {
  351. P->Eflags.EFLAG_OF = (High ^ (High << 1)) >> 15;
  352. }
  353. Carry = High >> (16 - Count);
  354. High = ((High << Count) | (Low >> (16 - Count))) & 0xffff;
  355. Sign = High >> 15;
  356. }
  357. P->Eflags.EFLAG_CF = Carry;
  358. P->Eflags.EFLAG_PF = XmComputeParity(High);
  359. P->Eflags.EFLAG_ZF = (High == 0);
  360. P->Eflags.EFLAG_SF = Sign;
  361. }
  362. XmStoreResult(P, High);
  363. return;
  364. }
  365. VOID
  366. XmShrdOp (
  367. IN PRXM_CONTEXT P
  368. )
  369. /*++
  370. Routine Description:
  371. This function emulates a shrd opcode.
  372. Arguments:
  373. P - Supplies a pointer to the emulation context structure.
  374. Return Value:
  375. None.
  376. --*/
  377. {
  378. ULONG Carry;
  379. ULONG Count;
  380. ULONG High;
  381. ULONG Low;
  382. ULONG Sign;
  383. //
  384. // Double shift right logical and store result.
  385. //
  386. // The high 32-bits of the shift are the source.
  387. // The low 32-bits of the shift are the destination.
  388. // The shift count has been masked modulo the datatype.
  389. //
  390. // This shift is equivalent to extracting the low 32-bits of the right
  391. // shifted result.
  392. //
  393. High = P->SrcValue.Long;
  394. Low = P->DstValue.Long;
  395. Count = P->Shift;
  396. if (Count != 0) {
  397. if (P->DataType == LONG_DATA) {
  398. if (Count == 1) {
  399. P->Eflags.EFLAG_OF = High ^ (Low >> 31);
  400. }
  401. Carry = Low >> (Count - 1);
  402. Low = (High << (32 - Count)) | (Low >> Count);
  403. Sign = Low >> 31;
  404. } else {
  405. if (Count == 1) {
  406. P->Eflags.EFLAG_OF = High ^ (Low >> 15);
  407. }
  408. Carry = Low >> (Count - 1);
  409. Low = ((High << (16 - Count)) | (Low >> Count)) & 0xffff;
  410. Sign = Low >> 15;
  411. }
  412. P->Eflags.EFLAG_CF = Carry;
  413. P->Eflags.EFLAG_PF = XmComputeParity(Low);
  414. P->Eflags.EFLAG_ZF = (Low == 0);
  415. P->Eflags.EFLAG_SF = Sign;
  416. }
  417. XmStoreResult(P, Low);
  418. return;
  419. }