span.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  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\n", 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\n", 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\n",
  308. s->name, TNAME);
  309. s->type = SDATA;
  310. }
  311. if(reloc) {
  312. switch(t) {
  313. default:
  314. instoffset = s->value + a->offset + INITDAT;
  315. break;
  316. case STEXT:
  317. if(s->value == -1)
  318. undefsym(s);
  319. case SCONST:
  320. case SLEAF:
  321. case SSTRING:
  322. instoffset = s->value + a->offset;
  323. break;
  324. }
  325. return C_ADDR;
  326. }
  327. instoffset = s->value + a->offset - BIG;
  328. t = immaddr(instoffset);
  329. if(t) {
  330. if(immhalf(instoffset))
  331. return immfloat(t) ? C_HFEXT : C_HEXT;
  332. if(immfloat(t))
  333. return C_FEXT;
  334. return C_SEXT;
  335. }
  336. return C_LEXT;
  337. case D_AUTO:
  338. instoffset = autosize + a->offset;
  339. t = immaddr(instoffset);
  340. if(t){
  341. if(immhalf(instoffset))
  342. return immfloat(t) ? C_HFAUTO : C_HAUTO;
  343. if(immfloat(t))
  344. return C_FAUTO;
  345. return C_SAUTO;
  346. }
  347. return C_LAUTO;
  348. case D_PARAM:
  349. instoffset = autosize + a->offset + 4L;
  350. t = immaddr(instoffset);
  351. if(t){
  352. if(immhalf(instoffset))
  353. return immfloat(t) ? C_HFAUTO : C_HAUTO;
  354. if(immfloat(t))
  355. return C_FAUTO;
  356. return C_SAUTO;
  357. }
  358. return C_LAUTO;
  359. case D_NONE:
  360. instoffset = a->offset;
  361. t = immaddr(instoffset);
  362. if(t) {
  363. if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */
  364. return immfloat(t) ? C_HFOREG : C_HOREG;
  365. if(immfloat(t))
  366. return C_FOREG; /* n.b. that it will also satisfy immrot */
  367. t = immrot(instoffset);
  368. if(t)
  369. return C_SROREG;
  370. if(immhalf(instoffset))
  371. return C_HOREG;
  372. return C_SOREG;
  373. }
  374. t = immrot(instoffset);
  375. if(t)
  376. return C_ROREG;
  377. return C_LOREG;
  378. }
  379. return C_GOK;
  380. case D_PSR:
  381. return C_PSR;
  382. case D_OCONST:
  383. switch(a->name) {
  384. case D_EXTERN:
  385. case D_STATIC:
  386. s = a->sym;
  387. t = s->type;
  388. if(t == 0 || t == SXREF) {
  389. diag("undefined external: %s in %s\n",
  390. s->name, TNAME);
  391. s->type = SDATA;
  392. }
  393. instoffset = s->value + a->offset + INITDAT;
  394. if(s->type == STEXT || s->type == SLEAF) {
  395. if(s->value == -1)
  396. undefsym(s);
  397. instoffset = s->value + a->offset;
  398. }
  399. return C_LCON;
  400. }
  401. return C_GOK;
  402. case D_FCONST:
  403. return C_FCON;
  404. case D_CONST:
  405. switch(a->name) {
  406. case D_NONE:
  407. instoffset = a->offset;
  408. if(a->reg != NREG)
  409. goto aconsize;
  410. t = immrot(instoffset);
  411. if(t)
  412. return C_RCON;
  413. t = immrot(~instoffset);
  414. if(t)
  415. return C_NCON;
  416. return C_LCON;
  417. case D_EXTERN:
  418. case D_STATIC:
  419. s = a->sym;
  420. if(s == S)
  421. break;
  422. t = s->type;
  423. switch(t) {
  424. case 0:
  425. case SXREF:
  426. diag("undefined external: %s in %s\n",
  427. s->name, TNAME);
  428. s->type = SDATA;
  429. break;
  430. case STEXT:
  431. if(s->value == -1)
  432. undefsym(s);
  433. case SSTRING:
  434. case SCONST:
  435. case SLEAF:
  436. instoffset = s->value + a->offset;
  437. return C_LCON;
  438. }
  439. if(!reloc) {
  440. instoffset = s->value + a->offset - BIG;
  441. t = immrot(instoffset);
  442. if(t && instoffset != 0)
  443. return C_RECON;
  444. }
  445. instoffset = s->value + a->offset + INITDAT;
  446. return C_LCON;
  447. case D_AUTO:
  448. instoffset = autosize + a->offset;
  449. goto aconsize;
  450. case D_PARAM:
  451. instoffset = autosize + a->offset + 4L;
  452. aconsize:
  453. t = immrot(instoffset);
  454. if(t)
  455. return C_RACON;
  456. return C_LACON;
  457. }
  458. return C_GOK;
  459. case D_BRANCH:
  460. return C_SBRA;
  461. }
  462. return C_GOK;
  463. }
  464. Optab*
  465. oplook(Prog *p)
  466. {
  467. int a1, a2, a3, r;
  468. char *c1, *c3;
  469. Optab *o, *e;
  470. a1 = p->optab;
  471. if(a1)
  472. return optab+(a1-1);
  473. a1 = p->from.class;
  474. if(a1 == 0) {
  475. a1 = aclass(&p->from) + 1;
  476. p->from.class = a1;
  477. }
  478. a1--;
  479. a3 = p->to.class;
  480. if(a3 == 0) {
  481. a3 = aclass(&p->to) + 1;
  482. p->to.class = a3;
  483. }
  484. a3--;
  485. a2 = C_NONE;
  486. if(p->reg != NREG)
  487. a2 = C_REG;
  488. r = p->as;
  489. o = oprange[r].start;
  490. if(o == 0) {
  491. a1 = opcross[repop[r]][a1][a2][a3];
  492. if(a1) {
  493. p->optab = a1+1;
  494. return optab+a1;
  495. }
  496. o = oprange[r].stop; /* just generate an error */
  497. }
  498. if(0) {
  499. print("oplook %A %d %d %d\n",
  500. (int)p->as, a1, a2, a3);
  501. print(" %d %d\n", p->from.type, p->to.type);
  502. }
  503. e = oprange[r].stop;
  504. c1 = xcmp[a1];
  505. c3 = xcmp[a3];
  506. for(; o<e; o++)
  507. if(o->a2 == a2)
  508. if(c1[o->a1])
  509. if(c3[o->a3]) {
  510. p->optab = (o-optab)+1;
  511. return o;
  512. }
  513. diag("illegal combination %A %d %d %d\n",
  514. p->as, a1, a2, a3);
  515. prasm(p);
  516. if(o == 0)
  517. o = optab;
  518. return o;
  519. }
  520. int
  521. cmp(int a, int b)
  522. {
  523. if(a == b)
  524. return 1;
  525. switch(a) {
  526. case C_LCON:
  527. if(b == C_RCON || b == C_NCON)
  528. return 1;
  529. break;
  530. case C_LACON:
  531. if(b == C_RACON)
  532. return 1;
  533. break;
  534. case C_LECON:
  535. if(b == C_RECON)
  536. return 1;
  537. break;
  538. case C_HFEXT:
  539. return b == C_HEXT || b == C_FEXT;
  540. case C_FEXT:
  541. case C_HEXT:
  542. return b == C_HFEXT;
  543. case C_SEXT:
  544. return cmp(C_HFEXT, b);
  545. case C_LEXT:
  546. return cmp(C_SEXT, b);
  547. case C_HFAUTO:
  548. return b == C_HAUTO || b == C_FAUTO;
  549. case C_FAUTO:
  550. case C_HAUTO:
  551. return b == C_HFAUTO;
  552. case C_SAUTO:
  553. return cmp(C_HFAUTO, b);
  554. case C_LAUTO:
  555. return cmp(C_SAUTO, b);
  556. case C_HFOREG:
  557. return b == C_HOREG || b == C_FOREG;
  558. case C_FOREG:
  559. case C_HOREG:
  560. return b == C_HFOREG;
  561. case C_SROREG:
  562. return cmp(C_SOREG, b) || cmp(C_ROREG, b);
  563. case C_SOREG:
  564. case C_ROREG:
  565. return b == C_SROREG || cmp(C_HFOREG, b);
  566. case C_LOREG:
  567. return cmp(C_SROREG, b);
  568. case C_LBRA:
  569. if(b == C_SBRA)
  570. return 1;
  571. break;
  572. }
  573. return 0;
  574. }
  575. int
  576. ocmp(const void *a1, const void *a2)
  577. {
  578. Optab *p1, *p2;
  579. int n;
  580. p1 = (Optab*)a1;
  581. p2 = (Optab*)a2;
  582. n = p1->as - p2->as;
  583. if(n)
  584. return n;
  585. n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */
  586. if(n)
  587. return n;
  588. n = p1->a1 - p2->a1;
  589. if(n)
  590. return n;
  591. n = p1->a2 - p2->a2;
  592. if(n)
  593. return n;
  594. n = p1->a3 - p2->a3;
  595. if(n)
  596. return n;
  597. return 0;
  598. }
  599. void
  600. buildop(void)
  601. {
  602. int i, n, r;
  603. armv4 = !debug['h'];
  604. for(i=0; i<C_GOK; i++)
  605. for(n=0; n<C_GOK; n++)
  606. xcmp[i][n] = cmp(n, i);
  607. for(n=0; optab[n].as != AXXX; n++)
  608. if((optab[n].flag & V4) && !armv4) {
  609. optab[n].as = AXXX;
  610. break;
  611. }
  612. qsort(optab, n, sizeof(optab[0]), ocmp);
  613. for(i=0; i<n; i++) {
  614. r = optab[i].as;
  615. oprange[r].start = optab+i;
  616. while(optab[i].as == r)
  617. i++;
  618. oprange[r].stop = optab+i;
  619. i--;
  620. switch(r)
  621. {
  622. default:
  623. diag("unknown op in build: %A\n", r);
  624. errorexit();
  625. case AADD:
  626. oprange[AAND] = oprange[r];
  627. oprange[AEOR] = oprange[r];
  628. oprange[ASUB] = oprange[r];
  629. oprange[ARSB] = oprange[r];
  630. oprange[AADC] = oprange[r];
  631. oprange[ASBC] = oprange[r];
  632. oprange[ARSC] = oprange[r];
  633. oprange[AORR] = oprange[r];
  634. oprange[ABIC] = oprange[r];
  635. break;
  636. case ACMP:
  637. oprange[ATST] = oprange[r];
  638. oprange[ATEQ] = oprange[r];
  639. oprange[ACMN] = oprange[r];
  640. break;
  641. case AMVN:
  642. break;
  643. case ABEQ:
  644. oprange[ABNE] = oprange[r];
  645. oprange[ABCS] = oprange[r];
  646. oprange[ABHS] = oprange[r];
  647. oprange[ABCC] = oprange[r];
  648. oprange[ABLO] = oprange[r];
  649. oprange[ABMI] = oprange[r];
  650. oprange[ABPL] = oprange[r];
  651. oprange[ABVS] = oprange[r];
  652. oprange[ABVC] = oprange[r];
  653. oprange[ABHI] = oprange[r];
  654. oprange[ABLS] = oprange[r];
  655. oprange[ABGE] = oprange[r];
  656. oprange[ABLT] = oprange[r];
  657. oprange[ABGT] = oprange[r];
  658. oprange[ABLE] = oprange[r];
  659. break;
  660. case ASLL:
  661. oprange[ASRL] = oprange[r];
  662. oprange[ASRA] = oprange[r];
  663. break;
  664. case AMUL:
  665. oprange[AMULU] = oprange[r];
  666. break;
  667. case ADIV:
  668. oprange[AMOD] = oprange[r];
  669. oprange[AMODU] = oprange[r];
  670. oprange[ADIVU] = oprange[r];
  671. break;
  672. case AMOVW:
  673. case AMOVB:
  674. case AMOVBU:
  675. case AMOVH:
  676. case AMOVHU:
  677. break;
  678. case ASWPW:
  679. oprange[ASWPBU] = oprange[r];
  680. break;
  681. case AB:
  682. case ABL:
  683. case ASWI:
  684. case AWORD:
  685. case AMOVM:
  686. case ARFE:
  687. case ATEXT:
  688. case ACASE:
  689. case ABCASE:
  690. break;
  691. case AADDF:
  692. oprange[AADDD] = oprange[r];
  693. oprange[ASUBF] = oprange[r];
  694. oprange[ASUBD] = oprange[r];
  695. oprange[AMULF] = oprange[r];
  696. oprange[AMULD] = oprange[r];
  697. oprange[ADIVF] = oprange[r];
  698. oprange[ADIVD] = oprange[r];
  699. oprange[AMOVFD] = oprange[r];
  700. oprange[AMOVDF] = oprange[r];
  701. break;
  702. case ACMPF:
  703. oprange[ACMPD] = oprange[r];
  704. break;
  705. case AMOVF:
  706. oprange[AMOVD] = oprange[r];
  707. break;
  708. case AMOVFW:
  709. oprange[AMOVWF] = oprange[r];
  710. oprange[AMOVWD] = oprange[r];
  711. oprange[AMOVDW] = oprange[r];
  712. break;
  713. case AMULL:
  714. oprange[AMULA] = oprange[r];
  715. oprange[AMULAL] = oprange[r];
  716. oprange[AMULLU] = oprange[r];
  717. oprange[AMULALU] = oprange[r];
  718. break;
  719. }
  720. }
  721. }
  722. /*
  723. void
  724. buildrep(int x, int as)
  725. {
  726. Opcross *p;
  727. Optab *e, *s, *o;
  728. int a1, a2, a3, n;
  729. if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
  730. diag("assumptions fail in buildrep");
  731. errorexit();
  732. }
  733. repop[as] = x;
  734. p = (opcross + x);
  735. s = oprange[as].start;
  736. e = oprange[as].stop;
  737. for(o=e-1; o>=s; o--) {
  738. n = o-optab;
  739. for(a2=0; a2<2; a2++) {
  740. if(a2) {
  741. if(o->a2 == C_NONE)
  742. continue;
  743. } else
  744. if(o->a2 != C_NONE)
  745. continue;
  746. for(a1=0; a1<32; a1++) {
  747. if(!xcmp[a1][o->a1])
  748. continue;
  749. for(a3=0; a3<32; a3++)
  750. if(xcmp[a3][o->a3])
  751. (*p)[a1][a2][a3] = n;
  752. }
  753. }
  754. }
  755. oprange[as].start = 0;
  756. }
  757. */