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