asm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. #include "l.h"
  2. #define KMASK 0xF0000000
  3. #define LPUT(c)\
  4. {\
  5. cbp[0] = (c)>>24;\
  6. cbp[1] = (c)>>16;\
  7. cbp[2] = (c)>>8;\
  8. cbp[3] = (c);\
  9. cbp += 4;\
  10. cbc -= 4;\
  11. if(cbc <= 0)\
  12. cflush();\
  13. }
  14. #define CPUT(c)\
  15. {\
  16. cbp[0] = (c);\
  17. cbp++;\
  18. cbc--;\
  19. if(cbc <= 0)\
  20. cflush();\
  21. }
  22. void strnput(char*, int);
  23. long
  24. entryvalue(void)
  25. {
  26. char *a;
  27. Sym *s;
  28. a = INITENTRY;
  29. if(*a >= '0' && *a <= '9')
  30. return atolwhex(a);
  31. s = lookup(a, 0);
  32. if(s->type == 0)
  33. return INITTEXT;
  34. if(dlm && s->type == SDATA)
  35. return s->value+INITDAT;
  36. if(s->type != STEXT && s->type != SLEAF)
  37. diag("entry not text: %s", s->name);
  38. return s->value;
  39. }
  40. void
  41. asmb(void)
  42. {
  43. Prog *p;
  44. long t;
  45. Optab *o;
  46. if(debug['v'])
  47. Bprint(&bso, "%5.2f asm\n", cputime());
  48. Bflush(&bso);
  49. seek(cout, HEADR, 0);
  50. pc = INITTEXT;
  51. for(p = firstp; p != P; p = p->link) {
  52. if(p->as == ATEXT) {
  53. curtext = p;
  54. autosize = p->to.offset + 4;
  55. if(p->from3.type == D_CONST) {
  56. for(; pc < p->pc; pc++)
  57. CPUT(0);
  58. }
  59. }
  60. if(p->pc != pc) {
  61. diag("phase error %lux sb %lux",
  62. p->pc, pc);
  63. if(!debug['a'])
  64. prasm(curp);
  65. pc = p->pc;
  66. }
  67. curp = p;
  68. o = oplook(p); /* could probably avoid this call */
  69. if(asmout(p, o, 0)) {
  70. p = p->link;
  71. pc += 4;
  72. }
  73. pc += o->size;
  74. }
  75. if(debug['a'])
  76. Bprint(&bso, "\n");
  77. Bflush(&bso);
  78. cflush();
  79. curtext = P;
  80. switch(HEADTYPE) {
  81. case 0:
  82. case 1:
  83. case 2:
  84. case 5:
  85. seek(cout, HEADR+textsize, 0);
  86. break;
  87. case 3:
  88. seek(cout, rnd(HEADR+textsize, 4), 0);
  89. break;
  90. case 4:
  91. seek(cout, rnd(HEADR+textsize, 4096), 0);
  92. break;
  93. }
  94. if(dlm){
  95. char buf[8];
  96. write(cout, buf, INITDAT-textsize);
  97. textsize = INITDAT;
  98. }
  99. for(t = 0; t < datsize; t += sizeof(buf)-100) {
  100. if(datsize-t > sizeof(buf)-100)
  101. datblk(t, sizeof(buf)-100);
  102. else
  103. datblk(t, datsize-t);
  104. }
  105. symsize = 0;
  106. lcsize = 0;
  107. if(!debug['s']) {
  108. if(debug['v'])
  109. Bprint(&bso, "%5.2f sym\n", cputime());
  110. Bflush(&bso);
  111. switch(HEADTYPE) {
  112. case 0:
  113. case 1:
  114. case 2:
  115. case 5:
  116. seek(cout, HEADR+textsize+datsize, 0);
  117. break;
  118. case 3:
  119. seek(cout, rnd(HEADR+textsize, 4)+datsize, 0);
  120. break;
  121. case 4:
  122. seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0);
  123. break;
  124. }
  125. if(!debug['s'])
  126. asmsym();
  127. if(debug['v'])
  128. Bprint(&bso, "%5.2f sp\n", cputime());
  129. Bflush(&bso);
  130. if(!debug['s'])
  131. asmlc();
  132. if(dlm)
  133. asmdyn();
  134. if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */
  135. if((symsize+lcsize) & 1)
  136. CPUT(0);
  137. cflush();
  138. }
  139. else if(dlm){
  140. asmdyn();
  141. cflush();
  142. }
  143. seek(cout, 0L, 0);
  144. switch(HEADTYPE) {
  145. case 0:
  146. lput(0x1030107); /* magic and sections */
  147. lput(textsize); /* sizes */
  148. lput(datsize);
  149. lput(bsssize);
  150. lput(symsize); /* nsyms */
  151. lput(entryvalue()); /* va of entry */
  152. lput(0L);
  153. lput(lcsize);
  154. break;
  155. case 1:
  156. lput(0x4a6f7921); /* Joy! */
  157. lput(0x70656666); /* peff */
  158. lput(0x70777063); /* pwpc */
  159. lput(1);
  160. lput(0);
  161. lput(0);
  162. lput(0);
  163. lput(0);
  164. lput(0x30002); /*YY*/
  165. lput(0);
  166. lput(~0);
  167. lput(0);
  168. lput(textsize+datsize);
  169. lput(textsize+datsize);
  170. lput(textsize+datsize);
  171. lput(0xd0); /* header size */
  172. lput(0x10400);
  173. lput(~0);
  174. lput(0);
  175. lput(0xc);
  176. lput(0xc);
  177. lput(0xc);
  178. lput(0xc0);
  179. lput(0x01010400);
  180. lput(~0);
  181. lput(0);
  182. lput(0x38);
  183. lput(0x38);
  184. lput(0x38);
  185. lput(0x80);
  186. lput(0x04040400);
  187. lput(0);
  188. lput(1);
  189. lput(0);
  190. lput(~0);
  191. lput(0);
  192. lput(~0);
  193. lput(0);
  194. lput(0);
  195. lput(0);
  196. lput(0);
  197. lput(0);
  198. lput(0);
  199. lput(0);
  200. lput(0);
  201. lput(0);
  202. lput(0);
  203. lput(0);
  204. lput(0x3100); /* load address */
  205. lput(0);
  206. lput(0);
  207. lput(0); /* whew! */
  208. break;
  209. case 2:
  210. if(dlm)
  211. lput(0x80000000 | (4*21*21+7)); /* magic */
  212. else
  213. lput(4*21*21+7); /* magic */
  214. lput(textsize); /* sizes */
  215. lput(datsize);
  216. lput(bsssize);
  217. lput(symsize); /* nsyms */
  218. lput(entryvalue()); /* va of entry */
  219. lput(0L);
  220. lput(lcsize);
  221. break;
  222. case 3:
  223. break;
  224. case 4:
  225. lput((0x1DFL<<16)|3L); /* magic and sections */
  226. lput(time(0)); /* time and date */
  227. lput(rnd(HEADR+textsize, 4096)+datsize);
  228. lput(symsize); /* nsyms */
  229. lput((0x48L<<16)|15L); /* size of optional hdr and flags */
  230. lput((0413<<16)|01L); /* magic and version */
  231. lput(textsize); /* sizes */
  232. lput(datsize);
  233. lput(bsssize);
  234. lput(entryvalue()); /* va of entry */
  235. lput(INITTEXT); /* va of base of text */
  236. lput(INITDAT); /* va of base of data */
  237. lput(INITDAT); /* address of TOC */
  238. lput((1L<<16)|1); /* sn(entry) | sn(text) */
  239. lput((2L<<16)|1); /* sn(data) | sn(toc) */
  240. lput((0L<<16)|3); /* sn(loader) | sn(bss) */
  241. lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */
  242. lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */
  243. lput(0); /* max stack allowed */
  244. lput(0); /* max data allowed */
  245. lput(0); lput(0); lput(0); /* reserved */
  246. strnput(".text", 8); /* text segment */
  247. lput(INITTEXT); /* address */
  248. lput(INITTEXT);
  249. lput(textsize);
  250. lput(HEADR);
  251. lput(0L);
  252. lput(HEADR+textsize+datsize+symsize);
  253. lput(lcsize); /* line number size */
  254. lput(0x20L); /* flags */
  255. strnput(".data", 8); /* data segment */
  256. lput(INITDAT); /* address */
  257. lput(INITDAT);
  258. lput(datsize);
  259. lput(rnd(HEADR+textsize, 4096)); /* sizes */
  260. lput(0L);
  261. lput(0L);
  262. lput(0L);
  263. lput(0x40L); /* flags */
  264. strnput(".bss", 8); /* bss segment */
  265. lput(INITDAT+datsize); /* address */
  266. lput(INITDAT+datsize);
  267. lput(bsssize);
  268. lput(0L);
  269. lput(0L);
  270. lput(0L);
  271. lput(0L);
  272. lput(0x80L); /* flags */
  273. break;
  274. case 5:
  275. strnput("\177ELF", 4); /* e_ident */
  276. CPUT(1); /* class = 32 bit */
  277. CPUT(2); /* data = MSB */
  278. CPUT(1); /* version = CURRENT */
  279. strnput("", 9);
  280. lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */
  281. lput(1L); /* version = CURRENT */
  282. lput(entryvalue() & ~KMASK); /* entry vaddr */
  283. lput(52L); /* offset to first phdr */
  284. lput(0L); /* offset to first shdr */
  285. lput(0L); /* flags = PPC */
  286. lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/
  287. lput((3L<<16)|0L); /* # Phdrs & Shdr size */
  288. lput((0L<<16)|0L); /* # Shdrs & shdr string size */
  289. lput(1L); /* text - type = PT_LOAD */
  290. lput(HEADR); /* file offset */
  291. lput(INITTEXT & ~KMASK); /* vaddr */
  292. lput(INITTEXT); /* paddr */
  293. lput(textsize); /* file size */
  294. lput(textsize); /* memory size */
  295. lput(0x05L); /* protections = RX */
  296. lput(0x10000L); /* alignment code?? */
  297. lput(1L); /* data - type = PT_LOAD */
  298. lput(HEADR+textsize); /* file offset */
  299. lput(INITDAT & ~KMASK); /* vaddr */
  300. lput(INITDAT); /* paddr */
  301. lput(datsize); /* file size */
  302. lput(datsize); /* memory size */
  303. lput(0x07L); /* protections = RWX */
  304. lput(0x10000L); /* alignment code?? */
  305. lput(0L); /* data - type = PT_NULL */
  306. lput(HEADR+textsize+datsize); /* file offset */
  307. lput(0L);
  308. lput(0L);
  309. lput(symsize); /* symbol table size */
  310. lput(lcsize); /* line number size */
  311. lput(0x04L); /* protections = R */
  312. lput(0x04L); /* alignment code?? */
  313. break;
  314. }
  315. cflush();
  316. }
  317. void
  318. strnput(char *s, int n)
  319. {
  320. for(; *s; s++){
  321. CPUT(*s);
  322. n--;
  323. }
  324. for(; n > 0; n--)
  325. CPUT(0);
  326. }
  327. void
  328. cput(long l)
  329. {
  330. CPUT(l);
  331. }
  332. void
  333. wput(long l)
  334. {
  335. cbp[0] = l>>8;
  336. cbp[1] = l;
  337. cbp += 2;
  338. cbc -= 2;
  339. if(cbc <= 0)
  340. cflush();
  341. }
  342. void
  343. lput(long l)
  344. {
  345. LPUT(l);
  346. }
  347. void
  348. cflush(void)
  349. {
  350. int n;
  351. n = sizeof(buf.cbuf) - cbc;
  352. if(n)
  353. write(cout, buf.cbuf, n);
  354. cbp = buf.cbuf;
  355. cbc = sizeof(buf.cbuf);
  356. }
  357. void
  358. asmsym(void)
  359. {
  360. Prog *p;
  361. Auto *a;
  362. Sym *s;
  363. int h;
  364. s = lookup("etext", 0);
  365. if(s->type == STEXT)
  366. putsymb(s->name, 'T', s->value, s->version);
  367. for(h=0; h<NHASH; h++)
  368. for(s=hash[h]; s!=S; s=s->link)
  369. switch(s->type) {
  370. case SCONST:
  371. putsymb(s->name, 'D', s->value, s->version);
  372. continue;
  373. case SDATA:
  374. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  375. continue;
  376. case SBSS:
  377. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  378. continue;
  379. case SFILE:
  380. putsymb(s->name, 'f', s->value, s->version);
  381. continue;
  382. }
  383. for(p=textp; p!=P; p=p->cond) {
  384. s = p->from.sym;
  385. if(s->type != STEXT && s->type != SLEAF)
  386. continue;
  387. /* filenames first */
  388. for(a=p->to.autom; a; a=a->link)
  389. if(a->type == D_FILE)
  390. putsymb(a->sym->name, 'z', a->aoffset, 0);
  391. else
  392. if(a->type == D_FILE1)
  393. putsymb(a->sym->name, 'Z', a->aoffset, 0);
  394. if(s->type == STEXT)
  395. putsymb(s->name, 'T', s->value, s->version);
  396. else
  397. putsymb(s->name, 'L', s->value, s->version);
  398. /* frame, auto and param after */
  399. putsymb(".frame", 'm', p->to.offset+4, 0);
  400. for(a=p->to.autom; a; a=a->link)
  401. if(a->type == D_AUTO)
  402. putsymb(a->sym->name, 'a', -a->aoffset, 0);
  403. else
  404. if(a->type == D_PARAM)
  405. putsymb(a->sym->name, 'p', a->aoffset, 0);
  406. }
  407. if(debug['v'] || debug['n'])
  408. Bprint(&bso, "symsize = %lud\n", symsize);
  409. Bflush(&bso);
  410. }
  411. void
  412. putsymb(char *s, int t, long v, int ver)
  413. {
  414. int i, f;
  415. if(t == 'f')
  416. s++;
  417. LPUT(v);
  418. if(ver)
  419. t += 'a' - 'A';
  420. CPUT(t+0x80); /* 0x80 is variable length */
  421. if(t == 'Z' || t == 'z') {
  422. CPUT(s[0]);
  423. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  424. CPUT(s[i]);
  425. CPUT(s[i+1]);
  426. }
  427. CPUT(0);
  428. CPUT(0);
  429. i++;
  430. }
  431. else {
  432. for(i=0; s[i]; i++)
  433. CPUT(s[i]);
  434. CPUT(0);
  435. }
  436. symsize += 4 + 1 + i + 1;
  437. if(debug['n']) {
  438. if(t == 'z' || t == 'Z') {
  439. Bprint(&bso, "%c %.8lux ", t, v);
  440. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  441. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  442. Bprint(&bso, "/%x", f);
  443. }
  444. Bprint(&bso, "\n");
  445. return;
  446. }
  447. if(ver)
  448. Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
  449. else
  450. Bprint(&bso, "%c %.8lux %s\n", t, v, s);
  451. }
  452. }
  453. #define MINLC 4
  454. void
  455. asmlc(void)
  456. {
  457. long oldpc, oldlc;
  458. Prog *p;
  459. long v, s;
  460. oldpc = INITTEXT;
  461. oldlc = 0;
  462. for(p = firstp; p != P; p = p->link) {
  463. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  464. if(p->as == ATEXT)
  465. curtext = p;
  466. if(debug['L'])
  467. Bprint(&bso, "%6lux %P\n",
  468. p->pc, p);
  469. continue;
  470. }
  471. if(debug['L'])
  472. Bprint(&bso, "\t\t%6ld", lcsize);
  473. v = (p->pc - oldpc) / MINLC;
  474. while(v) {
  475. s = 127;
  476. if(v < 127)
  477. s = v;
  478. CPUT(s+128); /* 129-255 +pc */
  479. if(debug['L'])
  480. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  481. v -= s;
  482. lcsize++;
  483. }
  484. s = p->line - oldlc;
  485. oldlc = p->line;
  486. oldpc = p->pc + MINLC;
  487. if(s > 64 || s < -64) {
  488. CPUT(0); /* 0 vv +lc */
  489. CPUT(s>>24);
  490. CPUT(s>>16);
  491. CPUT(s>>8);
  492. CPUT(s);
  493. if(debug['L']) {
  494. if(s > 0)
  495. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  496. s, 0, s);
  497. else
  498. Bprint(&bso, " lc%ld(%d,%ld)\n",
  499. s, 0, s);
  500. Bprint(&bso, "%6lux %P\n",
  501. p->pc, p);
  502. }
  503. lcsize += 5;
  504. continue;
  505. }
  506. if(s > 0) {
  507. CPUT(0+s); /* 1-64 +lc */
  508. if(debug['L']) {
  509. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  510. Bprint(&bso, "%6lux %P\n",
  511. p->pc, p);
  512. }
  513. } else {
  514. CPUT(64-s); /* 65-128 -lc */
  515. if(debug['L']) {
  516. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  517. Bprint(&bso, "%6lux %P\n",
  518. p->pc, p);
  519. }
  520. }
  521. lcsize++;
  522. }
  523. while(lcsize & 1) {
  524. s = 129;
  525. CPUT(s);
  526. lcsize++;
  527. }
  528. if(debug['v'] || debug['L'])
  529. Bprint(&bso, "lcsize = %ld\n", lcsize);
  530. Bflush(&bso);
  531. }
  532. void
  533. datblk(long s, long n)
  534. {
  535. Prog *p;
  536. char *cast;
  537. long l, fl, j, d;
  538. int i, c;
  539. memset(buf.dbuf, 0, n+100);
  540. for(p = datap; p != P; p = p->link) {
  541. curp = p;
  542. l = p->from.sym->value + p->from.offset - s;
  543. c = p->reg;
  544. i = 0;
  545. if(l < 0) {
  546. if(l+c <= 0)
  547. continue;
  548. while(l < 0) {
  549. l++;
  550. i++;
  551. }
  552. }
  553. if(l >= n)
  554. continue;
  555. if(p->as != AINIT && p->as != ADYNT) {
  556. for(j=l+(c-i)-1; j>=l; j--)
  557. if(buf.dbuf[j]) {
  558. print("%P\n", p);
  559. diag("multiple initialization");
  560. break;
  561. }
  562. }
  563. switch(p->to.type) {
  564. default:
  565. diag("unknown mode in initialization\n%P", p);
  566. break;
  567. case D_FCONST:
  568. switch(c) {
  569. default:
  570. case 4:
  571. fl = ieeedtof(&p->to.ieee);
  572. cast = (char*)&fl;
  573. for(; i<c; i++) {
  574. buf.dbuf[l] = cast[fnuxi8[i+4]];
  575. l++;
  576. }
  577. break;
  578. case 8:
  579. cast = (char*)&p->to.ieee;
  580. for(; i<c; i++) {
  581. buf.dbuf[l] = cast[fnuxi8[i]];
  582. l++;
  583. }
  584. break;
  585. }
  586. break;
  587. case D_SCONST:
  588. for(; i<c; i++) {
  589. buf.dbuf[l] = p->to.sval[i];
  590. l++;
  591. }
  592. break;
  593. case D_CONST:
  594. d = p->to.offset;
  595. if(p->to.sym) {
  596. if(p->to.sym->type == SUNDEF){
  597. ckoff(p->to.sym, d);
  598. d += p->to.sym->value;
  599. }
  600. if(p->to.sym->type == STEXT ||
  601. p->to.sym->type == SLEAF)
  602. d += p->to.sym->value;
  603. if(p->to.sym->type == SDATA)
  604. d += p->to.sym->value + INITDAT;
  605. if(p->to.sym->type == SBSS)
  606. d += p->to.sym->value + INITDAT;
  607. if(dlm)
  608. dynreloc(p->to.sym, l+s+INITDAT, 1, 0, 0);
  609. }
  610. cast = (char*)&d;
  611. switch(c) {
  612. default:
  613. diag("bad nuxi %d %d\n%P", c, i, curp);
  614. break;
  615. case 1:
  616. for(; i<c; i++) {
  617. buf.dbuf[l] = cast[inuxi1[i]];
  618. l++;
  619. }
  620. break;
  621. case 2:
  622. for(; i<c; i++) {
  623. buf.dbuf[l] = cast[inuxi2[i]];
  624. l++;
  625. }
  626. break;
  627. case 4:
  628. for(; i<c; i++) {
  629. buf.dbuf[l] = cast[inuxi4[i]];
  630. l++;
  631. }
  632. break;
  633. }
  634. break;
  635. }
  636. }
  637. write(cout, buf.dbuf, n);
  638. }