asm.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. #include "l.h"
  2. #define PADDR(a) ((a) & ~0xfffffffff0000000ull)
  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. vlong
  23. entryvalue(void)
  24. {
  25. char *a;
  26. Sym *s;
  27. a = INITENTRY;
  28. if(*a >= '0' && *a <= '9')
  29. return atolwhex(a);
  30. s = lookup(a, 0);
  31. if(s->type == 0)
  32. return INITTEXT;
  33. if(dlm && s->type == SDATA)
  34. return s->value+INITDAT;
  35. if(s->type != STEXT && s->type != SLEAF)
  36. diag("entry not text: %s", s->name);
  37. return s->value;
  38. }
  39. void
  40. asmb(void)
  41. {
  42. Prog *p;
  43. long t, magic;
  44. Optab *o;
  45. vlong vl;
  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 + 8;
  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 %llux sb %llux",
  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. case 9:
  86. case 10:
  87. seek(cout, HEADR+textsize, 0);
  88. break;
  89. case 3:
  90. seek(cout, rnd(HEADR+textsize, 4), 0);
  91. break;
  92. }
  93. if(dlm){
  94. char buf[8];
  95. write(cout, buf, INITDAT-textsize);
  96. textsize = INITDAT;
  97. }
  98. for(t = 0; t < datsize; t += sizeof(buf)-100) {
  99. if(datsize-t > sizeof(buf)-100)
  100. datblk(t, sizeof(buf)-100);
  101. else
  102. datblk(t, datsize-t);
  103. }
  104. symsize = 0;
  105. lcsize = 0;
  106. if(!debug['s']) {
  107. if(debug['v'])
  108. Bprint(&bso, "%5.2f sym\n", cputime());
  109. Bflush(&bso);
  110. switch(HEADTYPE) {
  111. case 0:
  112. case 1:
  113. case 2:
  114. case 5:
  115. case 9:
  116. case 10:
  117. seek(cout, HEADR+textsize+datsize, 0);
  118. break;
  119. case 3:
  120. seek(cout, rnd(HEADR+textsize, 4)+datsize, 0);
  121. break;
  122. }
  123. if(!debug['s'])
  124. asmsym();
  125. if(debug['v'])
  126. Bprint(&bso, "%5.2f sp\n", cputime());
  127. Bflush(&bso);
  128. if(!debug['s'])
  129. asmlc();
  130. if(dlm)
  131. asmdyn();
  132. if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */
  133. if((symsize+lcsize) & 1)
  134. CPUT(0);
  135. cflush();
  136. }
  137. else if(dlm){
  138. asmdyn();
  139. cflush();
  140. }
  141. seek(cout, 0L, 0);
  142. switch(HEADTYPE) {
  143. case 0:
  144. lput(0x1030107); /* magic and sections */
  145. lput(textsize); /* sizes */
  146. lput(datsize);
  147. lput(bsssize);
  148. lput(symsize); /* nsyms */
  149. lput(entryvalue()); /* va of entry */
  150. lput(0L);
  151. lput(lcsize);
  152. break;
  153. case 1:
  154. if(dlm)
  155. lput(0x80000000 | (4*21*21+7)); /* q.out magic */
  156. else
  157. lput(4*21*21+7); /* q.out magic */
  158. lput(textsize); /* sizes */
  159. lput(datsize);
  160. lput(bsssize);
  161. lput(symsize); /* nsyms */
  162. lput(entryvalue()); /* va of entry */
  163. lput(0L);
  164. lput(lcsize);
  165. break;
  166. case 2: /* plan9 */
  167. magic = 4*27*27+7;
  168. magic |= 0x00008000; /* fat header */
  169. if(dlm)
  170. magic |= 0x80000000; /* dlm */
  171. lput(magic);
  172. lput(textsize); /* sizes */
  173. lput(datsize);
  174. lput(bsssize);
  175. lput(symsize); /* nsyms */
  176. vl = entryvalue();
  177. lput(PADDR(vl)); /* va of entry (real mode on boot) */
  178. lput(0L);
  179. lput(lcsize);
  180. llput(vl); /* va of entry */
  181. break;
  182. case 3:
  183. break;
  184. case 5:
  185. elf32(POWER, ELFDATA2MSB, 0, nil);
  186. break;
  187. case 9: /* ELF64 Header */
  188. case 10: /* A2 weirdness */
  189. elf64(POWER64, ELFDATA2MSB, 0, nil);
  190. break;
  191. }
  192. cflush();
  193. }
  194. void
  195. strnput(char *s, int n)
  196. {
  197. for(; *s; s++){
  198. CPUT(*s);
  199. n--;
  200. }
  201. for(; n > 0; n--)
  202. CPUT(0);
  203. }
  204. void
  205. cput(long l)
  206. {
  207. CPUT(l);
  208. }
  209. void
  210. wput(long l)
  211. {
  212. cbp[0] = l>>8;
  213. cbp[1] = l;
  214. cbp += 2;
  215. cbc -= 2;
  216. if(cbc <= 0)
  217. cflush();
  218. }
  219. void
  220. wputl(long l)
  221. {
  222. cbp[0] = l;
  223. cbp[1] = l>>8;
  224. cbp += 2;
  225. cbc -= 2;
  226. if(cbc <= 0)
  227. cflush();
  228. }
  229. void
  230. lput(long l)
  231. {
  232. cbp[0] = l>>24;
  233. cbp[1] = l>>16;
  234. cbp[2] = l>>8;
  235. cbp[3] = l;
  236. cbp += 4;
  237. cbc -= 4;
  238. if(cbc <= 0)
  239. cflush();
  240. }
  241. void
  242. lputl(long l)
  243. {
  244. cbp[3] = l>>24;
  245. cbp[2] = l>>16;
  246. cbp[1] = l>>8;
  247. cbp[0] = l;
  248. cbp += 4;
  249. cbc -= 4;
  250. if(cbc <= 0)
  251. cflush();
  252. }
  253. void
  254. llput(vlong v)
  255. {
  256. lput(v>>32);
  257. lput(v);
  258. }
  259. void
  260. llputl(vlong v)
  261. {
  262. lputl(v);
  263. lputl(v>>32);
  264. }
  265. void
  266. cflush(void)
  267. {
  268. int n;
  269. n = sizeof(buf.cbuf) - cbc;
  270. if(n)
  271. write(cout, buf.cbuf, n);
  272. cbp = buf.cbuf;
  273. cbc = sizeof(buf.cbuf);
  274. }
  275. void
  276. asmsym(void)
  277. {
  278. Prog *p;
  279. Auto *a;
  280. Sym *s;
  281. int h;
  282. s = lookup("etext", 0);
  283. if(s->type == STEXT)
  284. putsymb(s->name, 'T', s->value, s->version);
  285. for(h=0; h<NHASH; h++)
  286. for(s=hash[h]; s!=S; s=s->link)
  287. switch(s->type) {
  288. case SCONST:
  289. putsymb(s->name, 'D', s->value, s->version);
  290. continue;
  291. case SDATA:
  292. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  293. continue;
  294. case SBSS:
  295. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  296. continue;
  297. case SFILE:
  298. putsymb(s->name, 'f', s->value, s->version);
  299. continue;
  300. }
  301. for(p=textp; p!=P; p=p->cond) {
  302. s = p->from.sym;
  303. if(s->type != STEXT && s->type != SLEAF)
  304. continue;
  305. /* filenames first */
  306. for(a=p->to.autom; a; a=a->link)
  307. if(a->type == D_FILE)
  308. putsymb(a->sym->name, 'z', a->aoffset, 0);
  309. else
  310. if(a->type == D_FILE1)
  311. putsymb(a->sym->name, 'Z', a->aoffset, 0);
  312. if(s->type == STEXT)
  313. putsymb(s->name, 'T', s->value, s->version);
  314. else
  315. putsymb(s->name, 'L', s->value, s->version);
  316. /* frame, auto and param after */
  317. putsymb(".frame", 'm', p->to.offset+8, 0);
  318. for(a=p->to.autom; a; a=a->link)
  319. if(a->type == D_AUTO)
  320. putsymb(a->sym->name, 'a', -a->aoffset, 0);
  321. else
  322. if(a->type == D_PARAM)
  323. putsymb(a->sym->name, 'p', a->aoffset, 0);
  324. }
  325. if(debug['v'] || debug['n'])
  326. Bprint(&bso, "symsize = %lud\n", symsize);
  327. Bflush(&bso);
  328. }
  329. void
  330. putsymb(char *s, int t, vlong v, int ver)
  331. {
  332. int i, f, l;
  333. if(t == 'f')
  334. s++;
  335. l = 4;
  336. switch(HEADTYPE){
  337. default:
  338. break;
  339. case 2:
  340. case 9:
  341. case 10:
  342. lput(v>>32);
  343. l = 8;
  344. break;
  345. }
  346. lput(v);
  347. if(ver)
  348. t += 'a' - 'A';
  349. cput(t+0x80); /* 0x80 is variable length */
  350. if(t == 'Z' || t == 'z') {
  351. cput(s[0]);
  352. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  353. cput(s[i]);
  354. cput(s[i+1]);
  355. }
  356. cput(0);
  357. cput(0);
  358. i++;
  359. }
  360. else {
  361. for(i=0; s[i]; i++)
  362. cput(s[i]);
  363. cput(0);
  364. }
  365. symsize += l + 1 + i + 1;
  366. if(debug['n']) {
  367. if(t == 'z' || t == 'Z') {
  368. Bprint(&bso, "%c %.8llux ", t, v);
  369. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  370. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  371. Bprint(&bso, "/%x", f);
  372. }
  373. Bprint(&bso, "\n");
  374. return;
  375. }
  376. if(ver)
  377. Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
  378. else
  379. Bprint(&bso, "%c %.8llux %s\n", t, v, s);
  380. }
  381. }
  382. #define MINLC 4
  383. void
  384. asmlc(void)
  385. {
  386. vlong oldpc, oldlc;
  387. Prog *p;
  388. long v, s;
  389. oldpc = INITTEXT;
  390. oldlc = 0;
  391. for(p = firstp; p != P; p = p->link) {
  392. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  393. if(p->as == ATEXT)
  394. curtext = p;
  395. if(debug['V'])
  396. Bprint(&bso, "%6llux %P\n",
  397. p->pc, p);
  398. continue;
  399. }
  400. if(debug['V'])
  401. Bprint(&bso, "\t\t%6ld", lcsize);
  402. v = (p->pc - oldpc) / MINLC;
  403. while(v) {
  404. s = 127;
  405. if(v < 127)
  406. s = v;
  407. CPUT(s+128); /* 129-255 +pc */
  408. if(debug['V'])
  409. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  410. v -= s;
  411. lcsize++;
  412. }
  413. s = p->line - oldlc;
  414. oldlc = p->line;
  415. oldpc = p->pc + MINLC;
  416. if(s > 64 || s < -64) {
  417. CPUT(0); /* 0 vv +lc */
  418. CPUT(s>>24);
  419. CPUT(s>>16);
  420. CPUT(s>>8);
  421. CPUT(s);
  422. if(debug['V']) {
  423. if(s > 0)
  424. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  425. s, 0, s);
  426. else
  427. Bprint(&bso, " lc%ld(%d,%ld)\n",
  428. s, 0, s);
  429. Bprint(&bso, "%6llux %P\n",
  430. p->pc, p);
  431. }
  432. lcsize += 5;
  433. continue;
  434. }
  435. if(s > 0) {
  436. CPUT(0+s); /* 1-64 +lc */
  437. if(debug['V']) {
  438. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  439. Bprint(&bso, "%6llux %P\n",
  440. p->pc, p);
  441. }
  442. } else {
  443. CPUT(64-s); /* 65-128 -lc */
  444. if(debug['V']) {
  445. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  446. Bprint(&bso, "%6llux %P\n",
  447. p->pc, p);
  448. }
  449. }
  450. lcsize++;
  451. }
  452. while(lcsize & 1) {
  453. s = 129;
  454. CPUT(s);
  455. lcsize++;
  456. }
  457. if(debug['v'] || debug['V'])
  458. Bprint(&bso, "lcsize = %ld\n", lcsize);
  459. Bflush(&bso);
  460. }
  461. void
  462. datblk(long s, long n)
  463. {
  464. Prog *p;
  465. uchar *cast;
  466. long l, fl, j;
  467. vlong d;
  468. int i, c;
  469. memset(buf.dbuf, 0, n+100);
  470. for(p = datap; p != P; p = p->link) {
  471. curp = p;
  472. l = p->from.sym->value + p->from.offset - s;
  473. c = p->reg;
  474. i = 0;
  475. if(l < 0) {
  476. if(l+c <= 0)
  477. continue;
  478. while(l < 0) {
  479. l++;
  480. i++;
  481. }
  482. }
  483. if(l >= n)
  484. continue;
  485. if(p->as != AINIT && p->as != ADYNT) {
  486. for(j=l+(c-i)-1; j>=l; j--)
  487. if(buf.dbuf[j]) {
  488. print("%P\n", p);
  489. diag("multiple initialization");
  490. break;
  491. }
  492. }
  493. switch(p->to.type) {
  494. default:
  495. diag("unknown mode in initialization\n%P", p);
  496. break;
  497. case D_FCONST:
  498. switch(c) {
  499. default:
  500. case 4:
  501. fl = ieeedtof(&p->to.ieee);
  502. cast = (uchar*)&fl;
  503. for(; i<c; i++) {
  504. buf.dbuf[l] = cast[fnuxi8[i+4]];
  505. l++;
  506. }
  507. break;
  508. case 8:
  509. cast = (uchar*)&p->to.ieee;
  510. for(; i<c; i++) {
  511. buf.dbuf[l] = cast[fnuxi8[i]];
  512. l++;
  513. }
  514. break;
  515. }
  516. break;
  517. case D_SCONST:
  518. for(; i<c; i++) {
  519. buf.dbuf[l] = p->to.sval[i];
  520. l++;
  521. }
  522. break;
  523. case D_DCONST:
  524. case D_CONST:
  525. d = p->to.offset;
  526. if(p->to.sym) {
  527. if(p->to.sym->type == SUNDEF){ /* TO DO: simplify */
  528. ckoff(p->to.sym, d);
  529. d += p->to.sym->value;
  530. }
  531. if(p->to.sym->type == STEXT ||
  532. p->to.sym->type == SLEAF)
  533. d += p->to.sym->value;
  534. if(p->to.sym->type == SDATA)
  535. d += p->to.sym->value + INITDAT;
  536. if(p->to.sym->type == SBSS)
  537. d += p->to.sym->value + INITDAT;
  538. if(dlm)
  539. dynreloc(p->to.sym, l+s+INITDAT, 1, 0, 0);
  540. }
  541. fl = d;
  542. cast = (uchar*)&fl;
  543. switch(c) {
  544. default:
  545. diag("bad nuxi %d %d\n%P", c, i, curp);
  546. break;
  547. case 1:
  548. for(; i<c; i++) {
  549. buf.dbuf[l] = cast[inuxi1[i]];
  550. l++;
  551. }
  552. break;
  553. case 2:
  554. for(; i<c; i++) {
  555. buf.dbuf[l] = cast[inuxi2[i]];
  556. l++;
  557. }
  558. break;
  559. case 4:
  560. for(; i<c; i++) {
  561. buf.dbuf[l] = cast[inuxi4[i]];
  562. l++;
  563. }
  564. break;
  565. case 8:
  566. cast = (uchar*)&d;
  567. for(; i<c; i++) {
  568. buf.dbuf[l] = cast[inuxi8[i]];
  569. l++;
  570. }
  571. break;
  572. }
  573. break;
  574. }
  575. }
  576. write(cout, buf.dbuf, n);
  577. }