From 101f7cbd61c61222460e4b028ad6256aeae84147 Mon Sep 17 00:00:00 2001 From: Kai Backman Date: Mon, 12 Oct 2009 13:35:28 -0700 Subject: [PATCH] changed 5c 64 bit word ordering to little endian so it matches 5g. fixes to 64 bit code gen. added (finally) function to do shifts properly. go/test: passes 83% (287/342) R=rsc APPROVED=rsc DELTA=156 (50 added, 53 deleted, 53 changed) OCL=35589 CL=35616 --- src/cmd/5c/cgen.c | 4 +- src/cmd/5c/gc.h | 1 + src/cmd/5c/swt.c | 4 +- src/cmd/5g/cgen64.c | 124 +++++++++++++------------------------ src/cmd/5g/gg.h | 2 + src/cmd/5g/gsubr.c | 28 +++++++++ src/pkg/runtime/arm/vlrt.c | 26 ++++---- test/arm-pass.txt | 2 + 8 files changed, 94 insertions(+), 97 deletions(-) diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c index bbad8a17919..9e74f515b04 100644 --- a/src/cmd/5c/cgen.c +++ b/src/cmd/5c/cgen.c @@ -916,12 +916,12 @@ sugen(Node *n, Node *nn, int32 w) reglcgen(&nod1, nn, Z); nn->type = t; - if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ + if(isbigendian) gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); else gopcode(OAS, nod32const(n->vconst), Z, &nod1); nod1.xoffset += SZ_LONG; - if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ + if(isbigendian) gopcode(OAS, nod32const(n->vconst), Z, &nod1); else gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h index 9aa7681b2e9..9e9d1bd7d5a 100644 --- a/src/cmd/5c/gc.h +++ b/src/cmd/5c/gc.h @@ -175,6 +175,7 @@ EXTERN int32 continpc; EXTERN int32 curarg; EXTERN int32 cursafe; EXTERN Prog* firstp; +EXTERN int32 isbigendian; EXTERN Prog* lastp; EXTERN int32 maxargsafe; EXTERN int mnstring; diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c index 5f50e483c54..4c2a81cbfff 100644 --- a/src/cmd/5c/swt.c +++ b/src/cmd/5c/swt.c @@ -311,13 +311,13 @@ gextern(Sym *s, Node *a, int32 o, int32 w) { if(a->op == OCONST && typev[a->type->etype]) { - if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ + if(isbigendian) gpseudo(ADATA, s, nod32const(a->vconst>>32)); else gpseudo(ADATA, s, nod32const(a->vconst)); p->from.offset += o; p->reg = 4; - if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ + if(isbigendian) gpseudo(ADATA, s, nod32const(a->vconst)); else gpseudo(ADATA, s, nod32const(a->vconst>>32)); diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 8e768198db5..a732991db40 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -49,7 +49,8 @@ cgen64(Node *n, Node *res) gmove(ncon(0), &t1); - gins(ASUB, &t1, &al); + p1 = gins(ASUB, &t1, &al); + p1->scond |= C_SBIT; gins(ASBC, &t1, &ah); gins(AMOVW, &al, &lo2); @@ -104,6 +105,7 @@ cgen64(Node *n, Node *res) regalloc(&al, lo1.type, N); regalloc(&ah, hi1.type, N); + // Do op. Leave result in ah:al. switch(n->op) { default: @@ -117,7 +119,8 @@ cgen64(Node *n, Node *res) gins(AMOVW, &lo1, &al); gins(AMOVW, &hi2, &bh); gins(AMOVW, &lo2, &bl); - gins(AADD, &bl, &al); + p1 = gins(AADD, &bl, &al); + p1->scond |= C_SBIT; gins(AADC, &bh, &ah); regfree(&bl); regfree(&bh); @@ -131,7 +134,8 @@ cgen64(Node *n, Node *res) gins(AMOVW, &hi1, &ah); gins(AMOVW, &lo2, &bl); gins(AMOVW, &hi2, &bh); - gins(ASUB, &bl, &al); + p1 = gins(ASUB, &bl, &al); + p1->scond |= C_SBIT; gins(ASBC, &bh, &ah); regfree(&bl); regfree(&bh); @@ -139,10 +143,10 @@ cgen64(Node *n, Node *res) case OMUL: // TODO(kaib): this can be done with 4 regs and does not need 6 - regalloc(&bh, types[TPTR32], N); regalloc(&bl, types[TPTR32], N); - regalloc(&ch, types[TPTR32], N); + regalloc(&bh, types[TPTR32], N); regalloc(&cl, types[TPTR32], N); + regalloc(&ch, types[TPTR32], N); // load args into bh:bl and bh:bl. gins(AMOVW, &hi1, &bh); @@ -156,27 +160,27 @@ cgen64(Node *n, Node *res) p1->from.reg = bl.val.u.reg; p1->reg = cl.val.u.reg; p1->to.type = D_REGREG; - p1->to.reg = al.val.u.reg; - p1->to.offset = ah.val.u.reg; + p1->to.reg = ah.val.u.reg; + p1->to.offset = al.val.u.reg; //print("%P\n", p1); // bl * ch - p1 = gins(AMULALU, N, N); + p1 = gins(AMULA, N, N); p1->from.type = D_REG; - p1->from.reg = ah.val.u.reg; - p1->reg = bl.val.u.reg; + p1->from.reg = bl.val.u.reg; + p1->reg = ch.val.u.reg; p1->to.type = D_REGREG; - p1->to.reg = ch.val.u.reg; + p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); // bh * cl - p1 = gins(AMULALU, N, N); + p1 = gins(AMULA, N, N); p1->from.type = D_REG; - p1->from.reg = ah.val.u.reg; - p1->reg = bh.val.u.reg; + p1->from.reg = bh.val.u.reg; + p1->reg = cl.val.u.reg; p1->to.type = D_REGREG; - p1->to.reg = cl.val.u.reg; + p1->to.reg = ah.val.u.reg; p1->to.offset = ah.val.u.reg; //print("%P\n", p1); @@ -188,8 +192,8 @@ cgen64(Node *n, Node *res) break; case OLSH: - regalloc(&bh, hi1.type, N); regalloc(&bl, lo1.type, N); + regalloc(&bh, hi1.type, N); gins(AMOVW, &hi1, &bh); gins(AMOVW, &lo1, &bl); @@ -205,32 +209,21 @@ cgen64(Node *n, Node *res) if(v >= 32) { gins(AEOR, &al, &al); // MOVW bl<<(v-32), ah - p1 = gins(AMOVW, &bl, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | (v-32)<<7 | bl.val.u.reg; - p1->from.reg = NREG; + gshift(AMOVW, &bl, SHIFT_LL, v-32, &ah); goto olsh_break; } // general literal left shift // MOVW bl<from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | v<<7 | bl.val.u.reg; - p1->from.reg = NREG; + gshift(AMOVW, &bl, SHIFT_LL, v, &al); // MOVW bh<from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | v<<7 | bh.val.u.reg; - p1->from.reg = NREG; + gshift(AMOVW, &bh, SHIFT_LL, v, &ah); // OR bl>>(32-v), ah - p1 = gins(AORR, &bl, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | (32-v)<<7 | bl.val.u.reg; - p1->from.reg = NREG; + gshift(AORR, &bl, SHIFT_LR, 32-v, &ah); + goto olsh_break; } @@ -244,25 +237,19 @@ cgen64(Node *n, Node *res) gcmp(ACMP, &s, &creg); // MOVW.LT bl<from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | s.val.u.reg << 8 | 1<<4 | bl.val.u.reg; + p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al); p1->scond = C_SCOND_LT; - // MOVW.LT bh<from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | s.val.u.reg << 8 | 1<<4 | bh.val.u.reg; + // MOVW.LT bh<scond = C_SCOND_LT; // SUB.LT creg, s p1 = gins(ASUB, &creg, &s); p1->scond = C_SCOND_LT; - // OR.LT bl>>(32-s), ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | t1.val.u.reg<<8| 1<<4 | bl.val.u.reg; + // OR.LT bl>>creg, ah + p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah); p1->scond = C_SCOND_LT; // BLT end @@ -278,19 +265,15 @@ cgen64(Node *n, Node *res) p1->scond = C_SCOND_LT; // MOVW.LT creg>>1, creg - p1 = gins(AMOVW, N, &creg); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | 1<<7 | creg.val.u.reg; + p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg); p1->scond = C_SCOND_LT; // SUB.LT creg, s p1 = gins(ASUB, &s, &creg); p1->scond = C_SCOND_LT; - // MOVW bl<<(s-32), ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | s.val.u.reg<<8 | 1<<4 | bl.val.u.reg; + // MOVW bl<scond = C_SCOND_LT; p3 = gbranch(ABLT, T); @@ -310,8 +293,8 @@ olsh_break: case ORSH: - regalloc(&bh, hi1.type, N); regalloc(&bl, lo1.type, N); + regalloc(&bh, hi1.type, N); gins(AMOVW, &hi1, &bh); gins(AMOVW, &lo1, &bl); @@ -320,14 +303,10 @@ olsh_break: if(v >= 64) { if(bh.type->etype == TINT32) { // MOVW bh->31, al - p1 = gins(AMOVW, N, &al); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_AR | 31 << 7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_AR, 31, &al); // MOVW bh->31, ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_AR | 31 << 7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { gins(AEOR, &al, &al); gins(AEOR, &ah, &ah); @@ -337,19 +316,13 @@ olsh_break: if(v >= 32) { if(bh.type->etype == TINT32) { // MOVW bh->(v-32), al - p1 = gins(AMOVW, N, &al); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_AR | (v-32)<<7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_AR, v-32, &al); // MOVW bh->31, ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_AR | 31<<7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_AR, 31, &ah); } else { // MOVW bh>>(v-32), al - p1 = gins(AMOVW, N, &al); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | (v-32)<<7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_LR, v-32, &al); gins(AEOR, &ah, &ah); } goto orsh_break; @@ -358,26 +331,17 @@ olsh_break: // general literal right shift // MOVW bl>>v, al - p1 = gins(AMOVW, N, &al); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | v<<7 | bl.val.u.reg; + gshift(AMOVW, &bl, SHIFT_LR, v, &al); - // OR bh<<(32-v), al, al - p1 = gins(AORR, N, &al); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LL | (32-v)<<7 | bh.val.u.reg; - p1->reg = al.val.u.reg; + // OR bh<<(32-v), al + gshift(AORR, &bh, SHIFT_LL, 32-v, &al); if(bh.type->etype == TINT32) { // MOVW bh->v, ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_AR | v<<7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_AR, v, &ah); } else { // MOVW bh>>v, ah - p1 = gins(AMOVW, N, &ah); - p1->from.type = D_SHIFT; - p1->from.offset = SHIFT_LR | v<<7 | bh.val.u.reg; + gshift(AMOVW, &bh, SHIFT_LR, v, &ah); } goto orsh_break; } diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h index c681b59dd1c..867c34139cc 100644 --- a/src/cmd/5g/gg.h +++ b/src/cmd/5g/gg.h @@ -97,6 +97,8 @@ Prog* gins(int, Node*, Node*); int samaddr(Node*, Node*); void raddr(Node *n, Prog *p); Prog* gcmp(int, Node*, Node*); +Prog* gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs); +Prog * gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs); void naddr(Node*, Addr*); void cgen_aret(Node*, Node*); diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c index df175349fe7..e9131b43683 100644 --- a/src/cmd/5g/gsubr.c +++ b/src/cmd/5g/gsubr.c @@ -964,6 +964,34 @@ gcmp(int as, Node *lhs, Node *rhs) return p; } +/* generate a constant shift +*/ +Prog* +gshift(int as, Node *lhs, int32 stype, int32 sval, Node *rhs) +{ + Prog *p; + + if (sval < 0 || sval > 31) + fatal("bad shift value: %d", sval); + + p = gins(as, N, rhs); + p->from.type = D_SHIFT; + p->from.offset = stype | sval<<7 | lhs->val.u.reg; + return p; +} + +/* generate a register shift +*/ +Prog * +gregshift(int as, Node *lhs, int32 stype, Node *reg, Node *rhs) +{ + Prog *p; + p = gins(as, N, rhs); + p->from.type = D_SHIFT; + p->from.offset = stype | reg->val.u.reg << 8 | 1<<4 | lhs->val.u.reg; + return p; +} + /* * generate code to compute n; diff --git a/src/pkg/runtime/arm/vlrt.c b/src/pkg/runtime/arm/vlrt.c index a012b3e14ef..276a91f2041 100755 --- a/src/pkg/runtime/arm/vlrt.c +++ b/src/pkg/runtime/arm/vlrt.c @@ -34,19 +34,19 @@ typedef signed char schar; typedef struct Vlong Vlong; struct Vlong { - union - { - struct - { - ulong hi; - ulong lo; - }; - struct - { - ushort hims; - ushort hils; - ushort loms; - ushort lols; + union + { + struct + { + ulong lo; + ulong hi; + }; + struct + { + ushort lols; + ushort loms; + ushort hils; + ushort hims; }; }; }; diff --git a/test/arm-pass.txt b/test/arm-pass.txt index d16071006d6..15c7be6e41e 100644 --- a/test/arm-pass.txt +++ b/test/arm-pass.txt @@ -243,6 +243,7 @@ interface/returntype.go interface/struct.go iota.go ken/complit.go +ken/divmod.go ken/embed.go ken/for.go ken/interbasic.go @@ -262,6 +263,7 @@ ken/simpfun.go ken/simpprint.go ken/simpswitch.go ken/simpvar.go +ken/string.go ken/strvar.go method.go method1.go