assemble.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /* assemble.c - main loop for assembler */
  2. #include "syshead.h"
  3. #include "const.h"
  4. #include "type.h"
  5. #include "address.h"
  6. #include "globvar.h"
  7. #include "opcode.h"
  8. #include "scan.h"
  9. PRIVATE bool_t nocolonlabel; /* set for labels not followed by ':' */
  10. PRIVATE void (*routine) P((void));
  11. #ifdef I80386
  12. PRIVATE opcode_t rep = 0; /* which rep/repne prefix was seen */
  13. #endif
  14. PRIVATE pfv rout_table[] =
  15. {
  16. pelse,
  17. pelseif,
  18. pelsifc,
  19. pendif,
  20. pif,
  21. pifc,
  22. /* start of non-conditionals */
  23. palign,
  24. pasciz,
  25. pblkw,
  26. pblock,
  27. pbss,
  28. pcomm,
  29. pcomm1,
  30. pdata,
  31. pendb,
  32. penter,
  33. pentry,
  34. pequ,
  35. peven,
  36. pexport,
  37. pfail,
  38. pfcb,
  39. pfcc,
  40. pfdb,
  41. #if SIZEOF_OFFSET_T > 2
  42. pfqb,
  43. #endif
  44. pget,
  45. pglobl,
  46. pident,
  47. pimport,
  48. plcomm,
  49. plcomm1,
  50. plist,
  51. ploc,
  52. pmaclist,
  53. pmacro,
  54. pmap,
  55. porg,
  56. pproceof,
  57. prmb,
  58. psect,
  59. pset,
  60. psetdp,
  61. ptext,
  62. #ifdef I80386
  63. puse16,
  64. puse32,
  65. #endif
  66. pwarn,
  67. /* end of pseudo-ops */
  68. #ifdef I80386
  69. mbcc,
  70. mbswap,
  71. mcall,
  72. mcalli,
  73. mdivmul,
  74. menter,
  75. mEwGw,
  76. mExGx,
  77. mf_inher,
  78. mf_m,
  79. mf_m2,
  80. mf_m2_ax,
  81. mf_m2_m4,
  82. mf_m2_m4_m8,
  83. mf_m4_m8_optst,
  84. mf_m4_m8_st,
  85. mf_m4_m8_stst,
  86. mf_m4_m8_m10_st,
  87. mf_m10,
  88. mf_optst,
  89. mf_st,
  90. mf_stst,
  91. mf_w_inher,
  92. mf_w_m,
  93. mf_w_m2,
  94. mf_w_m2_ax,
  95. mgroup1,
  96. mgroup2,
  97. mgroup6,
  98. mgroup7,
  99. mgroup8,
  100. mGvEv,
  101. mGvMa,
  102. mGvMp,
  103. mimul,
  104. min,
  105. mincdec,
  106. minher,
  107. minher16,
  108. minher32,
  109. minhera,
  110. mint,
  111. mjcc,
  112. mjcxz,
  113. mlea,
  114. mmov,
  115. mmovx,
  116. mnegnot,
  117. mout,
  118. mpushpop,
  119. mret,
  120. mseg,
  121. msetcc,
  122. mshdouble,
  123. mtest,
  124. mxchg,
  125. #endif /* I80386 */
  126. #ifdef MC6809
  127. mall, /* all address modes allowed, like LDA */
  128. malter, /* all but immediate, like STA */
  129. mimmed, /* immediate only (ANDCC, ORCC) */
  130. mindex, /* indexed (LEA's) */
  131. minher, /* inherent, like CLC or CLRA */
  132. mlong, /* long branches */
  133. mshort, /* short branches */
  134. msstak, /* S-stack (PSHS, PULS) */
  135. mswap, /* TFR, EXG */
  136. mustak, /* U-stack (PSHU,PULU) */
  137. #endif /* MC6809 */
  138. };
  139. FORWARD void asline P((void));
  140. /*
  141. This uses registers as follows: A is for work and is not preserved by
  142. the subroutines.B holds the last symbol code, X usually points to data
  143. about the last symbol, U usually holds the value of last expression
  144. or symbol, and Y points to the current char. The value in Y is needed
  145. by READCH and GETSYM. EXPRES needs B and Y, and returns a value in U.
  146. If the expression starts with an identifier, X must point to its string.
  147. LOOKUP needs a string pointer in X and length in A. It returns a table
  148. pointer in X (unless not assembling and not found), symbol type in A
  149. and overflow in CC.
  150. */
  151. PUBLIC void assemble()
  152. {
  153. while (TRUE)
  154. {
  155. asline();
  156. if (label != NUL_PTR) /* must be confirmed if still set */
  157. { /* it is nulled by EQU, COMM and SET */
  158. #ifndef MC6809
  159. #define NEEDENDLABEL ILLAB
  160. if (nocolonlabel)
  161. error(NEEDENDLABEL);
  162. #endif
  163. if(pass && label->value_reg_or_op.value != oldlabel)
  164. {
  165. dirty_pass = TRUE;
  166. if( pass == last_pass )
  167. error(UNSTABLE_LABEL);
  168. }
  169. label->type |= LABIT; /* confirm, perhaps redundant */
  170. if (label->type & REDBIT)
  171. {
  172. /* REDBIT meant 'GLOBLBIT' while LABIT was not set. */
  173. label->type |= EXPBIT;
  174. label->type &= ~REDBIT;
  175. }
  176. if ((mcount | popflags) == 0)
  177. /* unaccompanied label, display adr like EQU and SET */
  178. showlabel();
  179. label = NUL_PTR; /* reset for next line */
  180. }
  181. skipline();
  182. listline();
  183. genbin();
  184. genobj();
  185. binmbuf = lc += lcjump
  186. #ifdef I80386
  187. + immcount
  188. #endif
  189. ;
  190. }
  191. }
  192. PRIVATE void asline()
  193. {
  194. register struct sym_s *symptr;
  195. postb = popflags = pcrflag =
  196. #ifdef I80386
  197. sprefix = oprefix = aprefix =
  198. #endif
  199. immcount = lastexp.data = lcjump = 0;
  200. #ifdef I80386
  201. sib = NO_SIB;
  202. #endif
  203. #if SIZEOF_OFFSET_T > 2
  204. fqflag =
  205. #endif
  206. fdflag = fcflag = FALSE;
  207. cpuwarn();
  208. readline();
  209. getsym();
  210. if (sym != IDENT) /* expect label, mnemonic or macro */
  211. {
  212. /* Warn if not a comment marker or a hash (for /lib/cpp) */
  213. if( sym != EOLSYM && sym != IMMEDIATE )
  214. list_force = TRUE;
  215. return; /* anything else is a comment */
  216. }
  217. symptr = gsymptr;
  218. if (!ifflag)
  219. /* not assembling, just test for IF/ELSE/ELSEIF/ENDIF */
  220. {
  221. if (symptr == NUL_PTR || !(symptr->type & MNREGBIT) ||
  222. symptr->data & REGBIT ||
  223. symptr->value_reg_or_op.op.routine >= MIN_NONCOND)
  224. return;
  225. }
  226. else if (!(symptr->type & (MACBIT | MNREGBIT)))
  227. /* not macro, op, pseudo-op or register, expect label */
  228. {
  229. oldlabel = symptr->value_reg_or_op.value;
  230. if ((nocolonlabel = (*lineptr - ':')) == 0) /* exported label? */
  231. {
  232. sym = COLON;
  233. ++lineptr;
  234. }
  235. if (symptr->type & (LABIT | VARBIT))
  236. {
  237. if (symptr->type & REDBIT)
  238. labelerror(RELAB);
  239. label = symptr;
  240. if (pass && !(symptr->type & VARBIT) /*&& last_pass>1*/)
  241. {
  242. label->data = (label->data & FORBIT) | lcdata;
  243. label->value_reg_or_op.value = lc;
  244. }
  245. }
  246. else if (checksegrel(symptr))
  247. {
  248. symptr->type &= ~COMMBIT; /* ignore COMM, PCOMM gives warning */
  249. #ifdef MC6809
  250. #if 0
  251. if (sym == COLON)
  252. symptr->type |= EXPBIT;
  253. #endif
  254. #endif
  255. /* remember if forward referenced */
  256. symptr->data = (symptr->data & FORBIT) | lcdata;
  257. symptr->value_reg_or_op.value = lc;
  258. /* unless changed by EQU,COMM or SET */
  259. label = symptr;
  260. }
  261. getsym();
  262. if (sym != IDENT)
  263. {
  264. if (sym == EQOP)
  265. {
  266. getsym();
  267. pequ();
  268. }
  269. return; /* anything but ident is comment */
  270. }
  271. symptr = gsymptr;
  272. }
  273. if (symptr->type & MACBIT)
  274. {
  275. entermac(symptr);
  276. return;
  277. }
  278. if (!(symptr->type & MNREGBIT))
  279. {
  280. error(OPEXP);
  281. return;
  282. }
  283. if (symptr->data & REGBIT)
  284. {
  285. error(REGUID);
  286. return;
  287. }
  288. mnsize = 0;
  289. if ((page = (symptr->data & (PAGE1 | PAGE2))) != 0)
  290. {
  291. #ifdef MNSIZE
  292. if (page == (PAGE1 | PAGE2))
  293. {
  294. mnsize = 1;
  295. page = 0;
  296. }
  297. else
  298. #endif
  299. {
  300. #ifdef PAGE2_OPCODE
  301. if (page == PAGE2)
  302. page = PAGE2_OPCODE;
  303. else
  304. #endif
  305. page = PAGE1_OPCODE;
  306. mcount = 1;
  307. }
  308. }
  309. opcode = symptr->value_reg_or_op.op.opcode;
  310. #ifdef I80386
  311. needcpu((page==0 && ((opcode&0xF0) == 0x60||(opcode&0xF6)==0xC0))?1:0);
  312. #endif
  313. routine = rout_table[symptr->value_reg_or_op.op.routine];
  314. getsym();
  315. (*routine)();
  316. #ifdef I80386
  317. /* We handle "rep[ne]" refix as separate instruction; check if its use is valid */
  318. if (opcode == 0xF2 || opcode == 0xF3) { /* REP */
  319. rep = opcode;
  320. /* Not another prefix */
  321. } else if (opcode != 0x2E && /* CSEG */
  322. opcode != 0x3E && /* DSEG */
  323. opcode != 0x26 && /* ESEG */
  324. opcode != 0x64 && /* FSEG */
  325. opcode != 0x65 && /* GSEG */
  326. opcode != 0x36 && /* SSEG */
  327. opcode != 0xF0) { /* LOCK */
  328. if (rep == 0xF2 && (opcode&0xF6) != 0xA6) /* REPNE CMPS/SCAS */
  329. error (REPNE_STRING);
  330. if (rep == 0xF3 && !((opcode&0xFC) == 0x6C || /* REP INS/OUTS */
  331. (opcode&0xFC) == 0xA4 || /* REP MOVS/CMPS */
  332. (opcode&0xFC) == 0xAC || /* REP SCAS/LODS */
  333. (opcode&0xFE) == 0xAA)) /* REP STOS */
  334. error (REP_STRING);
  335. rep = 0;
  336. }
  337. #endif
  338. if (sym != EOLSYM)
  339. error(JUNK_AFTER_OPERANDS);
  340. #ifdef I80386
  341. needcpu(page==PAGE1_OPCODE?2:0);
  342. if (aprefix != 0)
  343. ++mcount;
  344. if (oprefix != 0)
  345. ++mcount;
  346. if (sprefix != 0)
  347. ++mcount;
  348. #endif
  349. }