Module Name: src Committed By: isaki Date: Fri Apr 19 13:57:53 UTC 2013
Modified Files: src/sys/arch/m68k/fpe: fpu_trig.c Log Message: Implement inverse trigonometric functions (i.e., FACOS, FASIN, FATAN instructions). o arccos is calculated using arcsin. o arcsin is calculated using arctan. o arctan is calculated by the CORDIC. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 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_trig.c diff -u src/sys/arch/m68k/fpe/fpu_trig.c:1.11 src/sys/arch/m68k/fpe/fpu_trig.c:1.12 --- src/sys/arch/m68k/fpe/fpu_trig.c:1.11 Fri Apr 19 13:31:11 2013 +++ src/sys/arch/m68k/fpe/fpu_trig.c Fri Apr 19 13:57:52 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_trig.c,v 1.11 2013/04/19 13:31:11 isaki Exp $ */ +/* $NetBSD: fpu_trig.c,v 1.12 2013/04/19 13:57:52 isaki Exp $ */ /* * Copyright (c) 1995 Ken Nakata @@ -57,28 +57,120 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fpu_trig.c,v 1.11 2013/04/19 13:31:11 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu_trig.c,v 1.12 2013/04/19 13:57:52 isaki Exp $"); #include "fpu_emulate.h" +/* + * arccos(x) = pi/2 - arcsin(x) + */ struct fpn * fpu_acos(struct fpemu *fe) { - /* stub */ - return &fe->fe_f2; + struct fpn *r; + + if (ISNAN(&fe->fe_f2)) + return &fe->fe_f2; + if (ISINF(&fe->fe_f2)) + return fpu_newnan(fe); + + r = fpu_asin(fe); + CPYFPN(&fe->fe_f2, r); + + /* pi/2 - asin(x) */ + fpu_const(&fe->fe_f1, FPU_CONST_PI); + fe->fe_f1.fp_exp--; + fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; + r = fpu_add(fe); + + return r; } +/* + * x + * arcsin(x) = arctan(---------------) + * sqrt(1 - x^2) + */ struct fpn * fpu_asin(struct fpemu *fe) { - /* stub */ - return &fe->fe_f2; + struct fpn x; + struct fpn *r; + + if (ISNAN(&fe->fe_f2)) + return &fe->fe_f2; + if (ISZERO(&fe->fe_f2)) + return &fe->fe_f2; + + if (ISINF(&fe->fe_f2)) + return fpu_newnan(fe); + + CPYFPN(&x, &fe->fe_f2); + + /* x^2 */ + CPYFPN(&fe->fe_f1, &fe->fe_f2); + r = fpu_mul(fe); + + /* 1 - x^2 */ + CPYFPN(&fe->fe_f2, r); + fe->fe_f2.fp_sign = 1; + fpu_const(&fe->fe_f1, FPU_CONST_1); + r = fpu_add(fe); + + /* sqrt(1-x^2) */ + CPYFPN(&fe->fe_f2, r); + r = fpu_sqrt(fe); + + /* x/sqrt */ + CPYFPN(&fe->fe_f2, r); + CPYFPN(&fe->fe_f1, &x); + r = fpu_div(fe); + + /* arctan */ + CPYFPN(&fe->fe_f2, r); + return fpu_atan(fe); } +/* + * arctan(x): + * + * if (x < 0) { + * x = abs(x); + * sign = 1; + * } + * y = arctan(x); + * if (sign) { + * y = -y; + * } + */ struct fpn * fpu_atan(struct fpemu *fe) { - /* stub */ + struct fpn a; + struct fpn x; + struct fpn v; + + if (ISNAN(&fe->fe_f2)) + return &fe->fe_f2; + if (ISZERO(&fe->fe_f2)) + return &fe->fe_f2; + + CPYFPN(&a, &fe->fe_f2); + + if (ISINF(&fe->fe_f2)) { + /* f2 <- pi/2 */ + fpu_const(&fe->fe_f2, FPU_CONST_PI); + fe->fe_f2.fp_exp--; + + fe->fe_f2.fp_sign = a.fp_sign; + return &fe->fe_f2; + } + + fpu_const(&x, FPU_CONST_1); + fpu_const(&fe->fe_f2, FPU_CONST_0); + CPYFPN(&v, &fe->fe_f2); + fpu_cordit1(fe, &x, &a, &fe->fe_f2, &v); + return &fe->fe_f2; }