Module Name: src
Committed By: tsutsui
Date: Sat Oct 15 15:14:30 UTC 2011
Modified Files:
src/sys/arch/m68k/fpe: fpu_emulate.c fpu_emulate.h fpu_hyperb.c
fpu_trig.c
Log Message:
Add hyperboric and trigonometric functions to m68k FPE, written by isaki@.
With these emulations (~4KB text) xeyes on XM6i works better.
Discussed with isaki@ at OSC 2011 Hiroshima.
To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/m68k/fpe/fpu_emulate.c
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/m68k/fpe/fpu_emulate.h
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/m68k/fpe/fpu_hyperb.c \
src/sys/arch/m68k/fpe/fpu_trig.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/m68k/fpe/fpu_emulate.c
diff -u src/sys/arch/m68k/fpe/fpu_emulate.c:1.35 src/sys/arch/m68k/fpe/fpu_emulate.c:1.36
--- src/sys/arch/m68k/fpe/fpu_emulate.c:1.35 Mon Jul 18 14:11:27 2011
+++ src/sys/arch/m68k/fpe/fpu_emulate.c Sat Oct 15 15:14:29 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emulate.c,v 1.35 2011/07/18 14:11:27 isaki Exp $ */
+/* $NetBSD: fpu_emulate.c,v 1.36 2011/10/15 15:14:29 tsutsui Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.35 2011/07/18 14:11:27 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.36 2011/10/15 15:14:29 tsutsui Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -65,7 +65,6 @@ static int fpu_emul_arith(struct fpemu *
static int fpu_emul_type1(struct fpemu *, struct instruction *);
static int fpu_emul_brcc(struct fpemu *, struct instruction *);
static int test_cc(struct fpemu *, int);
-static struct fpn *fpu_cmp(struct fpemu *);
#ifdef DEBUG_FPE
#define DUMP_INSN(insn) \
@@ -494,7 +493,7 @@ fpu_emul_fmovm(struct fpemu *fe, struct
return sig;
}
-static struct fpn *
+struct fpn *
fpu_cmp(struct fpemu *fe)
{
struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
Index: src/sys/arch/m68k/fpe/fpu_emulate.h
diff -u src/sys/arch/m68k/fpe/fpu_emulate.h:1.17 src/sys/arch/m68k/fpe/fpu_emulate.h:1.18
--- src/sys/arch/m68k/fpe/fpu_emulate.h:1.17 Sun Oct 9 01:34:19 2011
+++ src/sys/arch/m68k/fpe/fpu_emulate.h Sat Oct 15 15:14:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emulate.h,v 1.17 2011/10/09 01:34:19 tsutsui Exp $ */
+/* $NetBSD: fpu_emulate.h,v 1.18 2011/10/15 15:14:30 tsutsui Exp $ */
/*
* Copyright (c) 1995 Gordon Ross
@@ -244,6 +244,9 @@ int fpu_emul_fscale(struct fpemu *fe, st
#include "fpu_arith_proto.h"
int fpu_emulate(struct frame *frame, struct fpframe *fpf, ksiginfo_t *ksi);
+struct fpn *fpu_cmp(struct fpemu *);
+
+struct fpn *fpu_sincos_taylor(struct fpemu *, struct fpn *, u_int, int);
/*
* "helper" functions
Index: src/sys/arch/m68k/fpe/fpu_hyperb.c
diff -u src/sys/arch/m68k/fpe/fpu_hyperb.c:1.5 src/sys/arch/m68k/fpe/fpu_hyperb.c:1.6
--- src/sys/arch/m68k/fpe/fpu_hyperb.c:1.5 Mon Jul 18 07:44:30 2011
+++ src/sys/arch/m68k/fpe/fpu_hyperb.c Sat Oct 15 15:14:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_hyperb.c,v 1.5 2011/07/18 07:44:30 isaki Exp $ */
+/* $NetBSD: fpu_hyperb.c,v 1.6 2011/10/15 15:14:30 tsutsui Exp $ */
/*
* Copyright (c) 1995 Ken Nakata
@@ -31,8 +31,33 @@
* @(#)fpu_hyperb.c 10/24/95
*/
+/*
+ * Copyright (c) 2011 Tetsuya Isaki. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_hyperb.c,v 1.5 2011/07/18 07:44:30 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_hyperb.c,v 1.6 2011/10/15 15:14:30 tsutsui Exp $");
#include "fpu_emulate.h"
@@ -52,20 +77,87 @@ fpu_atanh(struct fpemu *fe)
struct fpn *
fpu_cosh(struct fpemu *fe)
{
- /* stub */
+ struct fpn s0;
+ struct fpn *r;
+ int hyperb = 1;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+
+ if (ISINF(&fe->fe_f2)) {
+ fe->fe_f2.fp_sign = 0;
+ return &fe->fe_f2;
+ }
+
+ fpu_const(&s0, 0x32); /* 1.0 */
+ r = fpu_sincos_taylor(fe, &s0, 1, hyperb);
+ CPYFPN(&fe->fe_f2, r);
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
struct fpn *
fpu_sinh(struct fpemu *fe)
{
- /* stub */
+ struct fpn s0;
+ struct fpn *r;
+ int hyperb = 1;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+ if (ISINF(&fe->fe_f2))
+ return &fe->fe_f2;
+
+ CPYFPN(&s0, &fe->fe_f2);
+ r = fpu_sincos_taylor(fe, &s0, 2, hyperb);
+ CPYFPN(&fe->fe_f2, r);
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
struct fpn *
fpu_tanh(struct fpemu *fe)
{
- /* stub */
+ struct fpn x;
+ struct fpn s;
+ struct fpn *r;
+ int sign;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+
+ if (ISINF(&fe->fe_f2)) {
+ sign = fe->fe_f2.fp_sign;
+ fpu_const(&fe->fe_f2, 0x32);
+ fe->fe_f2.fp_sign = sign;
+ return &fe->fe_f2;
+ }
+
+ CPYFPN(&x, &fe->fe_f2);
+
+ /* sinh(x) */
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_sinh(fe);
+ CPYFPN(&s, r);
+
+ /* cosh(x) */
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_cosh(fe);
+ CPYFPN(&fe->fe_f2, r);
+
+ CPYFPN(&fe->fe_f1, &s);
+ r = fpu_div(fe);
+
+ CPYFPN(&fe->fe_f2, r);
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
Index: src/sys/arch/m68k/fpe/fpu_trig.c
diff -u src/sys/arch/m68k/fpe/fpu_trig.c:1.5 src/sys/arch/m68k/fpe/fpu_trig.c:1.6
--- src/sys/arch/m68k/fpe/fpu_trig.c:1.5 Mon Jul 18 07:44:30 2011
+++ src/sys/arch/m68k/fpe/fpu_trig.c Sat Oct 15 15:14:30 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_trig.c,v 1.5 2011/07/18 07:44:30 isaki Exp $ */
+/* $NetBSD: fpu_trig.c,v 1.6 2011/10/15 15:14:30 tsutsui Exp $ */
/*
* Copyright (c) 1995 Ken Nakata
@@ -31,11 +31,39 @@
* @(#)fpu_trig.c 10/24/95
*/
+/*
+ * Copyright (c) 2011 Tetsuya Isaki. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_trig.c,v 1.5 2011/07/18 07:44:30 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_trig.c,v 1.6 2011/10/15 15:14:30 tsutsui Exp $");
#include "fpu_emulate.h"
+static inline struct fpn *fpu_cos_halfpi(struct fpemu *);
+static inline struct fpn *fpu_sin_halfpi(struct fpemu *);
+
struct fpn *
fpu_acos(struct fpemu *fe)
{
@@ -57,30 +85,411 @@ fpu_atan(struct fpemu *fe)
return &fe->fe_f2;
}
+/*
+ * taylor expansion used by sin(), cos(), sinh(), cosh().
+ * hyperb is for sinh(), cosh().
+ */
+struct fpn *
+fpu_sincos_taylor(struct fpemu *fe, struct fpn *s0, u_int f, int hyperb)
+{
+ struct fpn res;
+ struct fpn x2;
+ struct fpn *s1;
+ struct fpn *r;
+ int sign;
+ u_int k;
+
+ /* x2 := x * x */
+ CPYFPN(&fe->fe_f1, &fe->fe_f2);
+ r = fpu_mul(fe);
+ CPYFPN(&x2, r);
+
+ /* res := s0 */
+ CPYFPN(&res, s0);
+
+ sign = 1; /* sign := (-1)^n */
+
+ for (;;) {
+ /* (f1 :=) s0 * x^2 */
+ CPYFPN(&fe->fe_f1, s0);
+ CPYFPN(&fe->fe_f2, &x2);
+ r = fpu_mul(fe);
+ CPYFPN(&fe->fe_f1, r);
+
+ /*
+ * for sin(), s1 := s0 * x^2 / (2n+1)2n
+ * for cos(), s1 := s0 * x^2 / 2n(2n-1)
+ */
+ k = f * (f + 1);
+ fpu_explode(fe, &fe->fe_f2, FTYPE_LNG, &k);
+ s1 = fpu_div(fe);
+
+ /* break if s1 is enough small */
+ if (ISZERO(s1))
+ break;
+ if (res.fp_exp - s1->fp_exp >= FP_NMANT)
+ break;
+
+ /* s0 := s1 for next loop */
+ CPYFPN(s0, s1);
+
+ CPYFPN(&fe->fe_f2, s1);
+ if (!hyperb) {
+ /* (-1)^n */
+ fe->fe_f2.fp_sign = sign;
+ }
+
+ /* res += s1 */
+ CPYFPN(&fe->fe_f1, &res);
+ r = fpu_add(fe);
+ CPYFPN(&res, r);
+
+ f += 2;
+ sign ^= 1;
+ }
+
+ CPYFPN(&fe->fe_f2, &res);
+ return &fe->fe_f2;
+}
+
+/*
+ * inf (-1)^n 2n
+ * cos(x) = \sum { ------ * x }
+ * n=0 2n!
+ *
+ * x^2 x^4 x^6
+ * = 1 - --- + --- - --- + ...
+ * 2! 4! 6!
+ *
+ * = s0 - s1 + s2 - s3 + ...
+ *
+ * x*x x*x x*x
+ * s0 = 1, s1 = ---*s0, s2 = ---*s1, s3 = ---*s2, ...
+ * 1*2 3*4 5*6
+ *
+ * here 0 <= x < pi/2
+ */
+static inline struct fpn *
+fpu_cos_halfpi(struct fpemu *fe)
+{
+ struct fpn s0;
+
+ /* s0 := 1 */
+ fpu_const(&s0, 0x32);
+
+ return fpu_sincos_taylor(fe, &s0, 1, 0);
+}
+
+/*
+ * inf (-1)^n 2n+1
+ * sin(x) = \sum { ------- * x }
+ * n=0 (2n+1)!
+ *
+ * x^3 x^5 x^7
+ * = x - --- + --- - --- + ...
+ * 3! 5! 7!
+ *
+ * = s0 - s1 + s2 - s3 + ...
+ *
+ * x*x x*x x*x
+ * s0 = x, s1 = ---*s0, s2 = ---*s1, s3 = ---*s2, ...
+ * 2*3 4*5 6*7
+ *
+ * here 0 <= x < pi/2
+ */
+static inline struct fpn *
+fpu_sin_halfpi(struct fpemu *fe)
+{
+ struct fpn s0;
+
+ /* s0 := x */
+ CPYFPN(&s0, &fe->fe_f2);
+
+ return fpu_sincos_taylor(fe, &s0, 2, 0);
+}
+
+/*
+ * cos(x):
+ *
+ * if (x < 0) {
+ * x = abs(x);
+ * }
+ * if (x > 2*pi) {
+ * x %= 2*pi;
+ * }
+ * if (x > pi) {
+ * x -= pi;
+ * sign inverse;
+ * }
+ * if (x > pi/2) {
+ * y = sin(x - pi/2);
+ * sign inverse;
+ * } else {
+ * y = cos(x);
+ * }
+ * if (sign) {
+ * y = -y;
+ * }
+ */
struct fpn *
fpu_cos(struct fpemu *fe)
{
- /* stub */
+ struct fpn x;
+ struct fpn p;
+ struct fpn *r;
+ int sign;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+ if (ISINF(&fe->fe_f2))
+ return fpu_newnan(fe);
+
+ CPYFPN(&x, &fe->fe_f2);
+
+ /* x = abs(input) */
+ x.fp_sign = 0;
+ sign = 0;
+
+ /* p <- 2*pi */
+ fpu_const(&p, 0);
+ p.fp_exp++;
+
+ /*
+ * if (x > 2*pi*N)
+ * cos(x) is cos(x - 2*pi*N)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_mod(fe);
+ CPYFPN(&x, r);
+ }
+
+ /* p <- pi */
+ p.fp_exp--;
+
+ /*
+ * if (x > pi)
+ * cos(x) is -cos(x - pi)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ fe->fe_f2.fp_sign = 1;
+ r = fpu_add(fe);
+ CPYFPN(&x, r);
+
+ sign ^= 1;
+ }
+
+ /* p <- pi/2 */
+ p.fp_exp--;
+
+ /*
+ * if (x > pi/2)
+ * cos(x) is -sin(x - pi/2)
+ * else
+ * cos(x)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ fe->fe_f2.fp_sign = 1;
+ r = fpu_add(fe);
+
+ CPYFPN(&fe->fe_f2, r);
+ r = fpu_sin_halfpi(fe);
+ sign ^= 1;
+ } else {
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_cos_halfpi(fe);
+ }
+
+ CPYFPN(&fe->fe_f2, r);
+ fe->fe_f2.fp_sign = sign;
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
+/*
+ * sin(x):
+ *
+ * if (x < 0) {
+ * x = abs(x);
+ * sign = 1;
+ * }
+ * if (x > 2*pi) {
+ * x %= 2*pi;
+ * }
+ * if (x > pi) {
+ * x -= pi;
+ * sign inverse;
+ * }
+ * if (x > pi/2) {
+ * y = cos(x - pi/2);
+ * } else {
+ * y = sin(x);
+ * }
+ * if (sign) {
+ * y = -y;
+ * }
+ */
struct fpn *
fpu_sin(struct fpemu *fe)
{
- /* stub */
+ struct fpn x;
+ struct fpn p;
+ struct fpn *r;
+ int sign;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+ if (ISINF(&fe->fe_f2))
+ return fpu_newnan(fe);
+
+ CPYFPN(&x, &fe->fe_f2);
+
+ /* x = abs(input) */
+ sign = x.fp_sign;
+ x.fp_sign = 0;
+
+ /* p <- 2*pi */
+ fpu_const(&p, 0);
+ p.fp_exp++;
+
+ /*
+ * if (x > 2*pi*N)
+ * sin(x) is sin(x - 2*pi*N)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_mod(fe);
+ CPYFPN(&x, r);
+ }
+
+ /* p <- pi */
+ p.fp_exp--;
+
+ /*
+ * if (x > pi)
+ * sin(x) is -sin(x - pi)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ fe->fe_f2.fp_sign = 1;
+ r = fpu_add(fe);
+ CPYFPN(&x, r);
+
+ sign ^= 1;
+ }
+
+ /* p <- pi/2 */
+ p.fp_exp--;
+
+ /*
+ * if (x > pi/2)
+ * sin(x) is cos(x - pi/2)
+ * else
+ * sin(x)
+ */
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ r = fpu_cmp(fe);
+ if (r->fp_sign == 0) {
+ CPYFPN(&fe->fe_f1, &x);
+ CPYFPN(&fe->fe_f2, &p);
+ fe->fe_f2.fp_sign = 1;
+ r = fpu_add(fe);
+
+ CPYFPN(&fe->fe_f2, r);
+ r = fpu_cos_halfpi(fe);
+ } else {
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_sin_halfpi(fe);
+ }
+
+ CPYFPN(&fe->fe_f2, r);
+ fe->fe_f2.fp_sign = sign;
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
+/*
+ * tan(x) = sin(x) / cos(x)
+ */
struct fpn *
fpu_tan(struct fpemu *fe)
{
- /* stub */
+ struct fpn x;
+ struct fpn s;
+ struct fpn *r;
+
+ fe->fe_fpsr &= ~FPSR_EXCP; /* clear all exceptions */
+
+ if (ISNAN(&fe->fe_f2))
+ return &fe->fe_f2;
+ if (ISINF(&fe->fe_f2))
+ return fpu_newnan(fe);
+
+ CPYFPN(&x, &fe->fe_f2);
+
+ /* sin(x) */
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_sin(fe);
+ CPYFPN(&s, r);
+
+ /* cos(x) */
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_cos(fe);
+ CPYFPN(&fe->fe_f2, r);
+
+ CPYFPN(&fe->fe_f1, &s);
+ r = fpu_div(fe);
+
+ CPYFPN(&fe->fe_f2, r);
+
+ fpu_upd_fpsr(fe, &fe->fe_f2);
return &fe->fe_f2;
}
struct fpn *
fpu_sincos(struct fpemu *fe, int regc)
{
- /* stub */
- return &fe->fe_f2;
+ struct fpn x;
+ struct fpn *r;
+
+ CPYFPN(&x, &fe->fe_f2);
+
+ /* cos(x) */
+ r = fpu_cos(fe);
+ fpu_implode(fe, r, FTYPE_EXT, &fe->fe_fpframe->fpf_regs[regc]);
+
+ /* sin(x) */
+ CPYFPN(&fe->fe_f2, &x);
+ r = fpu_sin(fe);
+ fpu_upd_fpsr(fe, r);
+ return r;
}