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.

614 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Instructions with common (shared) BYTE, WORD, and DWORD flavors.
  7. Author:
  8. 29-Jun-1995 BarryBo
  9. Revision History:
  10. --*/
  11. // THIS FILE IS #include'd INTO FILES WHICH DEFINE THE FOLLOWING MACROS:
  12. // GET_REG - function returning pointer to register
  13. // MSB - most signigicant bit
  14. // MOD_RM - decode mod/rm bits
  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. // DISPATCHCOMMON - mangles function name by appening 8/16/32
  20. // AREG - GP_AL/GP_AX/GP_EAX, etc.
  21. // BREG - ...
  22. // CREG - ...
  23. // DREG - ...
  24. OPERATION MANGLENAME(Group1Map)[8] = {OPNAME(Add),
  25. OPNAME(Or),
  26. OPNAME(Adc),
  27. OPNAME(Sbb),
  28. OPNAME(And),
  29. OPNAME(Sub),
  30. OPNAME(Xor),
  31. OPNAME(Cmp)};
  32. OPERATION MANGLENAME(Group1LockMap)[8] = {LOCKOPNAME(Add),
  33. LOCKOPNAME(Or),
  34. LOCKOPNAME(Adc),
  35. LOCKOPNAME(Sbb),
  36. LOCKOPNAME(And),
  37. LOCKOPNAME(Sub),
  38. LOCKOPNAME(Xor),
  39. OPNAME(Cmp)};
  40. // A macro to generate _m_r functions
  41. #define DC_M_R(x, y) \
  42. DISPATCHCOMMON(x ## _m_r) \
  43. { \
  44. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2); \
  45. \
  46. Instr->Operation = y; \
  47. DEREF(Instr->Operand2); \
  48. Instr->Size = cbInstr+1; \
  49. }
  50. // A macro to generate _r_m functions
  51. #define DC_R_M(x, y) \
  52. DISPATCHCOMMON(x ## _r_m) \
  53. { \
  54. int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1); \
  55. \
  56. Instr->Operation = y; \
  57. DEREF(Instr->Operand2); \
  58. Instr->Size = cbInstr+1; \
  59. }
  60. // A macro to generate _a_i functions
  61. #define DC_A_I(x, y) \
  62. DISPATCHCOMMON(x ## _a_i) \
  63. { \
  64. Instr->Operation = y; \
  65. Instr->Operand1.Type = OPND_REGREF; \
  66. Instr->Operand1.Reg = AREG; \
  67. Instr->Operand2.Type = OPND_IMM; \
  68. Instr->Operand2.Immed = GET_VAL(eipTemp+1); \
  69. Instr->Size = 1+sizeof(UTYPE); \
  70. }
  71. // The monster macro which generates all three
  72. #define DC_ALL(x, y) \
  73. DC_M_R(x,y) \
  74. DC_R_M(x,y) \
  75. DC_A_I(x,y)
  76. // SETSIZE sets the size of a jump instruction
  77. #if MSB==0x80
  78. #define SETSIZE Instr->Size = 1+sizeof(UTYPE); // 1 byte opcode
  79. #else
  80. #define SETSIZE Instr->Size = 2+sizeof(UTYPE); // 2 byte opcode
  81. #endif
  82. #if DBG
  83. #define CLEAR_ADRPREFIX State->AdrPrefix = FALSE;
  84. #else
  85. #define CLEAR_ADRPREFIX
  86. #endif
  87. // This macro generates jump functions
  88. // If the ADR: prefix is set, get the 16-bit loword from the 32-bit
  89. // immediate value following the JMP instruction, and add that value
  90. // to the loword of EIP, and use that value as the new IP register.
  91. #define DISPATCHJUMP(x) \
  92. DISPATCHCOMMON(j ## x) \
  93. { \
  94. Instr->Operand1.Type = OPND_NOCODEGEN; \
  95. if (State->AdrPrefix) { \
  96. Instr->Operand1.Immed = MAKELONG((short)GET_SHORT(eipTemp+1)+1+sizeof(UTYPE)+(short)LOWORD(eipTemp), HIWORD(eipTemp)); \
  97. CLEAR_ADRPREFIX; \
  98. } else { \
  99. Instr->Operand1.Immed = (STYPE)GET_VAL(eipTemp+1)+1+sizeof(UTYPE)+eipTemp; \
  100. } \
  101. if (Instr->Operand1.Immed > eipTemp) { \
  102. Instr->Operation = OP_CTRL_COND_J ## x ## Fwd; \
  103. } else { \
  104. Instr->Operation = OP_CTRL_COND_J ## x ##; \
  105. } \
  106. SETSIZE \
  107. }
  108. DC_ALL(LOCKadd, LOCKOPNAME(Add))
  109. DC_ALL(LOCKor, LOCKOPNAME(Or))
  110. DC_ALL(LOCKadc, LOCKOPNAME(Adc))
  111. DC_ALL(LOCKsbb, LOCKOPNAME(Sbb))
  112. DC_ALL(LOCKand, LOCKOPNAME(And))
  113. DC_ALL(LOCKsub, LOCKOPNAME(Sub))
  114. DC_ALL(LOCKxor, LOCKOPNAME(Xor))
  115. DC_ALL(add, OPNAME(Add))
  116. DC_ALL(or, OPNAME(Or))
  117. DC_ALL(adc, OPNAME(Adc))
  118. DC_ALL(sbb, OPNAME(Sbb))
  119. DC_ALL(and, OPNAME(And))
  120. DC_ALL(sub, OPNAME(Sub))
  121. DC_ALL(xor, OPNAME(Xor))
  122. DISPATCHCOMMON(cmp_m_r)
  123. {
  124. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
  125. Instr->Operation = OPNAME(Cmp);
  126. DEREF(Instr->Operand1); // both params are byval
  127. DEREF(Instr->Operand2);
  128. Instr->Size = cbInstr+1;
  129. }
  130. DISPATCHCOMMON(cmp_r_m)
  131. {
  132. int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
  133. Instr->Operation = OPNAME(Cmp);
  134. DEREF(Instr->Operand1); // both params are byval
  135. DEREF(Instr->Operand2);
  136. Instr->Size = cbInstr+1;
  137. }
  138. DISPATCHCOMMON(cmp_a_i)
  139. {
  140. Instr->Operation = OPNAME(Cmp);
  141. Instr->Operand1.Type = OPND_REGVALUE; // both params are byval
  142. Instr->Operand1.Reg = AREG;
  143. Instr->Operand2.Type = OPND_IMM;
  144. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  145. Instr->Size = 1+sizeof(UTYPE);
  146. }
  147. DISPATCHCOMMON(GROUP_1)
  148. {
  149. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  150. BYTE g = GET_BYTE(eipTemp+1);
  151. // <instruction> modrm, imm
  152. Instr->Operand2.Type = OPND_IMM;
  153. Instr->Operand2.Immed = GET_VAL(eipTemp+1+cbInstr); // get immB
  154. g = (g >> 3) & 0x07;
  155. Instr->Operation = MANGLENAME(Group1Map)[g];
  156. if (g == 7) {
  157. // Cmp takes both params as byval
  158. DEREF(Instr->Operand1);
  159. }
  160. Instr->Size = cbInstr+sizeof(UTYPE)+1;
  161. }
  162. DISPATCHCOMMON(LOCKGROUP_1)
  163. {
  164. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  165. BYTE g = GET_BYTE(eipTemp+1);
  166. // <instruction> modrm, imm
  167. Instr->Operand2.Type = OPND_IMM;
  168. Instr->Operand2.Immed = GET_VAL(eipTemp+1+cbInstr); // get immB
  169. g = (g >> 3) & 0x07;
  170. Instr->Operation = MANGLENAME(Group1LockMap)[g];
  171. if (g == 7) {
  172. // Cmp takes both args as byval
  173. DEREF(Instr->Operand1);
  174. }
  175. Instr->Size = cbInstr+sizeof(UTYPE)+1;
  176. }
  177. DISPATCHCOMMON(test_r_m)
  178. {
  179. int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
  180. Instr->Operation = OPNAME(Test);
  181. DEREF(Instr->Operand1); // both args are byval
  182. DEREF(Instr->Operand2);
  183. Instr->Size = cbInstr+1;
  184. }
  185. DISPATCHCOMMON(xchg_r_m)
  186. {
  187. int cbInstr = MOD_RM(State, &Instr->Operand2, &Instr->Operand1);
  188. // Operand2 is always a register. If operand1 is a memory location,
  189. // we must use the locked version, otherwise use the regular version.
  190. if (Instr->Operand1.Type == OPND_REGREF){
  191. Instr->Operation = OPNAME(Xchg);
  192. } else {
  193. Instr->Operation = LOCKOPNAME(Xchg);
  194. }
  195. Instr->Size = cbInstr+1;
  196. }
  197. DISPATCHCOMMON(xadd_m_r)
  198. {
  199. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
  200. Instr->Operation = OPNAME(Xadd);
  201. Instr->Size = cbInstr+2;
  202. }
  203. DISPATCHCOMMON(cmpxchg_m_r)
  204. {
  205. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
  206. Instr->Operation = OPNAME(CmpXchg);
  207. Instr->Size = cbInstr+2;
  208. }
  209. DISPATCHCOMMON(LOCKxadd_m_r)
  210. {
  211. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
  212. Instr->Operation = LOCKOPNAME(Xadd);
  213. Instr->Size = cbInstr+2;
  214. }
  215. DISPATCHCOMMON(LOCKcmpxchg_m_r)
  216. {
  217. int cbInstr = MOD_RM(State, &Instr->Operand1, &Instr->Operand2);
  218. Instr->Operation = LOCKOPNAME(CmpXchg);
  219. Instr->Size = cbInstr+2;
  220. }
  221. DC_M_R(mov, OPNAME(Mov))
  222. DC_R_M(mov, OPNAME(Mov))
  223. DISPATCHCOMMON(mov_a_m) // mov accum, [full displacement]
  224. {
  225. Instr->Operation = OPNAME(Mov);
  226. Instr->Operand1.Type = OPND_REGREF;
  227. Instr->Operand1.Reg = AREG;
  228. Instr->Operand2.Type = OPND_ADDRREF;
  229. DEREF(Instr->Operand2); // this is a klunky ADDRVAL8/16/32 expansion
  230. if (State->AdrPrefix) {
  231. Instr->Operand2.Immed = GET_SHORT(eipTemp+1);
  232. Instr->Size = 3;
  233. #if DBG
  234. State->AdrPrefix = FALSE;
  235. #endif
  236. } else {
  237. Instr->Operand2.Immed = GET_LONG(eipTemp+1);
  238. Instr->Size = 5;
  239. }
  240. }
  241. DISPATCHCOMMON(mov_m_a) // mov [full displacement], accum
  242. {
  243. Instr->Operation = OPNAME(Mov);
  244. Instr->Operand1.Type = OPND_ADDRREF;
  245. Instr->Operand2.Type = OPND_REGVALUE;
  246. Instr->Operand2.Reg = AREG;
  247. if (State->AdrPrefix) {
  248. Instr->Operand1.Immed = GET_SHORT(eipTemp+1);
  249. Instr->Size = 3;
  250. #if DBG
  251. State->AdrPrefix = FALSE;
  252. #endif
  253. } else {
  254. Instr->Operand1.Immed = GET_LONG(eipTemp+1);
  255. Instr->Size = 5;
  256. }
  257. }
  258. DISPATCHCOMMON(test_a_i)
  259. {
  260. Instr->Operation = OPNAME(Test);
  261. Instr->Operand1.Type = OPND_REGVALUE;
  262. Instr->Operand1.Reg = AREG;
  263. Instr->Operand2.Type = OPND_IMM;
  264. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  265. Instr->Size = 1+sizeof(UTYPE);
  266. }
  267. DISPATCHCOMMON(mov_a_i)
  268. {
  269. Instr->Operation = OPNAME(Mov);
  270. Instr->Operand1.Type = OPND_REGREF;
  271. Instr->Operand1.Reg = AREG;
  272. Instr->Operand2.Type = OPND_IMM;
  273. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  274. Instr->Size = sizeof(UTYPE)+1;
  275. }
  276. DISPATCHCOMMON(mov_b_i)
  277. {
  278. Instr->Operation = OPNAME(Mov);
  279. Instr->Operand1.Type = OPND_REGREF;
  280. Instr->Operand1.Reg = BREG;
  281. Instr->Operand2.Type = OPND_IMM;
  282. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  283. Instr->Size = sizeof(UTYPE)+1;
  284. }
  285. DISPATCHCOMMON(mov_c_i)
  286. {
  287. Instr->Operation = OPNAME(Mov);
  288. Instr->Operand1.Type = OPND_REGREF;
  289. Instr->Operand1.Reg = CREG;
  290. Instr->Operand2.Type = OPND_IMM;
  291. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  292. Instr->Size = sizeof(UTYPE)+1;
  293. }
  294. DISPATCHCOMMON(mov_d_i)
  295. {
  296. Instr->Operation = OPNAME(Mov);
  297. Instr->Operand1.Type = OPND_REGREF;
  298. Instr->Operand1.Reg = DREG;
  299. Instr->Operand2.Type = OPND_IMM;
  300. Instr->Operand2.Immed = GET_VAL(eipTemp+1);
  301. Instr->Size = sizeof(UTYPE)+1;
  302. }
  303. DISPATCHCOMMON(GROUP_2)
  304. {
  305. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  306. BYTE g = GET_BYTE(eipTemp+1);
  307. // <instruction> modrm, imm
  308. Instr->Operand2.Type = OPND_IMM;
  309. Instr->Operand2.Immed = GET_VAL(eipTemp+1+cbInstr) & 0x1f;
  310. switch ((g >> 3) & 0x07) {
  311. case 0: // rol
  312. if (Instr->Operand2.Immed)
  313. Instr->Operation = OPNAME(Rol);
  314. else
  315. Instr->Operation = OP_Nop;
  316. break;
  317. case 1: // ror
  318. if (Instr->Operand2.Immed)
  319. Instr->Operation = OPNAME(Ror);
  320. else
  321. Instr->Operation = OP_Nop;
  322. break;
  323. case 2: // rcl
  324. Instr->Operation = OPNAME(Rcl);
  325. break;
  326. case 3: // rcr
  327. Instr->Operation = OPNAME(Rcr);
  328. break;
  329. case 4: // shl
  330. Instr->Operation = OPNAME(Shl);
  331. break;
  332. case 5: // shr
  333. Instr->Operation = OPNAME(Shr);
  334. break;
  335. case 7: // sar
  336. Instr->Operation = OPNAME(Sar);
  337. break;
  338. case 6: // <bad>
  339. BAD_INSTR;
  340. break;
  341. }
  342. Instr->Size = 2+cbInstr;
  343. }
  344. DISPATCHCOMMON(mov_m_i)
  345. {
  346. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  347. Instr->Operation = OPNAME(Mov);
  348. Instr->Operand2.Type = OPND_IMM;
  349. Instr->Operand2.Immed = GET_VAL(eipTemp+cbInstr+1);
  350. Instr->Size = cbInstr+sizeof(UTYPE)+1;
  351. }
  352. DISPATCHCOMMON(GROUP_2_1)
  353. {
  354. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  355. BYTE g = GET_BYTE(eipTemp+1);
  356. // <instruction> modrm, 1
  357. switch ((g >> 3) & 0x07) {
  358. case 0: // rol
  359. Instr->Operation = OPNAME(Rol1);
  360. break;
  361. case 1: // ror
  362. Instr->Operation = OPNAME(Ror1);
  363. break;
  364. case 2: // rcl
  365. Instr->Operation = OPNAME(Rcl1);
  366. break;
  367. case 3: // rcr
  368. Instr->Operation = OPNAME(Rcr1);
  369. break;
  370. case 4: // shl
  371. Instr->Operation = OPNAME(Shl1);
  372. break;
  373. case 5: // shr
  374. Instr->Operation = OPNAME(Shr1);
  375. break;
  376. case 7: // sar
  377. Instr->Operation = OPNAME(Sar1);
  378. break;
  379. case 6: // <bad>
  380. BAD_INSTR;
  381. break;
  382. }
  383. Instr->Size = cbInstr+1;
  384. }
  385. DISPATCHCOMMON(GROUP_2_CL)
  386. {
  387. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  388. BYTE g = GET_BYTE(eipTemp+1);
  389. Instr->Operand2.Type = OPND_REGVALUE;
  390. Instr->Operand2.Reg = GP_CL; //UNDONE: the fragments must mask by 31
  391. // <instruction> modrm, imm
  392. switch ((g >> 3) & 0x07) {
  393. case 0: // rol
  394. Instr->Operation = OPNAME(Rol);
  395. break;
  396. case 1: // ror
  397. Instr->Operation = OPNAME(Ror);
  398. break;
  399. case 2: // rcl
  400. Instr->Operation = OPNAME(Rcl);
  401. break;
  402. case 3: // rcr
  403. Instr->Operation = OPNAME(Rcr);
  404. break;
  405. case 4: // shl
  406. Instr->Operation = OPNAME(Shl);
  407. break;
  408. case 5: // shr
  409. Instr->Operation = OPNAME(Shr);
  410. break;
  411. case 7: // sar
  412. Instr->Operation = OPNAME(Sar);
  413. break;
  414. case 6: // <bad>
  415. BAD_INSTR;
  416. break;
  417. }
  418. Instr->Size = 1+cbInstr;
  419. }
  420. DISPATCHCOMMON(GROUP_3)
  421. {
  422. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  423. BYTE g = GET_BYTE(eipTemp+1);
  424. switch ((g >> 3) & 0x07) {
  425. case 1: // bad
  426. BAD_INSTR;
  427. break;
  428. case 0: // test modrm, imm
  429. Instr->Operation = OPNAME(Test);
  430. DEREF(Instr->Operand1); // both args are byval
  431. Instr->Operand2.Type = OPND_IMM;
  432. Instr->Operand2.Immed = GET_VAL(eipTemp+1+cbInstr);
  433. cbInstr += sizeof(UTYPE); // account for the imm size
  434. break;
  435. case 2: // not, modrm
  436. Instr->Operation = OPNAME(Not);
  437. break;
  438. case 3: // neg, modrm
  439. Instr->Operation = OPNAME(Neg);
  440. break;
  441. case 4: // mul al, modrm
  442. Instr->Operation = OPNAME(Mul);
  443. break;
  444. case 5: // imul al, modrm
  445. Instr->Operation = OPNAME(Muli);
  446. break;
  447. case 6: // div al, modrm
  448. Instr->Operation = OPNAME(Div);
  449. break;
  450. case 7: // idiv al, modrm
  451. Instr->Operation = OPNAME(Idiv);
  452. break;
  453. }
  454. Instr->Size = cbInstr+1;
  455. }
  456. DISPATCHCOMMON(LOCKGROUP_3)
  457. {
  458. int cbInstr = MOD_RM(State, &Instr->Operand1, NULL);
  459. BYTE g = GET_BYTE(eipTemp+1);
  460. switch ((g >> 3) & 0x07) {
  461. case 0:
  462. case 1: // bad
  463. BAD_INSTR;
  464. break;
  465. case 2: // not, modrm
  466. Instr->Operation = LOCKOPNAME(Not);
  467. break;
  468. case 3: // neg, modrm
  469. Instr->Operation = LOCKOPNAME(Neg);
  470. break;
  471. default:
  472. BAD_INSTR;
  473. break;
  474. }
  475. Instr->Size = cbInstr+1;
  476. }
  477. DISPATCHCOMMON(lods)
  478. {
  479. if (Instr->FsOverride) {
  480. if (State->RepPrefix) {
  481. Instr->Operation = OPNAME(FsRepLods);
  482. } else {
  483. Instr->Operation = OPNAME(FsLods);
  484. }
  485. } else {
  486. if (State->RepPrefix) {
  487. Instr->Operation = OPNAME(RepLods);
  488. } else {
  489. Instr->Operation = OPNAME(Lods);
  490. }
  491. }
  492. }
  493. DISPATCHCOMMON(scas)
  494. {
  495. OPERATION ScasMap[6] = {OPNAME(Scas),
  496. OPNAME(RepzScas),
  497. OPNAME(RepnzScas),
  498. OPNAME(FsScas),
  499. OPNAME(FsRepzScas),
  500. OPNAME(FsRepnzScas)
  501. };
  502. Instr->Operation = ScasMap[State->RepPrefix + 3*Instr->FsOverride];
  503. }
  504. DISPATCHCOMMON(stos)
  505. {
  506. if (State->RepPrefix) {
  507. Instr->Operation = OPNAME(RepStos);
  508. } else {
  509. Instr->Operation = OPNAME(Stos);
  510. }
  511. }
  512. DISPATCHCOMMON(movs)
  513. {
  514. if (Instr->FsOverride) {
  515. if (State->RepPrefix) {
  516. Instr->Operation = OPNAME(FsRepMovs);
  517. } else {
  518. Instr->Operation = OPNAME(FsMovs);
  519. }
  520. } else {
  521. if (State->RepPrefix) {
  522. Instr->Operation = OPNAME(RepMovs);
  523. } else {
  524. Instr->Operation = OPNAME(Movs);
  525. }
  526. }
  527. }
  528. DISPATCHCOMMON(cmps)
  529. {
  530. OPERATION CmpsMap[6] = {OPNAME(Cmps),
  531. OPNAME(RepzCmps),
  532. OPNAME(RepnzCmps),
  533. OPNAME(FsCmps),
  534. OPNAME(FsRepzCmps),
  535. OPNAME(FsRepnzCmps)
  536. };
  537. Instr->Operation = CmpsMap[State->RepPrefix + 3*Instr->FsOverride];
  538. }
  539. // Now the jump instructions:
  540. DISPATCHJUMP(o)
  541. DISPATCHJUMP(no)
  542. DISPATCHJUMP(b)
  543. DISPATCHJUMP(ae)
  544. DISPATCHJUMP(e)
  545. DISPATCHJUMP(ne)
  546. DISPATCHJUMP(be)
  547. DISPATCHJUMP(a)
  548. DISPATCHJUMP(s)
  549. DISPATCHJUMP(ns)
  550. DISPATCHJUMP(p)
  551. DISPATCHJUMP(np)
  552. DISPATCHJUMP(l)
  553. DISPATCHJUMP(nl)
  554. DISPATCHJUMP(le)
  555. DISPATCHJUMP(g)