summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2014-07-01 20:26:10 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2014-07-01 20:26:10 +0000
commit82e214d54cc6907774153aa597e4d06f29457bc9 (patch)
tree44f2f840595157aafc9051e99770baeac7eab57b
parent298922e69bd699192a3b91432235af2583312dca (diff)
Replace the assembly 88100 FPU imprecise exception code (mostly triggered by
denormal results) with C code using softfloat to correctly round the inexact results in the best possible way according to the current rounding mode. No functional change intended, and this assembly code was surprisingly almost non-buggy, as opposed to the precise exception code replaced a few weeks ago; still an improvement as this replaces 900 lines of arcane assembly with 90 lines of understandable C code.
-rw-r--r--sys/arch/aviion/conf/Makefile.aviion4
-rw-r--r--sys/arch/luna88k/conf/Makefile.luna88k4
-rw-r--r--sys/arch/m88k/conf/files.m88k3
-rw-r--r--sys/arch/m88k/include/fpu.h13
-rw-r--r--sys/arch/m88k/m88k/m88100_fp.c179
-rw-r--r--sys/arch/m88k/m88k/m88100_fp_imp.S918
-rw-r--r--sys/arch/m88k/m88k/trap.c26
7 files changed, 161 insertions, 986 deletions
diff --git a/sys/arch/aviion/conf/Makefile.aviion b/sys/arch/aviion/conf/Makefile.aviion
index bde4c65043a..186c34d8a55 100644
--- a/sys/arch/aviion/conf/Makefile.aviion
+++ b/sys/arch/aviion/conf/Makefile.aviion
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.aviion,v 1.46 2014/06/09 16:26:32 miod Exp $
+# $OpenBSD: Makefile.aviion,v 1.47 2014/07/01 20:26:09 miod Exp $
# For instructions on building kernels consult the config(8) and options(4)
# manual pages.
@@ -143,7 +143,7 @@ db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl
rm -f db_structinfo.o
locore.o: ${_machdir}/${_mach}/locore.S assym.h
-eh.o m88100_fp_imp.o mutex.o process.o subr.o: assym.h
+eh.o mutex.o process.o subr.o: assym.h
# The install target can be redefined by putting a
# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
diff --git a/sys/arch/luna88k/conf/Makefile.luna88k b/sys/arch/luna88k/conf/Makefile.luna88k
index 22d551e682f..f3e05822b18 100644
--- a/sys/arch/luna88k/conf/Makefile.luna88k
+++ b/sys/arch/luna88k/conf/Makefile.luna88k
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.luna88k,v 1.54 2014/06/09 16:26:32 miod Exp $
+# $OpenBSD: Makefile.luna88k,v 1.55 2014/07/01 20:26:09 miod Exp $
# For instructions on building kernels consult the config(8) and options(4)
# manual pages.
@@ -143,7 +143,7 @@ db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl
rm -f db_structinfo.o
locore.o: ${_machdir}/${_mach}/locore.S assym.h
-eh.o m88100_fp_imp.o mutex.o process.o subr.o: assym.h
+eh.o mutex.o process.o subr.o: assym.h
# The install target can be redefined by putting a
# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
diff --git a/sys/arch/m88k/conf/files.m88k b/sys/arch/m88k/conf/files.m88k
index ee78c974160..6a32e822779 100644
--- a/sys/arch/m88k/conf/files.m88k
+++ b/sys/arch/m88k/conf/files.m88k
@@ -1,4 +1,4 @@
-# $OpenBSD: files.m88k,v 1.27 2014/06/09 16:26:32 miod Exp $
+# $OpenBSD: files.m88k,v 1.28 2014/07/01 20:26:09 miod Exp $
file arch/m88k/m88k/atomic.S multiprocessor
file arch/m88k/m88k/db_disasm.c ddb
@@ -8,7 +8,6 @@ file arch/m88k/m88k/db_trace.c ddb
file arch/m88k/m88k/fpu.c
file arch/m88k/m88k/in_cksum.c inet
file arch/m88k/m88k/m88100_fp.c m88100
-file arch/m88k/m88k/m88100_fp_imp.S m88100
file arch/m88k/m88k/m88100_machdep.c m88100
file arch/m88k/m88k/m88110_fp.c m88110
file arch/m88k/m88k/m88110_mmu.S m88110
diff --git a/sys/arch/m88k/include/fpu.h b/sys/arch/m88k/include/fpu.h
index 1fd6c9e643d..993b14c0d51 100644
--- a/sys/arch/m88k/include/fpu.h
+++ b/sys/arch/m88k/include/fpu.h
@@ -1,7 +1,7 @@
-/* $OpenBSD: fpu.h,v 1.1 2007/12/08 18:39:50 miod Exp $ */
+/* $OpenBSD: fpu.h,v 1.2 2014/07/01 20:26:09 miod Exp $ */
/*
- * Copyright (c) 2007, Miodrag Vallat.
+ * Copyright (c) 2007, 2014, Miodrag Vallat.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -37,4 +37,13 @@
#define FPSR_EFOVF 0x02
#define FPSR_EFINX 0x01
+/* FPIT bits */
+#define FPIT_DBL 0x00000400
+
+/* FPRH bits and masks */
+#define FPRH_SIGN 0x80000000
+#define FPRH_ADDONE 0x02000000
+#define FPRH_MANTH_MASK 0x001fffff
+#define FPRH_MANTH_BITS 21
+
#endif /* _M88K_FPU_H_ */
diff --git a/sys/arch/m88k/m88k/m88100_fp.c b/sys/arch/m88k/m88k/m88100_fp.c
index 9a5d79590d2..374d29a37e6 100644
--- a/sys/arch/m88k/m88k/m88100_fp.c
+++ b/sys/arch/m88k/m88k/m88100_fp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88100_fp.c,v 1.1 2014/06/09 16:26:32 miod Exp $ */
+/* $OpenBSD: m88100_fp.c,v 1.2 2014/07/01 20:26:09 miod Exp $ */
/*
* Copyright (c) 2007, 2014, Miodrag Vallat.
@@ -25,16 +25,21 @@
#include <machine/fpu.h>
#include <machine/frame.h>
+#include <machine/ieee.h>
#include <machine/ieeefp.h>
#include <machine/trap.h>
#include <machine/m88100.h>
#include <lib/libkern/softfloat.h>
+#include <lib/libkern/milieu.h>
+float32 normalizeRoundAndPackFloat32(int, int16, bits32);
+float64 normalizeRoundAndPackFloat64(flag, int16, bits64);
#include <m88k/m88k/fpu.h>
int m88100_fpu_emulate(struct trapframe *);
void m88100_fpu_fetch(struct trapframe *, u_int, u_int, u_int, fparg *);
+void m88100_fpu_checksig(struct trapframe *, int, int);
/*
* All 88100 precise floating-point exceptions are handled there.
@@ -47,14 +52,9 @@ void m88100_fpu_fetch(struct trapframe *, u_int, u_int, u_int, fparg *);
void
m88100_fpu_precise_exception(struct trapframe *frame)
{
- struct proc *p = curproc;
int fault_type;
- vaddr_t fault_addr;
- union sigval sv;
int sig;
- fault_addr = frame->tf_sxip & XIP_ADDR;
-
/* if FPECR_FUNIMP is set, all other bits are undefined, ignore them */
if (ISSET(frame->tf_fpecr, FPECR_FUNIMP))
frame->tf_fpecr = FPECR_FUNIMP;
@@ -76,36 +76,7 @@ m88100_fpu_precise_exception(struct trapframe *frame)
*/
__asm__ volatile ("fstcr %0, %%fcr62" :: "r"(frame->tf_fpsr));
- if (sig != 0) {
- if (sig == SIGILL) {
- if (fault_type == SI_NOINFO)
- fault_type = ILL_ILLOPC;
- } else {
- if (frame->tf_fpecr & FPECR_FIOV)
- fault_type = FPE_FLTSUB;
- else if (frame->tf_fpecr & FPECR_FROP)
- fault_type = FPE_FLTINV;
- else if (frame->tf_fpecr & FPECR_FDVZ)
- fault_type = FPE_INTDIV;
- else if (frame->tf_fpecr & FPECR_FUNF) {
- if (frame->tf_fpsr & FPSR_EFUNF)
- fault_type = FPE_FLTUND;
- else if (frame->tf_fpsr & FPSR_EFINX)
- fault_type = FPE_FLTRES;
- } else if (frame->tf_fpecr & FPECR_FOVF) {
- if (frame->tf_fpsr & FPSR_EFOVF)
- fault_type = FPE_FLTOVF;
- else if (frame->tf_fpsr & FPSR_EFINX)
- fault_type = FPE_FLTRES;
- } else if (frame->tf_fpecr & FPECR_FINX)
- fault_type = FPE_FLTRES;
- }
-
- sv.sival_ptr = (void *)fault_addr;
- KERNEL_LOCK();
- trapsignal(p, sig, 0, fault_type, sv);
- KERNEL_UNLOCK();
- }
+ m88100_fpu_checksig(frame, sig, fault_type);
}
/*
@@ -343,3 +314,139 @@ do_int:
return (rc);
}
+
+/*
+ * All 88100 imprecise floating-point exceptions are handled there.
+ *
+ * We ignore the exception condition bits and simply round the intermediate
+ * result according to the current rounding mode, raising whichever exception
+ * conditions are necessary in the process.
+ */
+
+void
+m88100_fpu_imprecise_exception(struct trapframe *frame)
+{
+ flag sign;
+ int16 exp;
+ bits32 mant32;
+ bits64 mant64;
+ fparg res;
+ u_int fmt;
+
+ /* Reset the exception cause register */
+ __asm__ volatile ("fstcr %r0, %fcr0");
+
+ /*
+ * Pick the inexact result, build a float32 or a float64 out of it, and
+ * normalize it to the destination width.
+ */
+
+ if (frame->tf_fpit & FPIT_DBL)
+ fmt = FTYPE_DBL;
+ else
+ fmt = FTYPE_SNG;
+
+ sign = (frame->tf_fprh & FPRH_SIGN) != 0;
+ exp = ((int32_t)frame->tf_fpit) >> 20; /* signed, unbiaised exponent */
+
+ if (fmt == FTYPE_SNG) {
+ exp += SNG_EXP_BIAS;
+ mant32 = (frame->tf_fprh & FPRH_MANTH_MASK);
+ mant32 <<= (SNG_FRACBITS - FPRH_MANTH_BITS + 1);
+ mant32 |= frame->tf_fprl >> (DBL_FRACBITS - SNG_FRACBITS);
+
+ /*
+ * If the mantissa has been incremented, revert this; but
+ * if doing so causes the mantissa hidden bit to clear,
+ * the exponent needs to be decremented and the hidden bit
+ * restored.
+ */
+ if (frame->tf_fprh & FPRH_ADDONE) {
+ mant32--;
+ if ((mant32 & (1 << SNG_FRACBITS)) == 0) {
+ exp--;
+ mant32 |= 1 << SNG_FRACBITS;
+ }
+ }
+
+ /* normalizeRoundAndPackFloat32() requirement */
+ mant32 <<= (31 - SNG_FRACBITS - 1);
+ res.sng = normalizeRoundAndPackFloat32(sign, exp, mant32);
+ } else {
+ exp += DBL_EXP_BIAS;
+ mant64 = frame->tf_fprh & FPRH_MANTH_MASK;
+ mant64 <<= (DBL_FRACBITS - FPRH_MANTH_BITS + 1);
+ mant64 |= frame->tf_fprl;
+
+ /*
+ * If the mantissa has been incremented, revert this; but
+ * if doing so causes the mantissa hidden bit to clear,
+ * the exponent needs to be decremented and the hidden bit
+ * restored.
+ */
+ if (frame->tf_fprh & FPRH_ADDONE) {
+ mant64--;
+ if ((mant64 & (1LL << DBL_FRACBITS)) == 0) {
+ exp--;
+ mant64 |= 1LL << DBL_FRACBITS;
+ }
+ }
+
+ /* normalizeRoundAndPackFloat64() requirement */
+ mant64 <<= (63 - DBL_FRACBITS - 1);
+ res.dbl = normalizeRoundAndPackFloat64(sign, exp, mant64);
+ }
+
+ fpu_store(frame, frame->tf_fpit & 0x1f, fmt, fmt, &res);
+
+ /*
+ * Update the floating point status register regardless of
+ * whether we'll deliver a signal or not.
+ */
+ __asm__ volatile ("fstcr %0, %%fcr62" :: "r"(frame->tf_fpsr));
+
+ /* Check for a SIGFPE condition */
+ if (frame->tf_fpsr & frame->tf_fpcr)
+ m88100_fpu_checksig(frame, SIGFPE, 0 /* SI_NOINFO */);
+}
+
+/*
+ * Check if a signal needs to be delivered, and send it.
+ */
+void
+m88100_fpu_checksig(struct trapframe *frame, int sig, int fault_type)
+{
+ struct proc *p = curproc;
+ union sigval sv;
+
+ if (sig != 0) {
+ if (sig == SIGILL) {
+ if (fault_type == SI_NOINFO)
+ fault_type = ILL_ILLOPC;
+ } else {
+ if (frame->tf_fpecr & FPECR_FIOV)
+ fault_type = FPE_FLTSUB;
+ else if (frame->tf_fpecr & FPECR_FROP)
+ fault_type = FPE_FLTINV;
+ else if (frame->tf_fpecr & FPECR_FDVZ)
+ fault_type = FPE_INTDIV;
+ else if (frame->tf_fpecr & FPECR_FUNF) {
+ if (frame->tf_fpsr & FPSR_EFUNF)
+ fault_type = FPE_FLTUND;
+ else if (frame->tf_fpsr & FPSR_EFINX)
+ fault_type = FPE_FLTRES;
+ } else if (frame->tf_fpecr & FPECR_FOVF) {
+ if (frame->tf_fpsr & FPSR_EFOVF)
+ fault_type = FPE_FLTOVF;
+ else if (frame->tf_fpsr & FPSR_EFINX)
+ fault_type = FPE_FLTRES;
+ } else if (frame->tf_fpecr & FPECR_FINX)
+ fault_type = FPE_FLTRES;
+ }
+
+ sv.sival_ptr = (void *)(frame->tf_sxip & XIP_ADDR);
+ KERNEL_LOCK();
+ trapsignal(p, sig, 0, fault_type, sv);
+ KERNEL_UNLOCK();
+ }
+}
diff --git a/sys/arch/m88k/m88k/m88100_fp_imp.S b/sys/arch/m88k/m88k/m88100_fp_imp.S
deleted file mode 100644
index ae5fb770a11..00000000000
--- a/sys/arch/m88k/m88k/m88100_fp_imp.S
+++ /dev/null
@@ -1,918 +0,0 @@
-/* $OpenBSD: m88100_fp_imp.S,v 1.1 2014/06/09 10:26:10 miod Exp $ */
-/*
- * Mach Operating System
- * Copyright (c) 1991 Carnegie Mellon University
- * Copyright (c) 1991 OMRON Corporation
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
- * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie the
- * rights to redistribute these changes.
- */
-
-/* Floating point trouble routines */
-#include "assym.h"
-#include <machine/asm.h>
-
-#define destsize 10
-
-/* Floating-Point Status Register bits */
-#define inexact 0
-#define overflow 1
-#define underflow 2
-
-#define sign 31
-
-#define modehi 30
-#define modelo 29
-
-/*
- * Branch to the routine to make a denormalized number.
- */
-ASLOCAL(FPunderflow)
- st %r1, %r31, 0 /* save return address */
- set %r2, %r2, 1<underflow>
- set %r2, %r2, 1<inexact>
-
-/*
- * Now the floating point number, which has an exponent smaller than what
- * IEEE allows, must be denormalized. Denormalization is done by calculating
- * the difference between a denormalized exponent and an underflow exponent
- * and shifting the mantissa by that amount. A one may need to be subtracted
- * from the LSB if a one was added during rounding.
- * %r9 is used to contain the guard, round, sticky, and an inaccuracy bit in
- * case some bits were shifted off the mantissa during denormalization.
- * %r9 will contain:
- * bit 4 -- new addone if one added during rounding after denormalization
- * bit 3 -- inaccuracy flag caused by denormalization or pre-denormalization
- * inexactness
- * bit 2 -- guard bit of result
- * bit 1 -- round bit of result
- * bit 0 -- sticky bit of result
- */
-
-FPU_denorm:
- bb1.n destsize, %r12, Udouble /* denorm for double */
- extu %r9, %r10, 3<26> /* load r9 with grs */
-Usingle:
- mak %r5, %r10, 21<3> /* extract high 21 bits of mantissa */
- extu %r6, %r11, 3<29> /* extract low 3 bits of mantissa */
- or %r11, %r5, %r6 /* form 24 bits of mantissa */
-
-/* See if the addone bit is set and unround if it is. */
- bb0.n 25, %r10, nounrounds /* do not unround if addone bit clear */
- extu %r6, %r12, 12<20> /* extract signed exponent from IMPCR */
-unrounds:
- subu %r11, %r11, 1 /* subtract 1 from mantissa */
-
-/*
- * If the hidden bit is cleared after subtracting the one, then the one added
- * during the rounding must have propagated through the mantissa. The exponent
- * will need to be decremented.
- */
- bb1 23, %r11, nounrounds /* if hidden bit is set, the exponent */
- /* does not need to be decremented */
-decexps:
- sub %r6, %r6, 1 /* decrement exponent */
- set %r11, %r11, 1<23> /* set the hidden bit */
-
-/*
- * For both single and double precision, there are cases where it is easier
- * and quicker to make a special case. Examples of this are if the shift
- * amount is only 1 or 2, or all the mantissa is shifted off, or all the
- * mantissa is shifted off and it is still shifting, or, in the case of
- * doubles, if the shift amount is around the boundary of MANTLO and MANTHI.
- */
-
-nounrounds:
- or %r8, %r0, %lo16(0x00000f81)
- /* load r8 with -127 in decimal */
- /* for lowest 12 bits */
- sub %r7, %r8, %r6 /* find difference between two */
- /* exponents, this amount is the */
- /* shift amount */
- cmp %r6, %r7, 3 /* check to see if r7 contains 3 */
- /* or more */
- bb1 ge, %r6, threesing /* br to code that handles shifts of */
- /* 3 or more */
- cmp %r6, %r7, 2 /* check to see if r7 contains 2 */
- bb1 eq, %r6, twosing /* br to code that handles shifts of */
- /* 2 */
-one:
- rot %r9, %r9, 0<1> /* rotate roundoff register once, */
- /* this places guard in round and */
- /* round in sticky */
- bb0 31, %r9, nosticky1s /* do not or round and sticky if */
- /* sticky is 0, this lost bit will */
- /* be cleared later */
- set %r9, %r9, 1<0> /* or round and sticky */
-nosticky1s:
- bb0 0, %r11, guardclr1s /* do not set guard bit if LSB = 0 */
- set %r9, %r9, 1<2> /* set guard bit */
-guardclr1s:
- extu %r11, %r11, 31<1> /* shift mantissa right 1 */
- br.n round /* round result */
- mak %r9, %r9, 3<0> /* clear bits lost during rotation */
-
-twosing:
- rot %r9, %r9, 0<2> /* rotate roundff register twice, */
- /* this places guard in sticky */
- bb0 30, %r9, nosticky2s /* do not or guard and sticky if */
- /* sticky is 0, this lost bit will be */
- /* cleared later */
- br.n noround2s /* skip or old guard and old round if */
- /* old sticky set */
- set %r9, %r9, 1<0> /* or guard and sticky */
-nosticky2s:
- bb0 31, %r9, noround2s /* do not or guard and round if round */
- /* is 0, this lost bit will be */
- /* cleared later */
- set %r9, %r9, 1<0> /* or guard and round */
-noround2s:
- bb0 0, %r11, roundclr2s /* do not set round bit if LSB = 0 */
- set %r9, %r9, 1<1> /* set round bit */
-roundclr2s:
- bb0 1, %r11, guardclr2s /* do not set guard bit if LSB+1 = 0 */
- set %r9, %r9, 1<2> /* set guard bit */
-guardclr2s:
- extu %r11, %r11, 30<2> /* shift mantissa right 2 */
- br.n round /* round result */
- mak %r9, %r9, 3<0> /* clear bits lost during rotation */
-
-threesing:
- bb1 0, %r9, noguard3s /* check sticky initially */
- /* sticky is set, forget most of the */
- /* oring */
-nosticky3s:
- bb0 1, %r9, noround3s /* check round initially, do not set */
- /* sticky */
- br.n noguard3s /* forget most of the rest of oring */
- set %r9, %r9, 1<0> /* if round is clear, set sticky if */
- /* round set */
-noround3s:
- bb0.n 2, %r9, noguard3s /* check guard initially, do not set */
- /* sticky */
- clr %r9, %r9, 2<1> /* clear the original guard and round */
- /* for when you get to round section */
- set %r9, %r9, 1<0> /* if guard is clear, set sticky if */
- /* guard set */
-noguard3s:
- cmp %r6, %r7, 23 /* check if # of shifts is <=23 */
- bb1 gt, %r6, s24 /* branch to see if shifts = 24 */
- sub %r6, %r7, 2 /* get number of bits to check for */
- /* sticky */
- mak %r6, %r6, 5<5> /* shift width into width field */
- mak %r8, %r11, %r6 /* mask off shifted bits -2 */
- ff1 %r8, %r8 /* see if r8 has any ones */
- bb1 5, %r8, nostky23 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky23:
- or %r8, %r0, 0x22 /* start code to get new mantissa */
- /* plus two extra bits for new round */
- /* and new guard bits */
- subu %r8, %r8, %r7
- mak %r8, %r8, 5<5> /* shift field width into second five */
- /* bits */
- extu %r6, %r6, 5<5> /* shift previous shifted -2 into */
- /* offset field */
- or %r6, %r6, %r8 /* complete field */
- extu %r11, %r11, %r6 /* form new mantissa with two extra */
- /* bits */
-
- bb0 0, %r11, nornd3s /* do not set new round bit */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd3s:
- bb0 1, %r11, nogrd3s /* do not set new guard bit */
- set %r9, %r9, 1<2> /* set new guard bit */
-nogrd3s:
- br.n round /* round mantissa */
- extu %r11, %r11, 30<2> /* shift off remaining two bits */
-
-s24:
- cmp %r6, %r7, 24 /* check to see if # of shifts is 24 */
- bb1 gt, %r6, s25 /* branch to see if shifts = 25 */
- bb1 0, %r9, nostky24 /* skip checking if old sticky set */
- extu %r8, %r11, 22<0> /* prepare to check bits that will be */
- /* shifted into the sticky */
- ff1 %r8, %r8 /* see if there are any 1''s */
- bb1 5, %r8, nostky24 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky24:
- bb0 22, %r11, nornd24 /* do not set new round bit */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd24:
- set %r9, %r9, 1<2> /* set new guard bit, this is hidden */
- /* bit */
- br.n round /* round mantissa */
- or %r11, %r0, %r0 /* clear r11, all of mantissa */
- /* shifted off */
-
-s25:
- cmp %r6, %r7, 25 /* check to see if # of shifts is 25 */
- bb1 gt, %r6, s26 /* branch to execute for shifts => 26 */
- bb1 0, %r9, nostky25 /* skip checking if old sticky set */
- extu %r8, %r11, 23<0> /* prepare to check bits that will be */
- /* shifted into the sticky */
- ff1 %r8, %r8 /* see if there are any 1''s */
- bb1 5, %r8, nostky25 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky25:
- set %r9, %r9, 1<1> /* set new round bit, this is hidden */
- /* bit */
- clr %r9, %r9, 1<2> /* clear guard bit since nothing */
- /* shifted in */
- br.n round /* round and assemble result */
- or %r11, %r0, %r0 /* clear r11, all of mantissa */
- /* shifted off */
-
-s26:
- set %r9, %r9, 1<0> /* set sticky bit, this contains */
- /* hidden bit */
- clr %r9, %r9, 2<1> /* clear guard and round bits since */
- /* nothing shifted in */
- br.n round /* round and assemble result */
- or %r11, %r0, %r0 /* clear mantissa */
-
-Udouble:
- mak %r5, %r10, 21<0> /* extract upper bits of mantissa */
- bb0.n 25, %r10, nounroundd /* do not unround if addone bit clear */
- extu %r6, %r12, 12<20> /* extract signed exponenet from IMPCR */
-unroundd:
- or %r8, %r0, 1
- subu.co %r11, %r11, %r8 /* subtract 1 from mantissa */
- subu.ci %r5, %r5, %r0 /* subtract borrow from upper word */
- bb1 20, %r5, nounroundd /* if hidden bit is set, then */
- /* exponent does not need to be */
- /* decremented */
-decexpd:
- sub %r6, %r6, 1 /* decrement exponent */
- set %r5, %r5, 1<20> /* set the hidden bit */
-
-nounroundd:
- or %r8, %r0, %lo16(0x00000c01)
- /* load r8 with -1023 in decimal */
- /* for lowest 12 bits */
- sub %r7, %r8, %r6 /* find difference between two */
- /* exponents, this amount is the */
- /* shift amount */
- cmp %r6, %r7, 3 /* check to see if r7 contains */
- /* 3 or more */
- bb1 ge, %r6, threedoub /* br to code that handles shifts of */
- /* 3 or more */
- cmp %r6, %r7, 2 /* check to see if r7 contains 2 */
- bb1 eq, %r6, twodoub /* br to code that handles shifts */
- /* of 2 */
-
-onedoub:
- rot %r9, %r9, 0<1> /* rotate roundoff register once, */
- /* this places guard in round and */
- /* round in sticky */
- bb0 31, %r9, nosticky1d /* do not or round and sticky if */
- /* sticky is 0, this lost bit */
- /* will be cleared later */
- set %r9, %r9, 1<0> /* or old round and old sticky into */
- /* new sticky */
-nosticky1d:
- bb0 0, %r11, guardclr1d /* do not set new guard bit */
- /* if old LSB = 0 */
- set %r9, %r9, 1<2> /* set new guard bit */
-guardclr1d:
- extu %r11, %r11, 31<1> /* shift lower mantissa over 1 */
- mak %r6, %r5, 1<31> /* shift off low bit of high mantissa */
- or %r11, %r6, %r11 /* load high bit onto lower mantissa */
- extu %r5, %r5, 20<1> /* shift right once upper 20 bits of */
- /* mantissa */
- br.n round /* round mantissa and assemble result */
- mak %r9, %r9, 3<0> /* clear bits lost during rotation */
-
-twodoub:
- rot %r9, %r9, 0<2> /* rotate roundoff register twice, */
- /* this places old guard into sticky */
- bb0 30, %r9, nosticky2d /* do not or old guard and old sticky */
- /* if old sticky is 0 */
- br.n noround2d /* skip or of old guard and old round */
- /* if old sticky set */
- set %r9, %r9, 1<0> /* or old guard and old sticky into */
- /* new sticky */
-nosticky2d:
- bb0 31, %r9, noround2d /* do not or old guard and old round */
- /* if old round is 0 */
- set %r9, %r9, 1<0> /* or old guard and old round into */
- /* new sticky */
-noround2d:
- bb0 0, %r11, roundclr2d /* do not set round bit */
- /* if old LSB = 0 */
- set %r9, %r9, 1<1> /* set new round bit */
-roundclr2d:
- bb0 1, %r11, guardclr2d /* do not set guard bit */
- /* if old LSB + 1 = 0 */
- set %r9, %r9, 1<2> /* set new guard bit */
-guardclr2d:
- extu %r11, %r11, 30<2> /* shift lower mantissa over 2 */
- mak %r6, %r5, 2<30> /* shift off low bits of high */
- /* mantissa */
- or %r11, %r6, %r11 /* load high bit onto lower mantissa */
- extu %r5, %r5, 19<2> /* shift right twice upper 19 bits of */
- /* mantissa */
- br.n round /* round mantissa and assemble result */
- mak %r9, %r9, 3<0> /* clear bits lost during rotation */
-
-threedoub:
- bb1 0, %r9, noguard3d /* checky sticky initially */
- /* sticky is set, forget most of */
- /* rest of oring */
-nosticky3d:
- bb0 1, %r9, noround3d /* check old round, do not set sticky */
- /* if old round is clear, */
- /* set otherwise */
- br.n noguard3d /* sticky is set, forget most of */
- /* rest of oring */
- set %r9, %r9, 1<0> /* set sticky if old round is set */
-noround3d:
- bb0 2, %r9, noguard3d /* check old guard, do not set sticky */
- /* if 0 */
- clr %r9, %r9, 2<1> /* clear the original guard and round */
- /* for when you get to round section */
- set %r9, %r9, 1<0> /* set sticky if old guard is set */
-noguard3d:
- cmp %r6, %r7, 32 /* do I need to work with a 1 or 2 */
- /* word mantissa when forming sticky, */
- /* round and guard */
- bb1 gt, %r6, d33 /* jump to code that handles 2 word */
- /* mantissas */
- sub %r6, %r7, 2 /* get number of bits to check for */
- /* sticky */
- mak %r6, %r6, 5<5> /* shift width into width field */
- mak %r8, %r11, %r6 /* mask off shifted bits -2 */
- ff1 %r8, %r8 /* see if r8 has any ones */
- bb1 5, %r8, nostky32 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky32:
- or %r8, %r0, 0x22 /* start code to get new mantissa */
- /* plus two extra bits for new round */
- /* and new guard bits, the upper word */
- /* bits will be shifted after the */
- /* round and guard bits are handled */
- subu %r8, %r8, %r7
- mak %r8, %r8, 5<5> /* shift field width into second five */
- /* bits */
- extu %r6, %r6, 5<5> /* shift previous shifted -2 into */
- /* offset field */
- or %r6, %r6, %r8 /* complete bit field */
- extu %r11, %r11, %r6 /* partially form new low mantissa */
- /* with 2 more bits */
- bb0 0, %r11, nornd32d /* do not set new round bit */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd32d:
- bb0 1, %r11, nogrd32d /* do not set new guard bit */
- set %r9, %r9, 1<2> /* set new guard bit */
-nogrd32d:
- extu %r11, %r11, 30<2> /* shift off remaining two bits */
- mak %r6, %r7, 5<5> /* shift field width into second 5 */
- /* bits, if the width is 32, then */
- /* these bits will be 0 */
- or %r8, %r0, 32 /* load word length into r8 */
- sub %r8, %r8, %r7 /* form offset for high bits moved to */
- /* low word */
- or %r6, %r6, %r8 /* form complete bit field */
- mak %r6, %r5, %r6 /* get shifted bits of high word */
- or %r11, %r6, %r11 /* form new low word of mantissa */
- bcnd ne0, %r8, regular33 /* do not adjust for special case */
- /* of r8 containing zeros, which */
- br.n round /* would cause all of the bits to be */
- or %r5, %r0, %r0 /* extracted under the regular method */
-regular33:
- mak %r6, %r7, 5<0> /* place lower 5 bits of shift */
- /* into r6 */
- mak %r8, %r8, 5<5> /* shift r8 into width field */
- or %r6, %r6, %r8 /* form field for shifting of upper */
- /* bits */
- br.n round /* round and assemble result */
- extu %r5, %r5, %r6 /* form new high word mantissa */
-
-d33:
- cmp %r6, %r7, 33 /* is the number of bits to be */
- /* shifted is 33? */
- bb1 gt, %r6, d34 /* check to see if # of bits is 34 */
- bb1 0, %r9, nostky33 /* skip checking if old sticky set */
- mak %r6, %r11, 31<0> /* check bits that will be shifted */
- /* into sticky */
- ff1 %r8, %r8 /* check for ones */
- bb1 5, %r8, nostky33 /* do not set sticky if there are no */
- /* ones */
- set %r9, %r9, 1<0> /* set new sticky bit */
-nostky33:
- bb0 31, %r11, nornd33 /* do not set round if bit is not a 1 */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd33:
- bb0 0, %r5, nogrd33 /* do not set guard bit if bit is not */
- /* a 1 */
- set %r9, %r9, 1<2> /* set new guard bit */
-nogrd33:
- extu %r11, %r5, 31<1> /* shift high bits into low word */
- br.n round /* round and assemble result */
- or %r5, %r0, %r0 /* clear high word */
-
-d34:
- cmp %r6, %r7, 34 /* is the number of bits to be */
- /* shifted 34? */
- bb1 gt, %r6, d35 /* check to see if # of bits is >= 35 */
- bb1 0, %r9, nostky34 /* skip checking if old sticky set */
- ff1 %r8, %r11 /* check bits that will be shifted */
- /* into sticky */
- bb1 5, %r8, nostky34 /* do not set sticky if there are no */
- /* ones */
- set %r9, %r9, 1<0> /* set new sticky bit */
-nostky34:
- bb0 0, %r5, nornd34 /* do not set round if bit is not a 1 */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd34:
- bb0 1, %r5, nogrd34 /* do not set guard bit if bit is not */
- /* a 1 */
- set %r9, %r9, 1<2> /* set new guard bit */
-nogrd34:
- extu %r11, %r5, 30<2> /* shift high bits into low word */
- br.n round /* round and assemble result */
- or %r5, %r0, %r0 /* clear high word */
-
-d35:
- cmp %r6, %r7, 52 /* see if # of shifts is */
- /* 35 <= X <= 52 */
- bb1 gt, %r6, d53 /* check to see if # of shifts is 52 */
- bb1.n 0, %r9, nostky35 /* skip checking if old sticky set */
- sub %r7, %r7, 34 /* subtract 32 from # of shifts */
- /* so that operations can be done on */
- /* the upper word, and then subtract */
- /* two more checking guard and */
- /* sticky bits */
- ff1 %r8, %r11 /* see if lower word has a bit for */
- /* sticky */
- bb1 5, %r8, stkycheck35 /* see if upper word has any sticky */
- /* bits */
- br.n nostky35 /* quit checking for sticky */
- set %r9, %r9, 1<0> /* set sticky bit */
-stkycheck35:
- mak %r6, %r7, 5<5> /* place width into width field */
- mak %r8, %r5, %r6 /* mask off shifted bits - 2 */
- ff1 %r8, %r8 /* see if r8 has any ones */
- bb1 5, %r8, nostky35 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky35:
- or %r8, %r0, 32 /* look at what does not get shifted */
- /* off plus round and sticky, */
- /* remember that the r7 value was */
- /* adjusted so that it did not */
- /* include new round or new sticky in */
- /* shifted off bits */
- subu %r8, %r8, %r7 /* complement width */
- mak %r8, %r8, 5<5> /* shift width into width field */
- or %r8, %r7, %r8 /* add offset field */
- extu %r11, %r5, %r8 /* extract upper bits into low word */
- bb0 0, %r11, nornd35 /* do not set new round bit */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd35:
- bb0 1, %r11, nogrd35 /* do not set new guard bit */
- set %r9, %r9, 1<2> /* set new guard bit */
-nogrd35:
- extu %r11, %r11, 30<2> /* shift off remaining guard and round bits */
- br.n round /* round and assemble result */
- or %r5, %r0, %r0 /* clear high word */
-
-d53:
- cmp %r6, %r7, 53 /* check to see if # of shifts is 53 */
- bb1 gt, %r6, d54 /* branch to see if shifts = 54 */
- bb1 0, %r9, nostky53 /* skip checking if old sticky set */
- ff1 %r8, %r11 /* see if lower word has a bit for */
- /* sticky */
- bb1 5, %r8, stkycheck53 /* see if upper word has any sticky */
- /* bits */
- br.n nostky53 /* quit checking for sticky */
- set %r9, %r9, 1<0> /* set sticky bit */
-stkycheck53:
- mak %r6, %r5, 19<0> /* check bits that are shifted into */
- /* sticky */
- ff1 %r8, %r6 /* see if r6 has any ones */
- bb1 5, %r8, nostky53 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky53:
- bb0 19, %r5, nornd53 /* do not set new round bit */
- set %r9, %r9, 1<1> /* set new round bit */
-nornd53:
- set %r9, %r9, 1<2> /* set new guard bit, this is hidden */
- /* bit */
- or %r5, %r0, %r0 /* clear high word */
- br.n round /* round and assemble result */
- or %r11, %r0, %r0 /* clear low word */
-
-d54:
- cmp %r6, %r7, 54 /* check to see if # of shifts is 54 */
- bb1 gt, %r6, d55 /* branch to execute for shifts =>55 */
- bb1 0, %r9, nostky54 /* skip checking if old sticky set */
- ff1 %r8, %r11 /* see if lower word has a bit for */
- /* sticky */
- bb1 5, %r8, stkycheck54 /* see if upper word has any sticky */
- /* bits */
- br.n nostky54 /* quit checking for sticky */
- set %r9, %r9, 1<0> /* set sticky bit */
-stkycheck54:
- mak %r6, %r5, 20<0> /* check bits that are shifted into */
- /* sticky */
- ff1 %r8, %r6 /* see if r6 has any ones */
- bb1 5, %r8, nostky54 /* do not set sticky if no ones found */
- set %r9, %r9, 1<0> /* set sticky bit */
-nostky54:
- set %r9, %r9, 1<1> /* set new round bit, this is hidden */
- /* bit */
- clr %r9, %r9, 1<2> /* clear guard bit since nothing */
- /* shifted in */
- or %r5, %r0, %r0 /* clear high word */
- br.n round /* round and assemble result */
- or %r11, %r0, %r0 /* clear low word */
-
-d55:
- set %r9, %r9, 1<0> /* set new sticky bit, this contains */
- /* hidden bit */
- clr %r9, %r9, 2<1> /* clear guard and round bits since */
- /* nothing shifted in */
- or %r5, %r0, %r0 /* clear high word */
- or %r11, %r0, %r0 /* clear low word */
-
-
-/*
- * The first item that the rounding code does is see if either guard, round,
- * or sticky is set. If all are clear, then there is no denormalization loss
- * and no need to round, then branch to assemble answer.
- * For rounding, a branch table is set up. The left two most bits are the
- * rounding mode. The third bit is either the LSB of the mantissa or the
- * sign bit, depending on the rounding mode. The three LSB''s are the guard,
- * round and sticky bits.
- */
-
-round:
- ff1 %r8, %r9 /* see if there is denormalization */
- /* loss */
- bb1 5, %r8, assemble /* no denormalization loss or */
- /* inexactness */
- extu %r6, %r10, 2<modelo> /* extract rounding mode */
- bb1.n modehi, %r10, signext /* use sign bit instead of LSB */
- mak %r6, %r6, 2<4> /* shift over rounding mode */
- extu %r7, %r11, 1<0> /* extract LSB */
- br.n grs /* skip sign extraction */
- mak %r7, %r7, 1<3> /* shift over LSB */
-signext:
- extu %r7, %r10, 1<31> /* extract sign bit */
- mak %r7, %r7, 1<3> /* shift sign bit over */
-grs:
- or %r6, %r6, %r7
- or %r6, %r6, %r9 /* or in guard, round, and sticky */
- or.u %r1, %r0, %hi16(roundtable) /* form address of branch table */
- or %r1, %r1, %lo16(roundtable)
- lda %r6, %r1[%r6] /* scale offset into branch table */
- jmp.n %r6 /* jump to branch table */
- set %r9, %r9, 1<3> /* set inexact flag in r9 */
-
-roundtable:
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br addone
- br addone
- br addone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br addone
- br addone
- br addone
- br addone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br addone
- br addone
- br addone
- br addone
- br addone
- br addone
- br addone
- br noaddone
- br addone
- br addone
- br addone
- br addone
- br addone
- br addone
- br addone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
- br noaddone
-
-/* Round by adding a one to the LSB of the mantissa. */
-addone:
- or %r6, %r0, 1 /* load a 1 into r6 so that add.co */
- /* can be used */
- add.co %r11, %r11, %r6 /* add a one to the lower word of */
- /* result */
- bb0.n destsize, %r12, noaddone/* single result, forget carry */
- set %r9, %r9, 1<4> /* indicate that a 1 has been added */
- add.ci %r5, %r5, %r0 /* propagate carry into high word */
-
-noaddone:
- set %r2, %r2, 1<inexact>
- set %r2, %r2, 1<underflow>
-
-/*
- * Assemble the result of the denormalization routine for writeback to the
- * destination register. The exponent of a denormalized number is zero,
- * so simply assemble the sign and the new mantissa.
- */
-
-assemble:
- bb1 destsize, %r12, doubassem /* assemble double result */
- bb0 sign, %r10, exassems /* exit assemble if sign is */
- /* zero */
- set %r11, %r11, 1<sign> /* make result negative */
-exassems:
- br Ureturn
-
-doubassem:
- bb0.n sign, %r10, signclr /* do not set sign in r10 */
- or %r10, %r5, %r0 /* load high word from r5 */
- /* into r10 */
- set %r10, %r10, 1<sign> /* high word with sign loaded */
-signclr:
- /* FALLTHROUGH */
- /* br Ureturn */
-
-/* Return to fpui. */
-Ureturn:
- ld %r1, %r31, 0 /* load return address */
- jmp %r1
-
-/*
- * FPoverflow
- */
-
-ASLOCAL(FPoverflow)
- st %r1, %r31, 0 /* save return address */
- set %r2, %r2, 1<overflow>
- set %r2, %r2, 1<inexact>
-
-/* Determine which rounding mode to use for the default procedure. */
-
- bb1 modehi, %r10, signed /* mode is either round */
- /* toward pos. or neg. */
- bb0 modelo, %r10, OFnearest /* rounding mode is round */
- /* nearest */
- br OFzero /* rounding mode is round */
- /* zero */
-signed:
- bb0 modelo, %r10, OFnegative /* rounding mode is round */
- /* negative */
- br positive /* rounding mode is round */
- /* positive */
-
-/*
- * In the round toward nearest mode, positive values are rounded to
- * positive infinity and negative values are loaded toward negative infinity.
- * The value for single or double precision is loaded from a data table.
- */
-
-OFnearest:
- bb1.n destsize, %r12, neardouble /* branch to neardouble of */
- /* double result */
- mask.u %r5, %r10, 0x8000 /* mask off sign bit from */
- /* MANTHI */
- or.u %r11, %r0, %hi16(0x7f800000) /* load single infinity */
- /* constant */
- or %r11, %r11, %lo16(0x7f800000)
- br.n FPof_return /* return with result */
- or %r11, %r5, %r11 /* adjust sign */
-neardouble:
- or %r11, %r0, %r0 /* load lower word of double */
- /* infinity */
- or.u %r10, %r0, %hi16(0x7ff00000) /* load upper word of double */
- /* infinity */
- or %r10, %r10, %lo16(0x7ff00000)
- br.n FPof_return /* return with result */
- or %r10, %r5, %r10 /* adjust sign */
-
-/*
- * In the round toward zero mode, positive values are rounded to the largest
- * postive finite number and negative values are rounded toward the largest
- * negative finite number.
- * The value for single or double precision is loaded from a data table.
- */
-
-OFzero:
- bb1.n destsize, %r12, zerodouble /* branch to zerodouble of */
- /* double result */
- mask.u %r5, %r10, 0x8000 /* mask off sign bit from */
- /* MANTHI */
- or.u %r11, %r0, %hi16(0x7f7fffff) /* load single finite number */
- /* constant */
- or %r11, %r11, %lo16(0x7f7fffff)
- br.n FPof_return /* return with result */
- or %r11, %r5, %r11 /* adjust sign */
-zerodouble:
- set %r11, %r0, 0<0> /* load lower word of double */
- /* finite number */
- or.u %r10, %r0, %hi16(0x7fefffff) /* load upper word of double */
- /* finite number */
- or %r10, %r10, %lo16(0x7fefffff)
- br.n FPof_return /* return with result */
- or %r10, %r5, %r10 /* adjust sign */
-
-/*
- * In the round toward positve mode, positive values are rounded to
- * postive infinity and negative values are loaded toward the largest
- * negative finite number.
- * The value for single or double precision is loaded from a data table.
- */
-
-positive:
- bb1 destsize, %r12, posdouble /* branch to section for */
- /* double result */
-possingle:
- bb1 sign, %r10, possingleneg /* branch to section for */
- /* negatives */
-possinglepos:
- or.u %r11, %r0, %hi16(0x7f800000) /* load single infinity */
- /* constant */
- br.n FPof_return /* return with result */
- or %r11, %r11, %lo16(0x7f800000)
-possingleneg:
- or.u %r11, %r0, %hi16(0x7f7fffff) /* load single finite number */
- /* constant */
- or %r11, %r11, %lo16(0x7f7fffff)
- br.n FPof_return /* return with result */
- set %r11, %r11, 1<sign> /* set sign for negative */
-posdouble:
- bb1 sign, %r10, posdoubleneg /* branch to negative double */
- /* results */
-posdoublepos:
- or %r11, %r0, %r0 /* load lower word of double */
- /* infinity */
- or.u %r10, %r0, %hi16(0x7ff00000) /* load upper word of double */
- /* infinity */
- br.n FPof_return /* return with result */
- or %r10, %r10, %lo16(0x7ff00000)
-posdoubleneg:
- set %r11, %r0, 0<0> /* load lower word of finite */
- /* number */
- or.u %r10, %r0, %hi16(0x7fefffff) /* load upper word of finite */
- /* number */
- or %r10, %r10, %lo16(0x7fefffff)
- br.n FPof_return /* return with result */
- set %r10, %r10, 1<sign> /* set sign for negative */
-
-/*
- * In the round toward negative mode, positive values are rounded to the
- * largest postive finite number and negative values are rounded to negative
- * infinity.
- * The value for single or double precision is loaded from a data table.
- */
-
-OFnegative:
- bb1 destsize, %r12, negdouble /* branch to section for */
- /* double result */
-negsingle:
- bb1 sign, %r10, negsingleneg /* branch to section for */
- /* negatives */
-negsinglepos:
- or.u %r11, %r0, %hi16(0x7f7fffff) /* load single finite number */
- /* constant */
- br.n FPof_return /* return with result */
- or %r11, %r11, %lo16(0x7f7fffff)
-negsingleneg:
- or.u %r11, %r0, %hi16(0x7f800000) /* load single infinity */
- /* constant */
- or %r11, %r11, %lo16(0x7f800000)
- br.n FPof_return /* return with result */
- set %r11, %r11, 1<sign> /* set sign for negative */
-negdouble:
- bb1 sign, %r10, negdoubleneg /* branch to negative double */
- /* results */
-negdoublepos:
- set %r11, %r0, 0<0> /* load lower word of finite */
- /* number */
- or.u %r10, %r0, %hi16(0x7fefffff) /* load upper word of finite */
- /* number */
- br.n FPof_return /* return with result */
- or %r10, %r10, %lo16(0x7fefffff)
-negdoubleneg:
- or %r11, %r0, %r0 /* load lower word of double */
- /* infinity */
- or.u %r10, %r0, %hi16(0x7ff00000) /* load upper word of double */
- /* infinity */
- or %r10, %r10, %lo16(0x7ff00000)
- set %r10, %r10, 1<sign> /* set sign for negative */
-
-FPof_return:
- ld %r1, %r31, 0 /* load return address */
- jmp %r1
-
-ENTRY(m88100_fpu_imprecise_exception)
- or %r29, %r2, %r0 /* r29 is now the E.F. */
- subu %r31, %r31, 16
- st %r1, %r31, 4
- st %r29, %r31, 8
-
- ld %r2 , %r29, EF_FPSR
- ld %r3 , %r29, EF_FPCR
- ld %r4 , %r29, EF_FPECR
- ld %r10, %r29, EF_FPRH
- ld %r11, %r29, EF_FPRL
- ld %r12, %r29, EF_FPIT
-
-/*
- * Load into r1 the return address for the exception handlers. Looking
- * at FPECR, branch to the appropriate exception handler.
- */
-
- or.u %r1, %r0, %hi16(fpui_wrapup) /* load return address of */
- or %r1, %r1, %lo16(fpui_wrapup) /* functions */
-
- bb0 2, %r4, 2f /* branch to FPunderflow if */
- br _ASM_LABEL(FPunderflow) /* bit set */
-2:
- bb0 1, %r4, 3f /* branch to FPoverflow if */
- br _ASM_LABEL(FPoverflow) /* bit set */
-3:
- /* XXX handle inexact!!! */
-
-fpui_wrapup:
- FLUSH_PIPELINE /* make sure all floating */
- /* point operations have */
- /* finished */
- ldcr %r4, %cr1 /* load the PSR */
-#if 0
- set %r4, %r4, 1<PSR_FPU_DISABLE_BIT>
-#endif
- set %r4, %r4, 1<PSR_INTERRUPT_DISABLE_BIT>
- stcr %r4, %cr1
- ld %r1, %r31, 4
- ld %r29, %r31, 8
- addu %r31, %r31, 16
-
- fstcr %r2, FPSR /* write revised value of FPSR... */
- fstcr %r3, FPCR /* ...and FPCR... */
- st %r2, %r29, EF_FPSR /* ...into the trapframe as well */
- st %r3, %r29, EF_FPCR
-
- /* write back the results */
- extu %r2, %r12, 5<0>
- bb0.n destsize, %r12, Iwritesingle
- addu %r3, %r29, EF_R0
- st %r10, %r3[%r2]
- addu %r2, %r2, 1
- clr %r2, %r2, 27<5>
-Iwritesingle:
- jmp.n %r1
- st %r11, %r3[%r2]
diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c
index 0e1dec19918..5d2ebe03784 100644
--- a/sys/arch/m88k/m88k/trap.c
+++ b/sys/arch/m88k/m88k/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.98 2014/06/09 16:26:32 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.99 2014/07/01 20:26:09 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* Copyright (c) 1998 Steve Murphree, Jr.
@@ -509,29 +509,7 @@ user_fault:
goto userexit;
case T_FPEIFLT+T_USER:
m88100_fpu_imprecise_exception(frame);
- /* Check for a SIGFPE condition */
- if (frame->tf_fpsr & frame->tf_fpcr) {
- sig = SIGFPE;
- if (frame->tf_fpecr & FPECR_FIOV)
- fault_type = FPE_FLTSUB;
- else if (frame->tf_fpecr & FPECR_FROP)
- fault_type = FPE_FLTINV;
- else if (frame->tf_fpecr & FPECR_FDVZ)
- fault_type = FPE_INTDIV;
- else if (frame->tf_fpecr & FPECR_FUNF) {
- if (frame->tf_fpsr & FPSR_EFUNF)
- fault_type = FPE_FLTUND;
- else if (frame->tf_fpsr & FPSR_EFINX)
- fault_type = FPE_FLTRES;
- } else if (frame->tf_fpecr & FPECR_FOVF) {
- if (frame->tf_fpsr & FPSR_EFOVF)
- fault_type = FPE_FLTOVF;
- else if (frame->tf_fpsr & FPSR_EFINX)
- fault_type = FPE_FLTRES;
- } else if (frame->tf_fpecr & FPECR_FINX)
- fault_type = FPE_FLTRES;
- }
- break;
+ goto userexit;
case T_SIGSYS+T_USER:
sig = SIGSYS;
break;