span.c 12 KB

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