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