#include "l.h" #define BIG ((1<<17)-10) void span(void) { Prog *p; Sym *setext; Optab *o; int m; long c, oc, v; oc = 0; loop: if(debug['v']) Bprint(&bso, "%5.2f span\n", cputime()); Bflush(&bso); c = INITTEXT; for(p = firstp; p != P; p = p->link) { if(oc != 0 && p->to.type == D_BRANCH && p->to.class == C_SBRA+1) { v = 0; if(p->cond != P) if(p->cond->pc > c) v = p->cond->pc - p->pc; /* foreward */ else v = p->cond->pc - c; /* backward */ if(v < -BIG || v > BIG) { p->to.class = C_LBRA+1; p->optab = 0; } } p->pc = c; o = oplook(p); m = o->size; if(m == 0) { if(p->as == ATEXT) { curtext = p; autosize = p->to.offset + 4; if(p->from.sym != S) p->from.sym->value = c; continue; } diag("zero-width instruction\n%P\n", p); continue; } c += m; } c = rnd(c, 8); setext = lookup("etext", 0); if(setext != S) { setext->value = c; textsize = c - INITTEXT; } if(INITRND) INITDAT = rnd(c, INITRND); if(debug['v']) Bprint(&bso, "tsize = %lux\n", textsize); if(oc != c) { oc = c; goto loop; } Bflush(&bso); } void xdefine(char *p, int t, long v) { Sym *s; s = lookup(p, 0); if(s->type == 0 || s->type == SXREF) { s->type = t; s->value = v; } } long regoff(Adr *a) { offset = 0; aclass(a); return offset; } int cclass(void) { long o; o = offset; if(o == 0) return C_ZCON-C_ZCON; if((o & ~0xff) == 0) return C_SCON-C_ZCON; if((o & ~0xff) == ~0xff) return C_MCON-C_ZCON; if((o & ~0xffff) == 0) return C_PCON-C_ZCON; if((o & ~0xffff) == ~0xffff) return C_NCON-C_ZCON; return C_LCON-C_ZCON; } int aclass(Adr *a) { Sym *s; int t; noacache = 0; switch(a->type) { case D_NONE: return C_NONE; case D_REG: return C_REG; case D_OREG: switch(a->name) { case D_EXTERN: case D_STATIC: if(a->sym == 0 || a->sym->name == 0) { print("null sym external\n"); print("%D\n", a); return C_GOK; } t = a->sym->type; if(t == 0 || t == SXREF) { diag("undefined external: %s in %s\n", a->sym->name, TNAME); a->sym->type = SDATA; } offset = a->sym->value + a->offset + INITDAT; noacache = 1; if(offset >= INITDAT && offset <= INITDAT+0xff+0xff) return C_SEXT; if(offset >= 0 && offset <= 0xffff) return C_SEXT; return C_LEXT; case D_AUTO: offset = autosize + a->offset; return C_ZAUTO + cclass(); case D_PARAM: offset = autosize + a->offset + 4L; return C_ZAUTO + cclass(); case D_NONE: offset = a->offset; t = C_ZOREG + cclass(); if(a->reg == NREG) { if(t == C_LOREG) return C_LEXT; /* if(t == C_POREG) return C_SEXT; */ } return t; } return C_GOK; case D_OCONST: switch(a->name) { case D_EXTERN: case D_STATIC: s = a->sym; t = s->type; if(t == 0 || t == SXREF) { diag("undefined external: %s in %s\n", s->name, TNAME); s->type = SDATA; } offset = s->value + a->offset; if(s->type != STEXT && s->type != SLEAF) { noacache = 1; offset += INITDAT; } return C_ZCON + cclass(); } return C_GOK; case D_CONST: switch(a->name) { case D_NONE: offset = a->offset; if(a->reg != NREG) return C_ZACON + cclass(); return C_ZCON + cclass(); case D_EXTERN: case D_STATIC: s = a->sym; if(s == S) break; t = s->type; switch(t) { case 0: case SXREF: diag("undefined external: %s in %s\n", s->name, TNAME); s->type = SDATA; break; case STEXT: case SLEAF: offset = s->value + a->offset; return C_LCON; } offset = s->value + a->offset + INITDAT; noacache = 1; return C_ZCON + cclass(); case D_AUTO: offset = autosize + a->offset; return C_ZACON + cclass(); case D_PARAM: offset = autosize + a->offset + 4L; return C_ZACON + cclass(); } return C_GOK; case D_BRANCH: return C_SBRA; } return C_GOK; } Optab* oplook(Prog *p) { int a1, a2, a3, r, noopcache; char *c1, *c3; Optab *o, *e; a1 = p->optab; if(a1) return optab+(a1-1); noopcache = 0; a1 = p->from.class; if(a1 == 0) { a1 = aclass(&p->from) + 1; if(!noacache) p->from.class = a1; else noopcache = 1; } a1--; a3 = p->to.class; if(a3 == 0) { a3 = aclass(&p->to) + 1; if(!noacache) p->to.class = a3; else noopcache = 1; } a3--; a2 = C_NONE; if(p->reg != NREG) a2 = C_REG; r = p->as; o = oprange[r].start; if(o == 0) { r = opcross[repop[r]][a1][a2][a3]; if(r) { if(!noopcache) p->optab = r; return optab+r-1; } diag("no combination %A %d %d %d\n%P\n", p->as, a1, a2, a3, p); return optab + opcross[repop[AMOVL]][C_REG][C_NONE][C_REG] - 1; } e = oprange[r].stop; c1 = xcmp[a1]; c3 = xcmp[a3]; for(; oa2 == a2) if(c1[o->a1]) if(c3[o->a3]) { if(!noopcache) p->optab = (o-optab)+1; return o; } diag("illegal combination %A %d %d %d\n%P\n", p->as, a1, a2, a3, p); return o; } int cmp(int a, int b) { if(a == b) return 1; switch(a) { case C_LCON: if(b == C_ZCON || b == C_SCON || b == C_MCON || b == C_PCON || b == C_NCON) return 1; break; case C_PCON: if(b == C_ZCON || b == C_SCON) return 1; break; case C_SCON: if(b == C_ZCON) return 1; break; case C_NCON: if(b == C_MCON) return 1; break; case C_LACON: if(b == C_ZACON || b == C_SACON || b == C_MACON || b == C_PACON || b == C_NACON) return 1; break; case C_PACON: if(b == C_ZACON || b == C_SACON) return 1; break; case C_SACON: if(b == C_ZACON) return 1; break; case C_NACON: if(b == C_MACON) return 1; break; case C_LBRA: if(b == C_SBRA) return 1; break; case C_LAUTO: if(b == C_ZAUTO || b == C_SAUTO || b == C_MAUTO || b == C_PAUTO || b == C_NAUTO) return 1; break; case C_PAUTO: if(b == C_ZAUTO || b == C_SAUTO) return 1; break; case C_SAUTO: if(b == C_ZAUTO) return 1; break; case C_NAUTO: if(b == C_MAUTO) return 1; break; case C_LOREG: if(b == C_ZOREG || b == C_SOREG || b == C_MOREG || b == C_POREG || b == C_NOREG) return 1; break; case C_POREG: if(b == C_ZOREG || b == C_SOREG) return 1; break; case C_SOREG: if(b == C_ZOREG) return 1; break; case C_NOREG: if(b == C_MOREG) return 1; break; case C_LEXT: if(b == C_SEXT) return 1; break; } return 0; } int ocmp(void *a1, void *a2) { Optab *p1, *p2; int n; p1 = a1; p2 = a2; n = p1->as - p2->as; if(n) return n; n = p1->a1 - p2->a1; if(n) return n; n = p1->a2 - p2->a2; if(n) return n; n = p1->a3 - p2->a3; if(n) return n; return 0; } void buildop(void) { int i, n, r; for(i=0; i<32; i++) for(n=0; n<32; n++) xcmp[i][n] = cmp(n, i); for(n=0; optab[n].as != AXXX; n++) ; qsort(optab, n, sizeof(optab[0]), ocmp); for(i=0; i= 32 || x >= nelem(opcross)) { diag("assumptions fail in buildrep"); errorexit(); } repop[as] = x; p = (opcross + x); s = oprange[as].start; e = oprange[as].stop; for(o=e-1; o>=s; o--) { n = o-optab; for(a2=0; a2<2; a2++) { if(a2) { if(o->a2 == C_NONE) continue; } else if(o->a2 != C_NONE) continue; for(a1=0; a1<32; a1++) { if(!xcmp[a1][o->a1]) continue; for(a3=0; a3<32; a3++) if(xcmp[a3][o->a3]) (*p)[a1][a2][a3] = n+1; } } } oprange[as].start = 0; }