Commit 101f7cbd authored by Kai Backman's avatar Kai Backman

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
parent 23724081
...@@ -916,12 +916,12 @@ sugen(Node *n, Node *nn, int32 w) ...@@ -916,12 +916,12 @@ sugen(Node *n, Node *nn, int32 w)
reglcgen(&nod1, nn, Z); reglcgen(&nod1, nn, Z);
nn->type = t; nn->type = t;
if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(isbigendian)
gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
else else
gopcode(OAS, nod32const(n->vconst), Z, &nod1); gopcode(OAS, nod32const(n->vconst), Z, &nod1);
nod1.xoffset += SZ_LONG; nod1.xoffset += SZ_LONG;
if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(isbigendian)
gopcode(OAS, nod32const(n->vconst), Z, &nod1); gopcode(OAS, nod32const(n->vconst), Z, &nod1);
else else
gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
......
...@@ -175,6 +175,7 @@ EXTERN int32 continpc; ...@@ -175,6 +175,7 @@ EXTERN int32 continpc;
EXTERN int32 curarg; EXTERN int32 curarg;
EXTERN int32 cursafe; EXTERN int32 cursafe;
EXTERN Prog* firstp; EXTERN Prog* firstp;
EXTERN int32 isbigendian;
EXTERN Prog* lastp; EXTERN Prog* lastp;
EXTERN int32 maxargsafe; EXTERN int32 maxargsafe;
EXTERN int mnstring; EXTERN int mnstring;
......
...@@ -311,13 +311,13 @@ gextern(Sym *s, Node *a, int32 o, int32 w) ...@@ -311,13 +311,13 @@ gextern(Sym *s, Node *a, int32 o, int32 w)
{ {
if(a->op == OCONST && typev[a->type->etype]) { 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)); gpseudo(ADATA, s, nod32const(a->vconst>>32));
else else
gpseudo(ADATA, s, nod32const(a->vconst)); gpseudo(ADATA, s, nod32const(a->vconst));
p->from.offset += o; p->from.offset += o;
p->reg = 4; p->reg = 4;
if(1 || align(0, types[TCHAR], Aarg1)) /* isbigendian */ if(isbigendian)
gpseudo(ADATA, s, nod32const(a->vconst)); gpseudo(ADATA, s, nod32const(a->vconst));
else else
gpseudo(ADATA, s, nod32const(a->vconst>>32)); gpseudo(ADATA, s, nod32const(a->vconst>>32));
......
...@@ -49,7 +49,8 @@ cgen64(Node *n, Node *res) ...@@ -49,7 +49,8 @@ cgen64(Node *n, Node *res)
gmove(ncon(0), &t1); gmove(ncon(0), &t1);
gins(ASUB, &t1, &al); p1 = gins(ASUB, &t1, &al);
p1->scond |= C_SBIT;
gins(ASBC, &t1, &ah); gins(ASBC, &t1, &ah);
gins(AMOVW, &al, &lo2); gins(AMOVW, &al, &lo2);
...@@ -104,6 +105,7 @@ cgen64(Node *n, Node *res) ...@@ -104,6 +105,7 @@ cgen64(Node *n, Node *res)
regalloc(&al, lo1.type, N); regalloc(&al, lo1.type, N);
regalloc(&ah, hi1.type, N); regalloc(&ah, hi1.type, N);
// Do op. Leave result in ah:al. // Do op. Leave result in ah:al.
switch(n->op) { switch(n->op) {
default: default:
...@@ -117,7 +119,8 @@ cgen64(Node *n, Node *res) ...@@ -117,7 +119,8 @@ cgen64(Node *n, Node *res)
gins(AMOVW, &lo1, &al); gins(AMOVW, &lo1, &al);
gins(AMOVW, &hi2, &bh); gins(AMOVW, &hi2, &bh);
gins(AMOVW, &lo2, &bl); gins(AMOVW, &lo2, &bl);
gins(AADD, &bl, &al); p1 = gins(AADD, &bl, &al);
p1->scond |= C_SBIT;
gins(AADC, &bh, &ah); gins(AADC, &bh, &ah);
regfree(&bl); regfree(&bl);
regfree(&bh); regfree(&bh);
...@@ -131,7 +134,8 @@ cgen64(Node *n, Node *res) ...@@ -131,7 +134,8 @@ cgen64(Node *n, Node *res)
gins(AMOVW, &hi1, &ah); gins(AMOVW, &hi1, &ah);
gins(AMOVW, &lo2, &bl); gins(AMOVW, &lo2, &bl);
gins(AMOVW, &hi2, &bh); gins(AMOVW, &hi2, &bh);
gins(ASUB, &bl, &al); p1 = gins(ASUB, &bl, &al);
p1->scond |= C_SBIT;
gins(ASBC, &bh, &ah); gins(ASBC, &bh, &ah);
regfree(&bl); regfree(&bl);
regfree(&bh); regfree(&bh);
...@@ -139,10 +143,10 @@ cgen64(Node *n, Node *res) ...@@ -139,10 +143,10 @@ cgen64(Node *n, Node *res)
case OMUL: case OMUL:
// TODO(kaib): this can be done with 4 regs and does not need 6 // 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(&bl, types[TPTR32], N);
regalloc(&ch, types[TPTR32], N); regalloc(&bh, types[TPTR32], N);
regalloc(&cl, types[TPTR32], N); regalloc(&cl, types[TPTR32], N);
regalloc(&ch, types[TPTR32], N);
// load args into bh:bl and bh:bl. // load args into bh:bl and bh:bl.
gins(AMOVW, &hi1, &bh); gins(AMOVW, &hi1, &bh);
...@@ -156,27 +160,27 @@ cgen64(Node *n, Node *res) ...@@ -156,27 +160,27 @@ cgen64(Node *n, Node *res)
p1->from.reg = bl.val.u.reg; p1->from.reg = bl.val.u.reg;
p1->reg = cl.val.u.reg; p1->reg = cl.val.u.reg;
p1->to.type = D_REGREG; p1->to.type = D_REGREG;
p1->to.reg = al.val.u.reg; p1->to.reg = ah.val.u.reg;
p1->to.offset = ah.val.u.reg; p1->to.offset = al.val.u.reg;
//print("%P\n", p1); //print("%P\n", p1);
// bl * ch // bl * ch
p1 = gins(AMULALU, N, N); p1 = gins(AMULA, N, N);
p1->from.type = D_REG; p1->from.type = D_REG;
p1->from.reg = ah.val.u.reg; p1->from.reg = bl.val.u.reg;
p1->reg = bl.val.u.reg; p1->reg = ch.val.u.reg;
p1->to.type = D_REGREG; 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; p1->to.offset = ah.val.u.reg;
//print("%P\n", p1); //print("%P\n", p1);
// bh * cl // bh * cl
p1 = gins(AMULALU, N, N); p1 = gins(AMULA, N, N);
p1->from.type = D_REG; p1->from.type = D_REG;
p1->from.reg = ah.val.u.reg; p1->from.reg = bh.val.u.reg;
p1->reg = bh.val.u.reg; p1->reg = cl.val.u.reg;
p1->to.type = D_REGREG; 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; p1->to.offset = ah.val.u.reg;
//print("%P\n", p1); //print("%P\n", p1);
...@@ -188,8 +192,8 @@ cgen64(Node *n, Node *res) ...@@ -188,8 +192,8 @@ cgen64(Node *n, Node *res)
break; break;
case OLSH: case OLSH:
regalloc(&bh, hi1.type, N);
regalloc(&bl, lo1.type, N); regalloc(&bl, lo1.type, N);
regalloc(&bh, hi1.type, N);
gins(AMOVW, &hi1, &bh); gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl); gins(AMOVW, &lo1, &bl);
...@@ -205,32 +209,21 @@ cgen64(Node *n, Node *res) ...@@ -205,32 +209,21 @@ cgen64(Node *n, Node *res)
if(v >= 32) { if(v >= 32) {
gins(AEOR, &al, &al); gins(AEOR, &al, &al);
// MOVW bl<<(v-32), ah // MOVW bl<<(v-32), ah
p1 = gins(AMOVW, &bl, &ah); gshift(AMOVW, &bl, SHIFT_LL, v-32, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | (v-32)<<7 | bl.val.u.reg;
p1->from.reg = NREG;
goto olsh_break; goto olsh_break;
} }
// general literal left shift // general literal left shift
// MOVW bl<<v, al // MOVW bl<<v, al
p1 = gins(AMOVW, &bl, &al); gshift(AMOVW, &bl, SHIFT_LL, v, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | v<<7 | bl.val.u.reg;
p1->from.reg = NREG;
// MOVW bh<<v, ah // MOVW bh<<v, ah
p1 = gins(AMOVW, &bh, &ah); gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | v<<7 | bh.val.u.reg;
p1->from.reg = NREG;
// OR bl>>(32-v), ah // OR bl>>(32-v), ah
p1 = gins(AORR, &bl, &ah); gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | (32-v)<<7 | bl.val.u.reg;
p1->from.reg = NREG;
goto olsh_break; goto olsh_break;
} }
...@@ -244,25 +237,19 @@ cgen64(Node *n, Node *res) ...@@ -244,25 +237,19 @@ cgen64(Node *n, Node *res)
gcmp(ACMP, &s, &creg); gcmp(ACMP, &s, &creg);
// MOVW.LT bl<<s, al // MOVW.LT bl<<s, al
p1 = gins(AMOVW, N, &al); p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | s.val.u.reg << 8 | 1<<4 | bl.val.u.reg;
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// MOVW.LT bh<<s, al // MOVW.LT bh<<s, ah
p1 = gins(AMOVW, N, &al); p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | s.val.u.reg << 8 | 1<<4 | bh.val.u.reg;
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// SUB.LT creg, s // SUB.LT creg, s
p1 = gins(ASUB, &creg, &s); p1 = gins(ASUB, &creg, &s);
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// OR.LT bl>>(32-s), ah // OR.LT bl>>creg, ah
p1 = gins(AMOVW, N, &ah); p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | t1.val.u.reg<<8| 1<<4 | bl.val.u.reg;
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// BLT end // BLT end
...@@ -278,19 +265,15 @@ cgen64(Node *n, Node *res) ...@@ -278,19 +265,15 @@ cgen64(Node *n, Node *res)
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// MOVW.LT creg>>1, creg // MOVW.LT creg>>1, creg
p1 = gins(AMOVW, N, &creg); p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | 1<<7 | creg.val.u.reg;
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// SUB.LT creg, s // SUB.LT creg, s
p1 = gins(ASUB, &s, &creg); p1 = gins(ASUB, &s, &creg);
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
// MOVW bl<<(s-32), ah // MOVW bl<<s, ah
p1 = gins(AMOVW, N, &ah); p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | s.val.u.reg<<8 | 1<<4 | bl.val.u.reg;
p1->scond = C_SCOND_LT; p1->scond = C_SCOND_LT;
p3 = gbranch(ABLT, T); p3 = gbranch(ABLT, T);
...@@ -310,8 +293,8 @@ olsh_break: ...@@ -310,8 +293,8 @@ olsh_break:
case ORSH: case ORSH:
regalloc(&bh, hi1.type, N);
regalloc(&bl, lo1.type, N); regalloc(&bl, lo1.type, N);
regalloc(&bh, hi1.type, N);
gins(AMOVW, &hi1, &bh); gins(AMOVW, &hi1, &bh);
gins(AMOVW, &lo1, &bl); gins(AMOVW, &lo1, &bl);
...@@ -320,14 +303,10 @@ olsh_break: ...@@ -320,14 +303,10 @@ olsh_break:
if(v >= 64) { if(v >= 64) {
if(bh.type->etype == TINT32) { if(bh.type->etype == TINT32) {
// MOVW bh->31, al // MOVW bh->31, al
p1 = gins(AMOVW, N, &al); gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_AR | 31 << 7 | bh.val.u.reg;
// MOVW bh->31, ah // MOVW bh->31, ah
p1 = gins(AMOVW, N, &ah); gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_AR | 31 << 7 | bh.val.u.reg;
} else { } else {
gins(AEOR, &al, &al); gins(AEOR, &al, &al);
gins(AEOR, &ah, &ah); gins(AEOR, &ah, &ah);
...@@ -337,19 +316,13 @@ olsh_break: ...@@ -337,19 +316,13 @@ olsh_break:
if(v >= 32) { if(v >= 32) {
if(bh.type->etype == TINT32) { if(bh.type->etype == TINT32) {
// MOVW bh->(v-32), al // MOVW bh->(v-32), al
p1 = gins(AMOVW, N, &al); gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_AR | (v-32)<<7 | bh.val.u.reg;
// MOVW bh->31, ah // MOVW bh->31, ah
p1 = gins(AMOVW, N, &ah); gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_AR | 31<<7 | bh.val.u.reg;
} else { } else {
// MOVW bh>>(v-32), al // MOVW bh>>(v-32), al
p1 = gins(AMOVW, N, &al); gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | (v-32)<<7 | bh.val.u.reg;
gins(AEOR, &ah, &ah); gins(AEOR, &ah, &ah);
} }
goto orsh_break; goto orsh_break;
...@@ -358,26 +331,17 @@ olsh_break: ...@@ -358,26 +331,17 @@ olsh_break:
// general literal right shift // general literal right shift
// MOVW bl>>v, al // MOVW bl>>v, al
p1 = gins(AMOVW, N, &al); gshift(AMOVW, &bl, SHIFT_LR, v, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | v<<7 | bl.val.u.reg;
// OR bh<<(32-v), al, al // OR bh<<(32-v), al
p1 = gins(AORR, N, &al); gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | (32-v)<<7 | bh.val.u.reg;
p1->reg = al.val.u.reg;
if(bh.type->etype == TINT32) { if(bh.type->etype == TINT32) {
// MOVW bh->v, ah // MOVW bh->v, ah
p1 = gins(AMOVW, N, &ah); gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_AR | v<<7 | bh.val.u.reg;
} else { } else {
// MOVW bh>>v, ah // MOVW bh>>v, ah
p1 = gins(AMOVW, N, &ah); gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LR | v<<7 | bh.val.u.reg;
} }
goto orsh_break; goto orsh_break;
} }
......
...@@ -97,6 +97,8 @@ Prog* gins(int, Node*, Node*); ...@@ -97,6 +97,8 @@ Prog* gins(int, Node*, Node*);
int samaddr(Node*, Node*); int samaddr(Node*, Node*);
void raddr(Node *n, Prog *p); void raddr(Node *n, Prog *p);
Prog* gcmp(int, Node*, Node*); 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 naddr(Node*, Addr*);
void cgen_aret(Node*, Node*); void cgen_aret(Node*, Node*);
......
...@@ -964,6 +964,34 @@ gcmp(int as, Node *lhs, Node *rhs) ...@@ -964,6 +964,34 @@ gcmp(int as, Node *lhs, Node *rhs)
return p; 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; * generate code to compute n;
......
...@@ -34,19 +34,19 @@ typedef signed char schar; ...@@ -34,19 +34,19 @@ typedef signed char schar;
typedef struct Vlong Vlong; typedef struct Vlong Vlong;
struct Vlong struct Vlong
{ {
union union
{ {
struct struct
{ {
ulong hi; ulong lo;
ulong lo; ulong hi;
}; };
struct struct
{ {
ushort hims; ushort lols;
ushort hils; ushort loms;
ushort loms; ushort hils;
ushort lols; ushort hims;
}; };
}; };
}; };
......
...@@ -243,6 +243,7 @@ interface/returntype.go ...@@ -243,6 +243,7 @@ interface/returntype.go
interface/struct.go interface/struct.go
iota.go iota.go
ken/complit.go ken/complit.go
ken/divmod.go
ken/embed.go ken/embed.go
ken/for.go ken/for.go
ken/interbasic.go ken/interbasic.go
...@@ -262,6 +263,7 @@ ken/simpfun.go ...@@ -262,6 +263,7 @@ ken/simpfun.go
ken/simpprint.go ken/simpprint.go
ken/simpswitch.go ken/simpswitch.go
ken/simpvar.go ken/simpvar.go
ken/string.go
ken/strvar.go ken/strvar.go
method.go method.go
method1.go method1.go
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment