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