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/ql/span.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ql/span.c')
-rwxr-xr-x | sys/src/cmd/ql/span.c | 1055 |
1 files changed, 1055 insertions, 0 deletions
diff --git a/sys/src/cmd/ql/span.c b/sys/src/cmd/ql/span.c new file mode 100755 index 000000000..cc4e5bb86 --- /dev/null +++ b/sys/src/cmd/ql/span.c @@ -0,0 +1,1055 @@ +#include "l.h" +#define r0iszero 1 + +void +span(void) +{ + Prog *p, *q; + Sym *setext; + Optab *o; + int m, bflag; + long c, otxt; + + 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->from3.type == D_CONST) { + if(p->from3.offset & 3) + diag("illegal origin\n%P", p); + if(c > p->from3.offset) + diag("passed origin (#%lux)\n%P", c, p); + else + c = p->from3.offset; + p->pc = c; + } + if(p->from.sym != S) + p->from.sym->value = c; + /* need passes to resolve branches? */ + if(c-otxt >= (1L<<15)) + bflag = c; + otxt = c; + continue; + } + if(p->as != ANOP) + diag("zero-width instruction\n%P", p); + continue; + } + c += m; + } + + /* + * 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); + if((o->type == 16 || o->type == 17) && p->cond) { + otxt = p->cond->pc - c; + if(otxt < -(1L<<16)+10 || otxt >= (1L<<15)-10) { + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = p->cond; + p->cond = q; + q = prg(); + q->link = p->link; + p->link = q; + q->as = ABR; + q->to.type = D_BRANCH; + q->cond = q->link->link; + addnop(p->link); + addnop(p); + 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; + } + 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_SPR: + if(a->offset == D_LR) + return C_LR; + if(a->offset == D_XER) + return C_XER; + if(a->offset == D_CTR) + return C_CTR; + return C_SPR; + + case D_DCR: + return C_SPR; + + case D_SREG: + return C_SREG; + + case D_FPSCR: + return C_FPSCR; + + case D_MSR: + return C_MSR; + + 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; + } + if(dlm){ + instoffset = a->sym->value + a->offset; + switch(a->sym->type){ + case STEXT: + case SLEAF: + case SCONST: + case SUNDEF: + break; + default: + instoffset += INITDAT; + } + return C_ADDR; + } + instoffset = a->sym->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG) + return C_SEXT; + return C_LEXT; + case D_AUTO: + instoffset = autosize + a->offset; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + + case D_PARAM: + instoffset = autosize + a->offset + 4L; + if(instoffset >= -BIG && instoffset < BIG) + return C_SAUTO; + return C_LAUTO; + 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_OPT: + instoffset = a->offset & 31L; + if(a->name == D_NONE) + return C_SCON; + return C_GOK; + + case D_CONST: + switch(a->name) { + + case D_NONE: + instoffset = a->offset; + consize: + if(instoffset >= 0) { + if(r0iszero && instoffset == 0) + return C_ZCON; + if(instoffset <= 0x7fff) + return C_SCON; + if(instoffset <= 0xffff) + return C_ANDCON; + if((instoffset & 0xffff) == 0) + return C_UCON; + return C_LCON; + } + if(instoffset >= -0x8000) + return C_ADDCON; + if((instoffset & 0xffff) == 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 || s->type == SUNDEF) { + instoffset = s->value + a->offset; + return C_LCON; + } + if(s->type == SCONST) { + instoffset = s->value + a->offset; + if(dlm) + return C_LCON; + goto consize; + } + if(!dlm){ + instoffset = s->value + a->offset - BIG; + if(instoffset >= -BIG && instoffset < BIG && instoffset != 0) + return C_SECON; + } + instoffset = s->value + a->offset + INITDAT; + if(dlm) + return C_LCON; + /* not sure why this barfs */ + return C_LCON; + /* + if(instoffset == 0) + return C_ZCON; + if(instoffset >= -0x8000 && instoffset <= 0xffff) + return C_SCON; + if((instoffset & 0xffff) == 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, a4, r; + char *c1, *c3, *c4; + 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->from3.class; + if(a3 == 0) { + a3 = aclass(&p->from3) + 1; + p->from3.class = a3; + } + a3--; + a4 = p->to.class; + if(a4 == 0) { + a4 = aclass(&p->to) + 1; + p->to.class = a4; + } + a4--; + 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]; + c4 = xcmp[a4]; + for(; o<e; o++) + if(o->a2 == a2) + if(c1[o->a1]) + if(c3[o->a3]) + if(c4[o->a4]) { + p->optab = (o-optab)+1; + return o; + } + diag("illegal combination %A %R %R %R %R", + p->as, a1, a2, a3, a4); + 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 || b == C_ADDCON || b == C_ANDCON) + return 1; + break; + case C_ADDCON: + if(b == C_ZCON || b == C_SCON) + return 1; + break; + case C_ANDCON: + if(b == C_ZCON || b == C_SCON) + return 1; + break; + case C_SPR: + if(b == C_LR || b == C_XER || b == C_CTR) + 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_LEXT: + if(b == C_SEXT) + return 1; + break; + case C_LAUTO: + if(b == C_SAUTO) + return 1; + break; + case C_REG: + if(r0iszero && 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(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; + n = p1->a4 - p2->a4; + 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 ADCBF: /* unary indexed: op (b+a); op (b) */ + oprange[ADCBI] = oprange[r]; + oprange[ADCBST] = oprange[r]; + oprange[ADCBT] = oprange[r]; + oprange[ADCBTST] = oprange[r]; + oprange[ADCBZ] = oprange[r]; + oprange[AICBI] = oprange[r]; + break; + case AECOWX: /* indexed store: op s,(b+a); op s,(b) */ + oprange[ASTWCCC] = oprange[r]; + break; + case AREM: /* macro */ + oprange[AREMCC] = oprange[r]; + oprange[AREMV] = oprange[r]; + oprange[AREMVCC] = oprange[r]; + oprange[AREMU] = oprange[r]; + oprange[AREMUCC] = oprange[r]; + oprange[AREMUV] = oprange[r]; + oprange[AREMUVCC] = oprange[r]; + break; + case ADIVW: /* op Rb[,Ra],Rd */ + oprange[AMULHW] = oprange[r]; + oprange[AMULHWCC] = oprange[r]; + oprange[AMULHWU] = oprange[r]; + oprange[AMULHWUCC] = oprange[r]; + oprange[AMULLWCC] = oprange[r]; + oprange[AMULLWVCC] = oprange[r]; + oprange[AMULLWV] = oprange[r]; + oprange[ADIVWCC] = oprange[r]; + oprange[ADIVWV] = oprange[r]; + oprange[ADIVWVCC] = oprange[r]; + oprange[ADIVWU] = oprange[r]; + oprange[ADIVWUCC] = oprange[r]; + oprange[ADIVWUV] = oprange[r]; + oprange[ADIVWUVCC] = oprange[r]; + oprange[AADDCC] = oprange[r]; + oprange[AADDCV] = oprange[r]; + oprange[AADDCVCC] = oprange[r]; + oprange[AADDV] = oprange[r]; + oprange[AADDVCC] = oprange[r]; + oprange[AADDE] = oprange[r]; + oprange[AADDECC] = oprange[r]; + oprange[AADDEV] = oprange[r]; + oprange[AADDEVCC] = oprange[r]; + oprange[ACRAND] = oprange[r]; + oprange[ACRANDN] = oprange[r]; + oprange[ACREQV] = oprange[r]; + oprange[ACRNAND] = oprange[r]; + oprange[ACRNOR] = oprange[r]; + oprange[ACROR] = oprange[r]; + oprange[ACRORN] = oprange[r]; + oprange[ACRXOR] = oprange[r]; + oprange[AMULCHW] = oprange[r]; + oprange[AMULCHWCC] = oprange[r]; + oprange[AMULCHWU] = oprange[r]; + oprange[AMULCHWUCC] = oprange[r]; + oprange[AMULHHW] = oprange[r]; + oprange[AMULHHWCC] = oprange[r]; + oprange[AMULHHWU] = oprange[r]; + oprange[AMULHHWUCC] = oprange[r]; + oprange[AMULLHW] = oprange[r]; + oprange[AMULLHWCC] = oprange[r]; + oprange[AMULLHWU] = oprange[r]; + oprange[AMULLHWUCC] = oprange[r]; + break; + case AMACCHW: /* strictly 3 registers */ + oprange[AMACCHWCC] = oprange[r]; + oprange[AMACCHWS] = oprange[r]; + oprange[AMACCHWSCC] = oprange[r]; + oprange[AMACCHWSU] = oprange[r]; + oprange[AMACCHWSUCC] = oprange[r]; + oprange[AMACCHWSUV] = oprange[r]; + oprange[AMACCHWSUVCC] = oprange[r]; + oprange[AMACCHWSV] = oprange[r]; + oprange[AMACCHWSVCC] = oprange[r]; + oprange[AMACCHWU] = oprange[r]; + oprange[AMACCHWUCC] = oprange[r]; + oprange[AMACCHWUV] = oprange[r]; + oprange[AMACCHWUVCC] = oprange[r]; + oprange[AMACCHWV] = oprange[r]; + oprange[AMACCHWVCC] = oprange[r]; + oprange[AMACHHW] = oprange[r]; + oprange[AMACHHWCC] = oprange[r]; + oprange[AMACHHWS] = oprange[r]; + oprange[AMACHHWSCC] = oprange[r]; + oprange[AMACHHWSU] = oprange[r]; + oprange[AMACHHWSUCC] = oprange[r]; + oprange[AMACHHWSUV] = oprange[r]; + oprange[AMACHHWSUVCC] = oprange[r]; + oprange[AMACHHWSV] = oprange[r]; + oprange[AMACHHWSVCC] = oprange[r]; + oprange[AMACHHWU] = oprange[r]; + oprange[AMACHHWUCC] = oprange[r]; + oprange[AMACHHWUV] = oprange[r]; + oprange[AMACHHWUVCC] = oprange[r]; + oprange[AMACHHWV] = oprange[r]; + oprange[AMACHHWVCC] = oprange[r]; + oprange[AMACLHW] = oprange[r]; + oprange[AMACLHWCC] = oprange[r]; + oprange[AMACLHWS] = oprange[r]; + oprange[AMACLHWSCC] = oprange[r]; + oprange[AMACLHWSU] = oprange[r]; + oprange[AMACLHWSUCC] = oprange[r]; + oprange[AMACLHWSUV] = oprange[r]; + oprange[AMACLHWSUVCC] = oprange[r]; + oprange[AMACLHWSV] = oprange[r]; + oprange[AMACLHWSVCC] = oprange[r]; + oprange[AMACLHWU] = oprange[r]; + oprange[AMACLHWUCC] = oprange[r]; + oprange[AMACLHWUV] = oprange[r]; + oprange[AMACLHWUVCC] = oprange[r]; + oprange[AMACLHWV] = oprange[r]; + oprange[AMACLHWVCC] = oprange[r]; + oprange[ANMACCHW] = oprange[r]; + oprange[ANMACCHWCC] = oprange[r]; + oprange[ANMACCHWS] = oprange[r]; + oprange[ANMACCHWSCC] = oprange[r]; + oprange[ANMACCHWSV] = oprange[r]; + oprange[ANMACCHWSVCC] = oprange[r]; + oprange[ANMACCHWV] = oprange[r]; + oprange[ANMACCHWVCC] = oprange[r]; + oprange[ANMACHHW] = oprange[r]; + oprange[ANMACHHWCC] = oprange[r]; + oprange[ANMACHHWS] = oprange[r]; + oprange[ANMACHHWSCC] = oprange[r]; + oprange[ANMACHHWSV] = oprange[r]; + oprange[ANMACHHWSVCC] = oprange[r]; + oprange[ANMACHHWV] = oprange[r]; + oprange[ANMACHHWVCC] = oprange[r]; + oprange[ANMACLHW] = oprange[r]; + oprange[ANMACLHWCC] = oprange[r]; + oprange[ANMACLHWS] = oprange[r]; + oprange[ANMACLHWSCC] = oprange[r]; + oprange[ANMACLHWSV] = oprange[r]; + oprange[ANMACLHWSVCC] = oprange[r]; + oprange[ANMACLHWV] = oprange[r]; + oprange[ANMACLHWVCC] = oprange[r]; + break; + case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */ + oprange[AMOVH] = oprange[r]; + oprange[AMOVHZ] = oprange[r]; + break; + case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x */ + oprange[AMOVHU] = oprange[r]; + oprange[AMOVHZU] = oprange[r]; + oprange[AMOVWU] = oprange[r]; + oprange[AMOVMW] = oprange[r]; + break; + case AAND: /* logical op Rb,Rs,Ra; no literal */ + oprange[AANDN] = oprange[r]; + oprange[AANDNCC] = oprange[r]; + oprange[AEQV] = oprange[r]; + oprange[AEQVCC] = oprange[r]; + oprange[ANAND] = oprange[r]; + oprange[ANANDCC] = oprange[r]; + oprange[ANOR] = oprange[r]; + oprange[ANORCC] = oprange[r]; + oprange[AORCC] = oprange[r]; + oprange[AORN] = oprange[r]; + oprange[AORNCC] = oprange[r]; + oprange[AXORCC] = oprange[r]; + break; + case AADDME: /* op Ra, Rd */ + oprange[AADDMECC] = oprange[r]; + oprange[AADDMEV] = oprange[r]; + oprange[AADDMEVCC] = oprange[r]; + oprange[AADDZE] = oprange[r]; + oprange[AADDZECC] = oprange[r]; + oprange[AADDZEV] = oprange[r]; + oprange[AADDZEVCC] = oprange[r]; + oprange[ASUBME] = oprange[r]; + oprange[ASUBMECC] = oprange[r]; + oprange[ASUBMEV] = oprange[r]; + oprange[ASUBMEVCC] = oprange[r]; + oprange[ASUBZE] = oprange[r]; + oprange[ASUBZECC] = oprange[r]; + oprange[ASUBZEV] = oprange[r]; + oprange[ASUBZEVCC] = oprange[r]; + break; + case AADDC: + oprange[AADDCCC] = oprange[r]; + break; + case ABEQ: + oprange[ABGE] = oprange[r]; + oprange[ABGT] = oprange[r]; + oprange[ABLE] = oprange[r]; + oprange[ABLT] = oprange[r]; + oprange[ABNE] = oprange[r]; + oprange[ABVC] = oprange[r]; + oprange[ABVS] = oprange[r]; + break; + case ABR: + oprange[ABL] = oprange[r]; + break; + case ABC: + oprange[ABCL] = oprange[r]; + break; + case AEXTSB: /* op Rs, Ra */ + oprange[AEXTSBCC] = oprange[r]; + oprange[AEXTSH] = oprange[r]; + oprange[AEXTSHCC] = oprange[r]; + oprange[ACNTLZW] = oprange[r]; + oprange[ACNTLZWCC] = oprange[r]; + break; + case AFABS: /* fop [s,]d */ + oprange[AFABSCC] = oprange[r]; + oprange[AFNABS] = oprange[r]; + oprange[AFNABSCC] = oprange[r]; + oprange[AFNEG] = oprange[r]; + oprange[AFNEGCC] = oprange[r]; + oprange[AFRSP] = oprange[r]; + oprange[AFRSPCC] = oprange[r]; + oprange[AFCTIW] = oprange[r]; + oprange[AFCTIWCC] = oprange[r]; + oprange[AFCTIWZ] = oprange[r]; + oprange[AFCTIWZCC] = oprange[r]; + oprange[AFRES] = oprange[r]; + oprange[AFRESCC] = oprange[r]; + oprange[AFRSQRTE] = oprange[r]; + oprange[AFRSQRTECC] = oprange[r]; + oprange[AFSQRT] = oprange[r]; + oprange[AFSQRTCC] = oprange[r]; + oprange[AFSQRTS] = oprange[r]; + oprange[AFSQRTSCC] = oprange[r]; + oprange[AFPRE] = oprange[r]; + oprange[AFPRSQRTE] = oprange[r]; + oprange[AFPABS] = oprange[r]; + oprange[AFPNEG] = oprange[r]; + oprange[AFPRSP] = oprange[r]; + oprange[AFPNABS] = oprange[r]; + oprange[AFSABS] = oprange[r]; + oprange[AFSNEG] = oprange[r]; + oprange[AFSNABS] = oprange[r]; + oprange[AFPCTIW] = oprange[r]; + oprange[AFPCTIWZ] = oprange[r]; + break; + case AFADD: + oprange[AFADDS] = oprange[r]; + oprange[AFADDCC] = oprange[r]; + oprange[AFADDSCC] = oprange[r]; + oprange[AFDIV] = oprange[r]; + oprange[AFDIVS] = oprange[r]; + oprange[AFDIVCC] = oprange[r]; + oprange[AFDIVSCC] = oprange[r]; + oprange[AFSUB] = oprange[r]; + oprange[AFSUBS] = oprange[r]; + oprange[AFSUBCC] = oprange[r]; + oprange[AFSUBSCC] = oprange[r]; + oprange[AFPADD] = oprange[r]; + oprange[AFPSUB] = oprange[r]; + break; + case AFMADD: + oprange[AFMADDCC] = oprange[r]; + oprange[AFMADDS] = oprange[r]; + oprange[AFMADDSCC] = oprange[r]; + oprange[AFMSUB] = oprange[r]; + oprange[AFMSUBCC] = oprange[r]; + oprange[AFMSUBS] = oprange[r]; + oprange[AFMSUBSCC] = oprange[r]; + oprange[AFNMADD] = oprange[r]; + oprange[AFNMADDCC] = oprange[r]; + oprange[AFNMADDS] = oprange[r]; + oprange[AFNMADDSCC] = oprange[r]; + oprange[AFNMSUB] = oprange[r]; + oprange[AFNMSUBCC] = oprange[r]; + oprange[AFNMSUBS] = oprange[r]; + oprange[AFNMSUBSCC] = oprange[r]; + oprange[AFSEL] = oprange[r]; + oprange[AFSELCC] = oprange[r]; + oprange[AFPSEL] = oprange[r]; + oprange[AFPMADD] = oprange[r]; + oprange[AFXMADD] = oprange[r]; + oprange[AFXCPMADD] = oprange[r]; + oprange[AFXCSMADD] = oprange[r]; + oprange[AFPNMADD] = oprange[r]; + oprange[AFXNMADD] = oprange[r]; + oprange[AFXCPNMADD] = oprange[r]; + oprange[AFXCSNMADD] = oprange[r]; + oprange[AFPMSUB] = oprange[r]; + oprange[AFXMSUB] = oprange[r]; + oprange[AFXCPMSUB] = oprange[r]; + oprange[AFXCSMSUB] = oprange[r]; + oprange[AFPNMSUB] = oprange[r]; + oprange[AFXNMSUB] = oprange[r]; + oprange[AFXCPNMSUB] = oprange[r]; + oprange[AFXCSNMSUB] = oprange[r]; + oprange[AFXCPNPMA] = oprange[r]; + oprange[AFXCSNPMA] = oprange[r]; + oprange[AFXCPNSMA] = oprange[r]; + oprange[AFXCSNSMA] = oprange[r]; + oprange[AFXCXNPMA] = oprange[r]; + oprange[AFXCXNSMA] = oprange[r]; + oprange[AFXCXMA] = oprange[r]; + oprange[AFXCXNMS] = oprange[r]; + break; + case AFMUL: + oprange[AFMULS] = oprange[r]; + oprange[AFMULCC] = oprange[r]; + oprange[AFMULSCC] = oprange[r]; + oprange[AFPMUL] = oprange[r]; + oprange[AFXMUL] = oprange[r]; + oprange[AFXPMUL] = oprange[r]; + oprange[AFXSMUL] = oprange[r]; + break; + case AFCMPO: + oprange[AFCMPU] = oprange[r]; + break; + case AMTFSB0: + oprange[AMTFSB0CC] = oprange[r]; + oprange[AMTFSB1] = oprange[r]; + oprange[AMTFSB1CC] = oprange[r]; + break; + case ANEG: /* op [Ra,] Rd */ + oprange[ANEGCC] = oprange[r]; + oprange[ANEGV] = oprange[r]; + oprange[ANEGVCC] = oprange[r]; + break; + case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */ + oprange[AXOR] = oprange[r]; + break; + case ASLW: + oprange[ASLWCC] = oprange[r]; + oprange[ASRW] = oprange[r]; + oprange[ASRWCC] = oprange[r]; + break; + case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ + oprange[ASRAWCC] = oprange[r]; + break; + case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */ + oprange[ASUB] = oprange[r]; + oprange[ASUBCC] = oprange[r]; + oprange[ASUBV] = oprange[r]; + oprange[ASUBVCC] = oprange[r]; + oprange[ASUBCCC] = oprange[r]; + oprange[ASUBCV] = oprange[r]; + oprange[ASUBCVCC] = oprange[r]; + oprange[ASUBE] = oprange[r]; + oprange[ASUBECC] = oprange[r]; + oprange[ASUBEV] = oprange[r]; + oprange[ASUBEVCC] = oprange[r]; + break; + case ASYNC: + oprange[AISYNC] = oprange[r]; + break; + case ARLWMI: + oprange[ARLWMICC] = oprange[r]; + oprange[ARLWNM] = oprange[r]; + oprange[ARLWNMCC] = oprange[r]; + break; + case AFMOVD: + oprange[AFMOVDCC] = oprange[r]; + oprange[AFMOVDU] = oprange[r]; + oprange[AFMOVS] = oprange[r]; + oprange[AFMOVSU] = oprange[r]; + break; + case AECIWX: + oprange[ALWAR] = oprange[r]; + break; + case ASYSCALL: /* just the op; flow of control */ + oprange[ARFI] = oprange[r]; + oprange[ARFCI] = oprange[r]; + break; + case AMOVHBR: + oprange[AMOVWBR] = oprange[r]; + break; + case AFSMOVS: /* indexed floating loads and stores (fp2) */ + oprange[AFSMOVSU] = oprange[r]; + oprange[AFSMOVDU] = oprange[r]; + oprange[AFXMOVS] = oprange[r]; + oprange[AFXMOVSU] = oprange[r]; + oprange[AFXMOVDU] = oprange[r]; + oprange[AFPMOVS] = oprange[r]; + oprange[AFPMOVSU] = oprange[r]; + oprange[AFPMOVDU] = oprange[r]; + oprange[AFPMOVIW] = oprange[r]; + break; + case AFPMOVD: /* indexed load/store and moves (fp2) */ + oprange[AFSMOVD] = oprange[r]; + oprange[AFXMOVD] = oprange[r]; + break; + case AFMOVSPD: /* move between fp reg sets (fp2) */ + oprange[AFMOVPSD] = oprange[r]; + break; + case AADD: + case AANDCC: /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ + case ACMP: + case ACMPU: + case AEIEIO: + case ALSW: + case AMOVB: /* macro: move byte with sign extension */ + case AMOVBU: /* macro: move byte with sign extension & update */ + case AMOVW: + case AMOVFL: + case AMULLW: /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */ + case ASUBC: /* op r1,$s,r3; op r1[,r2],r3 */ + case ASTSW: + case ATLBIE: + case ATW: + case AWORD: + case ANOP: + case ATEXT: + break; + } + } +} + +enum{ + ABSD = 0, + ABSU = 1, + RELD = 2, + RELU = 3, +}; + +int modemap[8] = { 0, 1, -1, 2, 3, 4, 5, 6}; + +typedef struct Reloc Reloc; + +struct Reloc +{ + int n; + int t; + uchar *m; + ulong *a; +}; + +Reloc rels; + +static void +grow(Reloc *r) +{ + int t; + uchar *m, *nm; + ulong *a, *na; + + t = r->t; + r->t += 64; + m = r->m; + a = r->a; + r->m = nm = malloc(r->t*sizeof(uchar)); + r->a = na = malloc(r->t*sizeof(ulong)); + memmove(nm, m, t*sizeof(uchar)); + memmove(na, a, t*sizeof(ulong)); + free(m); + free(a); +} + +void +dynreloc(Sym *s, long v, int abs, int split, int sext) +{ + int i, k, n; + uchar *m; + ulong *a; + Reloc *r; + + if(v&3) + diag("bad relocation address"); + v >>= 2; + if(s->type == SUNDEF) + k = abs ? ABSU : RELU; + else + k = abs ? ABSD : RELD; + if(split) + k += 4; + if(sext) + k += 2; + /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */ + k = modemap[k]; + r = &rels; + n = r->n; + if(n >= r->t) + grow(r); + m = r->m; + a = r->a; + for(i = n; i > 0; i--){ + if(v < a[i-1]){ /* happens occasionally for data */ + m[i] = m[i-1]; + a[i] = a[i-1]; + } + else + break; + } + m[i] = k; + a[i] = v; + r->n++; +} + +static int +sput(char *s) +{ + char *p; + + p = s; + while(*s) + cput(*s++); + cput(0); + return s-p+1; +} + +void +asmdyn() +{ + int i, n, t, c; + Sym *s; + ulong la, ra, *a; + vlong off; + uchar *m; + Reloc *r; + + cflush(); + off = seek(cout, 0, 1); + lput(0); + t = 0; + lput(imports); + t += 4; + for(i = 0; i < NHASH; i++) + for(s = hash[i]; s != S; s = s->link) + if(s->type == SUNDEF){ + lput(s->sig); + t += 4; + t += sput(s->name); + } + + la = 0; + r = &rels; + n = r->n; + m = r->m; + a = r->a; + lput(n); + t += 4; + for(i = 0; i < n; i++){ + ra = *a-la; + if(*a < la) + diag("bad relocation order"); + if(ra < 256) + c = 0; + else if(ra < 65536) + c = 1; + else + c = 2; + cput((c<<6)|*m++); + t++; + if(c == 0){ + cput(ra); + t++; + } + else if(c == 1){ + wput(ra); + t += 2; + } + else{ + lput(ra); + t += 4; + } + la = *a++; + } + + cflush(); + seek(cout, off, 0); + lput(t); + + if(debug['v']){ + Bprint(&bso, "import table entries = %d\n", imports); + Bprint(&bso, "export table entries = %d\n", exports); + } +} |