xref: /inferno-os/libinterp/comp-power.c (revision 2a571cc0ece4073eb56d5ccfc3e061a09a353e13)
1 #include "lib9.h"
2 #include "isa.h"
3 #include "interp.h"
4 #include "raise.h"
5 
6 /*
7  * Copyright © 1997 C H Forsyth (forsyth@terzarima.net)
8  */
9 
10 #define	ROMABLE	0	/* costs something to zero patch vectors */
11 #define	RESCHED 1	/* check for interpreter reschedule */
12 
13 #define PATCH(ptr)		   *ptr |= ((ulong)code-(ulong)ptr) & 0xfffc
14 
15 #define T(r)	*((void**)(R.r))
16 
17 #define	XO(o,xo)	(((o)<<26)|((xo)<<1))
18 
19 /* botch: ARRR, AIRR, LRRR, etc have dest first (will fix soon) */
20 
21 #define	OPARRR(o,d,a,b)	((o)|((d)<<21)|((a)<<16)|((b)<<11))
22 #define	ARRR(o,d,a,b)		gen((o)|((d)<<21)|((a)<<16)|((b)<<11))
23 #define	AIRR(o,d,a,v)		gen((o)|((d)<<21)|((a)<<16)|((v)&0xFFFF))
24 #define	IRR(o,v,a,d)	AIRR((o),(d),(a),(v))
25 #define	RRR(o,b,a,d)	ARRR((o),(d),(a),(b))
26 #define	LRRR(o,a,s,b)		ARRR((o),(s),(a),(b))
27 #define	LIRR(o,a,s,v)		AIRR((o),(s),(a),(v))
28 #define	Bx(li,aa)		gen((18<<26)|((li)&0x3FFFFFC)|((aa)<<1))
29 #define	RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
30 					(((mb)&31L)<<6)|(((me)&31L)<<1))
31 #define	MFSPR(s, d)	gen(XO(31,339) | ((d)<<21) | ((s)<<11))
32 #define	MTSPR(s, d)	gen(XO(31,467) | ((s)<<21) | ((d)<<11));
33 
34 #define	MFCR(d)		gen(XO(31,19) | ((d)<<21))
35 #define	MTCRF(s, mask)	gen(XO(31,144) | ((s)<<21) | ((mask)<<12))
36 #define	MTCR(s)		MTCRF(s, 0xff)
37 
38 #define	SLWI(d,a,n)	gen(slw((d),(a),(n),0))
39 #define	LRET()	gen(Oblr)
40 
41 #define	SETR0()	if(macjit){	AIRR(Oaddi, Rzero, 0, 0); }		/* set R0 to 0 */
42 
43 /* assumes H can be formed from signed halfword */
44 #define	CMPH(r)		AIRR(Ocmpi, Rcrf0, (r), (ulong)H);
45 #define NOTNIL(r)	(CMPH((r)), CCALL(EQ, bounds))
46 
47 enum
48 {
49 	Rzero	= 0,	/* zero by design, not definition (P9/Inferno) */
50 
51 	Rsp = 1,
52 	Rsb = 2,
53 	Rarg	= 3,
54 
55 	Ro1	= 8,
56 	Ro2	= 9,
57 	Ro3	= 10,
58 	Ri	= 11,
59 	Rj	= 12,
60 
61 	Rmp	= 13,
62 	Rfp	= 14,
63 	Rreg	= 15,
64 	Rta	= 16,		/* unused */
65 	Rpic	= 17,		/* address for computed goto, for move to CTR or LR */
66 
67 	Rcon = 26,	/* constant builder; temporary */
68 	/* 27, 28, 29, 30 are potentially external registers (P9/Inferno) */
69 	Rlink = 31,	/* holds copies of LR; linker temp */
70 
71 	Rfret	= 0,
72 	Rf1	= 4,
73 	Rf2	= 6,
74 	Rfcvi	= 27,	/* floating conversion constant (P9/Inferno) */
75 	Rfzero = 28,	/* 0.0 (P9/Inferno) */
76 	Rfhalf = 29,	/* 0.5 (P9/Inferno) */
77 
78 	Rlr = 8<<5,	/* SPR(LR) */
79 	Rctr = 9<<5,	/* SPR(CTR) */
80 
81 	Rcrf0 = 0,		/* condition code field 0 */
82 	Rcrf1 = 1<<2,	/* condition code field 1 */
83 
84 	Rcrbrel = 31,	/* condition code bit set to force relinquish */
85 
86 	Olwz	= XO(32, 0),
87 	Olwzu = XO(33, 0),
88 	Olwzx = XO(31, 23),
89 	Olbz	= XO(34, 0),
90 	Olbzu = XO(35, 0),
91 	Olbzx = XO(31, 87),
92 	Olfd	= XO(50, 0),
93 	Olhz	= XO(40, 0),
94 	Olhzx = XO(31, 279),
95 	Ostw	= XO(36, 0),
96 	Ostwu = XO(37, 0),
97 	Ostwx = XO(31, 151),
98 	Ostb	= XO(38, 0),
99 	Ostbu = XO(39, 0),
100 	Ostbx = XO(31, 215),
101 	Osth	= XO(44,0),
102 	Osthx = XO(31, 407),
103 	Ostfd	= XO(54, 0),
104 	Ostfdu	= XO(55, 0),
105 
106 	Oaddc	= XO(31,10),
107 	Oadde	= XO(31, 138),
108 	Oaddi	= XO(14, 0),	/* simm */
109 	Oaddic_	= XO(13, 0),
110 	Oaddis	= XO(15, 0),
111 	Ocrxor	= XO(19, 193),
112 	Ofadd	= XO(63, 21),
113 	Ofcmpo	= XO(63, 32),
114 	Ofctiwz	= XO(63, 15),
115 	Ofsub	= XO(63, 20),
116 	Ofmr	= XO(63, 72),
117 	Ofmul	= XO(63, 25),
118 	Ofdiv	= XO(63, 18),
119 	Ofneg	= XO(63, 40),
120 	Oori		= XO(24,0),	/* uimm */
121 	Ooris	= XO(25,0),	/* uimm */
122 	Odivw	= XO(31, 491),
123 	Odivwu	= XO(31, 459),
124 	Omulhw	= XO(31, 75),
125 	Omulhwu	= XO(31, 11),
126 	Omulli	= XO(7, 0),
127 	Omullw	= XO(31, 235),
128 	Osubf	= XO(31, 40),
129 	Osubfc	= XO(31,8),
130 	Osubfe	= XO(31,136),
131 	Osubfic	= XO(8, 0),
132 	Oadd	= XO(31, 266),
133 	Oand	= XO(31, 28),
134 	Oneg	= XO(31, 104),
135 	Oor		= XO(31, 444),
136 	Oxor		= XO(31, 316),
137 
138 	Ocmpi = XO(11, 0),
139 	Ocmp = XO(31, 0),
140 	Ocmpl = XO(31, 32),
141 	Ocmpli = XO(10,0),
142 
143 	Orlwinm = XO(21, 0),
144 	Oslw	= XO(31, 24),
145 	Osraw = XO(31,792),
146 	Osrawi =	XO(31,824),
147 	Osrw = XO(31,536),
148 
149 	Cnone	= OPARRR(0,20,0,0),	/* unconditional */
150 	Ceq		= OPARRR(0,12,2,0),
151 	Cle		= OPARRR(0,4,1,0),
152 	Clt		= OPARRR(0,12,0,0),
153 	Cdnz	= OPARRR(0,16,0,0),
154 	Cgt		= OPARRR(0,12,1,0),
155 	Cne		= OPARRR(0,4,2,0),
156 	Cge		= OPARRR(0,4,0,0),
157 	Cle1		= OPARRR(0,4,5,0),	/* Cle on CR1 */
158 	Crelq	= OPARRR(0,12,Rcrbrel,0),	/* relinquish */
159 	Cnrelq	= OPARRR(0,4,Rcrbrel,0),	/* not relinquish */
160 	Cpredict	= OPARRR(0,1,0,0),	/* reverse prediction */
161 	Lk		= 1,
162 	Aa		= 2,
163 
164 	Obeq	= OPARRR(16<<26,12,2,0),
165 	Obge	= OPARRR(16<<26,4,0,0),
166 	Obgt		= OPARRR(16<<26,12,1,0),
167 	Oble		= OPARRR(16<<26,4,1,0),
168 	Oblt		= OPARRR(16<<26,12,0,0),
169 	Obne	= OPARRR(16<<26,4,2,0),
170 
171 	Ob		= XO(18, 0),
172 	Obc		= XO(16, 0),
173 	Obcctr	= XO(19,528),
174 	Obcctrl	= Obcctr | Lk,
175 	Obctr	= Obcctr | Cnone,
176 	Obctrl	= Obctr | Lk,
177 	Obclr	= XO(19, 16),
178 	Oblr		= Obclr | Cnone,
179 	Oblrl		= Oblr | Lk,
180 
181 	Olea	= 100,		// pseudo op
182 
183 	SRCOP	= (1<<0),
184 	DSTOP	= (1<<1),
185 	WRTPC	= (1<<2),	/* update R.PC */
186 	TCHECK	= (1<<3),	/* check R.t for continue/ret */
187 	NEWPC	= (1<<4),	/* goto R.PC */
188 	DBRAN	= (1<<5),	/* dest is branch */
189 	THREOP	= (1<<6),
190 
191 	Lg2Rune	= sizeof(Rune)==4? 2: 1,
192 	ANDAND	= 1,
193 	OROR,
194 	EQAND,
195 
196 	MacRET	= 0,
197 	MacFRP,
198 	MacCASE,
199 	MacFRAM,
200 	MacCOLR,
201 	MacMCAL,
202 	MacMFRA,
203 	MacCVTFW,
204 	MacRELQ,
205 	MacEND,
206 	NMACRO
207 };
208 
209 	void	(*comvec)(void);
210 	int	macjit;
211 extern	long	das(ulong*);
212 static	ulong*	code;
213 static	ulong*	base;
214 static	ulong*	patch;
215 static	int	pass;
216 static	Module*	mod;
217 static	ulong*	tinit;
218 static	ulong*	litpool;
219 static	int	nlit;
220 static	ulong	macro[NMACRO];
221 static	void	ldbigc(long, int);
222 static	void	rdestroy(void);
223 static	void	macret(void);
224 static	void	macfrp(void);
225 static	void	maccase(void);
226 static	void	maccvtfw(void);
227 static	void	macfram(void);
228 static	void	maccolr(void);
229 static	void	macend(void);
230 static	void	macmcal(void);
231 static	void	macmfra(void);
232 static	void	macrelq(void);
233 static	void	movmem(Inst*);
234 
235 struct
236 {
237 	int	o;
238 	void	(*f)(void);
239 } macinit[] =
240 {
241 	MacFRP,		macfrp,		/* decrement and free pointer */
242 	MacRET,		macret,		/* return instruction */
243 	MacCASE,	maccase,	/* case instruction */
244 	MacCOLR,	maccolr,	/* increment and color pointer */
245 	MacFRAM,	macfram,	/* frame instruction */
246 	MacMCAL,	macmcal,	/* mcall bottom half */
247 	MacMFRA,	macmfra,	/* punt mframe because t->initialize==0 */
248 	MacCVTFW,	maccvtfw,
249 	MacRELQ,		macrelq,	/* reschedule */
250 	MacEND,		macend,
251 	0
252 };
253 
254 static void
255 rdestroy(void)
256 {
257 	destroy(R.s);
258 }
259 
260 static void
261 rmcall(void)
262 {
263 	Frame *f;
264 	Prog *p;
265 
266 	if((void*)R.dt == H)
267 		error(exModule);
268 
269 	f = (Frame*)R.FP;
270 	if(f == H)
271 		error(exModule);
272 
273 	f->mr = nil;
274 	((void(*)(Frame*))R.dt)(f);
275 	R.SP = (uchar*)f;
276 	R.FP = f->fp;
277 	if(f->t == nil)
278 		unextend(f);
279 	else
280 		freeptrs(f, f->t);
281 	p = currun();
282 	if(p->kill != nil)
283 		error(p->kill);
284 }
285 
286 static void
287 rmfram(void)
288 {
289 	Type *t;
290 	Frame *f;
291 	uchar *nsp;
292 
293 	t = (Type*)R.s;
294 	if(t == H)
295 		error(exModule);
296 	nsp = R.SP + t->size;
297 	if(nsp >= R.TS) {
298 		R.s = t;
299 		extend();
300 		T(d) = R.s;
301 		return;
302 	}
303 	f = (Frame*)R.SP;
304 	R.SP = nsp;
305 	f->t = t;
306 	f->mr = nil;
307 	initmem(t, f);
308 	T(d) = f;
309 }
310 
311 void
312 urk(char *s)
313 {
314 	print("compile failed: %s\n", s);	// debugging
315 	error(exCompile);	// production
316 }
317 
318 static void
319 gen(ulong o)
320 {
321 	*code++ = o;
322 }
323 
324 static void
325 br(ulong op, ulong disp)
326 {
327 	*code++ = op | (disp & 0xfffc);
328 }
329 
330 static void
331 mfspr(int d, int s)
332 {
333 	MFSPR(s, d);
334 }
335 
336 static void
337 mtspr(int d, int s)
338 {
339 	MTSPR(s, d);
340 }
341 
342 static ulong
343 slw(int d, int s, int v, int rshift)
344 {
345 	int m0, m1;
346 
347 	if(v < 0 || v > 32)
348 		urk("slw v");
349 	if(v < 0)
350 		v = 0;
351 	else if(v > 32)
352 		v = 32;
353 	if(rshift) {	/* shift right */
354 		m0 = v;
355 		m1 = 31;
356 		v = 32-v;
357 	} else {
358 		m0 = 0;
359 		m1 = 31-v;
360 	}
361 	return RLW(Orlwinm, d, s, v, m0, m1);
362 }
363 
364 static void
365 jr(int reg)
366 {
367 	mtspr(Rctr, reg);	/* code would be faster if this were loaded well before branch */
368 	gen(Obctr);
369 }
370 
371 static void
372 jrl(int reg)
373 {
374 	mtspr(Rctr, reg);
375 	gen(Obctrl);
376 }
377 
378 static void
379 jrc(int op, int reg)
380 {
381 	mtspr(Rctr, reg);
382 	gen(Obcctr | op);
383 }
384 
385 static long
386 brdisp(ulong *dest)
387 {
388 	ulong d, top;
389 
390 	d = (ulong)dest - (ulong)code;
391 	if(!ROMABLE)
392 		return d & 0x3fffffc;
393 	top = d>>25;
394 	if(top == 0 || top == 0x7F){
395 		/* fits in 26-bit signed displacement */
396 		return d & 0x3fffffc;
397 	}
398 	return -1;
399 }
400 
401 static void
402 jmp(ulong *dest)
403 {
404 	long d;
405 
406 	if((d = brdisp(dest)) < 0){
407 		ldbigc((ulong)dest, Rpic);	/* Rpic & Rctr must be free */
408 		jr(Rpic);
409 	} else
410 		gen(Ob | d);
411 }
412 
413 static void
414 jmpl(ulong *dest)
415 {
416 	long d;
417 
418 	if((d = brdisp(dest)) < 0){
419 		ldbigc((ulong)dest, Rpic);	/* Rpic must be free */
420 		jrl(Rpic);
421 	} else
422 		gen(Ob | d | Lk);
423 }
424 
425 static void
426 jmpc(int op, ulong *dest)
427 {
428 	ldbigc((ulong)dest, Rpic);
429 	jrc(op, Rpic);
430 }
431 
432 static int
433 bigc(long c)
434 {
435 	if(c >= -0x8000 && c <= 0x7FFF)
436 		return 0;
437 	return 1;
438 }
439 
440 static void
441 ldbigc(long c, int reg)
442 {
443 	AIRR(Oaddis, reg,Rzero,c>>16);
444 	LIRR(Oori, reg,reg,c);
445 }
446 
447 static void
448 ldc(long c, int reg)
449 {
450 	if(!bigc(c))
451 		AIRR(Oaddi, reg, Rzero, c);
452 	else if((ulong)c <= 0xFFFF)
453 		LIRR(Oori, reg, Rzero, c);
454 	else if((c&0xFFFF) == 0)
455 		LIRR(Ooris, reg, Rzero, c>>16);
456 	else {
457 		AIRR(Oaddis, reg,Rzero,c>>16);
458 		LIRR(Oori, reg,reg,c);
459 	}
460 }
461 
462 static void
463 mem(int inst, long disp, int rm, int r)
464 {
465 	if(bigc(disp)) {
466 		ldc(disp, Rcon);
467 		switch(inst){
468 		default: 		urk("mem op"); break;
469 		case Olea:		inst = Oadd; break;
470 		case Olwz:	inst = Olwzx; break;
471 		case Olbz:		inst = Olbzx; break;
472 		case Olhz:		inst = Olhzx; break;
473 		case Ostw:	inst = Ostwx; break;
474 		case Ostb:		inst = Ostbx; break;
475 		case Osth:		inst = Osthx; break;
476 		}
477 		ARRR(inst, r, Rcon, rm);
478 	} else {
479 		if(inst == Olea)
480 			inst = Oaddi;
481 		AIRR(inst, r, rm,disp);
482 	}
483 }
484 
485 static void
486 opx(int mode, Adr *a, int op, int reg)
487 {
488 	ulong c;
489 	int r, rx, lea;
490 
491 	lea = 0;
492 	if(op == Olea){
493 		lea = 1;
494 		op = Oaddi;
495 	}
496 	switch(mode) {
497 	case AFP:
498 		c = a->ind;
499 		if(bigc(c))
500 			urk("bigc op1b 1");
501 		AIRR(op, reg, Rfp,c);
502 		break;
503 	case AMP:
504 		c = a->ind;
505 		if(bigc(c))
506 			urk("bigc op1b 2");
507 		AIRR(op, reg, Rmp,c);
508 		break;
509 	case AIMM:
510 		if(lea) {
511 			if(a->imm != 0) {
512 				ldc(a->imm, reg);
513 				AIRR(Ostw, reg, Rreg,O(REG,st));
514 			} else
515 				AIRR(Ostw, Rzero, Rreg,O(REG,st));
516 			AIRR(Oaddi, reg, Rreg,O(REG,st));
517 		} else
518 			ldc(a->imm, reg);
519 		return;
520 	case AIND|AFP:
521 		r = Rfp;
522 		goto offset;
523 	case AIND|AMP:
524 		r = Rmp;
525 	offset:
526 		c = a->i.s;
527 		rx = Ri;
528 		if(lea || op == Olwz)
529 			rx = reg;
530 		AIRR(Olwz, rx, r,a->i.f);
531 		if(!lea || c != 0)
532 			AIRR(op, reg, rx,c);
533 		break;
534 	}
535 }
536 
537 static void
538 opwld(Inst *i, int op, int reg)
539 {
540 	opx(USRC(i->add), &i->s, op, reg);
541 }
542 
543 static void
544 opwst(Inst *i, int op, int reg)
545 {
546 	opx(UDST(i->add), &i->d, op, reg);
547 }
548 
549 static void
550 op2(Inst *i, int op, int reg)
551 {
552 	int lea;
553 
554 	lea = 0;
555 	if(op == Olea){
556 		op = Oaddi;
557 		lea = 1;
558 	}
559 	switch(i->add & ARM) {
560 	case AXNON:
561 		if(lea)
562 			op = Olea;
563 		opwst(i, op, reg);
564 		return;
565 	case AXIMM:
566 		if(lea)
567 			urk("op2/lea");
568 		ldc((short)i->reg, reg);
569 		return;
570 	case AXINF:
571 		IRR(op, i->reg,Rfp, reg);
572 		break;
573 	case AXINM:
574 		IRR(op, i->reg,Rmp, reg);
575 		break;
576 	}
577 }
578 
579 static void
580 op12(Inst *i, int b1flag, int b2flag)
581 {
582 	int o1, o2;
583 
584 	o1 = Olwz;
585 	if(b1flag)
586 		o1 = Olbz;
587 	o2 = Olwz;
588 	if(b2flag)
589 		o2 = Olbz;
590 	if((i->add & ARM) == AXIMM) {
591 		opwld(i, o1, Ro1);
592 		op2(i, o2, Ro2);
593 	} else {
594 		op2(i, o2, Ro2);
595 		opwld(i, o1, Ro1);
596 	}
597 }
598 
599 static void
600 op13(Inst *i, int o1, int o2)
601 {
602 	opwld(i, o1, Ro1);
603 	opwst(i, o2, Ro1);
604 }
605 
606 static ulong
607 branch(Inst *i)
608 {
609 	ulong rel;
610 
611 	if(base == 0)
612 		return 0;
613 	rel = (ulong)(base+patch[i->d.ins - mod->prog]);
614 	rel -= (ulong)code;
615 	if(rel & 3 || (long)rel <= -(1<<16) || (long)rel >= 1<<16)
616 		urk("branch off");
617 	return rel & 0xfffc;
618 }
619 
620 static void
621 schedcheck(Inst *i)
622 {
623 	ulong *cp;
624 
625 	if(i != nil && i->d.ins != nil && i->d.ins > i)
626 		return;	/* only backwards jumps can loop: needn't check forward ones */
627 	cp = code;
628 	gen(Obc | Cnrelq | Cpredict);
629 	jmpl(base+macro[MacRELQ]);
630 	PATCH(cp);
631 }
632 
633 static void
634 literal(ulong imm, int roff)
635 {
636 	nlit++;
637 
638 	ldbigc((ulong)litpool, Ro1);
639 	IRR(Ostw, roff, Rreg, Ro1);
640 
641 	if(pass == 0)
642 		return;
643 
644 	*litpool = imm;
645 	litpool++;
646 }
647 
648 static void
649 bounds(void)
650 {
651 	/* mem(Ostw, O(REG,FP), Rreg, Rfp); */
652 	error(exBounds);
653 }
654 
655 static void
656 punt(Inst *i, int m, void (*fn)(void))
657 {
658 	ulong pc;
659 
660 	if(m & SRCOP) {
661 		if(UXSRC(i->add) == SRC(AIMM))
662 			literal(i->s.imm, O(REG, s));
663 		else {
664 			opwld(i, Olea, Ro1);
665 			mem(Ostw, O(REG, s), Rreg, Ro1);
666 		}
667 	}
668 	if(m & DSTOP) {
669 		opwst(i, Olea, Ro3);
670 		IRR(Ostw, O(REG,d),Rreg, Ro3);
671 	}
672 	if(m & WRTPC) {
673 		pc = patch[i-mod->prog+1];
674 		ldbigc((ulong)(base+pc), Ro1);
675 		IRR(Ostw, O(REG,PC),Rreg, Ro1);
676 	}
677 	if(m & DBRAN) {
678 		pc = patch[i->d.ins-mod->prog];
679 		literal((ulong)(base+pc), O(REG, d));
680 	}
681 
682 	switch(i->add&ARM) {
683 	case AXNON:
684 		if(m & THREOP) {
685 			IRR(Olwz, O(REG,d),Rreg, Ro2);
686 			IRR(Ostw, O(REG,m),Rreg, Ro2);
687 		}
688 		break;
689 	case AXIMM:
690 		literal((short)i->reg, O(REG,m));
691 		break;
692 	case AXINF:
693 		mem(Olea, i->reg, Rfp, Ro2);
694 		mem(Ostw, O(REG, m), Rreg, Ro2);
695 		break;
696 	case AXINM:
697 		mem(Olea, i->reg, Rmp, Ro2);
698 		mem(Ostw, O(REG, m), Rreg, Ro2);
699 		break;
700 	}
701 	IRR(Ostw, O(REG,FP),Rreg, Rfp);
702 
703 	jmpl((ulong*)fn);
704 
705 	ldc((ulong)&R, Rreg);
706 	SETR0();
707 	if(m & TCHECK) {
708 		IRR(Olwz, O(REG,t),Rreg, Ro1);
709 		IRR(Olwz, O(REG,xpc),Rreg, Ro2);
710 		IRR(Ocmpi, 0, Ro1, Rcrf0);
711 		mtspr(Rctr, Ro2);
712 		gen(Obcctr | Cne);
713 	}
714 	IRR(Olwz, O(REG,FP),Rreg, Rfp);
715 	IRR(Olwz, O(REG,MP),Rreg, Rmp);
716 
717 	if(m & NEWPC) {
718 		IRR(Olwz, O(REG,PC),Rreg, Ro1);
719 		jr(Ro1);
720 	}
721 }
722 
723 static void
724 comgoto(Inst *i)
725 {
726 	WORD *t, *e;
727 
728 	opwld(i, Olwz, Ro2);
729 	opwst(i, Olea, Ro3);
730 	SLWI(Ro2, Ro2, 2);
731 	ARRR(Olwzx, Ro1, Ro3,Ro2);
732 	jr(Ro1);
733 
734 	if(pass == 0)
735 		return;
736 
737 	t = (WORD*)(mod->origmp+i->d.ind);
738 	e = t + t[-1];
739 	t[-1] = 0;
740 	while(t < e) {
741 		t[0] = (ulong)(base + patch[t[0]]);
742 		t++;
743 	}
744 }
745 
746 static void
747 comcase(Inst *i, int w)
748 {
749 	int l;
750 	WORD *t, *e;
751 
752 	if(w != 0) {
753 		opwld(i, Olwz, Ro1);		// v
754 		opwst(i, Olea, Ro3);		// table
755 		jmp(base+macro[MacCASE]);
756 	}
757 
758 	t = (WORD*)(mod->origmp+i->d.ind+4);
759 	l = t[-1];
760 
761 	/* have to take care not to relocate the same table twice -
762 	 * the limbo compiler can duplicate a case instruction
763 	 * during its folding phase
764 	 */
765 
766 	if(pass == 0) {
767 		if(l >= 0)
768 			t[-1] = -l-1;	/* Mark it not done */
769 		return;
770 	}
771 	if(l >= 0)			/* Check pass 2 done */
772 		return;
773 	t[-1] = -l-1;			/* Set real count */
774 	e = t + t[-1]*3;
775 	while(t < e) {
776 		t[2] = (ulong)(base + patch[t[2]]);
777 		t += 3;
778 	}
779 	t[0] = (ulong)(base + patch[t[0]]);
780 }
781 
782 static void
783 comcasel(Inst *i)
784 {
785 	int l;
786 	WORD *t, *e;
787 
788 	t = (WORD*)(mod->origmp+i->d.ind+8);
789 	l = t[-2];
790 	if(pass == 0) {
791 		if(l >= 0)
792 			t[-2] = -l-1;	/* Mark it not done */
793 		return;
794 	}
795 	if(l >= 0)			/* Check pass 2 done */
796 		return;
797 	t[-2] = -l-1;			/* Set real count */
798 	e = t + t[-2]*6;
799 	while(t < e) {
800 		t[4] = (ulong)base + patch[t[4]];
801 		t += 6;
802 	}
803 	t[0] = (ulong)base + patch[t[0]];
804 }
805 
806 static void
807 commframe(Inst *i)
808 {
809 	ulong *cp1, *cp2;
810 
811 	opwld(i, Olwz, Ri);	// must use Ri for MacFRAM
812 	CMPH(Ri);
813 	cp1 = code;
814 	br(Obeq, 0);
815 
816 	if((i->add&ARM) == AXIMM) {
817 		mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame), Ri, Ri);
818 	} else {
819 		op2(i, Olwz, Ro2);
820 		SLWI(Ro2, Ro2, 3);	// assumes sizeof(Modl) == 8
821 		ARRR(Oadd, Ri, Ro2, Ro2);
822 		mem(Olwz, OA(Modlink, links)+O(Modl, frame), Ri, Ri);
823 	}
824 
825 	AIRR(Olwz, Ro2, Ri,O(Type,initialize));
826 	AIRR(Ocmpi, Rcrf0, Ro2, 0);
827 	cp2 = code;
828 	br(Obne, 0);
829 
830 	opwst(i, Olea, Rj);
831 
832 	PATCH(cp1);
833 	ldbigc((ulong)(base+patch[i-mod->prog+1]), Rpic);
834 	mtspr(Rlr, Rpic);
835 	jmp(base+macro[MacMFRA]);
836 
837 	PATCH(cp2);
838 	jmpl(base+macro[MacFRAM]);
839 	opwst(i, Ostw, Ro1);
840 }
841 
842 static void
843 commcall(Inst *i)
844 {
845 	opwld(i, Olwz, Ro1);				// f in Ro1
846 	AIRR(Olwz, Ro3, Rreg,O(REG,M));
847 	AIRR(Ostw, Rfp, Ro1,O(Frame,fp));			// f->fp = R.FP
848 	AIRR(Ostw, Ro3, Ro1,O(Frame,mr));			// f->mr = R.M
849 	opwst(i, Olwz, Ri);
850 	if((i->add&ARM) == AXIMM) {
851 		mem(Olwz, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), Ri, Rj);	// ml->entry in Rj
852 	} else {
853 		op2(i, Olwz, Rj);
854 		SLWI(Rj, Rj, 3);	// assumes sizeof(Modl) == 8
855 		ARRR(Oadd, Ri, Rj, Rj);
856 		mem(Olwz, OA(Modlink, links)+O(Modl, u.pc), Rj, Rj);
857 	}
858 	jmpl(base+macro[MacMCAL]);
859 }
860 
861 static int
862 swapbraop(int b)
863 {
864 	switch(b) {
865 	case Obge:
866 		return Oble;
867 	case Oble:
868 		return Obge;
869 	case Obgt:
870 		return Oblt;
871 	case Oblt:
872 		return Obgt;
873 	}
874 	return b;
875 }
876 
877 static void
878 cbra(Inst *i, int op)
879 {
880 	if(RESCHED)
881 		schedcheck(i);
882 	if(UXSRC(i->add) == SRC(AIMM) && !bigc(i->s.imm)) {
883 		op2(i, Olwz, Ro1);
884 		AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm);
885 		op = swapbraop(op);
886 	} else if((i->add & ARM) == AXIMM) {
887 		opwld(i, Olwz, Ro1);
888 		AIRR(Ocmpi, Rcrf0, Ro1, i->reg);
889 	} else {
890 		op12(i, 0, 0);
891 		ARRR(Ocmp, Rcrf0, Ro1, Ro2);
892 	}
893 	br(op, branch(i));
894 }
895 
896 static void
897 cbrab(Inst *i, int op)
898 {
899 	if(RESCHED)
900 		schedcheck(i);
901 	if(UXSRC(i->add) == SRC(AIMM)) {
902 		op2(i, Olbz, Ro1);
903 		AIRR(Ocmpi, Rcrf0, Ro1, i->s.imm&0xFF);
904 		op = swapbraop(op);
905 	} else if((i->add & ARM) == AXIMM) {
906 		opwld(i, Olbz, Ro1);
907 		AIRR(Ocmpi, Rcrf0, Ro1, i->reg&0xFF);	// mask i->reg?
908 	} else {
909 		op12(i, 1, 1);
910 		ARRR(Ocmp, Rcrf0, Ro1, Ro2);
911 	}
912 	br(op, branch(i));
913 }
914 
915 static void
916 cbraf(Inst *i, int op)
917 {
918 	if(RESCHED)
919 		schedcheck(i);
920 	opwld(i, Olfd, Rf1);
921 	op2(i, Olfd, Rf2);
922 	ARRR(Ofcmpo, Rcrf0, Rf1, Rf2);
923 	br(op, branch(i));
924 }
925 
926 static void
927 cbral(Inst *i, int cms, int cls, int mode)
928 {
929 	ulong *cp;
930 
931 	if(RESCHED)
932 		schedcheck(i);
933 	cp = nil;
934 	opwld(i, Olea, Ri);
935 	op2(i, Olea, Rj);
936 	IRR(Olwz, 0,Ri, Ro1);
937 	IRR(Olwz, 0,Rj, Ro2);
938 	ARRR(Ocmp, Rcrf0, Ro1, Ro2);
939 	switch(mode) {
940 	case ANDAND:
941 		cp = code;
942 		br(cms, 0);
943 		break;
944 	case OROR:
945 		br(cms, branch(i));
946 		break;
947 	case EQAND:
948 		br(cms, branch(i));
949 		cp = code;
950 		br(Obne, 0);
951 		break;
952 	}
953 	IRR(Olwz, 4,Ri, Ro1);
954 	IRR(Olwz, 4,Rj, Ro2);
955 	ARRR(Ocmpl, Rcrf0, Ro1, Ro2);
956 	br(cls, branch(i));
957 	if(cp)
958 		PATCH(cp);
959 }
960 
961 static void
962 shrl(Inst *i)
963 {
964 //	int c;
965 
966 //	if(USRC(i->add) != AIMM) {
967 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
968 		return;
969 //	}
970 /*
971 	c = i->s.imm;
972 	op2(i, Olea, Ro3);
973 	IRR(Olwz, 0,Ro3, Ro1);
974 	if(c >= 32) {
975 		if((i->add&ARM) != AXNON)
976 			opwst(i, Olea, Ro3);
977 		SRR(Osra, 31, Ro1, Ro2);
978 		IRR(Ostw, 0,Ro3, Ro2);
979 		if(c >= 64) {
980 			IRR(Ostw, 4,Ro3, Ro2);
981 			return;
982 		}
983 		if(c > 32)
984 			SRR(Osra, c-32, Ro1, Ro1);
985 		IRR(Ostw, 4,Ro3, Ro1);
986 		return;
987 	}
988 	IRR(Olwz, 4,Ro3, Ro2);
989 	if((i->add&ARM) != AXNON)
990 		opwst(i, Olea, Ro3);
991 	if(c != 0) {
992 		SRR(Osll, 32-c, Ro1, Ri);
993 		SRR(Osra, c, Ro1, Ro1);
994 		SRR(Osrl, c, Ro2, Ro2);
995 		RRR(Oor, Ri, Ro2, Ro2);
996 	}
997 	IRR(Ostw, 4,Ro3, Ro2);
998 	IRR(Ostw, 0,Ro3, Ro1);
999 */
1000 }
1001 
1002 static void
1003 shll(Inst *i)
1004 {
1005 //	int c;
1006 
1007 //	if(USRC(i->add) != AIMM) {
1008 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1009 		return;
1010 //	}
1011 /*
1012 	c = i->s.imm;
1013 	if(c >= 64) {
1014 		opwst(i, Olea, Ro3);
1015 		IRR(Ostw, 0,Ro3, Rzero);
1016 		IRR(Ostw, 4,Ro3, Rzero);
1017 		return;
1018 	}
1019 	op2(i, Olea, Ro3);
1020 	if(c >= 32) {
1021 		IRR(Olwz, 4,Ro3, Ro1);
1022 		if((i->add&ARM) != AXNON)
1023 			opwst(i, Olea, Ro3);
1024 		IRR(Ostw, 4,Ro3, Rzero);
1025 		if(c > 32)
1026 			SRR(Osll, c-32, Ro1, Ro1);
1027 		IRR(Ostw, 0,Ro3, Ro1);
1028 		return;
1029 	}
1030 	IRR(Olwz, 4,Ro3, Ro2);
1031 	IRR(Olwz, 0,Ro3, Ro1);
1032 	if((i->add&ARM) != AXNON)
1033 		opwst(i, Olea, Ro3);
1034 	if(c != 0) {
1035 		SRR(Osrl, 32-c, Ro2, Ri);
1036 		SRR(Osll, c, Ro2, Ro2);
1037 		SRR(Osll, c, Ro1, Ro1);
1038 		RRR(Oor, Ri, Ro1, Ro1);
1039 	}
1040 	IRR(Ostw, 4,Ro3, Ro2);
1041 	IRR(Ostw, 0,Ro3, Ro1);
1042 */
1043 }
1044 
1045 static void
1046 compdbg(void)
1047 {
1048 	print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s);
1049 }
1050 
1051 static void
1052 comp(Inst *i)
1053 {
1054 	int o, q, b;
1055 	ulong *cp, *cp1;
1056 	char buf[64];
1057 
1058 	if(0) {
1059 		Inst xx;
1060 		xx.add = AXIMM|SRC(AIMM);
1061 		xx.s.imm = (ulong)code;
1062 		xx.reg = i-mod->prog;
1063 		punt(&xx, SRCOP, compdbg);
1064 	}
1065 
1066 	switch(i->op) {
1067 	default:
1068 		snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i);
1069 		error(buf);
1070 		break;
1071 	case IMCALL:
1072 		if((i->add&ARM) == AXIMM)
1073 			commcall(i);
1074 		else
1075 			punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]);
1076 		break;
1077 	case ISEND:
1078 	case IRECV:
1079 	case IALT:
1080 		punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]);
1081 		break;
1082 	case ISPAWN:
1083 		punt(i, SRCOP|DBRAN, optab[i->op]);
1084 		break;
1085 	case IBNEC:
1086 	case IBEQC:
1087 	case IBLTC:
1088 	case IBLEC:
1089 	case IBGTC:
1090 	case IBGEC:
1091 		punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]);
1092 		break;
1093 	case ICASEC:
1094 		comcase(i, 0);
1095 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
1096 		break;
1097 	case ICASEL:
1098 		comcasel(i);
1099 		punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]);
1100 		break;
1101 	case IADDC:
1102 	case IMULL:
1103 	case IDIVL:
1104 	case IMODL:
1105 	case IMNEWZ:
1106 	case ILSRW:
1107 	case ILSRL:
1108 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1109 		break;
1110 	case IMFRAME:
1111 		if((i->add&ARM) == AXIMM)
1112 			commframe(i);
1113 		else
1114 			punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1115 		break;
1116 	case ILOAD:
1117 	case INEWA:
1118 	case INEWAZ:
1119 	case INEW:
1120 	case INEWZ:
1121 	case ISLICEA:
1122 	case ISLICELA:
1123 	case ICONSB:
1124 	case ICONSW:
1125 	case ICONSL:
1126 	case ICONSF:
1127 	case ICONSM:
1128 	case ICONSMP:
1129 	case ICONSP:
1130 	case IMOVMP:
1131 	case IHEADMP:
1132 	case IINSC:
1133 	case ICVTAC:
1134 	case ICVTCW:
1135 	case ICVTWC:
1136 	case ICVTCL:
1137 	case ICVTLC:
1138 	case ICVTFC:
1139 	case ICVTCF:
1140 	case ICVTFL:
1141 	case ICVTLF:
1142 	case ICVTRF:
1143 	case ICVTFR:
1144 	case ICVTWS:
1145 	case ICVTSW:
1146 	case IMSPAWN:
1147 	case ICVTCA:
1148 	case ISLICEC:
1149 	case INBALT:
1150 		punt(i, SRCOP|DSTOP, optab[i->op]);
1151 		break;
1152 	case INEWCM:
1153 	case INEWCMP:
1154 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1155 		break;
1156 	case INEWCB:
1157 	case INEWCW:
1158 	case INEWCF:
1159 	case INEWCP:
1160 	case INEWCL:
1161 		punt(i, DSTOP|THREOP, optab[i->op]);
1162 		break;
1163 	case IEXIT:
1164 		punt(i, 0, optab[i->op]);
1165 		break;
1166 	case ICVTWB:
1167 		op13(i, Olwz, Ostb);
1168 		break;
1169 	case ICVTBW:
1170 		op13(i, Olbz, Ostw);
1171 		break;
1172 	case IMOVB:
1173 		if(USRC(i->add) == AIMM && i->s.imm == 0) {
1174 			opwst(i, Ostb, Rzero);
1175 			break;
1176 		}
1177 		op13(i, Olbz, Ostb);
1178 		break;
1179 	case IMOVW:
1180 		if(USRC(i->add) == AIMM && i->s.imm == 0) {
1181 			opwst(i, Ostw, Rzero);
1182 			break;
1183 		}
1184 		op13(i, Olwz, Ostw);
1185 		break;
1186 	case ICVTLW:
1187 		opwld(i, Olea, Ro1);
1188 		AIRR(Olwz, Ro2, Ro1,4);
1189 		opwst(i, Ostw, Ro2);
1190 		break;
1191 	case ICVTWL:
1192 		opwld(i, Olwz, Ro1);
1193 		opwst(i, Olea, Ro2);
1194 		LRRR(Osrawi, Ro3, Ro1, 31);
1195 		AIRR(Ostw, Ro1, Ro2,4);
1196 		AIRR(Ostw, Ro3, Ro2,0);
1197 		break;
1198 	case IHEADM:
1199 		opwld(i, Olwz, Ro1);
1200 		AIRR(Oaddi, Ro1, Ro1,OA(List,data));
1201 		movmem(i);
1202 		break;
1203 	case IMOVM:
1204 		opwld(i, Olea, Ro1);
1205 		movmem(i);
1206 		break;
1207 	case IRET:
1208 		jmp(base+macro[MacRET]);
1209 		break;
1210 	case IFRAME:
1211 		if(UXSRC(i->add) != SRC(AIMM)) {
1212 			punt(i, SRCOP|DSTOP, optab[i->op]);
1213 			break;
1214 		}
1215 		tinit[i->s.imm] = 1;
1216 		ldc((ulong)mod->type[i->s.imm], Ri);
1217 		jmpl(base+macro[MacFRAM]);
1218 		opwst(i, Ostw, Ro1);
1219 		break;
1220 	case ILEA:
1221 		op13(i, Olea, Ostw);
1222 		break;
1223 	case IHEADW:
1224 		opwld(i, Olwz, Ro1);
1225 		AIRR(Olwz, Ro1, Ro1,OA(List,data));
1226 		opwst(i, Ostw, Ro1);
1227 		break;
1228 	case IHEADF:
1229 		opwld(i, Olwz, Ro1);
1230 		AIRR(Olfd, Rf1, Ro1,OA(List,data));
1231 		opwst(i, Ostfd, Rf1);
1232 		break;
1233 	case IHEADB:
1234 		opwld(i, Olwz, Ro1);
1235 		AIRR(Olbz, Ro1, Ro1,OA(List,data));
1236 		opwst(i, Ostb, Ro1);
1237 		break;
1238 	case ITAIL:
1239 		opwld(i, Olwz, Ro1);
1240 		AIRR(Olwz, Ro1, Ro1,O(List,tail));
1241 		goto movp;
1242 	case IMOVP:
1243 		opwld(i, Olwz, Ro1);
1244 		goto movp;
1245 	case IHEADP:
1246 		opwld(i, Olwz, Ro1);
1247 		AIRR(Olwz, Ro1, Ro1,OA(List,data));
1248 	movp:
1249 		CMPH(Ro1);
1250 		cp = code;
1251 		br(Obeq, 0);
1252 		jmpl(base+macro[MacCOLR]);
1253 		PATCH(cp);
1254 		opwst(i, Olea, Ro3);
1255 		AIRR(Olwz, Ri, Ro3,0);
1256 		AIRR(Ostw, Ro1, Ro3,0);
1257 		jmpl(base+macro[MacFRP]);
1258 		break;
1259 	case ILENA:
1260 		opwld(i, Olwz, Ri);
1261 		ldc(0, Ro1);
1262 		CMPH(Ri);
1263 		cp = code;
1264 		br(Obeq, 0);
1265 		AIRR(Olwz, Ro1, Ri,O(Array,len));
1266 		PATCH(cp);
1267 		opwst(i, Ostw, Ro1);
1268 		break;
1269 	case ILENC:
1270 		opwld(i, Olwz, Ri);
1271 		ldc(0, Ro1);
1272 		CMPH(Ri);
1273 		cp = code;
1274 		br(Obeq, 0);
1275 		AIRR(Olwz, Ro1, Ri,O(String,len));
1276 		AIRR(Ocmpi, Rcrf0, Ro1, 0);
1277 		br(Obge, 2*4);	// BGE 2(PC); skip
1278 		ARRR(Oneg, Ro1, Ro1, 0);
1279 		PATCH(cp);
1280 		opwst(i, Ostw, Ro1);
1281 		break;
1282 	case ILENL:
1283 		opwld(i, Olwz, Ro1);
1284 		ldc(0, Ro3);
1285 		CMPH(Ro1);
1286 		cp = code;
1287 		br(Obeq, 0);
1288 
1289 		cp1 = code;
1290 		AIRR(Olwz, Ro1, Ro1,O(List,tail));
1291 		AIRR(Oaddi, Ro3, Ro3, 1);
1292 		CMPH(Ro1);
1293 		br(Obne, ((ulong)cp1-(ulong)code));
1294 
1295 		PATCH(cp);
1296 		opwst(i, Ostw, Ro3);
1297 		break;
1298 	case IMOVL:
1299 		opwld(i, Olea, Ro1);
1300 		AIRR(Olwz, Ro2, Ro1,0);
1301 		AIRR(Olwz, Ro3, Ro1,4);
1302 		opwst(i, Olea, Ro1);
1303 		AIRR(Ostw, Ro2, Ro1,0);
1304 		AIRR(Ostw, Ro3, Ro1,4);
1305 		break;
1306 	case IMOVF:
1307 		opwld(i, Olfd, Rf1);
1308 		opwst(i, Ostfd, Rf1);
1309 		break;
1310 	case ICVTFW:
1311 		if(!macjit){
1312 			opwld(i, Olfd, Rf1);
1313 			jmpl(base+macro[MacCVTFW]);
1314 			opwst(i, Ostw, Ro1);
1315 			break;
1316 		}
1317 	case ICVTWF:
1318 		punt(i, SRCOP|DSTOP, optab[i->op]);
1319 		break;
1320 	case INEGF:
1321 		opwld(i, Olfd, Rf1);
1322 		ARRR(Ofneg, Rf2, 0, Rf1);
1323 		opwst(i, Ostfd, Rf2);
1324 		break;
1325 	case IXORL:
1326 	case IORL:
1327 	case IANDL:
1328 	case IADDL:
1329 	case ISUBL:
1330 		opwld(i, Olea, Ro1);
1331 		op2(i, Olea, Ro3);
1332 
1333 		AIRR(Olwz, Rj, Ro1,4);	/* ls */
1334 		AIRR(Olwz, Ro2, Ro3,4);
1335 		AIRR(Olwz, Ri, Ro1,0);	/* ms */
1336 		AIRR(Olwz, Ro1, Ro3,0);
1337 
1338 		switch(i->op) {
1339 		case IXORL:
1340 			o = Oxor;
1341 			goto l1;
1342 		case IORL:
1343 			o = Oor;
1344 			goto l1;
1345 		case IANDL:
1346 			o = Oand;
1347 		l1:
1348 			LRRR(o, Ro1, Ri, Ro1);
1349 			LRRR(o, Ro2, Rj, Ro2);
1350 			break;
1351 		case IADDL:
1352 			RRR(Oaddc, Rj,Ro2, Ro2);
1353 			RRR(Oadde, Ri,Ro1, Ro1);
1354 			break;
1355 		case ISUBL:
1356 			RRR(Osubfc, Ro2,Rj, Ro2);
1357 			RRR(Osubfe, Ro1,Ri, Ro1);
1358 			break;
1359 		}
1360 		if((i->add&ARM) != AXNON)
1361 			opwst(i, Olea, Ro3);
1362 		IRR(Ostw, 0,Ro3, Ro1);
1363 		IRR(Ostw, 4,Ro3, Ro2);
1364 		break;
1365 	case ISHLL:
1366 		shll(i);
1367 		break;
1368 	case ISHRL:
1369 		shrl(i);
1370 		break;
1371 	case IADDF:	o = Ofadd; goto f1;
1372 	case ISUBF:	o = Ofsub; goto f1;
1373 	case IMULF:	o = Ofmul; goto f1;
1374 	case IDIVF:	o = Ofdiv; goto f1;
1375 	f1:
1376 		opwld(i, Olfd, Rf1);
1377 		op2(i, Olfd, Rf2);
1378 		if(o == Ofmul)
1379 			gen(o | (Rf2<<21) | (Rf2<<16) | (Rf1<<6));	/* odd one out: op D,A,-,C */
1380 		else
1381 			ARRR(o, Rf2, Rf2, Rf1);
1382 		opwst(i, Ostfd, Rf2);
1383 		break;
1384 
1385 	case IBEQF:
1386 		cbraf(i, Obeq);
1387 		break;
1388 	case IBGEF:
1389 		cbraf(i, Obge);
1390 	case IBGTF:
1391 		cbraf(i, Obgt);
1392 		break;
1393 	case IBLEF:
1394 		cbraf(i, Oble);
1395 		break;
1396 	case IBLTF:
1397 		cbraf(i, Oblt);
1398 		break;
1399 	case IBNEF:
1400 		cbraf(i, Obne);
1401 		break;
1402 
1403 	case IBLTB:
1404 		cbrab(i, Oblt);
1405 		break;
1406 	case IBLEB:
1407 		cbrab(i, Oble);
1408 		break;
1409 	case IBGTB:
1410 		cbrab(i, Obgt);
1411 		break;
1412 	case IBGEB:
1413 		cbrab(i, Obge);
1414 		break;
1415 	case IBEQB:
1416 		cbrab(i, Obeq);
1417 		break;
1418 	case IBNEB:
1419 		cbrab(i, Obne);
1420 		break;
1421 
1422 	case IBLTW:
1423 		cbra(i, Oblt);
1424 		break;
1425 	case IBLEW:
1426 		cbra(i, Oble);
1427 		break;
1428 	case IBGTW:
1429 		cbra(i, Obgt);
1430 		break;
1431 	case IBGEW:
1432 		cbra(i, Obge);
1433 		break;
1434 	case IBEQW:
1435 		cbra(i, Obeq);
1436 		break;
1437 	case IBNEW:
1438 		cbra(i, Obne);
1439 		break;
1440 
1441 	case IBEQL:
1442 		cbral(i, Obne, Obeq, ANDAND);
1443 		break;
1444 	case IBNEL:
1445 		cbral(i, Obne, Obne, OROR);
1446 		break;
1447 	case IBLTL:
1448 		cbral(i, Oblt, Oblt, EQAND);
1449 		break;
1450 	case IBLEL:
1451 		cbral(i, Oblt, Oble, EQAND);
1452 		break;
1453 	case IBGTL:
1454 		cbral(i, Obgt, Obgt, EQAND);
1455 		break;
1456 	case IBGEL:
1457 		cbral(i, Obgt, Obge, EQAND);
1458 		break;
1459 
1460 	case ISUBB:
1461 	case IADDB:
1462 	case IANDB:
1463 	case IORB:
1464 	case IXORB:
1465 	case IMODB:
1466 	case IDIVB:
1467 	case IMULB:
1468 		b = 1;
1469 		op12(i, b, b);
1470 		goto s2;
1471 	case ISHLB:
1472 	case ISHRB:
1473 		b = 1;
1474 		op12(i, 0, b);
1475 		goto s2;
1476 	case ISUBW:
1477 	case IADDW:
1478 	case IANDW:
1479 	case IORW:
1480 	case IXORW:
1481 	case ISHLW:
1482 	case ISHRW:
1483 	case IMODW:
1484 	case IDIVW:
1485 	case IMULW:
1486 		b = 0;
1487 		op12(i, b, b);
1488 	s2:
1489 		q = 0;
1490 		switch(i->op) {
1491 		case ISUBB:
1492 		case ISUBW:	o = Osubf; q = Osubfic;
1493 			// TO DO: if immediate operand, should use opcode q
1494 			USED(q);
1495 			ARRR(o, Ro3, Ro1, Ro2);
1496 			break;
1497 		case IADDB:
1498 		case IADDW:	o = Oadd; q = Oaddi; goto c1;
1499 		case IMULB:
1500 		case IMULW:	o = Omullw; q = Omulli; goto c1;
1501 		case IDIVB:
1502 		case IDIVW:	o = Odivw; goto c1;
1503 		c1:
1504 			// TO DO: if immediate operand, should use opcode q
1505 			USED(q);
1506 			ARRR(o, Ro3, Ro2, Ro1);
1507 			break;
1508 		case IANDB:
1509 		case IANDW:	o = Oand; goto c2;
1510 		case IORB:
1511 		case IORW:	o = Oor; goto c2;
1512 		case IXORB:
1513 		case IXORW:	o = Oxor; goto c2;
1514 		case ISHLB:
1515 		case ISHLW:	o = Oslw; goto c2;
1516 		case ISHRB:
1517 		case ISHRW:	o = Osraw; goto c2;
1518 		c2:
1519 			LRRR(o, Ro3,Ro2,Ro1);
1520 			break;
1521 		case IMODB:
1522 		case IMODW:
1523 			ARRR(Odivw, Ro3, Ro2, Ro1);
1524 			ARRR(Omullw, Ro3, Ro3, Ro1);
1525 			ARRR(Osubf, Ro3, Ro3, Ro2);
1526 			break;
1527 		}
1528 		opwst(i, b? Ostb: Ostw, Ro3);
1529 		break;
1530 	case ICALL:
1531 		opwld(i, Olwz, Ro1);	/* f = T(s) */
1532 		ldbigc((ulong)(base+patch[i-mod->prog+1]), Ro2);	/* R.pc */
1533 		AIRR(Ostw, Rfp, Ro1,O(Frame,fp));	/* f->fp = R.fp */
1534 		AIRR(Ostw, Ro2, Ro1,O(Frame,lr));	/* f->lr = R.pc */
1535 		AIRR(Oaddi, Rfp, Ro1, 0);	/* R.fp = (uchar*)f */
1536 		jmp(base+patch[i->d.ins - mod->prog]);
1537 		break;
1538 	case IJMP:
1539 		if(RESCHED)
1540 			schedcheck(i);
1541 		jmp(base+patch[i->d.ins - mod->prog]);
1542 		break;
1543 	case IGOTO:
1544 		comgoto(i);
1545 		break;
1546 	case IINDC:
1547 		opwld(i, Olwz, Ro1);			// Ro1 = string
1548 		if((i->add&ARM) != AXIMM)
1549 			op2(i, Olwz, Ro2);			// Ro2 = i
1550 		AIRR(Olwz, Ri, Ro1,O(String,len));	// len<0 => index Runes, otherwise bytes
1551 		AIRR(Oaddi, Ro1, Ro1,O(String,data));
1552 		AIRR(Ocmpi, Rcrf0, Ri, 0);
1553 		if(bflag){
1554 			br(Obge, 2*4);
1555 			ARRR(Oneg, Ri, Ri, 0);
1556 			if((i->add&ARM) != AXIMM)
1557 				ARRR(Ocmpl, Rcrf1, Ri, Ro2);		/* CMPU len, i */
1558 			else
1559 				AIRR(Ocmpli, Rcrf1, Ri, i->reg);	/* CMPU len, i */
1560 			jmpc(Cle1, (ulong*)bounds);
1561 		}
1562 		cp = code;
1563 		br(Obge, 0);
1564 		if((i->add&ARM) != AXIMM){
1565 			SLWI(Ro2, Ro2, Lg2Rune);
1566 			if(sizeof(Rune) == 4)
1567 				ARRR(Olwz, Ro3, Ro1, Ro2);
1568 			else
1569 				ARRR(Olhzx, Ro3, Ro1, Ro2);
1570 		} else
1571 			mem(Olwz, (short)i->reg<<Lg2Rune, Ro1, Ro3);	/* BUG: TO DO: 16-bit signed displacement */
1572 		gen(Ob | (2*4));	// skip
1573 		PATCH(cp);
1574 		if((i->add&ARM) != AXIMM)
1575 			ARRR(Olbzx, Ro3, Ro1, Ro2);
1576 		else
1577 			AIRR(Olbz, Ro3, Ro1,i->reg);
1578 		opwst(i, Ostw, Ro3);
1579 		break;
1580 	case IINDX:
1581 	case IINDB:
1582 	case IINDF:
1583 	case IINDW:
1584 	case IINDL:
1585 		opwld(i, Olwz, Ro1);			/* Ro1 = a */
1586 		opwst(i, Olwz, Ro3);			/* Ro3 = i */
1587 		if(bflag){
1588 			AIRR(Olwz, Ro2, Ro1, O(Array, len));		/* Ro2 = a->len */
1589 			ARRR(Ocmpl, Rcrf0, Ro3, Ro2);			/* CMPU i, len */
1590 			jmpc(Cge, (ulong*)bounds);
1591 		}
1592 		// TO DO: check a != H
1593 		AIRR(Olwz, Ro2, Ro1,O(Array,data));	/* Ro2 = a->data */
1594 		switch(i->op) {
1595 		case IINDX:
1596 			AIRR(Olwz, Ri, Ro1,O(Array,t));			// Ri = a->t
1597 			AIRR(Olwz, Ro1, Ri,O(Type,size));		// Ro1 = a->t->size
1598 			ARRR(Omullw, Ro3, Ro3, Ro1);			// Ro3 = i*size
1599 			break;
1600 		case IINDL:
1601 		case IINDF:
1602 			SLWI(Ro3, Ro3, 3);		/* Ro3 = i*8 */
1603 			break;
1604 		case IINDW:
1605 			SLWI(Ro3, Ro3, 2);		/* Ro3 = i*4 */
1606 			break;
1607 		case IINDB:
1608 			/* no further work */
1609 			break;
1610 		}
1611 		ARRR(Oadd, Ro2, Ro2, Ro3);		/* Ro2 = i*size + data */
1612 		op2(i, Ostw, Ro2);
1613 		break;
1614 	case ICASE:
1615 		comcase(i, 1);
1616 		break;
1617 	case IRAISE:
1618 		punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
1619 		break;
1620 	case IMULX:
1621 	case IDIVX:
1622 	case ICVTXX:
1623 	case IMULX0:
1624 	case IDIVX0:
1625 	case ICVTXX0:
1626 	case IMULX1:
1627 	case IDIVX1:
1628 	case ICVTXX1:
1629 	case ICVTFX:
1630 	case ICVTXF:
1631 	case IEXPW:
1632 	case IEXPL:
1633 	case IEXPF:
1634 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1635 		break;
1636 	case ISELF:
1637 		punt(i, DSTOP, optab[i->op]);
1638 		break;
1639 	}
1640 }
1641 
1642 enum {
1643 	PREFLEN = 64,	/* max instruction words in comvec */
1644 };
1645 
1646 static void
1647 preamble(void)
1648 {
1649 	ulong *s;
1650 
1651 	if(comvec != nil)
1652 		return;
1653 	s = code = malloc(PREFLEN*sizeof(*code));
1654 	if(s == nil)
1655 		error(exNomem);
1656 
1657 #ifdef __ELF__
1658 	if(macjit) {
1659 		ulong *cp;
1660 		int r;
1661 
1662 		/*
1663 		 * ELF frame:
1664 		 *  0(%sp) - back chain
1665 		 *  4(%sp) - callee's LR save slot
1666 		 *  8(%sp) to 36(%sp) - 8 words of parameter list area
1667 		 * 40(%sp) to 48(%sp) - pad to 16 byte alignment/local vars
1668 		 */
1669 		mfspr(Ro1, Rlr);
1670 		AIRR(Ostw, Ro1, Rsp,4);
1671 		AIRR(Ostwu, Rsp, Rsp,-128);
1672 
1673 		MFCR(Ro1);
1674 		AIRR(Ostw, Ro1, Rsp,52);
1675 		for (r = 14; r < 32; ++r)
1676 			AIRR(Ostw, r, Rsp,r*4);
1677 
1678 		cp = code;
1679 		gen(Ob | Lk);
1680 
1681 		AIRR(Olwz, Ro1, Rsp,52);
1682 		MTCR(Ro1);
1683 		for (r = 14; r < 32; ++r)
1684 			AIRR(Olwz, r, Rsp,r*4);
1685 		AIRR(Oaddi, Rsp, Rsp, 128);
1686 
1687 		AIRR(Olwz, Ro1, Rsp,4);
1688 		mtspr(Rlr, Ro1);
1689 		LRET();
1690 
1691 		PATCH(cp);
1692 	}
1693 #endif	/* __ELF__ */
1694 
1695 	ldc((ulong)&R, Rreg);
1696 	SETR0();
1697 	mfspr(Rlink, Rlr);
1698 	AIRR(Ostw, Rlink, Rreg,O(REG,xpc));
1699 	AIRR(Olwz, Ri, Rreg,O(REG,PC));
1700 	mtspr(Rctr, Ri);
1701 	AIRR(Olwz, Rfp, Rreg,O(REG,FP));
1702 	AIRR(Olwz, Rmp, Rreg,O(REG,MP));
1703 	gen(Obctr);
1704 	if(code >= (ulong*)(s + PREFLEN))
1705 		urk("preamble");
1706 	comvec = (void*)s;
1707 	segflush(s, PREFLEN*sizeof(*s));
1708 	if(cflag > 3) {
1709 		print("comvec\n");
1710 		while(s < code)
1711 			s += das(s);
1712 	}
1713 }
1714 
1715 static void
1716 macfrp(void)
1717 {
1718 	CMPH(Ri);
1719 	gen(Obclr | Ceq);	// arg == $H? => return
1720 
1721 	AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
1722 	AIRR(Oaddic_, Rj, Ro2, -1);		// ref(arg)-- and test
1723 	AIRR(Ostw, Rj, Ri,O(Heap,ref)-sizeof(Heap));
1724 	gen(Obclr | Cne);		// ref(arg) nonzero? => return
1725 
1726 	AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap));	// restore ref count of 1 for destroy
1727 	mfspr(Rlink, Rlr);
1728 	AIRR(Ostw, Rlink, Rreg,O(REG,st));
1729 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));
1730 	AIRR(Ostw, Ri, Rreg,O(REG,s));
1731 
1732 	jmpl((ulong*)rdestroy);				// CALL	destroy
1733 
1734 	ldc((ulong)&R, Rreg);
1735 	SETR0();
1736 	AIRR(Olwz, Rlink, Rreg,O(REG,st));
1737 	mtspr(Rlr, Rlink);
1738 	AIRR(Olwz, Rfp, Rreg,O(REG,FP));
1739 	AIRR(Olwz, Rmp, Rreg,O(REG,MP));
1740 	LRET();
1741 }
1742 
1743 static void
1744 macret(void)
1745 {
1746 	ulong *cp1, *cp2, *cp3, *cp4, *cp5, *linterp;
1747 	Inst i;
1748 
1749 	AIRR(Olwz, Ro1, Rfp,O(Frame,t));
1750 	AIRR(Ocmpi, Rcrf0, Ro1, 0);
1751 	cp1 = code;
1752 	br(Obeq, 0);		// t(Rfp) == 0
1753 
1754 	AIRR(Olwz, Rpic, Ro1,O(Type,destroy));
1755 	AIRR(Ocmpi, Rcrf0, Rpic, 0);
1756 	cp2 = code;
1757 	br(Obeq, 0);		// destroy(t(fp)) == 0
1758 
1759 	AIRR(Olwz, Ro2, Rfp,O(Frame,fp));
1760 	AIRR(Ocmpi, Rcrf0, Ro2, 0);
1761 	cp3 = code;
1762 	br(Obeq, 0);		// fp(Rfp) == 0
1763 
1764 	AIRR(Olwz, Ro3, Rfp,O(Frame,mr));
1765 	AIRR(Ocmpi, Rcrf0, Ro3, 0);
1766 	cp4 = code;
1767 	br(Obeq, 0);		// mr(Rfp) == 0
1768 
1769 	AIRR(Olwz, Ro2, Rreg,O(REG,M));
1770 	AIRR(Olwz, Ro3, Ro2,O(Heap,ref)-sizeof(Heap));
1771 	AIRR(Oaddic_, Ro3, Ro3, -1);	// --ref(arg), set cc
1772 	cp5 = code;
1773 	br(Obeq, 0);	// --ref(arg) == 0?
1774 	AIRR(Ostw, Ro3, Ro2,O(Heap,ref)-sizeof(Heap));
1775 
1776 	AIRR(Olwz, Ro1, Rfp,O(Frame,mr));
1777 	AIRR(Ostw, Ro1, Rreg,O(REG,M));
1778 	AIRR(Olwz, Rmp, Ro1,O(Modlink,MP));
1779 	AIRR(Ostw, Rmp, Rreg,O(REG,MP));
1780 	AIRR(Olwz, Ro3, Ro1,O(Modlink,compiled));	// R.M->compiled?
1781 	AIRR(Ocmpi, Rcrf0, Ro3, 0);
1782 	linterp = code;
1783 	br(Obeq, 0);
1784 
1785 	PATCH(cp4);
1786 	jrl(Rpic);			// call destroy(t(fp))
1787 	AIRR(Ostw, Rfp, Rreg,O(REG,SP));
1788 	AIRR(Olwz, Ro1, Rfp,O(Frame,lr));
1789 	AIRR(Olwz, Rfp, Rfp,O(Frame,fp));
1790 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));	// R.FP = Rfp
1791 	jr(Ro1);				// goto lr(Rfp)
1792 
1793 	PATCH(linterp);
1794 	jrl(Rpic);			// call destroy(t(fp))
1795 	AIRR(Ostw, Rfp, Rreg,O(REG,SP));
1796 	AIRR(Olwz, Ro1, Rfp,O(Frame,lr));
1797 	AIRR(Olwz, Rfp, Rfp,O(Frame,fp));
1798 	AIRR(Ostw, Ro1, Rreg,O(REG,PC));	// R.PC = fp->lr
1799 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));	// R.FP = Rfp
1800 	AIRR(Olwz, Rpic, Rreg,O(REG,xpc));
1801 	mtspr(Rlr, Rpic);
1802 	gen(Oblr);		// return to xec uncompiled code
1803 
1804 	PATCH(cp1);
1805 	PATCH(cp2);
1806 	PATCH(cp3);
1807 	PATCH(cp5);
1808 	i.add = AXNON;
1809 	punt(&i, TCHECK|NEWPC, optab[IRET]);
1810 }
1811 
1812 static void
1813 maccase(void)
1814 {
1815 	ulong *cp1, *cp2, *cp3, *loop;
1816 
1817 /*
1818  * Ro1 = value (input arg), t
1819  * Ro2 = count, n
1820  * Ro3 = table pointer (input arg)
1821  * Ri  = n/2, n2
1822  * Rj  = pivot element t+n/2*3, l
1823  */
1824 
1825 	IRR(Olwz, 0,Ro3, Ro2);		// count
1826 	IRR(Oaddi, 0,Ro3, Rlink);	// initial table pointer
1827 
1828 	loop = code;			// loop:
1829 	AIRR(Ocmpi, Rcrf0, Ro2, 0);
1830 	cp1 = code;
1831 	br(Oble, 0);	// n <= 0? goto out
1832 	LRRR(Osrawi, Ri, Ro2, 1);		// n2 = n>>1
1833 	SLWI(Rj, Ri, 1);
1834 	ARRR(Oadd, Rj, Rj, Ri);
1835 	SLWI(Rj, Rj, 2);
1836 	ARRR(Oadd, Rj, Rj, Ro3);	// l = t + n2*3;
1837 	AIRR(Olwz, Rpic, Rj,4);
1838 	ARRR(Ocmp, Rcrf0, Ro1, Rpic);
1839 	cp2 = code;
1840 	br(Oblt, 0);		// v < l[1]? goto low
1841 
1842 	IRR(Olwz, 8,Rj, Rpic);
1843 	ARRR(Ocmp, Rcrf0, Ro1, Rpic);
1844 	cp3 = code;
1845 	br(Obge, 0);		// v >= l[2]? goto high
1846 
1847 	IRR(Olwz, 12,Rj, Ro3);		// found
1848 	jr(Ro3);
1849 
1850 	PATCH(cp2);	// low:
1851 	IRR(Oaddi, 0, Ri, Ro2);	// n = n2
1852 	jmp(loop);
1853 
1854 	PATCH(cp3);	// high:
1855 	IRR(Oaddi, 12, Rj, Ro3);	// t = l+3;
1856 	IRR(Oaddi, 1, Ri, Rpic);
1857 	RRR(Osubf, Ro2, Rpic, Ro2);	// n -= n2 + 1
1858 	jmp(loop);
1859 
1860 	PATCH(cp1);	// out:
1861 	IRR(Olwz, 0,Rlink, Ro2);		// initial n
1862 	SLWI(Ro3, Ro2, 1);
1863 	RRR(Oadd, Ro3, Ro2, Ro2);
1864 	SLWI(Ro2, Ro2, 2);
1865 	RRR(Oadd, Ro2, Rlink, Rlink);
1866 	IRR(Olwz, 4,Rlink, Ro3);		// (initial t)[n*3+1]
1867 	jr(Ro3);
1868 }
1869 
1870 static	void
1871 macmcal(void)
1872 {
1873 	ulong *cp;
1874 
1875 	AIRR(Olwz, Ro2, Ri,O(Modlink,prog));
1876 	mfspr(Rlink, Rlr);
1877 	AIRR(Ostw, Rlink, Ro1,O(Frame,lr));	// f->lr = return
1878 	AIRR(Ocmpi, Rcrf0, Ro2, 0);
1879 	AIRR(Oaddi, Rfp, Ro1, 0);		// R.FP = f
1880 	cp = code;
1881 	br(Obne, 0);		// CMPL ml->m->prog != 0
1882 
1883 	AIRR(Ostw, Rlink, Rreg,O(REG,st));
1884 	AIRR(Ostw, Ro1, Rreg,O(REG,FP));
1885 	AIRR(Ostw, Rj, Rreg,O(REG,dt));
1886 	jmpl((ulong*)rmcall);			// CALL	rmcall
1887 	ldc((ulong)&R, Rreg);
1888 	SETR0();
1889 	AIRR(Olwz, Rlink, Rreg,O(REG,st));
1890 	mtspr(Rlr, Rlink);
1891 	AIRR(Olwz, Rfp, Rreg,O(REG,FP));
1892 	AIRR(Olwz, Rmp, Rreg,O(REG,MP));
1893 	gen(Oblr);	// RET
1894 
1895 	PATCH(cp);
1896 	AIRR(Olwz, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
1897 	AIRR(Ostw, Ri, Rreg,O(REG,M));
1898 	AIRR(Oaddi, Ro2, Ro2, 1);
1899 	AIRR(Olwz, Rmp, Ri,O(Modlink,MP));
1900 	AIRR(Ostw, Ro2, Ri,O(Heap,ref)-sizeof(Heap));
1901 	AIRR(Ostw, Rmp, Rreg,O(REG,MP));
1902 	AIRR(Olwz, Ro2, Ri,O(Modlink,compiled));
1903 	AIRR(Ocmpi, Rcrf0, Ro2, 0);
1904 	mtspr(Rctr, Rj);
1905 	gen(Obcctr | Cne);	// return to compiled code
1906 
1907 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));	// R.FP = Rfp
1908 	AIRR(Ostw, Rj, Rreg,O(REG,PC));	// R.PC = Rj
1909 	AIRR(Olwz, Rpic, Rreg,O(REG,xpc));
1910 	mtspr(Rlr, Rpic);
1911 	gen(Oblr);		// return to xec uncompiled code
1912 }
1913 
1914 static	void
1915 macmfra(void)
1916 {
1917 	mfspr(Rlink, Rlr);
1918 	AIRR(Ostw, Rlink, Rreg,O(REG,st));
1919 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));
1920 	AIRR(Ostw, Ri, Rreg,O(REG,s));
1921 	AIRR(Ostw, Rj, Rreg,O(REG,d));
1922 	jmpl((ulong*)rmfram);
1923 	ldc((ulong)&R, Rreg);
1924 	SETR0();
1925 	AIRR(Olwz, Rlink, Rreg,O(REG,st));
1926 	mtspr(Rlr, Rlink);
1927 	AIRR(Olwz, Rfp, Rreg,O(REG,FP));
1928 	AIRR(Olwz, Rmp, Rreg,O(REG,MP));
1929 	gen(Oblr);
1930 }
1931 
1932 static void
1933 macfram(void)
1934 {
1935 	ulong *cp;
1936 
1937 	/*
1938 	 * Ri has t
1939 	 */
1940 	AIRR(Olwz, Ro2, Ri,O(Type,size));		// MOVW t->size, Ro3
1941 	AIRR(Olwz, Ro1, Rreg,O(REG,SP));		// MOVW	R.SP, Ro1  (=(Frame*)R.SP)
1942 	AIRR(Olwz, Ro3, Rreg,O(REG,TS));		// MOVW	R.TS, tmp
1943 	ARRR(Oadd, Ro2, Ro2, Ro1);		// ADD Ro1, t->size, nsp
1944 	ARRR(Ocmpl, Rcrf0, Ro2, Ro3);		// CMPU nsp,tmp (nsp >= R.TS?)
1945 	cp = code;
1946 	br(Obge, 0);			// BGE expand
1947 
1948 	AIRR(Olwz, Rj, Ri,O(Type,initialize));
1949 	mtspr(Rctr, Rj);
1950 	AIRR(Ostw, Ro2, Rreg,O(REG,SP));		// R.SP = nsp
1951 	AIRR(Ostw, Rzero, Ro1,O(Frame,mr));	// Ro1->mr = nil
1952 	AIRR(Ostw, Ri, Ro1,O(Frame,t));		// Ro1->t = t
1953 	gen(Obctr);				// become t->init(Ro1), returning Ro1
1954 
1955 	PATCH(cp);					// expand:
1956 	AIRR(Ostw, Ri, Rreg,O(REG,s));		// MOVL	t, R.s
1957 	mfspr(Rlink, Rlr);
1958 	AIRR(Ostw, Rlink, Rreg,O(REG,st));	// MOVL	Rlink, R.st
1959 	AIRR(Ostw, Rfp, Rreg,O(REG,FP));		// MOVL	RFP, R.FP
1960 	jmpl((ulong*)extend);		// CALL	extend
1961 	ldc((ulong)&R, Rreg);
1962 	SETR0();
1963 	AIRR(Olwz, Rlink, Rreg,O(REG,st));	// reload registers
1964 	mtspr(Rlr, Rlink);
1965 	AIRR(Olwz, Rfp, Rreg,O(REG,FP));
1966 	AIRR(Olwz, Rmp, Rreg,O(REG,MP));
1967 	AIRR(Olwz, Ro1, Rreg,O(REG,s));		// return R.s set by extend
1968 	LRET();	// RET
1969 }
1970 
1971 static void
1972 movloop(int ldu, int stu, int adj)
1973 {
1974 	ulong *cp;
1975 
1976 	AIRR(Oaddi, Ro1, Ro1, -adj);	// adjust for update ld/st
1977 	AIRR(Oaddi, Ro3, Ro3, -adj);
1978 	mtspr(Rctr, Ro2);
1979 
1980 	cp = code;			// l0:
1981 	AIRR(ldu, Ri, Ro1,adj);
1982 	AIRR(stu, Ri, Ro3,adj);
1983 	br(Obc | Cdnz, ((ulong)cp-(ulong)code));	// DBNZ l0
1984 }
1985 
1986 static void
1987 movmem(Inst *i)
1988 {
1989 	ulong *cp;
1990 
1991 	// source address already in Ro1
1992 	if((i->add&ARM) != AXIMM){
1993 		op2(i, Olwz, Ro2);
1994 		AIRR(Ocmpi, Rcrf0, Ro2, 0);
1995 		cp = code;
1996 		br(Oble, 0);
1997 		opwst(i, Olea, Ro3);
1998 		movloop(Olbzu, Ostbu, 1);
1999 		PATCH(cp);
2000 		return;
2001 	}
2002 	switch(i->reg){
2003 	case 4:
2004 		AIRR(Olwz, Ro2, Ro1,0);
2005 		opwst(i, Ostw, Ro2);
2006 		break;
2007 	case 8:
2008 		AIRR(Olwz, Ro2, Ro1,0);
2009 		opwst(i, Olea, Ro3);
2010 		AIRR(Olwz, Ro1, Ro1,4);
2011 		AIRR(Ostw, Ro2, Ro3,0);
2012 		AIRR(Ostw, Ro1, Ro3,4);
2013 		break;
2014 	default:
2015 		// could use lwsi/stwsi loop...
2016 		opwst(i, Olea, Ro3);
2017 		if((i->reg&3) == 0) {
2018 			ldc(i->reg>>2, Ro2);
2019 			movloop(Olwzu, Ostwu, 4);
2020 		} else {
2021 			ldc(i->reg, Ro2);
2022 			movloop(Olbzu, Ostbu, 1);
2023 		}
2024 		break;
2025 	}
2026 }
2027 
2028 static void
2029 maccolr(void)
2030 {
2031 	ldbigc((ulong)&mutator, Ri);
2032 	AIRR(Olwz, Ri, Ri,0);
2033 	AIRR(Olwz, Ro3, Ro1,O(Heap,color)-sizeof(Heap));	// h->color
2034 
2035 	AIRR(Olwz, Ro2, Ro1,O(Heap,ref)-sizeof(Heap));	// h->ref
2036 
2037 	ARRR(Ocmp, Rcrf0, Ri, Ro3);
2038 	AIRR(Oaddi, Ro2, Ro2, 1);	// h->ref++
2039 	AIRR(Ostw, Ro2, Ro1,O(Heap,ref)-sizeof(Heap));
2040 	gen(Obclr | Ceq);	// return if h->color == mutator
2041 
2042 	ldc(propagator, Ro3);
2043 	AIRR(Ostw, Ro3, Ro1,O(Heap,color)-sizeof(Heap));	// h->color = propagator
2044 	ldc((ulong)&nprop, Ro3);
2045 	AIRR(Ostw, Ro1, Ro3,0);	// nprop = !0
2046 	LRET();
2047 }
2048 
2049 static void
2050 maccvtfw(void)
2051 {
2052 	ulong *cp;
2053 
2054 	ARRR(Ofcmpo, Rcrf0, Rf1, Rfzero);
2055 	ARRR(Ofneg, Rf2, 0, Rfhalf);
2056 	cp = code;
2057 	br(Oblt, 0);
2058 	ARRR(Ofmr, Rf2, 0, Rfhalf);
2059 	PATCH(cp);
2060 	ARRR(Ofadd, Rf1, Rf1, Rf2);	//x<0? x-.5: x+.5
2061 	ARRR(Ofctiwz, Rf2, 0, Rf1);
2062 	/* avoid using Ostfdu for now, since software emulation will run on same stack */
2063 	if(0){
2064 		AIRR(Ostfdu, Rf2, Rsp,-8);		// MOVDU Rf2, -8(R1)    (store in temp)
2065 	}else{
2066 		AIRR(Oaddi, Rsp, Rsp, -8);		// SUB $8, R1
2067 		AIRR(Ostfd, Rf2, Rsp,0);		// MOVD Rf2, 0(R1)    (store in temp)
2068 	}
2069 	AIRR(Olwz, Ro1, Rsp,4);		// MOVW 4(R1), Ro1
2070 	AIRR(Oaddi, Rsp, Rsp, 8);		// ADD $8, R1
2071 	LRET();
2072 }
2073 
2074 static void
2075 macrelq(void)
2076 {
2077 	ARRR(Ocrxor, Rcrbrel, Rcrbrel, Rcrbrel);	/* clear the relinquish condition */
2078 	mfspr(Rlink, Rlr);
2079 	IRR(Ostw, O(REG,FP),Rreg, Rfp);
2080 	IRR(Ostw, O(REG,PC),Rreg, Rlink);
2081 	IRR(Olwz, O(REG,xpc),Rreg, Ro2);
2082 	jr(Ro2);
2083 }
2084 
2085 static void
2086 macend(void)
2087 {
2088 }
2089 
2090 void
2091 comd(Type *t)
2092 {
2093 	int i, j, m, c;
2094 
2095 	mfspr(Rlink, Rlr);
2096 	AIRR(Ostw, Rlink, Rreg,O(REG,dt));
2097 	for(i = 0; i < t->np; i++) {
2098 		c = t->map[i];
2099 		j = i<<5;
2100 		for(m = 0x80; m != 0; m >>= 1) {
2101 			if(c & m) {
2102 				mem(Olwz, j, Rfp, Ri);
2103 				jmpl(base+macro[MacFRP]);
2104 			}
2105 			j += sizeof(WORD*);
2106 		}
2107 	}
2108 	AIRR(Olwz, Rlink, Rreg,O(REG,dt));
2109 	mtspr(Rlr, Rlink);
2110 	gen(Oblr);
2111 }
2112 
2113 void
2114 comi(Type *t)
2115 {
2116 	int i, j, m, c;
2117 
2118 	ldc((ulong)H, Ri);
2119 	for(i = 0; i < t->np; i++) {
2120 		c = t->map[i];
2121 		j = i<<5;
2122 		for(m = 0x80; m != 0; m >>= 1) {
2123 			if(c & m)
2124 				mem(Ostw, j, Ro1, Ri);
2125 			j += sizeof(WORD*);
2126 		}
2127 	}
2128 	LRET();
2129 }
2130 
2131 void
2132 typecom(Type *t)
2133 {
2134 	int n;
2135 	ulong *tmp, *start;
2136 
2137 	if(t == nil || t->initialize != 0)
2138 		return;
2139 
2140 	tmp = mallocz(4096*sizeof(ulong), 0);
2141 	if(tmp == nil)
2142 		error(exNomem);
2143 
2144 	code = tmp;
2145 	comi(t);
2146 	n = code - tmp;
2147 	code = tmp;
2148 	comd(t);
2149 	n += code - tmp;
2150 	free(tmp);
2151 
2152 	n *= sizeof(*code);
2153 	code = mallocz(n, 0);
2154 	if(code == nil)
2155 		return;
2156 
2157 	start = code;
2158 	t->initialize = code;
2159 	comi(t);
2160 	t->destroy = code;
2161 	comd(t);
2162 
2163 	segflush(start, n);
2164 
2165 	if(cflag > 3)
2166 		print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n",
2167 			(ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n);
2168 }
2169 
2170 static void
2171 patchex(Module *m, ulong *p)
2172 {
2173 	Handler *h;
2174 	Except *e;
2175 
2176 	if((h = m->htab) == nil)
2177 		return;
2178 	for( ; h->etab != nil; h++){
2179 		h->pc1 = p[h->pc1];
2180 		h->pc2 = p[h->pc2];
2181 		for(e = h->etab; e->s != nil; e++)
2182 			e->pc = p[e->pc];
2183 		if(e->pc != -1)
2184 			e->pc = p[e->pc];
2185 	}
2186 }
2187 
2188 int
2189 compile(Module *m, int size, Modlink *ml)
2190 {
2191 	Link *l;
2192 	Modl *e;
2193 	int i, n;
2194 	ulong *s, *tmp;
2195 
2196 	base = nil;
2197 	patch = mallocz(size*sizeof(*patch), ROMABLE);
2198 	tinit = malloc(m->ntype*sizeof(*tinit));
2199 	tmp = malloc(4096*sizeof(ulong));
2200 	if(tinit == nil || patch == nil || tmp == nil)
2201 		goto bad;
2202 
2203 	preamble();
2204 
2205 	mod = m;
2206 	n = 0;
2207 	pass = 0;
2208 	nlit = 0;
2209 
2210 	for(i = 0; i < size; i++) {
2211 		code = tmp;
2212 		comp(&m->prog[i]);
2213 		if(code >= &tmp[4096]) {
2214 			print("%3d %D\n", i, &m->prog[i]);
2215 			urk("tmp ovflo");
2216 		}
2217 		patch[i] = n;
2218 		n += code - tmp;
2219 	}
2220 
2221 	for(i=0; macinit[i].f; i++) {
2222 		code = tmp;
2223 		(*macinit[i].f)();
2224 		macro[macinit[i].o] = n;
2225 		n += code - tmp;
2226 	}
2227 
2228 	base = mallocz((n+nlit)*sizeof(*base), 0);
2229 	if(base == nil)
2230 		goto bad;
2231 
2232 	if(cflag > 3)
2233 		print("dis=%5d %5d ppc=%5d asm=%.8lux lit=%d: %s\n",
2234 			size, size*sizeof(Inst), n, (ulong)base, nlit, m->name);
2235 
2236 	pass++;
2237 	nlit = 0;
2238 	litpool = base+n;
2239 	code = base;
2240 	n = 0;
2241 
2242 	for(i = 0; i < size; i++) {
2243 		s = code;
2244 		comp(&m->prog[i]);
2245 		if(patch[i] != n) {
2246 			print("%3d %D\n", i, &m->prog[i]);
2247 			urk("phase error");
2248 		}
2249 		n += code - s;
2250 		if(cflag > 3) {
2251 			print("%3d %D\n", i, &m->prog[i]);
2252 			while(s < code)
2253 				s += das(s);
2254 		}/**/
2255 	}
2256 
2257 	for(i=0; macinit[i].f; i++) {
2258 		if(macro[macinit[i].o] != n) {
2259 			print("macinit %d\n", macinit[i].o);
2260 			urk("phase error");
2261 		}
2262 		s = code;
2263 		(*macinit[i].f)();
2264 		n += code - s;
2265 		if(cflag > 3) {
2266 			print("macinit %d\n", macinit[i].o);
2267 			while(s < code)
2268 				s += das(s);
2269 		}/**/
2270 	}
2271 
2272 	for(l = m->ext; l->name; l++) {
2273 		l->u.pc = (Inst*)(base+patch[l->u.pc-m->prog]);
2274 		typecom(l->frame);
2275 	}
2276 	if(ml != nil) {
2277 		e = &ml->links[0];
2278 		for(i = 0; i < ml->nlinks; i++) {
2279 			e->u.pc = (Inst*)(base+patch[e->u.pc-m->prog]);
2280 			typecom(e->frame);
2281 			e++;
2282 		}
2283 	}
2284 	for(i = 0; i < m->ntype; i++) {
2285 		if(tinit[i] != 0)
2286 			typecom(m->type[i]);
2287 	}
2288 	patchex(m, patch);
2289 	m->entry = (Inst*)(base+patch[mod->entry-mod->prog]);
2290 	free(patch);
2291 	free(tinit);
2292 	free(tmp);
2293 	free(m->prog);
2294 	m->prog = (Inst*)base;
2295 	m->compiled = 1;
2296 	segflush(base, n*sizeof(*base));
2297 	return 1;
2298 bad:
2299 	free(patch);
2300 	free(tinit);
2301 	free(base);
2302 	free(tmp);
2303 	return 0;
2304 }
2305