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