xref: /inferno-os/libinterp/comp-mips.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
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