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)
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);
......
......@@ -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;
......
......@@ -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));
......
......@@ -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<<v, al
p1 = gins(AMOVW, &bl, &al);
p1->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<<v, ah
p1 = gins(AMOVW, &bh, &ah);
p1->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<<s, al
p1 = gins(AMOVW, N, &al);
p1->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<<s, al
p1 = gins(AMOVW, N, &al);
p1->from.type = D_SHIFT;
p1->from.offset = SHIFT_LL | s.val.u.reg << 8 | 1<<4 | bh.val.u.reg;
// MOVW.LT bh<<s, ah
p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
p1->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<<s, ah
p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
p1->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;
}
......
......@@ -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*);
......
......@@ -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;
......
......@@ -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;
};
};
};
......
......@@ -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
......
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