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.

734 lines
12 KiB

  1. /* asmexpr.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 <ctype.h>
  12. #include "asm86.h"
  13. #include "asmfcn.h"
  14. #include "asmctype.h"
  15. #include "asmexpr.h"
  16. #include "asmmsg.h"
  17. extern UCHAR opprec [];
  18. extern char fValidSym, addplusflagCur;
  19. /*** endstring - check for end of string
  20. *
  21. * flag = endstring ();
  22. *
  23. * Entry delim = string delimiter character
  24. * Exit none
  25. * Returns TRUE if at end of string
  26. * FALSE if not at end of string
  27. * Calls error
  28. * Note Double occurances of delimiter character are returned as a
  29. * single occurance of the delimiter character.
  30. */
  31. UCHAR PASCAL CODESIZE
  32. endstring ()
  33. {
  34. register UCHAR cc;
  35. if ((cc = PEEKC ()) == 0) {
  36. /* End of line before delim */
  37. errorc (E_UEL);
  38. return (TRUE);
  39. }
  40. else if (cc == delim) {
  41. /* check for escaped quote character */
  42. SKIPC ();
  43. if ((cc = PEEKC ()) != delim) {
  44. BACKC ();
  45. return (TRUE);
  46. }
  47. }
  48. return (FALSE);
  49. }
  50. /*** oblititem - release parse stack record
  51. *
  52. * oblititem (arg);
  53. *
  54. * Entry *arg = parse stack record
  55. * Exit parse stack record released
  56. * Returns none
  57. * Calls free
  58. */
  59. VOID PASCAL CODESIZE
  60. oblititem (
  61. register DSCREC *arg
  62. ){
  63. register char c;
  64. if ((c = arg->itype) == ENDEXPR || c == OPERATOR || c == OPERAND)
  65. dfree( (UCHAR *)arg );
  66. }
  67. /*** flteval - Look at ST | ST(i) and create entry
  68. *
  69. * flteval ();
  70. *
  71. * Entry *ptr = parse stack entry
  72. * Exit
  73. * Returns
  74. * Calls
  75. */
  76. VOID PASCAL CODESIZE
  77. flteval ()
  78. {
  79. *itemptr = emptydsc;
  80. /* ST means ST(0) */
  81. /* We are 8087 stack */
  82. itemptr->dsckind.opnd.dtype = M_RCONST | M_FLTSTACK;
  83. /* Need + if ST(i) */
  84. addplusflagCur = (PEEKC () == '(');
  85. }
  86. /*** createitem - make item entry
  87. *
  88. * createitem (itemkind, itemsub, p);
  89. *
  90. * Entry itemkind = kind of item
  91. * itemsub =
  92. * *p = activation record
  93. * Exit
  94. * Returns
  95. * Calls
  96. * Note If symbol, look further to see if EQU, record name
  97. * and do appropriate thing.
  98. */
  99. VOID PASCAL CODESIZE
  100. createitem (
  101. UCHAR itemkind,
  102. UCHAR itemsub
  103. ){
  104. register struct psop *pso; /* parse stack operand structure */
  105. switch (itemkind) {
  106. case OPERAND:
  107. /* Create default record */
  108. itemptr = defaultdsc ();
  109. pso = &(itemptr->dsckind.opnd);
  110. switch (itemsub) {
  111. case ICONST:
  112. pso->doffset = val;
  113. break;
  114. case ISIZE:
  115. #ifdef V386
  116. pso->doffset = (long) (SHORT) varsize;
  117. #else
  118. pso->doffset = varsize;
  119. #endif
  120. pso->s++; /* note for expr evaluator */
  121. break;
  122. case IUNKNOWN:
  123. pso->dflag = INDETER;
  124. break;
  125. case ISYM:
  126. createsym ();
  127. break;
  128. }
  129. break;
  130. case OPERATOR:
  131. itemptr = dalloc();
  132. itemptr->dsckind.opr.oidx = opertype;
  133. break;
  134. }
  135. /* Set type of entry */
  136. itemptr->itype = itemkind;
  137. }
  138. /*** numeric - evaluate numeric string
  139. *
  140. * numeric (count, base, p);
  141. *
  142. * Entry count = number of characters in string
  143. * base = conversion base
  144. * *p = activation record
  145. * Exit
  146. * Returns
  147. * Calls
  148. */
  149. VOID PASCAL CODESIZE
  150. numeric (
  151. SHORT cnt,
  152. SHORT base
  153. ){
  154. register UCHAR t;
  155. register long temp = 0;
  156. OFFSET maxInt;
  157. maxInt = (fArth32)? OFFSETMAX: 0xffff;
  158. if (base > 10)
  159. for (; cnt; cnt--) {
  160. if ((t = MAP (NEXTC ()) - '0') > 9)
  161. t -= 'A' - '9' - 1;
  162. if (t >= base)
  163. errorc (E_NDN);
  164. if ((OFFSET)(temp = temp * base + t) > maxInt)
  165. errorc (E_DVZ);
  166. }
  167. else
  168. for (; cnt; cnt--) {
  169. if ((t = NEXTC () - '0') >= base)
  170. errorc (E_NDN);
  171. if ((OFFSET)(temp = temp * base + t) > maxInt)
  172. errorc (E_DVZ);
  173. }
  174. val = temp;
  175. }
  176. /*** evalconst - evaluate constant
  177. *
  178. * type = evalconst (p);
  179. *
  180. * Entry *p = parser activation record
  181. * Exit numeric item added to parse stack entry
  182. * Returns type of item added to parse stack
  183. * Calls
  184. */
  185. void PASCAL CODESIZE
  186. evalconst ()
  187. {
  188. register char cc;
  189. register SHORT i = 0;
  190. char *endscan, *begscan;
  191. SHORT rbase;
  192. begscan = lbufp;
  193. while (isxdigit (cc = PEEKC ())) {
  194. SKIPC ();
  195. i++;
  196. }
  197. switch (MAP (cc)) {
  198. case 'H':
  199. rbase = 16;
  200. SKIPC ();
  201. break;
  202. case 'O':
  203. case 'Q':
  204. rbase = 8;
  205. SKIPC ();
  206. break;
  207. default:
  208. BACKC ();
  209. switch (MAP (NEXTC ())) {
  210. case 'B':
  211. rbase = 2;
  212. i--;
  213. break;
  214. case 'D':
  215. rbase = 10;
  216. i--;
  217. break;
  218. default:
  219. if (cc == '.')
  220. errorcSYN ();
  221. if (radixescape)
  222. rbase = 10;
  223. else
  224. rbase = radix;
  225. break;
  226. }
  227. break;
  228. }
  229. endscan = lbufp;
  230. lbufp = begscan;
  231. numeric (i, rbase);
  232. lbufp = endscan;
  233. }
  234. /*** evalstring - evaluate quoted string
  235. *
  236. * type = evalstring ();
  237. *
  238. * Entry
  239. * Exit new item added to parse stack
  240. * Returns type of item added to stack
  241. * Calls
  242. */
  243. char PASCAL CODESIZE
  244. evalstring ()
  245. {
  246. register USHORT i, max;
  247. max = 2;
  248. if (cputype & P386)
  249. max += 2;
  250. delim = NEXTC (); /* Set delim for string */
  251. i = 0;
  252. val = 0;
  253. while (!endstring () && i <= max) {
  254. val = (val << 8) + ((UCHAR)NEXTC ());
  255. i++;
  256. }
  257. if (i == 0)
  258. errorc (E_EMS);
  259. else if (i > max) { /* Too long */
  260. while (!endstring ())
  261. SKIPC ();
  262. errorcSYN ();
  263. }
  264. if (PEEKC () == delim)
  265. SKIPC ();
  266. createitem (OPERAND, ICONST);
  267. return (OPERAND);
  268. }
  269. /*** getitem - get next item on line
  270. *
  271. * getitem (p);
  272. *
  273. * Entry *p = activation record
  274. * Exit *itemptr = description of item
  275. * Returns
  276. * Calls
  277. */
  278. char PASCAL CODESIZE
  279. getitem (
  280. struct ar *p
  281. ){
  282. register char cc;
  283. #ifdef FIXCOMPILERBUG
  284. char cc1;
  285. #endif
  286. if (fValidSym)
  287. return (evalalpha (p));
  288. /* The compiler bug looses the correct value for cc when optimization is
  289. turned on. This in turn caused an exception to occure near getitem+1C0.
  290. The bogus code below sidesteps the problem. */
  291. #ifdef FIXCOMPILERBUG // This was put in to get around a MIPS compiler bug(12/3/90)
  292. cc1 = skipblanks();
  293. if (ISTERM (cc1))
  294. return (ENDEXPR);
  295. cc = cc1;
  296. #else
  297. if (ISTERM (cc = skipblanks()))
  298. return (ENDEXPR);
  299. #endif
  300. if (LEGAL1ST (cc))
  301. return (evalalpha (p));
  302. /* token is not alpha string or .string (.TYPE) operator */
  303. if (ISOPER (cc)) {
  304. SKIPC ();
  305. switch (cc) {
  306. case '(':
  307. opertype = OPLPAR;
  308. break;
  309. case '+':
  310. opertype = OPPLUS;
  311. break;
  312. case '-':
  313. opertype = OPMINUS;
  314. break;
  315. case '*':
  316. opertype = OPMULT;
  317. break;
  318. case '/':
  319. opertype = OPDIV;
  320. break;
  321. case ')':
  322. opertype = OPRPAR;
  323. break;
  324. case '.':
  325. errorcSYN ();
  326. opertype = OPDOT;
  327. break;
  328. case ',': /* should never get here, for density */
  329. break;
  330. default:
  331. if (cc == '[')
  332. opertype = OPLBRK;
  333. else if (cc == ']')
  334. opertype = OPRBRK;
  335. else if (cc == ':')
  336. opertype = OPCOLON;
  337. break;
  338. }
  339. operprec = opprec [opertype];
  340. createitem (OPERATOR, ISYM);
  341. return (OPERATOR);
  342. }
  343. else if (isdigit (cc)){
  344. evalconst ();
  345. createitem (OPERAND, ICONST);
  346. return (OPERAND);
  347. }
  348. else if ((cc == '"') || (cc == '\''))
  349. /* String may be made into constant if <=2 */
  350. return (evalstring ());
  351. else
  352. return (ENDEXPR);
  353. }
  354. /*** defaultdsc - create a default parse stack entry
  355. *
  356. * ptr = defaultdsc ();
  357. *
  358. * Entry none
  359. * Exit none
  360. * Returns *ptr = default parse stack entry
  361. * Calls malloc
  362. */
  363. DSCREC * PASCAL CODESIZE
  364. defaultdsc ()
  365. {
  366. register DSCREC *valu;
  367. valu = dalloc();
  368. *valu = emptydsc;
  369. return (valu);
  370. }
  371. VOID PASCAL
  372. makedefaultdsc ()
  373. {
  374. register struct psop *p; /* parse stack operand structure */
  375. emptydsc.itype = OPERAND;
  376. p = &emptydsc.dsckind.opnd;
  377. p->dtype = xltsymtoresult[REC];
  378. p->dflag = KNOWN;
  379. p->fixtype = FCONSTANT;
  380. }
  381. /*** checksegment - see if sreg is correct segment register for variable
  382. *
  383. * routine ();
  384. *
  385. * Entry
  386. * Exit
  387. * Returns
  388. * Calls
  389. */
  390. char PASCAL CODESIZE
  391. checksegment (
  392. UCHAR sreg,
  393. register struct ar *p
  394. ){
  395. register SYMBOL FARSYM *segctx;
  396. register SYMBOL FARSYM *segptr;
  397. if (sreg != NOSEG) { /* NOseg never found */
  398. /* Current Sreg assume */
  399. segctx = regsegment[sreg];
  400. /* Assume looking for left arg to : */
  401. segptr = p->curresult->dsckind.opnd.dcontext;
  402. if (!segptr) /* If no :, use segment */
  403. segptr = p->curresult->dsckind.opnd.dsegment;
  404. if (segptr && segctx) {
  405. #ifndef FEATURE
  406. if (segctx == pFlatGroup) /* flat space matchs all */
  407. goto found;
  408. #endif
  409. /* if same segorg or ptr is segment ... and Same group */
  410. if (segctx == segptr ||
  411. (segptr->symkind == SEGMENT &&
  412. segctx == segptr->symu.segmnt.grouptr)) {
  413. found:
  414. p->segovr = sreg;
  415. p->curresult->dsckind.opnd.dcontext = segctx;
  416. return (TRUE);
  417. }
  418. }
  419. }
  420. return (FALSE);
  421. }
  422. /*** findsegment - find segment for variable
  423. *
  424. * routine ();
  425. *
  426. * Entry
  427. * Exit
  428. * Returns
  429. * Calls
  430. */
  431. VOID PASCAL CODESIZE
  432. findsegment (
  433. UCHAR dseg,
  434. register struct ar *p
  435. ){
  436. register struct psop *pso; /* parse stack operand structure */
  437. pso = &(p->curresult->dsckind.opnd);
  438. if ((M_DATA & p->rstype) &&
  439. (pso->dsegment || pso->dcontext) &&
  440. p->linktype != FCONSTANT && pso->fixtype != FOFFSET && emittext) {
  441. /* Should find segment */
  442. if (!checksegment (dseg, p)) {
  443. /* If not in default */
  444. checksegment (CSSEG, p);
  445. checksegment (ESSEG, p);
  446. checksegment (SSSEG, p);
  447. checksegment (DSSEG, p);
  448. #ifdef V386
  449. if (cputype&P386)
  450. {
  451. checksegment (FSSEG, p);
  452. checksegment (GSSEG, p);
  453. }
  454. #endif
  455. if (p->segovr == NOSEG)
  456. /* If not found,UNKNOWN */
  457. p->segovr = NOSEG+1;
  458. }
  459. }
  460. }
  461. /*** exprop - process expression operator
  462. *
  463. * exprop (p);
  464. *
  465. * Entry
  466. * Exit
  467. * Returns
  468. * Calls
  469. */
  470. VOID PASCAL CODESIZE
  471. exprop (
  472. register struct ar *p
  473. ){
  474. register struct dscrec *pTop = itemptr;
  475. p->curprec = (unsigned char)operprec; /* Get prec of new operator */
  476. if (!p->lastitem) /* start */
  477. pTop->prec = 0;
  478. else
  479. pTop->prec = p->lastitem->prec;
  480. switch (pTop->dsckind.opr.oidx) {
  481. case OPRPAR:
  482. if (--p->parenlevel >= 0)
  483. break;
  484. /* Unmatched right paren is from count dup (xx) */
  485. p->parenlevel = 0;
  486. BACKC ();
  487. dfree((char *)pTop);
  488. p->exprdone = TRUE;
  489. return;
  490. case OPRBRK:
  491. if (--p->bracklevel >= 0)
  492. break;
  493. p->exprdone = TRUE;
  494. return;
  495. case OPLPAR:
  496. p->parenlevel++;
  497. goto leftComm;
  498. case OPLBRK:
  499. p->bracklevel++;
  500. leftComm:
  501. /* See if could have no oper in which case kludge + */
  502. if ((p->lastitem || p->addplusflag) &&
  503. p->lastitem->itype != OPERATOR) {
  504. /* make + OPERATOR */
  505. opertype = OPPLUS;
  506. createitem (OPERATOR, ISYM);
  507. p->bracklevel--;
  508. exprop(p);
  509. p->bracklevel++;
  510. p->lastprec = 6;
  511. }
  512. break;
  513. default:
  514. pTop->prec = p->curprec;
  515. break;
  516. }
  517. p->unaryflag = FALSE;
  518. if (pTop->dsckind.opr.oidx == OPPLUS ||
  519. pTop->dsckind.opr.oidx == OPMINUS) {
  520. if (!p->lastitem)
  521. p->unaryflag = TRUE;
  522. else if (p->lastitem->itype == OPERATOR)
  523. p->unaryflag = !(p->lastitem->dsckind.opr.oidx == OPRPAR ||
  524. p->lastitem->dsckind.opr.oidx == OPRBRK);
  525. }
  526. if (p->unaryflag ||
  527. (p->curprec > p->lastprec &&
  528. !(pTop->dsckind.opr.oidx == OPRPAR ||
  529. pTop->dsckind.opr.oidx == OPRBRK))) {
  530. /* Push OPERATOR */
  531. pTop->previtem = p->lastitem;
  532. p->lastitem = pTop;
  533. if (p->unaryflag) {
  534. if (pTop->dsckind.opr.oidx == OPPLUS)
  535. pTop->dsckind.opr.oidx = OPUNPLUS;
  536. else
  537. pTop->dsckind.opr.oidx = OPUNMINUS;
  538. pTop->prec = p->lastprec;
  539. p->lastprec = 10;
  540. }
  541. else
  542. p->lastprec = p->curprec;
  543. if (pTop->dsckind.opr.oidx == OPLPAR ||
  544. pTop->dsckind.opr.oidx == OPLBRK)
  545. p->lastprec = 0;
  546. }
  547. else /* Evaluate top OPERATOR */
  548. evaluate (p);
  549. }
  550. /*** forceimmed - generate error if value is not immediate
  551. *
  552. * routine ();
  553. *
  554. * Entry
  555. * Exit
  556. * Returns
  557. * Calls
  558. */
  559. VOID PASCAL CODESIZE
  560. forceimmed (
  561. register DSCREC *dsc
  562. ){
  563. if (dsc->dsckind.opnd.mode != 4)
  564. /* Must be constant */
  565. errorc (E_CXP);
  566. }
  567. /*** exprconst - check for constant expression
  568. *
  569. * routine ();
  570. *
  571. * Entry
  572. * Exit
  573. * Returns
  574. * Calls
  575. */
  576. OFFSET PASCAL CODESIZE
  577. exprconst ()
  578. {
  579. char sign;
  580. register OFFSET ret;
  581. ret = exprsmag(&sign);
  582. if (sign) {
  583. /* change to simple unary minus
  584. * pso->doffset = 65535 - ret + 1; */
  585. ret = -(long)ret;
  586. if (!fArth32)
  587. ret &= 0xffff;
  588. }
  589. return (ret);
  590. }
  591. /*** exprsmag - evaluate constant expression and return sign/magnitude
  592. *
  593. * ushort = exprsmag (sign, magnitude);
  594. *
  595. * Entry none
  596. * Exit sign = TRUE if sign of result is set
  597. * magnitude = magnitude of result
  598. * Returns 16 bit integer result
  599. * Calls expreval
  600. */
  601. OFFSET PASCAL CODESIZE
  602. exprsmag (
  603. char *sign
  604. ){
  605. register struct psop *pso; /* parse stack operand structure */
  606. register OFFSET ret;
  607. DSCREC *dsc;
  608. dsc = expreval (&nilseg);
  609. forceimmed (dsc);
  610. pso = &(dsc->dsckind.opnd);
  611. *sign = pso->dsign;
  612. ret = pso->doffset;
  613. dfree ((char *)dsc );
  614. return (ret);
  615. }