1 #include "limbo.h"
2
3 static int addrmode[Rend] =
4 {
5 /* Rreg */ Afp,
6 /* Rmreg */ Amp,
7 /* Roff */ Aoff,
8 /* Rnoff */ Anoff,
9 /* Rdesc */ Adesc,
10 /* Rdescp */ Adesc,
11 /* Rconst */ Aimm,
12 /* Ralways */ Aerr,
13 /* Radr */ Afpind,
14 /* Rmadr */ Ampind,
15 /* Rcant */ Aerr,
16 /* Rpc */ Apc,
17 /* Rmpc */ Aerr,
18 /* Rareg */ Aerr,
19 /* Ramreg */ Aerr,
20 /* Raadr */ Aerr,
21 /* Ramadr */ Aerr,
22 /* Rldt */ Aldt,
23 };
24
25 static Decl *wtemp;
26 static Decl *bigtemp;
27 static int ntemp;
28 static Node retnode;
29 static Inst zinst;
30
31 int *blockstack;
32 int blockdep;
33 int nblocks;
34 static int lenblockstack;
35 static Node *ntoz;
36
37 static Inst* genfixop(Src *src, int op, Node *s, Node *m, Node *d);
38
39 void
genstart(void)40 genstart(void)
41 {
42 Decl *d;
43
44 d = mkdecl(&nosrc, Dlocal, tint);
45 d->sym = enter(".ret", 0);
46 d->offset = IBY2WD * REGRET;
47
48 retnode = znode;
49 retnode.op = Oname;
50 retnode.addable = Rreg;
51 retnode.decl = d;
52 retnode.ty = tint;
53
54 zinst.op = INOP;
55 zinst.sm = Anone;
56 zinst.dm = Anone;
57 zinst.mm = Anone;
58
59 firstinst = allocmem(sizeof *firstinst);
60 *firstinst = zinst;
61 lastinst = firstinst;
62
63 blocks = -1;
64 blockdep = 0;
65 nblocks = 0;
66 }
67
68 /*
69 * manage nested control flow blocks
70 */
71 int
pushblock(void)72 pushblock(void)
73 {
74 if(blockdep >= lenblockstack){
75 lenblockstack = blockdep + 32;
76 blockstack = reallocmem(blockstack, lenblockstack * sizeof *blockstack);
77 }
78 blockstack[blockdep++] = blocks;
79 return blocks = nblocks++;
80 }
81
82 void
repushblock(int b)83 repushblock(int b)
84 {
85 blockstack[blockdep++] = blocks;
86 blocks = b;
87 }
88
89 void
popblock(void)90 popblock(void)
91 {
92 blocks = blockstack[blockdep -= 1];
93 }
94
95 void
tinit(void)96 tinit(void)
97 {
98 wtemp = nil;
99 bigtemp = nil;
100 }
101
102 Decl*
tdecls(void)103 tdecls(void)
104 {
105 Decl *d;
106
107 for(d = wtemp; d != nil; d = d->next){
108 if(d->tref != 1)
109 fatal("temporary %s has %d references", d->sym->name, d->tref-1);
110 }
111
112 for(d = bigtemp; d != nil; d = d->next){
113 if(d->tref != 1)
114 fatal("temporary %s has %d references", d->sym->name, d->tref-1);
115 }
116
117 return appdecls(wtemp, bigtemp);
118 }
119
120 Node*
talloc(Node * n,Type * t,Node * nok)121 talloc(Node *n, Type *t, Node *nok)
122 {
123 Decl *d, *ok;
124 Desc *desc;
125 char buf[StrSize];
126
127 ok = nil;
128 if(nok != nil)
129 ok = nok->decl;
130 if(ok == nil || ok->tref == 0 || tattr[ok->ty->kind].big != tattr[t->kind].big || ok->ty->align != t->align)
131 ok = nil;
132 *n = znode;
133 n->op = Oname;
134 n->addable = Rreg;
135 n->ty = t;
136 if(tattr[t->kind].big){
137 desc = mktdesc(t);
138 if(ok != nil && ok->desc == desc){
139 ok->tref++;
140 ok->refs++;
141 n->decl = ok;
142 return n;
143 }
144 for(d = bigtemp; d != nil; d = d->next){
145 if(d->tref == 1 && d->desc == desc && d->ty->align == t->align){
146 d->tref++;
147 d->refs++;
148 n->decl = d;
149 return n;
150 }
151 }
152 d = mkdecl(&nosrc, Dlocal, t);
153 d->desc = desc;
154 d->tref = 2;
155 d->refs = 1;
156 n->decl = d;
157 seprint(buf, buf+sizeof(buf), ".b%d", ntemp++);
158 d->sym = enter(buf, 0);
159 d->next = bigtemp;
160 bigtemp = d;
161 return n;
162 }
163 if(ok != nil
164 && tattr[ok->ty->kind].isptr == tattr[t->kind].isptr
165 && ok->ty->size == t->size){
166 ok->tref++;
167 n->decl = ok;
168 return n;
169 }
170 for(d = wtemp; d != nil; d = d->next){
171 if(d->tref == 1
172 && tattr[d->ty->kind].isptr == tattr[t->kind].isptr
173 && d->ty->size == t->size
174 && d->ty->align == t->align){
175 d->tref++;
176 n->decl = d;
177 return n;
178 }
179 }
180 d = mkdecl(&nosrc, Dlocal, t);
181 d->tref = 2;
182 d->refs = 1;
183 n->decl = d;
184 seprint(buf, buf+sizeof(buf), ".t%d", ntemp++);
185 d->sym = enter(buf, 0);
186 d->next = wtemp;
187 wtemp = d;
188 return n;
189 }
190
191 void
tfree(Node * n)192 tfree(Node *n)
193 {
194 if(n == nil || n->decl == nil || n->decl->tref == 0)
195 return;
196 if(n->decl->tref == 1)
197 fatal("double free of temporary %s", n->decl->sym->name);
198 if (--n->decl->tref == 1)
199 zcom1(n, nil);
200 }
201
202 void
tfreelater(Node * n)203 tfreelater(Node *n)
204 {
205 if(n == nil || n->decl == nil || n->decl->tref == 0)
206 return;
207 if(n->decl->tref == 1)
208 fatal("double free of temporary %s", n->decl->sym->name);
209 if(--n->decl->tref == 1){
210 Node *nn = mkn(Oname, nil, nil);
211
212 *nn = *n;
213 nn->left = ntoz;
214 ntoz = nn;
215 n->decl->tref++;
216 }
217 }
218
219 void
tfreenow()220 tfreenow()
221 {
222 Node *n, *nn;
223
224 for(n = ntoz; n != nil; n = nn){
225 nn = n->left;
226 n->left = nil;
227 if(n->decl->tref != 2)
228 fatal("bad free of temporary %s", n->decl->sym->name);
229 --n->decl->tref;
230 zcom1(n, nil);
231 }
232 ntoz = nil;
233 }
234
235 /*
236 * realloc a temporary after it's been freed
237 */
238 Node*
tacquire(Node * n)239 tacquire(Node *n)
240 {
241 if(n == nil || n->decl == nil || n->decl->tref == 0)
242 return n;
243 /*
244 if(n->decl->tref != 1)
245 fatal("tacquire ref != 1: %d", n->decl->tref);
246 */
247 n->decl->tref++;
248 return n;
249 }
250
251 void
trelease(Node * n)252 trelease(Node *n)
253 {
254 if(n == nil || n->decl == nil || n->decl->tref == 0)
255 return;
256 if(n->decl->tref == 1)
257 fatal("double release of temporary %s", n->decl->sym->name);
258 n->decl->tref--;
259 }
260
261 Inst*
mkinst(void)262 mkinst(void)
263 {
264 Inst *in;
265
266 in = lastinst->next;
267 if(in == nil){
268 in = allocmem(sizeof *in);
269 *in = zinst;
270 lastinst->next = in;
271 }
272 lastinst = in;
273 in->block = blocks;
274 if(blocks < 0)
275 fatal("mkinst no block");
276 return in;
277 }
278
279 Inst*
nextinst(void)280 nextinst(void)
281 {
282 Inst *in;
283
284 in = lastinst->next;
285 if(in != nil)
286 return in;
287 in = allocmem(sizeof(*in));
288 *in = zinst;
289 lastinst->next = in;
290 return in;
291 }
292
293 /*
294 * allocate a node for returning
295 */
296 Node*
retalloc(Node * n,Node * nn)297 retalloc(Node *n, Node *nn)
298 {
299 if(nn->ty == tnone)
300 return nil;
301 *n = znode;
302 n->op = Oind;
303 n->addable = Radr;
304 n->left = dupn(1, &n->src, &retnode);
305 n->ty = nn->ty;
306 return n;
307 }
308
309 Inst*
genrawop(Src * src,int op,Node * s,Node * m,Node * d)310 genrawop(Src *src, int op, Node *s, Node *m, Node *d)
311 {
312 Inst *in;
313
314 in = mkinst();
315 in->op = op;
316 in->src = *src;
317 if(in->sm != Anone || in->mm != Anone || in->dm != Anone)
318 fatal("bogus mkinst in genrawop: %I\n", in);
319 if(s != nil){
320 in->s = genaddr(s);
321 in->sm = addrmode[s->addable];
322 }
323 if(m != nil){
324 in->m = genaddr(m);
325 in->mm = addrmode[m->addable];
326 if(in->mm == Ampind || in->mm == Afpind)
327 fatal("illegal addressing mode in register %n", m);
328 }
329 if(d != nil){
330 in->d = genaddr(d);
331 in->dm = addrmode[d->addable];
332 }
333 return in;
334 }
335
336 Inst*
genop(Src * src,int op,Node * s,Node * m,Node * d)337 genop(Src *src, int op, Node *s, Node *m, Node *d)
338 {
339 Inst *in;
340 int iop;
341
342 iop = disoptab[op][opind[d->ty->kind]];
343 if(iop == 0)
344 fatal("can't deal with op %s on %n %n %n in genop", opname[op], s, m, d);
345 if(iop == IMULX || iop == IDIVX)
346 return genfixop(src, iop, s, m, d);
347 in = mkinst();
348 in->op = iop;
349 in->src = *src;
350 if(s != nil){
351 in->s = genaddr(s);
352 in->sm = addrmode[s->addable];
353 }
354 if(m != nil){
355 in->m = genaddr(m);
356 in->mm = addrmode[m->addable];
357 if(in->mm == Ampind || in->mm == Afpind)
358 fatal("illegal addressing mode in register %n", m);
359 }
360 if(d != nil){
361 in->d = genaddr(d);
362 in->dm = addrmode[d->addable];
363 }
364 return in;
365 }
366
367 Inst*
genbra(Src * src,int op,Node * s,Node * m)368 genbra(Src *src, int op, Node *s, Node *m)
369 {
370 Type *t;
371 Inst *in;
372 int iop;
373
374 t = s->ty;
375 if(t == tany)
376 t = m->ty;
377 iop = disoptab[op][opind[t->kind]];
378 if(iop == 0)
379 fatal("can't deal with op %s on %n %n in genbra", opname[op], s, m);
380 in = mkinst();
381 in->op = iop;
382 in->src = *src;
383 if(s != nil){
384 in->s = genaddr(s);
385 in->sm = addrmode[s->addable];
386 }
387 if(m != nil){
388 in->m = genaddr(m);
389 in->mm = addrmode[m->addable];
390 if(in->mm == Ampind || in->mm == Afpind)
391 fatal("illegal addressing mode in register %n", m);
392 }
393 return in;
394 }
395
396 Inst*
genchan(Src * src,Node * sz,Type * mt,Node * d)397 genchan(Src *src, Node *sz, Type *mt, Node *d)
398 {
399 Inst *in;
400 Desc *td;
401 Addr reg;
402 int op, regm;
403
404 regm = Anone;
405 reg.decl = nil;
406 reg.reg = 0;
407 reg.offset = 0;
408 op = chantab[mt->kind];
409 if(op == 0)
410 fatal("can't deal with op %d in genchan", mt->kind);
411
412 switch(mt->kind){
413 case Tadt:
414 case Tadtpick:
415 case Ttuple:
416 td = mktdesc(mt);
417 if(td->nmap != 0){
418 op++; /* sleazy */
419 usedesc(td);
420 regm = Adesc;
421 reg.decl = mt->decl;
422 }else{
423 regm = Aimm;
424 reg.offset = mt->size;
425 }
426 break;
427 }
428 in = mkinst();
429 in->op = op;
430 in->src = *src;
431 in->s = reg;
432 in->sm = regm;
433 if(sz != nil){
434 in->m = genaddr(sz);
435 in->mm = addrmode[sz->addable];
436 }
437 if(d != nil){
438 in->d = genaddr(d);
439 in->dm = addrmode[d->addable];
440 }
441 return in;
442 }
443
444 Inst*
genmove(Src * src,int how,Type * mt,Node * s,Node * d)445 genmove(Src *src, int how, Type *mt, Node *s, Node *d)
446 {
447 Inst *in;
448 Desc *td;
449 Addr reg;
450 int op, regm;
451
452 regm = Anone;
453 reg.decl = nil;
454 reg.reg = 0;
455 reg.offset = 0;
456 op = movetab[how][mt->kind];
457 if(op == 0)
458 fatal("can't deal with op %d on %n %n in genmove", how, s, d);
459
460 switch(mt->kind){
461 case Tadt:
462 case Tadtpick:
463 case Ttuple:
464 case Texception:
465 if(mt->size == 0 && how == Mas)
466 return nil;
467 td = mktdesc(mt);
468 if(td->nmap != 0){
469 op++; /* sleazy */
470 usedesc(td);
471 regm = Adesc;
472 reg.decl = mt->decl;
473 }else{
474 regm = Aimm;
475 reg.offset = mt->size;
476 }
477 break;
478 }
479 in = mkinst();
480 in->op = op;
481 in->src = *src;
482 if(s != nil){
483 in->s = genaddr(s);
484 in->sm = addrmode[s->addable];
485 }
486 in->m = reg;
487 in->mm = regm;
488 if(d != nil){
489 in->d = genaddr(d);
490 in->dm = addrmode[d->addable];
491 }
492 if(s->addable == Rpc)
493 in->op = IMOVPC;
494 return in;
495 }
496
497 void
patch(Inst * b,Inst * dst)498 patch(Inst *b, Inst *dst)
499 {
500 Inst *n;
501
502 for(; b != nil; b = n){
503 n = b->branch;
504 b->branch = dst;
505 }
506 }
507
508 long
getpc(Inst * i)509 getpc(Inst *i)
510 {
511 if(i->pc == 0 && i != firstinst && (firstinst->op != INOOP || i != firstinst->next)){
512 do
513 i = i->next;
514 while(i != nil && i->pc == 0);
515 if(i == nil || i->pc == 0)
516 fatal("bad instruction in getpc");
517 }
518 return i->pc;
519 }
520
521 /*
522 * follow all possible paths from n,
523 * marking reached code, compressing branches, and reclaiming unreached insts
524 */
525 void
reach(Inst * in)526 reach(Inst *in)
527 {
528 Inst *last;
529
530 foldbranch(in);
531 last = in;
532 for(in = in->next; in != nil; in = in->next){
533 if(!in->reach)
534 last->next = in->next;
535 else
536 last = in;
537 }
538 lastinst = last;
539 }
540
541 /*
542 * follow all possible paths from n,
543 * marking reached code, compressing branches, and eliminating tail recursion
544 */
545 void
foldbranch(Inst * in)546 foldbranch(Inst *in)
547 {
548 Inst *b, *next;
549 Label *lab;
550 int i, n;
551
552 while(in != nil && !in->reach){
553 in->reach = 1;
554 if(in->branch != nil)
555 while(in->branch->op == IJMP){
556 if(in == in->branch || in->branch == in->branch->branch)
557 break;
558 in->branch = in->branch->branch;
559 }
560 switch(in->op){
561 case IGOTO:
562 case ICASE:
563 case ICASEL:
564 case ICASEC:
565 case IEXC:
566 foldbranch(in->d.decl->ty->cse->iwild);
567 lab = in->d.decl->ty->cse->labs;
568 n = in->d.decl->ty->cse->nlab;
569 for(i = 0; i < n; i++)
570 foldbranch(lab[i].inst);
571 if(in->op == IEXC)
572 in->op = INOOP;
573 return;
574 case IEXC0:
575 foldbranch(in->branch);
576 in->op = INOOP;
577 break;
578 case IRET:
579 case IEXIT:
580 case IRAISE:
581 return;
582 case IJMP:
583 b = in->branch;
584 switch(b->op){
585 case ICASE:
586 case ICASEL:
587 case ICASEC:
588 case IRET:
589 case IEXIT:
590 next = in->next;
591 *in = *b;
592 in->next = next;
593 continue;
594 }
595 foldbranch(b);
596 return;
597 default:
598 if(in->branch != nil)
599 foldbranch(in->branch);
600 break;
601 }
602
603 in = in->next;
604 }
605 }
606
607 /*
608 * convert the addressable node into an operand
609 * see the comment for sumark
610 */
611 Addr
genaddr(Node * n)612 genaddr(Node *n)
613 {
614 Addr a;
615
616 a.reg = 0;
617 a.offset = 0;
618 a.decl = nil;
619 if(n == nil)
620 return a;
621 switch(n->addable){
622 case Rreg:
623 if(n->decl != nil)
624 a.decl = n->decl;
625 else
626 a = genaddr(n->left);
627 break;
628 case Rmreg:
629 if(n->decl != nil)
630 a.decl = n->decl;
631 else
632 a = genaddr(n->left);
633 break;
634 case Rdesc:
635 a.decl = n->ty->decl;
636 break;
637 case Roff:
638 case Rnoff:
639 a.decl = n->decl;
640 break;
641 case Rconst:
642 a.offset = n->val;
643 break;
644 case Radr:
645 a = genaddr(n->left);
646 break;
647 case Rmadr:
648 a = genaddr(n->left);
649 break;
650 case Rareg:
651 case Ramreg:
652 a = genaddr(n->left);
653 if(n->op == Oadd)
654 a.reg += n->right->val;
655 break;
656 case Raadr:
657 case Ramadr:
658 a = genaddr(n->left);
659 if(n->op == Oadd)
660 a.offset += n->right->val;
661 break;
662 case Rldt:
663 a.decl = n->decl;
664 break;
665 case Rdescp:
666 case Rpc:
667 a.decl = n->decl;
668 break;
669 default:
670 fatal("can't deal with %n in genaddr", n);
671 break;
672 }
673 return a;
674 }
675
676 int
sameaddr(Node * n,Node * m)677 sameaddr(Node *n, Node *m)
678 {
679 Addr a, b;
680
681 if(n->addable != m->addable)
682 return 0;
683 a = genaddr(n);
684 b = genaddr(m);
685 return a.offset == b.offset && a.reg == b.reg && a.decl == b.decl;
686 }
687
688 long
resolvedesc(Decl * mod,long length,Decl * decls)689 resolvedesc(Decl *mod, long length, Decl *decls)
690 {
691 Desc *g, *d, *last;
692 int descid;
693
694 g = gendesc(mod, length, decls);
695 g->used = 0;
696 last = nil;
697 for(d = descriptors; d != nil; d = d->next){
698 if(!d->used){
699 if(last != nil)
700 last->next = d->next;
701 else
702 descriptors = d->next;
703 continue;
704 }
705 last = d;
706 }
707
708 g->next = descriptors;
709 descriptors = g;
710
711 descid = 0;
712 for(d = descriptors; d != nil; d = d->next)
713 d->id = descid++;
714 if(g->id != 0)
715 fatal("bad global descriptor id");
716
717 return descid;
718 }
719
720 int
resolvemod(Decl * m)721 resolvemod(Decl *m)
722 {
723 Decl *id, *d;
724
725 for(id = m->ty->ids; id != nil; id = id->next){
726 switch(id->store){
727 case Dfn:
728 id->iface->pc = id->pc;
729 id->iface->desc = id->desc;
730 if(debug['v']) print("R1: %s %p %p %p\n", id->sym->name, id, id->iface, id->pc);
731 break;
732 case Dtype:
733 if(id->ty->kind != Tadt)
734 break;
735 for(d = id->ty->ids; d != nil; d = d->next){
736 if(d->store == Dfn){
737 d->iface->pc = d->pc;
738 d->iface->desc = d->desc;
739 if(debug['v']) print("R2: %s %p %p %p\n", d->sym->name, d, d->iface, d->pc);
740 }
741 }
742 break;
743 }
744 }
745 /* for addiface */
746 for(id = m->ty->tof->ids; id != nil; id = id->next){
747 if(id->store == Dfn){
748 if(id->pc == nil)
749 id->pc = id->iface->pc;
750 if(id->desc == nil)
751 id->desc = id->iface->desc;
752 if(debug['v']) print("R3: %s %p %p %p\n", id->sym->name, id, id->iface, id->pc);
753 }
754 }
755 return m->ty->tof->decl->init->val;
756 }
757
758 /*
759 * place the Tiface decs in another list
760 */
761 Decl*
resolveldts(Decl * d,Decl ** dd)762 resolveldts(Decl *d, Decl **dd)
763 {
764 Decl *d1, *ld1, *d2, *ld2, *n;
765
766 d1 = d2 = nil;
767 ld1 = ld2 = nil;
768 for( ; d != nil; d = n){
769 n = d->next;
770 d->next = nil;
771 if(d->ty->kind == Tiface){
772 if(d2 == nil)
773 d2 = d;
774 else
775 ld2->next = d;
776 ld2 = d;
777 }
778 else{
779 if(d1 == nil)
780 d1 = d;
781 else
782 ld1->next = d;
783 ld1 = d;
784 }
785 }
786 *dd = d2;
787 return d1;
788 }
789
790 /*
791 * fix up all pc's
792 * finalize all data offsets
793 * fix up instructions with offsets too large
794 */
795 long
resolvepcs(Inst * inst)796 resolvepcs(Inst *inst)
797 {
798 Decl *d;
799 Inst *in;
800 int op;
801 ulong r, off;
802 long v, pc;
803
804 pc = 0;
805 for(in = inst; in != nil; in = in->next){
806 if(!in->reach || in->op == INOP)
807 fatal("unreachable pc: %I %ld", in, pc);
808 if(in->op == INOOP){
809 in->pc = pc;
810 continue;
811 }
812 d = in->s.decl;
813 if(d != nil){
814 if(in->sm == Adesc){
815 if(d->desc != nil)
816 in->s.offset = d->desc->id;
817 }else
818 in->s.reg += d->offset;
819 }
820 r = in->s.reg;
821 off = in->s.offset;
822 if((in->sm == Afpind || in->sm == Ampind)
823 && (r >= MaxReg || off >= MaxReg))
824 fatal("big offset in %I\n", in);
825
826 d = in->m.decl;
827 if(d != nil){
828 if(in->mm == Adesc){
829 if(d->desc != nil)
830 in->m.offset = d->desc->id;
831 }else
832 in->m.reg += d->offset;
833 }
834 v = 0;
835 switch(in->mm){
836 case Anone:
837 break;
838 case Aimm:
839 case Apc:
840 case Adesc:
841 v = in->m.offset;
842 break;
843 case Aoff:
844 case Anoff:
845 v = in->m.decl->iface->offset;
846 break;
847 case Afp:
848 case Amp:
849 case Aldt:
850 v = in->m.reg;
851 if(v < 0)
852 v = 0x8000;
853 break;
854
855 default:
856 fatal("can't deal with %I's m mode\n", in);
857 break;
858 }
859 if(v > 0x7fff || v < -0x8000){
860 switch(in->op){
861 case IALT:
862 case IINDX:
863 warn(in->src.start, "possible bug: temp m too big in %I: %ld %ld %d\n", in, in->m.reg, in->m.reg, MaxReg);
864 rewritedestreg(in, IMOVW, RTemp);
865 break;
866 default:
867 op = IMOVW;
868 if(isbyteinst[in->op])
869 op = IMOVB;
870 in = rewritesrcreg(in, op, RTemp, pc++);
871 break;
872 }
873 }
874
875 d = in->d.decl;
876 if(d != nil){
877 if(in->dm == Apc)
878 in->d.offset = d->pc->pc;
879 else
880 in->d.reg += d->offset;
881 }
882 r = in->d.reg;
883 off = in->d.offset;
884 if((in->dm == Afpind || in->dm == Ampind)
885 && (r >= MaxReg || off >= MaxReg))
886 fatal("big offset in %I\n", in);
887
888 in->pc = pc;
889 pc++;
890 }
891 for(in = inst; in != nil; in = in->next){
892 d = in->s.decl;
893 if(d != nil && in->sm == Apc)
894 in->s.offset = d->pc->pc;
895 d = in->d.decl;
896 if(d != nil && in->dm == Apc)
897 in->d.offset = d->pc->pc;
898 if(in->branch != nil){
899 in->dm = Apc;
900 in->d.offset = in->branch->pc;
901 }
902 }
903 return pc;
904 }
905
906 /*
907 * fixp up a big register constant uses as a source
908 * ugly: smashes the instruction
909 */
910 Inst*
rewritesrcreg(Inst * in,int op,int treg,int pc)911 rewritesrcreg(Inst *in, int op, int treg, int pc)
912 {
913 Inst *new;
914 Addr a;
915 int am;
916
917 a = in->m;
918 am = in->mm;
919 in->mm = Afp;
920 in->m.reg = treg;
921 in->m.decl = nil;
922
923 new = allocmem(sizeof(*in));
924 *new = *in;
925
926 *in = zinst;
927 in->src = new->src;
928 in->next = new;
929 in->op = op;
930 in->s = a;
931 in->sm = am;
932 in->dm = Afp;
933 in->d.reg = treg;
934 in->pc = pc;
935 in->reach = 1;
936 in->block = new->block;
937 return new;
938 }
939
940 /*
941 * fix up a big register constant by moving to the destination
942 * after the instruction completes
943 */
944 Inst*
rewritedestreg(Inst * in,int op,int treg)945 rewritedestreg(Inst *in, int op, int treg)
946 {
947 Inst *n;
948
949 n = allocmem(sizeof(*n));
950 *n = zinst;
951 n->next = in->next;
952 in->next = n;
953 n->src = in->src;
954 n->op = op;
955 n->sm = Afp;
956 n->s.reg = treg;
957 n->d = in->m;
958 n->dm = in->mm;
959 n->reach = 1;
960 n->block = in->block;
961
962 in->mm = Afp;
963 in->m.reg = treg;
964 in->m.decl = nil;
965
966 return n;
967 }
968
969 int
instconv(Fmt * f)970 instconv(Fmt *f)
971 {
972 Inst *in;
973 char buf[512], *p;
974 char *op, *comma;
975
976 in = va_arg(f->args, Inst*);
977 op = nil;
978 if(in->op < MAXDIS)
979 op = instname[in->op];
980 if(op == nil)
981 op = "??";
982 buf[0] = '\0';
983 if(in->op == INOP)
984 return fmtstrcpy(f, "\tnop");
985 p = seprint(buf, buf + sizeof(buf), "\t%s\t", op);
986 comma = "";
987 if(in->sm != Anone){
988 p = addrprint(p, buf + sizeof(buf), in->sm, &in->s);
989 comma = ",";
990 }
991 if(in->mm != Anone){
992 p = seprint(p, buf + sizeof(buf), "%s", comma);
993 p = addrprint(p, buf + sizeof(buf), in->mm, &in->m);
994 comma = ",";
995 }
996 if(in->dm != Anone){
997 p = seprint(p, buf + sizeof(buf), "%s", comma);
998 p = addrprint(p, buf + sizeof(buf), in->dm, &in->d);
999 }
1000
1001 if(asmsym && in->s.decl != nil && in->sm == Adesc)
1002 p = seprint(p, buf+sizeof(buf), " #%D", in->s.decl);
1003 if(0 && asmsym && in->m.decl != nil)
1004 p = seprint(p, buf+sizeof(buf), " #%D", in->m.decl);
1005 if(asmsym && in->d.decl != nil && in->dm == Apc)
1006 p = seprint(p, buf+sizeof(buf), " #%D", in->d.decl);
1007 if(asmsym)
1008 p = seprint(p, buf+sizeof(buf), " #%U", in->src);
1009 USED(p);
1010 return fmtstrcpy(f, buf);
1011 }
1012
1013 char*
addrprint(char * buf,char * end,int am,Addr * a)1014 addrprint(char *buf, char *end, int am, Addr *a)
1015 {
1016 switch(am){
1017 case Anone:
1018 return buf;
1019 case Aimm:
1020 case Apc:
1021 case Adesc:
1022 return seprint(buf, end, "$%ld", a->offset);
1023 case Aoff:
1024 return seprint(buf, end, "$%ld", a->decl->iface->offset);
1025 case Anoff:
1026 return seprint(buf, end, "-$%ld", a->decl->iface->offset);
1027 case Afp:
1028 return seprint(buf, end, "%ld(fp)", a->reg);
1029 case Afpind:
1030 return seprint(buf, end, "%ld(%ld(fp))", a->offset, a->reg);
1031 case Amp:
1032 return seprint(buf, end, "%ld(mp)", a->reg);
1033 case Ampind:
1034 return seprint(buf, end, "%ld(%ld(mp))", a->offset, a->reg);
1035 case Aldt:
1036 return seprint(buf, end, "$%ld", a->reg);
1037 case Aerr:
1038 default:
1039 return seprint(buf, end, "%ld(%ld(?%d?))", a->offset, a->reg, am);
1040 }
1041 }
1042
1043 static void
genstore(Src * src,Node * n,int offset)1044 genstore(Src *src, Node *n, int offset)
1045 {
1046 Decl *de;
1047 Node d;
1048
1049 de = mkdecl(&nosrc, Dlocal, tint);
1050 de->sym = nil;
1051 de->offset = offset;
1052
1053 d = znode;
1054 d.op = Oname;
1055 d.addable = Rreg;
1056 d.decl = de;
1057 d.ty = tint;
1058 genrawop(src, IMOVW, n, nil, &d);
1059 }
1060
1061 static Inst*
genfixop(Src * src,int op,Node * s,Node * m,Node * d)1062 genfixop(Src *src, int op, Node *s, Node *m, Node *d)
1063 {
1064 int p, a;
1065 Node *mm;
1066 Inst *i;
1067
1068 mm = m ? m: d;
1069 op = fixop(op, mm->ty, s->ty, d->ty, &p, &a);
1070 if(op == IMOVW){ /* just zero d */
1071 s = sumark(mkconst(src, 0));
1072 return genrawop(src, op, s, nil, d);
1073 }
1074 if(op != IMULX && op != IDIVX)
1075 genstore(src, sumark(mkconst(src, a)), STemp);
1076 genstore(src, sumark(mkconst(src, p)), DTemp);
1077 i = genrawop(src, op, s, m, d);
1078 return i;
1079 }
1080
1081 Inst*
genfixcastop(Src * src,int op,Node * s,Node * d)1082 genfixcastop(Src *src, int op, Node *s, Node *d)
1083 {
1084 int p, a;
1085 Node *m;
1086
1087 op = fixop(op, s->ty, tint, d->ty, &p, &a);
1088 if(op == IMOVW){ /* just zero d */
1089 s = sumark(mkconst(src, 0));
1090 return genrawop(src, op, s, nil, d);
1091 }
1092 m = sumark(mkconst(src, p));
1093 if(op != ICVTXX)
1094 genstore(src, sumark(mkconst(src, a)), STemp);
1095 return genrawop(src, op, s, m, d);
1096 }
1097