📄 span.c
字号:
#include "l.h"static struct { ulong start; ulong size;} pool;void checkpool(Prog*);void flushpool(Prog*, int);voidspan(void){ Prog *p; Sym *setext, *s; Optab *o; int m, bflag, i; long c, otxt, v; if(debug['v']) Bprint(&bso, "%5.2f span\n", cputime()); Bflush(&bso); bflag = 0; c = INITTEXT; otxt = c; 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; /* need passes to resolve branches */ if(c-otxt >= 1L<<17) bflag = 1; otxt = c; continue; } diag("zero-width instruction\n%P", p); continue; } switch(o->flag & (LFROM|LTO|LPOOL)) { case LFROM: addpool(p, &p->from); break; case LTO: addpool(p, &p->to); break; case LPOOL: if ((p->scond&C_SCOND) == 14) flushpool(p, 0); break; } if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14) flushpool(p, 0); c += m; if(blitrl) checkpool(p); } /* * if any procedure is large enough to * generate a large SBRA branch, then * generate extra passes putting branches * around jmps to fix. this is rare. */ while(bflag) { if(debug['v']) Bprint(&bso, "%5.2f span1\n", cputime()); bflag = 0; c = INITTEXT; for(p = firstp; p != P; p = p->link) { p->pc = c; o = oplook(p);/* very larg branches if(o->type == 6 && p->cond) { otxt = p->cond->pc - c; if(otxt < 0) otxt = -otxt; if(otxt >= (1L<<17) - 10) { q = prg(); q->link = p->link; p->link = q; q->as = AB; q->to.type = D_BRANCH; q->cond = p->cond; p->cond = q; q = prg(); q->link = p->link; p->link = q; q->as = AB; q->to.type = D_BRANCH; q->cond = q->link->link; bflag = 1; } } */ 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", p); continue; } c += m; } } if(debug['t']) { /* * add strings to text segment */ c = rnd(c, 8); for(i=0; i<NHASH; i++) for(s = hash[i]; s != S; s = s->link) { if(s->type != SSTRING) continue; v = s->value; while(v & 3) v++; s->value = c; c += v; } } 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);}/* * when the first reference to the literal pool threatens * to go out of range of a 12-bit PC-relative offset, * drop the pool now, and branch round it. * this happens only in extended basic blocks that exceed 4k. */voidcheckpool(Prog *p){ if(pool.size >= 0xffc || immaddr((p->pc+4)+4+pool.size - pool.start+8) == 0) flushpool(p, 1); else if(p->link == P) flushpool(p, 2);}voidflushpool(Prog *p, int skip){ Prog *q; if(blitrl) { if(skip){ if(debug['v'] && skip == 1) print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start); q = prg(); q->as = AB; q->to.type = D_BRANCH; q->cond = p->link; q->link = blitrl; blitrl = q; } else if(p->pc+pool.size-pool.start < 2048) return; elitrl->link = p->link; p->link = blitrl; blitrl = 0; /* BUG: should refer back to values until out-of-range */ elitrl = 0; pool.size = 0; pool.start = 0; }}voidaddpool(Prog *p, Adr *a){ Prog *q, t; int c; c = aclass(a); t = zprg; t.as = AWORD; switch(c) { default: t.to = *a; break; case C_SROREG: case C_LOREG: case C_ROREG: case C_FOREG: case C_SOREG: case C_FAUTO: case C_SAUTO: case C_LAUTO: case C_LACON: t.to.type = D_CONST; t.to.offset = instoffset; break; } for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */ if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) { p->cond = q; return; } q = prg(); *q = t; q->pc = pool.size; if(blitrl == P) { blitrl = q; pool.start = p->pc; } else elitrl->link = q; elitrl = q; pool.size += 4; p->cond = q;}voidxdefine(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; }}longregoff(Adr *a){ instoffset = 0; aclass(a); return instoffset;}longimmrot(ulong v){ int i; for(i=0; i<16; i++) { if((v & ~0xff) == 0) return (i<<8) | v | (1<<25); v = (v<<2) | (v>>30); } return 0;}longimmaddr(long v){ if(v >= 0 && v <= 0xfff) return (v & 0xfff) | (1<<24) | /* pre indexing */ (1<<23); /* pre indexing, up */ if(v >= -0xfff && v < 0) return (-v & 0xfff) | (1<<24); /* pre indexing */ return 0;}intimmfloat(long v){ return (v & 0xC03) == 0; /* offset will fit in floating-point load/store */}intimmhalf(long v){ if(v >= 0 && v <= 0xff) return v| (1<<24)| /* pre indexing */ (1<<23); /* pre indexing, up */ if(v >= -0xff && v < 0) return (-v & 0xff)| (1<<24); /* pre indexing */ return 0;}intaclass(Adr *a){ Sym *s; int t; switch(a->type) { case D_NONE: return C_NONE; case D_REG: return C_REG; case D_REGREG: return C_REGREG; case D_SHIFT: return C_SHIFT; case D_FREG: return C_FREG; case D_FPCR: return C_FCR; 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; } s = a->sym; t = s->type; if(t == 0 || t == SXREF) { diag("undefined external: %s in %s", s->name, TNAME); s->type = SDATA; } if(dlm) { switch(t) { default: instoffset = s->value + a->offset + INITDAT; break; case SUNDEF: case STEXT: case SCONST: case SLEAF: case SSTRING: instoffset = s->value + a->offset; break; } return C_ADDR; } instoffset = s->value + a->offset - BIG; t = immaddr(instoffset); if(t) { if(immhalf(instoffset)) return immfloat(t) ? C_HFEXT : C_HEXT; if(immfloat(t)) return C_FEXT; return C_SEXT; } return C_LEXT; case D_AUTO: instoffset = autosize + a->offset; t = immaddr(instoffset); if(t){ if(immhalf(instoffset)) return immfloat(t) ? C_HFAUTO : C_HAUTO; if(immfloat(t)) return C_FAUTO; return C_SAUTO; } return C_LAUTO; case D_PARAM: instoffset = autosize + a->offset + 4L; t = immaddr(instoffset); if(t){ if(immhalf(instoffset)) return immfloat(t) ? C_HFAUTO : C_HAUTO; if(immfloat(t)) return C_FAUTO; return C_SAUTO; } return C_LAUTO; case D_NONE: instoffset = a->offset; t = immaddr(instoffset); if(t) { if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */ return immfloat(t) ? C_HFOREG : C_HOREG; if(immfloat(t)) return C_FOREG; /* n.b. that it will also satisfy immrot */ t = immrot(instoffset); if(t) return C_SROREG; if(immhalf(instoffset)) return C_HOREG; return C_SOREG; } t = immrot(instoffset); if(t) return C_ROREG; return C_LOREG; } return C_GOK; case D_PSR: return C_PSR; 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", s->name, TNAME); s->type = SDATA; } instoffset = s->value + a->offset + INITDAT; if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) instoffset = s->value + a->offset; return C_LCON; } return C_GOK; case D_FCONST: return C_FCON; case D_CONST: switch(a->name) { case D_NONE: instoffset = a->offset; if(a->reg != NREG) goto aconsize; t = immrot(instoffset); if(t) return C_RCON; t = immrot(~instoffset); if(t) return C_NCON; return C_LCON; 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", s->name, TNAME); s->type = SDATA; break; case SUNDEF: case STEXT: case SSTRING: case SCONST: case SLEAF: instoffset = s->value + a->offset; return C_LCON; } if(!dlm) { instoffset = s->value + a->offset - BIG; t = immrot(instoffset); if(t && instoffset != 0) return C_RECON; } instoffset = s->value + a->offset + INITDAT; return C_LCON; case D_AUTO: instoffset = autosize + a->offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -