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
Sym* sym;
int width;
uchar type;
char reg;
uchar index;
uchar etype;
uchar scale; /* doubles as width in DATA op */
......@@ -40,12 +41,18 @@ struct Prog
Addr from; // src address
Addr to; // dst address
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 int32 dynloc;
EXTERN uchar reg[D_NONE];
EXTERN uchar reg[REGALLOC_FMAX];
EXTERN int32 pcloc; // instruction counter
EXTERN Strlit emptystring;
extern char* anames[];
......@@ -57,6 +64,7 @@ EXTERN Node* deferproc;
EXTERN Node* deferreturn;
EXTERN Node* throwindex;
EXTERN Node* throwreturn;
EXTERN int maxstksize;
/*
* gen.c
......@@ -115,6 +123,8 @@ void ginit(void);
void gclean(void);
void regalloc(Node*, Type*, Node*);
void regfree(Node*);
void tempalloc(Node*, Type*);
void tempfree(Node*);
Node* nodarg(Type*, int);
void nodreg(Node*, Type*, int);
void nodindreg(Node*, Type*, int);
......
......@@ -65,10 +65,8 @@ compile(Node *fn)
ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
gen(curfn->enter);
gen(curfn->nbody);
gclean();
checklabels();
if(curfn->type->outtuple != 0)
......@@ -85,10 +83,14 @@ compile(Node *fn)
*/
// fill in argument size
ptxt->to.type = D_CONST2;
ptxt->to.offset2 = rnd(curfn->type->argwid, maxround);
// 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'])
frame(0);
......@@ -359,42 +361,6 @@ cgen_asop(Node *n)
if(!isint[nr->type->etype])
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) {
case OADD:
case OSUB:
......
......@@ -64,6 +64,8 @@ zhist(Biobuf *b, int line, vlong offset)
Addr a;
Bputc(b, AHISTORY);
Bputc(b, 0);
Bputc(b, 0);
Bputc(b, line);
Bputc(b, line>>8);
Bputc(b, line>>16);
......@@ -82,19 +84,26 @@ zaddr(Biobuf *b, Addr *a, int s)
{
int32 l;
Ieee e;
int i;
char *n;
// Bputc(b, a->type);
// TODO(kaib): Re-introduce registers once we figure out what they are used
// for.
// Bputc(b, a->reg);
// Bputc(b, s);
// TODO(kaib): ditto for Addr.name
// Bputc(b, a->name);
switch(a->type) {
case D_STATIC:
case D_EXTERN:
case D_AUTO:
case D_PARAM:
Bputc(b, D_OREG);
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) {
default:
print("unknown type %d in zaddr\n", a->type);
......@@ -107,10 +116,18 @@ zaddr(Biobuf *b, Addr *a, int s)
case D_PARAM:
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_CONST:
case D_BRANCH:
case D_SHIFT:
case D_STATIC:
case D_AUTO:
l = a->offset;
Bputc(b, l);
Bputc(b, l>>8);
......@@ -118,27 +135,27 @@ zaddr(Biobuf *b, Addr *a, int s)
Bputc(b, l>>24);
break;
// case D_SCONST:
// n = a->sval;
// for(i=0; i<NSNAME; i++) {
// Bputc(b, b, *n);
// n++;
// }
// break;
// case D_FCONST:
// ieeedtod(&e, a->dval);
// l = e.l;
// Bputc(b, l);
// Bputc(b, l>>8);
// Bputc(b, l>>16);
// Bputc(b, l>>24);
// l = e.h;
// Bputc(b, l);
// Bputc(b, l>>8);
// Bputc(b, l>>16);
// Bputc(b, l>>24);
// break;
case D_SCONST:
n = a->sval;
for(i=0; i<NSNAME; i++) {
Bputc(b, *n);
n++;
}
break;
case D_FCONST:
ieeedtod(&e, a->dval);
l = e.l;
Bputc(b, l);
Bputc(b, l>>8);
Bputc(b, l>>16);
Bputc(b, l>>24);
l = e.h;
Bputc(b, l);
Bputc(b, l>>8);
Bputc(b, l>>16);
Bputc(b, l>>24);
break;
}
}
......@@ -228,6 +245,8 @@ dumpfuncs(void)
break;
}
Bputc(bout, p->as);
Bputc(bout, p->scond);
Bputc(bout, p->reg);
Bputc(bout, p->lineno);
Bputc(bout, p->lineno>>8);
Bputc(bout, p->lineno>>16);
......
......@@ -190,129 +190,118 @@ afunclit(Addr *a)
}
}
// TODO(kaib): probably not needed.
static int resvd[] =
{
// D_DI, // for movstring
// 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
/*
* allocate register of type t, leave in n.
* if o != N, o is desired fixed register.
* caller must regfree(n).
*/
void
ginit(void)
regalloc(Node *n, Type *t, Node *o)
{
// int i;
int i, et;
if(t == T)
fatal("regalloc: t nil");
et = simtype[t->etype];
switch(et) {
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;
// for(i=0; i<nelem(reg); i++)
// reg[i] = 1;
// for(i=D_AX; i<=D_R15; i++)
// reg[i] = 0;
// for(i=D_X0; i<=D_X7; i++)
// reg[i] = 0;
yyerror("out of fixed registers");
goto err;
// for(i=0; i<nelem(resvd); i++)
// reg[resvd[i]]++;
case TFLOAT32:
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);
err:
nodreg(n, t, 0);
return;
out:
reg[i]++;
nodreg(n, t, i);
}
void
gclean(void)
regfree(Node *n)
{
// int i;
// for(i=0; i<nelem(resvd); i++)
// reg[resvd[i]]--;
// for(i=D_AX; i<=D_R15; i++)
// if(reg[i])
// yyerror("reg %R left allocated\n", i);
// for(i=D_X0; i<=D_X7; i++)
// if(reg[i])
// yyerror("reg %R left allocated\n", i);
int i;
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
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]--;
}
/*
* allocate register of type t, leave in n.
* if o != N, o is desired fixed register.
* caller must regfree(n).
*/
void
regalloc(Node *n, Type *t, Node *o)
tempalloc(Node *n, Type *t)
{
// int i, et;
// if(t == T)
// fatal("regalloc: t nil");
// et = simtype[t->etype];
// switch(et) {
// 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 >= 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);
int w;
// err:
// nodreg(n, t, 0);
// return;
dowidth(t);
// out:
// reg[i]++;
// nodreg(n, t, i);
memset(n, 0, sizeof(*n));
n->op = ONAME;
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
regfree(Node *n)
tempfree(Node *n)
{
// int i;
// if(n->op != OREGISTER && n->op != OINDREG)
// fatal("regfree: not a register");
// 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]--;
//print("tempfree %d\n", n->xoffset);
if(n->xoffset != -stksize)
fatal("tempfree %lld %d", -n->xoffset, stksize);
stksize = n->ostk;
}
/*
......@@ -410,575 +399,563 @@ gconreg(int as, vlong c, int reg)
gins(as, &n1, &n2);
}
#define CASE(a,b) (((a)<<16)|((b)<<0))
/*
* generate move:
* t = f
* Is this node a memory operand?
*/
// TODO(kaib): Crib the new gmove from 8g
void
gmove(Node *f, Node *t)
int
ismem(Node *n)
{
int ft, tt, t64, a;
Node nod, nod1, nod2, nod3, nodc;
Prog *p1, *p2;
switch(n->op) {
case OINDREG:
case ONAME:
case OPARAM:
return 1;
}
return 0;
}
ft = simtype[f->type->etype];
tt = simtype[t->type->etype];
#define CASE(a,b) (((a)<<16)|((b)<<0))
t64 = 0;
if(tt == TINT64 || tt == TUINT64 || tt == TPTR64)
t64 = 1;
void
gmove(Node *f, Node *t)
{
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'])
print("gop: %O %O[%E],%O[%E]\n", OAS,
f->op, ft, t->op, tt);
/*
* load
*/
if(f->op == ONAME || f->op == OINDREG ||
f->op == OIND || f->op == OINDEX)
fatal("gmove load not implemented");
// switch(ft) {
// case TINT8:
// a = AMOVBLSX;
// if(t64)
// a = AMOVBQSX;
// goto ld;
// case TBOOL:
// case TUINT8:
// a = AMOVBLZX;
// if(t64)
// a = AMOVBQZX;
// goto ld;
// case TINT16:
// a = AMOVWLSX;
// if(t64)
// a = AMOVWQSX;
// goto ld;
// case TUINT16:
// 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;
print("gmove %N -> %N\n", f, t);
ft = simsimtype(f->type);
tt = simsimtype(t->type);
cvt = t->type;
// cannot have two integer memory operands;
// except 64-bit, which always copies via registers anyway.
// TODO(kaib): re-enable check
// if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
// goto hard;
// convert constant to desired type
if(f->op == OLITERAL) {
if(tt == TFLOAT32)
convconst(&con, types[TFLOAT64], &f->val);
else
convconst(&con, t->type, &f->val);
f = &con;
ft = simsimtype(con.type);
// some constants can't move directly to memory.
if(ismem(t)) {
// float constants come from memory.
if(isfloat[tt])
goto hard;
}
}
// ld:
// regalloc(&nod, f->type, t);
// nod.type = t64? types[TINT64]: types[TINT32];
// gins(a, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// value -> value copy, only one memory operand.
// figure out the instruction to use.
// break out of switch for one-instruction gins.
// goto rdst for "destination must be register".
// goto hard for "convert to cvt type first".
// otherwise handle and return.
// case TFLOAT32:
// a = AMOVSS;
// goto fld;
// 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;
// }
switch(CASE(ft, tt)) {
default:
goto fatal;
/*
* integer copy and truncate
*/
case CASE(TINT8, TINT8): // same size
case CASE(TINT8, TUINT8):
case CASE(TUINT8, TINT8):
case CASE(TUINT8, TUINT8):
case CASE(TINT16, TINT8): // truncate
case CASE(TUINT16, TINT8):
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;
break;
/*
* store
*/
if(t->op == ONAME || t->op == OINDREG ||
t->op == OIND || t->op == OINDEX)
case CASE(TINT64, TINT8): // truncate low word
case CASE(TUINT64, TINT8):
case CASE(TINT64, TUINT8):
case CASE(TUINT64, TUINT8):
fatal("gmove INT64,INT8 not implemented");
// split64(f, &flo, &fhi);
// nodreg(&r1, t->type, D_AX);
// gins(AMOVB, &flo, &r1);
// gins(AMOVB, &r1, t);
// splitclean();
return;
switch(tt) {
case TBOOL:
case TINT8:
case TUINT8:
a = AMOVB;
goto st;
case TINT16:
case TUINT16:
case CASE(TINT16, TINT16): // same size
case CASE(TINT16, TUINT16):
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;
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;
case TPTR32:
/*
* store to pointer.
*/
a = AMOVW;
switch(t->op) {
default:
dump("gmove to", t);
fatal("gmove t %O", t->op);
case CASE(TINT64, TINT16): // truncate low word
case CASE(TUINT64, TINT16):
case CASE(TINT64, TUINT16):
case CASE(TUINT64, TUINT16):
fatal("gmove INT64,INT16 not implemented");
// split64(f, &flo, &fhi);
// nodreg(&r1, t->type, D_AX);
// gins(AMOVW, &flo, &r1);
// gins(AMOVW, &r1, t);
// splitclean();
return;
case OINDREG:
if(t->val.u.reg != REGSP)
goto refcount;
break;
case CASE(TINT32, TINT32): // same size
case CASE(TINT32, TUINT32):
case CASE(TUINT32, TINT32):
case CASE(TUINT32, TUINT32):
a = AMOVW;
break;
case ONAME:
switch(t->class) {
default:
dump("gmove", t);
fatal("gmove t %O class %d reg %R", t->op, t->class, t->val.u.reg);
case PEXTERN:
goto refcount;
break;
case PAUTO:
case PPARAM:
case PPARAMOUT:
break;
}
break;
}
goto st;
st:
// 64-bit immediates only allowed for move into registers.
// this is not a move into a register.
if(f->op == OLITERAL && !t64) {
gins(a, f, t);
return;
}
fst:
regalloc(&nod, t->type, f);
gmove(f, &nod);
gins(a, &nod, t);
regfree(&nod);
case CASE(TINT64, TINT32): // truncate
case CASE(TUINT64, TINT32):
case CASE(TINT64, TUINT32):
case CASE(TUINT64, TUINT32):
fatal("gmove INT64,INT32 not implemented");
// split64(f, &flo, &fhi);
// nodreg(&r1, t->type, D_AX);
// gins(AMOVL, &flo, &r1);
// gins(AMOVL, &r1, t);
// splitclean();
return;
refcount:
fatal("gmove refcount not implemented");
// if(!debug['r'])
// goto st;
// // for now, mark ref count updates with AXCHGQ.
// // using a temporary on the left, so no semantic
// // changes. code is likely slower, but still correct.
// if(t64)
// a = AXCHGQ;
// else
// a = AXCHGL;
// regalloc(&nod, t->type, f);
// gmove(f, &nod);
// gins(a, &nod, t);
// regfree(&nod);
case CASE(TINT64, TINT64): // same size
case CASE(TINT64, TUINT64):
case CASE(TUINT64, TINT64):
case CASE(TUINT64, TUINT64):
fatal("gmove INT64,INT64 not implemented");
// split64(f, &flo, &fhi);
// split64(t, &tlo, &thi);
// if(f->op == OLITERAL) {
// gins(AMOVL, &flo, &tlo);
// gins(AMOVL, &fhi, &thi);
// } else {
// nodreg(&r1, t->type, D_AX);
// nodreg(&r2, t->type, D_DX);
// gins(AMOVL, &flo, &r1);
// gins(AMOVL, &fhi, &r2);
// gins(AMOVL, &r1, &tlo);
// gins(AMOVL, &r2, &thi);
// }
// splitclean();
// splitclean();
return;
case TFLOAT32:
a = AMOVW;
goto fst;
case TFLOAT64:
fatal("gmove TFLOAT64 not implemented");
// a = AMOVSD;
goto fst;
/*
* integer up-conversions
*/
// case CASE(TINT8, TINT16): // sign extend int8
// case CASE(TINT8, TUINT16):
// a = AMOVBWSX;
// goto rdst;
// case CASE(TINT8, TINT32):
// case CASE(TINT8, TUINT32):
// a = AMOVBLSX;
// goto rdst;
// case CASE(TINT8, TINT64): // convert via int32
// case CASE(TINT8, TUINT64):
// cvt = types[TINT32];
// goto hard;
// case CASE(TUINT8, TINT16): // zero extend uint8
// case CASE(TUINT8, TUINT16):
// a = AMOVBWZX;
// goto rdst;
// case CASE(TUINT8, TINT32):
// case CASE(TUINT8, TUINT32):
// a = AMOVBLZX;
// goto rdst;
// case CASE(TUINT8, TINT64): // convert via uint32
// case CASE(TUINT8, TUINT64):
// cvt = types[TUINT32];
// goto hard;
// case CASE(TINT16, TINT32): // sign extend int16
// case CASE(TINT16, TUINT32):
// a = AMOVWLSX;
// 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 integer
// */
// case CASE(TFLOAT32, TINT16):
// case CASE(TFLOAT32, TINT32):
// case CASE(TFLOAT32, TINT64):
// case CASE(TFLOAT64, TINT16):
// case CASE(TFLOAT64, TINT32):
// case CASE(TFLOAT64, TINT64):
// if(t->op == OREGISTER)
// goto hardmem;
// 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;
// case CASE(TFLOAT32, TINT8):
// case CASE(TFLOAT32, TUINT16):
// case CASE(TFLOAT32, TUINT8):
// case CASE(TFLOAT64, TINT8):
// 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):
// // convert via int64.
// tempalloc(&t1, types[TINT64]);
// gmove(f, &t1);
// split64(&t1, &tlo, &thi);
// gins(ACMPL, &thi, ncon(0));
// p1 = gbranch(AJEQ, T);
// gins(AMOVL, ncon(0), &tlo);
// patch(p1, pc);
// gmove(&tlo, t);
// splitclean();
// tempfree(&t1);
// return;
// case CASE(TFLOAT32, TUINT64):
// case CASE(TFLOAT64, TUINT64):
// bignodes();
// nodreg(&f0, types[ft], D_F0);
// nodreg(&f1, types[ft], D_F0 + 1);
// nodreg(&ax, types[TUINT16], D_AX);
// gmove(f, &f0);
// // if 0 > v { answer = 0 }
// gmove(&zerof, &f0);
// gins(AFUCOMP, &f0, &f1);
// gins(AFSTSW, N, &ax);
// gins(ASAHF, N, N);
// p1 = gbranch(optoas(OGT, types[tt]), 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);
// gins(AFMOVVP, &f0, t); // don't care about t, but will pop the stack
// split64(t, &tlo, &thi);
// gins(AMOVL, ncon(0), &tlo);
// gins(AMOVL, ncon(0), &thi);
// splitclean();
// p1 = gbranch(AJMP, T);
// patch(p2, pc);
// // in range; algorithm is:
// // if small enough, use native float64 -> int64 conversion.
// // otherwise, subtract 2^63, convert, and add it back.
// // 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);
// tempfree(&t2);
// // 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;
// /*
// * 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, TFLOAT64):
// fatal("gmove TINT,TFLOAT not implemented");
// // if(t->op != OREGISTER)
// // goto hard;
// // if(f->op == OREGISTER) {
// // cvt = f->type;
// // goto hardmem;
// // }
// // switch(ft) {
// // case TINT16:
// // a = AFMOVW;
// // break;
// // case TINT32:
// // a = AFMOVL;
// // break;
// // default:
// // a = AFMOVV;
// // break;
// // }
// break;
// case CASE(TINT8, TFLOAT32):
// case CASE(TINT8, TFLOAT64):
// case CASE(TUINT16, TFLOAT32):
// case CASE(TUINT16, TFLOAT64):
// case CASE(TUINT8, TFLOAT32):
// case CASE(TUINT8, TFLOAT64):
// // convert via int32 memory
// cvt = types[TINT32];
// 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;
// /*
// * float to float
// */
// case CASE(TFLOAT32, TFLOAT32):
// case CASE(TFLOAT64, TFLOAT64):
// // 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;
// 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(f->op == OREGISTER)
// gins(AFMOVDP, f, t);
// else
// gins(AFMOVF, f, t);
// 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;
}
/*
* convert
*/
fatal("gmove convert not implemented");
// 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, TINT32):
// case CASE(TINT8, TUINT32):
// a = AMOVBLSX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xff;
// // if(f->val.vval & 0x80)
// // f->val.vval |= 0xffffff00;
// // a = AMOVL;
// // }
// break;
// case CASE(TINT8, TINT64):
// case CASE(TINT8, TUINT64):
// case CASE(TINT8, TPTR64):
// a = AMOVBQSX;
// // 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(TBOOL, TUINT16):
// case CASE(TBOOL, TINT32):
// case CASE(TBOOL, TUINT32):
// case CASE(TUINT8, TINT16):
// case CASE(TUINT8, TUINT16):
// case CASE(TUINT8, TINT32):
// case CASE(TUINT8, TUINT32):
// a = AMOVBLZX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xff;
// // 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, TPTR64):
// a = AMOVBQZX;
// // if(f->op == OCONST) {
// // f->val.vval &= 0xff;
// // a = AMOVL; /* zero-extends to 64-bits */
// // }
// break;
// /*
// * float to fix
// */
// case CASE(TFLOAT32, TINT8):
// case CASE(TFLOAT32, TINT16):
// 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, 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, TINT32):
// regalloc(&nod, t->type, N);
// gins(ACVTTSD2SL, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TFLOAT64, TBOOL):
// case CASE(TFLOAT64, TUINT8):
// case CASE(TFLOAT64, TUINT16):
// case CASE(TFLOAT64, TUINT32):
// case CASE(TFLOAT64, TINT64):
// case CASE(TFLOAT64, TUINT64):
// case CASE(TFLOAT64, TPTR64):
// regalloc(&nod, t->type, N);
// gins(ACVTTSD2SQ, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// /*
// * uvlong to float
// */
// case CASE(TUINT64, TFLOAT64):
// case CASE(TUINT64, TFLOAT32):
// a = ACVTSQ2SS;
// if(tt == TFLOAT64)
// a = ACVTSQ2SD;
// regalloc(&nod, f->type, f);
// gmove(f, &nod);
// regalloc(&nod1, t->type, t);
// nodconst(&nodc, types[TUINT64], 0);
// gins(ACMPQ, &nod, &nodc);
// p1 = gbranch(AJLT, T);
// gins(a, &nod, &nod1);
// p2 = gbranch(AJMP, T);
// patch(p1, pc);
// regalloc(&nod2, f->type, N);
// regalloc(&nod3, f->type, N);
// gmove(&nod, &nod2);
// nodconst(&nodc, types[TUINT64], 1);
// gins(ASHRQ, &nodc, &nod2);
// gmove(&nod, &nod3);
// 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);
// regfree(&nod);
// regfree(&nod1);
// return;
// case CASE(TUINT32, TFLOAT64):
// case CASE(TUINT32, TFLOAT32):
// a = ACVTSQ2SS;
// if(tt == TFLOAT64)
// a = ACVTSQ2SD;
// regalloc(&nod, f->type, f);
// gins(AMOVLQZX, f, &nod);
// regalloc(&nod1, t->type, t);
// gins(a, &nod, &nod1);
// gmove(&nod1, t);
// regfree(&nod);
// regfree(&nod1);
// return;
// /*
// * fix to float
// */
// 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(TPTR64, TFLOAT64):
// regalloc(&nod, t->type, t);
// gins(ACVTSQ2SD, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// case CASE(TBOOL, 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(TUINT8, TFLOAT64):
// case CASE(TINT16, TFLOAT64):
// case CASE(TUINT16, TFLOAT64):
// case CASE(TINT32, TFLOAT64):
// regalloc(&nod, t->type, t);
// gins(ACVTSL2SD, f, &nod);
// gmove(&nod, t);
// regfree(&nod);
// return;
// /*
// * float to float
// */
// 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):
// a = AMOVSD;
// break;
// }
// if(a == AMOVQ ||
// a == AMOVSD ||
// a == AMOVSS ||
// (a == AMOVL && f->type->width == t->type->width)) /* TO DO: check AMOVL */
// if(samaddr(f, t))
// return;
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
......@@ -1053,13 +1030,17 @@ naddr(Node *n, Addr *a)
fatal("naddr: bad %O %D", n->op, a);
break;
// case OREGISTER:
// a->type = n->val.u.reg;
// a->sym = S;
// break;
case OREGISTER:
a->type = D_OREG;
if (n->val.u.reg <= REGALLOC_RMAX)
a->reg = n->val.u.reg;
else
a->reg = n->val.u.reg - REGALLOC_F0;
a->sym = S;
break;
// case OINDEX:
// case OIND:
case OINDEX:
case OIND:
// naddr(n->left, a);
// if(a->type >= D_AX && a->type <= D_DI)
// a->type += D_INDIR;
......@@ -1376,21 +1357,15 @@ optoas(int op, Type *t)
// a = AMOVSD;
// break;
// case CASE(OADD, TINT8):
// case CASE(OADD, TUINT8):
// a = AADDB;
// break;
// case CASE(OADD, TINT16):
// case CASE(OADD, TUINT16):
// a = AADDW;
// break;
// case CASE(OADD, TINT32):
// case CASE(OADD, TUINT32):
// case CASE(OADD, TPTR32):
// a = AADDL;
// break;
case CASE(OADD, TINT8):
case CASE(OADD, TUINT8):
case CASE(OADD, TINT16):
case CASE(OADD, TUINT16):
case CASE(OADD, TINT32):
case CASE(OADD, TUINT32):
case CASE(OADD, TPTR32):
a = AADD;
break;
// case CASE(OADD, TINT64):
// case CASE(OADD, TUINT64):
......@@ -1436,50 +1411,6 @@ optoas(int op, Type *t)
// a = ASUBSD;
// 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, TUINT8):
// a = ANEGB;
......
......@@ -122,13 +122,14 @@ Dconv(Fmt *fp)
break;
case D_CONST:
if(fp->flags & FmtLong) {
d1 = a->offset & 0xffffffffLL;
d2 = (a->offset>>32) & 0xffffffffLL;
snprint(str, sizeof(str), "$%lud-%lud", (ulong)d1, (ulong)d2);
break;
}
snprint(str, sizeof(str), "$%d", a->offset);
if(a->reg != NREG)
sprint(str, "$%N(R%d)", a, a->reg);
else
sprint(str, "$%N", a);
break;
case D_CONST2:
sprint(str, "$%d-%d", a->offset, a->offset2);
break;
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