From b5365e76bb7f71331dd35fa44869021b09e3d6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aram=20H=C4=83v=C4=83rneanu?= Date: Mon, 15 Dec 2014 21:00:50 +0100 Subject: [PATCH] cmd/7g: fix comparisons Arm64 CPU uses op from, reg form, not op from, to. Fixes #5 Change-Id: I5203ee8f1c4fef52da2ec3da2afae07bf7ff0273 --- src/cmd/7g/cgen.c | 18 +++++++++--------- src/cmd/7g/gg.h | 2 ++ src/cmd/7g/ggen.c | 10 +++++----- src/cmd/7g/gsubr.c | 39 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/cmd/7g/cgen.c b/src/cmd/7g/cgen.c index 7a957f5e22eb0..dd6212207c572 100644 --- a/src/cmd/7g/cgen.c +++ b/src/cmd/7g/cgen.c @@ -348,7 +348,7 @@ cgen(Node *n, Node *res) cgen(nl, &n1); nodconst(&n2, types[tptr], 0); - gins(optoas(OCMP, types[tptr]), &n1, &n2); + gcmp(optoas(OCMP, types[tptr]), &n1, &n2); p1 = gbranch(optoas(OEQ, types[tptr]), T, 0); n2 = n1; @@ -383,7 +383,7 @@ cgen(Node *n, Node *res) cgen(nl, &n1); nodconst(&n2, types[tptr], 0); - gins(optoas(OCMP, types[tptr]), &n1, &n2); + gcmp(optoas(OCMP, types[tptr]), &n1, &n2); p1 = gbranch(optoas(OEQ, types[tptr]), T, 0); n2 = n1; @@ -735,7 +735,7 @@ agenr(Node *n, Node *a, Node *res) p1->from.offset = nl->type->bound; } } - gins(optoas(OCMP, types[TUINT64]), &n2, &n4); + gcmp(optoas(OCMP, types[TUINT64]), &n2, &n4); if(n4.op == OREGISTER) regfree(&n4); p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); @@ -1094,7 +1094,7 @@ bgen(Node *n, int true, int likely, Prog *to) regalloc(&n1, n->type, N); cgen(n, &n1); nodconst(&n2, n->type, 0); - gins(optoas(OCMP, n->type), &n1, &n2); + gcmp(optoas(OCMP, n->type), &n1, &n2); a = ABNE; if(!true) a = ABEQ; @@ -1201,7 +1201,7 @@ bgen(Node *n, int true, int likely, Prog *to) nodconst(&tmp, types[tptr], 0); regalloc(&n2, types[tptr], &n1); gmove(&n1, &n2); - gins(optoas(OCMP, types[tptr]), &n2, &tmp); + gcmp(optoas(OCMP, types[tptr]), &n2, &tmp); regfree(&n2); patch(gbranch(a, types[tptr], likely), to); regfree(&n1); @@ -1220,7 +1220,7 @@ bgen(Node *n, int true, int likely, Prog *to) nodconst(&tmp, types[tptr], 0); regalloc(&n2, types[tptr], &n1); gmove(&n1, &n2); - gins(optoas(OCMP, types[tptr]), &n2, &tmp); + gcmp(optoas(OCMP, types[tptr]), &n2, &tmp); regfree(&n2); patch(gbranch(a, types[tptr], likely), to); regfree(&n1); @@ -1254,7 +1254,7 @@ bgen(Node *n, int true, int likely, Prog *to) // TODO(minux): cmpi does accept 16-bit signed immediate as p->to. // and cmpli accepts 16-bit unsigned immediate. //if(smallintconst(nr)) { - // gins(optoas(OCMP, nr->type), &n1, nr); + // gcmp(optoas(OCMP, nr->type), &n1, nr); // patch(gbranch(optoas(a, nr->type), nr->type, likely), to); // regfree(&n1); // break; @@ -1265,7 +1265,7 @@ bgen(Node *n, int true, int likely, Prog *to) cmp: l = &n1; r = &n2; - gins(optoas(OCMP, nr->type), l, r); + gcmp(optoas(OCMP, nr->type), l, r); if(isfloat[nr->type->etype] && (a == OLE || a == OGE)) { // To get NaN right, must rewrite x <= y into separate x < y or x = y. switch(a) { @@ -1501,7 +1501,7 @@ sgen(Node *n, Node *ns, int64 w) p->to.type = D_OREG; p->to.offset = dir; - p = gins(ACMP, &src, &nend); + p = gcmp(ACMP, &src, &nend); patch(gbranch(ABNE, T, 0), ploop); regfree(&nend); diff --git a/src/cmd/7g/gg.h b/src/cmd/7g/gg.h index 612a34cac29c0..1cce339275ba9 100644 --- a/src/cmd/7g/gg.h +++ b/src/cmd/7g/gg.h @@ -95,6 +95,8 @@ void afunclit(Addr*, Node*); void nodfconst(Node*, Type*, Mpflt*); void gtrack(Sym*); void fixlargeoffset(Node *n); +void raddr(Node *n, Prog *p); +Prog* gcmp(int, Node*, Node*); /* * cplx.c diff --git a/src/cmd/7g/ggen.c b/src/cmd/7g/ggen.c index 6d93432463196..61718cc304e94 100644 --- a/src/cmd/7g/ggen.c +++ b/src/cmd/7g/ggen.c @@ -261,7 +261,7 @@ ginscall(Node *f, int proc) if(proc == 2) { nodreg(®, types[TINT64], D_R0+3); - p = gins(ACMP, ®, N); + p = gcmp(ACMP, ®, N); p->to.type = D_REG; p->to.reg = D_R0; p = gbranch(ABEQ, T, +1); @@ -562,7 +562,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res) } // Handle divide-by-zero panic. - p1 = gins(optoas(OCMP, t), &tr, N); + p1 = gcmp(optoas(OCMP, t), &tr, N); p1->to.type = D_REG; p1->to.reg = REGZERO; p1 = gbranch(optoas(ONE, t), T, +1); @@ -573,7 +573,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res) if(check) { nodconst(&nm1, t, -1); - gins(optoas(OCMP, t), &tr, &nm1); + gcmp(optoas(OCMP, t), &tr, &nm1); p1 = gbranch(optoas(ONE, t), T, +1); if(op == ODIV) { // a / (-1) is -a. @@ -857,7 +857,7 @@ cgen_shift(int op, int bounded, Node *nl, Node *nr, Node *res) // test and fix up large shifts if(!bounded) { nodconst(&n3, tcount, nl->type->width*8); - gins(optoas(OCMP, tcount), &n1, &n3); + gcmp(optoas(OCMP, tcount), &n1, &n3); p1 = gbranch(optoas(OLT, tcount), T, +1); if(op == ORSH && issigned[nl->type->etype]) { nodconst(&n3, types[TUINT32], nl->type->width*8-1); @@ -923,7 +923,7 @@ clearfat(Node *nl) p->to.offset = 8; pl = p; - p = gins(ACMP, &dst, &end); + p = gcmp(ACMP, &dst, &end); patch(gbranch(ABNE, T, 0), pl); regfree(&end); diff --git a/src/cmd/7g/gsubr.c b/src/cmd/7g/gsubr.c index 61e2918ac01f7..c3f2e991c75b0 100644 --- a/src/cmd/7g/gsubr.c +++ b/src/cmd/7g/gsubr.c @@ -573,7 +573,7 @@ ginscon2(int as, Node *n2, vlong c) fatal("ginscon2"); case ACMP: if(-BIG <= c && c <= BIG) { - gins(as, n2, &n1); + gcmp(as, n2, &n1); return; } break; @@ -581,7 +581,7 @@ ginscon2(int as, Node *n2, vlong c) // MOV n1 into register first regalloc(&ntmp, types[TINT64], N); gins(AMOV, &n1, &ntmp); - gins(as, n2, &ntmp); + gcmp(as, n2, &ntmp); regfree(&ntmp); } @@ -1083,6 +1083,41 @@ fixlargeoffset(Node *n) } } +/* + * insert n into reg slot of p + */ +void +raddr(Node *n, Prog *p) +{ + Addr a; + + naddr(n, &a, 1); + if(a.type != D_REG && a.type != D_FREG) { + if(n) + fatal("bad in raddr: %O", n->op); + else + fatal("bad in raddr: "); + p->reg = NREG; + } else + p->reg = a.reg; +} + +/* generate a comparison +TODO(kaib): one of the args can actually be a small constant. relax the constraint and fix call sites. + */ +Prog* +gcmp(int as, Node *lhs, Node *rhs) +{ + Prog *p; + + if(lhs->op != OREGISTER) + fatal("bad operands to gcmp: %O %O", lhs->op, rhs->op); + + p = gins(as, rhs, N); + raddr(lhs, p); + return p; +} + /* * generate code to compute n; * make a refer to result.