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