Commit 190b5c9a authored by Kai Backman's avatar Kai Backman

fixes to 5g object file generation. arm specific regalloc.

R=rsc
APPROVED=rsc
DELTA=976  (164 added, 237 deleted, 575 changed)
OCL=30705
CL=30743
parent 94439982
...@@ -26,6 +26,7 @@ struct Addr ...@@ -26,6 +26,7 @@ struct Addr
Sym* sym; Sym* sym;
int width; int width;
uchar type; uchar type;
char reg;
uchar index; uchar index;
uchar etype; uchar etype;
uchar scale; /* doubles as width in DATA op */ uchar scale; /* doubles as width in DATA op */
...@@ -40,12 +41,18 @@ struct Prog ...@@ -40,12 +41,18 @@ struct Prog
Addr from; // src address Addr from; // src address
Addr to; // dst address Addr to; // dst address
Prog* link; // next instruction in this func Prog* link; // next instruction in this func
void* reg; // pointer to containing Reg struct char reg;
uchar scond;
}; };
#define REGALLOC_R0 0
#define REGALLOC_RMAX REGEXT
#define REGALLOC_F0 (REGALLOC_RMAX+1)
#define REGALLOC_FMAX (REGALLOC_F0 + FREGEXT)
EXTERN Biobuf* bout; EXTERN Biobuf* bout;
EXTERN int32 dynloc; EXTERN int32 dynloc;
EXTERN uchar reg[D_NONE]; EXTERN uchar reg[REGALLOC_FMAX];
EXTERN int32 pcloc; // instruction counter EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring; EXTERN Strlit emptystring;
extern char* anames[]; extern char* anames[];
...@@ -57,6 +64,7 @@ EXTERN Node* deferproc; ...@@ -57,6 +64,7 @@ EXTERN Node* deferproc;
EXTERN Node* deferreturn; EXTERN Node* deferreturn;
EXTERN Node* throwindex; EXTERN Node* throwindex;
EXTERN Node* throwreturn; EXTERN Node* throwreturn;
EXTERN int maxstksize;
/* /*
* gen.c * gen.c
...@@ -115,6 +123,8 @@ void ginit(void); ...@@ -115,6 +123,8 @@ void ginit(void);
void gclean(void); void gclean(void);
void regalloc(Node*, Type*, Node*); void regalloc(Node*, Type*, Node*);
void regfree(Node*); void regfree(Node*);
void tempalloc(Node*, Type*);
void tempfree(Node*);
Node* nodarg(Type*, int); Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int); void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int); void nodindreg(Node*, Type*, int);
......
...@@ -65,10 +65,8 @@ compile(Node *fn) ...@@ -65,10 +65,8 @@ compile(Node *fn)
ptxt = gins(ATEXT, curfn->nname, &nod1); ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from); afunclit(&ptxt->from);
ginit();
gen(curfn->enter); gen(curfn->enter);
gen(curfn->nbody); gen(curfn->nbody);
gclean();
checklabels(); checklabels();
if(curfn->type->outtuple != 0) if(curfn->type->outtuple != 0)
...@@ -85,10 +83,14 @@ compile(Node *fn) ...@@ -85,10 +83,14 @@ compile(Node *fn)
*/ */
// fill in argument size // fill in argument size
ptxt->to.type = D_CONST2;
ptxt->to.offset2 = rnd(curfn->type->argwid, maxround); ptxt->to.offset2 = rnd(curfn->type->argwid, maxround);
// fill in final stack size // fill in final stack size
ptxt->to.offset = rnd(stksize+maxarg, maxround); if(stksize > maxstksize)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, maxround);
maxstksize = 0;
if(debug['f']) if(debug['f'])
frame(0); frame(0);
...@@ -359,42 +361,6 @@ cgen_asop(Node *n) ...@@ -359,42 +361,6 @@ cgen_asop(Node *n)
if(!isint[nr->type->etype]) if(!isint[nr->type->etype])
goto hard; goto hard;
switch(n->etype) {
case OADD:
if(smallintconst(nr))
if(mpgetfix(nr->val.u.xval) == 1) {
a = optoas(OINC, nl->type);
if(nl->addable) {
gins(a, N, nl);
goto ret;
}
if(sudoaddable(a, nl, &addr)) {
p1 = gins(a, N, N);
p1->to = addr;
sudoclean();
goto ret;
}
}
break;
case OSUB:
if(smallintconst(nr))
if(mpgetfix(nr->val.u.xval) == 1) {
a = optoas(ODEC, nl->type);
if(nl->addable) {
gins(a, N, nl);
goto ret;
}
if(sudoaddable(a, nl, &addr)) {
p1 = gins(a, N, N);
p1->to = addr;
sudoclean();
goto ret;
}
}
break;
}
switch(n->etype) { switch(n->etype) {
case OADD: case OADD:
case OSUB: case OSUB:
......
...@@ -64,6 +64,8 @@ zhist(Biobuf *b, int line, vlong offset) ...@@ -64,6 +64,8 @@ zhist(Biobuf *b, int line, vlong offset)
Addr a; Addr a;
Bputc(b, AHISTORY); Bputc(b, AHISTORY);
Bputc(b, 0);
Bputc(b, 0);
Bputc(b, line); Bputc(b, line);
Bputc(b, line>>8); Bputc(b, line>>8);
Bputc(b, line>>16); Bputc(b, line>>16);
...@@ -82,19 +84,26 @@ zaddr(Biobuf *b, Addr *a, int s) ...@@ -82,19 +84,26 @@ zaddr(Biobuf *b, Addr *a, int s)
{ {
int32 l; int32 l;
Ieee e; Ieee e;
int i;
char *n;
// Bputc(b, a->type); switch(a->type) {
// TODO(kaib): Re-introduce registers once we figure out what they are used case D_STATIC:
// for. case D_EXTERN:
// Bputc(b, a->reg); case D_AUTO:
// Bputc(b, s); case D_PARAM:
// TODO(kaib): ditto for Addr.name Bputc(b, D_OREG);
// Bputc(b, a->name); Bputc(b, a->reg);
Bputc(b, s);
Bputc(b, a->type);
break;
default:
Bputc(b, a->type);
Bputc(b, a->reg);
Bputc(b, s);
Bputc(b, D_NONE);
}
Bputc(b, 1);
Bputc(b, 0);
Bputc(b, 0);
Bputc(b, 0);
switch(a->type) { switch(a->type) {
default: default:
print("unknown type %d in zaddr\n", a->type); print("unknown type %d in zaddr\n", a->type);
...@@ -107,10 +116,18 @@ zaddr(Biobuf *b, Addr *a, int s) ...@@ -107,10 +116,18 @@ zaddr(Biobuf *b, Addr *a, int s)
case D_PARAM: case D_PARAM:
break; break;
case D_CONST2:
l = a->offset2;
Bputc(b, l);
Bputc(b, l>>8);
Bputc(b, l>>16);
Bputc(b, l>>24); // fall through
case D_OREG: case D_OREG:
case D_CONST: case D_CONST:
case D_BRANCH: case D_BRANCH:
case D_SHIFT: case D_SHIFT:
case D_STATIC:
case D_AUTO:
l = a->offset; l = a->offset;
Bputc(b, l); Bputc(b, l);
Bputc(b, l>>8); Bputc(b, l>>8);
...@@ -118,27 +135,27 @@ zaddr(Biobuf *b, Addr *a, int s) ...@@ -118,27 +135,27 @@ zaddr(Biobuf *b, Addr *a, int s)
Bputc(b, l>>24); Bputc(b, l>>24);
break; break;
// case D_SCONST: case D_SCONST:
// n = a->sval; n = a->sval;
// for(i=0; i<NSNAME; i++) { for(i=0; i<NSNAME; i++) {
// Bputc(b, b, *n); Bputc(b, *n);
// n++; n++;
// } }
// break; break;
// case D_FCONST: case D_FCONST:
// ieeedtod(&e, a->dval); ieeedtod(&e, a->dval);
// l = e.l; l = e.l;
// Bputc(b, l); Bputc(b, l);
// Bputc(b, l>>8); Bputc(b, l>>8);
// Bputc(b, l>>16); Bputc(b, l>>16);
// Bputc(b, l>>24); Bputc(b, l>>24);
// l = e.h; l = e.h;
// Bputc(b, l); Bputc(b, l);
// Bputc(b, l>>8); Bputc(b, l>>8);
// Bputc(b, l>>16); Bputc(b, l>>16);
// Bputc(b, l>>24); Bputc(b, l>>24);
// break; break;
} }
} }
...@@ -228,6 +245,8 @@ dumpfuncs(void) ...@@ -228,6 +245,8 @@ dumpfuncs(void)
break; break;
} }
Bputc(bout, p->as); Bputc(bout, p->as);
Bputc(bout, p->scond);
Bputc(bout, p->reg);
Bputc(bout, p->lineno); Bputc(bout, p->lineno);
Bputc(bout, p->lineno>>8); Bputc(bout, p->lineno>>8);
Bputc(bout, p->lineno>>16); Bputc(bout, p->lineno>>16);
......
...@@ -190,129 +190,118 @@ afunclit(Addr *a) ...@@ -190,129 +190,118 @@ afunclit(Addr *a)
} }
} }
// TODO(kaib): probably not needed. /*
static int resvd[] = * allocate register of type t, leave in n.
{ * if o != N, o is desired fixed register.
// D_DI, // for movstring * caller must regfree(n).
// D_SI, // for movstring */
// D_AX, // for divide
// D_CX, // for shift
// D_DX, // for divide
// REGSP, // for stack
// D_R14, // reserved for m
// D_R15, // reserved for u
};
// TODO(kaib): As per rsc this is probably overcomplicated for arm
void void
ginit(void) regalloc(Node *n, Type *t, Node *o)
{ {
// int i; int i, et;
// for(i=0; i<nelem(reg); i++) if(t == T)
// reg[i] = 1; fatal("regalloc: t nil");
// for(i=D_AX; i<=D_R15; i++) et = simtype[t->etype];
// reg[i] = 0;
// for(i=D_X0; i<=D_X7; i++)
// reg[i] = 0;
// for(i=0; i<nelem(resvd); i++) switch(et) {
// reg[resvd[i]]++; case TINT8:
} case TUINT8:
case TINT16:
case TUINT16:
case TINT32:
case TUINT32:
case TINT64:
case TUINT64:
case TPTR32:
case TPTR64:
case TBOOL:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
if(i >= REGALLOC_R0 && i <= REGALLOC_RMAX)
goto out;
}
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
if(reg[i] == 0)
goto out;
void yyerror("out of fixed registers");
gclean(void) goto err;
{
// int i;
// for(i=0; i<nelem(resvd); i++) case TFLOAT32:
// reg[resvd[i]]--; case TFLOAT64:
case TFLOAT80:
if(o != N && o->op == OREGISTER) {
i = o->val.u.reg;
if(i >= REGALLOC_F0 && i <= REGALLOC_FMAX)
goto out;
}
for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
if(reg[i] == 0)
goto out;
yyerror("out of floating registers");
goto err;
}
yyerror("regalloc: unknown type %T", t);
// for(i=D_AX; i<=D_R15; i++) err:
// if(reg[i]) nodreg(n, t, 0);
// yyerror("reg %R left allocated\n", i); return;
// for(i=D_X0; i<=D_X7; i++)
// if(reg[i]) out:
// yyerror("reg %R left allocated\n", i); reg[i]++;
nodreg(n, t, i);
} }
/*
* allocate register of type t, leave in n.
* if o != N, o is desired fixed register.
* caller must regfree(n).
*/
void void
regalloc(Node *n, Type *t, Node *o) regfree(Node *n)
{ {
// int i, et; int i;
// if(t == T) if(n->op != OREGISTER && n->op != OINDREG)
// fatal("regalloc: t nil"); fatal("regfree: not a register");
// et = simtype[t->etype]; i = n->val.u.reg;
if(i < 0 || i >= sizeof(reg))
fatal("regfree: reg out of range");
if(reg[i] <= 0)
fatal("regfree: reg not allocated");
reg[i]--;
}
// switch(et) { void
// case TINT8: tempalloc(Node *n, Type *t)
// case TUINT8: {
// case TINT16: int w;
// case TUINT16:
// case TINT32:
// case TUINT32:
// case TINT64:
// case TUINT64:
// case TPTR32:
// case TPTR64:
// case TBOOL:
// if(o != N && o->op == OREGISTER) {
// i = o->val.u.reg;
// if(i >= D_AX && i <= D_R15)
// goto out;
// }
// for(i=D_AX; i<=D_R15; i++)
// if(reg[i] == 0)
// goto out;
// yyerror("out of fixed registers");
// goto err;
// case TFLOAT32:
// case TFLOAT64:
// case TFLOAT80:
// if(o != N && o->op == OREGISTER) {
// i = o->val.u.reg;
// if(i >= D_X0 && i <= D_X7)
// goto out;
// }
// for(i=D_X0; i<=D_X7; i++)
// if(reg[i] == 0)
// goto out;
// yyerror("out of floating registers");
// goto err;
// }
// yyerror("regalloc: unknown type %T", t);
// err: dowidth(t);
// nodreg(n, t, 0);
// return;
// out: memset(n, 0, sizeof(*n));
// reg[i]++; n->op = ONAME;
// nodreg(n, t, i); n->sym = S;
n->type = t;
n->etype = t->etype;
n->class = PAUTO;
n->addable = 1;
n->ullman = 1;
n->noescape = 1;
n->ostk = stksize;
w = t->width;
stksize += w;
stksize = rnd(stksize, w);
n->xoffset = -stksize;
//print("tempalloc %d -> %d from %p\n", n->ostk, n->xoffset, __builtin_return_address(0));
if(stksize > maxstksize)
maxstksize = stksize;
} }
void void
regfree(Node *n) tempfree(Node *n)
{ {
// int i; //print("tempfree %d\n", n->xoffset);
if(n->xoffset != -stksize)
// if(n->op != OREGISTER && n->op != OINDREG) fatal("tempfree %lld %d", -n->xoffset, stksize);
// fatal("regfree: not a register"); stksize = n->ostk;
// i = n->val.u.reg;
// if(i < 0 || i >= sizeof(reg))
// fatal("regfree: reg out of range");
// if(reg[i] <= 0)
// fatal("regfree: reg not allocated");
// reg[i]--;
} }
/* /*
...@@ -410,575 +399,563 @@ gconreg(int as, vlong c, int reg) ...@@ -410,575 +399,563 @@ gconreg(int as, vlong c, int reg)
gins(as, &n1, &n2); gins(as, &n1, &n2);
} }
#define CASE(a,b) (((a)<<16)|((b)<<0))
/* /*
* generate move: * Is this node a memory operand?
* t = f
*/ */
// TODO(kaib): Crib the new gmove from 8g int
void ismem(Node *n)
gmove(Node *f, Node *t)
{ {
int ft, tt, t64, a; switch(n->op) {
Node nod, nod1, nod2, nod3, nodc; case OINDREG:
Prog *p1, *p2; case ONAME:
case OPARAM:
return 1;
}
return 0;
}
ft = simtype[f->type->etype]; #define CASE(a,b) (((a)<<16)|((b)<<0))
tt = simtype[t->type->etype];
t64 = 0; void
if(tt == TINT64 || tt == TUINT64 || tt == TPTR64) gmove(Node *f, Node *t)
t64 = 1; {
int a, ft, tt;
Type *cvt;
Node r1, r2, t1, t2, flo, fhi, tlo, thi, con, f0, f1, ax, dx, cx;
Prog *p1, *p2, *p3;
if(debug['M']) if(debug['M'])
print("gop: %O %O[%E],%O[%E]\n", OAS, print("gmove %N -> %N\n", f, t);
f->op, ft, t->op, tt);
/* ft = simsimtype(f->type);
* load tt = simsimtype(t->type);
*/ cvt = t->type;
if(f->op == ONAME || f->op == OINDREG ||
f->op == OIND || f->op == OINDEX) // cannot have two integer memory operands;
fatal("gmove load not implemented"); // except 64-bit, which always copies via registers anyway.
// switch(ft) { // TODO(kaib): re-enable check
// case TINT8: // if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
// a = AMOVBLSX; // goto hard;
// if(t64)
// a = AMOVBQSX; // convert constant to desired type
// goto ld; if(f->op == OLITERAL) {
// case TBOOL: if(tt == TFLOAT32)
// case TUINT8: convconst(&con, types[TFLOAT64], &f->val);
// a = AMOVBLZX; else
// if(t64) convconst(&con, t->type, &f->val);
// a = AMOVBQZX; f = &con;
// goto ld; ft = simsimtype(con.type);
// case TINT16:
// a = AMOVWLSX; // some constants can't move directly to memory.
// if(t64) if(ismem(t)) {
// a = AMOVWQSX; // float constants come from memory.
// goto ld; if(isfloat[tt])
// case TUINT16: goto hard;
// a = AMOVWLZX; }
// if(t64) }
// a = AMOVWQZX;
// goto ld;
// case TINT32:
// if(isfloat[tt]) {
// regalloc(&nod, t->type, t);
// if(tt == TFLOAT64)
// a = ACVTSL2SD;
// else
// a = ACVTSL2SS;
// gins(a, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// }
// a = AMOVL;
// if(t64)
// a = AMOVLQSX;
// goto ld;
// case TUINT32:
// case TPTR32:
// a = AMOVL;
// if(t64)
// a = AMOVLQZX;
// goto ld;
// case TINT64:
// if(isfloat[tt]) {
// regalloc(&nod, t->type, t);
// if(tt == TFLOAT64)
// a = ACVTSQ2SD;
// else
// a = ACVTSQ2SS;
// gins(a, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// }
// case TUINT64:
// case TPTR64:
// a = AMOVQ;
// ld: // value -> value copy, only one memory operand.
// regalloc(&nod, f->type, t); // figure out the instruction to use.
// nod.type = t64? types[TINT64]: types[TINT32]; // break out of switch for one-instruction gins.
// gins(a, f, &nod); // goto rdst for "destination must be register".
// gmove(&nod, t); // goto hard for "convert to cvt type first".
// regfree(&nod); // otherwise handle and return.
// return;
// case TFLOAT32: switch(CASE(ft, tt)) {
// a = AMOVSS; default:
// goto fld; goto fatal;
// case TFLOAT64:
// a = AMOVSD;
// fld:
// regalloc(&nod, f->type, t);
// if(tt != TFLOAT64 && tt != TFLOAT32){ /* TO DO: why is this here */
// dump("odd tree", f);
// nod.type = t64? types[TINT64]: types[TINT32];
// }
// gins(a, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// }
/* /*
* store * integer copy and truncate
*/ */
if(t->op == ONAME || t->op == OINDREG || case CASE(TINT8, TINT8): // same size
t->op == OIND || t->op == OINDEX) case CASE(TINT8, TUINT8):
case CASE(TUINT8, TINT8):
switch(tt) { case CASE(TUINT8, TUINT8):
case TBOOL: case CASE(TINT16, TINT8): // truncate
case TINT8: case CASE(TUINT16, TINT8):
case TUINT8: case CASE(TINT32, TINT8):
case CASE(TUINT32, TINT8):
case CASE(TINT16, TUINT8):
case CASE(TUINT16, TUINT8):
case CASE(TINT32, TUINT8):
case CASE(TUINT32, TUINT8):
a = AMOVB; a = AMOVB;
goto st;
case TINT16:
case TUINT16:
a = AMOVH;
goto st;
case TINT32:
case TUINT32:
a = AMOVW;
goto st;
case TINT64:
case TUINT64:
fatal("gmove TINT64 and TUINT64 not implemented");
// a = AMOVQ;
goto st;
case TPTR64:
fatal("gmove TPTR64 not implemented");
break; break;
case TPTR32: case CASE(TINT64, TINT8): // truncate low word
/* case CASE(TUINT64, TINT8):
* store to pointer. case CASE(TINT64, TUINT8):
*/ case CASE(TUINT64, TUINT8):
a = AMOVW; fatal("gmove INT64,INT8 not implemented");
switch(t->op) { // split64(f, &flo, &fhi);
default: // nodreg(&r1, t->type, D_AX);
dump("gmove to", t); // gins(AMOVB, &flo, &r1);
fatal("gmove t %O", t->op); // gins(AMOVB, &r1, t);
// splitclean();
return;
case OINDREG: case CASE(TINT16, TINT16): // same size
if(t->val.u.reg != REGSP) case CASE(TINT16, TUINT16):
goto refcount; case CASE(TUINT16, TINT16):
case CASE(TUINT16, TUINT16):
case CASE(TINT32, TINT16): // truncate
case CASE(TUINT32, TINT16):
case CASE(TINT32, TUINT16):
case CASE(TUINT32, TUINT16):
a = AMOVH;
break; break;
case ONAME: case CASE(TINT64, TINT16): // truncate low word
switch(t->class) { case CASE(TUINT64, TINT16):
default: case CASE(TINT64, TUINT16):
dump("gmove", t); case CASE(TUINT64, TUINT16):
fatal("gmove t %O class %d reg %R", t->op, t->class, t->val.u.reg); fatal("gmove INT64,INT16 not implemented");
case PEXTERN: // split64(f, &flo, &fhi);
goto refcount; // nodreg(&r1, t->type, D_AX);
break; // gins(AMOVW, &flo, &r1);
case PAUTO: // gins(AMOVW, &r1, t);
case PPARAM: // splitclean();
case PPARAMOUT: return;
break;
} case CASE(TINT32, TINT32): // same size
case CASE(TINT32, TUINT32):
case CASE(TUINT32, TINT32):
case CASE(TUINT32, TUINT32):
a = AMOVW;
break; break;
}
goto st;
st: case CASE(TINT64, TINT32): // truncate
// 64-bit immediates only allowed for move into registers. case CASE(TUINT64, TINT32):
// this is not a move into a register. case CASE(TINT64, TUINT32):
if(f->op == OLITERAL && !t64) { case CASE(TUINT64, TUINT32):
gins(a, f, t); fatal("gmove INT64,INT32 not implemented");
return; // split64(f, &flo, &fhi);
} // nodreg(&r1, t->type, D_AX);
fst: // gins(AMOVL, &flo, &r1);
regalloc(&nod, t->type, f); // gins(AMOVL, &r1, t);
gmove(f, &nod); // splitclean();
gins(a, &nod, t);
regfree(&nod);
return; return;
refcount: case CASE(TINT64, TINT64): // same size
fatal("gmove refcount not implemented"); case CASE(TINT64, TUINT64):
// if(!debug['r']) case CASE(TUINT64, TINT64):
// goto st; case CASE(TUINT64, TUINT64):
// // for now, mark ref count updates with AXCHGQ. fatal("gmove INT64,INT64 not implemented");
// // using a temporary on the left, so no semantic // split64(f, &flo, &fhi);
// // changes. code is likely slower, but still correct. // split64(t, &tlo, &thi);
// if(t64) // if(f->op == OLITERAL) {
// a = AXCHGQ; // gins(AMOVL, &flo, &tlo);
// else // gins(AMOVL, &fhi, &thi);
// a = AXCHGL; // } else {
// regalloc(&nod, t->type, f); // nodreg(&r1, t->type, D_AX);
// gmove(f, &nod); // nodreg(&r2, t->type, D_DX);
// gins(a, &nod, t); // gins(AMOVL, &flo, &r1);
// regfree(&nod); // gins(AMOVL, &fhi, &r2);
// gins(AMOVL, &r1, &tlo);
// gins(AMOVL, &r2, &thi);
// }
// splitclean();
// splitclean();
return; return;
case TFLOAT32: /*
a = AMOVW; * integer up-conversions
goto fst;
case TFLOAT64:
fatal("gmove TFLOAT64 not implemented");
// a = AMOVSD;
goto fst;
}
/*
* convert
*/ */
fatal("gmove convert not implemented"); // case CASE(TINT8, TINT16): // sign extend int8
// switch(CASE(ft, tt)) {
// default:
/*
* integer to integer
********
* a = AGOK; break;
* case CASE(TBOOL, TBOOL):
* case CASE(TINT8, TBOOL):
* case CASE(TUINT8, TBOOL):
* case CASE(TINT16, TBOOL):
* case CASE(TUINT16, TBOOL):
* case CASE(TINT32, TBOOL):
* case CASE(TUINT32, TBOOL):
* case CASE(TPTR64, TBOOL):
* case CASE(TBOOL, TINT8):
* case CASE(TINT8, TINT8):
* case CASE(TUINT8, TINT8):
* case CASE(TINT16, TINT8):
* case CASE(TUINT16, TINT8):
* case CASE(TINT32, TINT8):
* case CASE(TUINT32, TINT8):
* case CASE(TPTR64, TINT8):
* case CASE(TBOOL, TUINT8):
* case CASE(TINT8, TUINT8):
* case CASE(TUINT8, TUINT8):
* case CASE(TINT16, TUINT8):
* case CASE(TUINT16, TUINT8):
* case CASE(TINT32, TUINT8):
* case CASE(TUINT32, TUINT8):
* case CASE(TPTR64, TUINT8):
* case CASE(TINT16, TINT16):
* case CASE(TUINT16, TINT16):
* case CASE(TINT32, TINT16):
* case CASE(TUINT32, TINT16):
* case CASE(TPTR64, TINT16):
* case CASE(TINT16, TUINT16):
* case CASE(TUINT16, TUINT16):
* case CASE(TINT32, TUINT16):
* case CASE(TUINT32, TUINT16):
* case CASE(TPTR64, TUINT16):
* case CASE(TINT64, TUINT):
* case CASE(TINT64, TUINT32):
* case CASE(TUINT64, TUINT32):
*****/
// a = AMOVL;
// break;
// case CASE(TINT64, TINT8):
// case CASE(TINT64, TINT16):
// case CASE(TINT64, TINT32):
// case CASE(TUINT64, TINT8):
// case CASE(TUINT64, TINT16):
// case CASE(TUINT64, TINT32):
// a = AMOVLQSX; // this looks bad
// break;
// case CASE(TINT32, TINT64):
// case CASE(TINT32, TPTR64):
// a = AMOVLQSX;
// break;
// case CASE(TUINT32, TINT64):
// case CASE(TUINT32, TUINT64):
// case CASE(TUINT32, TPTR64):
// case CASE(TPTR32, TINT64):
// case CASE(TPTR32, TUINT64):
// case CASE(TPTR32, TPTR64):
// a = AMOVLQZX;
// break;
// case CASE(TPTR64, TINT64):
// case CASE(TINT64, TINT64):
// case CASE(TUINT64, TINT64):
// case CASE(TINT64, TUINT64):
// case CASE(TUINT64, TUINT64):
// case CASE(TPTR64, TUINT64):
// case CASE(TINT64, TPTR64):
// case CASE(TUINT64, TPTR64):
// case CASE(TPTR64, TPTR64):
// a = AMOVQ;
// break;
// case CASE(TINT16, TINT32):
// case CASE(TINT16, TUINT32):
// a = AMOVWLSX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xffff;
// // if(f->val.vval & 0x8000)
// // f->val.vval |= 0xffff0000;
// // a = AMOVL;
// // }
// break;
// case CASE(TINT16, TINT64):
// case CASE(TINT16, TUINT64):
// case CASE(TINT16, TPTR64):
// a = AMOVWQSX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xffff;
// // if(f->val.vval & 0x8000){
// // f->val.vval |= 0xffff0000;
// // f->val.vval |= (vlong)~0 << 32;
// // }
// // a = AMOVL;
// // }
// break;
// case CASE(TUINT16, TINT32):
// case CASE(TUINT16, TUINT32):
// a = AMOVWLZX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xffff;
// // a = AMOVL;
// // }
// break;
// case CASE(TUINT16, TINT64):
// case CASE(TUINT16, TUINT64):
// case CASE(TUINT16, TPTR64):
// a = AMOVWQZX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xffff;
// // a = AMOVL; /* MOVL also zero-extends to 64 bits */
// // }
// break;
// case CASE(TINT8, TINT16):
// case CASE(TINT8, TUINT16): // case CASE(TINT8, TUINT16):
// a = AMOVBWSX;
// goto rdst;
// case CASE(TINT8, TINT32): // case CASE(TINT8, TINT32):
// case CASE(TINT8, TUINT32): // case CASE(TINT8, TUINT32):
// a = AMOVBLSX; // a = AMOVBLSX;
// // if(f->op == OCONST) { // goto rdst;
// // f->val.vval &= 0xff; // case CASE(TINT8, TINT64): // convert via int32
// // if(f->val.vval & 0x80)
// // f->val.vval |= 0xffffff00;
// // a = AMOVL;
// // }
// break;
// case CASE(TINT8, TINT64):
// case CASE(TINT8, TUINT64): // case CASE(TINT8, TUINT64):
// case CASE(TINT8, TPTR64): // cvt = types[TINT32];
// a = AMOVBQSX; // goto hard;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xff;
// // if(f->val.vval & 0x80){
// // f->val.vval |= 0xffffff00;
// // f->val.vval |= (vlong)~0 << 32;
// // }
// // a = AMOVQ;
// // }
// break;
// case CASE(TBOOL, TINT16): // case CASE(TUINT8, TINT16): // zero extend uint8
// case CASE(TBOOL, TUINT16):
// case CASE(TBOOL, TINT32):
// case CASE(TBOOL, TUINT32):
// case CASE(TUINT8, TINT16):
// case CASE(TUINT8, TUINT16): // case CASE(TUINT8, TUINT16):
// a = AMOVBWZX;
// goto rdst;
// case CASE(TUINT8, TINT32): // case CASE(TUINT8, TINT32):
// case CASE(TUINT8, TUINT32): // case CASE(TUINT8, TUINT32):
// a = AMOVBLZX; // a = AMOVBLZX;
// // if(f->op == OCONST) { // goto rdst;
// // f->val.vval &= 0xff; // case CASE(TUINT8, TINT64): // convert via uint32
// // a = AMOVL;
// // }
// break;
// case CASE(TBOOL, TINT64):
// case CASE(TBOOL, TUINT64):
// case CASE(TBOOL, TPTR64):
// case CASE(TUINT8, TINT64):
// case CASE(TUINT8, TUINT64): // case CASE(TUINT8, TUINT64):
// case CASE(TUINT8, TPTR64): // cvt = types[TUINT32];
// a = AMOVBQZX; // goto hard;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xff; // case CASE(TINT16, TINT32): // sign extend int16
// // a = AMOVL; /* zero-extends to 64-bits */ // case CASE(TINT16, TUINT32):
// // } // a = AMOVWLSX;
// break; // goto rdst;
// case CASE(TINT16, TINT64): // convert via int32
// case CASE(TINT16, TUINT64):
// cvt = types[TINT32];
// goto hard;
// case CASE(TUINT16, TINT32): // zero extend uint16
// case CASE(TUINT16, TUINT32):
// a = AMOVWLZX;
// goto rdst;
// case CASE(TUINT16, TINT64): // convert via uint32
// case CASE(TUINT16, TUINT64):
// cvt = types[TUINT32];
// goto hard;
// case CASE(TINT32, TINT64): // sign extend int32
// case CASE(TINT32, TUINT64):
// fatal("gmove TINT32,INT64 not implemented");
// // split64(t, &tlo, &thi);
// // nodreg(&flo, tlo.type, D_AX);
// // nodreg(&fhi, thi.type, D_DX);
// // gmove(f, &flo);
// // gins(ACDQ, N, N);
// // gins(AMOVL, &flo, &tlo);
// // gins(AMOVL, &fhi, &thi);
// // splitclean();
// return;
// case CASE(TUINT32, TINT64): // zero extend uint32
// case CASE(TUINT32, TUINT64):
// fatal("gmove TUINT32,INT64 not implemented");
// // split64(t, &tlo, &thi);
// // gmove(f, &tlo);
// // gins(AMOVL, ncon(0), &thi);
// // splitclean();
// return;
// /* // /*
// * float to fix // * float to integer
// */ // */
// case CASE(TFLOAT32, TINT8):
// case CASE(TFLOAT32, TINT16): // case CASE(TFLOAT32, TINT16):
// case CASE(TFLOAT32, TINT32): // case CASE(TFLOAT32, TINT32):
// regalloc(&nod, t->type, N);
// gins(ACVTTSS2SL, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TFLOAT32, TBOOL):
// case CASE(TFLOAT32, TUINT8):
// case CASE(TFLOAT32, TUINT16):
// case CASE(TFLOAT32, TUINT32):
// case CASE(TFLOAT32, TINT64): // case CASE(TFLOAT32, TINT64):
// case CASE(TFLOAT32, TUINT64):
// case CASE(TFLOAT32, TPTR64):
// regalloc(&nod, t->type, N);
// gins(ACVTTSS2SQ, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TFLOAT64, TINT8):
// case CASE(TFLOAT64, TINT16): // case CASE(TFLOAT64, TINT16):
// case CASE(TFLOAT64, TINT32): // case CASE(TFLOAT64, TINT32):
// regalloc(&nod, t->type, N); // case CASE(TFLOAT64, TINT64):
// gins(ACVTTSD2SL, f, &nod); // if(t->op == OREGISTER)
// gmove(&nod, t); // goto hardmem;
// regfree(&nod); // nodreg(&r1, types[ft], D_F0);
// if(ft == TFLOAT32)
// gins(AFMOVF, f, &r1);
// else
// gins(AFMOVD, f, &r1);
// // set round to zero mode during conversion
// tempalloc(&t1, types[TUINT16]);
// tempalloc(&t2, types[TUINT16]);
// gins(AFSTCW, N, &t1);
// gins(AMOVW, ncon(0xf7f), &t2);
// gins(AFLDCW, &t2, N);
// if(tt == TINT16)
// gins(AFMOVWP, &r1, t);
// else if(tt == TINT32)
// gins(AFMOVLP, &r1, t);
// else
// gins(AFMOVVP, &r1, t);
// gins(AFLDCW, &t1, N);
// tempfree(&t2);
// tempfree(&t1);
// return; // return;
// case CASE(TFLOAT64, TBOOL): // case CASE(TFLOAT32, TINT8):
// case CASE(TFLOAT64, TUINT8): // case CASE(TFLOAT32, TUINT16):
// case CASE(TFLOAT32, TUINT8):
// case CASE(TFLOAT64, TINT8):
// case CASE(TFLOAT64, TUINT16): // case CASE(TFLOAT64, TUINT16):
// case CASE(TFLOAT64, TUINT8):
// // convert via int32.
// tempalloc(&t1, types[TINT32]);
// gmove(f, &t1);
// switch(tt) {
// default:
// fatal("gmove %T", t);
// case TINT8:
// gins(ACMPL, &t1, ncon(-0x80));
// p1 = gbranch(optoas(OLT, types[TINT32]), T);
// gins(ACMPL, &t1, ncon(0x7f));
// p2 = gbranch(optoas(OGT, types[TINT32]), T);
// p3 = gbranch(AJMP, T);
// patch(p1, pc);
// patch(p2, pc);
// gmove(ncon(-0x80), &t1);
// patch(p3, pc);
// gmove(&t1, t);
// break;
// case TUINT8:
// gins(ATESTL, ncon(0xffffff00), &t1);
// p1 = gbranch(AJEQ, T);
// gins(AMOVB, ncon(0), &t1);
// patch(p1, pc);
// gmove(&t1, t);
// break;
// case TUINT16:
// gins(ATESTL, ncon(0xffff0000), &t1);
// p1 = gbranch(AJEQ, T);
// gins(AMOVW, ncon(0), &t1);
// patch(p1, pc);
// gmove(&t1, t);
// break;
// }
// tempfree(&t1);
// return;
// case CASE(TFLOAT32, TUINT32):
// case CASE(TFLOAT64, TUINT32): // case CASE(TFLOAT64, TUINT32):
// case CASE(TFLOAT64, TINT64): // // convert via int64.
// case CASE(TFLOAT64, TUINT64): // tempalloc(&t1, types[TINT64]);
// case CASE(TFLOAT64, TPTR64): // gmove(f, &t1);
// regalloc(&nod, t->type, N); // split64(&t1, &tlo, &thi);
// gins(ACVTTSD2SQ, f, &nod); // gins(ACMPL, &thi, ncon(0));
// gmove(&nod, t); // p1 = gbranch(AJEQ, T);
// regfree(&nod); // gins(AMOVL, ncon(0), &tlo);
// patch(p1, pc);
// gmove(&tlo, t);
// splitclean();
// tempfree(&t1);
// return; // return;
// /* // case CASE(TFLOAT32, TUINT64):
// * uvlong to float // case CASE(TFLOAT64, TUINT64):
// */ // bignodes();
// case CASE(TUINT64, TFLOAT64): // nodreg(&f0, types[ft], D_F0);
// case CASE(TUINT64, TFLOAT32): // nodreg(&f1, types[ft], D_F0 + 1);
// a = ACVTSQ2SS; // nodreg(&ax, types[TUINT16], D_AX);
// if(tt == TFLOAT64)
// a = ACVTSQ2SD; // gmove(f, &f0);
// regalloc(&nod, f->type, f);
// gmove(f, &nod); // // if 0 > v { answer = 0 }
// regalloc(&nod1, t->type, t); // gmove(&zerof, &f0);
// nodconst(&nodc, types[TUINT64], 0); // gins(AFUCOMP, &f0, &f1);
// gins(ACMPQ, &nod, &nodc); // gins(AFSTSW, N, &ax);
// p1 = gbranch(AJLT, T); // gins(ASAHF, N, N);
// gins(a, &nod, &nod1); // p1 = gbranch(optoas(OGT, types[tt]), T);
// p2 = gbranch(AJMP, T); // // if 1<<64 <= v { answer = 0 too }
// gmove(&two64f, &f0);
// gins(AFUCOMP, &f0, &f1);
// gins(AFSTSW, N, &ax);
// gins(ASAHF, N, N);
// p2 = gbranch(optoas(OGT, types[tt]), T);
// patch(p1, pc); // patch(p1, pc);
// regalloc(&nod2, f->type, N); // gins(AFMOVVP, &f0, t); // don't care about t, but will pop the stack
// regalloc(&nod3, f->type, N); // split64(t, &tlo, &thi);
// gmove(&nod, &nod2); // gins(AMOVL, ncon(0), &tlo);
// nodconst(&nodc, types[TUINT64], 1); // gins(AMOVL, ncon(0), &thi);
// gins(ASHRQ, &nodc, &nod2); // splitclean();
// gmove(&nod, &nod3); // p1 = gbranch(AJMP, T);
// gins(AANDL, &nodc, &nod3);
// gins(AORQ, &nod3, &nod2);
// gins(a, &nod2, &nod1);
// gins(tt == TFLOAT64? AADDSD: AADDSS, &nod1, &nod1);
// regfree(&nod2);
// regfree(&nod3);
// patch(p2, pc); // patch(p2, pc);
// regfree(&nod);
// regfree(&nod1);
// return;
// case CASE(TUINT32, TFLOAT64): // // in range; algorithm is:
// case CASE(TUINT32, TFLOAT32): // // if small enough, use native float64 -> int64 conversion.
// a = ACVTSQ2SS; // // otherwise, subtract 2^63, convert, and add it back.
// if(tt == TFLOAT64)
// a = ACVTSQ2SD; // // set round to zero mode during conversion
// regalloc(&nod, f->type, f); // tempalloc(&t1, types[TUINT16]);
// gins(AMOVLQZX, f, &nod); // tempalloc(&t2, types[TUINT16]);
// regalloc(&nod1, t->type, t); // gins(AFSTCW, N, &t1);
// gins(a, &nod, &nod1); // gins(AMOVW, ncon(0xf7f), &t2);
// gmove(&nod1, t); // gins(AFLDCW, &t2, N);
// regfree(&nod); // tempfree(&t2);
// regfree(&nod1);
// // actual work
// gmove(&two63f, &f0);
// gins(AFUCOMP, &f0, &f1);
// gins(AFSTSW, N, &ax);
// gins(ASAHF, N, N);
// p2 = gbranch(optoas(OLE, types[tt]), T);
// gins(AFMOVVP, &f0, t);
// p3 = gbranch(AJMP, T);
// patch(p2, pc);
// gmove(&two63f, &f0);
// gins(AFSUBDP, &f0, &f1);
// gins(AFMOVVP, &f0, t);
// split64(t, &tlo, &thi);
// gins(AXORL, ncon(0x80000000), &thi); // + 2^63
// patch(p3, pc);
// patch(p1, pc);
// splitclean();
// // restore rounding mode
// gins(AFLDCW, &t1, N);
// tempfree(&t1);
// return; // return;
// /* // /*
// * fix to float // * integer to float
// */ // */
// case CASE(TINT16, TFLOAT32):
// case CASE(TINT16, TFLOAT64):
// case CASE(TINT32, TFLOAT32):
// case CASE(TINT32, TFLOAT64):
// case CASE(TINT64, TFLOAT32): // case CASE(TINT64, TFLOAT32):
// case CASE(TPTR64, TFLOAT32):
// regalloc(&nod, t->type, t);
// gins(ACVTSQ2SS, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TINT64, TFLOAT64): // case CASE(TINT64, TFLOAT64):
// case CASE(TPTR64, TFLOAT64): // fatal("gmove TINT,TFLOAT not implemented");
// regalloc(&nod, t->type, t); // // if(t->op != OREGISTER)
// gins(ACVTSQ2SD, f, &nod); // // goto hard;
// gmove(&nod, t); // // if(f->op == OREGISTER) {
// regfree(&nod); // // cvt = f->type;
// return; // // goto hardmem;
// // }
// // switch(ft) {
// // case TINT16:
// // a = AFMOVW;
// // break;
// // case TINT32:
// // a = AFMOVL;
// // break;
// // default:
// // a = AFMOVV;
// // break;
// // }
// break;
// case CASE(TBOOL, TFLOAT32):
// case CASE(TINT8, TFLOAT32): // case CASE(TINT8, TFLOAT32):
// case CASE(TUINT8, TFLOAT32):
// case CASE(TINT16, TFLOAT32):
// case CASE(TUINT16, TFLOAT32):
// case CASE(TINT32, TFLOAT32):
// regalloc(&nod, t->type, t);
// gins(ACVTSL2SS, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TBOOL, TFLOAT64):
// case CASE(TINT8, TFLOAT64): // case CASE(TINT8, TFLOAT64):
// case CASE(TUINT8, TFLOAT64): // case CASE(TUINT16, TFLOAT32):
// case CASE(TINT16, TFLOAT64):
// case CASE(TUINT16, TFLOAT64): // case CASE(TUINT16, TFLOAT64):
// case CASE(TINT32, TFLOAT64): // case CASE(TUINT8, TFLOAT32):
// regalloc(&nod, t->type, t); // case CASE(TUINT8, TFLOAT64):
// gins(ACVTSL2SD, f, &nod); // // convert via int32 memory
// gmove(&nod, t); // cvt = types[TINT32];
// regfree(&nod); // goto hardmem;
// case CASE(TUINT32, TFLOAT32):
// case CASE(TUINT32, TFLOAT64):
// // convert via int64 memory
// cvt = types[TINT64];
// goto hardmem;
// case CASE(TUINT64, TFLOAT32):
// case CASE(TUINT64, TFLOAT64):
// // algorithm is:
// // if small enough, use native int64 -> uint64 conversion.
// // otherwise, halve (rounding to odd?), convert, and double.
// nodreg(&ax, types[TUINT32], D_AX);
// nodreg(&dx, types[TUINT32], D_DX);
// nodreg(&cx, types[TUINT32], D_CX);
// tempalloc(&t1, f->type);
// split64(&t1, &tlo, &thi);
// gmove(f, &t1);
// gins(ACMPL, &thi, ncon(0));
// p1 = gbranch(AJLT, T);
// // native
// t1.type = types[TINT64];
// gmove(&t1, t);
// p2 = gbranch(AJMP, T);
// // simulated
// patch(p1, pc);
// gmove(&tlo, &ax);
// gmove(&thi, &dx);
// p1 = gins(ASHRL, ncon(1), &ax);
// p1->from.index = D_DX; // double-width shift DX -> AX
// p1->from.scale = 0;
// gins(ASETCC, N, &cx);
// gins(AORB, &cx, &ax);
// gins(ASHRL, ncon(1), &dx);
// gmove(&dx, &thi);
// gmove(&ax, &tlo);
// nodreg(&r1, types[tt], D_F0);
// nodreg(&r2, types[tt], D_F0 + 1);
// gmove(&t1, &r1); // t1.type is TINT64 now, set above
// gins(AFMOVD, &r1, &r1);
// gins(AFADDDP, &r1, &r2);
// gmove(&r1, t);
// patch(p2, pc);
// splitclean();
// tempfree(&t1);
// return; // return;
// /* // /*
// * float to float // * float to float
// */ // */
// case CASE(TFLOAT32, TFLOAT32): // case CASE(TFLOAT32, TFLOAT32):
// a = AMOVSS;
// break;
// case CASE(TFLOAT64, TFLOAT32):
// a = ACVTSD2SS;
// break;
// case CASE(TFLOAT32, TFLOAT64):
// a = ACVTSS2SD;
// break;
// case CASE(TFLOAT64, TFLOAT64): // case CASE(TFLOAT64, TFLOAT64):
// a = AMOVSD; // // The way the code generator uses floating-point
// // registers, a move from F0 to F0 is intended as a no-op.
// // On the x86, it's not: it pushes a second copy of F0
// // on the floating point stack. So toss it away here.
// // Also, F0 is the *only* register we ever evaluate
// // into, so we should only see register/register as F0/F0.
// if(f->op == OREGISTER && t->op == OREGISTER) {
// if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
// goto fatal;
// return;
// }
// if(ismem(f) && ismem(t))
// goto hard;
// a = AFMOVF;
// if(ft == TFLOAT64)
// a = AFMOVD;
// if(ismem(t)) {
// if(f->op != OREGISTER || f->val.u.reg != D_F0)
// fatal("gmove %N", f);
// a = AFMOVFP;
// if(ft == TFLOAT64)
// a = AFMOVDP;
// }
// break; // break;
// case CASE(TFLOAT32, TFLOAT64):
// if(f->op == OREGISTER && t->op == OREGISTER) {
// if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
// goto fatal;
// return;
// } // }
// if(a == AMOVQ || // if(f->op == OREGISTER)
// a == AMOVSD || // gins(AFMOVDP, f, t);
// a == AMOVSS || // else
// (a == AMOVL && f->type->width == t->type->width)) /* TO DO: check AMOVL */ // gins(AFMOVF, f, t);
// if(samaddr(f, t))
// return; // return;
// case CASE(TFLOAT64, TFLOAT32):
// if(f->op == OREGISTER && t->op == OREGISTER) {
// tempalloc(&r1, types[TFLOAT32]);
// gins(AFMOVFP, f, &r1);
// gins(AFMOVF, &r1, t);
// tempfree(&r1);
// return;
// }
// if(f->op == OREGISTER)
// gins(AFMOVFP, f, t);
// else
// gins(AFMOVD, f, t);
// return;
}
gins(a, f, t); gins(a, f, t);
return;
rdst:
// requires register destination
regalloc(&r1, t->type, t);
gins(a, f, &r1);
gmove(&r1, t);
regfree(&r1);
return;
hard:
// requires register intermediate
regalloc(&r1, cvt, t);
gmove(f, &r1);
gmove(&r1, t);
regfree(&r1);
return;
hardmem:
// requires memory intermediate
tempalloc(&r1, cvt);
gmove(f, &r1);
gmove(&r1, t);
tempfree(&r1);
return;
fatal:
// should not happen
fatal("gmove %N -> %N", f, t);
} }
int int
...@@ -1053,13 +1030,17 @@ naddr(Node *n, Addr *a) ...@@ -1053,13 +1030,17 @@ naddr(Node *n, Addr *a)
fatal("naddr: bad %O %D", n->op, a); fatal("naddr: bad %O %D", n->op, a);
break; break;
// case OREGISTER: case OREGISTER:
// a->type = n->val.u.reg; a->type = D_OREG;
// a->sym = S; if (n->val.u.reg <= REGALLOC_RMAX)
// break; a->reg = n->val.u.reg;
else
a->reg = n->val.u.reg - REGALLOC_F0;
a->sym = S;
break;
// case OINDEX: case OINDEX:
// case OIND: case OIND:
// naddr(n->left, a); // naddr(n->left, a);
// if(a->type >= D_AX && a->type <= D_DI) // if(a->type >= D_AX && a->type <= D_DI)
// a->type += D_INDIR; // a->type += D_INDIR;
...@@ -1376,21 +1357,15 @@ optoas(int op, Type *t) ...@@ -1376,21 +1357,15 @@ optoas(int op, Type *t)
// a = AMOVSD; // a = AMOVSD;
// break; // break;
// case CASE(OADD, TINT8): case CASE(OADD, TINT8):
// case CASE(OADD, TUINT8): case CASE(OADD, TUINT8):
// a = AADDB; case CASE(OADD, TINT16):
// break; case CASE(OADD, TUINT16):
case CASE(OADD, TINT32):
// case CASE(OADD, TINT16): case CASE(OADD, TUINT32):
// case CASE(OADD, TUINT16): case CASE(OADD, TPTR32):
// a = AADDW; a = AADD;
// break; break;
// case CASE(OADD, TINT32):
// case CASE(OADD, TUINT32):
// case CASE(OADD, TPTR32):
// a = AADDL;
// break;
// case CASE(OADD, TINT64): // case CASE(OADD, TINT64):
// case CASE(OADD, TUINT64): // case CASE(OADD, TUINT64):
...@@ -1436,50 +1411,6 @@ optoas(int op, Type *t) ...@@ -1436,50 +1411,6 @@ optoas(int op, Type *t)
// a = ASUBSD; // a = ASUBSD;
// break; // break;
// case CASE(OINC, TINT8):
// case CASE(OINC, TUINT8):
// a = AINCB;
// break;
// case CASE(OINC, TINT16):
// case CASE(OINC, TUINT16):
// a = AINCW;
// break;
// case CASE(OINC, TINT32):
// case CASE(OINC, TUINT32):
// case CASE(OINC, TPTR32):
// a = AINCL;
// break;
// case CASE(OINC, TINT64):
// case CASE(OINC, TUINT64):
// case CASE(OINC, TPTR64):
// a = AINCQ;
// break;
// case CASE(ODEC, TINT8):
// case CASE(ODEC, TUINT8):
// a = ADECB;
// break;
// case CASE(ODEC, TINT16):
// case CASE(ODEC, TUINT16):
// a = ADECW;
// break;
// case CASE(ODEC, TINT32):
// case CASE(ODEC, TUINT32):
// case CASE(ODEC, TPTR32):
// a = ADECL;
// break;
// case CASE(ODEC, TINT64):
// case CASE(ODEC, TUINT64):
// case CASE(ODEC, TPTR64):
// a = ADECQ;
// break;
// case CASE(OMINUS, TINT8): // case CASE(OMINUS, TINT8):
// case CASE(OMINUS, TUINT8): // case CASE(OMINUS, TUINT8):
// a = ANEGB; // a = ANEGB;
......
...@@ -122,13 +122,14 @@ Dconv(Fmt *fp) ...@@ -122,13 +122,14 @@ Dconv(Fmt *fp)
break; break;
case D_CONST: case D_CONST:
if(fp->flags & FmtLong) { if(a->reg != NREG)
d1 = a->offset & 0xffffffffLL; sprint(str, "$%N(R%d)", a, a->reg);
d2 = (a->offset>>32) & 0xffffffffLL; else
snprint(str, sizeof(str), "$%lud-%lud", (ulong)d1, (ulong)d2); sprint(str, "$%N", a);
break; break;
}
snprint(str, sizeof(str), "$%d", a->offset); case D_CONST2:
sprint(str, "$%d-%d", a->offset, a->offset2);
break; break;
case D_FCONST: case D_FCONST:
......
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