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