Commit f229c8b5 authored by Ken Thompson's avatar Ken Thompson

identical complex implementation

for 6g and 8g. can also be used
for 5g. 5g is still a stub.

R=rsc
CC=golang-dev
https://golang.org/cl/362041
parent 5b1a196c
...@@ -38,3 +38,6 @@ clean: ...@@ -38,3 +38,6 @@ clean:
install: $(TARG) install: $(TARG)
cp $(TARG) "$(GOBIN)"/$(TARG) cp $(TARG) "$(GOBIN)"/$(TARG)
%.$O: ../gc/%.c
$(CC) $(CFLAGS) -c -I. -o $@ ../gc/$*.c
...@@ -134,12 +134,12 @@ void nodfconst(Node*, Type*, Mpflt*); ...@@ -134,12 +134,12 @@ void nodfconst(Node*, Type*, Mpflt*);
* cplx.c * cplx.c
*/ */
int complexop(Node*, Node*); int complexop(Node*, Node*);
void complexmove(Node*, Node*, int); void complexmove(Node*, Node*);
void complexgen(Node*, Node*); void complexgen(Node*, Node*);
void complexbool(int, Node*, Node*, int, Prog*); void complexbool(int, Node*, Node*, int, Prog*);
/* /*
* obj.c * gobj.c
*/ */
void datastring(char*, int, Addr*); void datastring(char*, int, Addr*);
......
...@@ -483,7 +483,7 @@ gmove(Node *f, Node *t) ...@@ -483,7 +483,7 @@ gmove(Node *f, Node *t)
cvt = t->type; cvt = t->type;
if(iscomplex[ft] || iscomplex[tt]) { if(iscomplex[ft] || iscomplex[tt]) {
complexmove(f, t, 0); complexmove(f, t);
return; return;
} }
......
...@@ -22,6 +22,7 @@ OFILES=\ ...@@ -22,6 +22,7 @@ OFILES=\
gsubr.$O\ gsubr.$O\
cgen.$O\ cgen.$O\
cgen64.$O\ cgen64.$O\
cplx.$O\
peep.$O\ peep.$O\
reg.$O\ reg.$O\
...@@ -38,3 +39,6 @@ clean: ...@@ -38,3 +39,6 @@ clean:
install: $(TARG) install: $(TARG)
cp $(TARG) "$(GOBIN)"/$(TARG) cp $(TARG) "$(GOBIN)"/$(TARG)
%.$O: ../gc/%.c
$(CC) $(CFLAGS) -c -I. -o $@ ../gc/$*.c
...@@ -57,12 +57,6 @@ cgen(Node *n, Node *res) ...@@ -57,12 +57,6 @@ cgen(Node *n, Node *res)
if(res == N || res->type == T) if(res == N || res->type == T)
fatal("cgen: res nil"); fatal("cgen: res nil");
// TODO compile complex
if(n != N && n->type != T && iscomplex[n->type->etype])
return;
if(res != N && res->type != T && iscomplex[res->type->etype])
return;
// inline slices // inline slices
if(cgen_inline(n, res)) if(cgen_inline(n, res))
return; return;
...@@ -98,6 +92,12 @@ cgen(Node *n, Node *res) ...@@ -98,6 +92,12 @@ cgen(Node *n, Node *res)
break; break;
} }
// complex types
if(complexop(n, res)) {
complexgen(n, res);
return;
}
// if both are addressable, move // if both are addressable, move
if(n->addable && res->addable) { if(n->addable && res->addable) {
gmove(n, res); gmove(n, res);
...@@ -741,12 +741,6 @@ bgen(Node *n, int true, Prog *to) ...@@ -741,12 +741,6 @@ bgen(Node *n, int true, Prog *to)
nl = n->left; nl = n->left;
nr = n->right; nr = n->right;
// TODO compile complex
if(nl != N && nl->type != T && iscomplex[nl->type->etype])
return;
if(nr != N && nr->type != T && iscomplex[nr->type->etype])
return;
if(n->type == T) { if(n->type == T) {
convlit(&n, types[TBOOL]); convlit(&n, types[TBOOL]);
if(n->type == T) if(n->type == T)
...@@ -857,6 +851,7 @@ bgen(Node *n, int true, Prog *to) ...@@ -857,6 +851,7 @@ bgen(Node *n, int true, Prog *to)
break; break;
} }
a = brcom(a); a = brcom(a);
true = !true;
} }
// make simplest on right // make simplest on right
...@@ -960,6 +955,10 @@ bgen(Node *n, int true, Prog *to) ...@@ -960,6 +955,10 @@ bgen(Node *n, int true, Prog *to)
patch(gbranch(optoas(a, nr->type), T), to); patch(gbranch(optoas(a, nr->type), T), to);
break; break;
} }
if(iscomplex[nl->type->etype]) {
complexbool(a, nl, nr, true, to);
break;
}
if(is64(nr->type)) { if(is64(nr->type)) {
if(!nl->addable) { if(!nl->addable) {
......
...@@ -157,6 +157,14 @@ void split64(Node*, Node*, Node*); ...@@ -157,6 +157,14 @@ void split64(Node*, Node*, Node*);
void splitclean(void); void splitclean(void);
void nswap(Node*, Node*); void nswap(Node*, Node*);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*);
void complexgen(Node*, Node*);
void complexbool(int, Node*, Node*, int, Prog*);
/* /*
* gobj.c * gobj.c
*/ */
......
...@@ -1059,6 +1059,11 @@ gmove(Node *f, Node *t) ...@@ -1059,6 +1059,11 @@ gmove(Node *f, Node *t)
tt = simsimtype(t->type); tt = simsimtype(t->type);
cvt = t->type; cvt = t->type;
if(iscomplex[ft] || iscomplex[tt]) {
complexmove(f, t);
return;
}
// cannot have two integer memory operands; // cannot have two integer memory operands;
// except 64-bit, which always copies via registers anyway. // except 64-bit, which always copies via registers anyway.
if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t)) if(isint[ft] && isint[tt] && !is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
...@@ -1489,13 +1494,13 @@ gmove(Node *f, Node *t) ...@@ -1489,13 +1494,13 @@ gmove(Node *f, Node *t)
// on the floating point stack. So toss it away here. // on the floating point stack. So toss it away here.
// Also, F0 is the *only* register we ever evaluate // Also, F0 is the *only* register we ever evaluate
// into, so we should only see register/register as F0/F0. // into, so we should only see register/register as F0/F0.
if(ismem(f) && ismem(t))
goto hard;
if(f->op == OREGISTER && t->op == OREGISTER) { if(f->op == OREGISTER && t->op == OREGISTER) {
if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0) if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
goto fatal; goto fatal;
return; return;
} }
if(ismem(f) && ismem(t))
goto hard;
a = AFMOVF; a = AFMOVF;
if(ft == TFLOAT64) if(ft == TFLOAT64)
a = AFMOVD; a = AFMOVD;
...@@ -1509,6 +1514,8 @@ gmove(Node *f, Node *t) ...@@ -1509,6 +1514,8 @@ gmove(Node *f, Node *t)
break; break;
case CASE(TFLOAT32, TFLOAT64): case CASE(TFLOAT32, TFLOAT64):
if(ismem(f) && ismem(t))
goto hard;
if(f->op == OREGISTER && t->op == OREGISTER) { if(f->op == OREGISTER && t->op == OREGISTER) {
if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0) if(f->val.u.reg != D_F0 || t->val.u.reg != D_F0)
goto fatal; goto fatal;
...@@ -1521,6 +1528,8 @@ gmove(Node *f, Node *t) ...@@ -1521,6 +1528,8 @@ gmove(Node *f, Node *t)
return; return;
case CASE(TFLOAT64, TFLOAT32): case CASE(TFLOAT64, TFLOAT32):
if(ismem(f) && ismem(t))
goto hard;
if(f->op == OREGISTER && t->op == OREGISTER) { if(f->op == OREGISTER && t->op == OREGISTER) {
tempname(&r1, types[TFLOAT32]); tempname(&r1, types[TFLOAT32]);
gins(AFMOVFP, f, &r1); gins(AFMOVFP, f, &r1);
......
...@@ -79,6 +79,7 @@ char *runtimeimport = ...@@ -79,6 +79,7 @@ char *runtimeimport =
"func \"\".uint64mod (? uint64, ? uint64) uint64\n" "func \"\".uint64mod (? uint64, ? uint64) uint64\n"
"func \"\".float64toint64 (? float64) int64\n" "func \"\".float64toint64 (? float64) int64\n"
"func \"\".int64tofloat64 (? int64) float64\n" "func \"\".int64tofloat64 (? int64) float64\n"
"func \"\".complex128div (num complex128, den complex128) (quo complex128)\n"
"\n" "\n"
"$$\n"; "$$\n";
char *unsafeimport = char *unsafeimport =
......
This diff is collapsed.
...@@ -101,3 +101,5 @@ func int64mod(int64, int64) int64 ...@@ -101,3 +101,5 @@ func int64mod(int64, int64) int64
func uint64mod(uint64, uint64) uint64 func uint64mod(uint64, uint64) uint64
func float64toint64(float64) int64 func float64toint64(float64) int64
func int64tofloat64(int64) float64 func int64tofloat64(int64) float64
func complex128div(num complex128, den complex128) (quo complex128)
...@@ -851,13 +851,22 @@ walkexpr(Node **np, NodeList **init) ...@@ -851,13 +851,22 @@ walkexpr(Node **np, NodeList **init)
case ODIV: case ODIV:
case OMOD: case OMOD:
walkexpr(&n->left, init);
walkexpr(&n->right, init);
/*
* rewrite complex div into function call.
*/
et = n->left->type->etype;
if(iscomplex[et] && n->op == ODIV) {
n = mkcall("complex128div", n->type, init,
conv(n->left, types[TCOMPLEX128]),
conv(n->right, types[TCOMPLEX128]));
goto ret;
}
/* /*
* rewrite div and mod into function calls * rewrite div and mod into function calls
* on 32-bit architectures. * on 32-bit architectures.
*/ */
walkexpr(&n->left, init);
walkexpr(&n->right, init);
et = n->left->type->etype;
if(widthptr > 4 || (et != TUINT64 && et != TINT64)) if(widthptr > 4 || (et != TUINT64 && et != TINT64))
goto ret; goto ret;
if(et == TINT64) if(et == TINT64)
......
...@@ -48,6 +48,7 @@ OFILES=\ ...@@ -48,6 +48,7 @@ OFILES=\
chan.$O\ chan.$O\
closure.$O\ closure.$O\
float.$O\ float.$O\
complex.$O\
hashmap.$O\ hashmap.$O\
iface.$O\ iface.$O\
malloc.$O\ malloc.$O\
......
// Copyright 2010 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 "runtime.h"
// complex128div(num, den complex128) (quo complex128)
void
·complex128div(float64 numreal, float64 numimag,
float64 denreal, float64 denimag,
float64 quoreal, float64 quoimag)
{
float64 a, b, ratio, denom;
a = denreal;
if(a < 0)
a = -a;
b = denimag;
if(b < 0)
b = -b;
if(a <= b) {
if(b == 0)
throw("complex divide");
ratio = denreal/denimag;
denom = denreal*ratio + denimag;
quoreal = (numreal*ratio + numimag) / denom;
quoimag = (numimag*ratio - numreal) / denom;
} else {
ratio = denimag/denreal;
denom = denimag*ratio + denreal;
quoreal = (numimag*ratio + numreal) / denom;
quoimag = (numimag - numreal*ratio) / denom;
}
FLUSH(&quoreal);
FLUSH(&quoimag);
}
...@@ -56,6 +56,25 @@ Hello World! ...@@ -56,6 +56,25 @@ Hello World!
== ken/ == ken/
=========== ken/cplx0.go
(+5.000000e+000+6.000000e+000i)
(+5.000000e+000+6.000000e+000i)
(+5.000000e+000+6.000000e+000i)
(+5.000000e+000+6.000000e+000i)
=========== ken/cplx3.go
(+1.292308e+000-1.384615e-001i)
(+1.292308e+000-1.384615e-001i)
64
=========== ken/cplx4.go
c = (-5.000000-6.000000i)
c = (5.000000+6.000000i)
c = (5.000000+6.000000i)
c = (5.000000+6.000000i)
c = (5+6i)
c = (13+7i)
=========== ken/intervar.go =========== ken/intervar.go
print 1 bio 2 file 3 -- abc print 1 bio 2 file 3 -- abc
......
// true // $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
......
// [ $GOARCH != amd64 ] || ($G $D/$F.go && $L $F.$A && ./$A.out) // $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
......
// [ $GOARCH != amd64 ] || ($G $D/$F.go && $L $F.$A && ./$A.out) // $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
......
// true // $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
...@@ -20,7 +20,7 @@ var complexBits = reflect.Typeof(complex(0i)).Size() * 8 ...@@ -20,7 +20,7 @@ var complexBits = reflect.Typeof(complex(0i)).Size() * 8
func main() { func main() {
c0 := C1 c0 := C1
c0 = (c0+c0+c0) / (c0+c0) c0 = (c0+c0+c0) / (c0+c0+3i)
println(c0) println(c0)
c := *(*complex)(unsafe.Pointer(&c0)) c := *(*complex)(unsafe.Pointer(&c0))
......
// true // $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment