2010-02-19 21:42:50 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "gg.h"
|
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
static void subnode(Node *nr, Node *ni, Node *nc);
|
|
|
|
static void negate(Node *n);
|
|
|
|
static void zero(Node *n);
|
|
|
|
static int isimag1i(Node*);
|
|
|
|
|
2010-02-19 21:42:50 -07:00
|
|
|
#define CASE(a,b) (((a)<<16)|((b)<<0))
|
|
|
|
|
|
|
|
/*
|
|
|
|
* generate:
|
|
|
|
* res = n;
|
|
|
|
* simplifies and calls gmove.
|
2010-02-21 18:51:39 -07:00
|
|
|
* perm is
|
|
|
|
* 0 (r,i) -> (r,i)
|
|
|
|
* 1 (r,i) -> (-i,r) *1i
|
|
|
|
* 2 (r,i) -> (i,-r) /1i
|
2010-02-19 21:42:50 -07:00
|
|
|
*/
|
|
|
|
void
|
2010-02-21 18:51:39 -07:00
|
|
|
complexmove(Node *f, Node *t, int perm)
|
2010-02-19 21:42:50 -07:00
|
|
|
{
|
|
|
|
int ft, tt;
|
2010-02-21 18:51:39 -07:00
|
|
|
Node n1, n2, n3, n4, nc;
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-03-02 19:32:11 -07:00
|
|
|
if(debug['g']) {
|
2010-03-05 21:16:04 -07:00
|
|
|
dump("\ncomplexmove-f", f);
|
|
|
|
dump("complexmove-t", t);
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!t->addable)
|
2010-03-05 21:16:04 -07:00
|
|
|
fatal("complexmove: to not addable");
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
ft = simsimtype(f->type);
|
|
|
|
tt = simsimtype(t->type);
|
|
|
|
switch(CASE(ft,tt)) {
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
default:
|
|
|
|
fatal("complexmove: unknown conversion: %T -> %T\n",
|
|
|
|
f->type, t->type);
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
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;
|
|
|
|
}
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
subnode(&n1, &n2, f);
|
|
|
|
subnode(&n3, &n4, t);
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
// 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;
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
case CASE(TFLOAT32,TCOMPLEX64):
|
|
|
|
case CASE(TFLOAT32,TCOMPLEX128):
|
|
|
|
case CASE(TFLOAT64,TCOMPLEX64):
|
|
|
|
case CASE(TFLOAT64,TCOMPLEX128):
|
|
|
|
// float to complex goes to real part
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
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;
|
|
|
|
}
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
|
|
|
|
2010-03-02 19:32:11 -07:00
|
|
|
int
|
|
|
|
complexop(Node *n, Node *res)
|
|
|
|
{
|
|
|
|
if(n != N && n->type != T)
|
|
|
|
if(iscomplex[n->type->etype]) {
|
2010-03-05 21:16:04 -07:00
|
|
|
goto yes;
|
|
|
|
}
|
|
|
|
if(res != N && res->type != T)
|
|
|
|
if(iscomplex[res->type->etype]) {
|
|
|
|
goto yes;
|
2010-03-02 19:32:11 -07:00
|
|
|
}
|
2010-03-05 21:16:04 -07:00
|
|
|
|
|
|
|
if(n->op == OREAL || n->op == OIMAG)
|
|
|
|
return 1;
|
|
|
|
|
2010-03-02 19:32:11 -07:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
yes:
|
2010-03-05 21:16:04 -07:00
|
|
|
switch(n->op) {
|
|
|
|
case OCONV: // implemented ops
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
case ODIV:
|
|
|
|
case OMINUS:
|
|
|
|
case OCMPLX:
|
|
|
|
case OREAL:
|
|
|
|
case OIMAG:
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case ODOT: // sudoaddr
|
|
|
|
case ODOTPTR:
|
|
|
|
case OINDEX:
|
|
|
|
case OIND:
|
|
|
|
case ONAME:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2010-03-02 19:32:11 -07:00
|
|
|
}
|
|
|
|
|
2010-02-19 21:42:50 -07:00
|
|
|
void
|
|
|
|
complexgen(Node *n, Node *res)
|
|
|
|
{
|
|
|
|
Node *nl, *nr;
|
2010-03-05 21:16:04 -07:00
|
|
|
Node tnl, tnr;
|
2010-02-21 18:51:39 -07:00
|
|
|
Node n1, n2, n3, n4, n5, n6;
|
|
|
|
Node ra, rb, rc, rd;
|
2010-02-19 21:42:50 -07:00
|
|
|
int tl, tr;
|
|
|
|
|
2010-03-02 19:32:11 -07:00
|
|
|
if(debug['g']) {
|
2010-03-05 21:16:04 -07:00
|
|
|
dump("\ncomplexgen-n", n);
|
|
|
|
dump("complexgen-res", res);
|
|
|
|
}
|
|
|
|
|
|
|
|
// pick off float/complex opcodes
|
|
|
|
switch(n->op) {
|
|
|
|
case OCMPLX:
|
|
|
|
tempname(&tnr, n->type);
|
|
|
|
tr = simsimtype(n->type);
|
|
|
|
tr = cplxsubtype(tr);
|
|
|
|
|
|
|
|
n1 = tnr;
|
|
|
|
n1.type = types[tr];
|
|
|
|
|
|
|
|
n2 = tnr;
|
|
|
|
n2.type = types[tr];
|
|
|
|
n2.xoffset += n2.type->width;
|
|
|
|
|
|
|
|
cgen(n->left, &n1);
|
|
|
|
cgen(n->right, &n2);
|
|
|
|
cgen(&tnr, res);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case OREAL:
|
|
|
|
n = n->left;
|
|
|
|
tr = simsimtype(n->type);
|
|
|
|
tr = cplxsubtype(tr);
|
|
|
|
subnode(&n1, &n2, n);
|
|
|
|
cgen(&n1, res);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case OIMAG:
|
|
|
|
n = n->left;
|
|
|
|
tr = simsimtype(n->type);
|
|
|
|
tr = cplxsubtype(tr);
|
|
|
|
subnode(&n1, &n2, n);
|
|
|
|
cgen(&n2, res);
|
|
|
|
return;
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// perform conversion from n to res
|
|
|
|
tl = simsimtype(res->type);
|
|
|
|
tl = cplxsubtype(tl);
|
|
|
|
tr = simsimtype(n->type);
|
|
|
|
tr = cplxsubtype(tr);
|
|
|
|
if(tl != tr) {
|
2010-02-21 18:51:39 -07:00
|
|
|
if(!n->addable) {
|
|
|
|
tempname(&n1, n->type);
|
|
|
|
complexmove(n, &n1, 0);
|
|
|
|
n = &n1;
|
|
|
|
}
|
|
|
|
complexmove(n, res, 0);
|
2010-02-19 21:42:50 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-05 21:16:04 -07:00
|
|
|
if(!res->addable) {
|
|
|
|
igen(res, &n1, N);
|
|
|
|
cgen(n, &n1);
|
|
|
|
regfree(&n1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(n->addable) {
|
|
|
|
complexmove(n, res, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
dump("complexgen: unknown op", n);
|
|
|
|
fatal("complexgen: unknown op %O", n->op);
|
|
|
|
|
|
|
|
case ODOT:
|
|
|
|
case ODOTPTR:
|
|
|
|
case OINDEX:
|
|
|
|
case OIND:
|
|
|
|
case ONAME: // PHEAP or PPARAMREF var
|
|
|
|
igen(n, &n1, res);
|
|
|
|
complexmove(&n1, res, 0);
|
|
|
|
regfree(&n1);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case OCONV:
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
case ODIV:
|
|
|
|
case OMINUS:
|
|
|
|
case OCMPLX:
|
|
|
|
case OREAL:
|
|
|
|
case OIMAG:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-02-19 21:42:50 -07:00
|
|
|
nl = n->left;
|
|
|
|
if(nl == N)
|
|
|
|
return;
|
|
|
|
nr = n->right;
|
2010-02-21 18:51:39 -07:00
|
|
|
|
|
|
|
// make both sides addable in ullman order
|
2010-02-19 21:42:50 -07:00
|
|
|
if(nr != N) {
|
2010-02-21 18:51:39 -07:00
|
|
|
if(nl->ullman > nr->ullman && !nl->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnl, nl->type);
|
|
|
|
cgen(nl, &tnl);
|
|
|
|
nl = &tnl;
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
2010-02-21 18:51:39 -07:00
|
|
|
if(!nr->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnr, nr->type);
|
|
|
|
cgen(nr, &tnr);
|
|
|
|
nr = &tnr;
|
2010-02-21 18:51:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!nl->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnl, nl->type);
|
|
|
|
cgen(nl, &tnl);
|
|
|
|
nl = &tnl;
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
2010-03-05 21:16:04 -07:00
|
|
|
fatal("complexgen: unknown op %O", n->op);
|
2010-02-19 21:42:50 -07:00
|
|
|
break;
|
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
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;
|
|
|
|
|
2010-02-19 21:42:50 -07:00
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
2010-02-21 18:51:39 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2010-02-19 21:42:50 -07:00
|
|
|
case OMUL:
|
2010-02-21 18:51:39 -07:00
|
|
|
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);
|
2010-02-19 21:42:50 -07:00
|
|
|
break;
|
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
case ODIV:
|
|
|
|
if(isimag1i(nr)) {
|
|
|
|
complexmove(nl, res, 2);
|
|
|
|
break;
|
|
|
|
}
|
2010-03-02 19:32:11 -07:00
|
|
|
|
|
|
|
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(OADD, 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(OSUB, n5.type), &rd, &rc); // rc = (b*c - a*d)
|
|
|
|
|
|
|
|
gmove(&n3, &rb);
|
|
|
|
gins(optoas(OMUL, n5.type), &rb, &rb); // rb = c*c
|
|
|
|
gmove(&n4, &rd);
|
|
|
|
gins(optoas(OMUL, n5.type), &rd, &rd); // rd = d*d
|
|
|
|
gins(optoas(OADD, n5.type), &rd, &rb); // rb = (c*c + d*d)
|
|
|
|
|
|
|
|
gins(optoas(ODIV, n5.type), &rb, &ra); // ra = (a*c + b*d)/(c*c + d*d)
|
|
|
|
gins(optoas(ODIV, n5.type), &rb, &rc); // rc = (b*c - a*d)/(c*c + d*d)
|
|
|
|
|
|
|
|
gmove(&ra, &n5);
|
|
|
|
gmove(&rc, &n6);
|
|
|
|
|
|
|
|
regfree(&ra);
|
|
|
|
regfree(&rb);
|
|
|
|
regfree(&rc);
|
|
|
|
regfree(&rd);
|
|
|
|
break;
|
2010-02-21 18:51:39 -07:00
|
|
|
}
|
|
|
|
}
|
2010-02-19 21:42:50 -07:00
|
|
|
|
2010-03-02 19:32:11 -07:00
|
|
|
void
|
|
|
|
complexbool(int op, Node *nl, Node *nr, int true, Prog *to)
|
|
|
|
{
|
2010-03-05 21:16:04 -07:00
|
|
|
Node tnl, tnr;
|
2010-03-02 19:32:11 -07:00
|
|
|
Node n1, n2, n3, n4;
|
|
|
|
Node na, nb, nc;
|
|
|
|
|
|
|
|
// make both sides addable in ullman order
|
|
|
|
if(nr != N) {
|
|
|
|
if(nl->ullman > nr->ullman && !nl->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnl, nl->type);
|
|
|
|
cgen(nl, &tnl);
|
|
|
|
nl = &tnl;
|
2010-03-02 19:32:11 -07:00
|
|
|
}
|
|
|
|
if(!nr->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnr, nr->type);
|
|
|
|
cgen(nr, &tnr);
|
|
|
|
nr = &tnr;
|
2010-03-02 19:32:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!nl->addable) {
|
2010-03-05 21:16:04 -07:00
|
|
|
tempname(&tnl, nl->type);
|
|
|
|
cgen(nl, &tnl);
|
|
|
|
nl = &tnl;
|
2010-03-02 19:32:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// build tree
|
|
|
|
// real(l) == real(r) && imag(l) == imag(r)
|
|
|
|
|
|
|
|
subnode(&n1, &n2, nl);
|
|
|
|
subnode(&n3, &n4, nr);
|
|
|
|
|
|
|
|
memset(&na, 0, sizeof(na));
|
|
|
|
na.op = OANDAND;
|
|
|
|
na.left = &nb;
|
|
|
|
na.right = &nc;
|
|
|
|
na.type = types[TBOOL];
|
|
|
|
|
|
|
|
memset(&nb, 0, sizeof(na));
|
|
|
|
nb.op = OEQ;
|
|
|
|
nb.left = &n1;
|
|
|
|
nb.right = &n3;
|
|
|
|
nb.type = types[TBOOL];
|
|
|
|
|
|
|
|
memset(&nc, 0, sizeof(na));
|
|
|
|
nc.op = OEQ;
|
|
|
|
nc.left = &n2;
|
|
|
|
nc.right = &n4;
|
|
|
|
nc.type = types[TBOOL];
|
|
|
|
|
|
|
|
if(op == ONE)
|
|
|
|
true = !true;
|
|
|
|
|
|
|
|
bgen(&na, true, to);
|
|
|
|
}
|
|
|
|
|
2010-02-21 18:51:39 -07:00
|
|
|
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;
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|
2010-02-21 18:51:39 -07:00
|
|
|
|
|
|
|
*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);
|
2010-02-19 21:42:50 -07:00
|
|
|
}
|