ref: 479a31ae8f4a361b101aa203aa1c0822137708d7
dir: /sys/src/cmd/kl/span.c/
#include "l.h" void span(void) { Prog *p; Sym *setext; Optab *o; int m; long c; if(debug['v']) Bprint(&bso, "%5.2f span\n", cputime()); Bflush(&bso); c = INITTEXT; for(p = firstp; p != P; p = p->link) { 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; } if(p->as != ANOP) diag("zero-width instruction\n%P", 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); 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) { instoffset = 0; aclass(a); return instoffset; } int aclass(Adr *a) { Sym *s; int t; switch(a->type) { case D_NONE: return C_NONE; case D_REG: return C_REG; case D_FREG: return C_FREG; case D_CREG: return C_CREG; case D_PREG: if(a->reg == D_FSR) return C_FSR; if(a->reg == D_FPQ) return C_FQ; return C_PREG; case D_OREG: switch(a->name) { case D_EXTERN: case D_STATIC: if(a->sym == S) break; t = a->sym->type; if(t == 0 || t == SXREF) { diag("undefined external: %s in %s", a->sym->name, TNAME); a->sym->type = SDATA; } instoffset = a->sym->value + a->offset - BIG; if(instoffset >= -BIG && instoffset < BIG) { if(instoffset & 7) return C_OSEXT; return C_ESEXT; } if(instoffset & 7) return C_OLEXT; return C_ELEXT; case D_AUTO: instoffset = autosize + a->offset; goto dauto; case D_PARAM: instoffset = autosize + a->offset + 4L; dauto: if(instoffset >= -BIG && instoffset < BIG) { if(instoffset & 7) return C_OSAUTO; return C_ESAUTO; } if(instoffset & 7) return C_OLAUTO; return C_ELAUTO; case D_NONE: instoffset = a->offset; if(instoffset == 0) return C_ZOREG; if(instoffset >= -BIG && instoffset < BIG) return C_SOREG; return C_LOREG; } return C_GOK; case D_ASI: if(a->name == D_NONE) return C_ASI; return C_GOK; case D_CONST: switch(a->name) { case D_NONE: instoffset = a->offset; consize: if(instoffset == 0) return C_ZCON; if(instoffset >= -0x1000 && instoffset <= 0xfff) return C_SCON; if((instoffset & 0x3ff) == 0) return C_UCON; return C_LCON; case D_EXTERN: case D_STATIC: s = a->sym; if(s == S) break; t = s->type; if(t == 0 || t == SXREF) { diag("undefined external: %s in %s", s->name, TNAME); s->type = SDATA; } if(s->type == STEXT || s->type == SLEAF) { instoffset = s->value + a->offset; return C_LCON; } if(s->type == SCONST) { instoffset = s->value + a->offset; goto consize; } instoffset = s->value + a->offset - BIG; if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) return C_SECON; instoffset = s->value + a->offset + INITDAT; /* not sure why this barfs */ return C_LCON; /* if(instoffset == 0) return C_ZCON; if(instoffset >= -0x1000 && instoffset <= 0xfff) return C_SCON; if((instoffset & 0x3ff) == 0) return C_UCON; return C_LCON; */ case D_AUTO: instoffset = autosize + a->offset; if(instoffset >= -BIG && instoffset < BIG) return C_SACON; return C_LACON; case D_PARAM: instoffset = autosize + a->offset + 4L; if(instoffset >= -BIG && instoffset < BIG) return C_SACON; return C_LACON; } return C_GOK; case D_BRANCH: return C_SBRA; } return C_GOK; } Optab* oplook(Prog *p) { int a1, a2, a3, r; char *c1, *c3; Optab *o, *e; a1 = p->optab; if(a1) return optab+(a1-1); a1 = p->from.class; if(a1 == 0) { a1 = aclass(&p->from) + 1; p->from.class = a1; } a1--; a3 = p->to.class; if(a3 == 0) { a3 = aclass(&p->to) + 1; p->to.class = a3; } a3--; a2 = C_NONE; if(p->reg != NREG) a2 = C_REG; r = p->as; o = oprange[r].start; if(o == 0) o = oprange[r].stop; /* just generate an error */ e = oprange[r].stop; c1 = xcmp[a1]; c3 = xcmp[a3]; for(; o<e; o++) if(o->a2 == a2) if(c1[o->a1]) if(c3[o->a3]) { p->optab = (o-optab)+1; return o; } diag("illegal combination %A %d %d %d", p->as, a1, a2, a3); if(1||!debug['a']) prasm(p); if(o == 0) errorexit(); 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_UCON) return 1; break; case C_UCON: if(b == C_ZCON) return 1; break; case C_SCON: if(b == C_ZCON) return 1; break; case C_LACON: if(b == C_SACON) return 1; break; case C_LBRA: if(b == C_SBRA) return 1; break; case C_ELEXT: if(b == C_ESEXT) return 1; break; case C_LEXT: if(b == C_SEXT || b == C_ESEXT || b == C_OSEXT || b == C_ELEXT || b == C_OLEXT) return 1; break; case C_SEXT: if(b == C_ESEXT || b == C_OSEXT) return 1; break; case C_ELAUTO: if(b == C_ESAUTO) return 1; break; case C_LAUTO: if(b == C_SAUTO || b == C_ESAUTO || b == C_OSAUTO || b == C_ELAUTO || b == C_OLAUTO) return 1; break; case C_SAUTO: if(b == C_ESAUTO || b == C_OSAUTO) return 1; break; case C_REG: if(b == C_ZCON) return 1; break; case C_LOREG: if(b == C_ZOREG || b == C_SOREG) return 1; break; case C_SOREG: if(b == C_ZOREG) return 1; break; case C_ANY: return 1; } return 0; } int ocmp(const void *a1, const void *a2) { Optab *p1, *p2; int n; p1 = (Optab*)a1; p2 = (Optab*)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<C_NCLASS; i++) for(n=0; n<C_NCLASS; 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<n; i++) { r = optab[i].as; oprange[r].start = optab+i; while(optab[i].as == r) i++; oprange[r].stop = optab+i; i--; switch(r) { default: diag("unknown op in build: %A", r); errorexit(); case AADD: oprange[AADDX] = oprange[r]; oprange[ASUB] = oprange[r]; oprange[ASUBX] = oprange[r]; oprange[AMUL] = oprange[r]; oprange[AXOR] = oprange[r]; oprange[AXNOR] = oprange[r]; oprange[AAND] = oprange[r]; oprange[AANDN] = oprange[r]; oprange[AOR] = oprange[r]; oprange[AORN] = oprange[r]; oprange[ASLL] = oprange[r]; oprange[ASRL] = oprange[r]; oprange[ASRA] = oprange[r]; oprange[AADDCC] = oprange[r]; oprange[AADDXCC] = oprange[r]; oprange[ATADDCC] = oprange[r]; oprange[ATADDCCTV] = oprange[r]; oprange[ASUBCC] = oprange[r]; oprange[ASUBXCC] = oprange[r]; oprange[ATSUBCC] = oprange[r]; oprange[ATSUBCCTV] = oprange[r]; oprange[AXORCC] = oprange[r]; oprange[AXNORCC] = oprange[r]; oprange[AANDCC] = oprange[r]; oprange[AANDNCC] = oprange[r]; oprange[AORCC] = oprange[r]; oprange[AORNCC] = oprange[r]; oprange[AMULSCC] = oprange[r]; oprange[ASAVE] = oprange[r]; oprange[ARESTORE] = oprange[r]; break; case AMOVB: oprange[AMOVH] = oprange[r]; oprange[AMOVHU] = oprange[r]; oprange[AMOVBU] = oprange[r]; oprange[ASWAP] = oprange[r]; oprange[ATAS] = oprange[r]; break; case ABA: oprange[ABN] = oprange[r]; oprange[AFBA] = oprange[r]; oprange[AFBN] = oprange[r]; break; case ABE: oprange[ABCC] = oprange[r]; oprange[ABCS] = oprange[r]; oprange[ABGE] = oprange[r]; oprange[ABGU] = oprange[r]; oprange[ABG] = oprange[r]; oprange[ABLEU] = oprange[r]; oprange[ABLE] = oprange[r]; oprange[ABL] = oprange[r]; oprange[ABNEG] = oprange[r]; oprange[ABNE] = oprange[r]; oprange[ABPOS] = oprange[r]; oprange[ABVC] = oprange[r]; oprange[ABVS] = oprange[r]; oprange[AFBE] = oprange[r]; oprange[AFBG] = oprange[r]; oprange[AFBGE] = oprange[r]; oprange[AFBL] = oprange[r]; oprange[AFBLE] = oprange[r]; oprange[AFBLG] = oprange[r]; oprange[AFBNE] = oprange[r]; oprange[AFBO] = oprange[r]; oprange[AFBU] = oprange[r]; oprange[AFBUE] = oprange[r]; oprange[AFBUG] = oprange[r]; oprange[AFBUGE] = oprange[r]; oprange[AFBUL] = oprange[r]; oprange[AFBULE] = oprange[r]; break; case ATA: oprange[ATCC] = oprange[r]; oprange[ATCS] = oprange[r]; oprange[ATE] = oprange[r]; oprange[ATGE] = oprange[r]; oprange[ATGU] = oprange[r]; oprange[ATG] = oprange[r]; oprange[ATLEU] = oprange[r]; oprange[ATLE] = oprange[r]; oprange[ATL] = oprange[r]; oprange[ATNEG] = oprange[r]; oprange[ATNE] = oprange[r]; oprange[ATN] = oprange[r]; oprange[ATPOS] = oprange[r]; oprange[ATVC] = oprange[r]; oprange[ATVS] = oprange[r]; break; case AFADDD: oprange[AFADDF] = oprange[r]; oprange[AFADDX] = oprange[r]; oprange[AFDIVD] = oprange[r]; oprange[AFDIVF] = oprange[r]; oprange[AFDIVX] = oprange[r]; oprange[AFMULD] = oprange[r]; oprange[AFMULF] = oprange[r]; oprange[AFMULX] = oprange[r]; oprange[AFSUBD] = oprange[r]; oprange[AFSUBF] = oprange[r]; oprange[AFSUBX] = oprange[r]; break; case AFCMPD: oprange[AFCMPF] = oprange[r]; oprange[AFCMPX] = oprange[r]; oprange[AFCMPED] = oprange[r]; oprange[AFCMPEF] = oprange[r]; oprange[AFCMPEX] = oprange[r]; break; case AFABSF: oprange[AFMOVDF] = oprange[r]; oprange[AFMOVDW] = oprange[r]; oprange[AFMOVFD] = oprange[r]; oprange[AFMOVFW] = oprange[r]; oprange[AFMOVWD] = oprange[r]; oprange[AFMOVWF] = oprange[r]; oprange[AFNEGF] = oprange[r]; oprange[AFSQRTD] = oprange[r]; oprange[AFSQRTF] = oprange[r]; break; case AFMOVF: case AFMOVD: case AMOVW: case AMOVD: case AWORD: case ARETT: case AJMPL: case AJMP: case ACMP: case ANOP: case ATEXT: case ADIV: case ADIVL: case AMOD: case AMODL: break; } } }