]> Cypherpunks repositories - gostls13.git/commitdiff
fixes to 5g object file generation. arm specific regalloc.
authorKai Backman <kaib@golang.org>
Thu, 25 Jun 2009 18:01:17 +0000 (11:01 -0700)
committerKai Backman <kaib@golang.org>
Thu, 25 Jun 2009 18:01:17 +0000 (11:01 -0700)
R=rsc
APPROVED=rsc
DELTA=976  (164 added, 237 deleted, 575 changed)
OCL=30705
CL=30743

src/cmd/5g/gg.h
src/cmd/5g/ggen.c
src/cmd/5g/gobj.c
src/cmd/5g/gsubr.c
src/cmd/5g/list.c

index 914109a05da92d071a0e5f2b1e95e6abedcce3c2..19084f34f52a008f508c63941bd32ff7180b7b81 100644 (file)
@@ -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);
index fe561d8956e46fb365170c121bab1b7df6be45d2..9a73480a7148edb4a3c0fae744aa8bb394d05eb9 100644 (file)
@@ -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:
index ff70d48d34d21c0d9245a86e6a2cbee3eb245f81..6f2c94b2b08afe3492dfd09283e834d1b169a1fe 100644 (file)
@@ -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);
index ba68a697af9e4bc79f9fbbc9ee95dd172cb8393c..fe83abbb2bf1054115c27c43edf0294836a35bb6 100644 (file)
@@ -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;
index 76855bdb5701ce0343fbb7d03cb586dca561e382..ab8256ca511ac5dc5031d610f93c23f8b4413c08 100644 (file)
@@ -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: