span.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "l.h"
  10. void
  11. pagebug(Prog *p)
  12. {
  13. Prog *q;
  14. switch(p->as) {
  15. case ABGEZAL:
  16. case ABLTZAL:
  17. case AJAL:
  18. case ABEQ:
  19. case ABGEZ:
  20. case ABGTZ:
  21. case ABLEZ:
  22. case ABLTZ:
  23. case ABNE:
  24. case ABFPT:
  25. case ABFPF:
  26. case AJMP:
  27. q = prg();
  28. *q = *p;
  29. p->link = q;
  30. p->as = ANOR;
  31. p->optab = 0;
  32. p->from = zprg.from;
  33. p->from.type = D_REG;
  34. p->from.reg = REGZERO;
  35. p->to = p->from;
  36. }
  37. }
  38. void
  39. span(void)
  40. {
  41. Prog *p, *q;
  42. Sym *setext, *s;
  43. Optab *o;
  44. int m, bflag, i;
  45. int64_t c, otxt, v;
  46. if(debug['v'])
  47. Bprint(&bso, "%5.2f span\n", cputime());
  48. Bflush(&bso);
  49. bflag = 0;
  50. c = INITTEXT;
  51. otxt = c;
  52. for(p = firstp; p != P; p = p->link) {
  53. /* bug in early 4000 chips delayslot on page boundary */
  54. if((c&(0x1000-1)) == 0xffc)
  55. pagebug(p);
  56. p->pc = c;
  57. o = oplook(p);
  58. m = o->size;
  59. if(m == 0) {
  60. if(p->as == ATEXT) {
  61. curtext = p;
  62. autosize = p->to.offset + 4;
  63. if(p->from.sym != S)
  64. p->from.sym->value = c;
  65. /* need passes to resolve branches */
  66. if(c-otxt >= 1L<<17)
  67. bflag = 1;
  68. otxt = c;
  69. continue;
  70. }
  71. diag("zero-width instruction\n%P", p);
  72. continue;
  73. }
  74. c += m;
  75. }
  76. /*
  77. * if any procedure is large enough to
  78. * generate a large SBRA branch, then
  79. * generate extra passes putting branches
  80. * around jmps to fix. this is rare.
  81. */
  82. while(bflag) {
  83. if(debug['v'])
  84. Bprint(&bso, "%5.2f span1\n", cputime());
  85. bflag = 0;
  86. c = INITTEXT;
  87. for(p = firstp; p != P; p = p->link) {
  88. /* bug in early 4000 chips delayslot on page boundary */
  89. if((c&(0x1000-1)) == 0xffc)
  90. pagebug(p);
  91. p->pc = c;
  92. o = oplook(p);
  93. if(o->type == 6 && p->cond) {
  94. otxt = p->cond->pc - c;
  95. if(otxt < 0)
  96. otxt = -otxt;
  97. if(otxt >= (1L<<17) - 10) {
  98. q = prg();
  99. q->link = p->link;
  100. p->link = q;
  101. q->as = AJMP;
  102. q->to.type = D_BRANCH;
  103. q->cond = p->cond;
  104. p->cond = q;
  105. q = prg();
  106. q->link = p->link;
  107. p->link = q;
  108. q->as = AJMP;
  109. q->to.type = D_BRANCH;
  110. q->cond = q->link->link;
  111. addnop(p->link);
  112. addnop(p);
  113. bflag = 1;
  114. }
  115. }
  116. m = o->size;
  117. if(m == 0) {
  118. if(p->as == ATEXT) {
  119. curtext = p;
  120. autosize = p->to.offset + 4;
  121. if(p->from.sym != S)
  122. p->from.sym->value = c;
  123. continue;
  124. }
  125. diag("zero-width instruction\n%P", p);
  126. continue;
  127. }
  128. c += m;
  129. }
  130. }
  131. if(debug['t']) {
  132. /*
  133. * add strings to text segment
  134. */
  135. c = rnd(c, 8);
  136. for(i=0; i<NHASH; i++)
  137. for(s = hash[i]; s != S; s = s->link) {
  138. if(s->type != SSTRING)
  139. continue;
  140. v = s->value;
  141. while(v & 3)
  142. v++;
  143. s->value = c;
  144. c += v;
  145. }
  146. }
  147. c = rnd(c, 8);
  148. setext = lookup("etext", 0);
  149. if(setext != S) {
  150. setext->value = c;
  151. textsize = c - INITTEXT;
  152. }
  153. if(INITRND)
  154. INITDAT = rnd(c, INITRND);
  155. if(debug['v'])
  156. Bprint(&bso, "tsize = %llux\n", textsize);
  157. Bflush(&bso);
  158. }
  159. void
  160. xdefine(char *p, int t, int32_t v)
  161. {
  162. Sym *s;
  163. s = lookup(p, 0);
  164. if(s->type == 0 || s->type == SXREF) {
  165. s->type = t;
  166. s->value = v;
  167. }
  168. }
  169. int32_t
  170. regoff(Adr *a)
  171. {
  172. instoffset = 0;
  173. aclass(a);
  174. return instoffset;
  175. }
  176. aclass(Adr *a)
  177. {
  178. Sym *s;
  179. int t;
  180. switch(a->type) {
  181. case D_NONE:
  182. return C_NONE;
  183. case D_REG:
  184. return C_REG;
  185. case D_FREG:
  186. return C_FREG;
  187. case D_FCREG:
  188. return C_FCREG;
  189. case D_MREG:
  190. return C_MREG;
  191. case D_OREG:
  192. switch(a->name) {
  193. case D_EXTERN:
  194. case D_STATIC:
  195. if(a->sym == 0 || a->sym->name == 0) {
  196. print("null sym external\n");
  197. print("%D\n", a);
  198. return C_GOK;
  199. }
  200. t = a->sym->type;
  201. if(t == 0 || t == SXREF) {
  202. diag("undefined external: %s in %s",
  203. a->sym->name, TNAME);
  204. a->sym->type = SDATA;
  205. }
  206. instoffset = a->sym->value + a->offset - BIG;
  207. if(instoffset >= -BIG && instoffset < BIG)
  208. return C_SEXT;
  209. return C_LEXT;
  210. case D_AUTO:
  211. instoffset = autosize + a->offset;
  212. if(instoffset >= -BIG && instoffset < BIG)
  213. return C_SAUTO;
  214. return C_LAUTO;
  215. case D_PARAM:
  216. instoffset = autosize + a->offset + 4L;
  217. if(instoffset >= -BIG && instoffset < BIG)
  218. return C_SAUTO;
  219. return C_LAUTO;
  220. case D_NONE:
  221. instoffset = a->offset;
  222. if(instoffset == 0)
  223. return C_ZOREG;
  224. if(instoffset >= -BIG && instoffset < BIG)
  225. return C_SOREG;
  226. return C_LOREG;
  227. }
  228. return C_GOK;
  229. case D_HI:
  230. return C_LO;
  231. case D_LO:
  232. return C_HI;
  233. case D_OCONST:
  234. switch(a->name) {
  235. case D_EXTERN:
  236. case D_STATIC:
  237. s = a->sym;
  238. t = s->type;
  239. if(t == 0 || t == SXREF) {
  240. diag("undefined external: %s in %s",
  241. s->name, TNAME);
  242. s->type = SDATA;
  243. }
  244. instoffset = s->value + a->offset + INITDAT;
  245. if(s->type == STEXT || s->type == SLEAF)
  246. instoffset = s->value + a->offset;
  247. return C_LCON;
  248. }
  249. return C_GOK;
  250. case D_CONST:
  251. switch(a->name) {
  252. case D_NONE:
  253. instoffset = a->offset;
  254. consize:
  255. if(instoffset > 0) {
  256. if(instoffset <= 0x7fff)
  257. return C_SCON;
  258. if(instoffset <= 0xffff)
  259. return C_ANDCON;
  260. if((instoffset & 0xffff) == 0)
  261. return C_UCON;
  262. return C_LCON;
  263. }
  264. if(instoffset == 0)
  265. return C_ZCON;
  266. if(instoffset >= -0x8000)
  267. return C_ADDCON;
  268. if((instoffset & 0xffff) == 0)
  269. return C_UCON;
  270. return C_LCON;
  271. case D_EXTERN:
  272. case D_STATIC:
  273. s = a->sym;
  274. if(s == S)
  275. break;
  276. t = s->type;
  277. switch(t) {
  278. case 0:
  279. case SXREF:
  280. diag("undefined external: %s in %s",
  281. s->name, TNAME);
  282. s->type = SDATA;
  283. break;
  284. case SCONST:
  285. instoffset = s->value + a->offset;
  286. goto consize;
  287. case STEXT:
  288. case SLEAF:
  289. case SSTRING:
  290. instoffset = s->value + a->offset;
  291. return C_LCON;
  292. }
  293. instoffset = s->value + a->offset - BIG;
  294. if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
  295. return C_SECON;
  296. instoffset = s->value + a->offset + INITDAT;
  297. return C_LCON;
  298. case D_AUTO:
  299. instoffset = autosize + a->offset;
  300. if(instoffset >= -BIG && instoffset < BIG)
  301. return C_SACON;
  302. return C_LACON;
  303. case D_PARAM:
  304. instoffset = autosize + a->offset + 4L;
  305. if(instoffset >= -BIG && instoffset < BIG)
  306. return C_SACON;
  307. return C_LACON;
  308. }
  309. return C_GOK;
  310. case D_BRANCH:
  311. return C_SBRA;
  312. }
  313. return C_GOK;
  314. }
  315. Optab*
  316. oplook(Prog *p)
  317. {
  318. int a1, a2, a3, r;
  319. char *c1, *c3;
  320. Optab *o, *e;
  321. a1 = p->optab;
  322. if(a1)
  323. return optab+(a1-1);
  324. a1 = p->from.class;
  325. if(a1 == 0) {
  326. a1 = aclass(&p->from) + 1;
  327. p->from.class = a1;
  328. }
  329. a1--;
  330. a3 = p->to.class;
  331. if(a3 == 0) {
  332. a3 = aclass(&p->to) + 1;
  333. p->to.class = a3;
  334. }
  335. a3--;
  336. a2 = C_NONE;
  337. if(p->reg != NREG)
  338. a2 = C_REG;
  339. r = p->as;
  340. o = oprange[r].start;
  341. if(o == 0) {
  342. a1 = opcross[repop[r]][a1][a2][a3];
  343. if(a1) {
  344. p->optab = a1+1;
  345. return optab+a1;
  346. }
  347. o = oprange[r].stop; /* just generate an error */
  348. }
  349. e = oprange[r].stop;
  350. c1 = xcmp[a1];
  351. c3 = xcmp[a3];
  352. for(; o<e; o++)
  353. if(o->a2 == a2)
  354. if(c1[o->a1])
  355. if(c3[o->a3]) {
  356. p->optab = (o-optab)+1;
  357. return o;
  358. }
  359. diag("illegal combination %A %d %d %d",
  360. p->as, a1, a2, a3);
  361. if(!debug['a'])
  362. prasm(p);
  363. o = optab;
  364. p->optab = (o-optab)+1;
  365. return o;
  366. }
  367. int
  368. cmp(int a, int b)
  369. {
  370. if(a == b)
  371. return 1;
  372. switch(a) {
  373. case C_LCON:
  374. if(b == C_ZCON || b == C_SCON || b == C_UCON ||
  375. b == C_ADDCON || b == C_ANDCON)
  376. return 1;
  377. break;
  378. case C_ADD0CON:
  379. if(b == C_ADDCON)
  380. return 1;
  381. case C_ADDCON:
  382. if(b == C_ZCON || b == C_SCON)
  383. return 1;
  384. break;
  385. case C_AND0CON:
  386. if(b == C_ANDCON)
  387. return 1;
  388. case C_ANDCON:
  389. if(b == C_ZCON || b == C_SCON)
  390. return 1;
  391. break;
  392. case C_UCON:
  393. if(b == C_ZCON)
  394. return 1;
  395. break;
  396. case C_SCON:
  397. if(b == C_ZCON)
  398. return 1;
  399. break;
  400. case C_LACON:
  401. if(b == C_SACON)
  402. return 1;
  403. break;
  404. case C_LBRA:
  405. if(b == C_SBRA)
  406. return 1;
  407. break;
  408. case C_LEXT:
  409. if(b == C_SEXT)
  410. return 1;
  411. break;
  412. case C_LAUTO:
  413. if(b == C_SAUTO)
  414. return 1;
  415. break;
  416. case C_REG:
  417. if(b == C_ZCON)
  418. return 1;
  419. break;
  420. case C_LOREG:
  421. if(b == C_ZOREG || b == C_SOREG)
  422. return 1;
  423. break;
  424. case C_SOREG:
  425. if(b == C_ZOREG)
  426. return 1;
  427. break;
  428. }
  429. return 0;
  430. }
  431. int
  432. ocmp(const void *a1, const void *a2)
  433. {
  434. Optab *p1, *p2;
  435. int n;
  436. p1 = (Optab*)a1;
  437. p2 = (Optab*)a2;
  438. n = p1->as - p2->as;
  439. if(n)
  440. return n;
  441. n = p1->a1 - p2->a1;
  442. if(n)
  443. return n;
  444. n = p1->a2 - p2->a2;
  445. if(n)
  446. return n;
  447. n = p1->a3 - p2->a3;
  448. if(n)
  449. return n;
  450. return 0;
  451. }
  452. void
  453. buildop(void)
  454. {
  455. int i, n, r;
  456. for(i=0; i<32; i++)
  457. for(n=0; n<32; n++)
  458. xcmp[i][n] = cmp(n, i);
  459. for(n=0; optab[n].as != AXXX; n++)
  460. ;
  461. qsort(optab, n, sizeof(optab[0]), ocmp);
  462. for(i=0; i<n; i++) {
  463. r = optab[i].as;
  464. oprange[r].start = optab+i;
  465. while(optab[i].as == r)
  466. i++;
  467. oprange[r].stop = optab+i;
  468. i--;
  469. switch(r)
  470. {
  471. default:
  472. diag("unknown op in build: %A", r);
  473. errorexit();
  474. case AABSF:
  475. oprange[AMOVFD] = oprange[r];
  476. oprange[AMOVDF] = oprange[r];
  477. oprange[AMOVWF] = oprange[r];
  478. oprange[AMOVFW] = oprange[r];
  479. oprange[AMOVWD] = oprange[r];
  480. oprange[AMOVDW] = oprange[r];
  481. oprange[ANEGF] = oprange[r];
  482. oprange[ANEGD] = oprange[r];
  483. oprange[AABSD] = oprange[r];
  484. break;
  485. case AADD:
  486. buildrep(1, AADD);
  487. oprange[ASGT] = oprange[r];
  488. repop[ASGT] = 1;
  489. oprange[ASGTU] = oprange[r];
  490. repop[ASGTU] = 1;
  491. oprange[AADDU] = oprange[r];
  492. repop[AADDU] = 1;
  493. oprange[AADDVU] = oprange[r];
  494. repop[AADDVU] = 1;
  495. break;
  496. case AADDF:
  497. oprange[ADIVF] = oprange[r];
  498. oprange[ADIVD] = oprange[r];
  499. oprange[AMULF] = oprange[r];
  500. oprange[AMULD] = oprange[r];
  501. oprange[ASUBF] = oprange[r];
  502. oprange[ASUBD] = oprange[r];
  503. oprange[AADDD] = oprange[r];
  504. break;
  505. case AAND:
  506. buildrep(2, AAND);
  507. oprange[AXOR] = oprange[r];
  508. repop[AXOR] = 2;
  509. oprange[AOR] = oprange[r];
  510. repop[AOR] = 2;
  511. break;
  512. case ABEQ:
  513. oprange[ABNE] = oprange[r];
  514. break;
  515. case ABLEZ:
  516. oprange[ABGEZ] = oprange[r];
  517. oprange[ABGEZAL] = oprange[r];
  518. oprange[ABLTZ] = oprange[r];
  519. oprange[ABLTZAL] = oprange[r];
  520. oprange[ABGTZ] = oprange[r];
  521. break;
  522. case AMOVB:
  523. buildrep(3, AMOVB);
  524. oprange[AMOVH] = oprange[r];
  525. repop[AMOVH] = 3;
  526. break;
  527. case AMOVBU:
  528. buildrep(4, AMOVBU);
  529. oprange[AMOVHU] = oprange[r];
  530. repop[AMOVHU] = 4;
  531. break;
  532. case AMUL:
  533. oprange[AREM] = oprange[r];
  534. oprange[AREMU] = oprange[r];
  535. oprange[ADIVU] = oprange[r];
  536. oprange[AMULU] = oprange[r];
  537. oprange[ADIV] = oprange[r];
  538. oprange[ADIVVU] = oprange[r];
  539. oprange[ADIVV] = oprange[r];
  540. break;
  541. case ASLL:
  542. oprange[ASRL] = oprange[r];
  543. oprange[ASRA] = oprange[r];
  544. oprange[ASLLV] = oprange[r];
  545. oprange[ASRAV] = oprange[r];
  546. oprange[ASRLV] = oprange[r];
  547. break;
  548. case ASUB:
  549. oprange[ASUBU] = oprange[r];
  550. oprange[ANOR] = oprange[r];
  551. break;
  552. case ASYSCALL:
  553. oprange[ATLBP] = oprange[r];
  554. oprange[ATLBR] = oprange[r];
  555. oprange[ATLBWI] = oprange[r];
  556. oprange[ATLBWR] = oprange[r];
  557. break;
  558. case ACMPEQF:
  559. oprange[ACMPGTF] = oprange[r];
  560. oprange[ACMPGTD] = oprange[r];
  561. oprange[ACMPGEF] = oprange[r];
  562. oprange[ACMPGED] = oprange[r];
  563. oprange[ACMPEQD] = oprange[r];
  564. break;
  565. case ABFPT:
  566. oprange[ABFPF] = oprange[r];
  567. break;
  568. case AMOVWL:
  569. oprange[AMOVWR] = oprange[r];
  570. oprange[AMOVVR] = oprange[r];
  571. oprange[AMOVVL] = oprange[r];
  572. break;
  573. case AMOVW:
  574. buildrep(5, AMOVW);
  575. break;
  576. case AMOVD:
  577. buildrep(6, AMOVD);
  578. break;
  579. case AMOVF:
  580. buildrep(7, AMOVF);
  581. break;
  582. case AMOVV:
  583. buildrep(8, AMOVV);
  584. break;
  585. case ABREAK:
  586. case AWORD:
  587. case ARFE:
  588. case AJAL:
  589. case AJMP:
  590. case ATEXT:
  591. case ACASE:
  592. case ABCASE:
  593. break;
  594. }
  595. }
  596. }
  597. void
  598. buildrep(int x, int as)
  599. {
  600. Opcross *p;
  601. Optab *e, *s, *o;
  602. int a1, a2, a3, n;
  603. if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
  604. diag("assumptions fail in buildrep");
  605. errorexit();
  606. }
  607. repop[as] = x;
  608. p = (opcross + x);
  609. s = oprange[as].start;
  610. e = oprange[as].stop;
  611. for(o=e-1; o>=s; o--) {
  612. n = o-optab;
  613. for(a2=0; a2<2; a2++) {
  614. if(a2) {
  615. if(o->a2 == C_NONE)
  616. continue;
  617. } else
  618. if(o->a2 != C_NONE)
  619. continue;
  620. for(a1=0; a1<32; a1++) {
  621. if(!xcmp[a1][o->a1])
  622. continue;
  623. for(a3=0; a3<32; a3++)
  624. if(xcmp[a3][o->a3])
  625. (*p)[a1][a2][a3] = n;
  626. }
  627. }
  628. }
  629. oprange[as].start = 0;
  630. }