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