genobj.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /* genobj.c - object code generation routines for assembler */
  2. #include "syshead.h"
  3. #include "const.h"
  4. #include "type.h"
  5. #include "address.h"
  6. #include "file.h"
  7. #include "globvar.h"
  8. #define OBJBUFSIZE 512 /* size of object code output buffer */
  9. #define isge2byteoffset(offset) ((offset) >= 0x100)
  10. #define isge4byteoffset(offset) ((offset) >= 0x10000L)
  11. PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */
  12. PRIVATE char *absbuf; /* start */
  13. PRIVATE char *absbufend; /* last location + 1 */
  14. PRIVATE char *absbufptr; /* current location */
  15. PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */
  16. PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */
  17. PRIVATE unsigned numext; /* number of external symbols */
  18. PRIVATE char *objbuf; /* start */
  19. PRIVATE char *objbufend; /* last location + 1 */
  20. PRIVATE char *objbufptr; /* current location */
  21. PRIVATE unsigned char relsize; /* current relocation size, 0 init */
  22. /* local to genobjadr, but here */
  23. /* because of static re-init bug */
  24. PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */
  25. FORWARD void flushabs P((void));
  26. FORWARD void flushrmb P((void));
  27. FORWARD void genobjadr P((struct address_s *adrptr, int size));
  28. FORWARD void putobj1 P((opcode_pt ch));
  29. FORWARD void putobj4 P((u32_T offset));
  30. FORWARD void putobjoffset P((offset_t offset, count_t size));
  31. FORWARD void putobjword P((unsigned word));
  32. FORWARD void writeobj P((char *buf, unsigned count));
  33. /* accumulate RMB requests into 1 (so + and - requests cancel) */
  34. PUBLIC void accumulate_rmb(offset)
  35. offset_t offset;
  36. {
  37. if (objectc)
  38. {
  39. flushabs();
  40. rmbcount += offset;
  41. }
  42. }
  43. /* flush absolute object code buffer to object code buffer if necessary */
  44. PRIVATE void flushabs()
  45. {
  46. if (absbufptr > absbuf)
  47. {
  48. putobj1((absbufptr - absbuf) | OBJ_ABS);
  49. {
  50. register char *bufptr;
  51. bufptr = absbuf;
  52. do
  53. putobj1(*bufptr);
  54. while (++bufptr < absbufptr);
  55. absbufptr = absbuf;
  56. }
  57. }
  58. }
  59. /* flush object code buffer if necessary */
  60. PUBLIC void flushobj()
  61. {
  62. int ntowrite;
  63. if ((ntowrite = objbufptr - objbuf) > 0)
  64. {
  65. if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite)
  66. {
  67. error(OBJOUT);
  68. listline();
  69. finishup();
  70. }
  71. objbufptr = objbuf;
  72. }
  73. }
  74. /* flush RMB count if necessary */
  75. PRIVATE void flushrmb()
  76. {
  77. count_t size;
  78. if (rmbcount != 0)
  79. {
  80. #if SIZEOF_OFFSET_T > 2
  81. if (isge4byteoffset(rmbcount))
  82. {
  83. putobj1(OBJ_SKIP_4);
  84. size = 4;
  85. }
  86. else
  87. #endif
  88. if (isge2byteoffset(rmbcount))
  89. {
  90. putobj1(OBJ_SKIP_2);
  91. size = 2;
  92. }
  93. else
  94. {
  95. putobj1(OBJ_SKIP_1);
  96. size = 1;
  97. }
  98. putobjoffset(rmbcount, size);
  99. rmbcount = 0;
  100. }
  101. }
  102. /* generate object code for current line */
  103. /*
  104. any address parameter is (regrettably) in lastexp
  105. any immediate parameter is (corectly) in immadr
  106. */
  107. PUBLIC void genobj()
  108. {
  109. struct address_s *adrptr;
  110. char *bufptr;
  111. unsigned char remaining;
  112. if (objectc && mcount != 0)
  113. {
  114. if (popflags)
  115. {
  116. if (fcflag)
  117. {
  118. bufptr = databuf.fcbuf;
  119. remaining = mcount;
  120. do
  121. putabs(*bufptr++);
  122. while (--remaining != 0);
  123. }
  124. if (fdflag)
  125. {
  126. adrptr = databuf.fdbuf;
  127. remaining = mcount;
  128. do
  129. genobjadr(adrptr++, 2);
  130. while ((remaining -= 2) != 0);
  131. }
  132. #if SIZEOF_OFFSET_T > 2
  133. if (fqflag)
  134. {
  135. adrptr = databuf.fqbuf;
  136. remaining = mcount;
  137. do
  138. genobjadr(adrptr++, 4);
  139. while ((remaining -= 4) != 0);
  140. }
  141. #endif
  142. }
  143. else
  144. {
  145. remaining = mcount - 1; /* count opcode immediately */
  146. #ifdef I80386
  147. if (aprefix != 0)
  148. {
  149. putabs(aprefix);
  150. --remaining;
  151. }
  152. if (oprefix != 0)
  153. {
  154. putabs(oprefix);
  155. --remaining;
  156. }
  157. if (sprefix != 0)
  158. {
  159. putabs(sprefix);
  160. --remaining;
  161. }
  162. #endif
  163. if (page != 0)
  164. {
  165. putabs(page);
  166. --remaining;
  167. }
  168. putabs(opcode);
  169. if (remaining != 0)
  170. {
  171. if (postb != 0)
  172. {
  173. putabs(postb);
  174. --remaining;
  175. }
  176. #ifdef I80386
  177. if (sib != NO_SIB)
  178. {
  179. putabs(sib);
  180. --remaining;
  181. }
  182. #endif
  183. if (remaining != 0)
  184. genobjadr(&lastexp, remaining);
  185. }
  186. }
  187. #ifdef I80386
  188. if (immcount != 0)
  189. genobjadr(&immadr, immcount);
  190. #endif
  191. }
  192. }
  193. /* generate object code for current address */
  194. PRIVATE void genobjadr(adrptr, size)
  195. struct address_s *adrptr;
  196. smallcount_t size;
  197. {
  198. unsigned char byte;
  199. unsigned symnum;
  200. if (!(adrptr->data & RELBIT))
  201. {
  202. /* absolute address */
  203. char buf[sizeof(offset_t)];
  204. #if SIZEOF_OFFSET_T > 2
  205. u4cn(buf, adrptr->offset, size);
  206. #else
  207. u2cn(buf, adrptr->offset, size);
  208. #endif
  209. putabs(buf[0]);
  210. if (size > 1)
  211. putabs(buf[1]);
  212. if (size > 2)
  213. {
  214. putabs(buf[2]);
  215. putabs(buf[3]);
  216. }
  217. }
  218. else
  219. {
  220. /* relocatable address */
  221. if (size != relsize)
  222. /* set reloc size index |00|0000xx| */
  223. putobj((relsize = size) == 4 ? 0x03 : relsize);
  224. if (!(adrptr->data & IMPBIT))
  225. {
  226. /* offset relocation (known offset) */
  227. putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag);
  228. putobjoffset(adrptr->offset, size);
  229. }
  230. else
  231. {
  232. /* symbol relocation (imported symbol + offset) */
  233. {
  234. register struct sym_s **copyptr;
  235. for (copyptr = arrext, symnum = 0;
  236. symnum < numext && *copyptr++ != adrptr->sym; ++symnum)
  237. ;
  238. }
  239. byte = OBJ_SYMBOL_REL;
  240. if (isge2byteoffset(symnum))
  241. byte = OBJ_SYMBOL_REL | OBJ_S_MASK;
  242. #if SIZEOF_OFFSET_T > 2
  243. if (isge4byteoffset(adrptr->offset))
  244. {
  245. byte |= 0x03; /* 4 byte offset */
  246. size = 4;
  247. }
  248. else
  249. #endif
  250. if (isge2byteoffset(adrptr->offset))
  251. {
  252. byte |= 0x02; /* 2 byte offset */
  253. size = 2;
  254. }
  255. else if (adrptr->offset != 0)
  256. {
  257. byte |= 0x01; /* 1 byte offset */
  258. size = 1;
  259. }
  260. else
  261. size = 0;
  262. putobj(byte | pcrflag);
  263. if (isge2byteoffset(symnum))
  264. putobjword(symnum);
  265. else
  266. putobj1((opcode_pt) symnum);
  267. if (adrptr->offset != 0)
  268. putobjoffset(adrptr->offset, size);
  269. }
  270. }
  271. }
  272. /* initialise private variables */
  273. PUBLIC void initobj()
  274. {
  275. absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf;
  276. objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf;
  277. }
  278. /*
  279. write header to object file
  280. also build array of imported/exported symbols
  281. */
  282. PUBLIC void objheader()
  283. {
  284. static char module_header[] =
  285. {
  286. #ifdef I80386
  287. 0xA3, 0x86,
  288. 1, 0,
  289. (char) (0xA3 + 0x86 + 1 + 0),
  290. #endif
  291. #ifdef MC6809
  292. 'S', '1', /* 2 byte magic number */
  293. 0, 1, /* 2 byte number of modules in file */
  294. 'S' + '1' + 0 + 1, /* 1 byte checksum */
  295. #endif
  296. };
  297. static char seg_max_sizes[] =
  298. {
  299. 0x55, /* all segments have maximum size 2^16 */
  300. 0x55, /* this is encoded by 0b01 4 times per byte */
  301. 0x55, /* other codes are 0b00 = max size 2^8 */
  302. 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */
  303. };
  304. unsigned char byte;
  305. register struct sym_s **copyptr;
  306. struct sym_s **copytop;
  307. struct sym_s **hashptr;
  308. struct lc_s *lcp;
  309. char module_name[FILNAMLEN + 1];
  310. char *nameptr;
  311. unsigned offset;
  312. unsigned segsizebytes;
  313. unsigned size;
  314. unsigned char sizebits;
  315. unsigned strsiz; /* size of object string table */
  316. unsigned symosiz; /* size of object symbol table */
  317. register struct sym_s *symptr;
  318. u32_T textlength;
  319. int symcount = 0;
  320. if ((objectc = objectg) == 0)
  321. return;
  322. writeobj(module_header, sizeof module_header);
  323. /* calculate number of imported/exported symbols */
  324. /* and lengths of symbol and string tables */
  325. /* build array of imported/exported symbols */
  326. symosiz = 0;
  327. if (truefilename == NUL_PTR)
  328. truefilename = filnamptr;
  329. nameptr = strrchr(truefilename, DIRCHAR);
  330. strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename);
  331. if ((nameptr = strrchr(module_name, '.')) != NUL_PTR)
  332. *nameptr = 0;
  333. strsiz = strlen(module_name) + 1;
  334. for (hashptr = spt; hashptr < spt_top;)
  335. if ((symptr = *hashptr++) != NUL_PTR)
  336. do
  337. {
  338. if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
  339. (!globals_only_in_obj && symptr->name[0] != '.' &&
  340. !(symptr->type & (MNREGBIT | MACBIT | VARBIT))))
  341. {
  342. symcount ++;
  343. }
  344. }
  345. while ((symptr = symptr->next) != NUL_PTR);
  346. arrext = copyptr = asalloc( sizeof(struct sym_s *) * symcount);
  347. for (hashptr = spt; hashptr < spt_top;)
  348. if ((symptr = *hashptr++) != NUL_PTR)
  349. do
  350. {
  351. if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
  352. (!globals_only_in_obj && symptr->name[0] != '.' &&
  353. !(symptr->type & (MNREGBIT | MACBIT | VARBIT))))
  354. {
  355. *copyptr++ = symptr;
  356. strsiz += symptr->length + 1;
  357. if (textseg>=0 && (symptr->data & SEGM) == textseg)
  358. strsiz+=2;
  359. #if SIZEOF_OFFSET_T > 2
  360. if (isge4byteoffset(symptr->value_reg_or_op.value))
  361. size = 4 + 4;
  362. /* 4 is size of offset into string table and flags */
  363. /* 2nd 4 is for 4 byte offset */
  364. else
  365. #endif
  366. if (isge2byteoffset(symptr->value_reg_or_op.value))
  367. size = 4 + 2;
  368. else if (symptr->value_reg_or_op.value != 0)
  369. size = 4 + 1;
  370. else
  371. size = 4;
  372. symosiz += size;
  373. ++numext;
  374. }
  375. }
  376. while ((symptr = symptr->next) != NUL_PTR);
  377. copytop = copyptr;
  378. /* calculate length of text, and number of seg size bytes in header */
  379. textlength = segsizebytes = 0;
  380. lcp = lctab;
  381. do
  382. if (lcp->lc != 0)
  383. {
  384. textlength += lcp->lc; /* assuming text starts at 0 */
  385. #if SIZEOF_OFFSET_T > 2
  386. if (isge4byteoffset(lcp->lc))
  387. segsizebytes += 4;
  388. else
  389. #endif
  390. segsizebytes += 2; /* use 2 byte size if possible */
  391. }
  392. while (++lcp < lctabtop);
  393. /*
  394. offset to text = length of header since only 1 module
  395. header consists of:
  396. module header sizeof module_header
  397. offset to start of text 4
  398. length of text 4
  399. length of string area 2
  400. class 1
  401. revision 1
  402. seg max sizes sizeof seg_max_sizes
  403. seg size descriptors 4
  404. seg sizes segsizebytes
  405. symbol count 2
  406. symbol offsets and types symosiz
  407. strings strsiz
  408. */
  409. /* offset to start of text */
  410. putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 +
  411. sizeof seg_max_sizes + 4 + segsizebytes + 2 +
  412. symosiz) + strsiz);
  413. /* length of text */
  414. putobj4((u32_T) textlength);
  415. /* length of string area */
  416. putobjword(strsiz);
  417. /* class and revision */
  418. putobj1(0);
  419. putobj1(0);
  420. /* segment max sizes (constant) */
  421. writeobj(seg_max_sizes, sizeof seg_max_sizes);
  422. /* segment size descriptors */
  423. /* produce only 0 and 2 byte sizes */
  424. lcp = lctabtop;
  425. byte = 0;
  426. sizebits = OBJ_SEGSZ_TWO << 6;
  427. do
  428. {
  429. --lcp;
  430. if (lcp->lc != 0)
  431. {
  432. byte |= sizebits;
  433. #if SIZEOF_OFFSET_T > 2
  434. if (isge4byteoffset(lcp->lc))
  435. byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */
  436. #endif
  437. }
  438. if ((sizebits >>= 2) == 0)
  439. {
  440. putobj1(byte);
  441. byte = 0;
  442. sizebits = OBJ_SEGSZ_TWO << 6;
  443. }
  444. }
  445. while (lcp > lctab);
  446. /* segment sizes */
  447. do /* lcp starts at lctab */
  448. if (lcp->lc != 0)
  449. {
  450. #if SIZEOF_OFFSET_T > 2
  451. if (isge4byteoffset(lcp->lc))
  452. putobj4(lcp->lc);
  453. else
  454. #endif
  455. putobjword((unsigned) lcp->lc);
  456. }
  457. while (++lcp < lctabtop);
  458. /* symbol count */
  459. putobjword(numext);
  460. /* symbol offsets and types */
  461. offset = strlen(module_name) + 1; /* 1st symbol begins after name */
  462. for (copyptr = arrext; copyptr < copytop;)
  463. {
  464. putobjword(offset);
  465. symptr = *copyptr++;
  466. byte = symptr->type & OBJ_N_MASK;
  467. #if SIZEOF_OFFSET_T > 2
  468. if (isge4byteoffset(symptr->value_reg_or_op.value))
  469. {
  470. byte |= OBJ_SZ_FOUR;
  471. size = 4;
  472. }
  473. else
  474. #endif
  475. if (isge2byteoffset(symptr->value_reg_or_op.value))
  476. {
  477. byte |= OBJ_SZ_TWO;
  478. size = 2;
  479. }
  480. else if (symptr->value_reg_or_op.value != 0)
  481. {
  482. byte |= OBJ_SZ_ONE;
  483. size = 1;
  484. }
  485. else
  486. size = 0;
  487. if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
  488. {
  489. byte |= OBJ_SA_MASK;
  490. symptr->data &= ~OBJ_I_MASK;
  491. }
  492. putobjword((unsigned)
  493. (byte << 0x8) |
  494. (symptr->type & OBJ_E_MASK) | /* |E|0000000| */
  495. ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^
  496. /* |0|I|0|A|SEGM| */
  497. RELBIT)); /* RELBIT by negative logic */
  498. if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
  499. symptr->data |= OBJ_I_MASK;
  500. if (size != 0)
  501. putobjoffset(symptr->value_reg_or_op.value, size);
  502. offset += symptr->length + 1;
  503. if (textseg>=0 && (symptr->data & SEGM) == textseg)
  504. offset+=2;
  505. }
  506. /* strings */
  507. writeobj(module_name, strlen(module_name));
  508. putobj1(0);
  509. for (copyptr = arrext; copyptr < copytop;)
  510. {
  511. symptr = *copyptr++;
  512. writeobj(symptr->name, symptr->length);
  513. if (textseg>=0 && (symptr->data & SEGM) == textseg)
  514. {
  515. putobj1('.');
  516. putobj1(hexdigit[textseg]);
  517. }
  518. putobj1(0);
  519. }
  520. putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */
  521. }
  522. /* write trailer to object file */
  523. PUBLIC void objtrailer()
  524. {
  525. if (objectc)
  526. {
  527. putobj(0); /* end of object file */
  528. flushobj();
  529. }
  530. }
  531. /* write char to absolute object code buffer, flush if necessary */
  532. PUBLIC void putabs(ch)
  533. opcode_pt ch;
  534. {
  535. if (objectc)
  536. {
  537. if (rmbcount != 0)
  538. flushrmb();
  539. if (absbufptr >= absbufend)
  540. flushabs();
  541. *absbufptr++ = ch;
  542. }
  543. }
  544. /* write char to object code buffer, flush if necessary */
  545. PUBLIC void putobj(ch)
  546. opcode_pt ch;
  547. {
  548. if (objectc)
  549. {
  550. flushabs();
  551. flushrmb();
  552. putobj1(ch);
  553. }
  554. }
  555. /* write char to object code buffer assuming nothing in absolute & rmb bufs */
  556. PRIVATE void putobj1(ch)
  557. opcode_pt ch;
  558. {
  559. if (objbufptr >= objbufend)
  560. flushobj();
  561. *objbufptr++ = ch;
  562. }
  563. /* write 32 bit offset to object code buffer assuming ... */
  564. PRIVATE void putobj4(offset)
  565. u32_T offset;
  566. {
  567. char buf[sizeof offset];
  568. u4c4(buf, offset);
  569. writeobj(buf, 4);
  570. }
  571. /* write sized offset to object code buffer assuming ... */
  572. PRIVATE void putobjoffset(offset, size)
  573. offset_t offset;
  574. count_t size;
  575. {
  576. char buf[sizeof offset];
  577. #if SIZEOF_OFFSET_T > 2
  578. u4cn(buf, offset, size);
  579. #else
  580. u2cn(buf, offset, size);
  581. #endif
  582. putobj1(buf[0]);
  583. if (size > 1)
  584. putobj1(buf[1]);
  585. if (size > 2)
  586. {
  587. putobj1(buf[2]);
  588. putobj1(buf[3]);
  589. }
  590. }
  591. /* write word to object code buffer assuming ... */
  592. PRIVATE void putobjword(word)
  593. unsigned word;
  594. {
  595. char buf[sizeof word];
  596. u2c2(buf, word);
  597. putobj1(buf[0]);
  598. putobj1(buf[1]);
  599. }
  600. /* write several bytes to object code buffer assuming ... */
  601. PRIVATE void writeobj(buf, count)
  602. char *buf;
  603. unsigned count;
  604. {
  605. do
  606. putobj1(*buf++);
  607. while (--count);
  608. }