3 static char resvreg[nelem(reg)];
13 exfregoffset = FREGEXT;
24 tfield = types[TLONG];
29 zprog.from.type = D_NONE;
30 zprog.from.name = D_NONE;
31 zprog.from.reg = NREG;
32 zprog.to = zprog.from;
35 regnode.op = OREGISTER;
36 regnode.class = CEXREG;
40 regnode.type = types[TLONG];
42 constnode.op = OCONST;
43 constnode.class = CXXX;
44 constnode.complex = 0;
45 constnode.addable = 20;
46 constnode.type = types[TLONG];
48 fconstnode.op = OCONST;
49 fconstnode.class = CXXX;
50 fconstnode.complex = 0;
51 fconstnode.addable = 20;
52 fconstnode.type = types[TDOUBLE];
54 nodsafe = new(ONAME, Z, Z);
55 nodsafe->sym = slookup(".safe");
56 nodsafe->type = types[TINT];
57 nodsafe->etype = types[TINT]->etype;
58 nodsafe->class = CAUTO;
61 t = typ(TARRAY, types[TCHAR]);
62 symrathole = slookup(".rathole");
63 symrathole->class = CGLOBL;
66 nodrat = new(ONAME, Z, Z);
67 nodrat->sym = symrathole;
68 nodrat->type = types[TIND];
69 nodrat->etype = TVOID;
70 nodrat->class = CGLOBL;
74 nodret = new(ONAME, Z, Z);
75 nodret->sym = slookup(".ret");
76 nodret->type = types[TIND];
78 nodret->class = CPARAM;
79 nodret = new(OIND, nodret, Z);
84 memset(reg, 0, sizeof(reg));
91 /* keep two external registers */
94 memmove(resvreg, reg, sizeof(reg));
103 for(i=0; i<NREG; i++)
104 if(reg[i] && !resvreg[i])
105 diag(Z, "reg %d left allocated", i);
106 for(i=NREG; i<NREG+NFREG; i++)
107 if(reg[i] && !resvreg[i])
108 diag(Z, "freg %d left allocated", i-NREG);
111 symstring->type->width = nstring;
112 symrathole->type->width = nrathole;
113 for(i=0; i<NHASH; i++)
114 for(s = hash[i]; s != S; s = s->link) {
117 if(s->type->width == 0)
119 if(s->class != CGLOBL && s->class != CSTATIC)
121 if(s->type == types[TENUM])
123 gpseudo(AGLOBL, s, nodconst(s->type->width));
134 p = alloc(sizeof(*p));
148 gargs(Node *n, Node *tn1, Node *tn2)
151 Node fnxargs[20], *fnxp;
156 garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
160 garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
166 garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
173 garg1(n->left, tn1, tn2, f, fnxp);
174 garg1(n->right, tn1, tn2, f, fnxp);
178 if(n->complex >= FNX) {
190 if(typesuv[n->type->etype]) {
192 if(n->complex >= FNX) {
193 sugen(*fnxp, tn2, n->type->width);
196 sugen(n, tn2, n->type->width);
199 if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) {
201 if(n->complex >= FNX) {
209 if(n->complex >= FNX) {
215 gopcode(OAS, tn1, Z, tn2);
222 constnode.vconst = v;
229 constnode.vconst = v & MASK(32);
236 fconstnode.fconst = d;
241 nodreg(Node *n, Node *nn, int reg)
246 n->lineno = nn->lineno;
250 regret(Node *n, Node *nn)
255 if(typefd[nn->type->etype])
266 for(i=REGRET+1; i<NREG; i++)
269 diag(Z, "out of fixed registers");
274 regalloc(Node *n, Node *tn, Node *o)
279 switch(tn->type->etype) {
289 if(o != Z && o->op == OREGISTER) {
291 if(i >= 0 && i < NREG)
294 j = lasti + REGRET+1;
295 for(i=REGRET+1; i<NREG; i++) {
298 if(reg[j] == 0 && resvreg[j] == 0) {
300 lasti = (i - REGRET) % 3;
305 diag(tn, "out of fixed registers");
310 if(o != Z && o->op == OREGISTER) {
312 if(i >= NREG && i < NREG+NFREG)
316 for(i=NREG; i<NREG+NFREG; i++) {
325 diag(tn, "out of float registers");
331 n->complex = 0; /* already in registers */
335 n->left = alloc(sizeof(Node));
336 n->right = alloc(sizeof(Node));
337 if(o != Z && o->op == OREGPAIR) {
338 regalloc(n->left, ®node, o->left);
339 regalloc(n->right, ®node, o->right);
341 regalloc(n->left, ®node, Z);
342 regalloc(n->right, ®node, Z);
344 if(n->left->reg > n->right->reg){
346 n->left->reg = n->right->reg;
349 n->right->type = types[TULONG];
350 if(tn->type->etype == TUVLONG)
351 n->left->type = types[TULONG];
354 diag(tn, "unknown type in regalloc: %T", tn->type);
364 regialloc(Node *n, Node *tn, Node *o)
369 nod.type = types[TIND];
370 regalloc(n, &nod, o);
378 if(n->op == OREGPAIR) {
384 if(n->op != OREGISTER && n->op != OINDREG)
387 if(i < 0 || i >= sizeof(reg))
394 diag(n, "error in regfree: %d", i);
398 regsalloc(Node *n, Node *nn)
400 cursafe = align(cursafe, nn->type, Aaut3);
401 maxargsafe = maxround(maxargsafe, cursafe+curarg);
403 n->xoffset = -(stkoff + cursafe);
405 n->etype = nn->type->etype;
406 n->lineno = nn->lineno;
410 regaalloc1(Node *n, Node *nn)
412 nodreg(n, nn, REGARG);
414 curarg = align(curarg, nn->type, Aarg1);
415 curarg = align(curarg, nn->type, Aarg2);
416 maxargsafe = maxround(maxargsafe, cursafe+curarg);
420 regaalloc(Node *n, Node *nn)
422 curarg = align(curarg, nn->type, Aarg1);
426 n->xoffset = curarg + SZ_LONG;
429 curarg = align(curarg, nn->type, Aarg2);
430 maxargsafe = maxround(maxargsafe, cursafe+curarg);
434 regind(Node *n, Node *nn)
437 if(n->op != OREGISTER) {
438 diag(n, "regind not OREGISTER");
446 raddr(Node *n, Prog *p)
451 if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
455 if(a.type != D_REG && a.type != D_FREG) {
457 diag(n, "bad in raddr: %O", n->op);
459 diag(n, "bad in raddr: <null>");
466 naddr(Node *n, Adr *a)
476 diag(n, "bad in naddr: %O", n->op);
491 if(a->type == D_REG) {
495 if(a->type == D_CONST) {
504 a->offset = n->xoffset;
513 a->offset = n->xoffset;
514 if(n->class == CSTATIC)
516 if(n->class == CEXTERN || n->class == CGLOBL) {
520 if(n->class == CAUTO) {
524 if(n->class == CPARAM) {
533 if(typefd[n->type->etype]) {
538 a->offset = n->vconst;
544 if(a->type == D_OREG) {
551 if(n->left->op == OCONST) {
567 fop(int as, int f1, int f2, Node *t)
569 Node nod1, nod2, nod3;
571 nodreg(&nod1, t, NREG+f1);
572 nodreg(&nod2, t, NREG+f2);
573 regalloc(&nod3, t, t);
574 gopcode(as, &nod1, &nod2, &nod3);
580 gmovm(Node *f, Node *t, int w)
589 gmove(Node *f, Node *t)
598 print("gop: %O %O[%s],%O[%s]\n", OAS,
599 f->op, tnames[ft], t->op, tnames[tt]);
601 if(ft == TDOUBLE && f->op == OCONST) {
603 if(ft == TFLOAT && f->op == OCONST) {
608 * put it into a register then
609 * worry what to do with it.
611 if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
638 regalloc(&nod, f, t);
639 if(f->op == OINDREG && f->xoffset == 0 && nod.left->reg < nod.right->reg) {
640 gmovm(&nod1, nodconst((1<<nod.left->reg)|(1<<nod.right->reg)), 0);
642 /* low order first, because its value will be used first */
643 gins(AMOVW, &nod1, nod.left);
644 nod1.xoffset += SZ_LONG;
645 gins(AMOVW, &nod1, nod.right);
648 /* assumed not float or double */
649 regalloc(&nod, ®node, t);
650 gins(AMOVW, f, &nod);
653 if(typechlp[ft] && typeilp[tt])
654 regalloc(&nod, t, t);
656 regalloc(&nod, f, t);
666 * put it into a register then
669 if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
694 regalloc(&nod, t, f);
696 regalloc(&nod, t, Z);
700 if(t->op == OINDREG && t->xoffset == 0 && nod.left->reg < nod.right->reg){
701 gmovm(nodconst((1<<nod.left->reg)|(1<<nod.right->reg)), &nod1, 0);
703 gins(a, nod.left, &nod1);
704 nod1.xoffset += SZ_LONG;
705 gins(a, nod.right, &nod1);
714 * type x type cross table
753 if(tt == TFLOAT || tt == TDOUBLE) {
754 // ugly and probably longer than necessary,
755 // but vfp has a single instruction for this,
756 // so hopefully it won't last long.
759 // tmp1 = tmp & 0x80000000
761 // t = float(int32(tmp))
765 regalloc(&nod, f, Z);
766 regalloc(&nod1, f, Z);
767 gins(AMOVW, f, &nod);
768 gins(AMOVW, &nod, &nod1);
769 gins(AAND, nodconst(0x80000000), &nod1);
770 gins(AEOR, &nod1, &nod);
772 gins(AMOVWF, &nod, t);
774 gins(AMOVWD, &nod, t);
775 gins(ACMP, nodconst(0), Z);
781 regalloc(&nod, t, Z);
783 gins(AMOVF, nodfconst(2147483648.), &nod);
784 gins(AADDF, &nod, t);
786 gins(AMOVD, nodfconst(2147483648.), &nod);
787 gins(AADDD, &nod, t);
821 regalloc(&nod, f, Z);
822 gins(AMOVH, f, &nod);
823 gins(AMOVWD, &nod, t);
827 regalloc(&nod, f, Z);
828 gins(AMOVH, f, &nod);
829 gins(AMOVWF, &nod, t);
850 regalloc(&nod, f, Z);
851 gins(AMOVHU, f, &nod);
852 gins(AMOVWD, &nod, t);
856 regalloc(&nod, f, Z);
857 gins(AMOVHU, f, &nod);
858 gins(AMOVWF, &nod, t);
879 regalloc(&nod, f, Z);
880 gins(AMOVB, f, &nod);
881 gins(AMOVWD, &nod, t);
885 regalloc(&nod, f, Z);
886 gins(AMOVB, f, &nod);
887 gins(AMOVWF, &nod, t);
908 regalloc(&nod, f, Z);
909 gins(AMOVBU, f, &nod);
910 gins(AMOVWD, &nod, t);
914 regalloc(&nod, f, Z);
915 gins(AMOVBU, f, &nod);
916 gins(AMOVWF, &nod, t);
945 diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
946 if(a == AMOVW || a == AMOVF || a == AMOVD)
950 if(f->op != OREGPAIR || t->op != OREGPAIR)
951 diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
952 gins(a, f->left, t->left);
953 gins(a, f->right, t->right);
959 gmover(Node *f, Node *t)
966 if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
989 gins(int a, Node *f, Node *t)
1003 gopcode(int o, Node *f1, Node *f2, Node *t)
1009 if(f1 != Z && f1->type != T)
1010 et = f1->type->etype;
1025 if(et == TDOUBLE || et == TVLONG)
1031 if(f2 && f2->op == OCONST) {
1041 if(et == TDOUBLE || et == TVLONG)
1076 assert(f1->op == OCONST);
1077 f1->vconst = 32-f1->vconst;
1091 if(et == TDOUBLE || et == TVLONG)
1101 if(et == TDOUBLE || et == TVLONG)
1140 if(et == TDOUBLE || et == TVLONG)
1144 naddr(f1, &p->from);
1145 if(a == ACMP && f1->op == OCONST && p->from.offset < 0 &&
1146 p->from.offset != 0x80000000) {
1148 p->from.offset = -p->from.offset;
1160 /* ensure NaN comparison is always false */
1161 if(typefd[et] && !true)
1166 if(typefd[et] && !true)
1171 if(typefd[et] && true)
1176 if(typefd[et] && true)
1195 naddr(f2, &p->from);
1204 diag(Z, "bad in gopcode %O", o);
1208 naddr(f1, &p->from);
1219 samaddr(Node *f, Node *t)
1227 if(f->reg != t->reg)
1232 return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1253 diag(Z, "bad in gbranch %O", o);
1260 patch(Prog *op, long pc)
1264 op->to.type = D_BRANCH;
1268 gpseudo(int a, Sym *s, Node *n)
1273 p->from.type = D_OREG;
1275 p->from.name = D_EXTERN;
1277 p->reg = (profileflg ? 0 : NOPROF);
1278 if(s->class == CSTATIC)
1279 p->from.name = D_STATIC;
1281 if(a == ADATA || a == AGLOBL)
1290 if(n->op == OCONST) {
1291 if(!typefd[n->type->etype]) {
1293 if(vv >= (vlong)(-32766) && vv < (vlong)32766)
1296 * should be specialised for constant values which will
1297 * fit in different instructionsl; for now, let 5l
1311 for(i=0; i<16; i++) {
1312 if((v & ~0xff) == 0)
1314 if((~v & ~0xff) == 0)
1316 v = (v<<2) | ((ulong)v>>30);
1326 if(typechlp[t->etype]) {
1327 if(exregoffset <= REGEXT-2)
1330 if(reg[o] && !resvreg[o])
1332 resvreg[o] = reg[o] = 1;
1336 if(typefd[t->etype]) {
1337 if(exfregoffset <= NFREG-1)
1339 o = exfregoffset + NREG;
1340 if(reg[o] && !resvreg[o])
1342 resvreg[o] = reg[o] = 1;
1349 schar ewidth[NTYPE] =
1352 SZ_CHAR, /* [TCHAR] */
1353 SZ_CHAR, /* [TUCHAR] */
1354 SZ_SHORT, /* [TSHORT] */
1355 SZ_SHORT, /* [TUSHORT] */
1356 SZ_INT, /* [TINT] */
1357 SZ_INT, /* [TUINT] */
1358 SZ_LONG, /* [TLONG] */
1359 SZ_LONG, /* [TULONG] */
1360 SZ_VLONG, /* [TVLONG] */
1361 SZ_VLONG, /* [TUVLONG] */
1362 SZ_FLOAT, /* [TFLOAT] */
1363 SZ_DOUBLE, /* [TDOUBLE] */
1364 SZ_IND, /* [TIND] */
1370 SZ_INT, /* [TENUM] */
1376 BCHAR|BUCHAR, /* [TCHAR] */
1377 BCHAR|BUCHAR, /* [TUCHAR] */
1378 BSHORT|BUSHORT, /* [TSHORT] */
1379 BSHORT|BUSHORT, /* [TUSHORT] */
1380 BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */
1381 BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */
1382 BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */
1383 BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */
1384 BVLONG|BUVLONG, /* [TVLONG] */
1385 BVLONG|BUVLONG, /* [TUVLONG] */
1386 BFLOAT, /* [TFLOAT] */
1387 BDOUBLE, /* [TDOUBLE] */
1388 BLONG|BULONG|BIND, /* [TIND] */
1392 BSTRUCT, /* [TSTRUCT] */
1393 BUNION, /* [TUNION] */