xref: /inferno-os/libinterp/comp-386.c (revision 4a4256626644b5e413cfb1c228d396d27364030b)
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
bounds(void)156 bounds(void)
157 {
158 	error(exBounds);
159 }
160 
161 static void
rdestroy(void)162 rdestroy(void)
163 {
164 	destroy(R.s);
165 }
166 
167 static void
rmcall(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
rmfram(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
bc(int o)220 bc(int o)
221 {
222 	if(o < 127 && o > -128)
223 		return 1;
224 	return 0;
225 }
226 
227 static void
urk(void)228 urk(void)
229 {
230 	error(exCompile);
231 }
232 
233 static void
genb(uchar o)234 genb(uchar o)
235 {
236 	*code++ = o;
237 }
238 
239 static void
gen2(uchar o1,uchar o2)240 gen2(uchar o1, uchar o2)
241 {
242 	code[0] = o1;
243 	code[1] = o2;
244 	code += 2;
245 }
246 
247 static void
genw(ulong o)248 genw(ulong o)
249 {
250 	*(ulong*)code = o;
251 	code += 4;
252 }
253 
254 static void
modrm(int inst,ulong disp,int rm,int r)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
con(ulong o,int r)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
opwld(Inst * i,int mi,int r)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
opwst(Inst * i,int mi,int r)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
bra(ulong dst,int op)349 bra(ulong dst, int op)
350 {
351 	dst -= (DOT+5);
352 	genb(op);
353 	genw(dst);
354 }
355 
356 static void
rbra(ulong dst,int op)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
literal(ulong imm,int roff)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
punt(Inst * i,int m,void (* fn)(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
mid(Inst * i,uchar mi,int r)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
arith(Inst * i,int op2,int rm)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
arithb(Inst * i,int op2)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
shift(Inst * i,int ld,int st,int op,int r)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
arithf(Inst * i,int op)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
cmpl(int r,ulong v)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
swapbraop(int b)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
schedcheck(Inst * i)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
cbra(Inst * i,int jmp)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
cbral(Inst * i,int jmsw,int jlsw,int mode)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
cbrab(Inst * i,int jmp)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
cbraf(Inst * i,int jmp)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
comcase(Inst * i,int w)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
comcasel(Inst * i)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
commframe(Inst * i)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
commcall(Inst * i)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
larith(Inst * i,int op,int opc)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
shll(Inst * i)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
shrl(Inst * i)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
compdbg(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
comp(Inst * i)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, sizeof(Rune)==4? 10: 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 			if(sizeof(Rune) == 4){
1414 				gen2(Oldw, (1<<6)|(0<<3)|4);
1415 				gen2((2<<6)|(RBX<<3)|RAX, O(String, data));
1416 			}else{
1417 				genb(0x0f);
1418 				gen2(Omovzxw, (1<<6)|(0<<3)|4);
1419 				gen2((1<<6)|(RBX<<3)|RAX, O(String, data));
1420 			}
1421 			opwst(i, Ostw, RAX);
1422 			break;
1423 		}
1424 		modrm(Ocmpi, O(String, len), RAX, 7);
1425 		genb(0);
1426 		gen2(Ojltb, 7);
1427 		genb(0x0f);
1428 		gen2(Omovzxb, (1<<6)|(0<<3)|4);		/* movzbx 12(AX)(RBX*1), RAX */
1429 		gen2((0<<6)|(RBX<<3)|RAX, O(String, data));
1430 		if(sizeof(Rune) == 4){
1431 			gen2(Ojmpb, 4);
1432 			gen2(Oldw, (1<<6)|(0<<3)|4);		/* movl 12(AX)(RBX*4), RAX */
1433 			gen2((2<<6)|(RBX<<3)|RAX, O(String, data));
1434 		}else{
1435 			gen2(Ojmpb, 5);
1436 			genb(0x0f);
1437 			gen2(Omovzxw, (1<<6)|(0<<3)|4);		/* movzwx 12(AX)(RBX*2), RAX */
1438 			gen2((1<<6)|(RBX<<3)|RAX, O(String, data));
1439 		}
1440 		opwst(i, Ostw, RAX);
1441 		break;
1442 	case ICASE:
1443 		comcase(i, 1);
1444 		break;
1445 	case IMOVL:
1446 		opwld(i, Olea, RTA);
1447 		opwst(i, Olea, RTMP);
1448 		modrm(Oldw, 0, RTA, RAX);
1449 		modrm(Ostw, 0, RTMP, RAX);
1450 		modrm(Oldw, 4, RTA, RAX);
1451 		modrm(Ostw, 4, RTMP, RAX);
1452 		break;
1453 	case IADDL:
1454 		larith(i, 0x03, 0x13);
1455 		break;
1456 	case ISUBL:
1457 		larith(i, 0x2b, 0x1b);
1458 		break;
1459 	case IORL:
1460 		larith(i, 0x0b, 0x0b);
1461 		break;
1462 	case IANDL:
1463 		larith(i, 0x23, 0x23);
1464 		break;
1465 	case IXORL:
1466 		larith(i, 0x33, 0x33);
1467 		break;
1468 	case IBEQL:
1469 		cbral(i, Ojnel, Ojeql, ANDAND);
1470 		break;
1471 	case IBNEL:
1472 		cbral(i, Ojnel, Ojnel, OROR);
1473 		break;
1474 	case IBLEL:
1475 		cbral(i, Ojltl, Ojbel, EQAND);
1476 		break;
1477 	case IBGTL:
1478 		cbral(i, Ojgtl, Ojal, EQAND);
1479 		break;
1480 	case IBLTL:
1481 		cbral(i, Ojltl, Ojbl, EQAND);
1482 		break;
1483 	case IBGEL:
1484 		cbral(i, Ojgtl, Ojael, EQAND);
1485 		break;
1486 	case ISHLL:
1487 		shll(i);
1488 		break;
1489 	case ISHRL:
1490 		shrl(i);
1491 		break;
1492 	case IRAISE:
1493 		punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]);
1494 		break;
1495 	case IMULX:
1496 	case IDIVX:
1497 	case ICVTXX:
1498 	case IMULX0:
1499 	case IDIVX0:
1500 	case ICVTXX0:
1501 	case IMULX1:
1502 	case IDIVX1:
1503 	case ICVTXX1:
1504 	case ICVTFX:
1505 	case ICVTXF:
1506 	case IEXPW:
1507 	case IEXPL:
1508 	case IEXPF:
1509 		punt(i, SRCOP|DSTOP|THREOP, optab[i->op]);
1510 		break;
1511 	case ISELF:
1512 		punt(i, DSTOP, optab[i->op]);
1513 		break;
1514 	}
1515 }
1516 
1517 static void
preamble(void)1518 preamble(void)
1519 {
1520 	if(comvec)
1521 		return;
1522 
1523 	comvec = malloc(32);
1524 	if(comvec == nil)
1525 		error(exNomem);
1526 	code = (uchar*)comvec;
1527 
1528 	genb(Opushl+RBX);
1529 	genb(Opushl+RCX);
1530 	genb(Opushl+RDX);
1531 	genb(Opushl+RSI);
1532 	genb(Opushl+RDI);
1533 	con((ulong)&R, RTMP);
1534 	modrm(Oldw, O(REG, FP), RTMP, RFP);
1535 	modrm(Oldw, O(REG, MP), RTMP, RMP);
1536 	modrm(Ojmprm, O(REG, PC), RTMP, 4);
1537 
1538 	segflush(comvec, 32);
1539 }
1540 
1541 static void
maccase(void)1542 maccase(void)
1543 {
1544 	uchar *loop, *def, *lab1;
1545 
1546 	modrm(Oldw, 0, RSI, RDX);		// n = t[0]
1547 	modrm(Olea, 4, RSI, RSI);		// t = &t[1]
1548 	gen2(Oldw, (3<<6)|(RBX<<3)|RDX);	// MOVL	DX, BX
1549 	gen2(Oshr, (3<<6)|(4<<3)|RBX);		// SHL	BX,1
1550 	gen2(0x01, (3<<6)|(RDX<<3)|RBX);	// ADDL	DX, BX	BX = n*3
1551 	gen2(Opushrm, (0<<6)|(6<<3)|4);
1552 	genb((2<<6)|(RBX<<3)|RSI);		// PUSHL 0(SI)(BX*4)
1553 	loop = code;
1554 	cmpl(RDX, 0);
1555 	gen2(Ojleb, 0);
1556 	def = code-1;
1557 	gen2(Oldw, (3<<6)|(RCX<<3)|RDX);	// MOVL	DX, CX	n2 = n
1558 	gen2(Oshr, (3<<6)|(5<<3)|RCX);		// SHR	CX,1	n2 = n2>>1
1559 	gen2(Oldw, (3<<6)|(RBX<<3)|RCX);	// MOVL	CX, BX
1560 	gen2(Oshr, (3<<6)|(4<<3)|RBX);		// SHL	BX,1
1561 	gen2(0x01, (3<<6)|(RCX<<3)|RBX);	// ADDL	CX, BX	BX = n2*3
1562 	gen2(0x3b, (0<<6)|(RAX<<3)|4);
1563 	genb((2<<6)|(RBX<<3)|RSI);		// CMPL AX, 0(SI)(BX*4)
1564 	gen2(Ojgeb, 0);				// JGE	lab1
1565 	lab1 = code-1;
1566 	gen2(Oldw, (3<<6)|(RDX<<3)|RCX);
1567 	gen2(Ojmpb, loop-code-2);
1568 	*lab1 = code-lab1-1;			// lab1:
1569 	gen2(0x3b, (1<<6)|(RAX<<3)|4);
1570 	gen2((2<<6)|(RBX<<3)|RSI, 4);		// CMPL AX, 4(SI)(BX*4)
1571 	gen2(Ojltb, 0);
1572 	lab1 = code-1;
1573 	gen2(Olea, (1<<6)|(RSI<<3)|4);
1574 	gen2((2<<6)|(RBX<<3)|RSI, 12);		// LEA	12(SI)(RBX*4), RSI
1575 	gen2(0x2b, (3<<6)|(RDX<<3)|RCX);	// SUBL	CX, DX		n -= n2
1576 	gen2(Odecrm, (3<<6)|(1<<3)|RDX);	// DECL	DX		n -= 1
1577 	gen2(Ojmpb, loop-code-2);
1578 	*lab1 = code-lab1-1;			// lab1:
1579 	gen2(Oldw, (1<<6)|(RAX<<3)|4);
1580 	gen2((2<<6)|(RBX<<3)|RSI, 8);		// MOVL 8(SI)(BX*4), AX
1581 	genb(Opopl+RSI);			// ditch default
1582 	genb(Opopl+RSI);
1583 	gen2(Ojmprm, (3<<6)|(4<<3)|RAX);	// JMP*L AX
1584 	*def = code-def-1;			// def:
1585 	genb(Opopl+RAX);			// ditch default
1586 	genb(Opopl+RSI);
1587 	gen2(Ojmprm, (3<<6)|(4<<3)|RAX);
1588 }
1589 
1590 static void
macfrp(void)1591 macfrp(void)
1592 {
1593 	cmpl(RAX, (ulong)H);			// CMPL AX, $H
1594 	gen2(Ojneb, 0x01);			// JNE	.+1
1595 	genb(Oret);				// RET
1596 	modrm(0x83, O(Heap, ref)-sizeof(Heap), RAX, 7);
1597 	genb(0x01);				// CMP	AX.ref, $1
1598 	gen2(Ojeqb, 0x04);			// JNE	.+4
1599 	modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RAX, 1);
1600 	genb(Oret);				// DEC	AX.ref
1601 						// RET
1602 	con((ulong)&R, RTMP);			// MOV  $R, RTMP
1603 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL	RFP, R.FP
1604 	modrm(Ostw, O(REG, s), RTMP, RAX);	// MOVL	RAX, R.s
1605 	bra((ulong)rdestroy, Ocall);		// CALL rdestroy
1606 	con((ulong)&R, RTMP);			// MOVL	$R, RTMP
1607 	modrm(Oldw, O(REG, FP), RTMP, RFP);	// MOVL	R.MP, RMP
1608 	modrm(Oldw, O(REG, MP), RTMP, RMP);	// MOVL R.FP, RFP
1609 	genb(Oret);
1610 }
1611 
1612 static void
macret(void)1613 macret(void)
1614 {
1615 	Inst i;
1616 	uchar *s;
1617 	static ulong lpunt, lnomr, lfrmr, linterp;
1618 
1619 	s = code;
1620 
1621 	lpunt -= 2;
1622 	lnomr -= 2;
1623 	lfrmr -= 2;
1624 	linterp -= 2;
1625 
1626 	con(0, RBX);				// MOVL  $0, RBX
1627 	modrm(Oldw, O(Frame, t), RFP, RAX);	// MOVL  t(FP), RAX
1628 	gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX);	// CMPL  RAX, RBX
1629 	gen2(Ojeqb, lpunt-(code-s));		// JEQ	 lpunt
1630 	modrm(Oldw, O(Type, destroy), RAX, RAX);// MOVL  destroy(RAX), RAX
1631 	gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX);	// CMPL	 RAX, RBX
1632 	gen2(Ojeqb, lpunt-(code-s));		// JEQ	 lpunt
1633 	modrm(Ocmpw, O(Frame, fp), RFP, RBX);	// CMPL	 fp(FP), RBX
1634 	gen2(Ojeqb, lpunt-(code-s));		// JEQ	 lpunt
1635 	modrm(Ocmpw, O(Frame, mr), RFP, RBX);	// CMPL	 mr(FP), RBX
1636 	gen2(Ojeqb, lnomr-(code-s));		// JEQ	 lnomr
1637 	con((ulong)&R, RTMP);			// MOVL	 $R, RTMP
1638 	modrm(Oldw, O(REG, M), RTMP, RTA);	// MOVL	 R.M, RTA
1639 	modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RTA, 1);
1640 	gen2(Ojneb, lfrmr-(code-s));		// JNE	 lfrmr
1641 	modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0);
1642 	gen2(Ojmpb, lpunt-(code-s));		// JMP	 lpunt
1643 	lfrmr = code - s;
1644 	modrm(Oldw, O(Frame, mr), RFP, RTA);	// MOVL	 mr(FP), RTA
1645 	modrm(Ostw, O(REG, M), RTMP, RTA);	// MOVL	 RTA, R.M
1646 	modrm(Oldw, O(Modlink, MP), RTA, RMP);	// MOVL	 MP(RTA), RMP
1647 	modrm(Ostw, O(REG, MP), RTMP, RMP);	// MOVL	 RMP, R.MP
1648 	modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled
1649 	genb(0x00);
1650 	gen2(Ojeqb, linterp-(code-s));		// JEQ	linterp
1651 	lnomr = code - s;
1652 	gen2(Ocallrm, (3<<6)|(2<<3)|RAX);	// CALL* AX
1653 	con((ulong)&R, RTMP);			// MOVL	 $R, RTMP
1654 	modrm(Ostw, O(REG, SP), RTMP, RFP);	// MOVL  RFP, R.SP
1655 	modrm(Oldw, O(Frame, lr), RFP, RAX);	// MOVL  lr(RFP), RAX
1656 	modrm(Oldw, O(Frame, fp), RFP, RFP);	// MOVL  fp(RFP), RFP
1657 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL  RFP, R.FP
1658 	gen2(Ojmprm, (3<<6)|(4<<3)|RAX);	// JMP*L AX
1659 
1660 	linterp = code - s;			// return to uncompiled code
1661 	gen2(Ocallrm, (3<<6)|(2<<3)|RAX);	// CALL* AX
1662 	con((ulong)&R, RTMP);			// MOVL	 $R, RTMP
1663 	modrm(Ostw, O(REG, SP), RTMP, RFP);	// MOVL  RFP, R.SP
1664 	modrm(Oldw, O(Frame, lr), RFP, RAX);	// MOVL  lr(RFP), RAX
1665 	modrm(Ostw, O(REG, PC), RTMP, RAX);	// MOVL  RAX, R.PC
1666 	modrm(Oldw, O(Frame, fp), RFP, RFP);	// MOVL  fp(RFP), RFP
1667 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL  RFP, R.FP
1668 	genb(Opopl+RDI);			// return to uncompiled code
1669 	genb(Opopl+RSI);
1670 	genb(Opopl+RDX);
1671 	genb(Opopl+RCX);
1672 	genb(Opopl+RBX);
1673 	genb(Oret);
1674 						// label:
1675 	lpunt = code - s;
1676 
1677 	i.add = AXNON;
1678 	punt(&i, TCHECK|NEWPC, optab[IRET]);
1679 }
1680 
1681 static void
maccolr(void)1682 maccolr(void)
1683 {
1684 	modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RBX, 0);
1685 	gen2(Oldw, (0<<6)|(RAX<<3)|5);		// INCL	ref(BX)
1686 	genw((ulong)&mutator);			// MOVL	mutator, RAX
1687 	modrm(Ocmpw, O(Heap, color)-sizeof(Heap), RBX, RAX);
1688 	gen2(Ojneb, 0x01);			// CMPL	color(BX), RAX
1689 	genb(Oret);				// MOVL $propagator,RTMP
1690 	con(propagator, RAX);			// MOVL	RTMP, color(BX)
1691 	modrm(Ostw, O(Heap, color)-sizeof(Heap), RBX, RAX);
1692 	gen2(Ostw, (0<<6)|(RAX<<3)|5);		// can be any !0 value
1693 	genw((ulong)&nprop);			// MOVL	RBX, nprop
1694 	genb(Oret);
1695 }
1696 
1697 static void
macmcal(void)1698 macmcal(void)
1699 {
1700 	uchar *label, *mlnil, *interp;
1701 
1702 	cmpl(RAX, (ulong)H);
1703 	gen2(Ojeqb, 0);
1704 	mlnil = code - 1;
1705 	modrm(0x83, O(Modlink, prog), RTA, 7);	// CMPL $0, ml->prog
1706 	genb(0x00);
1707 	gen2(Ojneb, 0);				// JNE	patch
1708 	label = code-1;
1709 	*mlnil = code-mlnil-1;
1710 	modrm(Ostw, O(REG, FP), RTMP, RCX);
1711 	modrm(Ostw, O(REG, dt), RTMP, RAX);
1712 	bra((ulong)rmcall, Ocall);		// CALL rmcall
1713 	con((ulong)&R, RTMP);			// MOVL	$R, RTMP
1714 	modrm(Oldw, O(REG, FP), RTMP, RFP);
1715 	modrm(Oldw, O(REG, MP), RTMP, RMP);
1716 	genb(Oret);				// RET
1717 	*label = code-label-1;			// patch:
1718 	gen2(Oldw, (3<<6)|(RFP<<3)|RCX);	// MOVL CX, RFP		R.FP = f
1719 	modrm(Ostw, O(REG, M), RTMP, RTA);	// MOVL RTA, R.M
1720 	modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0);
1721 	modrm(Oldw, O(Modlink, MP), RTA, RMP);	// MOVL R.M->mp, RMP
1722 	modrm(Ostw, O(REG, MP), RTMP, RMP);	// MOVL RMP, R.MP	R.MP = ml->MP
1723 	modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled
1724 	genb(0x00);
1725 	genb(Opopl+RTA);			// balance call
1726 	gen2(Ojeqb, 0);				// JEQ	interp
1727 	interp = code-1;
1728 	gen2(Ojmprm, (3<<6)|(4<<3)|RAX);	// JMP*L AX
1729 	*interp = code-interp-1;		// interp:
1730 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL FP, R.FP
1731 	modrm(Ostw, O(REG, PC), RTMP, RAX);	// MOVL PC, R.PC
1732 	genb(Opopl+RDI);			// call to uncompiled code
1733 	genb(Opopl+RSI);
1734 	genb(Opopl+RDX);
1735 	genb(Opopl+RCX);
1736 	genb(Opopl+RBX);
1737 	genb(Oret);
1738 }
1739 
1740 static void
macfram(void)1741 macfram(void)
1742 {
1743 	uchar *label;
1744 
1745 	con((ulong)&R, RTMP);			// MOVL	$R, RTMP
1746 	modrm(Oldw, O(REG, SP), RTMP, RAX);	// MOVL	R.SP, AX
1747 	modrm(0x03, O(Type, size), RTA, RAX);	// ADDL size(RCX), RAX
1748 	modrm(0x3b, O(REG, TS), RTMP, RAX);	// CMPL	AX, R.TS
1749 	gen2(0x7c, 0x00);			// JL	.+(patch)
1750 	label = code-1;
1751 
1752 	modrm(Ostw, O(REG, s), RTMP, RTA);
1753 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL	RFP, R.FP
1754 	bra((ulong)extend, Ocall);		// CALL	extend
1755 	con((ulong)&R, RTMP);
1756 	modrm(Oldw, O(REG, FP), RTMP, RFP);	// MOVL	R.MP, RMP
1757 	modrm(Oldw, O(REG, MP), RTMP, RMP);	// MOVL R.FP, RFP
1758 	modrm(Oldw, O(REG, s), RTMP, RCX);	// MOVL	R.s, *R.d
1759 	genb(Oret);				// RET
1760 	*label = code-label-1;
1761 	modrm(Oldw, O(REG, SP), RTMP, RCX);	// MOVL	R.SP, CX
1762 	modrm(Ostw, O(REG, SP), RTMP, RAX);	// MOVL	AX, R.SP
1763 
1764 	modrm(Ostw, O(Frame, t), RCX, RTA);	// MOVL	RTA, t(CX) f->t = t
1765 	modrm(Omov, REGMOD*4, RCX, 0);     	// MOVL $0, mr(CX) f->mr
1766 	genw(0);
1767 	modrm(Oldw, O(Type, initialize), RTA, RTA);
1768 	gen2(Ojmprm, (3<<6)|(4<<3)|RTA);	// JMP*L RTA
1769 	genb(Oret);				// RET
1770 }
1771 
1772 static void
macmfra(void)1773 macmfra(void)
1774 {
1775 	con((ulong)&R, RTMP);			// MOVL	$R, RTMP
1776 	modrm(Ostw, O(REG, FP), RTMP, RFP);
1777 	modrm(Ostw, O(REG, s), RTMP, RAX);	// Save type
1778 	modrm(Ostw, O(REG, d), RTMP, RTA);	// Save destination
1779 	bra((ulong)rmfram, Ocall);		// CALL rmfram
1780 	con((ulong)&R, RTMP);			// MOVL	$R, RTMP
1781 	modrm(Oldw, O(REG, FP), RTMP, RFP);
1782 	modrm(Oldw, O(REG, MP), RTMP, RMP);
1783 	genb(Oret);				// RET
1784 }
1785 
1786 static void
macrelq(void)1787 macrelq(void)
1788 {
1789 	modrm(Ostw, O(REG, FP), RTMP, RFP);	// MOVL FP, R.FP
1790 	genb(Opopl+RAX);
1791 	modrm(Ostw, O(REG, PC), RTMP, RAX);	// MOVL PC, R.PC
1792 	genb(Opopl+RDI);
1793 	genb(Opopl+RSI);
1794 	genb(Opopl+RDX);
1795 	genb(Opopl+RCX);
1796 	genb(Opopl+RBX);
1797 	genb(Oret);
1798 }
1799 
1800 void
comd(Type * t)1801 comd(Type *t)
1802 {
1803 	int i, j, m, c;
1804 
1805 	for(i = 0; i < t->np; i++) {
1806 		c = t->map[i];
1807 		j = i<<5;
1808 		for(m = 0x80; m != 0; m >>= 1) {
1809 			if(c & m) {
1810 				modrm(Oldw, j, RFP, RAX);
1811 				rbra(macro[MacFRP], Ocall);
1812 			}
1813 			j += sizeof(WORD*);
1814 		}
1815 	}
1816 	genb(Oret);
1817 }
1818 
1819 void
comi(Type * t)1820 comi(Type *t)
1821 {
1822 	int i, j, m, c;
1823 
1824 	con((ulong)H, RAX);
1825 	for(i = 0; i < t->np; i++) {
1826 		c = t->map[i];
1827 		j = i<<5;
1828 		for(m = 0x80; m != 0; m >>= 1) {
1829 			if(c & m)
1830 				modrm(Ostw, j, RCX, RAX);
1831 			j += sizeof(WORD*);
1832 		}
1833 	}
1834 	genb(Oret);
1835 }
1836 
1837 void
typecom(Type * t)1838 typecom(Type *t)
1839 {
1840 	int n;
1841 	uchar *tmp;
1842 
1843 	if(t == nil || t->initialize != 0)
1844 		return;
1845 
1846 	tmp = mallocz(4096*sizeof(uchar), 0);
1847 	if(tmp == nil)
1848 		error(exNomem);
1849 
1850 	code = tmp;
1851 	comi(t);
1852 	n = code - tmp;
1853 	code = tmp;
1854 	comd(t);
1855 	n += code - tmp;
1856 	free(tmp);
1857 
1858 	code = mallocz(n, 0);
1859 	if(code == nil)
1860 		return;
1861 
1862 	t->initialize = code;
1863 	comi(t);
1864 	t->destroy = code;
1865 	comd(t);
1866 
1867 	if(cflag > 3)
1868 		print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n",
1869 			(ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n);
1870 
1871 	segflush(t->initialize, n);
1872 }
1873 
1874 static void
patchex(Module * m,ulong * p)1875 patchex(Module *m, ulong *p)
1876 {
1877 	Handler *h;
1878 	Except *e;
1879 
1880 	if((h = m->htab) == nil)
1881 		return;
1882 	for( ; h->etab != nil; h++){
1883 		h->pc1 = p[h->pc1];
1884 		h->pc2 = p[h->pc2];
1885 		for(e = h->etab; e->s != nil; e++)
1886 			e->pc = p[e->pc];
1887 		if(e->pc != -1)
1888 			e->pc = p[e->pc];
1889 	}
1890 }
1891 
1892 int
compile(Module * m,int size,Modlink * ml)1893 compile(Module *m, int size, Modlink *ml)
1894 {
1895 	ulong v;
1896 	Modl *e;
1897 	Link *l;
1898 	int i, n;
1899 	uchar *s, *tmp;
1900 
1901 	base = nil;
1902 	patch = mallocz(size*sizeof(*patch), 0);
1903 	tinit = malloc(m->ntype*sizeof(*tinit));
1904 	tmp = mallocz(4096*sizeof(uchar),0);
1905 	if(tinit == nil || patch == nil || tmp == nil)
1906 		goto bad;
1907 
1908 	preamble();
1909 
1910 	mod = m;
1911 	n = 0;
1912 	pass = 0;
1913 	nlit = 0;
1914 
1915 	for(i = 0; i < size; i++) {
1916 		code = tmp;
1917 		comp(&m->prog[i]);
1918 		patch[i] = n;
1919 		n += code - tmp;
1920 	}
1921 
1922 	for(i = 0; i < nelem(mactab); i++) {
1923 		code = tmp;
1924 		mactab[i].gen();
1925 		macro[mactab[i].idx] = n;
1926 		n += code - tmp;
1927 	}
1928 
1929 	n = (n+3)&~3;
1930 
1931 	nlit *= sizeof(ulong);
1932 	base = mallocz(n + nlit, 0);
1933 	if(base == nil)
1934 		goto bad;
1935 
1936 	if(cflag > 3)
1937 		print("dis=%5d %5d 386=%5d asm=%.8lux lit=%d: %s\n",
1938 			size, size*sizeof(Inst), n, (ulong)base, nlit, m->name);
1939 
1940 	pass++;
1941 	nlit = 0;
1942 	litpool = (ulong*)(base+n);
1943 	code = base;
1944 
1945 	for(i = 0; i < size; i++) {
1946 		s = code;
1947 		comp(&m->prog[i]);
1948 		if(cflag > 4) {
1949 			print("%D\n", &m->prog[i]);
1950 			das(s, code-s);
1951 		}
1952 	}
1953 
1954 	for(i = 0; i < nelem(mactab); i++)
1955 		mactab[i].gen();
1956 
1957 	v = (ulong)base;
1958 	for(l = m->ext; l->name; l++) {
1959 		l->u.pc = (Inst*)(v+patch[l->u.pc-m->prog]);
1960 		typecom(l->frame);
1961 	}
1962 	if(ml != nil) {
1963 		e = &ml->links[0];
1964 		for(i = 0; i < ml->nlinks; i++) {
1965 			e->u.pc = (Inst*)(v+patch[e->u.pc-m->prog]);
1966 			typecom(e->frame);
1967 			e++;
1968 		}
1969 	}
1970 	for(i = 0; i < m->ntype; i++) {
1971 		if(tinit[i] != 0)
1972 			typecom(m->type[i]);
1973 	}
1974 	patchex(m, patch);
1975 	m->entry = (Inst*)(v+patch[mod->entry-mod->prog]);
1976 	free(patch);
1977 	free(tinit);
1978 	free(tmp);
1979 	free(m->prog);
1980 	m->prog = (Inst*)base;
1981 	m->compiled = 1;
1982 	segflush(base, n*sizeof(base));
1983 	return 1;
1984 bad:
1985 	free(patch);
1986 	free(tinit);
1987 	free(tmp);
1988 	free(base);
1989 	return 0;
1990 }
1991 
1992