span.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. #include "l.h"
  2. static struct {
  3. ulong start;
  4. ulong size;
  5. } pool;
  6. void checkpool(Prog*);
  7. void flushpool(Prog*, int);
  8. void
  9. span(void)
  10. {
  11. Prog *p;
  12. Sym *setext, *s;
  13. Optab *o;
  14. int m, bflag, i;
  15. long c, otxt, v;
  16. if(debug['v'])
  17. Bprint(&bso, "%5.2f span\n", cputime());
  18. Bflush(&bso);
  19. bflag = 0;
  20. c = INITTEXT;
  21. otxt = c;
  22. for(p = firstp; p != P; p = p->link) {
  23. p->pc = c;
  24. o = oplook(p);
  25. m = o->size;
  26. if(m == 0) {
  27. if(p->as == ATEXT) {
  28. curtext = p;
  29. autosize = p->to.offset + 4;
  30. if(p->from.sym != S)
  31. p->from.sym->value = c;
  32. /* need passes to resolve branches */
  33. if(c-otxt >= 1L<<17)
  34. bflag = 1;
  35. otxt = c;
  36. continue;
  37. }
  38. diag("zero-width instruction\n%P", p);
  39. continue;
  40. }
  41. switch(o->flag & (LFROM|LTO|LPOOL)) {
  42. case LFROM:
  43. addpool(p, &p->from);
  44. break;
  45. case LTO:
  46. addpool(p, &p->to);
  47. break;
  48. case LPOOL:
  49. if ((p->scond&C_SCOND) == 14)
  50. flushpool(p, 0);
  51. break;
  52. }
  53. if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14)
  54. flushpool(p, 0);
  55. c += m;
  56. if(blitrl)
  57. checkpool(p);
  58. }
  59. /*
  60. * if any procedure is large enough to
  61. * generate a large SBRA branch, then
  62. * generate extra passes putting branches
  63. * around jmps to fix. this is rare.
  64. */
  65. while(bflag) {
  66. if(debug['v'])
  67. Bprint(&bso, "%5.2f span1\n", cputime());
  68. bflag = 0;
  69. c = INITTEXT;
  70. for(p = firstp; p != P; p = p->link) {
  71. p->pc = c;
  72. o = oplook(p);
  73. /* very larg branches
  74. if(o->type == 6 && p->cond) {
  75. otxt = p->cond->pc - c;
  76. if(otxt < 0)
  77. otxt = -otxt;
  78. if(otxt >= (1L<<17) - 10) {
  79. q = prg();
  80. q->link = p->link;
  81. p->link = q;
  82. q->as = AB;
  83. q->to.type = D_BRANCH;
  84. q->cond = p->cond;
  85. p->cond = q;
  86. q = prg();
  87. q->link = p->link;
  88. p->link = q;
  89. q->as = AB;
  90. q->to.type = D_BRANCH;
  91. q->cond = q->link->link;
  92. bflag = 1;
  93. }
  94. }
  95. */
  96. m = o->size;
  97. if(m == 0) {
  98. if(p->as == ATEXT) {
  99. curtext = p;
  100. autosize = p->to.offset + 4;
  101. if(p->from.sym != S)
  102. p->from.sym->value = c;
  103. continue;
  104. }
  105. diag("zero-width instruction\n%P", p);
  106. continue;
  107. }
  108. c += m;
  109. }
  110. }
  111. if(debug['t']) {
  112. /*
  113. * add strings to text segment
  114. */
  115. c = rnd(c, 8);
  116. for(i=0; i<NHASH; i++)
  117. for(s = hash[i]; s != S; s = s->link) {
  118. if(s->type != SSTRING)
  119. continue;
  120. v = s->value;
  121. while(v & 3)
  122. v++;
  123. s->value = c;
  124. c += v;
  125. }
  126. }
  127. c = rnd(c, 8);
  128. setext = lookup("etext", 0);
  129. if(setext != S) {
  130. setext->value = c;
  131. textsize = c - INITTEXT;
  132. }
  133. if(INITRND)
  134. INITDAT = rnd(c, INITRND);
  135. if(debug['v'])
  136. Bprint(&bso, "tsize = %lux\n", textsize);
  137. Bflush(&bso);
  138. }
  139. /*
  140. * when the first reference to the literal pool threatens
  141. * to go out of range of a 12-bit PC-relative offset,
  142. * drop the pool now, and branch round it.
  143. * this happens only in extended basic blocks that exceed 4k.
  144. */
  145. void
  146. checkpool(Prog *p)
  147. {
  148. if(pool.size >= 0xffc || immaddr((p->pc+4)+4+pool.size - pool.start+8) == 0)
  149. flushpool(p, 1);
  150. else if(p->link == P)
  151. flushpool(p, 2);
  152. }
  153. void
  154. flushpool(Prog *p, int skip)
  155. {
  156. Prog *q;
  157. if(blitrl) {
  158. if(skip){
  159. if(debug['v'] && skip == 1)
  160. print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);
  161. q = prg();
  162. q->as = AB;
  163. q->to.type = D_BRANCH;
  164. q->cond = p->link;
  165. q->link = blitrl;
  166. blitrl = q;
  167. }
  168. else if(p->pc+pool.size-pool.start < 2048)
  169. return;
  170. elitrl->link = p->link;
  171. p->link = blitrl;
  172. blitrl = 0; /* BUG: should refer back to values until out-of-range */
  173. elitrl = 0;
  174. pool.size = 0;
  175. pool.start = 0;
  176. }
  177. }
  178. void
  179. addpool(Prog *p, Adr *a)
  180. {
  181. Prog *q, t;
  182. int c;
  183. c = aclass(a);
  184. t = zprg;
  185. t.as = AWORD;
  186. switch(c) {
  187. default:
  188. t.to = *a;
  189. break;
  190. case C_SROREG:
  191. case C_LOREG:
  192. case C_ROREG:
  193. case C_FOREG:
  194. case C_SOREG:
  195. case C_FAUTO:
  196. case C_SAUTO:
  197. case C_LAUTO:
  198. case C_LACON:
  199. t.to.type = D_CONST;
  200. t.to.offset = instoffset;
  201. break;
  202. }
  203. for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */
  204. if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
  205. p->cond = q;
  206. return;
  207. }
  208. q = prg();
  209. *q = t;
  210. q->pc = pool.size;
  211. if(blitrl == P) {
  212. blitrl = q;
  213. pool.start = p->pc;
  214. } else
  215. elitrl->link = q;
  216. elitrl = q;
  217. pool.size += 4;
  218. p->cond = q;
  219. }
  220. void
  221. xdefine(char *p, int t, long v)
  222. {
  223. Sym *s;
  224. s = lookup(p, 0);
  225. if(s->type == 0 || s->type == SXREF) {
  226. s->type = t;
  227. s->value = v;
  228. }
  229. }
  230. long
  231. regoff(Adr *a)
  232. {
  233. instoffset = 0;
  234. aclass(a);
  235. return instoffset;
  236. }
  237. long
  238. immrot(ulong v)
  239. {
  240. int i;
  241. for(i=0; i<16; i++) {
  242. if((v & ~0xff) == 0)
  243. return (i<<8) | v | (1<<25);
  244. v = (v<<2) | (v>>30);
  245. }
  246. return 0;
  247. }
  248. long
  249. immaddr(long v)
  250. {
  251. if(v >= 0 && v <= 0xfff)
  252. return (v & 0xfff) |
  253. (1<<24) | /* pre indexing */
  254. (1<<23); /* pre indexing, up */
  255. if(v >= -0xfff && v < 0)
  256. return (-v & 0xfff) |
  257. (1<<24); /* pre indexing */
  258. return 0;
  259. }
  260. int
  261. immfloat(long v)
  262. {
  263. return (v & 0xC03) == 0; /* offset will fit in floating-point load/store */
  264. }
  265. int
  266. immhalf(long v)
  267. {
  268. if(v >= 0 && v <= 0xff)
  269. return v|
  270. (1<<24)| /* pre indexing */
  271. (1<<23); /* pre indexing, up */
  272. if(v >= -0xff && v < 0)
  273. return (-v & 0xff)|
  274. (1<<24); /* pre indexing */
  275. return 0;
  276. }
  277. int
  278. aclass(Adr *a)
  279. {
  280. Sym *s;
  281. int t;
  282. switch(a->type) {
  283. case D_NONE:
  284. return C_NONE;
  285. case D_REG:
  286. return C_REG;
  287. case D_REGREG:
  288. return C_REGREG;
  289. case D_SHIFT:
  290. return C_SHIFT;
  291. case D_FREG:
  292. return C_FREG;
  293. case D_FPCR:
  294. return C_FCR;
  295. case D_OREG:
  296. switch(a->name) {
  297. case D_EXTERN:
  298. case D_STATIC:
  299. if(a->sym == 0 || a->sym->name == 0) {
  300. print("null sym external\n");
  301. print("%D\n", a);
  302. return C_GOK;
  303. }
  304. s = a->sym;
  305. t = s->type;
  306. if(t == 0 || t == SXREF) {
  307. diag("undefined external: %s in %s",
  308. s->name, TNAME);
  309. s->type = SDATA;
  310. }
  311. if(dlm) {
  312. switch(t) {
  313. default:
  314. instoffset = s->value + a->offset + INITDAT;
  315. break;
  316. case SUNDEF:
  317. case STEXT:
  318. case SCONST:
  319. case SLEAF:
  320. case SSTRING:
  321. instoffset = s->value + a->offset;
  322. break;
  323. }
  324. return C_ADDR;
  325. }
  326. instoffset = s->value + a->offset - BIG;
  327. t = immaddr(instoffset);
  328. if(t) {
  329. if(immhalf(instoffset))
  330. return immfloat(t) ? C_HFEXT : C_HEXT;
  331. if(immfloat(t))
  332. return C_FEXT;
  333. return C_SEXT;
  334. }
  335. return C_LEXT;
  336. case D_AUTO:
  337. instoffset = autosize + a->offset;
  338. t = immaddr(instoffset);
  339. if(t){
  340. if(immhalf(instoffset))
  341. return immfloat(t) ? C_HFAUTO : C_HAUTO;
  342. if(immfloat(t))
  343. return C_FAUTO;
  344. return C_SAUTO;
  345. }
  346. return C_LAUTO;
  347. case D_PARAM:
  348. instoffset = autosize + a->offset + 4L;
  349. t = immaddr(instoffset);
  350. if(t){
  351. if(immhalf(instoffset))
  352. return immfloat(t) ? C_HFAUTO : C_HAUTO;
  353. if(immfloat(t))
  354. return C_FAUTO;
  355. return C_SAUTO;
  356. }
  357. return C_LAUTO;
  358. case D_NONE:
  359. instoffset = a->offset;
  360. t = immaddr(instoffset);
  361. if(t) {
  362. if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */
  363. return immfloat(t) ? C_HFOREG : C_HOREG;
  364. if(immfloat(t))
  365. return C_FOREG; /* n.b. that it will also satisfy immrot */
  366. t = immrot(instoffset);
  367. if(t)
  368. return C_SROREG;
  369. if(immhalf(instoffset))
  370. return C_HOREG;
  371. return C_SOREG;
  372. }
  373. t = immrot(instoffset);
  374. if(t)
  375. return C_ROREG;
  376. return C_LOREG;
  377. }
  378. return C_GOK;
  379. case D_PSR:
  380. return C_PSR;
  381. case D_OCONST:
  382. switch(a->name) {
  383. case D_EXTERN:
  384. case D_STATIC:
  385. s = a->sym;
  386. t = s->type;
  387. if(t == 0 || t == SXREF) {
  388. diag("undefined external: %s in %s",
  389. s->name, TNAME);
  390. s->type = SDATA;
  391. }
  392. instoffset = s->value + a->offset + INITDAT;
  393. if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)
  394. instoffset = s->value + a->offset;
  395. return C_LCON;
  396. }
  397. return C_GOK;
  398. case D_FCONST:
  399. return C_FCON;
  400. case D_CONST:
  401. switch(a->name) {
  402. case D_NONE:
  403. instoffset = a->offset;
  404. if(a->reg != NREG)
  405. goto aconsize;
  406. t = immrot(instoffset);
  407. if(t)
  408. return C_RCON;
  409. t = immrot(~instoffset);
  410. if(t)
  411. return C_NCON;
  412. return C_LCON;
  413. case D_EXTERN:
  414. case D_STATIC:
  415. s = a->sym;
  416. if(s == S)
  417. break;
  418. t = s->type;
  419. switch(t) {
  420. case 0:
  421. case SXREF:
  422. diag("undefined external: %s in %s",
  423. s->name, TNAME);
  424. s->type = SDATA;
  425. break;
  426. case SUNDEF:
  427. case STEXT:
  428. case SSTRING:
  429. case SCONST:
  430. case SLEAF:
  431. instoffset = s->value + a->offset;
  432. return C_LCON;
  433. }
  434. if(!dlm) {
  435. instoffset = s->value + a->offset - BIG;
  436. t = immrot(instoffset);
  437. if(t && instoffset != 0)
  438. return C_RECON;
  439. }
  440. instoffset = s->value + a->offset + INITDAT;
  441. return C_LCON;
  442. case D_AUTO:
  443. instoffset = autosize + a->offset;
  444. goto aconsize;
  445. case D_PARAM:
  446. instoffset = autosize + a->offset + 4L;
  447. aconsize:
  448. t = immrot(instoffset);
  449. if(t)
  450. return C_RACON;
  451. return C_LACON;
  452. }
  453. return C_GOK;
  454. case D_BRANCH:
  455. return C_SBRA;
  456. }
  457. return C_GOK;
  458. }
  459. Optab*
  460. oplook(Prog *p)
  461. {
  462. int a1, a2, a3, r;
  463. char *c1, *c3;
  464. Optab *o, *e;
  465. a1 = p->optab;
  466. if(a1)
  467. return optab+(a1-1);
  468. a1 = p->from.class;
  469. if(a1 == 0) {
  470. a1 = aclass(&p->from) + 1;
  471. p->from.class = a1;
  472. }
  473. a1--;
  474. a3 = p->to.class;
  475. if(a3 == 0) {
  476. a3 = aclass(&p->to) + 1;
  477. p->to.class = a3;
  478. }
  479. a3--;
  480. a2 = C_NONE;
  481. if(p->reg != NREG)
  482. a2 = C_REG;
  483. r = p->as;
  484. o = oprange[r].start;
  485. if(o == 0) {
  486. a1 = opcross[repop[r]][a1][a2][a3];
  487. if(a1) {
  488. p->optab = a1+1;
  489. return optab+a1;
  490. }
  491. o = oprange[r].stop; /* just generate an error */
  492. }
  493. if(0) {
  494. print("oplook %A %d %d %d\n",
  495. (int)p->as, a1, a2, a3);
  496. print(" %d %d\n", p->from.type, p->to.type);
  497. }
  498. e = oprange[r].stop;
  499. c1 = xcmp[a1];
  500. c3 = xcmp[a3];
  501. for(; o<e; o++)
  502. if(o->a2 == a2)
  503. if(c1[o->a1])
  504. if(c3[o->a3]) {
  505. p->optab = (o-optab)+1;
  506. return o;
  507. }
  508. diag("illegal combination %A %d %d %d",
  509. p->as, a1, a2, a3);
  510. prasm(p);
  511. if(o == 0)
  512. o = optab;
  513. return o;
  514. }
  515. int
  516. cmp(int a, int b)
  517. {
  518. if(a == b)
  519. return 1;
  520. switch(a) {
  521. case C_LCON:
  522. if(b == C_RCON || b == C_NCON)
  523. return 1;
  524. break;
  525. case C_LACON:
  526. if(b == C_RACON)
  527. return 1;
  528. break;
  529. case C_LECON:
  530. if(b == C_RECON)
  531. return 1;
  532. break;
  533. case C_HFEXT:
  534. return b == C_HEXT || b == C_FEXT;
  535. case C_FEXT:
  536. case C_HEXT:
  537. return b == C_HFEXT;
  538. case C_SEXT:
  539. return cmp(C_HFEXT, b);
  540. case C_LEXT:
  541. return cmp(C_SEXT, b);
  542. case C_HFAUTO:
  543. return b == C_HAUTO || b == C_FAUTO;
  544. case C_FAUTO:
  545. case C_HAUTO:
  546. return b == C_HFAUTO;
  547. case C_SAUTO:
  548. return cmp(C_HFAUTO, b);
  549. case C_LAUTO:
  550. return cmp(C_SAUTO, b);
  551. case C_HFOREG:
  552. return b == C_HOREG || b == C_FOREG;
  553. case C_FOREG:
  554. case C_HOREG:
  555. return b == C_HFOREG;
  556. case C_SROREG:
  557. return cmp(C_SOREG, b) || cmp(C_ROREG, b);
  558. case C_SOREG:
  559. case C_ROREG:
  560. return b == C_SROREG || cmp(C_HFOREG, b);
  561. case C_LOREG:
  562. return cmp(C_SROREG, b);
  563. case C_LBRA:
  564. if(b == C_SBRA)
  565. return 1;
  566. break;
  567. }
  568. return 0;
  569. }
  570. int
  571. ocmp(const void *a1, const void *a2)
  572. {
  573. Optab *p1, *p2;
  574. int n;
  575. p1 = (Optab*)a1;
  576. p2 = (Optab*)a2;
  577. n = p1->as - p2->as;
  578. if(n)
  579. return n;
  580. n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */
  581. if(n)
  582. return n;
  583. n = (p2->flag&VFP) - (p1->flag&VFP); /* floating point arch */
  584. if(n)
  585. return n;
  586. n = p1->a1 - p2->a1;
  587. if(n)
  588. return n;
  589. n = p1->a2 - p2->a2;
  590. if(n)
  591. return n;
  592. n = p1->a3 - p2->a3;
  593. if(n)
  594. return n;
  595. return 0;
  596. }
  597. void
  598. buildop(void)
  599. {
  600. int i, n, r;
  601. armv4 = !debug['h'];
  602. vfp = debug['f'];
  603. for(i=0; i<C_GOK; i++)
  604. for(n=0; n<C_GOK; n++)
  605. xcmp[i][n] = cmp(n, i);
  606. for(n=0; optab[n].as != AXXX; n++) {
  607. if((optab[n].flag & VFP) && !vfp)
  608. optab[n].as = AXXX;
  609. if((optab[n].flag & V4) && !armv4) {
  610. optab[n].as = AXXX;
  611. break;
  612. }
  613. }
  614. qsort(optab, n, sizeof(optab[0]), ocmp);
  615. for(i=0; i<n; i++) {
  616. r = optab[i].as;
  617. oprange[r].start = optab+i;
  618. while(optab[i].as == r)
  619. i++;
  620. oprange[r].stop = optab+i;
  621. i--;
  622. switch(r)
  623. {
  624. default:
  625. diag("unknown op in build: %A", r);
  626. errorexit();
  627. case AXXX:
  628. break;
  629. case AADD:
  630. oprange[AAND] = oprange[r];
  631. oprange[AEOR] = oprange[r];
  632. oprange[ASUB] = oprange[r];
  633. oprange[ARSB] = oprange[r];
  634. oprange[AADC] = oprange[r];
  635. oprange[ASBC] = oprange[r];
  636. oprange[ARSC] = oprange[r];
  637. oprange[AORR] = oprange[r];
  638. oprange[ABIC] = oprange[r];
  639. break;
  640. case ACMP:
  641. oprange[ATST] = oprange[r];
  642. oprange[ATEQ] = oprange[r];
  643. oprange[ACMN] = oprange[r];
  644. break;
  645. case AMVN:
  646. break;
  647. case ABEQ:
  648. oprange[ABNE] = oprange[r];
  649. oprange[ABCS] = oprange[r];
  650. oprange[ABHS] = oprange[r];
  651. oprange[ABCC] = oprange[r];
  652. oprange[ABLO] = oprange[r];
  653. oprange[ABMI] = oprange[r];
  654. oprange[ABPL] = oprange[r];
  655. oprange[ABVS] = oprange[r];
  656. oprange[ABVC] = oprange[r];
  657. oprange[ABHI] = oprange[r];
  658. oprange[ABLS] = oprange[r];
  659. oprange[ABGE] = oprange[r];
  660. oprange[ABLT] = oprange[r];
  661. oprange[ABGT] = oprange[r];
  662. oprange[ABLE] = oprange[r];
  663. break;
  664. case ASLL:
  665. oprange[ASRL] = oprange[r];
  666. oprange[ASRA] = oprange[r];
  667. break;
  668. case AMUL:
  669. oprange[AMULU] = oprange[r];
  670. break;
  671. case ADIV:
  672. oprange[AMOD] = oprange[r];
  673. oprange[AMODU] = oprange[r];
  674. oprange[ADIVU] = oprange[r];
  675. break;
  676. case AMOVW:
  677. case AMOVB:
  678. case AMOVBU:
  679. case AMOVH:
  680. case AMOVHU:
  681. break;
  682. case ASWPW:
  683. oprange[ASWPBU] = oprange[r];
  684. break;
  685. case AB:
  686. case ABL:
  687. case ABX:
  688. case ABXRET:
  689. case ASWI:
  690. case AWORD:
  691. case AMOVM:
  692. case ARFE:
  693. case ATEXT:
  694. case ACASE:
  695. case ABCASE:
  696. break;
  697. case AADDF:
  698. oprange[AADDD] = oprange[r];
  699. oprange[ASUBF] = oprange[r];
  700. oprange[ASUBD] = oprange[r];
  701. oprange[AMULF] = oprange[r];
  702. oprange[AMULD] = oprange[r];
  703. oprange[ADIVF] = oprange[r];
  704. oprange[ADIVD] = oprange[r];
  705. oprange[AMOVFD] = oprange[r];
  706. oprange[AMOVDF] = oprange[r];
  707. break;
  708. case ACMPF:
  709. oprange[ACMPD] = oprange[r];
  710. break;
  711. case AMOVF:
  712. oprange[AMOVD] = oprange[r];
  713. break;
  714. case AMOVFW:
  715. oprange[AMOVWF] = oprange[r];
  716. oprange[AMOVWD] = oprange[r];
  717. oprange[AMOVDW] = oprange[r];
  718. break;
  719. case AMULL:
  720. oprange[AMULA] = oprange[r];
  721. oprange[AMULAL] = oprange[r];
  722. oprange[AMULLU] = oprange[r];
  723. oprange[AMULALU] = oprange[r];
  724. break;
  725. }
  726. }
  727. }
  728. /*
  729. void
  730. buildrep(int x, int as)
  731. {
  732. Opcross *p;
  733. Optab *e, *s, *o;
  734. int a1, a2, a3, n;
  735. if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
  736. diag("assumptions fail in buildrep");
  737. errorexit();
  738. }
  739. repop[as] = x;
  740. p = (opcross + x);
  741. s = oprange[as].start;
  742. e = oprange[as].stop;
  743. for(o=e-1; o>=s; o--) {
  744. n = o-optab;
  745. for(a2=0; a2<2; a2++) {
  746. if(a2) {
  747. if(o->a2 == C_NONE)
  748. continue;
  749. } else
  750. if(o->a2 != C_NONE)
  751. continue;
  752. for(a1=0; a1<32; a1++) {
  753. if(!xcmp[a1][o->a1])
  754. continue;
  755. for(a3=0; a3<32; a3++)
  756. if(xcmp[a3][o->a3])
  757. (*p)[a1][a2][a3] = n;
  758. }
  759. }
  760. }
  761. oprange[as].start = 0;
  762. }
  763. */
  764. enum{
  765. ABSD = 0,
  766. ABSU = 1,
  767. RELD = 2,
  768. RELU = 3,
  769. };
  770. int modemap[4] = { 0, 1, -1, 2, };
  771. typedef struct Reloc Reloc;
  772. struct Reloc
  773. {
  774. int n;
  775. int t;
  776. uchar *m;
  777. ulong *a;
  778. };
  779. Reloc rels;
  780. static void
  781. grow(Reloc *r)
  782. {
  783. int t;
  784. uchar *m, *nm;
  785. ulong *a, *na;
  786. t = r->t;
  787. r->t += 64;
  788. m = r->m;
  789. a = r->a;
  790. r->m = nm = malloc(r->t*sizeof(uchar));
  791. r->a = na = malloc(r->t*sizeof(ulong));
  792. memmove(nm, m, t*sizeof(uchar));
  793. memmove(na, a, t*sizeof(ulong));
  794. free(m);
  795. free(a);
  796. }
  797. void
  798. dynreloc(Sym *s, long v, int abs)
  799. {
  800. int i, k, n;
  801. uchar *m;
  802. ulong *a;
  803. Reloc *r;
  804. if(v&3)
  805. diag("bad relocation address");
  806. v >>= 2;
  807. if(s != S && s->type == SUNDEF)
  808. k = abs ? ABSU : RELU;
  809. else
  810. k = abs ? ABSD : RELD;
  811. /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
  812. k = modemap[k];
  813. r = &rels;
  814. n = r->n;
  815. if(n >= r->t)
  816. grow(r);
  817. m = r->m;
  818. a = r->a;
  819. for(i = n; i > 0; i--){
  820. if(v < a[i-1]){ /* happens occasionally for data */
  821. m[i] = m[i-1];
  822. a[i] = a[i-1];
  823. }
  824. else
  825. break;
  826. }
  827. m[i] = k;
  828. a[i] = v;
  829. r->n++;
  830. }
  831. static int
  832. sput(char *s)
  833. {
  834. char *p;
  835. p = s;
  836. while(*s)
  837. cput(*s++);
  838. cput(0);
  839. return s-p+1;
  840. }
  841. void
  842. asmdyn()
  843. {
  844. int i, n, t, c;
  845. Sym *s;
  846. ulong la, ra, *a;
  847. vlong off;
  848. uchar *m;
  849. Reloc *r;
  850. cflush();
  851. off = seek(cout, 0, 1);
  852. lput(0);
  853. t = 0;
  854. lput(imports);
  855. t += 4;
  856. for(i = 0; i < NHASH; i++)
  857. for(s = hash[i]; s != S; s = s->link)
  858. if(s->type == SUNDEF){
  859. lput(s->sig);
  860. t += 4;
  861. t += sput(s->name);
  862. }
  863. la = 0;
  864. r = &rels;
  865. n = r->n;
  866. m = r->m;
  867. a = r->a;
  868. lput(n);
  869. t += 4;
  870. for(i = 0; i < n; i++){
  871. ra = *a-la;
  872. if(*a < la)
  873. diag("bad relocation order");
  874. if(ra < 256)
  875. c = 0;
  876. else if(ra < 65536)
  877. c = 1;
  878. else
  879. c = 2;
  880. cput((c<<6)|*m++);
  881. t++;
  882. if(c == 0){
  883. cput(ra);
  884. t++;
  885. }
  886. else if(c == 1){
  887. wput(ra);
  888. t += 2;
  889. }
  890. else{
  891. lput(ra);
  892. t += 4;
  893. }
  894. la = *a++;
  895. }
  896. cflush();
  897. seek(cout, off, 0);
  898. lput(t);
  899. if(debug['v']){
  900. Bprint(&bso, "import table entries = %d\n", imports);
  901. Bprint(&bso, "export table entries = %d\n", exports);
  902. }
  903. }