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