Source code of Windows XP (NT5)
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.

568 lines
8.4 KiB

  1. /* asmopcod.c -- microsoft 80x86 assembler
  2. **
  3. ** microsoft (r) macro assembler
  4. ** copyright (c) microsoft corp 1986. all rights reserved
  5. **
  6. ** randy nevin
  7. **
  8. ** 10/90 - Quick conversion to 32 bit by Jeff Spencer
  9. */
  10. #include <stdio.h>
  11. #include "asm86.h"
  12. #include "asmfcn.h"
  13. #ifdef FIXCOMPILERBUG
  14. // foobarfoofoo simply takes up space to get around a compiler bug
  15. void
  16. foobarfoofoo()
  17. {
  18. int foo;
  19. for( foo = 0; foo < 100000; foo++ );
  20. for( foo = 0; foo < 100000; foo++ );
  21. for( foo = 0; foo < 100000; foo++ );
  22. for( foo = 0; foo < 100000; foo++ );
  23. for( foo = 0; foo < 100000; foo++ );
  24. for( foo = 0; foo < 100000; foo++ );
  25. }
  26. #endif
  27. /*** forcesize - check for no size in pass 2
  28. *
  29. * routine ();
  30. *
  31. * Entry
  32. * Exit
  33. * Returns
  34. * Calls
  35. */
  36. VOID PASCAL CODESIZE
  37. forcesize (
  38. DSCREC *arg
  39. ){
  40. register struct psop *pso; /* parse stack operand structure */
  41. pso = &(arg->dsckind.opnd);
  42. if (pass2)
  43. if (!pso->sized)
  44. errorc (E_OHS);
  45. else if (M_CODE & pso->dtype)
  46. /* Not data assoc */
  47. errorc (E_ASD);
  48. if (arg != fltdsc) /* Large size ok for 8087 */
  49. if (pso->dsize > 2 && (
  50. #ifdef V386
  51. !(cputype&P386) ||
  52. #endif
  53. pso->dsize != 4))
  54. /* Illegal item size */
  55. errorc (E_IIS);
  56. }
  57. /*** checkmatch - check memory and register
  58. *
  59. * checkmatch ();
  60. *
  61. * Entry
  62. * Exit
  63. * Returns
  64. * Calls
  65. * Note Give error if Dmem has a size and does not match Dreg.
  66. * Force to same size
  67. */
  68. VOID PASCAL CODESIZE
  69. checkmatch (
  70. DSCREC *dreg,
  71. DSCREC *dmem
  72. ){
  73. register struct psop *psor; /* parse stack operand structure */
  74. register struct psop *psom; /* parse stack operand structure */
  75. psor = &(dreg->dsckind.opnd);
  76. psom = &(dmem->dsckind.opnd);
  77. if (psom->sized && (psom->w != psor->w
  78. #ifdef V386
  79. || (psom->dsize && psor->dsize != psom->dsize)
  80. #endif
  81. ))
  82. errorc ((USHORT)(psom->mode == psor->mode? E_OMM & ~E_WARN1: E_OMM));
  83. psom->w = psor->w;
  84. }
  85. /*** emitopcode - emit opcode to linker and display on listing
  86. *
  87. * emitopcode (val);
  88. *
  89. * Entry
  90. * Exit
  91. * Returns
  92. * Calls
  93. */
  94. VOID PASCAL CODESIZE
  95. emitopcode (
  96. UCHAR v
  97. ){
  98. if (pass2 || debug) {
  99. if (pass2 && emittext)
  100. /* Output to linker */
  101. emitcbyte (v);
  102. /* Display on listing */
  103. opdisplay (v);
  104. }
  105. if (emittext)
  106. pcoffset++;
  107. }
  108. /*** emitmodrm - emit modrm byte 64*p1+8*p2+p3
  109. *
  110. * emitmodrm (p1, p2, p3);
  111. *
  112. * Entry
  113. * Exit
  114. * Returns
  115. * Calls
  116. */
  117. VOID PASCAL CODESIZE
  118. emitmodrm (
  119. USHORT p1,
  120. USHORT p2,
  121. USHORT p3
  122. ){
  123. #ifdef V386
  124. if (p1>7)
  125. {
  126. /* 386 SIB opcodes have wired in RM of ESP */
  127. emitopcode ((UCHAR)(((p1-8) << 6) + (p2 << 3) + 4));
  128. listindex--;
  129. emitopcode ((UCHAR)p3);
  130. }
  131. else
  132. #endif
  133. emitopcode ((UCHAR)(((p1 > 3 ? (p1-5) : p1) << 6) + (p2 << 3) + p3));
  134. }
  135. /*** emitescape - emit segment escapt byte
  136. *
  137. * emitescape ();
  138. *
  139. * Entry
  140. * Exit
  141. * Returns
  142. * Calls
  143. */
  144. VOID PASCAL CODESIZE
  145. emitescape (
  146. DSCREC *dsc,
  147. UCHAR sreg
  148. ){
  149. register struct psop *pso; /* parse stack operand structure */
  150. pso = &(dsc->dsckind.opnd);
  151. if (pso->seg < NOSEG && pso->seg != sreg && pso->mode != 4) {
  152. if (checkpure && (cputype & (P286|P386)) && pso->seg == CSSEG)
  153. impure = TRUE;
  154. if (pso->seg < FSSEG)
  155. emitopcode((UCHAR)(0x26|(pso->seg<<3)));
  156. #ifdef V386
  157. else if (cputype & P386)
  158. emitopcode((UCHAR)(0x60|pso->seg));
  159. #endif
  160. else
  161. errorc (E_CRS);
  162. /* Flag is prefix */
  163. listbuffer[listindex-1] = ':';
  164. listindex++;
  165. }
  166. if (pso->seg > NOSEG)
  167. /* Unknown segreg */
  168. errorc (E_CRS);
  169. }
  170. #ifdef V386
  171. VOID PASCAL CODESIZE
  172. emitsize (
  173. USHORT value
  174. ){
  175. if (! (cputype & P386)) {
  176. if (errorcode == (E_IIS&~E_WARN1))
  177. errorcode = 0;
  178. errorc(E_IIS&~E_WARN1);
  179. }
  180. emitopcode((UCHAR)value);
  181. listbuffer[listindex-1] = '|';
  182. listindex++;
  183. }
  184. #endif
  185. /*** byteimmcheck - check if value is -128 .. +127
  186. *
  187. * routine ();
  188. *
  189. * Entry
  190. * Exit
  191. * Returns
  192. * Calls
  193. */
  194. VOID PASCAL CODESIZE
  195. byteimmcheck (
  196. register struct psop *pso
  197. ){
  198. register USHORT t;
  199. t = (USHORT)pso->doffset;
  200. if (pso->dsign)
  201. t = -t;
  202. if (t > (USHORT) 0x7F && t < (USHORT)~0x7F)
  203. errorc (E_VOR);
  204. }
  205. /*** emitOP - emit operand, value which may be in segment
  206. *
  207. * routine ();
  208. *
  209. * Entry
  210. * Exit
  211. * Returns
  212. * Calls
  213. */
  214. VOID PASCAL CODESIZE
  215. emitOP (
  216. register struct psop *pso
  217. ){
  218. USHORT i, fSegOnly;
  219. if (pso->dsign)
  220. pso->doffset = -(long)pso->doffset;
  221. pso->dsign = FALSE;
  222. if (fNeedList) {
  223. fSegOnly = (pso->fixtype == FBASESEG || pso->fixtype == FGROUPSEG);
  224. if (pso->dflag == INDETER) { /* Have ? */
  225. for (i = 1; i <= 2 * pso->dsize; i++) {
  226. listbuffer[listindex] = '?';
  227. if (listindex < LSTMAX)
  228. listindex++;
  229. else
  230. resetobjidx ();
  231. }
  232. }
  233. else if (pso->dsize == 1) {
  234. opdisplay ((UCHAR) pso->doffset);
  235. listindex--;
  236. }
  237. else if (!fSegOnly) {
  238. if (pso->dsize > 4 ||
  239. pso->dsize == 4 &&
  240. ((pso->fixtype&7) == FOFFSET || pso->fixtype == FCONSTANT)) {
  241. /* list full 32 bits, even if top is 0 */
  242. if (!highWord(pso->doffset)){
  243. offsetAscii((OFFSET) 0);
  244. copyascii();
  245. }
  246. offsetAscii (pso->doffset);
  247. }
  248. else
  249. offsetAscii (pso->doffset & 0xffff);
  250. copyascii ();
  251. }
  252. if ((pso->fixtype&7) == FPOINTER || fSegOnly) {
  253. if (pso->dsize != 2)
  254. listindex++;
  255. copytext ("--");
  256. copytext ("--");
  257. }
  258. if (pso->dflag == XTERNAL)
  259. copytext (" E");
  260. else if (pso->dsegment)
  261. copytext (" R");
  262. if (pso->dflag == UNDEFINED)
  263. copytext (" U");
  264. listindex++;
  265. if (fSegOnly && pso->dsize == 4){
  266. copytext("00");
  267. copytext("00");
  268. }
  269. }
  270. if (emittext) {
  271. if (pass2)
  272. if (pso->dflag != UNDEFINED)
  273. emitobject (pso);
  274. else if (pso->dsize != 1)
  275. emitcword ((OFFSET) 0); /* Just put out word */
  276. else {
  277. if (((USHORT) (pso->doffset >> 8)) != (USHORT)0 &&
  278. ((USHORT) (pso->doffset >> 8)) != (USHORT)-1)
  279. errorc (E_VOR);
  280. emitcbyte (0);
  281. }
  282. pcoffset += pso->dsize;
  283. }
  284. }
  285. /*** emitrest - emit displacement or immediate values based on
  286. * address passed in address mode
  287. *
  288. * emitrest (opc);
  289. *
  290. * Entry *opc = parse stack entry
  291. * Exit
  292. * Returns
  293. * Calls
  294. */
  295. VOID PASCAL CODESIZE
  296. emitrest (
  297. DSCREC *opc
  298. ){
  299. register struct psop *pso; /* parse stack operand structure */
  300. pso = &(opc->dsckind.opnd);
  301. if ((pso->mode != 3 && pso->mode != 4) && (pso->fixtype == FNONE))
  302. pso->fixtype = FCONSTANT;
  303. switch(pso->mode)
  304. /* There is something to output */
  305. {
  306. case 0:
  307. if(pso->rm != 6) break;
  308. case 2:
  309. pso->dsize = 2;
  310. goto bpcomm;
  311. /* 386 modes, 4 byte displacements */
  312. case 5:
  313. case 8:
  314. if ((pso->rm&7) != 5) break;
  315. case 7:
  316. case 10:
  317. pso->dsize = 4;
  318. bpcomm:
  319. /* we get empty dsize from some callers. for this operand,
  320. * we need to make it an offset. but not for far calls and
  321. * jumps */
  322. if ((pso->fixtype&7) == FPOINTER)
  323. pso->dsize += 2;
  324. emitOP (pso);
  325. break;
  326. case 1:
  327. case 6:
  328. case 9:
  329. pso->dsize = 1;
  330. emitOP (pso);
  331. break;
  332. case 3:
  333. break;
  334. case 4:
  335. /* Immediate mode */
  336. if (!pso->w || pso->dsize == 0)
  337. pso->dsize = (pso->w ? wordsize : 1);
  338. emitOP (pso);
  339. }
  340. }
  341. /*** errorforward - generate error if forward reference on pass 2
  342. *
  343. * routine ();
  344. *
  345. * Entry
  346. * Exit
  347. * Returns
  348. * Calls
  349. */
  350. VOID PASCAL CODESIZE
  351. errorforward (
  352. DSCREC *arg
  353. ){
  354. if (pass2)
  355. if (arg->dsckind.opnd.dflag == FORREF)
  356. errorc (E_IFR);
  357. }
  358. /*** errorimmed - generate error if immediate operand
  359. *
  360. * routine ();
  361. *
  362. * Entry
  363. * Exit
  364. * Returns
  365. * Calls
  366. */
  367. VOID PASCAL CODESIZE
  368. errorimmed (
  369. DSCREC *dsc
  370. ){
  371. if (dsc->dsckind.opnd.mode == 4) {
  372. errorc (E_NIM);
  373. dsc->dsckind.opnd.mode = 2;
  374. }
  375. }
  376. /*** rangecheck - check for register number within range
  377. *
  378. * routine ();
  379. *
  380. * Entry
  381. * Exit
  382. * Returns
  383. * Calls
  384. */
  385. VOID PASCAL CODESIZE
  386. rangecheck (
  387. USHORT *v,
  388. UCHAR limit
  389. ){
  390. if (*v > limit) {
  391. if (limit <= 7)
  392. errorc (E_IRV);
  393. else
  394. errorc (E_VOR);
  395. *v = limit;
  396. }
  397. }
  398. VOID PASCAL CODESIZE
  399. valuecheck(
  400. OFFSET *v,
  401. USHORT limit
  402. ){
  403. if (*v > limit) {
  404. if (limit <= 7)
  405. errorc (E_IRV);
  406. else
  407. errorc (E_VOR);
  408. *v = limit;
  409. }
  410. }
  411. /*** forceaccum - generate error if not register AX or AL
  412. *
  413. * routine ();
  414. *
  415. * Entry
  416. * Exit
  417. * Returns
  418. * Calls
  419. */
  420. VOID PASCAL CODESIZE
  421. forceaccum (
  422. DSCREC *dsc
  423. ){
  424. if (dsc->dsckind.opnd.mode != 3 || dsc->dsckind.opnd.rm)
  425. errorc (E_AXL);
  426. }
  427. /*** errorsegreg - generate error if operand is segment register
  428. *
  429. * errorsegreg (arg);
  430. *
  431. * Entry
  432. * Exit
  433. * Returns
  434. * Calls
  435. */
  436. VOID PASCAL CODESIZE
  437. errorsegreg (
  438. DSCREC *arg
  439. ){
  440. if (1 << REGRESULT & arg->dsckind.opnd.dtype)
  441. if (arg->dsckind.opnd.dsegment->symu.regsym.regtype == SEGREG)
  442. errorc (E_ISR);
  443. }