xref: /inferno-os/limbo/gen.c (revision 04f9470ee130b6877edcaa202c0a143c9a48fced)
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