12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "l.h"
- #define r0iszero 1
- void
- span(void)
- {
- Prog *p, *q;
- Sym *setext;
- Optab *o;
- int m, bflag;
- int32_t 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, int32_t v)
- {
- Sym *s;
- s = lookup(p, 0);
- if(s->type == 0 || s->type == SXREF) {
- s->type = t;
- s->value = v;
- }
- }
- int32_t
- 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(const void *a1, const 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;
- uint8_t *m;
- uint32_t *a;
- };
- Reloc rels;
- static void
- grow(Reloc *r)
- {
- int t;
- uint8_t *m, *nm;
- uint32_t *a, *na;
- t = r->t;
- r->t += 64;
- m = r->m;
- a = r->a;
- r->m = nm = malloc(r->t*sizeof(uint8_t));
- r->a = na = malloc(r->t*sizeof(uint32_t));
- memmove(nm, m, t*sizeof(uint8_t));
- memmove(na, a, t*sizeof(uint32_t));
- free(m);
- free(a);
- }
- void
- dynreloc(Sym *s, int32_t v, int abs, int split, int sext)
- {
- int i, k, n;
- uint8_t *m;
- uint32_t *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;
- uint32_t la, ra, *a;
- int64_t off;
- uint8_t *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);
- }
- }
|