1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096 |
- #include "limbo.h"
- static int addrmode[Rend] =
- {
- /* Rreg */ Afp,
- /* Rmreg */ Amp,
- /* Roff */ Aoff,
- /* Rnoff */ Anoff,
- /* Rdesc */ Adesc,
- /* Rdescp */ Adesc,
- /* Rconst */ Aimm,
- /* Ralways */ Aerr,
- /* Radr */ Afpind,
- /* Rmadr */ Ampind,
- /* Rcant */ Aerr,
- /* Rpc */ Apc,
- /* Rmpc */ Aerr,
- /* Rareg */ Aerr,
- /* Ramreg */ Aerr,
- /* Raadr */ Aerr,
- /* Ramadr */ Aerr,
- /* Rldt */ Aldt,
- };
- static Decl *wtemp;
- static Decl *bigtemp;
- static int ntemp;
- static Node retnode;
- static Inst zinst;
- int *blockstack;
- int blockdep;
- int nblocks;
- static int lenblockstack;
- static Node *ntoz;
- static Inst* genfixop(Src *src, int op, Node *s, Node *m, Node *d);
- void
- genstart(void)
- {
- Decl *d;
- d = mkdecl(&nosrc, Dlocal, tint);
- d->sym = enter(".ret", 0);
- d->offset = IBY2WD * REGRET;
- retnode = znode;
- retnode.op = Oname;
- retnode.addable = Rreg;
- retnode.decl = d;
- retnode.ty = tint;
- zinst.op = INOP;
- zinst.sm = Anone;
- zinst.dm = Anone;
- zinst.mm = Anone;
- firstinst = allocmem(sizeof *firstinst);
- *firstinst = zinst;
- lastinst = firstinst;
- blocks = -1;
- blockdep = 0;
- nblocks = 0;
- }
- /*
- * manage nested control flow blocks
- */
- int
- pushblock(void)
- {
- if(blockdep >= lenblockstack){
- lenblockstack = blockdep + 32;
- blockstack = reallocmem(blockstack, lenblockstack * sizeof *blockstack);
- }
- blockstack[blockdep++] = blocks;
- return blocks = nblocks++;
- }
- void
- repushblock(int b)
- {
- blockstack[blockdep++] = blocks;
- blocks = b;
- }
- void
- popblock(void)
- {
- blocks = blockstack[blockdep -= 1];
- }
- void
- tinit(void)
- {
- wtemp = nil;
- bigtemp = nil;
- }
- Decl*
- tdecls(void)
- {
- Decl *d;
- for(d = wtemp; d != nil; d = d->next){
- if(d->tref != 1)
- fatal("temporary %s has %d references", d->sym->name, d->tref-1);
- }
- for(d = bigtemp; d != nil; d = d->next){
- if(d->tref != 1)
- fatal("temporary %s has %d references", d->sym->name, d->tref-1);
- }
- return appdecls(wtemp, bigtemp);
- }
- Node*
- talloc(Node *n, Type *t, Node *nok)
- {
- Decl *d, *ok;
- Desc *desc;
- char buf[StrSize];
- ok = nil;
- if(nok != nil)
- ok = nok->decl;
- if(ok == nil || ok->tref == 0 || tattr[ok->ty->kind].big != tattr[t->kind].big || ok->ty->align != t->align)
- ok = nil;
- *n = znode;
- n->op = Oname;
- n->addable = Rreg;
- n->ty = t;
- if(tattr[t->kind].big){
- desc = mktdesc(t);
- if(ok != nil && ok->desc == desc){
- ok->tref++;
- ok->refs++;
- n->decl = ok;
- return n;
- }
- for(d = bigtemp; d != nil; d = d->next){
- if(d->tref == 1 && d->desc == desc && d->ty->align == t->align){
- d->tref++;
- d->refs++;
- n->decl = d;
- return n;
- }
- }
- d = mkdecl(&nosrc, Dlocal, t);
- d->desc = desc;
- d->tref = 2;
- d->refs = 1;
- n->decl = d;
- seprint(buf, buf+sizeof(buf), ".b%d", ntemp++);
- d->sym = enter(buf, 0);
- d->next = bigtemp;
- bigtemp = d;
- return n;
- }
- if(ok != nil
- && tattr[ok->ty->kind].isptr == tattr[t->kind].isptr
- && ok->ty->size == t->size){
- ok->tref++;
- n->decl = ok;
- return n;
- }
- for(d = wtemp; d != nil; d = d->next){
- if(d->tref == 1
- && tattr[d->ty->kind].isptr == tattr[t->kind].isptr
- && d->ty->size == t->size
- && d->ty->align == t->align){
- d->tref++;
- n->decl = d;
- return n;
- }
- }
- d = mkdecl(&nosrc, Dlocal, t);
- d->tref = 2;
- d->refs = 1;
- n->decl = d;
- seprint(buf, buf+sizeof(buf), ".t%d", ntemp++);
- d->sym = enter(buf, 0);
- d->next = wtemp;
- wtemp = d;
- return n;
- }
- void
- tfree(Node *n)
- {
- if(n == nil || n->decl == nil || n->decl->tref == 0)
- return;
- if(n->decl->tref == 1)
- fatal("double free of temporary %s", n->decl->sym->name);
- if (--n->decl->tref == 1)
- zcom1(n, nil);
- }
- void
- tfreelater(Node *n)
- {
- if(n == nil || n->decl == nil || n->decl->tref == 0)
- return;
- if(n->decl->tref == 1)
- fatal("double free of temporary %s", n->decl->sym->name);
- if(--n->decl->tref == 1){
- Node *nn = mkn(Oname, nil, nil);
- *nn = *n;
- nn->left = ntoz;
- ntoz = nn;
- n->decl->tref++;
- }
- }
- void
- tfreenow()
- {
- Node *n, *nn;
- for(n = ntoz; n != nil; n = nn){
- nn = n->left;
- n->left = nil;
- if(n->decl->tref != 2)
- fatal("bad free of temporary %s", n->decl->sym->name);
- --n->decl->tref;
- zcom1(n, nil);
- }
- ntoz = nil;
- }
- /*
- * realloc a temporary after it's been freed
- */
- Node*
- tacquire(Node *n)
- {
- if(n == nil || n->decl == nil || n->decl->tref == 0)
- return n;
- /*
- if(n->decl->tref != 1)
- fatal("tacquire ref != 1: %d", n->decl->tref);
- */
- n->decl->tref++;
- return n;
- }
- void
- trelease(Node *n)
- {
- if(n == nil || n->decl == nil || n->decl->tref == 0)
- return;
- if(n->decl->tref == 1)
- fatal("double release of temporary %s", n->decl->sym->name);
- n->decl->tref--;
- }
- Inst*
- mkinst(void)
- {
- Inst *in;
- in = lastinst->next;
- if(in == nil){
- in = allocmem(sizeof *in);
- *in = zinst;
- lastinst->next = in;
- }
- lastinst = in;
- in->block = blocks;
- if(blocks < 0)
- fatal("mkinst no block");
- return in;
- }
- Inst*
- nextinst(void)
- {
- Inst *in;
- in = lastinst->next;
- if(in != nil)
- return in;
- in = allocmem(sizeof(*in));
- *in = zinst;
- lastinst->next = in;
- return in;
- }
- /*
- * allocate a node for returning
- */
- Node*
- retalloc(Node *n, Node *nn)
- {
- if(nn->ty == tnone)
- return nil;
- *n = znode;
- n->op = Oind;
- n->addable = Radr;
- n->left = dupn(1, &n->src, &retnode);
- n->ty = nn->ty;
- return n;
- }
- Inst*
- genrawop(Src *src, int op, Node *s, Node *m, Node *d)
- {
- Inst *in;
- in = mkinst();
- in->op = op;
- in->src = *src;
- if(in->sm != Anone || in->mm != Anone || in->dm != Anone)
- fatal("bogus mkinst in genrawop: %I\n", in);
- if(s != nil){
- in->s = genaddr(s);
- in->sm = addrmode[s->addable];
- }
- if(m != nil){
- in->m = genaddr(m);
- in->mm = addrmode[m->addable];
- if(in->mm == Ampind || in->mm == Afpind)
- fatal("illegal addressing mode in register %n", m);
- }
- if(d != nil){
- in->d = genaddr(d);
- in->dm = addrmode[d->addable];
- }
- return in;
- }
- Inst*
- genop(Src *src, int op, Node *s, Node *m, Node *d)
- {
- Inst *in;
- int iop;
- iop = disoptab[op][opind[d->ty->kind]];
- if(iop == 0)
- fatal("can't deal with op %s on %n %n %n in genop", opname[op], s, m, d);
- if(iop == IMULX || iop == IDIVX)
- return genfixop(src, iop, s, m, d);
- in = mkinst();
- in->op = iop;
- in->src = *src;
- if(s != nil){
- in->s = genaddr(s);
- in->sm = addrmode[s->addable];
- }
- if(m != nil){
- in->m = genaddr(m);
- in->mm = addrmode[m->addable];
- if(in->mm == Ampind || in->mm == Afpind)
- fatal("illegal addressing mode in register %n", m);
- }
- if(d != nil){
- in->d = genaddr(d);
- in->dm = addrmode[d->addable];
- }
- return in;
- }
- Inst*
- genbra(Src *src, int op, Node *s, Node *m)
- {
- Type *t;
- Inst *in;
- int iop;
- t = s->ty;
- if(t == tany)
- t = m->ty;
- iop = disoptab[op][opind[t->kind]];
- if(iop == 0)
- fatal("can't deal with op %s on %n %n in genbra", opname[op], s, m);
- in = mkinst();
- in->op = iop;
- in->src = *src;
- if(s != nil){
- in->s = genaddr(s);
- in->sm = addrmode[s->addable];
- }
- if(m != nil){
- in->m = genaddr(m);
- in->mm = addrmode[m->addable];
- if(in->mm == Ampind || in->mm == Afpind)
- fatal("illegal addressing mode in register %n", m);
- }
- return in;
- }
- Inst*
- genchan(Src *src, Node *sz, Type *mt, Node *d)
- {
- Inst *in;
- Desc *td;
- Addr reg;
- int op, regm;
- regm = Anone;
- reg.decl = nil;
- reg.reg = 0;
- reg.offset = 0;
- op = chantab[mt->kind];
- if(op == 0)
- fatal("can't deal with op %d in genchan", mt->kind);
- switch(mt->kind){
- case Tadt:
- case Tadtpick:
- case Ttuple:
- td = mktdesc(mt);
- if(td->nmap != 0){
- op++; /* sleazy */
- usedesc(td);
- regm = Adesc;
- reg.decl = mt->decl;
- }else{
- regm = Aimm;
- reg.offset = mt->size;
- }
- break;
- }
- in = mkinst();
- in->op = op;
- in->src = *src;
- in->s = reg;
- in->sm = regm;
- if(sz != nil){
- in->m = genaddr(sz);
- in->mm = addrmode[sz->addable];
- }
- if(d != nil){
- in->d = genaddr(d);
- in->dm = addrmode[d->addable];
- }
- return in;
- }
- Inst*
- genmove(Src *src, int how, Type *mt, Node *s, Node *d)
- {
- Inst *in;
- Desc *td;
- Addr reg;
- int op, regm;
- regm = Anone;
- reg.decl = nil;
- reg.reg = 0;
- reg.offset = 0;
- op = movetab[how][mt->kind];
- if(op == 0)
- fatal("can't deal with op %d on %n %n in genmove", how, s, d);
- switch(mt->kind){
- case Tadt:
- case Tadtpick:
- case Ttuple:
- case Texception:
- if(mt->size == 0 && how == Mas)
- return nil;
- td = mktdesc(mt);
- if(td->nmap != 0){
- op++; /* sleazy */
- usedesc(td);
- regm = Adesc;
- reg.decl = mt->decl;
- }else{
- regm = Aimm;
- reg.offset = mt->size;
- }
- break;
- }
- in = mkinst();
- in->op = op;
- in->src = *src;
- if(s != nil){
- in->s = genaddr(s);
- in->sm = addrmode[s->addable];
- }
- in->m = reg;
- in->mm = regm;
- if(d != nil){
- in->d = genaddr(d);
- in->dm = addrmode[d->addable];
- }
- if(s->addable == Rpc)
- in->op = IMOVPC;
- return in;
- }
- void
- patch(Inst *b, Inst *dst)
- {
- Inst *n;
- for(; b != nil; b = n){
- n = b->branch;
- b->branch = dst;
- }
- }
- long
- getpc(Inst *i)
- {
- if(i->pc == 0 && i != firstinst && (firstinst->op != INOOP || i != firstinst->next)){
- do
- i = i->next;
- while(i != nil && i->pc == 0);
- if(i == nil || i->pc == 0)
- fatal("bad instruction in getpc");
- }
- return i->pc;
- }
- /*
- * follow all possible paths from n,
- * marking reached code, compressing branches, and reclaiming unreached insts
- */
- void
- reach(Inst *in)
- {
- Inst *last;
- foldbranch(in);
- last = in;
- for(in = in->next; in != nil; in = in->next){
- if(!in->reach)
- last->next = in->next;
- else
- last = in;
- }
- lastinst = last;
- }
- /*
- * follow all possible paths from n,
- * marking reached code, compressing branches, and eliminating tail recursion
- */
- void
- foldbranch(Inst *in)
- {
- Inst *b, *next;
- Label *lab;
- int i, n;
- while(in != nil && !in->reach){
- in->reach = 1;
- if(in->branch != nil)
- while(in->branch->op == IJMP){
- if(in == in->branch || in->branch == in->branch->branch)
- break;
- in->branch = in->branch->branch;
- }
- switch(in->op){
- case IGOTO:
- case ICASE:
- case ICASEL:
- case ICASEC:
- case IEXC:
- foldbranch(in->d.decl->ty->cse->iwild);
- lab = in->d.decl->ty->cse->labs;
- n = in->d.decl->ty->cse->nlab;
- for(i = 0; i < n; i++)
- foldbranch(lab[i].inst);
- if(in->op == IEXC)
- in->op = INOOP;
- return;
- case IEXC0:
- foldbranch(in->branch);
- in->op = INOOP;
- break;
- case IRET:
- case IEXIT:
- case IRAISE:
- return;
- case IJMP:
- b = in->branch;
- switch(b->op){
- case ICASE:
- case ICASEL:
- case ICASEC:
- case IRET:
- case IEXIT:
- next = in->next;
- *in = *b;
- in->next = next;
- continue;
- }
- foldbranch(b);
- return;
- default:
- if(in->branch != nil)
- foldbranch(in->branch);
- break;
- }
- in = in->next;
- }
- }
- /*
- * convert the addressable node into an operand
- * see the comment for sumark
- */
- Addr
- genaddr(Node *n)
- {
- Addr a;
- a.reg = 0;
- a.offset = 0;
- a.decl = nil;
- if(n == nil)
- return a;
- switch(n->addable){
- case Rreg:
- if(n->decl != nil)
- a.decl = n->decl;
- else
- a = genaddr(n->left);
- break;
- case Rmreg:
- if(n->decl != nil)
- a.decl = n->decl;
- else
- a = genaddr(n->left);
- break;
- case Rdesc:
- a.decl = n->ty->decl;
- break;
- case Roff:
- case Rnoff:
- a.decl = n->decl;
- break;
- case Rconst:
- a.offset = n->val;
- break;
- case Radr:
- a = genaddr(n->left);
- break;
- case Rmadr:
- a = genaddr(n->left);
- break;
- case Rareg:
- case Ramreg:
- a = genaddr(n->left);
- if(n->op == Oadd)
- a.reg += n->right->val;
- break;
- case Raadr:
- case Ramadr:
- a = genaddr(n->left);
- if(n->op == Oadd)
- a.offset += n->right->val;
- break;
- case Rldt:
- a.decl = n->decl;
- break;
- case Rdescp:
- case Rpc:
- a.decl = n->decl;
- break;
- default:
- fatal("can't deal with %n in genaddr", n);
- break;
- }
- return a;
- }
- int
- sameaddr(Node *n, Node *m)
- {
- Addr a, b;
- if(n->addable != m->addable)
- return 0;
- a = genaddr(n);
- b = genaddr(m);
- return a.offset == b.offset && a.reg == b.reg && a.decl == b.decl;
- }
- long
- resolvedesc(Decl *mod, long length, Decl *decls)
- {
- Desc *g, *d, *last;
- int descid;
- g = gendesc(mod, length, decls);
- g->used = 0;
- last = nil;
- for(d = descriptors; d != nil; d = d->next){
- if(!d->used){
- if(last != nil)
- last->next = d->next;
- else
- descriptors = d->next;
- continue;
- }
- last = d;
- }
- g->next = descriptors;
- descriptors = g;
- descid = 0;
- for(d = descriptors; d != nil; d = d->next)
- d->id = descid++;
- if(g->id != 0)
- fatal("bad global descriptor id");
- return descid;
- }
- int
- resolvemod(Decl *m)
- {
- Decl *id, *d;
- for(id = m->ty->ids; id != nil; id = id->next){
- switch(id->store){
- case Dfn:
- id->iface->pc = id->pc;
- id->iface->desc = id->desc;
- if(debug['v']) print("R1: %s %p %p %p\n", id->sym->name, id, id->iface, id->pc);
- break;
- case Dtype:
- if(id->ty->kind != Tadt)
- break;
- for(d = id->ty->ids; d != nil; d = d->next){
- if(d->store == Dfn){
- d->iface->pc = d->pc;
- d->iface->desc = d->desc;
- if(debug['v']) print("R2: %s %p %p %p\n", d->sym->name, d, d->iface, d->pc);
- }
- }
- break;
- }
- }
- /* for addiface */
- for(id = m->ty->tof->ids; id != nil; id = id->next){
- if(id->store == Dfn){
- if(id->pc == nil)
- id->pc = id->iface->pc;
- if(id->desc == nil)
- id->desc = id->iface->desc;
- if(debug['v']) print("R3: %s %p %p %p\n", id->sym->name, id, id->iface, id->pc);
- }
- }
- return m->ty->tof->decl->init->val;
- }
- /*
- * place the Tiface decs in another list
- */
- Decl*
- resolveldts(Decl *d, Decl **dd)
- {
- Decl *d1, *ld1, *d2, *ld2, *n;
- d1 = d2 = nil;
- ld1 = ld2 = nil;
- for( ; d != nil; d = n){
- n = d->next;
- d->next = nil;
- if(d->ty->kind == Tiface){
- if(d2 == nil)
- d2 = d;
- else
- ld2->next = d;
- ld2 = d;
- }
- else{
- if(d1 == nil)
- d1 = d;
- else
- ld1->next = d;
- ld1 = d;
- }
- }
- *dd = d2;
- return d1;
- }
- /*
- * fix up all pc's
- * finalize all data offsets
- * fix up instructions with offsets too large
- */
- long
- resolvepcs(Inst *inst)
- {
- Decl *d;
- Inst *in;
- int op;
- ulong r, off;
- long v, pc;
- pc = 0;
- for(in = inst; in != nil; in = in->next){
- if(!in->reach || in->op == INOP)
- fatal("unreachable pc: %I %ld", in, pc);
- if(in->op == INOOP){
- in->pc = pc;
- continue;
- }
- d = in->s.decl;
- if(d != nil){
- if(in->sm == Adesc){
- if(d->desc != nil)
- in->s.offset = d->desc->id;
- }else
- in->s.reg += d->offset;
- }
- r = in->s.reg;
- off = in->s.offset;
- if((in->sm == Afpind || in->sm == Ampind)
- && (r >= MaxReg || off >= MaxReg))
- fatal("big offset in %I\n", in);
- d = in->m.decl;
- if(d != nil){
- if(in->mm == Adesc){
- if(d->desc != nil)
- in->m.offset = d->desc->id;
- }else
- in->m.reg += d->offset;
- }
- v = 0;
- switch(in->mm){
- case Anone:
- break;
- case Aimm:
- case Apc:
- case Adesc:
- v = in->m.offset;
- break;
- case Aoff:
- case Anoff:
- v = in->m.decl->iface->offset;
- break;
- case Afp:
- case Amp:
- case Aldt:
- v = in->m.reg;
- if(v < 0)
- v = 0x8000;
- break;
- default:
- fatal("can't deal with %I's m mode\n", in);
- break;
- }
- if(v > 0x7fff || v < -0x8000){
- switch(in->op){
- case IALT:
- case IINDX:
- warn(in->src.start, "possible bug: temp m too big in %I: %ld %ld %d\n", in, in->m.reg, in->m.reg, MaxReg);
- rewritedestreg(in, IMOVW, RTemp);
- break;
- default:
- op = IMOVW;
- if(isbyteinst[in->op])
- op = IMOVB;
- in = rewritesrcreg(in, op, RTemp, pc++);
- break;
- }
- }
- d = in->d.decl;
- if(d != nil){
- if(in->dm == Apc)
- in->d.offset = d->pc->pc;
- else
- in->d.reg += d->offset;
- }
- r = in->d.reg;
- off = in->d.offset;
- if((in->dm == Afpind || in->dm == Ampind)
- && (r >= MaxReg || off >= MaxReg))
- fatal("big offset in %I\n", in);
- in->pc = pc;
- pc++;
- }
- for(in = inst; in != nil; in = in->next){
- d = in->s.decl;
- if(d != nil && in->sm == Apc)
- in->s.offset = d->pc->pc;
- d = in->d.decl;
- if(d != nil && in->dm == Apc)
- in->d.offset = d->pc->pc;
- if(in->branch != nil){
- in->dm = Apc;
- in->d.offset = in->branch->pc;
- }
- }
- return pc;
- }
- /*
- * fixp up a big register constant uses as a source
- * ugly: smashes the instruction
- */
- Inst*
- rewritesrcreg(Inst *in, int op, int treg, int pc)
- {
- Inst *new;
- Addr a;
- int am;
- a = in->m;
- am = in->mm;
- in->mm = Afp;
- in->m.reg = treg;
- in->m.decl = nil;
- new = allocmem(sizeof(*in));
- *new = *in;
- *in = zinst;
- in->src = new->src;
- in->next = new;
- in->op = op;
- in->s = a;
- in->sm = am;
- in->dm = Afp;
- in->d.reg = treg;
- in->pc = pc;
- in->reach = 1;
- in->block = new->block;
- return new;
- }
- /*
- * fix up a big register constant by moving to the destination
- * after the instruction completes
- */
- Inst*
- rewritedestreg(Inst *in, int op, int treg)
- {
- Inst *n;
- n = allocmem(sizeof(*n));
- *n = zinst;
- n->next = in->next;
- in->next = n;
- n->src = in->src;
- n->op = op;
- n->sm = Afp;
- n->s.reg = treg;
- n->d = in->m;
- n->dm = in->mm;
- n->reach = 1;
- n->block = in->block;
- in->mm = Afp;
- in->m.reg = treg;
- in->m.decl = nil;
- return n;
- }
- int
- instconv(Fmt *f)
- {
- Inst *in;
- char buf[512], *p;
- char *op, *comma;
- in = va_arg(f->args, Inst*);
- op = nil;
- if(in->op < MAXDIS)
- op = instname[in->op];
- if(op == nil)
- op = "??";
- buf[0] = '\0';
- if(in->op == INOP)
- return fmtstrcpy(f, "\tnop");
- p = seprint(buf, buf + sizeof(buf), "\t%s\t", op);
- comma = "";
- if(in->sm != Anone){
- p = addrprint(p, buf + sizeof(buf), in->sm, &in->s);
- comma = ",";
- }
- if(in->mm != Anone){
- p = seprint(p, buf + sizeof(buf), "%s", comma);
- p = addrprint(p, buf + sizeof(buf), in->mm, &in->m);
- comma = ",";
- }
- if(in->dm != Anone){
- p = seprint(p, buf + sizeof(buf), "%s", comma);
- p = addrprint(p, buf + sizeof(buf), in->dm, &in->d);
- }
-
- if(asmsym && in->s.decl != nil && in->sm == Adesc)
- p = seprint(p, buf+sizeof(buf), " #%D", in->s.decl);
- if(0 && asmsym && in->m.decl != nil)
- p = seprint(p, buf+sizeof(buf), " #%D", in->m.decl);
- if(asmsym && in->d.decl != nil && in->dm == Apc)
- p = seprint(p, buf+sizeof(buf), " #%D", in->d.decl);
- if(asmsym)
- p = seprint(p, buf+sizeof(buf), " #%U", in->src);
- USED(p);
- return fmtstrcpy(f, buf);
- }
- char*
- addrprint(char *buf, char *end, int am, Addr *a)
- {
- switch(am){
- case Anone:
- return buf;
- case Aimm:
- case Apc:
- case Adesc:
- return seprint(buf, end, "$%ld", a->offset);
- case Aoff:
- return seprint(buf, end, "$%ld", a->decl->iface->offset);
- case Anoff:
- return seprint(buf, end, "-$%ld", a->decl->iface->offset);
- case Afp:
- return seprint(buf, end, "%ld(fp)", a->reg);
- case Afpind:
- return seprint(buf, end, "%ld(%ld(fp))", a->offset, a->reg);
- case Amp:
- return seprint(buf, end, "%ld(mp)", a->reg);
- case Ampind:
- return seprint(buf, end, "%ld(%ld(mp))", a->offset, a->reg);
- case Aldt:
- return seprint(buf, end, "$%ld", a->reg);
- case Aerr:
- default:
- return seprint(buf, end, "%ld(%ld(?%d?))", a->offset, a->reg, am);
- }
- }
- static void
- genstore(Src *src, Node *n, int offset)
- {
- Decl *de;
- Node d;
- de = mkdecl(&nosrc, Dlocal, tint);
- de->sym = nil;
- de->offset = offset;
- d = znode;
- d.op = Oname;
- d.addable = Rreg;
- d.decl = de;
- d.ty = tint;
- genrawop(src, IMOVW, n, nil, &d);
- }
- static Inst*
- genfixop(Src *src, int op, Node *s, Node *m, Node *d)
- {
- int p, a;
- Node *mm;
- Inst *i;
- mm = m ? m: d;
- op = fixop(op, mm->ty, s->ty, d->ty, &p, &a);
- if(op == IMOVW){ /* just zero d */
- s = sumark(mkconst(src, 0));
- return genrawop(src, op, s, nil, d);
- }
- if(op != IMULX && op != IDIVX)
- genstore(src, sumark(mkconst(src, a)), STemp);
- genstore(src, sumark(mkconst(src, p)), DTemp);
- i = genrawop(src, op, s, m, d);
- return i;
- }
- Inst*
- genfixcastop(Src *src, int op, Node *s, Node *d)
- {
- int p, a;
- Node *m;
- op = fixop(op, s->ty, tint, d->ty, &p, &a);
- if(op == IMOVW){ /* just zero d */
- s = sumark(mkconst(src, 0));
- return genrawop(src, op, s, nil, d);
- }
- m = sumark(mkconst(src, p));
- if(op != ICVTXX)
- genstore(src, sumark(mkconst(src, a)), STemp);
- return genrawop(src, op, s, m, d);
- }
|