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