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.

848 lines
19 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. shareda.c
  5. Abstract:
  6. Instruction fragments with common (shared) BYTE, WORD, and DWORD flavors.
  7. Compiled twice per flavor, once with UNALIGNED and once with ALIGNED
  8. pointers.
  9. Author:
  10. 05-Nov-1995 BarryBo
  11. Revision History:
  12. --*/
  13. // THIS FILE IS #include'd INTO FILES WHICH DEFINE THE FOLLOWING MACROS:
  14. // MSB - most significant bit
  15. // UTYPE - UNSIGNED type which defines registers (BYTE/USHORT/DWORD)
  16. // STYPE - SIGNED type which defines registers (char/short/long)
  17. // GET_VAL - dereference a pointer of the right type (GET_BYTE/...)
  18. // PUT_VAL - writes a value into memory
  19. // FRAGCOMMON{0,1,2} - mangles the function name and declares parameters
  20. // AREG - al/ax/eax
  21. // BREG - ...
  22. // CREG - ...
  23. // DREG - ...
  24. FRAGCOMMON2(AddFrag)
  25. {
  26. UTYPE result;
  27. UTYPE op1 = GET_VAL(pop1);
  28. result = op1 + op2;
  29. PUT_VAL(pop1, result);
  30. SET_FLAGS_ADD(result, op1, op2, MSB);
  31. }
  32. FRAGCOMMON2(AddNoFlagsFrag)
  33. {
  34. UTYPE result;
  35. UTYPE op1 = GET_VAL(pop1);
  36. result = op1 + op2;
  37. PUT_VAL(pop1, result);
  38. }
  39. FRAGCOMMON1(IncFrag)
  40. {
  41. UTYPE op1, result;
  42. op1 = GET_VAL(pop1);
  43. result = op1+1;
  44. PUT_VAL(pop1, result);
  45. SET_FLAGS_INC(result, op1);
  46. }
  47. FRAGCOMMON1(IncNoFlagsFrag)
  48. {
  49. UTYPE op1, result;
  50. op1 = GET_VAL(pop1);
  51. result = op1+1;
  52. PUT_VAL(pop1, result);
  53. }
  54. FRAGCOMMON1(DecFrag)
  55. {
  56. UTYPE op1, result;
  57. op1 = GET_VAL(pop1);
  58. result = op1-1;
  59. PUT_VAL(pop1, result);
  60. SET_FLAGS_DEC(result, op1);
  61. }
  62. FRAGCOMMON1(DecNoFlagsFrag)
  63. {
  64. UTYPE op1, result;
  65. op1 = GET_VAL(pop1);
  66. result = op1-1;
  67. PUT_VAL(pop1, result);
  68. }
  69. FRAGCOMMON2(OrFrag)
  70. {
  71. UTYPE op1, result;
  72. op1 = GET_VAL(pop1);
  73. result = op1 | op2;
  74. PUT_VAL(pop1, result);
  75. SET_ZFLAG(result);
  76. SET_PFLAG(result);
  77. SET_SFLAG(result << (31-LMB));
  78. SET_CFLAG_OFF;
  79. SET_OFLAG_OFF;
  80. }
  81. FRAGCOMMON2(OrNoFlagsFrag)
  82. {
  83. UTYPE op1, result;
  84. op1 = GET_VAL(pop1);
  85. result = op1 | op2;
  86. PUT_VAL(pop1, result);
  87. }
  88. FRAGCOMMON2(AdcFrag)
  89. {
  90. UTYPE result, op1;
  91. op1 = GET_VAL(pop1);
  92. result = op1 + op2 + (UTYPE)GET_CFLAGZO;
  93. PUT_VAL(pop1, result);
  94. SET_FLAGS_ADD(result, op1, op2, MSB);
  95. }
  96. FRAGCOMMON2(AdcNoFlagsFrag)
  97. {
  98. UTYPE result, op1;
  99. op1 = GET_VAL(pop1);
  100. result = op1 + op2 + (UTYPE)GET_CFLAGZO;
  101. PUT_VAL(pop1, result);
  102. }
  103. FRAGCOMMON2(SbbFrag)
  104. {
  105. UTYPE result, op1;
  106. op1 = GET_VAL(pop1);
  107. result = op1 - op2 - (UTYPE)GET_CFLAGZO;
  108. PUT_VAL(pop1, result);
  109. SET_FLAGS_SUB(result, op1, op2, MSB);
  110. }
  111. FRAGCOMMON2(SbbNoFlagsFrag)
  112. {
  113. UTYPE result, op1;
  114. op1 = GET_VAL(pop1);
  115. result = op1 - op2 - (UTYPE)GET_CFLAGZO;
  116. PUT_VAL(pop1, result);
  117. }
  118. FRAGCOMMON2(AndFrag)
  119. {
  120. UTYPE result, op1;
  121. op1 = GET_VAL(pop1);
  122. result = op1 & op2;
  123. PUT_VAL(pop1, result);
  124. SET_ZFLAG(result);
  125. SET_PFLAG(result);
  126. SET_SFLAG(result << (31-LMB));
  127. SET_CFLAG_OFF;
  128. SET_OFLAG_OFF;
  129. }
  130. FRAGCOMMON2(AndNoFlagsFrag)
  131. {
  132. UTYPE result, op1;
  133. op1 = GET_VAL(pop1);
  134. result = op1 & op2;
  135. PUT_VAL(pop1, result);
  136. }
  137. FRAGCOMMON2(SubFrag)
  138. {
  139. UTYPE result, op1;
  140. op1 = GET_VAL(pop1);
  141. result = op1 - op2;
  142. PUT_VAL(pop1, result);
  143. SET_FLAGS_SUB(result, op1, op2, MSB);
  144. }
  145. FRAGCOMMON2(SubNoFlagsFrag)
  146. {
  147. UTYPE result, op1;
  148. op1 = GET_VAL(pop1);
  149. result = op1 - op2;
  150. PUT_VAL(pop1, result);
  151. }
  152. FRAGCOMMON2(XorFrag)
  153. {
  154. UTYPE result, op1;
  155. op1 = GET_VAL(pop1);
  156. result = op1 ^ op2;
  157. PUT_VAL(pop1, result);
  158. SET_ZFLAG(result);
  159. SET_PFLAG(result);
  160. SET_SFLAG(result << (31-LMB));
  161. SET_CFLAG_OFF;
  162. SET_OFLAG_OFF;
  163. }
  164. FRAGCOMMON2(XorNoFlagsFrag)
  165. {
  166. UTYPE result, op1;
  167. op1 = GET_VAL(pop1);
  168. result = op1 ^ op2;
  169. PUT_VAL(pop1, result);
  170. }
  171. // Note: both pop1 and pop2 are given by reference
  172. FRAGCOMMON2REF(XchgFrag)
  173. {
  174. XCHG_MEM(UTYPE, pop1, pop2);
  175. }
  176. FRAGCOMMON2REF(XaddFrag)
  177. {
  178. UTYPE op1, op2, result;
  179. op1 = GET_VAL(pop1);
  180. op2 = GET_VAL(pop2);
  181. result = op1+op2;
  182. PUT_VAL(pop2, op1);
  183. PUT_VAL(pop1, result);
  184. SET_FLAGS_ADD(result, op1, op2, MSB);
  185. }
  186. FRAGCOMMON2REF(XaddNoFlagsFrag)
  187. {
  188. UTYPE op1, op2, result;
  189. op1 = GET_VAL(pop1);
  190. op2 = GET_VAL(pop2);
  191. result = op1+op2;
  192. PUT_VAL(pop2, op1);
  193. PUT_VAL(pop1, result);
  194. }
  195. FRAGCOMMON2REF(CmpXchgFrag)
  196. {
  197. UTYPE op1, op2;
  198. UTYPE Value = AREG;
  199. op1 = GET_VAL(pop1);
  200. op2 = GET_VAL(pop2);
  201. SET_FLAGS_SUB(Value-op1, Value, op1, MSB);
  202. if (Value == op1) {
  203. PUT_VAL(pop1, op2);
  204. SET_ZFLAG(0); // zf has inverse logic
  205. } else {
  206. AREG = op1;
  207. SET_ZFLAG(1); // zf has inverse logic
  208. }
  209. }
  210. FRAGCOMMON2(RolFrag)
  211. {
  212. op2 &= LMB;
  213. if (op2) {
  214. UTYPE b;
  215. b = GET_VAL(pop1);
  216. #if _PPC_ && (LMB==31)
  217. b = _rotl(b, op2); // an instrinsic rotlw instruction on PPC
  218. #else
  219. b = (b << op2) | (b >> (LMB-op2+1));
  220. #endif
  221. PUT_VAL(pop1, b);
  222. SET_CFLAG((DWORD)b << 31);
  223. }
  224. }
  225. FRAGCOMMON2(RorFrag)
  226. {
  227. op2 &= LMB;
  228. if (op2) {
  229. UTYPE b;
  230. b = GET_VAL(pop1);
  231. #if _PPC_ && (LMB==31)
  232. b = _rotr(b, op2); // an instrinsic rotlw instruction on PPC
  233. #else
  234. b = (b >> op2) | (b << (LMB-op2+1));
  235. #endif
  236. PUT_VAL(pop1, b)
  237. SET_CFLAG((DWORD)b << (31-LMB));
  238. }
  239. }
  240. FRAGCOMMON2(RclFrag)
  241. {
  242. op2 &= LMB;
  243. if (op2) {
  244. UTYPE b;
  245. DWORD temp_cf;
  246. b = GET_VAL(pop1);
  247. temp_cf = (DWORD)b << (31-LMB+op2-1);
  248. b = (b << op2) | (b >> (LMB-op2+2)) | ((UTYPE)GET_CFLAGZO << (op2-1));
  249. PUT_VAL(pop1, b);
  250. SET_CFLAG(temp_cf);
  251. }
  252. }
  253. FRAGCOMMON2(RcrFrag)
  254. {
  255. op2 &= LMB;
  256. if (op2) {
  257. UTYPE b;
  258. DWORD temp_cf;
  259. b = GET_VAL(pop1);
  260. temp_cf = (DWORD)b << (32-op2);
  261. b = (b << (LMB-op2+2)) | (b >> op2) | (UTYPE)((GET_CFLAGZO) << (LMB-op2+1));
  262. PUT_VAL(pop1, b)
  263. SET_CFLAG(temp_cf);
  264. }
  265. }
  266. FRAGCOMMON2(ShlFrag)
  267. {
  268. op2 &= 0x1f;
  269. if (op2) {
  270. UTYPE b;
  271. UTYPE newb;
  272. b = GET_VAL(pop1);
  273. b <<= (op2-1);
  274. newb = b << 1;
  275. PUT_VAL(pop1, newb);
  276. SET_CFLAG((DWORD)b << (31-LMB));
  277. SET_ZFLAG(newb);
  278. SET_PFLAG(newb);
  279. SET_SFLAG(newb << (31-LMB));
  280. }
  281. }
  282. FRAGCOMMON2(ShlNoFlagsFrag)
  283. {
  284. op2 &= 0x1f;
  285. if (op2) {
  286. UTYPE b;
  287. b = GET_VAL(pop1);
  288. b <<= op2;
  289. PUT_VAL(pop1, b);
  290. }
  291. }
  292. FRAGCOMMON2(ShrFrag)
  293. {
  294. op2 &= 0x1f;
  295. if (op2) {
  296. UTYPE b;
  297. UTYPE newb;
  298. b = GET_VAL(pop1);
  299. b >>= (op2-1);
  300. newb = b >> 1;
  301. PUT_VAL(pop1, newb);
  302. SET_CFLAG((DWORD)b << 31);
  303. SET_ZFLAG(newb);
  304. SET_PFLAG(newb);
  305. SET_SFLAG_OFF;
  306. }
  307. }
  308. FRAGCOMMON2(ShrNoFlagsFrag)
  309. {
  310. op2 &= 0x1f;
  311. if (op2) {
  312. UTYPE b;
  313. b = GET_VAL(pop1);
  314. b >>= op2;
  315. PUT_VAL(pop1, b);
  316. }
  317. }
  318. FRAGCOMMON2(SarFrag)
  319. {
  320. op2 &= 0x1f;
  321. if (op2) {
  322. UTYPE b, temp, newb;
  323. b = GET_VAL(pop1);
  324. temp = b & MSB;
  325. b >>= (op2-1);
  326. newb = b >> 1;
  327. if (temp) {
  328. newb |= ~((1u << (LMB-op2+1))-1u);
  329. }
  330. PUT_VAL(pop1, newb);
  331. SET_CFLAG((DWORD)b << 31);
  332. SET_ZFLAG(newb);
  333. SET_PFLAG(newb);
  334. SET_SFLAG(newb << (31-LMB));
  335. }
  336. }
  337. FRAGCOMMON2(SarNoFlagsFrag)
  338. {
  339. op2 &= 0x1f;
  340. if (op2) {
  341. UTYPE b, temp, newb;
  342. b = GET_VAL(pop1);
  343. temp = b & MSB;
  344. newb = b >> op2;
  345. if (temp) {
  346. newb |= ~((1u << (LMB-op2+1))-1u);
  347. }
  348. PUT_VAL(pop1, newb);
  349. }
  350. }
  351. FRAGCOMMON1(Rol1Frag)
  352. {
  353. UTYPE b, temp_cf;
  354. b = GET_VAL(pop1);
  355. temp_cf = b & MSB;
  356. #if _PPC_ && (LMB==31)
  357. b = _rotl(b, 1); // an instrinsic rotlw instruction on PPC
  358. #else
  359. b = (b<<1) + (b >> LMB);
  360. #endif
  361. PUT_VAL(pop1, b);
  362. SET_CFLAG((DWORD)temp_cf << (31-LMB));
  363. SET_OFLAG((DWORD)(temp_cf ^ b) << (31-LMB));
  364. }
  365. FRAGCOMMON1(Rol1NoFlagsFrag)
  366. {
  367. UTYPE b, temp_cf;
  368. b = GET_VAL(pop1);
  369. temp_cf = b & MSB;
  370. #if _PPC_ && (LMB==31)
  371. b = _rotl(b, 1); // an instrinsic rotlw instruction on PPC
  372. #else
  373. b = (b<<1) + (b >> LMB);
  374. #endif
  375. PUT_VAL(pop1, b);
  376. }
  377. FRAGCOMMON1(Ror1Frag)
  378. {
  379. UTYPE b, newb;
  380. b = GET_VAL(pop1);
  381. #if _PPC_ && (LMB==31)
  382. newb = _rotr(b, 1); // an instrinsic rotlw instruction on PPC
  383. #else
  384. newb = (b >> 1) | (b << LMB);
  385. #endif
  386. PUT_VAL(pop1, newb);
  387. SET_CFLAG((DWORD)b << 31);
  388. SET_OFLAG((DWORD)((newb>>LMB) ^ (newb>>(LMB-1)) & 1) << 31); // xor top 2 bits together
  389. }
  390. FRAGCOMMON1(Ror1NoFlagsFrag)
  391. {
  392. UTYPE b, newb;
  393. b = GET_VAL(pop1);
  394. #if _PPC_ && (LMB==31)
  395. newb = _rotr(b, 1); // an instrinsic rotlw instruction on PPC
  396. #else
  397. newb = (b >> 1) | (b << LMB);
  398. #endif
  399. PUT_VAL(pop1, newb);
  400. }
  401. FRAGCOMMON1(Rcl1Frag)
  402. {
  403. UTYPE b, temp_cf;
  404. b = GET_VAL(pop1);
  405. temp_cf = b & MSB;
  406. b = (b<<1) + (UTYPE)GET_CFLAGZO;
  407. PUT_VAL(pop1, b);
  408. SET_CFLAG(temp_cf << (31-LMB));
  409. SET_OFLAG((DWORD)(temp_cf ^ b) << (31-LMB));
  410. }
  411. FRAGCOMMON1(Rcl1NoFlagsFrag)
  412. {
  413. UTYPE b;
  414. b = GET_VAL(pop1);
  415. b = (b<<1) + (UTYPE)GET_CFLAGZO;
  416. PUT_VAL(pop1, b);
  417. }
  418. FRAGCOMMON1(Rcr1Frag)
  419. {
  420. UTYPE b, temp_cf;
  421. b = GET_VAL(pop1);
  422. temp_cf = b & 1;
  423. b = (b >> 1) + (UTYPE)((cpu->flag_cf & 0x80000000) >> (31-LMB));
  424. PUT_VAL(pop1, b);
  425. SET_CFLAG((DWORD)temp_cf << 31);
  426. SET_OFLAG(((DWORD)b << (31-LMB)) ^ ((DWORD)b << (31-LMB+1))); // xor top 2 bits together
  427. }
  428. FRAGCOMMON1(Rcr1NoFlagsFrag)
  429. {
  430. UTYPE b;
  431. b = GET_VAL(pop1);
  432. b = (b >> 1) + (UTYPE)((cpu->flag_cf & 0x80000000) >> (31-LMB));
  433. PUT_VAL(pop1, b);
  434. }
  435. FRAGCOMMON1(Shl1Frag)
  436. {
  437. UTYPE b, newb;
  438. b = GET_VAL(pop1);
  439. newb = b << 1;
  440. PUT_VAL(pop1, newb);
  441. SET_CFLAG((DWORD)b << (31-LMB));
  442. SET_ZFLAG(newb);
  443. SET_PFLAG(newb);
  444. SET_SFLAG(newb << (31-LMB));
  445. SET_OFLAG(GET_CFLAG ^ GET_SFLAG);
  446. }
  447. FRAGCOMMON1(Shl1NoFlagsFrag)
  448. {
  449. UTYPE b, newb;
  450. b = GET_VAL(pop1);
  451. newb = b << 1;
  452. PUT_VAL(pop1, newb);
  453. }
  454. FRAGCOMMON1(Shr1Frag)
  455. {
  456. UTYPE b, newb;
  457. b = GET_VAL(pop1);
  458. newb = b >> 1;
  459. PUT_VAL(pop1, newb);
  460. SET_OFLAG((DWORD)b << (31-LMB));
  461. SET_CFLAG((DWORD)b << 31);
  462. SET_ZFLAG(newb);
  463. SET_PFLAG(newb);
  464. SET_SFLAG_OFF;
  465. }
  466. FRAGCOMMON1(Shr1NoFlagsFrag)
  467. {
  468. UTYPE b, newb;
  469. b = GET_VAL(pop1);
  470. newb = b >> 1;
  471. PUT_VAL(pop1, newb);
  472. }
  473. FRAGCOMMON1(Sar1Frag)
  474. {
  475. UTYPE b, temp, newb;
  476. b = GET_VAL(pop1);
  477. temp = b & MSB;
  478. newb = (b >> 1) + temp;
  479. PUT_VAL(pop1, newb);
  480. SET_CFLAG((DWORD)b << 31);
  481. SET_ZFLAG(newb);
  482. SET_PFLAG(newb);
  483. SET_SFLAG(newb << (31-LMB));
  484. SET_OFLAG_OFF;
  485. }
  486. FRAGCOMMON1(Sar1NoFlagsFrag)
  487. {
  488. UTYPE b, temp, newb;
  489. b = GET_VAL(pop1);
  490. temp = b & MSB;
  491. newb = (b >> 1) + temp;
  492. PUT_VAL(pop1, newb);
  493. }
  494. FRAGCOMMON1(NotFrag)
  495. {
  496. PUT_VAL(pop1, ~GET_VAL(pop1));
  497. }
  498. FRAGCOMMON1(NegFrag)
  499. {
  500. UTYPE op1, result;
  501. op1 = GET_VAL(pop1);
  502. result = (UTYPE)-(STYPE)op1;
  503. PUT_VAL(pop1, result);
  504. SET_CFLAG_IND(result != 0);
  505. SET_ZFLAG(result);
  506. SET_PFLAG(result);
  507. SET_AUXFLAG(op1 ^ result);
  508. SET_SFLAG(result << (31-LMB));
  509. SET_OFLAG((DWORD)(op1 & result) << (31-LMB));
  510. }
  511. FRAGCOMMON1(NegNoFlagsFrag)
  512. {
  513. UTYPE op1, result;
  514. op1 = GET_VAL(pop1);
  515. result = (UTYPE)-(STYPE)op1;
  516. PUT_VAL(pop1, result);
  517. }
  518. FRAGCOMMON1(MulFrag)
  519. {
  520. #if MSB == 0x80
  521. USHORT result;
  522. result = (USHORT)al * (USHORT)GET_BYTE(pop1);
  523. if (result <= 0xff) {
  524. SET_CFLAG_OFF;
  525. SET_OFLAG_OFF;
  526. } else {
  527. SET_CFLAG_ON;
  528. SET_OFLAG_ON;
  529. }
  530. ax = result;
  531. #elif MSB == 0x8000
  532. ULONG result;
  533. result = (ULONG)ax * (ULONG)GET_SHORT(pop1);
  534. if (result <= 0xffff) {
  535. SET_CFLAG_OFF;
  536. SET_OFLAG_OFF;
  537. } else {
  538. SET_CFLAG_ON;
  539. SET_OFLAG_ON;
  540. }
  541. ax = LOWORD(result);
  542. dx = HIWORD(result);
  543. #else // MSB == 0x80000000
  544. LARGE_INTEGER result;
  545. result = RtlEnlargedUnsignedMultiply(eax, GET_LONG(pop1));
  546. if (result.HighPart == 0) {
  547. SET_CFLAG_OFF;
  548. SET_OFLAG_OFF;
  549. } else {
  550. SET_CFLAG_ON;
  551. SET_OFLAG_ON;
  552. }
  553. eax = result.LowPart;
  554. edx = result.HighPart;
  555. #endif
  556. }
  557. FRAGCOMMON1(MulNoFlagsFrag)
  558. {
  559. #if MSB == 0x80
  560. USHORT result;
  561. result = (USHORT)al * (USHORT)GET_BYTE(pop1);
  562. ax = result;
  563. #elif MSB == 0x8000
  564. ULONG result;
  565. result = (ULONG)ax * (ULONG)GET_SHORT(pop1);
  566. ax = LOWORD(result);
  567. dx = HIWORD(result);
  568. #else // MSB == 0x80000000
  569. LARGE_INTEGER result;
  570. result = RtlEnlargedUnsignedMultiply(eax, GET_LONG(pop1));
  571. eax = result.LowPart;
  572. edx = result.HighPart;
  573. #endif
  574. }
  575. FRAGCOMMON1(MuliFrag)
  576. {
  577. #if MSB == 0x80
  578. SHORT result;
  579. result = (short)(char)al * (short)(char)GET_BYTE(pop1);
  580. if ((result & 0xff80) == 0 || (result & 0xff80) == 0xff80) {
  581. SET_CFLAG_OFF;
  582. SET_OFLAG_OFF;
  583. } else {
  584. SET_CFLAG_ON;
  585. SET_OFLAG_ON;
  586. }
  587. ax = result;
  588. #elif MSB == 0x8000
  589. LONG result;
  590. result = (long)(short)ax * (long)(short)GET_SHORT(pop1);
  591. if ((result & 0xffff8000) == 0 || (result & 0xffff8000) == 0xffff8000) {
  592. SET_CFLAG_OFF;
  593. SET_OFLAG_OFF;
  594. } else {
  595. SET_CFLAG_ON;
  596. SET_OFLAG_ON;
  597. }
  598. ax = LOWORD(result);
  599. dx = HIWORD(result);
  600. #else // MSB == 0x80000000
  601. LARGE_INTEGER result;
  602. LONGLONG ll;
  603. ll = Int32x32To64(eax, (long)GET_LONG(pop1));
  604. result = *(LARGE_INTEGER *)&ll;
  605. if ((result.HighPart == 0 && (result.LowPart & 0x80000000) == 0) ||
  606. (result.HighPart == 0xffffffff && (result.LowPart & 0x80000000) == 0x80000000)) {
  607. SET_CFLAG_OFF;
  608. SET_OFLAG_OFF;
  609. } else {
  610. SET_CFLAG_ON;
  611. SET_OFLAG_ON;
  612. }
  613. eax = result.LowPart;
  614. edx = result.HighPart;
  615. #endif
  616. }
  617. FRAGCOMMON1(MuliNoFlagsFrag)
  618. {
  619. #if MSB == 0x80
  620. SHORT result;
  621. result = (short)(char)al * (short)(char)GET_BYTE(pop1);
  622. ax = result;
  623. #elif MSB == 0x8000
  624. LONG result;
  625. result = (long)(short)ax * (long)(short)GET_SHORT(pop1);
  626. ax = LOWORD(result);
  627. dx = HIWORD(result);
  628. #else // MSB == 0x80000000
  629. LARGE_INTEGER result;
  630. LONGLONG ll;
  631. ll = Int32x32To64(eax, (long)GET_LONG(pop1));
  632. result = *(LARGE_INTEGER *)&ll;
  633. eax = result.LowPart;
  634. edx = result.HighPart;
  635. #endif
  636. }
  637. FRAGCOMMON1(DivFrag)
  638. {
  639. #if MSB == 0x80
  640. USHORT result, remainder;
  641. USHORT dividend, divisor;
  642. dividend = (USHORT)ax;
  643. divisor = GET_VAL(pop1);
  644. result = dividend / divisor; // may get div-by-zero fault
  645. remainder = dividend % divisor;
  646. if ((result & 0xff00) == 0) {
  647. al = (UTYPE)result;
  648. ah = (UTYPE)remainder;
  649. } else {
  650. OVERFLOW_INSTR;
  651. }
  652. #elif MSB == 0x8000
  653. DWORD result, remainder;
  654. DWORD dividend, divisor;
  655. dividend = (((DWORD)dx)<<16) | (DWORD)ax;
  656. divisor = (DWORD)GET_VAL(pop1);
  657. result = dividend / divisor; // may get div-by-zero fault
  658. remainder = dividend % divisor;
  659. if ((result & 0xffff0000) == 0) {
  660. AREG = (UTYPE)result;
  661. DREG = (UTYPE)remainder;
  662. } else {
  663. OVERFLOW_INSTR;
  664. }
  665. #else // MSB == 0x80000000
  666. LARGE_INTEGER result;
  667. LARGE_INTEGER remainder;
  668. LARGE_INTEGER dividend;
  669. LARGE_INTEGER divisor;
  670. // build large_integers, without sign extending the 32-bit values
  671. dividend.LowPart = AREG;
  672. dividend.HighPart = DREG;
  673. divisor.LowPart = (long)GET_LONG(pop1);
  674. divisor.HighPart = 0;
  675. result = RtlLargeIntegerDivide(dividend, divisor, &remainder);
  676. if (result.HighPart == 0) {
  677. AREG = result.LowPart;
  678. DREG = remainder.LowPart;
  679. } else {
  680. OVERFLOW_INSTR;
  681. }
  682. #endif
  683. }
  684. FRAGCOMMON1(IdivFrag)
  685. {
  686. #if MSB == 0x80
  687. short result, remainder;
  688. result = (signed short)ax / (STYPE)GET_VAL(pop1); // may get div-by-zero fault
  689. remainder = (signed short)ax % (STYPE)GET_VAL(pop1);
  690. if ((result & 0xff80) == 0 || (result & 0xff80) == 0xff80) {
  691. al = (UTYPE)result;
  692. ah = (UTYPE)remainder;
  693. } else {
  694. OVERFLOW_INSTR;
  695. }
  696. #elif MSB == 0x8000
  697. LONG result, remainder;
  698. result = (signed long)((dx<<16) | ax) / (signed long)(STYPE)GET_VAL(pop1); // may get div-by-zero fault
  699. remainder = (signed long)((dx<<16) | ax) % (signed long)(STYPE)GET_VAL(pop1);
  700. if ((result & 0xffff8000) == 0 || (result & 0xffff8000) == 0xffff8000) {
  701. AREG = (UTYPE)result;
  702. DREG = (UTYPE)remainder;
  703. } else {
  704. OVERFLOW_INSTR;
  705. }
  706. #else // MSB == 0x80000000
  707. LARGE_INTEGER result;
  708. LARGE_INTEGER remainder;
  709. LARGE_INTEGER dividend;
  710. LARGE_INTEGER divisor;
  711. DWORD op1;
  712. //
  713. // Since RtlLargeIntegerDivide and all of the overhead is large,
  714. // it is worthwhile making this check:
  715. //
  716. if ((long)DREG == -(long)(AREG >> 31)) {
  717. //
  718. // EDX:EAX is really just the value of EAX sign-extended into EDX.
  719. // This division can be performed with 32-bit arithmetic and no
  720. // overflow checking.
  721. //
  722. OPT_CwdIdivFrag32(cpu, pop1);
  723. return;
  724. }
  725. op1 = GET_LONG(pop1);
  726. // build UNSIGNED large_integers
  727. dividend.LowPart = AREG;
  728. dividend.HighPart = DREG;
  729. if (dividend.QuadPart < 0) {
  730. dividend.QuadPart = -dividend.QuadPart;
  731. }
  732. if ((long)op1 < 0) {
  733. divisor.LowPart = -(long)op1;
  734. } else {
  735. divisor.LowPart = op1;
  736. }
  737. divisor.HighPart = 0;
  738. // perform UNSIGNED division
  739. result = RtlLargeIntegerDivide(dividend, divisor, &remainder);
  740. // if divisor and dividend signs are different, fudge the result
  741. if ((dividend.HighPart != (int)DREG) ^ (divisor.LowPart != (int)op1)) {
  742. result.QuadPart = -result.QuadPart;
  743. }
  744. // adjust the sign of the remainder if the dividend is negative
  745. if (dividend.HighPart != (int)DREG) {
  746. remainder.QuadPart = -remainder.QuadPart;
  747. }
  748. if ((result.HighPart == 0 && (result.LowPart & MSB) == 0) ||
  749. (result.HighPart == 0xffffffff && (result.LowPart & MSB))) {
  750. AREG = (UTYPE)result.LowPart;
  751. DREG = (UTYPE)remainder.LowPart;
  752. } else {
  753. OVERFLOW_INSTR;
  754. }
  755. #endif
  756. }