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