]> Cypherpunks repositories - gostls13.git/commitdiff
all done except -
authorKen Thompson <ken@golang.org>
Mon, 22 Feb 2010 01:51:39 +0000 (17:51 -0800)
committerKen Thompson <ken@golang.org>
Mon, 22 Feb 2010 01:51:39 +0000 (17:51 -0800)
complex divide
float(complex) conversion
8g 5g etc
tests

R=rsc
CC=golang-dev
https://golang.org/cl/218044

src/cmd/6g/cplx.c
src/cmd/6g/gg.h
src/cmd/6g/gsubr.c

index 0a8b999c43b86622653eb90cbf6674e84e2acb6c..6c91761a350041229aeb34b95ade9b7cb0865bc8 100644 (file)
@@ -4,20 +4,29 @@
 
 #include "gg.h"
 
+static void    subnode(Node *nr, Node *ni, Node *nc);
+static void    negate(Node *n);
+static void    zero(Node *n);
+static int     isimag1i(Node*);
+
 #define        CASE(a,b)       (((a)<<16)|((b)<<0))
 
 /*
  * generate:
  *     res = n;
  * simplifies and calls gmove.
+ * perm is
+ *     0 (r,i) -> (r,i)
+ *     1 (r,i) -> (-i,r)   *1i
+ *     2 (r,i) -> (i,-r)   /1i
  */
 void
