break;
                }
 
+               if(is64(nr->type)) {
+                       if(!nl->addable) {
+                               tempalloc(&n1, nl->type);
+                               cgen(nl, &n1);
+                               nl = &n1;
+                       }
+                       if(!nr->addable) {
+                               tempalloc(&n2, nr->type);
+                               cgen(nr, &n2);
+                               nr = &n2;
+                       }
+                       cmp64(nl, nr, a, to);
+                       if(nr == &n2)
+                               tempfree(&n2);
+                       if(nl == &n1)
+                               tempfree(&n1);
+                       break;
+               }
+
                a = optoas(a, nr->type);
 
                if(nr->ullman >= UINF) {
        if(osrc % 4 != 0 || odst %4 != 0)
                fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
 
-       regalloc(&dst, types[tptr], N);
-       regalloc(&src, types[tptr], N);
-       regalloc(&tmp, types[TUINT32], N);
+       regalloc(&dst, types[tptr], res);
 
        if(n->ullman >= res->ullman) {
-               agen(n, &src);
+               agen(n, &dst);
+               regalloc(&src, types[tptr], N);
+               gins(AMOVW, &dst, &src);
                agen(res, &dst);
        } else {
                agen(res, &dst);
+               regalloc(&src, types[tptr], N);
                agen(n, &src);
        }
 
+       regalloc(&tmp, types[TUINT32], N);
+
        c = w % 4;      // bytes
        q = w / 4;      // quads
 
 
 void
 cmp64(Node *nl, Node *nr, int op, Prog *to)
 {
-       fatal("cmp64 not implemented");
-//     Node lo1, hi1, lo2, hi2, rr;
-//     Prog *br;
-//     Type *t;
-
-//     split64(nl, &lo1, &hi1);
-//     split64(nr, &lo2, &hi2);
-
-//     // compare most significant word;
-//     // if they differ, we're done.
-//     t = hi1.type;
-//     if(nl->op == OLITERAL || nr->op == OLITERAL)
-//             gins(ACMPL, &hi1, &hi2);
-//     else {
-//             regalloc(&rr, types[TINT32], N);
-//             gins(AMOVL, &hi1, &rr);
-//             gins(ACMPL, &rr, &hi2);
-//             regfree(&rr);
-//     }
-//     br = P;
-//     switch(op) {
-//     default:
-//             fatal("cmp64 %O %T", op, t);
-//     case OEQ:
-//             // cmp hi
-//             // jne L
-//             // cmp lo
-//             // jeq to
-//             // L:
-//             br = gbranch(AJNE, T);
-//             break;
-//     case ONE:
-//             // cmp hi
-//             // jne to
-//             // cmp lo
-//             // jne to
-//             patch(gbranch(AJNE, T), to);
-//             break;
-//     case OGE:
-//     case OGT:
-//             // cmp hi
-//             // jgt to
-//             // jlt L
-//             // cmp lo
-//             // jge to (or jgt to)
-//             // L:
-//             patch(gbranch(optoas(OGT, t), T), to);
-//             br = gbranch(optoas(OLT, t), T);
-//             break;
-//     case OLE:
-//     case OLT:
-//             // cmp hi
-//             // jlt to
-//             // jgt L
-//             // cmp lo
-//             // jle to (or jlt to)
-//             // L:
-//             patch(gbranch(optoas(OLT, t), T), to);
-//             br = gbranch(optoas(OGT, t), T);
-//             break;
-//     }
-
-//     // compare least significant word
-//     t = lo1.type;
-//     if(nl->op == OLITERAL || nr->op == OLITERAL)
-//             gins(ACMPL, &lo1, &lo2);
-//     else {
-//             regalloc(&rr, types[TINT32], N);
-//             gins(AMOVL, &lo1, &rr);
-//             gins(ACMPL, &rr, &lo2);
-//             regfree(&rr);
-//     }
-
-//     // jump again
-//     patch(gbranch(optoas(op, t), T), to);
-
-//     // point first branch down here if appropriate
-//     if(br != P)
-//             patch(br, pc);
-
-//     splitclean();
-//     splitclean();
+       Node lo1, hi1, lo2, hi2, r1, r2;
+       Prog *br;
+       Type *t;
+
+       split64(nl, &lo1, &hi1);
+       split64(nr, &lo2, &hi2);
+
+       // compare most significant word;
+       // if they differ, we're done.
+       t = hi1.type;
+       regalloc(&r1, types[TINT32], N);
+       regalloc(&r2, types[TINT32], N);
+       gins(AMOVW, &hi1, &r1);
+       gins(AMOVW, &hi2, &r2);
+       gcmp(ACMP, &r1, &r2);
+       regfree(&r1);
+       regfree(&r2);
+
+       br = P;
+       switch(op) {
+       default:
+               fatal("cmp64 %O %T", op, t);
+       case OEQ:
+               // cmp hi
+               // bne L
+               // cmp lo
+               // beq to
+               // L:
+               br = gbranch(ABNE, T);
+               break;
+       case ONE:
+               // cmp hi
+               // bne to
+               // cmp lo
+               // bne to
+               patch(gbranch(ABNE, T), to);
+               break;
+       case OGE:
+       case OGT:
+               // cmp hi
+               // bgt to
+               // blt L
+               // cmp lo
+               // bge to (or bgt to)
+               // L:
+               patch(gbranch(optoas(OGT, t), T), to);
+               br = gbranch(optoas(OLT, t), T);
+               break;
+       case OLE:
+       case OLT:
+               // cmp hi
+               // blt to
+               // bgt L
+               // cmp lo
+               // ble to (or jlt to)
+               // L:
+               patch(gbranch(optoas(OLT, t), T), to);
+               br = gbranch(optoas(OGT, t), T);
+               break;
+       }
+
+       // compare least significant word
+       t = lo1.type;
+       regalloc(&r1, types[TINT32], N);
+       regalloc(&r2, types[TINT32], N);
+       gins(AMOVW, &lo1, &r1);
+       gins(AMOVW, &lo2, &r2);
+       gcmp(ACMP, &r1, &r2);
+       regfree(&r1);
+       regfree(&r2);
+
+       // jump again
+       patch(gbranch(optoas(op, t), T), to);
+
+       // point first branch down here if appropriate
+       if(br != P)
+               patch(br, pc);
+
+       splitclean();
+       splitclean();
 }
 
 void
 regalloc(Node *n, Type *t, Node *o)
 {
-       int i, et;
+       int i, et, fixfree, floatfree;
+
+       if(debug['r']) {
+               fixfree = 0;
+               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
+                       if(reg[i] == 0)
+                               fixfree++;
+               floatfree = 0;
+               for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
+                       if(reg[i] == 0)
+                               floatfree++;
+               print("regalloc fix %d float %d\n", fixfree, floatfree);
+       }
 
        if(t == T)
                fatal("regalloc: t nil");
 void
 regfree(Node *n)
 {
-       int i;
+       int i, fixfree, floatfree;
+
+       if(debug['r']) {
+               fixfree = 0;
+               for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
+                       if(reg[i] == 0)
+                               fixfree++;
+               floatfree = 0;
+               for(i=REGALLOC_F0; i<=REGALLOC_FMAX; i++)
+                       if(reg[i] == 0)
+                               floatfree++;
+               print("regalloc fix %d float %d\n", fixfree, floatfree);
+       }
 
        if(n->op != OREGISTER && n->op != OINDREG)
                fatal("regfree: not a register");
        a = AGOK;
        switch(CASE(op, simtype[t->etype])) {
        default:
-               fatal("optoas: no entry %O-%T", op, t);
+               fatal("optoas: no entry %O-%T etype %T simtype %T", op, t, types[t->etype], types[simtype[t->etype]]);
                break;
 
 /*     case CASE(OADDR, TPTR32):