1
0
mirror of https://github.com/golang/go synced 2024-11-25 05:57:57 -07:00

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
This commit is contained in:
Kai Backman 2009-10-12 13:35:28 -07:00
parent 2372408189
commit 101f7cbd61
8 changed files with 94 additions and 97 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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;
}

View File

@ -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*);

View File

@ -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;

View File

@ -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;
};
};
};

View File

@ -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