-complexmove(Node *f, Node *t)
+complexmove(Node *f, Node *t, int perm)
 {
        int ft, tt;
-       Node n1, n2;
+       Node n1, n2, n3, n4, nc;
 
-       if(debug['g']) {
+       if(1||debug['g']) {
                dump("\ncomplex-f", f);
                dump("complex-t", t);
        }
@@ -25,55 +34,94 @@ complexmove(Node *f, Node *t)
        if(!t->addable)
                fatal("to no addable");
 
-       ft = cplxsubtype(simsimtype(f->type));
-       tt = cplxsubtype(simsimtype(t->type));
-
-       // copy halfs of complex literal
-       if(f->op == OLITERAL) {
-               // real part
-               nodfconst(&n1, types[ft], &f->val.u.cval->real);
-               n2 = *t;
-               n2.type = types[tt];
-               gmove(&n1, &n2);
-
-               // imag part
-               nodfconst(&n1, types[ft], &f->val.u.cval->imag);
-               n2.xoffset += n2.type->width;
-               gmove(&n1, &n2);
-               return;
-       }
+       ft = simsimtype(f->type);
+       tt = simsimtype(t->type);
+       switch(CASE(ft,tt)) {
 
-       // make from addable
-       if(!f->addable) {
-               tempname(&n1, f->type);
-               complexgen(f, &n1);
-               f = &n1;
-       }
+       default:
+               fatal("complexmove: unknown conversion: %T -> %T\n",
+                       f->type, t->type);
 
-       // real part
-       n1 = *f;
-       n1.type = types[ft];
+       case CASE(TCOMPLEX64,TCOMPLEX64):
+       case CASE(TCOMPLEX64,TCOMPLEX128):
+       case CASE(TCOMPLEX128,TCOMPLEX64):
+       case CASE(TCOMPLEX128,TCOMPLEX128):
+               // complex to complex move/convert
+               // make from addable
+               if(!f->addable) {
+                       tempname(&n1, f->type);
+                       complexmove(f, &n1, 0);
+                       f = &n1;
+               }
 
-       n2 = *t;
-       n2.type = types[tt];
+               subnode(&n1, &n2, f);
+               subnode(&n3, &n4, t);
 
-       gmove(&n1, &n2);
+               // perform the permutations.
+               switch(perm) {
+               case 0: // r,i => r,i
+                       gmove(&n1, &n3);
+                       gmove(&n2, &n4);
+                       break;
+               case 1: // r,i => -i,r
+                       regalloc(&nc, n3.type, N);
+                       gmove(&n2, &nc);
+                       negate(&nc);
+                       gmove(&n1, &n4);
+                       gmove(&nc, &n3);
+                       regfree(&nc);
+                       break;
+               case 2: // r,i => i,-r
+                       regalloc(&nc, n4.type, N);
+                       gmove(&n1, &nc);
+                       negate(&nc);
+                       gmove(&n2, &n3);
+                       gmove(&nc, &n4);
+                       regfree(&nc);
+                       break;
+               }
+               break;
 
-       // imag part
-       n1.xoffset += n1.type->width;
-       n2.xoffset += n2.type->width;
-       gmove(&n1, &n2);
+       case CASE(TFLOAT32,TCOMPLEX64):
+       case CASE(TFLOAT32,TCOMPLEX128):
+       case CASE(TFLOAT64,TCOMPLEX64):
+       case CASE(TFLOAT64,TCOMPLEX128):
+               // float to complex goes to real part
 
+               regalloc(&n1, types[ft], N);
+               cgen(f, &n1);
+               subnode(&n3, &n4, t);
+
+               // perform the permutations.
+               switch(perm) {
+               case 0: // no permutations
+                       gmove(&n1, &n3);
+                       zero(&n4);
+                       break;
+               case 1:
+                       gmove(&n1, &n4);
+                       zero(&n3);
+                       break;
+               case 2:
+                       negate(&n1);
+                       gmove(&n1, &n4);
+                       zero(&n3);
+                       break;
+               }
+               regfree(&n1);
+               break;
+       }
 }
 
 void
 complexgen(Node *n, Node *res)
 {
        Node *nl, *nr;
-       Node n1, n2;
+       Node n1, n2, n3, n4, n5, n6;
+       Node ra, rb, rc, rd;
        int tl, tr;
 
-       if(debug['g']) {
+       if(1||debug['g']) {
                dump("\ncomplex-n", n);
                dump("complex-res", res);
        }
@@ -84,42 +132,37 @@ complexgen(Node *n, Node *res)
        tr = simsimtype(n->type);
        tr = cplxsubtype(tr);
        if(tl != tr) {
-               tempname(&n1, n->type);
-               complexgen(n, &n1);
-               complexmove(&n1, n);
+               if(!n->addable) {
+                       tempname(&n1, n->type);
+                       complexmove(n, &n1, 0);
+                       n = &n1;
+               }
+               complexmove(n, res, 0);
                return;
        }
 
        nl = n->left;
        if(nl == N)
                return;
-
        nr = n->right;
+
+       // make both sides addable in ullman order
        if(nr != N) {
-               // make both sides addable in ullman order
-               if(nl->ullman > nr->ullman) {
-                       if(!nl->addable) {
-                               tempname(&n1, nl->type);
-                               complexgen(nl, &n1);
-                               nl = &n1;
-                       }
-                       if(!nr->addable) {
-                               tempname(&n1, nr->type);
-                               complexgen(nr, &n2);
-                               nr = &n2;
-                       }
-               } else {
-                       if(!nr->addable) {
-                               tempname(&n1, nr->type);
-                               complexgen(nr, &n2);
-                               nr = &n2;
-                       }
-                       if(!nl->addable) {
-                               tempname(&n1, nl->type);
-                               complexgen(nl, &n1);
-                               nl = &n1;
-                       }
+               if(nl->ullman > nr->ullman && !nl->addable) {
+                       tempname(&n1, nl->type);
+                       complexgen(nl, &n1);
+                       nl = &n1;
                }
+               if(!nr->addable) {
+                       tempname(&n2, nr->type);
+                       complexgen(nr, &n2);
+                       nr = &n2;
+               }
+       }
+       if(!nl->addable) {
+               tempname(&n1, nl->type);
+               complexgen(nl, &n1);
+               nl = &n1;
        }
 
        switch(n->op) {
@@ -127,21 +170,198 @@ complexgen(Node *n, Node *res)
                fatal("opcode %O", n->op);
                break;
 
+       case OCONV:
+               complexmove(nl, res, 0);
+               break;
+
+       case OMINUS:
+               subnode(&n1, &n2, nl);
+               subnode(&n5, &n6, res);
+
+               regalloc(&ra, n5.type, N);
+               gmove(&n1, &ra);
+               negate(&ra);
+               gmove(&ra, &n5);
+               regfree(&ra);
+
+               regalloc(&ra, n5.type, N);
+               gmove(&n2, &ra);
+               negate(&ra);
+               gmove(&ra, &n6);
+               regfree(&ra);
+               break;
+
        case OADD:
        case OSUB:
+
+               subnode(&n1, &n2, nl);
+               subnode(&n3, &n4, nr);
+               subnode(&n5, &n6, res);
+
+               regalloc(&ra, n5.type, N);
+               gmove(&n1, &ra);
+               gins(optoas(n->op, n5.type), &n3, &ra);
+               gmove(&ra, &n5);
+               regfree(&ra);
+
+               regalloc(&ra, n6.type, N);
+               gmove(&n2, &ra);
+               gins(optoas(n->op, n6.type), &n4, &ra);
+               gmove(&ra, &n6);
+               regfree(&ra);
+               break;
+
        case OMUL:
-       case ODIV:
-               if(nr == N)
-                       fatal("");
-               fatal("opcode %O", n->op);
+               if(isimag1i(nr)) {
+                       complexmove(nl, res, 1);
+                       break;
+               }
+               if(isimag1i(nl)) {
+                       complexmove(nr, res, 1);
+                       break;
+               }
+
+               subnode(&n1, &n2, nl);
+               subnode(&n3, &n4, nr);
+               subnode(&n5, &n6, res);
+
+               regalloc(&ra, n5.type, N);
+               regalloc(&rb, n5.type, N);
+               regalloc(&rc, n6.type, N);
+               regalloc(&rd, n6.type, N);
+
+               gmove(&n1, &ra);
+               gmove(&n3, &rc);
+               gins(optoas(OMUL, n5.type), &rc, &ra);  // ra = a*c
+               
+               gmove(&n2, &rb);
+               gmove(&n4, &rd);
+               gins(optoas(OMUL, n5.type), &rd, &rb);  // rb = b*d
+               gins(optoas(OSUB, n5.type), &rb, &ra);  // ra = (a*c - b*d)
+
+               gins(optoas(OMUL, n5.type), &n2, &rc);  // rc = b*c
+               gins(optoas(OMUL, n5.type), &n1, &rd);  // rd = a*d
+               gins(optoas(OADD, n5.type), &rd, &rc);  // rc = (b*c + a*d)
+
+               gmove(&ra, &n5);
+               gmove(&rc, &n6);
+
+               regfree(&ra);
+               regfree(&rb);
+               regfree(&rc);
+               regfree(&rd);
                break;
 
-       case OMINUS:
+       case ODIV:
+               if(isimag1i(nr)) {
+                       complexmove(nl, res, 2);
+                       break;
+               }
                fatal("opcode %O", n->op);
-               break;
+       }
+}
 
-       case OCONV:
-               complexmove(nl, res);
-               break;
+int
+cplxsubtype(int et)
+{
+       if(et == TCOMPLEX64)
+               return TFLOAT32;
+       if(et == TCOMPLEX128)
+               return TFLOAT64;
+       fatal("cplxsubtype: %E\n", et);
+       return 0;
+}
+
+void
+nodfconst(Node *n, Type *t, Mpflt* fval)
+{
+       memset(n, 0, sizeof(*n));
+       n->op = OLITERAL;
+       n->addable = 1;
+       ullmancalc(n);
+       n->val.u.fval = fval;
+       n->val.ctype = CTFLT;
+       n->type = t;
+
+       if(!isfloat[t->etype])
+               fatal("nodfconst: bad type %T", t);
+}
+
+static int
+isimag1i(Node *n)
+{
+       if(n != N)
+       if(n->op == OLITERAL)
+       if(n->val.ctype == CTCPLX)
+       if(mpgetflt(&n->val.u.cval->real) == 0.0)
+       if(mpgetflt(&n->val.u.cval->imag) == 1.0)
+               return 1;
+       return 0;
+}
+
+// break addable nc-complex into nr-real and ni-imaginary
+static void
+subnode(Node *nr, Node *ni, Node *nc)
+{
+       int tc;
+       Type *t;
+
+       if(!nc->addable)
+               fatal("subnode not addable");
+
+       tc = simsimtype(nc->type);
+       tc = cplxsubtype(tc);
+       t = types[tc];
+
+       if(nc->op == OLITERAL) {
+               nodfconst(nr, t, &nc->val.u.cval->real);
+               nodfconst(ni, t, &nc->val.u.cval->imag);
+               return;
        }
+
+       *nr = *nc;
+       nr->type = t;
+
+       *ni = *nc;
+       ni->type = t;
+       ni->xoffset += t->width;
+}
+
+// generate code to negate register nr
+static void
+negate(Node *nr)
+{
+       Node nc;
+       Mpflt fval;
+
+       memset(&nc, 0, sizeof(nc));
+       nc.op = OLITERAL;
+       nc.addable = 1;
+       ullmancalc(&nc);
+       nc.val.u.fval = &fval;
+       nc.val.ctype = CTFLT;
+       nc.type = nr->type;
+
+       mpmovecflt(nc.val.u.fval, -1.0);
+       gins(optoas(OMUL, nr->type), &nc, nr);
+}
+
+// generate code to zero addable dest nr
+static void
+zero(Node *nr)
+{
+       Node nc;
+       Mpflt fval;
+
+       memset(&nc, 0, sizeof(nc));
+       nc.op = OLITERAL;
+       nc.addable = 1;
+       ullmancalc(&nc);
+       nc.val.u.fval = &fval;
+       nc.val.ctype = CTFLT;
+       nc.type = nr->type;
+
+       mpmovecflt(nc.val.u.fval, 0.0);
+
+       gmove(&nc, nr);
 }
index 264d01f8510a4148f7d78f06759ab5425f731bb0..d2d5629cd4382e11b65e4e776dca2d7686825467 100644 (file)
@@ -134,7 +134,7 @@ void        nodfconst(Node*, Type*, Mpflt*);
 /*
  * cplx.c
  */
-void   complexmove(Node*, Node*);
+void   complexmove(Node*, Node*, int);
 void   complexgen(Node*, Node*);
 
 /*
index c58ebb78de55ca6cf8ec2a1ae54935532a6effd1..2ad6535b1e075f466e408d8a20e66a0dc80ecfec 100644 (file)
@@ -476,7 +476,7 @@ gmove(Node *f, Node *t)
        cvt = t->type;
 
        if(iscomplex[ft] || iscomplex[tt]) {
-               complexmove(f, t);
+               complexmove(f, t, 0);
                return;
        }
 
@@ -495,7 +495,7 @@ gmove(Node *f, Node *t)
                        // float constants come from memory.
                        if(isfloat[tt])
                                goto hard;
-                       // complex constants take double move.
+
                        // 64-bit immediates are really 32-bit sign-extended
                        // unless moving into a register.
                        if(isint[tt]) {
@@ -1979,29 +1979,3 @@ no:
        sudoclean();
        return 0;
 }
-
-int
-cplxsubtype(int et)
-{
-       if(et == TCOMPLEX64)
-               return TFLOAT32;
-       if(et == TCOMPLEX128)
-               return TFLOAT64;
-       fatal("cplxsubtype: %E\n", et);
-       return 0;
-}
-
-void
-nodfconst(Node *n, Type *t, Mpflt* fval)
-{
-       memset(n, 0, sizeof(*n));
-       n->op = OLITERAL;
-       n->addable = 1;
-       ullmancalc(n);
-       n->val.u.fval = fval;
-       n->val.ctype = CTFLT;
-       n->type = t;
-
-       if(!isfloat[t->etype])
-               fatal("nodfconst: bad type %T", t);
-}