xref: /inferno-os/libinterp/comp-sparc.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 
6 enum
7 {
8 	R8	= 8,		/* SUN calls these %o0 - %o7 */
9 	R9	= 9,
10 	R10	= 10,
11 	R11	= 11,
12 	R12	= 12,
13 	R13	= 13,
14 	R14	= 14,		/* SUN %sp */
15 	R15	= 15,		/* R15/%o7 is the default link register */
16 
17 	R16	= 16,		/* SUN calls these %l0 - %l7 */
18 	R17	= 17,
19 	R18	= 18,
20 	R19	= 19,
21 	R20	= 20,
22 	R21	= 21,
23 	R22	= 22,
24 	R23	= 23,
25 	RLINK	= 15,
26 
27 	RZ	= 0,		/* Always 0 */
28 	RFP	= R23,		/* Frame Pointer */
29 	RMP	= R22,		/* Module Pointer */
30 	RTA	= R21,		/* Intermediate address for double indirect */
31 	RREG	= R20,		/* Pointer to REG */
32 	RA3	= R19,		/* gpr 3 */
33 	RA2	= R18,		/* gpr 2 2+3 = L */
34 	RA1	= R17,		/* gpr 1 */
35 	RA0	= R16,		/* gpr 0 0+1 = L */
36 
37 	RCON	= R8,		/* Constant builder */
38 
39 	FA2	= 2,		/* Floating */
40 	FA3	= 3,
41 	FA4	= 4,
42 	FA5	= 5,
43 
44 	Olea	= (1<<20),	/* Pseudo op */
45 	Owry	= 48,
46 	Omul	= 11,
47 	Oumul	= 10,
48 	Osdiv	= 15,
49 	Osll	= 37,
50 	Osra	= 39,
51 	Osrl	= 38,
52 	Osethi	= 4,
53 	Oadd	= 0,
54 	Oaddcc	= 16,
55 	Oaddx	= 8,
56 	Osub	= 4,
57 	Osubcc	= 20,
58 	Osubx	= 12,
59 	Oor	= 2,
60 	Oand	= 1,
61 	Oxor	= 3,
62 	Oldw	= 0,
63 	Oldsh	= 10,
64 	Ostw	= 4,
65 	Osth	= 6,
66 	Ojmpl	= 56,
67 	Ocall	= 1,
68 	Ocmp	= 20,		/* subcc */
69 	Oldbu	= 1,
70 	Ostb	= 5,
71 	Oba	= 8,
72 	Obn	= 0,
73 	Obne	= 9,
74 	Obe	= 1,
75 	Obg	= 10,
76 	Oble	= 2,
77 	Obge	= 11,
78 	Obl	= 3,
79 	Obgu	= 12,
80 	Obleu	= 4,
81 	Obcc	= 13,
82 	Obcs	= 5,
83 	Obpos	= 14,
84 	Obneg	= 6,
85 	Obvc	= 15,
86 	Obvs	= 7,
87 	OfaddD	= 66,
88 	OfsubD	= 70,
89 	OfdivD	= 78,
90 	OfmulD	= 74,
91 	Oldf	= 32,
92 	Ostf	= 36,
93 	OfDtoQ	= 206,
94 	OfnegS	= 5,
95 	OfcmpD	= 82,
96 	Ofba	= 8,
97 	Ofbe	= 9,
98 	Ofbg	= 6,
99 	Ofbge	= 11,
100 	Ofbl	= 4,
101 	Ofble	= 13,
102 	Ofbne	= 1,
103 	OfWtoD	= 200,
104 	OfDtoW	= 210,
105 	Osave	= 60,
106 	Orestore= 61,
107 
108 	SRCOP	= (1<<0),
109 	DSTOP	= (1<<1),
110 	WRTPC	= (1<<2),
111 	TCHECK	= (1<<3),
112 	NEWPC	= (1<<4),
113 	DBRAN	= (1<<5),
114 	THREOP	= (1<<6),
115 
116 	ANDAND	= 1,
117 	OROR	= 2,
118 	EQAND	= 3,
119 
120 	MacFRP	= 0,
121 	MacRET	= 1,
122 	MacCASE	= 2,
123 	MacCOLR	= 3,
124 	MacMCAL	= 4,
125 	MacFRAM	= 5,
126 	MacMFRA	= 6,
127 	NMACRO
128 };
129 
130 #define OP(n)			   (n<<30)
131 #define I13(i)			   ((i)&0x1fff)
132 #define D22(i)			   ((i)&0x3fffff)
133 #define PC30(pc)		   (((ulong)(pc) - (ulong)code)>>2)
134 
135 #define CALL(addr)		   *code=OP(1)|PC30(addr); code++
136 #define FM2I(op2, i, rd)	   *code=OP(0)|(rd<<25)|(op2<<22)|D22(i); code++
137 #define BRA(cond, disp)		   *code=OP(0)|(cond<<25)|(2<<22)|D22((disp)); code++
138 #define BRAF(cond, disp)	   *code=OP(0)|(cond<<25)|(6<<22)|D22((disp)); code++
139 #define BRADIS(r, o)		   BRA(r, ((ulong)(base+patch[o])-(ulong)code)>>2)
140 #define BRAFDIS(r, o)		   BRAF(r, ((ulong)(base+patch[o])-(ulong)code)>>2)
141 #define BRAMAC(r, o)		   BRA(r, ((ulong)(base+macro[o])-(ulong)code)>>2);
142 #define FM3I(op, op3, i, rs1, rd)  *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|\
143 					   (1<<13)|I13(i)
144 #define FM3(op, op3, rs2, rs1, rd) *code++=OP(op)|(rd<<25)|(op3<<19)|(rs1<<14)|rs2
145 #define FMF1(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(52<<19)|(rs1<<14)|(opf<<5)|rs2
146 #define FMF2(opf, rs2, rs1, rd)	   *code++=OP(2)|(rd<<25)|(53<<19)|(rs1<<14)|(opf<<5)|rs2
147 #define NOOP			   *code++=(4<<22)
148 #define RETURN			   FM3I(2, Ojmpl, 8, RLINK, RZ);
149 #define MOV(s, d)		   FM3(2, Oor, s, RZ, d)
150 
151 #define RELPC(pc)		   (ulong)(base+pc)
152 #define PATCH(ptr)		   *ptr |= (code-ptr) & 0x3fffff
153 
154 static	ulong*	code;
155 static	ulong*	base;
156 static	ulong*	patch;
157 static	int	pass;
158 static	int	puntpc = 1;
159 static	Module*	mod;
160 static	uchar*	tinit;
161 static	ulong*	litpool;
162 static	int	nlit;
163 static	void	macfrp(void);
164 static	void	macret(void);
165 static	void	maccase(void);
166 static	void	maccolr(void);
167 static	void	macmcal(void);
168 static	void	macfram(void);
169 static	void	macmfra(void);
170 static	ulong	macro[NMACRO];
171 	void	(*comvec)(void);
172 extern	void	das(ulong*, int);
173 
174 #define T(r)	*((void**)(R.r))
175 
176 struct
177 {
178 	int	idx;
179 	void	(*gen)(void);
180 	char*	name;
181 } mactab[] =
182 {
183 	MacFRP,		macfrp,		"FRP", 	/* decrement and free pointer */
184 	MacRET,		macret,		"RET",	/* return instruction */
185 	MacCASE,	maccase,	"CASE",	/* case instruction */
186 	MacCOLR,	maccolr,	"COLR",	/* increment and color pointer */
187 	MacMCAL,	macmcal,	"MCAL",	/* mcall bottom half */
188 	MacFRAM,	macfram,	"FRAM",	/* frame instruction */
189 	MacMFRA,	macmfra,	"MFRA",	/* punt mframe because t->initialize==0 */
190 };
191 
192 static void
193 rdestroy(void)
194 {
195 	destroy(R.s);
196 }
197 
198 static void
199 rmcall(void)
200 {
201 	Prog *p;
202 	Frame *f;
203 
204 	f = (Frame*)R.FP;
205 	if(f == H)
206 		error(exModule);
207 
208 	f->mr = nil;
209 	((void(*)(Frame*))R.dt)(f);
210 	R.SP = (uchar*)f;
211 	R.FP = f->fp;
212 	if(f->t == nil)
213 		unextend(f);
214 	else
215 		freeptrs(f, f->t);
216 	p = currun();
217 	if(p->kill != nil)
218 		error(p->kill);
219 }
220 
221 static void
222 rmfram(void)
223 {
224 	Type *t;
225 	Frame *f;
226 	uchar *nsp;
227 
228 	if(R.d == H)
229                 error(exModule);
230         t = (Type*)R.s;
231         if(t == H)
232                 error(exModule);
233 
234 	nsp = R.SP + t->size;
235 	if(nsp >= R.TS) {
236 		R.s = t;
237 		extend();
238 		T(d) = R.s;
239 		return;
240 	}
241 	f = (Frame*)R.SP;
242 	R.SP = nsp;
243 	f->t = t;
244 	f->mr = nil;
245 	initmem(t, f);
246 	T(d) = f;
247 }
248 
249 static void
250 urk(void)
251 {
252 	error(exCompile);
253 }
254 
255 static int
256 bc(long c)
257 {
258 	c &= ~0xfffL;
259 	if (c == 0 || c == ~0xfffL)
260 		return 1;
261 
262 	return 0;
263 }
264 
265 static void
266 con(ulong o, int r, int opt)
267 {
268 	if(opt != 0) {
269 		if(bc(o)) {
270 			FM3I(2, Oadd, o & 0x1fff, RZ, r);
271 			return;
272 		}
273 		if((o & 0x3ff) == 0) {
274 			FM2I(Osethi, o>>10, r);
275 			return;
276 		}
277 	}
278 	FM2I(Osethi, o>>10, r);
279 	FM3I(2, Oadd, o & 0x3ff, r, r);
280 }
281 
282 static void
283 mem(int inst, ulong disp, int rm, int r)
284 {
285 	int op;
286 
287 	op = 3;
288 	if(inst == Olea) {
289 		op = 2;
290 		inst = Oadd;
291 	}
292 	if(bc(disp)) {
293 		FM3I(op, inst, disp, rm, r);
294 		return;
295 	}
296 	con(disp, RCON, 1);
297 	FM3(op, inst, RCON, rm, r);
298 }
299 
300 static void
301 opwld(Inst *i, int mi, int r)
302 {
303 	int ir, rta;
304 
305 	switch(UXSRC(i->add)) {
306 	default:
307 		print("%D\n", i);
308 		urk();
309 	case SRC(AFP):
310 		mem(mi, i->s.ind, RFP, r);
311 		return;
312 	case SRC(AMP):
313 		mem(mi, i->s.ind, RMP, r);
314 		return;
315 	case SRC(AIMM):
316 		con(i->s.imm, r, 1);
317 		if(mi == Olea) {
318 			mem(Ostw, O(REG, st), RREG, r);
319 			con((ulong)&R.st, r, 1);
320 		}
321 		return;
322 	case SRC(AIND|AFP):
323 		ir = RFP;
324 		break;
325 	case SRC(AIND|AMP):
326 		ir = RMP;
327 		break;
328 	}
329 	rta = RTA;
330 	if(mi == Olea)
331 		rta = r;
332 	mem(Oldw, i->s.i.f, ir, rta);
333 	mem(mi, i->s.i.s, rta, r);
334 }
335 
336 static void
337 opwst(Inst *i, int mi, int r)
338 {
339 	int ir, rta;
340 
341 	switch(UXDST(i->add)) {
342 	default:
343 		print("%D\n", i);
344 		urk();
345 	case DST(AIMM):
346 		con(i->d.imm, r, 1);
347 		return;
348 	case DST(AFP):
349 		mem(mi, i->d.ind, RFP, r);
350 		return;
351 	case DST(AMP):
352 		mem(mi, i->d.ind, RMP, r);
353 		return;
354 	case DST(AIND|AFP):
355 		ir = RFP;
356 		break;
357 	case DST(AIND|AMP):
358 		ir = RMP;
359 		break;
360 	}
361 	rta = RTA;
362 	if(mi == Olea)
363 		rta = r;
364 	mem(Oldw, i->d.i.f, ir, rta);
365 	mem(mi, i->d.i.s, rta, r);
366 }
367 
368 static void
369 opfl(Adr *a, int am, int mi, int r)
370 {
371 	int ir;
372 
373 	switch(am) {
374 	default:
375 		urk();
376 	case AFP:
377 		mem(mi, a->ind, RFP, r);
378 		mem(mi, a->ind+4, RFP, r+1);
379 		return;
380 	case AMP:
381 		mem(mi, a->ind, RMP, r);
382 		mem(mi, a->ind+4, RMP, r+1);
383 		return;
384 	case AIND|AFP:
385 		ir = RFP;
386 		break;
387 	case AIND|AMP:
388 		ir = RMP;
389 		break;
390 	}
391 	mem(Oldw, a->i.f, ir, RTA);
392 	mem(mi, a->i.s, RTA, r);
393 	mem(mi, a->i.s+4, RTA, r+1);
394 }
395 
396 static void
397 opflld(Inst *i, int mi, int r)
398 {
399 	opfl(&i->s, USRC(i->add), mi, r);
400 }
401 
402 static void
403 opflst(Inst *i, int mi, int r)
404 {
405 	opfl(&i->d, UDST(i->add), mi, r);
406 }
407 
408 static void
409 literal(ulong imm, int roff)
410 {
411 	nlit++;
412 
413 	con((ulong)litpool, RTA, 0);
414 	mem(Ostw, roff, RREG, RTA);
415 
416 	if(pass == 0)
417 		return;
418 
419 	*litpool = imm;
420 	litpool++;
421 }
422 
423 static void
424 punt(Inst *i, int m, void (*fn)(void))
425 {
426 	ulong pc;
427 
428 	if(m & SRCOP) {
429 		if(UXSRC(i->add) == SRC(AIMM))
430 			literal(i->s.imm, O(REG, s));
431 		else {
432 			opwld(i, Olea, RA0);
433 			mem(Ostw, O(REG, s), RREG, RA0);
434 		}
435 	}
436 
437 	if(m & DSTOP) {
438 		opwst(i, Olea, RA0);
439 		mem(Ostw, O(REG, d), RREG, RA0);
440 	}
441 	if(m & WRTPC) {
442 		con(RELPC(patch[i-mod->prog+1]), RA0, 0);
443 		mem(Ostw, O(REG, PC), RREG, RA0);
444 	}
445 	if(m & DBRAN) {
446 		pc = patch[(Inst*)i->d.imm-mod->prog];
447 		literal(RELPC(pc), O(REG, d));
448 	}
449 
450 	switch(i->add&ARM) {
451 	case AXNON:
452 		if(m & THREOP) {
453 			mem(Oldw, O(REG, d), RREG, RA0);
454 			mem(Ostw, O(REG, m), RREG, RA0);
455 		}
456 		break;
457 	case AXIMM:
458 		literal((short)i->reg, O(REG, m));
459 		break;
460 	case AXINF:
461 		mem(Olea, i->reg, RFP, RA0);
462 		mem(Ostw, O(REG, m), RREG, RA0);
463 		break;
464 	case AXINM:
465 		mem(Olea, i->reg, RMP, RA0);
466 		mem(Ostw, O(REG, m), RREG, RA0);
467 		break;
468 	}
469 
470 	CALL(fn);
471 	mem(Ostw, O(REG, FP), RREG, RFP);
472 
473 	con((ulong)&R, RREG, 1);
474 	if(m & TCHECK) {
475 		mem(Oldw, O(REG, t), RREG, RA0);
476 		FM3I(2, Ocmp, 0, RA0, RZ);
477 		BRA(Obe, 5);
478 		NOOP;
479 		mem(Oldw, O(REG, xpc), RREG, RLINK);
480 		RETURN;
481 		NOOP;
482 	}
483 
484 	mem(Oldw, O(REG, FP), RREG, RFP);
485 	mem(Oldw, O(REG, MP), RREG, RMP);
486 
487 	if(m & NEWPC) {
488 		mem(Oldw, O(REG, PC), RREG, RA0);
489 		FM3I(2, Ojmpl, 0, RA0, RZ);
490 		NOOP;
491 	}
492 }
493 
494 static void
495 midfl(Inst *i, int mi, int r)
496 {
497 	int ir;
498 
499 	switch(i->add&ARM) {
500 	default:
501 		opflst(i, mi, r);
502 		return;
503 	case AXIMM:
504 		con((short)i->reg, r, 1);
505 		return;
506 	case AXINF:
507 		ir = RFP;
508 		break;
509 	case AXINM:
510 		ir = RMP;
511 		break;
512 	}
513 	mem(mi, i->reg, ir, r);
514 	mem(mi, i->reg+4, ir, r+1);
515 }
516 
517 static void
518 mid(Inst *i, int mi, int r)
519 {
520 	int ir;
521 
522 	switch(i->add&ARM) {
523 	default:
524 		opwst(i, mi, r);
525 		return;
526 	case AXIMM:
527 		con((short)i->reg, r, 1);
528 		return;
529 	case AXINF:
530 		ir = RFP;
531 		break;
532 	case AXINM:
533 		ir = RMP;
534 		break;
535 	}
536 	mem(mi, i->reg, ir, r);
537 }
538 
539 static void
540 cbral(Inst *i, int jmsw, int jlsw, int mode)
541 {
542 	ulong dst, *label;
543 
544 	opwld(i, Olea, RA1);
545 	mid(i, Olea, RA3);
546 	mem(Oldw, 0, RA1, RA2);
547 	mem(Oldw, 0, RA3, RA0);
548 	FM3(2, Ocmp, RA0, RA2, RZ);
549 	label = nil;
550 	dst = i->d.ins-mod->prog;
551 	switch(mode) {
552 	case ANDAND:
553 		label = code;
554 		BRA(jmsw, 0);
555 		break;
556 	case OROR:
557 		BRADIS(jmsw, dst);
558 		break;
559 	case EQAND:
560 		BRADIS(jmsw, dst);
561 		NOOP;
562 		label = code;
563 		BRA(Obne, 0);
564 		break;
565 	}
566 	NOOP;
567 	mem(Oldw, 4, RA3, RA0);
568 	mem(Oldw, 4, RA1, RA2);
569 	FM3(2, Ocmp, RA0, RA2, RZ);
570 	BRADIS(jlsw, dst);
571 	if(label != nil)
572 		PATCH(label);
573 }
574 
575 static void
576 comcase(Inst *i, int w)
577 {
578 	int l;
579 	WORD *t, *e;
580 
581 	if(w != 0) {
582 		opwld(i, Oldw, RA0);		// v
583 		opwst(i, Olea, RCON);		// table
584 		BRAMAC(Oba, MacCASE);
585 		NOOP;
586 	}
587 
588 	t = (WORD*)(mod->origmp+i->d.ind+4);
589 	l = t[-1];
590 
591 	/* have to take care not to relocate the same table twice -
592 	 * the limbo compiler can duplicate a case instruction
593 	 * during its folding phase
594 	 */
595 
596 	if(pass == 0) {
597 		if(l >= 0)
598 			t[-1] = -l-1;	/* Mark it not done */
599 		return;
600 	}
601 	if(l >= 0)			/* Check pass 2 done */
602 		return;
603 	t[-1] = -l-1;			/* Set real count */
604 	e = t + t[-1]*3;
605 	while(t < e) {
606 		t[2] = RELPC(patch[t[2]]);
607 		t += 3;
608 	}
609 	t[0] = RELPC(patch[t[0]]);
610 }
611 
612 static void
613 comcasel(Inst *i)
614 {
615 	int l;
616 	WORD *t, *e;
617 
618 	t = (WORD*)(mod->origmp+i->d.ind+8);
619 	l = t[-2];
620 	if(pass == 0) {
621 		if(l >= 0)
622 			t[-2] = -l-1;	/* Mark it not done */
623 		return;
624 	}
625 	if(l >= 0)			/* Check pass 2 done */
626 		return;
627 	t[-2] = -l-1;			/* Set real count */
628 	e = t + t[-2]*6;
629 	while(t < e) {
630 		t[4] = RELPC(patch[t[4]]);
631 		t += 6;
632 	}
633 	t[0] = RELPC(patch[t[0]]);
634 }
635 
636 static void
637 commframe(Inst *i)
638 {
639 	int o;
640 	ulong *punt, *mlnil;
641 
642 	opwld(i, Oldw, RA0);
643 	FM3I(2, Ocmp, -1, RA0, RZ);
644 	mlnil = code;
645 	BRA(Obe, 0);
646 	NOOP;
647 
648 	if((i->add&ARM) == AXIMM) {
649 		o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame);
650 		mem(Oldw, o, RA0, RA3);
651 	} else {
652 		mid(i, Oldw, RA1);
653 		FM3I(2, Osll, 3, RA1, RA1);		// assumes sizeof(Modl) == 8
654 		FM3(2, Oadd, RA0, RA1, RA1);
655 		o = OA(Modlink, links)+O(Modl, frame);
656 		mem(Oldw, o, RA1, RA3);
657 	}
658 	mem(Oldw, O(Type, initialize), RA3, RA1);
659 	FM3I(2, Ocmp, 0, RA1, RZ);
660 	punt = code;
661 	BRA(Obne, 0);
662 	NOOP;
663 
664 	opwst(i, Olea, RA0);
665 
666 	/* Type in RA3, destination in RA0 */
667 	PATCH(mlnil);
668 	con(RELPC(patch[i-mod->prog+1])-8, RLINK, 0);
669 	BRAMAC(Oba, MacMFRA);
670 	NOOP;
671 
672 	/* Type in RA3 */
673 	PATCH(punt);
674 	CALL(base+macro[MacFRAM]);
675 	NOOP;
676 	opwst(i, Ostw, RA2);
677 }
678 
679 static void
680 commcall(Inst *i)
681 {
682 	opwld(i, Oldw, RA2);
683 	con(RELPC(patch[i-mod->prog+1]), RA0, 0);
684 	mem(Ostw, O(Frame, lr), RA2, RA0);
685 	mem(Ostw, O(Frame, fp), RA2, RFP);
686 	mem(Oldw, O(REG, M), RREG, RA3);
687 	mem(Ostw, O(Frame, mr), RA2, RA3);
688 	opwst(i, Oldw, RA3);
689 	if((i->add&ARM) == AXIMM) {
690 		CALL(base+macro[MacMCAL]);
691 		mem(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RA3, RA0);
692 	} else {
693 		mid(i, Oldw, RA1);
694 		FM3I(2, Osll, 3, RA1, RA1);		// assumes sizeof(Modl) == 8
695 		FM3(2, Oadd, RA1, RA3, RA0);
696 		CALL(base+macro[MacMCAL]);
697 		mem(Oldw, OA(Modlink, links)+O(Modl, u.pc), RA0, RA0);
698 	}
699 }
700 
701 static void
702 larith(Inst *i, int op, int opc)
703 {
704 	opflld(i, Oldw, RA0);
705 	midfl(i, Oldw, RA2);
706 	FM3(2, op, RA1, RA3, RA1);
707 	FM3(2, opc, RA0, RA2, RA0);
708 	opflst(i, Ostw, RA0);
709 }
710 
711 static void
712 movloop(Inst *i, int ld, int st)
713 {
714 	int s;
715 
716 	s = 1;
717 	if(ld == Oldw)
718 		s = 4;
719 	opwld(i, Olea, RA1);
720 	opwst(i, Olea, RA2);
721 	mem(ld, 0, RA1, RA0);
722 	mem(st, 0, RA2, RA0);
723 	FM3I(2, Oadd, s, RA2, RA2);
724 	FM3I(2, Oaddcc, -1, RA3, RA3);
725 	BRA(Obne, -4);
726 	FM3I(2, Oadd, s, RA1, RA1);
727 }
728 
729 static
730 void
731 compdbg(void)
732 {
733 	print("%s:%d@%.8ux\n", R.M->m->name, R.t, R.st);
734 }
735 
736 static void
737 shll(Inst *i)
738 {
739 	ulong *lab0, *lab1, *lab2;
740 
741 	opwld(i, Oldw, RA2);
742 	midfl(i, Oldw, RA0);
743 	FM3I(2, Ocmp, RZ, RA2, RZ);
744 	lab0 = code;
745 	BRA(Obe, 0);
746 	FM3I(2, Ocmp, 32, RA2, RZ);
747 	lab1 = code;
748 	BRA(Obl, 0);
749 	NOOP;
750 	FM3I(2, Osub, 32, RA2, RA2);
751 	FM3(2, Osll, RA2, RA1, RA0);
752 	lab2 = code;
753 	BRA(Oba, 0);
754 	MOV(RZ, RA1);
755 
756 	PATCH(lab1);
757 	FM3(2, Osll, RA2, RA0, RA0);
758 	con(32, RA3, 1);
759 	FM3(2, Osub, RA2, RA3, RA3);
760 	FM3(2, Osrl, RA3, RA1, RA3);
761 	FM3(2, Oor, RA0, RA3, RA0);
762 	FM3(2, Osll, RA2, RA1, RA1);
763 
764 	PATCH(lab0);
765 	PATCH(lab2);
766 	opflst(i, Ostw, RA0);
767 }
768 
769 static void
770 comp(Inst *i)
771 {
772 	int r;
773 	WORD *t, *e;
774 	char buf[64];
775 
776 	if(0) {
777 		Inst xx;
778 		xx.add = AXIMM|SRC(AIMM);
779 		xx.s.imm = (ulong)code;
780 		xx.reg = i-mod->prog;
781 		puntpc = 0;
782 		punt(&xx, SRCOP, compdbg);
783 		puntpc = 1;
784 	}
785 
786 	switch(i->op) {
787 	default:
788 		snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
789 		error(buf);
790 		break;
791 	case IMCALL:
792 		if((i->add&ARM) == AXIMM)
793 			commcall(i);
794 		else
795 			punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
796 		break;
797 	case ISEND:
798 	case IRECV:
799 	case IALT:
800 		punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
801 		break;
802 	case ISPAWN:
803 		punt(i, SRCOP|DBRAN, optab[i->op]);
804 		break;
805 	case IBNEC:
806 	case IBEQC:
807 	case IBLTC:
808 	case IBLEC:
809 	case IBGTC:
810 	case IBGEC:
811 		punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
812 		break;
813 	case ICASEC:
814 		comcase(i, 0);
815 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
816 		break;
817 	case ICASEL:
818 		comcasel(i);
819 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
820 		break;
821 	case IADDC:
822 	case IMULL:
823 	case IDIVL:
824 	case IMODL:
825 	case IMODW:
826 	case IMODB:
827 	case IMNEWZ:
828 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
829 		break;
830 	case ILOAD:
831 	case INEWA:
832 	case INEWAZ:
833 	case INEW:
834 	case INEWZ:
835 	case ISLICEA:
836 	case ISLICELA:
837 	case ICONSB:
838 	case ICONSW:
839 	case ICONSL:
840 	case ICONSF:
841 	case ICONSM:
842 	case ICONSMP:
843 	case ICONSP:
844 	case IMOVMP:
845 	case IHEADMP:
846 	case IHEADM:
847 	case IHEADB:
848 	case IHEADW:
849 	case IHEADL:
850 	case IHEADF:
851 	case IINDC:
852 	case ILENC:
853 	case IINSC:
854 	case ICVTAC:
855 	case ICVTCW:
856 	case ICVTWC:
857 	case ICVTLC:
858 	case ICVTCL:
859 	case ICVTFC:
860 	case ICVTCF:
861 	case ICVTRF:
862 	case ICVTFR:
863 	case IMSPAWN:
864 	case ICVTCA:
865 	case ISLICEC:
866 	case INBALT:
867 		punt(i, SRCOP|DSTOP, optab[i->op]);
868 		break;
869 	case INEWCM:
870 	case INEWCMP:
871 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
872 		break;
873 	case IMFRAME:
874 		if((i->add&ARM) == AXIMM)
875 			commframe(i);
876 		else
877 			punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
878 		break;
879 	case ICASE:
880 		comcase(i, 1);
881 		break;
882 	case IGOTO:
883 		opwld(i, Oldw, RA1);
884 		opwst(i, Olea, RA0);
885 		FM3I(2, Osll, 2, RA1, RA1);
886 		FM3(3, Oldw, RA1, RA0, RA0);
887 		FM3I(2, Ojmpl, 0, RA0, RZ);
888 		NOOP;
889 
890 		if(pass == 0)
891 			break;
892 
893 		t = (WORD*)(mod->origmp+i->d.ind);
894 		e = t + t[-1];
895 		t[-1] = 0;
896 		while(t < e) {
897 			t[0] = RELPC(patch[t[0]]);
898 			t++;
899 		}
900 		break;
901 	case IMOVL:
902 	movl:
903 		opflld(i, Oldw, RA0);
904 		opflst(i, Ostw, RA0);
905 		break;
906 	case IMOVM:
907 		if((i->add&ARM) == AXIMM) {
908 			if(i->reg == 8)
909 				goto movl;
910 			if((i->reg&3) == 0) {
911 				con(i->reg>>2, RA3, 1);
912 				movloop(i, Oldw, Ostw);
913 				break;
914 			}
915 		}
916 		mid(i, Oldw, RA3);
917 		movloop(i, Oldbu, Ostb);
918 		break;
919 	case IFRAME:
920 		if(UXSRC(i->add) != SRC(AIMM)) {
921 			punt(i, SRCOP|DSTOP, optab[i->op]);
922 			break;
923 		}
924 		tinit[i->s.imm] = 1;
925 		con((ulong)mod->type[i->s.imm], RA3, 1);
926 		CALL(base+macro[MacFRAM]);
927 		NOOP;
928 		opwst(i, Ostw, RA2);
929 		break;
930 	case INEWCB:
931 	case INEWCW:
932 	case INEWCF:
933 	case INEWCP:
934 	case INEWCL:
935 		punt(i, DSTOP|THREOP, optab[i->op]);
936 		break;
937 	case IEXIT:
938 		punt(i, 0, optab[i->op]);
939 		break;
940 	case ICVTBW:
941 		opwld(i, Oldbu, RA0);
942 		opwst(i, Ostw, RA0);
943 		break;
944 	case ICVTWB:
945 		opwld(i, Oldw, RA0);
946 		opwst(i, Ostb, RA0);
947 		break;
948 	case ILEA:
949 		opwld(i, Olea, RA0);
950 		opwst(i, Ostw, RA0);
951 		break;
952 	case IMOVW:
953 		opwld(i, Oldw, RA0);
954 		opwst(i, Ostw, RA0);
955 		break;
956 	case IMOVB:
957 		opwld(i, Oldbu, RA0);
958 		opwst(i, Ostb, RA0);
959 		break;
960 	case ICVTSW:
961 		opwld(i, Oldsh, RA0);
962 		opwst(i, Ostw, RA0);
963 		break;
964 	case ICVTWS:
965 		opwld(i, Oldw, RA0);
966 		opwst(i, Osth, RA0);
967 		break;
968 	case ITAIL:
969 		opwld(i, Oldw, RA0);
970 		mem(Oldw, O(List, tail), RA0, RA1);
971 		goto movp;
972 	case IMOVP:
973 	case IHEADP:
974 		opwld(i, Oldw, RA1);
975 		if(i->op == IHEADP)
976 			mem(Oldw, OA(List, data), RA1, RA1);
977 	movp:
978 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
979 		BRA(Obe, 5);
980 		con((ulong)&mutator, RA2, 1);
981 		CALL(base+macro[MacCOLR]);
982 		mem(Oldw, O(Heap, ref)-sizeof(Heap), RA1, RA0);
983 		opwst(i, Oldw, RA0);
984 		opwst(i, Ostw, RA1);
985 		CALL(base+macro[MacFRP]);
986 		NOOP;
987 		break;
988 	case ILENA:
989 		opwld(i, Oldw, RA1);
990 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
991 		BRA(Obe, 3);
992 		con(0, RA0, 1);
993 		mem(Oldw, O(Array, len), RA1, RA0);
994 		opwst(i, Ostw, RA0);
995 		break;
996 	case ILENL:
997 		con(0, RA0, 1);
998 		opwld(i, Oldw, RA1);
999 		FM3I(2, Ocmp, (ulong)H, RA1, RZ);
1000 		BRA(Obe, 5);
1001 		NOOP;
1002 		mem(Oldw, O(List, tail), RA1, RA1);
1003 		BRA(Oba, -4);
1004 		FM3I(2, Oadd, 1, RA0, RA0);
1005 		opwst(i, Ostw, RA0);
1006 		break;
1007 	case ICALL:
1008 		opwld(i, Oldw, RA0);
1009 		con(RELPC(patch[i-mod->prog+1]), RA1, 0);
1010 		mem(Ostw, O(Frame, lr), RA0, RA1);
1011 		mem(Ostw, O(Frame, fp), RA0, RFP);
1012 		BRADIS(Oba, i->d.ins-mod->prog);
1013 		MOV(RA0, RFP);
1014 		break;
1015 	case IJMP:
1016 		BRADIS(Oba, i->d.ins-mod->prog);
1017 		NOOP;
1018 		break;
1019 	case IBEQW:
1020 		r = Obe;
1021 	braw:
1022 		opwld(i, Oldw, RA1);
1023 		mid(i, Oldw, RA0);
1024 		FM3(2, Ocmp, RA0, RA1, RZ);
1025 		BRADIS(r, i->d.ins-mod->prog);
1026 		NOOP;
1027 		break;
1028 	case IBNEW:
1029 		r = Obne;
1030 		goto braw;
1031 	case IBLTW:
1032 		r = Obl;
1033 		goto braw;
1034 	case IBLEW:
1035 		r = Oble;
1036 		goto braw;
1037 	case IBGTW:
1038 		r = Obg;
1039 		goto braw;
1040 	case IBGEW:
1041 		r = Obge;
1042 		goto braw;
1043 	case IBEQB:
1044 		r = Obe;
1045 	brab:
1046 		opwld(i, Oldbu, RA1);
1047 		mid(i, Oldbu, RA0);
1048 		FM3(2, Ocmp, RA0, RA1, RZ);
1049 		BRADIS(r, i->d.ins-mod->prog);
1050 		NOOP;
1051 		break;
1052 	case IBNEB:
1053 		r = Obne;
1054 		goto brab;
1055 	case IBLTB:
1056 		r = Obl;
1057 		goto brab;
1058 	case IBLEB:
1059 		r = Oble;
1060 		goto brab;
1061 	case IBGTB:
1062 		r = Obg;
1063 		goto brab;
1064 	case IBGEB:
1065 		r = Obge;
1066 		goto brab;
1067 	case IBEQF:
1068 		r = Ofbe;
1069 	braf:
1070 		opflld(i, Oldf, FA4);
1071 		midfl(i, Oldf, FA2);
1072 		FMF2(OfcmpD, FA2, FA4, 0);
1073 		NOOP;
1074 		BRAFDIS(r, i->d.ins-mod->prog);
1075 		NOOP;
1076 		break;
1077 	case IBNEF:
1078 		r = Ofbne;
1079 		goto braf;
1080 	case IBLTF:
1081 		r = Ofbl;
1082 		goto braf;
1083 	case IBLEF:
1084 		r = Ofble;
1085 		goto braf;
1086 	case IBGTF:
1087 		r = Ofbg;
1088 		goto braf;
1089 	case IBGEF:
1090 		r = Ofbge;
1091 		goto braf;
1092 	case IRET:
1093 		BRAMAC(Oba, MacRET);
1094 		mem(Oldw, O(Frame,t), RFP, RA1);
1095 		break;
1096 	case IORW:
1097 		r = Oor;
1098 		goto arithw;
1099 	case IANDW:
1100 		r = Oand;
1101 		goto arithw;
1102 	case IXORW:
1103 		r = Oxor;
1104 		goto arithw;
1105 	case ISUBW:
1106 		r = Osub;
1107 		goto arithw;
1108 	case ISHRW:
1109 		r = Osra;
1110 		goto arithw;
1111 	case ISHLW:
1112 		r = Osll;
1113 		goto arithw;
1114 	case ILSRW:
1115 		r = Osrl;
1116 		goto arithw;
1117 	case IMULW:
1118 		r = Omul;
1119 		goto arithw;
1120 	case IDIVW:
1121 		r = Osdiv;
1122 		goto arithw;
1123 	case IADDW:
1124 		r = Oadd;
1125 	arithw:
1126 		mid(i, Oldw, RA1);
1127 		if(i->op == IDIVW) {
1128 			FM3I(2, Osra, 31, RA1, RA0);
1129 			FM3(2, Owry, RZ, RA0, 0);
1130 		}
1131 		if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm))
1132 			FM3I(2, r, i->s.imm, RA1, RA0);
1133 		else {
1134 			opwld(i, Oldw, RA0);
1135 			FM3(2, r, RA0, RA1, RA0);
1136 		}
1137 		opwst(i, Ostw, RA0);
1138 		break;
1139 	case IORB:
1140 		r = Oor;
1141 		goto arithb;
1142 	case IANDB:
1143 		r = Oand;
1144 		goto arithb;
1145 	case IXORB:
1146 		r = Oxor;
1147 		goto arithb;
1148 	case ISUBB:
1149 		r = Osub;
1150 		goto arithb;
1151 	case IMULB:
1152 		r = Omul;
1153 		goto arithb;
1154 	case IDIVB:
1155 		FM3(2, Owry, RZ, RZ, 0);
1156 		r = Osdiv;
1157 		goto arithb;
1158 	case IADDB:
1159 		r = Oadd;
1160 	arithb:
1161 		mid(i, Oldbu, RA1);
1162 		opwld(i, Oldbu, RA0);
1163 		FM3(2, r, RA0, RA1, RA0);
1164 		opwst(i, Ostb, RA0);
1165 		break;
1166 	case ISHRB:
1167 		r = Osra;
1168 		goto shiftb;
1169 	case ISHLB:
1170 		r = Osll;
1171 	shiftb:
1172 		mid(i, Oldbu, RA1);
1173 		if(UXSRC(i->add) == SRC(AIMM) && bc(i->s.imm))
1174 			FM3I(2, r, i->s.imm, RA1, RA0);
1175 		else {
1176 			opwld(i, Oldw, RA0);
1177 			FM3(2, r, RA0, RA1, RA0);
1178 		}
1179 		opwst(i, Ostb, RA0);
1180 		break;
1181 	case IINDL:
1182 	case IINDF:
1183 	case IINDW:
1184 	case IINDB:
1185 		opwld(i, Oldw, RA0);			/* a */
1186 		r = 0;
1187 		switch(i->op) {
1188 		case IINDL:
1189 		case IINDF:
1190 			r = 3;
1191 			break;
1192 		case IINDW:
1193 			r = 2;
1194 			break;
1195 		}
1196 		if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r)) {
1197 			mem(Oldw, O(Array, data), RA0, RA0);
1198 			FM3I(2, Oadd, (i->d.imm<<r), RA0, RA0);
1199 		}
1200 		else {
1201 			opwst(i, Oldw, RA1);
1202 			mem(Oldw, O(Array, data), RA0, RA0);
1203 			if(r != 0)
1204 				FM3I(2, Osll, r, RA1, RA1);
1205 			FM3(2, Oadd, RA0, RA1, RA0);
1206 		}
1207 		r = RMP;
1208 		if((i->add&ARM) == AXINF)
1209 			r = RFP;
1210 		mem(Ostw, i->reg, r, RA0);
1211 		break;
1212 	case IINDX:
1213 		opwld(i, Oldw, RA0);			/* a */
1214 		/*
1215 		r = 0;
1216 		if(UXDST(i->add) == DST(AIMM) && bc(i->d.imm<<r))
1217 			r = i->d.imm<<r;
1218 		else
1219 		*/
1220 			opwst(i, Oldw, RA1);		/* i */
1221 		mem(Oldw, O(Array, t), RA0, RA2);
1222 		mem(Oldw, O(Array, data), RA0, RA0);
1223 		mem(Oldw, O(Type, size), RA2, RA2);
1224 		/*
1225 		if(r != 0)
1226 			FM3I(2, Oumul, r, RA2, RA1);
1227 		else
1228 		*/
1229 			FM3(2, Oumul, RA1, RA2, RA1);
1230 		FM3(2, Oadd, RA0, RA1, RA0);
1231 		r = RMP;
1232 		if((i->add&ARM) == AXINF)
1233 			r = RFP;
1234 		mem(Ostw, i->reg, r, RA0);
1235 		break;
1236 	case IADDL:
1237 		larith(i, Oaddcc, Oaddx);
1238 		break;
1239 	case ISUBL:
1240 		larith(i, Osubcc, Osubx);
1241 		break;
1242 	case IORL:
1243 		larith(i, Oor, Oor);
1244 		break;
1245 	case IANDL:
1246 		larith(i, Oand, Oand);
1247 		break;
1248 	case IXORL:
1249 		larith(i, Oxor, Oxor);
1250 		break;
1251 	case ICVTWL:
1252 		opwld(i, Oldw, RA1);
1253 		FM3I(2, Osra, 31, RA1, RA0);
1254 		opflst(i, Ostw, RA0);
1255 		break;
1256 	case ICVTLW:
1257 		opwld(i, Olea, RA0);
1258 		mem(Oldw, 4, RA0, RA0);
1259 		opwst(i, Ostw, RA0);
1260 		break;
1261 	case IBEQL:
1262 		cbral(i, Obne, Obe, ANDAND);
1263 		break;
1264 	case IBNEL:
1265 		cbral(i, Obne, Obne, OROR);
1266 		break;
1267 	case IBLEL:
1268 		cbral(i, Obl, Obleu, EQAND);
1269 		break;
1270 	case IBGTL:
1271 		cbral(i, Obg, Obgu, EQAND);
1272 		break;
1273 	case IBLTL:
1274 		cbral(i, Obl, Obcs, EQAND);
1275 		break;
1276 	case IBGEL:
1277 		cbral(i, Obg, Obcc, EQAND);
1278 		break;
1279 	case IMOVF:
1280 		opflld(i, Oldf, FA2);
1281 		opflst(i, Ostf, FA2);
1282 		break;
1283 	case IDIVF:
1284 		r = OfdivD;
1285 		goto arithf;
1286 	case IMULF:
1287 		r = OfmulD;
1288 		goto arithf;
1289 	case ISUBF:
1290 		r = OfsubD;
1291 		goto arithf;
1292 	case IADDF:
1293 		r = OfaddD;
1294 	arithf:
1295 		opflld(i, Oldf, FA2);
1296 		midfl(i, Oldf, FA4);
1297 		FMF1(r, FA2, FA4, FA4);
1298 		opflst(i, Ostf, FA4);
1299 		break;
1300 	case INEGF:
1301 		opflld(i, Oldf, FA2);
1302 		FMF1(OfnegS, FA2, 0, FA2);
1303 		opflst(i, Ostf, FA2);
1304 		break;
1305 	case ICVTFL:
1306 		// >= Sparc 8
1307 		// opflld(i, Oldf, FA2);
1308 		// FMF1(OfDtoQ, FA2, 0, FA2);
1309 		// opflst(i, Ostf, FA2);
1310 		punt(i, SRCOP|DSTOP, optab[i->op]);
1311 		break;
1312 	case ICVTLF:
1313 		// >= Sparc 8
1314 		// opflld(i, Oldf, FA2);
1315 		// FMF1(OfQtoD, FA2, 0, FA2);
1316 		// opflst(i, Ostf, FA2);
1317 		punt(i, SRCOP|DSTOP, optab[i->op]);
1318 		break;
1319 	case ICVTWF:
1320 		opwld(i, Oldf, FA2);
1321 		FMF1(OfWtoD, FA2, 0, FA2);
1322 		opflst(i, Ostf, FA2);
1323 		break;
1324 	case ICVTFW:
1325 		opflld(i, Oldf, FA2);
1326 		FMF1(OfDtoW, FA2, 0, FA2);
1327 		opwst(i, Ostf, FA2);
1328 		break;
1329 	case ISHLL:
1330 		shll(i);
1331 		break;
1332 	case ISHRL:
1333 	case ILSRL:
1334 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1335 		break;
1336 	case IRAISE:
1337 		punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
1338 		break;
1339 	case IMULX:
1340 	case IDIVX:
1341 	case ICVTXX:
1342 	case IMULX0:
1343 	case IDIVX0:
1344 	case ICVTXX0:
1345 	case IMULX1:
1346 	case IDIVX1:
1347 	case ICVTXX1:
1348 	case ICVTFX:
1349 	case ICVTXF:
1350 	case IEXPW:
1351 	case IEXPL:
1352 	case IEXPF:
1353 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1354 		break;
1355 	case ISELF:
1356 		punt(i, DSTOP, optab[i->op]);
1357 		break;
1358 	}
1359 }
1360 
1361 static void
1362 preamble(void)
1363 {
1364 	ulong *start;
1365 
1366 	if(comvec)
1367 		return;
1368 
1369 	comvec = malloc(10 * sizeof(*code));
1370 	if(comvec == nil)
1371 		error(exNomem);
1372 	code = (ulong*)comvec;
1373 	start = code;
1374 
1375 	con((ulong)&R, RREG, 1);
1376 	mem(Ostw, O(REG, xpc), RREG, RLINK);
1377 	mem(Oldw, O(REG, PC), RREG, RA0);
1378 	mem(Oldw, O(REG, FP), RREG, RFP);
1379 	FM3I(2, Ojmpl, 0, RA0, RZ);
1380 	mem(Oldw, O(REG, MP), RREG, RMP);
1381 
1382 	segflush(comvec, 10 * sizeof(*code));
1383 
1384 	if(cflag > 4) {
1385 		print("comvec:\n");
1386 		das(start, code-start);
1387 	}
1388 }
1389 
1390 static void
1391 maccase(void)
1392 {
1393 	ulong *loop, *def, *lab1;
1394 
1395 	mem(Oldw, 0, RCON, RA3);		// n = t[0]
1396 	FM3I(2, Oadd, 4, RCON, RCON);
1397 	MOV(RA3, RA1);
1398 	FM3I(2, Osll, 1, RA1, RA1);
1399 	FM3(2, Oadd, RA3, RA1, RA1);
1400 	FM3I(2, Osll, 2, RA1, RA1);
1401 	FM3(3, Oldw, RCON, RA1, RLINK);
1402 
1403 	loop = code;
1404 	FM3(2, Ocmp, RZ, RA3, RZ);
1405 	def = code;
1406 	BRA(Oble, 0);
1407 	NOOP;
1408 
1409 	MOV(RA3, RA2);				// MOVL	DX, CX	n2 = n
1410 	FM3I(2, Osra, 1, RA2, RA2);		// SHR	CX,1	n2 = n2>>1
1411 	MOV(RA2, RA1);
1412 	FM3I(2, Osll, 1, RA1, RA1);
1413 	FM3(2, Oadd, RA2, RA1, RA1);
1414 	FM3I(2, Osll, 2, RA1, RA1);
1415 
1416 	FM3(3, Oldw, RA1, RCON, RTA);		// MOV	(RA1+RCON), RTA
1417 	FM3(2, Ocmp, RTA, RA0, RZ);
1418 	lab1 = code;
1419 	BRA(Obge, 0);
1420 	NOOP;
1421 	MOV(RA2, RA3);				// n = n2
1422 	BRA(Oba, loop-code);
1423 	NOOP;
1424 
1425 	PATCH(lab1);
1426 	FM3I(2, Oadd, 4, RA1, RTA);
1427 	FM3(3, Oldw, RTA, RCON, RTA);		// MOV	(RA1+RCON), RTA
1428 	FM3(2, Ocmp, RTA, RA0, RZ);
1429 	lab1 = code;
1430 	BRA(Obl, 0);
1431 	NOOP;
1432 
1433 	FM3I(2, Oadd, 12, RA1, RTA);
1434 	FM3(2, Oadd, RTA, RCON, RCON);
1435 	FM3(2, Osub, RA2, RA3, RA3);		// SUBL	CX, DX		n -= n2
1436 	FM3I(2, Oadd, -1, RA3, RA3);		// DECL	DX		n -= 1
1437 	BRA(Oba, loop-code);
1438 	NOOP;
1439 
1440 	PATCH(lab1);
1441 	FM3I(2, Oadd, 8, RA1, RTA);
1442 	FM3(3, Oldw, RTA, RCON, RLINK);
1443 
1444 	PATCH(def);
1445 	FM3I(2, Ojmpl, 0, RLINK, RZ);
1446 	NOOP;
1447 }
1448 
1449 static void
1450 macfrp(void)
1451 {
1452 	ulong *lab1, *lab2;
1453 
1454 	/* destroy the pointer in RA0 */
1455 	FM3I(2, Ocmp, -1, RA0, RZ);
1456 	lab1 = code;
1457 	BRA(Obe, 0);
1458 	NOOP;
1459 	mem(Oldw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
1460 	FM3I(2, Oadd, -1, RA2, RA2);
1461 	FM3I(2, Ocmp, 0, RA2, RZ);
1462 	lab2 = code;
1463 	BRA(Obne, 0);
1464 	NOOP;
1465 	mem(Ostw, O(REG, FP), RREG, RFP);
1466 	mem(Ostw, O(REG, st), RREG, RLINK);
1467 	CALL(rdestroy);
1468 	mem(Ostw, O(REG, s), RREG, RA0);
1469 	con((ulong)&R, RREG, 1);
1470 	mem(Oldw, O(REG, st), RREG, RLINK);
1471 	mem(Oldw, O(REG, FP), RREG, RFP);
1472 	RETURN;
1473 	mem(Oldw, O(REG, MP), RREG, RMP);
1474 	PATCH(lab2);
1475 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA0, RA2);
1476 	PATCH(lab1);
1477 	RETURN;
1478 	NOOP;
1479 }
1480 
1481 static void
1482 macret(void)
1483 {
1484 	Inst i;
1485 	ulong *cp1, *cp2, *cp3, *cp4, *cp5, *cp6;
1486 
1487 	FM3I(2, Ocmp, 0, RA1, RZ);
1488 	cp1 = code;
1489 	BRA(Obe, 0);				// t(Rfp) == 0
1490 	NOOP;
1491 
1492 	mem(Oldw, O(Type,destroy),RA1, RA0);
1493 	FM3I(2, Ocmp, 0, RA0, RZ);
1494 	cp2 = code;
1495 	BRA(Obe, 0);				// destroy(t(fp)) == 0
1496 	NOOP;
1497 
1498 	mem(Oldw, O(Frame,fp),RFP, RA2);
1499 	FM3I(2, Ocmp, 0, RA2, RZ);
1500 	cp3 = code;
1501 	BRA(Obe, 0);				// fp(Rfp) == 0
1502 	NOOP;
1503 
1504 	mem(Oldw, O(Frame,mr),RFP, RA3);
1505 	FM3I(2, Ocmp, 0, RA3, RZ);
1506 	cp4 = code;
1507 	BRA(Obe, 0);				// mr(Rfp) == 0
1508 	NOOP;
1509 
1510 	mem(Oldw, O(REG,M),RREG, RA2);
1511 	mem(Oldw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
1512 	FM3I(2, Oaddcc, -1, RA3, RA3);
1513 	cp5 = code;
1514 	BRA(Obe, 0);				// --ref(arg) == 0
1515 	NOOP;
1516 	mem(Ostw, O(Heap,ref)-sizeof(Heap),RA2, RA3);
1517 
1518 	mem(Oldw, O(Frame,mr),RFP, RA1);
1519 	mem(Ostw, O(REG,M),RREG, RA1);
1520 	mem(Oldw, O(Modlink,compiled),RA1, RA2);	// check for uncompiled code
1521 	mem(Oldw, O(Modlink,MP),RA1, RMP);
1522 	FM3I(2, Ocmp, 0, RA2, RZ);
1523 	cp6 = code;
1524 	BRA(Obe, 0);
1525 	NOOP;
1526 	mem(Ostw, O(REG,MP),RREG, RMP);
1527 
1528 	PATCH(cp4);
1529 	FM3I(2, Ojmpl, 0, RA0, RLINK);		// call destroy(t(fp))
1530 	NOOP;
1531 	mem(Ostw, O(REG,SP),RREG, RFP);
1532 	mem(Oldw, O(Frame,lr),RFP, RA1);
1533 	mem(Oldw, O(Frame,fp),RFP, RFP);
1534 	mem(Ostw, O(REG,FP),RREG, RFP);
1535 	FM3I(2, Ojmpl, 0, RA1, RZ);		// goto lr(Rfp)
1536 	NOOP;
1537 
1538 	PATCH(cp6);
1539 	FM3I(2, Ojmpl, 0, RA0, RLINK);		// call destroy(t(fp))
1540 	NOOP;
1541 	mem(Ostw, O(REG,SP),RREG, RFP);
1542 	mem(Oldw, O(Frame,lr),RFP, RA1);
1543 	mem(Oldw, O(Frame,fp),RFP, RFP);
1544 	mem(Ostw, O(REG,FP),RREG, RFP);
1545 	mem(Oldw, O(REG,xpc),RREG, RA2);
1546 	FM3I(2, Oadd, 0x8, RA2, RA2);
1547 	FM3I(2, Ojmpl, 0, RA2, RZ);		// return to uncompiled code
1548 	mem(Ostw, O(REG,PC),RREG, RA1);
1549 
1550 	PATCH(cp1);
1551 	PATCH(cp2);
1552 	PATCH(cp3);
1553 	PATCH(cp5);
1554 	i.add = AXNON;
1555 	punt(&i, TCHECK|NEWPC, optab[IRET]);
1556 }
1557 
1558 static void
1559 maccolr(void)
1560 {
1561 	ulong *br;
1562 
1563 	/* color the pointer in RA1 */
1564 	FM3I(2, Oadd, 1, RA0, RA0);
1565 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA1, RA0);
1566 	mem(Oldw, O(Heap, color)-sizeof(Heap), RA1, RA0);
1567 	mem(Oldw, 0, RA2, RA2);
1568 	FM3(2, Ocmp, RA0, RA2, RZ);
1569 	br = code;
1570 	BRA(Obe, 0);
1571 	con(propagator, RA2, 1);
1572 	mem(Ostw, O(Heap, color)-sizeof(Heap), RA1, RA2);
1573 	con((ulong)&nprop, RA2, 1);
1574 	RETURN;
1575 	mem(Ostw, 0, RA2, RA2);
1576 	PATCH(br);
1577 	RETURN;
1578 	NOOP;
1579 }
1580 
1581 static void
1582 macmcal(void)
1583 {
1584 	ulong *lab1, *lab2;
1585 
1586 	mem(Oldw, O(Modlink, prog), RA3, RA1);
1587 	FM3I(2, Ocmp, 0, RA1, RZ);
1588 	lab1 = code;
1589 	BRA(Obne, 0);
1590 	NOOP;
1591 
1592 	mem(Ostw, O(REG, st), RREG, RLINK);
1593 	mem(Ostw, O(REG, FP), RREG, RA2);
1594 	CALL(rmcall);				// CALL rmcall
1595 	mem(Ostw, O(REG, dt), RREG, RA0);
1596 
1597 	con((ulong)&R, RREG, 1);		// MOVL	$R, RREG
1598 	mem(Oldw, O(REG, st), RREG, RLINK);
1599 	mem(Oldw, O(REG, FP), RREG, RFP);
1600 	mem(Oldw, O(REG, MP), RREG, RMP);
1601 	RETURN;
1602 	NOOP;
1603 
1604 	PATCH(lab1);				// patch:
1605 	FM3(2, Oor, RA2, RZ, RFP);
1606 	mem(Ostw, O(REG, M), RREG, RA3);	// MOVL RA3, R.M
1607 	mem(Oldw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
1608 	FM3I(2, Oadd, 1, RA1, RA1);
1609 	mem(Ostw, O(Heap, ref)-sizeof(Heap), RA3, RA1);
1610 	mem(Oldw, O(Modlink, compiled), RA3, RA1);
1611 	mem(Oldw, O(Modlink, MP), RA3, RMP);	// MOVL R.M->MP, RMP
1612 	FM3I(2, Ocmp, 0, RA1, RZ);
1613 	lab2 = code;
1614 	BRA(Obe, 0);
1615 	mem(Ostw, O(REG, MP), RREG, RMP);	// MOVL RA3, R.MP	R.MP = ml->MP
1616 
1617 	FM3I(2, Ojmpl, 0, RA0, RZ);
1618 	NOOP;
1619 
1620 	PATCH(lab2);
1621 	mem(Ostw, O(REG,FP),RREG, RFP);
1622 	mem(Oldw, O(REG,xpc),RREG, RA1);
1623 	FM3I(2, Oadd, 0x8, RA1, RA1);
1624 	FM3I(2, Ojmpl, 0, RA1, RZ);		// call to uncompiled code
1625 	mem(Ostw, O(REG,PC),RREG, RA0);
1626 }
1627 
1628 static void
1629 macfram(void)
1630 {
1631 	ulong *lab1;
1632 
1633 	mem(Oldw, O(REG, SP), RREG, RA0);	// MOVL	R.SP, RA0
1634 	mem(Oldw, O(Type, size), RA3, RA1);
1635 	FM3(2, Oadd, RA0, RA1, RA0);
1636 	mem(Oldw, O(REG, TS), RREG, RA1);
1637 	FM3(2, Ocmp, RA1, RA0, RZ);
1638 	lab1 = code;
1639 	BRA(Obl, 0);
1640 	NOOP;
1641 
1642 	mem(Ostw, O(REG, s), RREG, RA3);
1643 	mem(Ostw, O(REG, st), RREG, RLINK);
1644 	CALL(extend);				// CALL	extend
1645 	mem(Ostw, O(REG, FP), RREG, RFP);	// MOVL	RFP, R.FP
1646 
1647 	con((ulong)&R, RREG, 1);
1648 	mem(Oldw, O(REG, st), RREG, RLINK);
1649 	mem(Oldw, O(REG, FP), RREG, RFP);	// MOVL	R.MP, RMP
1650 	mem(Oldw, O(REG, s), RREG, RA2);	// MOVL	R.s, *R.d
1651 	mem(Oldw, O(REG, MP), RREG, RMP);	// MOVL R.MP, RMP
1652 	RETURN;					// RET
1653 	NOOP;
1654 
1655 	PATCH(lab1);
1656 	mem(Oldw, O(REG, SP), RREG, RA2);	// MOVL	R.SP, RA2
1657 	mem(Ostw, O(REG, SP), RREG, RA0);	// MOVL	RA0, R.SP
1658 
1659 	mem(Ostw, O(Frame, t), RA2, RA3);	// MOVL	RA3, t(RA2) f->t = t
1660 	mem(Oldw, O(Type, initialize), RA3, RA3);
1661 	FM3I(2, Ojmpl, 0, RA3, RZ);
1662 	mem(Ostw, REGMOD*4, RA2, RZ);     	// MOVL $0, mr(RA2) f->mr
1663 }
1664 
1665 static void
1666 macmfra(void)
1667 {
1668 	mem(Ostw, O(REG, st), RREG, RLINK);
1669 	mem(Ostw, O(REG, s), RREG, RA3);	// Save type
1670 	mem(Ostw, O(REG, d), RREG, RA0);	// Save destination
1671 	CALL(rmfram);				// CALL rmfram
1672 	mem(Ostw, O(REG, FP), RREG, RFP);
1673 
1674 	con((ulong)&R, RREG, 1);
1675 	mem(Oldw, O(REG, st), RREG, RLINK);
1676 	mem(Oldw, O(REG, FP), RREG, RFP);
1677 	mem(Oldw, O(REG, MP), RREG, RMP);
1678 	RETURN;
1679 	NOOP;
1680 }
1681 
1682 void
1683 comd(Type *t)
1684 {
1685 	int i, j, m, c;
1686 
1687 	mem(Ostw, O(REG, dt), RREG, RLINK);
1688 	for(i = 0; i < t->np; i++) {
1689 		c = t->map[i];
1690 		j = i<<5;
1691 		for(m = 0x80; m != 0; m >>= 1) {
1692 			if(c & m) {
1693 				CALL(base+macro[MacFRP]);
1694 				mem(Oldw, j, RFP, RA0);
1695 			}
1696 			j += sizeof(WORD*);
1697 		}
1698 	}
1699 	mem(Oldw, O(REG, dt), RREG, RLINK);
1700 	RETURN;
1701 	NOOP;
1702 }
1703 
1704 void
1705 comi(Type *t)
1706 {
1707 	int i, j, m, c;
1708 
1709 	con((ulong)H, RA0, 1);
1710 	for(i = 0; i < t->np; i++) {
1711 		c = t->map[i];
1712 		j = i<<5;
1713 		for(m = 0x80; m != 0; m >>= 1) {
1714 			if(c & m)
1715 				mem(Ostw, j, RA2, RA0);
1716 			j += sizeof(WORD*);
1717 		}
1718 	}
1719 	RETURN;
1720 	NOOP;
1721 }
1722 
1723 void
1724 typecom(Type *t)
1725 {
1726 	int n;
1727 	ulong *tmp, *start;
1728 
1729 	if(t == nil || t->initialize != 0)
1730 		return;
1731 
1732 	tmp = mallocz(4096*sizeof(ulong), 0);
1733 	if(tmp == nil)
1734 		error(exNomem);
1735 
1736 	code = tmp;
1737 	comi(t);
1738 	n = code - tmp;
1739 	code = tmp;
1740 	comd(t);
1741 	n += code - tmp;
1742 	free(tmp);
1743 
1744 	n *= sizeof(*code);
1745 	code = mallocz(n, 0);
1746 	if(code == nil)
1747 		return;
1748 
1749 	start = code;
1750 	t->initialize = code;
1751 	comi(t);
1752 	t->destroy = code;
1753 	comd(t);
1754 
1755 	segflush(start, n);
1756 
1757 	if(cflag > 1)
1758 		print("typ= %.8p %4d i %.8p d %.8p asm=%d\n",
1759 			t, t->size, t->initialize, t->destroy, n);
1760 }
1761 
1762 static void
1763 patchex(Module *m, ulong *p)
1764 {
1765 	Handler *h;
1766 	Except *e;
1767 
1768 	if((h = m->htab) == nil)
1769 		return;
1770 	for( ; h->etab != nil; h++){
1771 		h->pc1 = p[h->pc1];
1772 		h->pc2 = p[h->pc2];
1773 		for(e = h->etab; e->s != nil; e++)
1774 			e->pc = p[e->pc];
1775 		if(e->pc != -1)
1776 			e->pc = p[e->pc];
1777 	}
1778 }
1779 
1780 int
1781 compile(Module *m, int size, Modlink *ml)
1782 {
1783 	Link *l;
1784 	Modl *e;
1785 	int i, n;
1786 	ulong *s, *tmp;
1787 
1788 	base = nil;
1789 	patch = mallocz(size*sizeof(*patch), 0);
1790 	tinit = malloc(m->ntype*sizeof(*tinit));
1791 	tmp = mallocz(1024*sizeof(ulong), 0);
1792 	if(tinit == nil || patch == nil || tmp == nil)
1793 		goto bad;
1794 
1795 	preamble();
1796 
1797 	mod = m;
1798 	n = 0;
1799 	pass = 0;
1800 	nlit = 0;
1801 
1802 	for(i = 0; i < size; i++) {
1803 		code = tmp;
1804 		comp(&m->prog[i]);
1805 		patch[i] = n;
1806 		n += code - tmp;
1807 	}
1808 
1809 	for(i = 0; i < nelem(mactab); i++) {
1810 		code = tmp;
1811 		mactab[i].gen();
1812 		macro[mactab[i].idx] = n;
1813 		n += code - tmp;
1814 	}
1815 
1816 	base = mallocz((n+nlit)*sizeof(*code), 0);
1817 	if(base == nil)
1818 		goto bad;
1819 
1820 	if(cflag > 1)
1821 		print("dis=%5d %5d sparc=%5d asm=%.8p lit=%d: %s\n",
1822 			size, size*sizeof(Inst), n, base, nlit, m->name);
1823 
1824 	pass++;
1825 	nlit = 0;
1826 	litpool = base+n;
1827 	code = base;
1828 
1829 	for(i = 0; i < size; i++) {
1830 		s = code;
1831 		comp(&m->prog[i]);
1832 		if(cflag > 2) {
1833 			print("%d %D\n", i, &m->prog[i]);
1834 			das(s, code-s);
1835 		}
1836 	}
1837 
1838 	for(i = 0; i < nelem(mactab); i++) {
1839 		s = code;
1840 		mactab[i].gen();
1841 		if(cflag > 2) {
1842 			print("%s:\n", mactab[i].name);
1843 			das(s, code-s);
1844 		}
1845 	}
1846 
1847 	if(n != (code - base))
1848 		error(exCphase);
1849 
1850 	for(l = m->ext; l->name; l++) {
1851 		l->u.pc = (Inst*)RELPC(patch[l->u.pc-m->prog]);
1852 		typecom(l->frame);
1853 	}
1854 	if(ml != nil) {
1855 		e = &ml->links[0];
1856 		for(i = 0; i < ml->nlinks; i++) {
1857 			e->u.pc = (Inst*)RELPC(patch[e->u.pc-m->prog]);
1858 			typecom(e->frame);
1859 			e++;
1860 		}
1861 	}
1862 	for(i = 0; i < m->ntype; i++) {
1863 		if(tinit[i] != 0)
1864 			typecom(m->type[i]);
1865 	}
1866 	patchex(m, patch);
1867 	m->entry = (Inst*)RELPC(patch[mod->entry-mod->prog]);
1868 	free(patch);
1869 	free(tinit);
1870 	free(tmp);
1871 	free(m->prog);
1872 	m->prog = (Inst*)base;
1873 	m->compiled = 1;
1874 	segflush(base, n*sizeof(*base));
1875 	return 1;
1876 bad:
1877 	free(patch);
1878 	free(tinit);
1879 	free(tmp);
1880 	free(base);
1881 	return 0;
1882 }
1883