diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/7l/span.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/7l/span.c')
-rwxr-xr-x | sys/src/cmd/7l/span.c | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/sys/src/cmd/7l/span.c b/sys/src/cmd/7l/span.c new file mode 100755 index 000000000..65ba2df56 --- /dev/null +++ b/sys/src/cmd/7l/span.c @@ -0,0 +1,584 @@ +#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 + 8; + if(p->from.sym != S) + p->from.sym->value = c; + continue; + } + 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; + } +} + +vlong /* BUG? */ +regoff(Adr *a) +{ + + offset = 0; + aclass(a); + return offset; +} + +/* + * note that we can't generate every 32 bit constant with MOVQA+MOVQAH, hence the + * comparison with 0x7fff8000. offset >= this value gets incorrectly sign extended in + * the 64 bit register. + */ +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_FCREG: + return C_FCREG; + + case D_PREG: + return C_PREG; + + case D_PCC: + return C_PCC; + + case D_OREG: + switch(a->name) { + case D_EXTERN: + case D_STATIC: + if(a->sym == 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", + a->sym->name, TNAME); + a->sym->type = SDATA; + } + offset = a->sym->value + a->offset - BIG; + if(offset >= -BIG && offset < BIG) + return C_SEXT; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LEXT; + badoff: + diag("offset out of range: %#llux", offset); + return C_GOK; + case D_AUTO: + offset = autosize + a->offset; + if(offset >= -BIG && offset < BIG) + return C_SAUTO; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LAUTO; + goto badoff; + case D_PARAM: + offset = autosize + a->offset + 8L; + if(offset >= -BIG && offset < BIG) + return C_SAUTO; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LAUTO; + goto badoff; + case D_NONE: + offset = a->offset; + if(offset == 0) + return C_ZOREG; + if(offset >= -BIG && offset < BIG) + return C_SOREG; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LOREG; + goto badoff; + } + return C_GOK; + + case D_CONST: + switch(a->name) { + + case D_NONE: + offset = a->offset; + if(offset > 0) { + if(offset <= 0xffLL) + return C_BCON; + if(offset <= 0x7fffLL) + return C_SCON; + if((offset & 0xffffLL) == 0 && offset <= 0x7fff0000LL) + return C_UCON; + if (offset < 0x7fff8000LL) + return C_LCON; + return C_QCON; + } + if(offset == 0) + return C_ZCON; + if(offset >= -0x100LL) + return C_NCON; + if(offset >= -0x8000LL) + return C_SCON; + if((offset & 0xffffLL) == 0 && offset >= -0x80000000LL) + return C_UCON; + if (offset >= -0x80000000LL) + return C_LCON; + return C_QCON; + + case D_EXTERN: + case D_STATIC: + s = a->sym; + if(s == 0) { + print("null sym const\n"); + print("%D\n", a); + return C_GOK; + } + 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) { + offset = s->value + a->offset; + return C_LCON; + } + offset = s->value + a->offset - BIG; + if (offset == 0L) { + offset = s->value + a->offset + INITDAT; + return C_LCON; /* botch */ + } + if(offset >= -BIG && offset < BIG && offset != 0L) + return C_SECON; + if (offset >= -0x80000000LL && offset < 0x7fff8000L && offset != 0LL /*&& offset >= -INITDAT*/) + return C_LECON; + /*offset = s->value + a->offset + INITDAT;*/ +/* if (offset >= -BIG && offset < BIG) + return C_SCON; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LCON; */ + goto badoff; + /*return C_QCON;*/ + + case D_AUTO: + offset = autosize + a->offset; + if(offset >= -BIG && offset < BIG) + return C_SACON; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LACON; + goto badoff; + + case D_PARAM: + offset = autosize + a->offset + 8L; + if(offset >= -BIG && offset < BIG) + return C_SACON; + if (offset >= -0x80000000LL && offset < 0x7fff8000LL) + return C_LACON; + goto badoff; + } + 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) { + a1 = opcross[repop[r]][a1][a2][a3]; + if(a1) { + p->optab = a1+1; + return optab+a1; + } + 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 (opcross %d)", + p->as, p->from.class-1, a2, a3, a1); + if(!debug['a']) + prasm(p); + o = optab; + p->optab = (o-optab)+1; + return o; +} + +int +cmp(int a, int b) +{ + + if(a == b) + return 1; + switch(a) { + case C_QCON: + if(b == C_ZCON || b == C_BCON || b == C_NCON || b == C_SCON || b == C_UCON || b == C_LCON) + return 1; + break; + case C_LCON: + if(b == C_ZCON || b == C_BCON || b == C_NCON || 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 || b == C_BCON || b == C_NCON) + return 1; + break; + case C_BCON: + 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_LEXT: + if(b == C_SEXT) + return 1; + break; + case C_LAUTO: + if(b == C_SAUTO) + 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; + } + 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<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 AADDQ: + oprange[AS4ADDQ] = oprange[r]; + oprange[AS8ADDQ] = oprange[r]; + oprange[ASUBQ] = oprange[r]; + oprange[AS4SUBQ] = oprange[r]; + oprange[AS8SUBQ] = oprange[r]; + break; + case AADDL: + oprange[AADDLV] = oprange[r]; + oprange[AS4ADDL] = oprange[r]; + oprange[AS8ADDL] = oprange[r]; + oprange[AADDQV] = oprange[r]; + oprange[ASUBQV] = oprange[r]; + oprange[ASUBL] = oprange[r]; + oprange[ASUBLV] = oprange[r]; + oprange[AS4SUBL] = oprange[r]; + oprange[AS8SUBL] = oprange[r]; + break; + case AAND: + oprange[AANDNOT] = oprange[r]; + oprange[AOR] = oprange[r]; + oprange[AORNOT] = oprange[r]; + oprange[AXOR] = oprange[r]; + oprange[AXORNOT] = oprange[r]; + break; + case AMULQ: + oprange[ACMPEQ] = oprange[r]; + oprange[ACMPGT] = oprange[r]; + oprange[ACMPGE] = oprange[r]; + oprange[ACMPUGT] = oprange[r]; + oprange[ACMPUGE] = oprange[r]; + oprange[ACMPBLE] = oprange[r]; + oprange[ACMOVEQ] = oprange[r]; + oprange[ACMOVNE] = oprange[r]; + oprange[ACMOVLT] = oprange[r]; + oprange[ACMOVGE] = oprange[r]; + oprange[ACMOVLE] = oprange[r]; + oprange[ACMOVGT] = oprange[r]; + oprange[ACMOVLBS] = oprange[r]; + oprange[ACMOVLBC] = oprange[r]; + oprange[AMULL] = oprange[r]; + oprange[AMULLV] = oprange[r]; + oprange[AMULQV] = oprange[r]; + oprange[AUMULH] = oprange[r]; + oprange[ASLLQ] = oprange[r]; + oprange[ASRLQ] = oprange[r]; + oprange[ASRAQ] = oprange[r]; + oprange[AEXTBL] = oprange[r]; + oprange[AEXTWL] = oprange[r]; + oprange[AEXTLL] = oprange[r]; + oprange[AEXTQL] = oprange[r]; + oprange[AEXTWH] = oprange[r]; + oprange[AEXTLH] = oprange[r]; + oprange[AEXTQH] = oprange[r]; + oprange[AINSBL] = oprange[r]; + oprange[AINSWL] = oprange[r]; + oprange[AINSLL] = oprange[r]; + oprange[AINSQL] = oprange[r]; + oprange[AINSWH] = oprange[r]; + oprange[AINSLH] = oprange[r]; + oprange[AINSQH] = oprange[r]; + oprange[AMSKBL] = oprange[r]; + oprange[AMSKWL] = oprange[r]; + oprange[AMSKLL] = oprange[r]; + oprange[AMSKQL] = oprange[r]; + oprange[AMSKWH] = oprange[r]; + oprange[AMSKLH] = oprange[r]; + oprange[AMSKQH] = oprange[r]; + oprange[AZAP] = oprange[r]; + oprange[AZAPNOT] = oprange[r]; + break; + case ABEQ: + oprange[ABNE] = oprange[r]; + oprange[ABGE] = oprange[r]; + oprange[ABLE] = oprange[r]; + oprange[ABGT] = oprange[r]; + oprange[ABLT] = oprange[r]; + break; + case AFBEQ: + oprange[AFBNE] = oprange[r]; + oprange[AFBGE] = oprange[r]; + oprange[AFBLE] = oprange[r]; + oprange[AFBGT] = oprange[r]; + oprange[AFBLT] = oprange[r]; + break; + case AMOVQ: + oprange[AMOVL] = oprange[r]; + oprange[AMOVLU] = oprange[r]; + oprange[AMOVQU] = oprange[r]; + oprange[AMOVA] = oprange[r]; + oprange[AMOVAH] = oprange[r]; + + oprange[AMOVBU] = oprange[r]; + oprange[AMOVWU] = oprange[r]; + oprange[AMOVB] = oprange[r]; + oprange[AMOVW] = oprange[r]; + break; + case AMOVT: + oprange[AMOVS] = oprange[r]; + break; + case AADDT: + oprange[AADDS] = oprange[r]; + oprange[ACMPTEQ] = oprange[r]; + oprange[ACMPTGT] = oprange[r]; + oprange[ACMPTGE] = oprange[r]; + oprange[ACMPTUN] = oprange[r]; + oprange[ADIVS] = oprange[r]; + oprange[ADIVT] = oprange[r]; + oprange[AMULS] = oprange[r]; + oprange[AMULT] = oprange[r]; + oprange[ASUBS] = oprange[r]; + oprange[ASUBT] = oprange[r]; + oprange[ACPYS] = oprange[r]; + oprange[ACPYSN] = oprange[r]; + oprange[ACPYSE] = oprange[r]; + oprange[ACVTLQ] = oprange[r]; + oprange[ACVTQL] = oprange[r]; + oprange[AFCMOVEQ] = oprange[r]; + oprange[AFCMOVNE] = oprange[r]; + oprange[AFCMOVLT] = oprange[r]; + oprange[AFCMOVGE] = oprange[r]; + oprange[AFCMOVLE] = oprange[r]; + oprange[AFCMOVGT] = oprange[r]; + break; + case ACVTTQ: + oprange[ACVTQT] = oprange[r]; + oprange[ACVTTS] = oprange[r]; + oprange[ACVTQS] = oprange[r]; + break; + case AJMP: + case AJSR: + break; + case ACALL_PAL: + break; + case AMOVQL: + oprange[AMOVLL] = oprange[r]; + break; + case AMOVQC: + oprange[AMOVLC] = oprange[r]; + break; + case AMOVQP: + oprange[AMOVLP] = oprange[r]; + break; + case AREI: + oprange[AMB] = oprange[r]; + oprange[ATRAPB] = oprange[r]; + break; + case AFETCH: + oprange[AFETCHM] = oprange[r]; + break; + case AWORD: + case ATEXT: + break; + } + } +} + +void +buildrep(int x, int as) +{ + Opcross *p; + Optab *e, *s, *o; + int a1, a2, a3, n; + + if(C_NONE != 0 || C_REG != 1 || C_GOK >= 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; + } + } + } + oprange[as].start = 0; +} |