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.

621 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. fragmisc.c
  5. Abstract:
  6. Miscellaneous instuction fragments.
  7. Author:
  8. 12-Jun-1995 BarryBo
  9. Revision History:
  10. 24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
  11. 20-Sept-1999[barrybo] added FRAG2REF(CmpXchg8bFrag32, ULONGLONG)
  12. --*/
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <float.h>
  19. #include "wx86.h"
  20. #include "wx86nt.h"
  21. #include "fragp.h"
  22. #include "fragmisc.h"
  23. #include "cpunotif.h"
  24. #include "config.h"
  25. #include "mrsw.h"
  26. #include "cpuassrt.h"
  27. #if MSCPU
  28. #include "atomic.h"
  29. #endif
  30. ASSERTNAME;
  31. void
  32. CpupUnlockTCAndDoInterrupt(
  33. PTHREADSTATE cpu,
  34. int Interrupt
  35. )
  36. {
  37. MrswReaderExit(&MrswTC);
  38. cpu->fTCUnlocked = TRUE;
  39. CpupDoInterrupt(Interrupt);
  40. // If we get here, CpupDoInterrupt returned due to CONTINUE_EXECUTION.
  41. // We need to redesign so we can jump to EndTranslatedCode now, as
  42. // the cache may have been flushed.
  43. CPUASSERT(FALSE);
  44. MrswReaderEnter(&MrswTC);
  45. cpu->fTCUnlocked = FALSE;
  46. }
  47. FRAG0(CbwFrag32)
  48. {
  49. eax = (signed long)(signed short)ax;
  50. }
  51. FRAG0(CbwFrag16)
  52. {
  53. ax = (signed short)(signed char)al;
  54. }
  55. FRAG0(PushEsFrag)
  56. {
  57. PUSH_LONG(ES);
  58. }
  59. FRAG0(PopEsFrag)
  60. {
  61. DWORD temp;
  62. POP_LONG(temp);
  63. ES = (USHORT)temp;
  64. }
  65. FRAG0(PushFsFrag)
  66. {
  67. PUSH_LONG(FS);
  68. }
  69. FRAG0(PopFsFrag)
  70. {
  71. DWORD temp;
  72. POP_LONG(temp);
  73. FS = (USHORT)temp;
  74. }
  75. FRAG0(PushGsFrag)
  76. {
  77. PUSH_LONG(GS);
  78. }
  79. FRAG0(PopGsFrag)
  80. {
  81. DWORD temp;
  82. POP_LONG(temp);
  83. GS = (USHORT)temp;
  84. }
  85. FRAG0(PushCsFrag)
  86. {
  87. PUSH_LONG(CS);
  88. }
  89. FRAG0(AasFrag)
  90. {
  91. if ( (al & 0x0f) > 9 || GET_AUXFLAG) {
  92. ah--;
  93. al = (al-6) & 0x0f;
  94. SET_CFLAG_ON;
  95. SET_AUXFLAG_ON;
  96. } else {
  97. SET_CFLAG_OFF;
  98. SET_AUXFLAG_OFF;
  99. al &= 0xf;
  100. }
  101. }
  102. FRAG0(PushSsFrag)
  103. {
  104. PUSH_LONG(SS);
  105. }
  106. FRAG0(PopSsFrag)
  107. {
  108. DWORD temp;
  109. POP_LONG(temp);
  110. SS = (USHORT)temp;
  111. }
  112. FRAG0(PushDsFrag)
  113. {
  114. PUSH_LONG(DS);
  115. }
  116. FRAG0(PopDsFrag)
  117. {
  118. DWORD temp;
  119. POP_LONG(temp);
  120. DS = (USHORT)temp;
  121. }
  122. FRAG0(DaaFrag)
  123. {
  124. if ((al & 0x0f) > 9 || GET_AUXFLAG) {
  125. al += 6;
  126. SET_AUXFLAG_ON;
  127. } else {
  128. SET_AUXFLAG_OFF;
  129. }
  130. if ((al & 0xf0) > 0x90 || GET_CFLAG) {
  131. al += 0x60;
  132. SET_CFLAG_ON;
  133. } else {
  134. SET_CFLAG_OFF;
  135. }
  136. SET_ZFLAG(al);
  137. SET_PFLAG(al);
  138. SET_SFLAG(al << (31-7)); // SET_SFLAG_IND(al & 0x80);
  139. }
  140. FRAG0(DasFrag)
  141. {
  142. if ( (al & 0x0f) > 9 || GET_AUXFLAG) {
  143. al -= 6;
  144. SET_AUXFLAG_ON;
  145. } else {
  146. SET_AUXFLAG_OFF;
  147. }
  148. if ( al > 0x9f || GET_CFLAG) {
  149. al -= 0x60;
  150. SET_CFLAG_ON;
  151. } else {
  152. SET_CFLAG_OFF;
  153. }
  154. SET_ZFLAG(al);
  155. SET_PFLAG(al);
  156. SET_SFLAG(al << (31-7)); // SET_SFLAG_IND(al & 0x80);
  157. }
  158. FRAG0(AaaFrag)
  159. {
  160. if ((al & 0x0f) > 9 || GET_AUXFLAG) {
  161. al=(al+6) & 0x0f;
  162. ah++; // inc ah
  163. SET_AUXFLAG_ON;
  164. SET_CFLAG_ON;
  165. } else {
  166. SET_AUXFLAG_OFF;
  167. SET_CFLAG_OFF;
  168. al &= 0xf;
  169. }
  170. }
  171. FRAG1IMM(AadFrag, BYTE)
  172. {
  173. al += ah * op1;
  174. ah = 0;
  175. SET_ZFLAG(al);
  176. SET_PFLAG(al);
  177. SET_SFLAG(al << (31-7)); // SET_SFLAG_IND(al & 0x80);
  178. }
  179. FRAG2(ImulFrag16, USHORT)
  180. {
  181. Imul3ArgFrag16(cpu, pop1, GET_SHORT(pop1), op2);
  182. }
  183. FRAG2(ImulFrag16A, USHORT)
  184. {
  185. Imul3ArgFrag16A(cpu, pop1, *pop1, op2);
  186. }
  187. FRAG3(Imul3ArgFrag16, USHORT, USHORT, USHORT)
  188. {
  189. long result;
  190. result = (long)(short)op2 * (long)(short)op3;
  191. PUT_SHORT(pop1, (USHORT)(short)result);
  192. if (HIWORD(result) == 0 || HIWORD(result) == 0xffff) {
  193. SET_CFLAG_OFF;
  194. SET_OFLAG_OFF;
  195. } else {
  196. SET_CFLAG_ON;
  197. SET_OFLAG_ON;
  198. }
  199. }
  200. FRAG3(Imul3ArgFrag16A, USHORT, USHORT, USHORT)
  201. {
  202. long result;
  203. result = (short)op2 * (short)op3;
  204. *pop1 = (USHORT)(short)result;
  205. if (HIWORD(result) == 0 || HIWORD(result) == 0xffff) {
  206. SET_CFLAG_OFF;
  207. SET_OFLAG_OFF;
  208. } else {
  209. SET_CFLAG_ON;
  210. SET_OFLAG_ON;
  211. }
  212. }
  213. FRAG2(ImulNoFlagsFrag16, USHORT)
  214. {
  215. short op1 = (short)GET_SHORT(pop1);
  216. PUT_SHORT(pop1, (op2 * (short)op2));
  217. }
  218. FRAG2(ImulNoFlagsFrag16A, USHORT)
  219. {
  220. *(short *)pop1 *= (short)op2;
  221. }
  222. FRAG3(Imul3ArgNoFlagsFrag16, USHORT, USHORT, USHORT)
  223. {
  224. PUT_SHORT(pop1, ((short)op2 * (short)op3));
  225. }
  226. FRAG3(Imul3ArgNoFlagsFrag16A, USHORT, USHORT, USHORT)
  227. {
  228. *pop1 = (USHORT)((short)op2 * (short)op3);
  229. }
  230. FRAG2(ImulFrag32, DWORD)
  231. {
  232. Imul3ArgFrag32(cpu, pop1, GET_LONG(pop1), op2);
  233. }
  234. FRAG2(ImulFrag32A, DWORD)
  235. {
  236. Imul3ArgFrag32A(cpu, pop1, *pop1, (long)op2);
  237. }
  238. FRAG3(Imul3ArgFrag32A, DWORD, DWORD, DWORD)
  239. {
  240. LARGE_INTEGER result;
  241. LONGLONG ll;
  242. ll = Int32x32To64((long)op2, (long)op3);
  243. result = *(LARGE_INTEGER *)&ll;
  244. *pop1 = result.LowPart;
  245. if (result.HighPart == 0 || result.HighPart == 0xffffffff) {
  246. SET_CFLAG_OFF;
  247. SET_OFLAG_OFF;
  248. } else {
  249. SET_CFLAG_ON;
  250. SET_OFLAG_ON;
  251. }
  252. }
  253. FRAG3(Imul3ArgFrag32, DWORD, DWORD, DWORD)
  254. {
  255. LARGE_INTEGER result;
  256. LONGLONG ll;
  257. ll = Int32x32To64((long)op2, (long)op3);
  258. result = *(LARGE_INTEGER *)&ll;
  259. PUT_LONG(pop1, result.LowPart);
  260. if (result.HighPart == 0 || result.HighPart == 0xffffffff) {
  261. SET_CFLAG_OFF;
  262. SET_OFLAG_OFF;
  263. } else {
  264. SET_CFLAG_ON;
  265. SET_OFLAG_ON;
  266. }
  267. }
  268. FRAG2(ImulNoFlagsFrag32, DWORD)
  269. {
  270. long op1 = (LONG)GET_LONG(pop1);
  271. PUT_LONG(pop1, (op1 * (long)op2));
  272. }
  273. FRAG2(ImulNoFlagsFrag32A, DWORD)
  274. {
  275. *(long *)pop1 *= (long)op2;
  276. }
  277. FRAG3(Imul3ArgNoFlagsFrag32A, DWORD, DWORD, DWORD)
  278. {
  279. *pop1 = (DWORD)( (long)op2 * (long)op3);
  280. }
  281. FRAG3(Imul3ArgNoFlagsFrag32, DWORD, DWORD, DWORD)
  282. {
  283. PUT_LONG(pop1, ((long)op2 * (long)op3));
  284. }
  285. FRAG0(SahfFrag)
  286. {
  287. DWORD dw = (DWORD)ah;
  288. SET_CFLAG(dw << 31); // CFLAG is low-bit of ah
  289. SET_PFLAG (!(dw & FLAG_PF)); // flag_pf contains an index into ParityBit[] array
  290. SET_AUXFLAG(dw); // AUX bit is already in the right place
  291. SET_ZFLAG (!(dw & FLAG_ZF)); // zf has inverse logic
  292. SET_SFLAG(dw << (31-7)); // SFLAG is bit 7 in AH
  293. }
  294. FRAG0(LahfFrag)
  295. {
  296. ah= 2 | // this bit is always set on Intel
  297. ((GET_CFLAG) ? FLAG_CF : 0) |
  298. ((GET_PFLAG) ? FLAG_PF : 0) |
  299. ((GET_AUXFLAG)? FLAG_AUX: 0) |
  300. ((cpu->flag_zf) ? 0 : FLAG_ZF) | // zf has inverse logic
  301. ((GET_SFLAG) ? FLAG_SF : 0);
  302. }
  303. FRAG1IMM(AamFrag, BYTE)
  304. {
  305. ah = al / op1;
  306. al %= op1;
  307. SET_ZFLAG(al);
  308. SET_PFLAG(al);
  309. SET_SFLAG(al << (31-7));
  310. }
  311. FRAG0(XlatFrag)
  312. {
  313. al = GET_BYTE(ebx+al);
  314. }
  315. FRAG0(CmcFrag)
  316. {
  317. SET_CFLAG_IND(!GET_CFLAG);
  318. }
  319. FRAG0(ClcFrag)
  320. {
  321. SET_CFLAG_OFF;
  322. }
  323. FRAG0(StcFrag)
  324. {
  325. SET_CFLAG_ON;
  326. }
  327. FRAG0(CldFrag)
  328. {
  329. cpu->flag_df = 1;
  330. }
  331. FRAG0(StdFrag)
  332. {
  333. cpu->flag_df = 0xffffffff;
  334. }
  335. FRAG1(SetoFrag, BYTE)
  336. {
  337. PUT_BYTE(pop1, (BYTE)GET_OFLAGZO);
  338. }
  339. FRAG1(SetnoFrag, BYTE)
  340. {
  341. PUT_BYTE(pop1, (GET_OFLAG == 0));
  342. }
  343. FRAG1(SetbFrag, BYTE)
  344. {
  345. PUT_BYTE(pop1, (BYTE)GET_CFLAGZO);
  346. }
  347. FRAG1(SetaeFrag, BYTE)
  348. {
  349. PUT_BYTE(pop1, (GET_CFLAG == 0));
  350. }
  351. FRAG1(SeteFrag, BYTE)
  352. {
  353. PUT_BYTE(pop1, (cpu->flag_zf == 0)); // inverse logic
  354. }
  355. FRAG1(SetneFrag, BYTE)
  356. {
  357. PUT_BYTE(pop1, (cpu->flag_zf != 0)); // inverse logic
  358. }
  359. FRAG1(SetbeFrag, BYTE)
  360. {
  361. PUT_BYTE(pop1, (GET_CFLAG || cpu->flag_zf == 0)); // inverse logic
  362. }
  363. FRAG1(SetaFrag, BYTE)
  364. {
  365. PUT_BYTE(pop1, (GET_CFLAG == 0 && cpu->flag_zf != 0)); // inverse logic
  366. }
  367. FRAG1(SetsFrag, BYTE)
  368. {
  369. PUT_BYTE(pop1, (BYTE)GET_SFLAGZO);
  370. }
  371. FRAG1(SetnsFrag, BYTE)
  372. {
  373. PUT_BYTE(pop1, (GET_SFLAG == 0));
  374. }
  375. FRAG1(SetpFrag, BYTE)
  376. {
  377. PUT_BYTE(pop1, (GET_PFLAG != 0));
  378. }
  379. FRAG1(SetnpFrag, BYTE)
  380. {
  381. PUT_BYTE(pop1, (GET_PFLAG == 0));
  382. }
  383. FRAG1(SetlFrag, BYTE)
  384. {
  385. PUT_BYTE(pop1, (GET_SFLAG != GET_OFLAG));
  386. }
  387. FRAG1(SetgeFrag, BYTE)
  388. {
  389. PUT_BYTE(pop1, (GET_SFLAGZO == GET_OFLAGZO));
  390. }
  391. FRAG1(SetleFrag, BYTE)
  392. {
  393. PUT_BYTE(pop1, (!cpu->flag_zf || (GET_SFLAG != GET_OFLAG))); // inverse logic
  394. }
  395. FRAG1(SetgFrag, BYTE)
  396. {
  397. PUT_BYTE(pop1, (cpu->flag_zf && !(GET_SFLAG ^ GET_OFLAG))); // inverse logic
  398. }
  399. FRAG2(Movzx8ToFrag16, USHORT)
  400. {
  401. PUT_SHORT(pop1, (USHORT)(BYTE)op2);
  402. }
  403. FRAG2(Movzx8ToFrag16A, USHORT)
  404. {
  405. *pop1 = (USHORT)(BYTE)op2;
  406. }
  407. FRAG2(Movsx8ToFrag16, USHORT)
  408. {
  409. PUT_SHORT(pop1, (USHORT)(short)(char)(BYTE)op2);
  410. }
  411. FRAG2(Movsx8ToFrag16A, USHORT)
  412. {
  413. *pop1 = (USHORT)(short)(char)(BYTE)op2;
  414. }
  415. FRAG2(Movzx8ToFrag32, DWORD)
  416. {
  417. PUT_LONG(pop1, (DWORD)(BYTE)op2);
  418. }
  419. FRAG2(Movzx8ToFrag32A, DWORD)
  420. {
  421. *pop1 = (DWORD)(BYTE)op2;
  422. }
  423. FRAG2(Movsx8ToFrag32, DWORD)
  424. {
  425. PUT_LONG(pop1, (DWORD)(long)(char)(BYTE)op2);
  426. }
  427. FRAG2(Movsx8ToFrag32A, DWORD)
  428. {
  429. *pop1 = (DWORD)(long)(char)(BYTE)op2;
  430. }
  431. FRAG2(Movzx16ToFrag32, DWORD)
  432. {
  433. PUT_LONG(pop1, (DWORD)(USHORT)op2);
  434. }
  435. FRAG2(Movzx16ToFrag32A, DWORD)
  436. {
  437. *pop1 = (DWORD)(USHORT)op2;
  438. }
  439. FRAG2(Movsx16ToFrag32, DWORD)
  440. {
  441. PUT_LONG(pop1, (DWORD)(long)(short)(USHORT)op2);
  442. }
  443. FRAG2(Movsx16ToFrag32A, DWORD)
  444. {
  445. *pop1 = (DWORD)(long)(short)(USHORT)op2;
  446. }
  447. FRAG1(BswapFrag32, DWORD)
  448. {
  449. DWORD d;
  450. PBYTE pSrc = (PBYTE)pop1;
  451. d = (pSrc[0] << 24) | (pSrc[1] << 16) | (pSrc[2] << 8) | pSrc[3];
  452. // pop1 is always a pointer to a register, so an ALIGNED store is correct
  453. *pop1 = d;
  454. }
  455. FRAG2(ArplFrag, USHORT)
  456. {
  457. USHORT op1 = GET_SHORT(pop1);
  458. op2 &= 3; // just get the RPL bits of the selector
  459. if ((op1&3) < op2) {
  460. // RPL bits of DEST < RPL bits of SRC
  461. op1 = (op1 & ~3) | op2; // copy RPL bits from SRC to DEST
  462. PUT_SHORT(pop1, op1); // store DEST
  463. SET_ZFLAG(0); // ZF=1
  464. } else {
  465. SET_ZFLAG(1);
  466. }
  467. }
  468. FRAG1(VerrFrag, USHORT)
  469. {
  470. USHORT op1 = GET_SHORT(pop1) & ~3; // mask off RPL bits
  471. if (op1 == KGDT_R3_CODE || // CS: selector
  472. op1 == KGDT_R3_DATA || // DS:, SS:, ES: selector
  473. op1 == KGDT_R3_TEB // FS: selector
  474. ) {
  475. SET_ZFLAG(0); // ZF=1
  476. } else {
  477. SET_ZFLAG(1); // ZF=0
  478. }
  479. }
  480. FRAG1(VerwFrag, USHORT)
  481. {
  482. USHORT op1 = GET_SHORT(pop1) & ~3; // mask off RPL bits
  483. if (op1 == KGDT_R3_DATA || // DS:, SS:, ES: selector
  484. op1 == KGDT_R3_TEB // FS: selector
  485. ) {
  486. SET_ZFLAG(0); // ZF=1
  487. } else {
  488. SET_ZFLAG(1); // ZF=0
  489. }
  490. }
  491. FRAG1(SmswFrag, USHORT)
  492. {
  493. //
  494. // This value is empirically discovered by running it on a Pentium
  495. // machine. CR0_PE, CR0_EX, and CR0_NE bits were set, and all others
  496. // notably CR0_MP, are clear.
  497. //
  498. PUT_SHORT(pop1, 0x31);
  499. }
  500. #if MSCPU
  501. FRAG0(IntOFrag)
  502. {
  503. if (GET_OFLAG) {
  504. Int4(); // raise overflow
  505. }
  506. }
  507. FRAG0(NopFrag)
  508. {
  509. }
  510. FRAG0(PrivilegedInstructionFrag)
  511. {
  512. PRIVILEGED_INSTR;
  513. }
  514. FRAG0(BadInstructionFrag)
  515. {
  516. Int6(); // Throw invalid opcode exception
  517. }
  518. FRAG2(FaultFrag, DWORD)
  519. {
  520. // pop1 = exception code
  521. // op2 = address where fault occurred
  522. #if DBG
  523. LOGPRINT((TRACELOG, "CPU: FaultFrag called\r\n"));
  524. #endif
  525. RtlRaiseStatus((NTSTATUS)(ULONGLONG)pop1);
  526. }
  527. #endif //MSCPU
  528. FRAG0(CPUID)
  529. {
  530. switch (eax) {
  531. case 0:
  532. eax = 1; // We are a 486 with CPUID (PPro returns 2)
  533. //ebx = 0x756e6547; // "GenuineIntel"
  534. //edx = 0x49656e69;
  535. //ecx = 0x6c65746e;
  536. ebx = 0x7263694d; // "Micr" with M in the low nibble of BL
  537. edx = 0x666f736f; // "osof" with o in the low nibble of DL
  538. ecx = 0x55504374; // "tCPU" with t in the low nibble of CL
  539. break;
  540. case 1:
  541. eax = (0 << 12) | // Type = 0 (2 bits) Original OEM Processor
  542. (4 << 8) | // Family = 4 (4 bits) 80486
  543. (1 << 4) | // Model = 1 (4 bits)
  544. 0; // Stepping=0 (4 bits)
  545. edx = (fUseNPXEM) ? 1: 0; // bit 0: FPU on-chip. wx86cpu doesn't
  546. // support any other features.
  547. break;
  548. default:
  549. //
  550. // The Intel behavior indicates that if eax is out-of-range, the
  551. // results returned in the regsiters are unpredictable but it
  552. // doesn't fault.
  553. //
  554. break;
  555. }
  556. }
  557. FRAG2REF(CmpXchg8bFrag32, ULONGLONG)
  558. {
  559. ULONGLONG EdxEax;
  560. ULONGLONG Value;
  561. EdxEax = (((ULONGLONG)edx) << 32) | (ULONGLONG)eax;
  562. Value = *(ULONGLONG UNALIGNED *)pop1;
  563. if (Value == EdxEax) {
  564. ULONGLONG EcxEbx;
  565. EcxEbx = (ULONGLONG)ecx << 32 | (ULONGLONG)ebx;
  566. *(ULONGLONG UNALIGNED *)pop1 = EcxEbx;
  567. SET_ZFLAG(0); // zf has inverse logic
  568. } else {
  569. eax = (ULONG)Value;
  570. edx = (ULONG)(Value >> 32);
  571. SET_ZFLAG(1); // zf has inverse logic
  572. }
  573. }
  574. FRAG0(Rdtsc)
  575. {
  576. LARGE_INTEGER Counter;
  577. // This is cheese, but it will at least return a value that increases
  578. // over time.
  579. NtQueryPerformanceCounter(&Counter, NULL);
  580. edx = Counter.HighPart;
  581. eax = Counter.LowPart;
  582. }