Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-4]: src/sys/arch/powerpc/powerpc Pull up revision 1.23 (request...
details: https://anonhg.NetBSD.org/src/rev/a0e302305a12
branches: netbsd-1-4
changeset: 470111:a0e302305a12
user: he <he%NetBSD.org@localhost>
date: Thu Jan 20 21:28:52 2000 +0000
description:
Pull up revision 1.23 (requested by danw):
Add (the beginnings of) an unaligned access handler for the
powerpc, to get around the fact that gcc currently generates bad
floating point copies sometimes, which breaks various things,
diffstat:
sys/arch/powerpc/powerpc/trap.c | 59 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 56 insertions(+), 3 deletions(-)
diffs (84 lines):
diff -r d0cf5e3ab1f3 -r a0e302305a12 sys/arch/powerpc/powerpc/trap.c
--- a/sys/arch/powerpc/powerpc/trap.c Thu Jan 20 21:27:54 2000 +0000
+++ b/sys/arch/powerpc/powerpc/trap.c Thu Jan 20 21:28:52 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.21 1999/03/26 08:32:15 tsubai Exp $ */
+/* $NetBSD: trap.c,v 1.21.2.1 2000/01/20 21:28:52 he Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -62,6 +62,8 @@
volatile int astpending;
volatile int want_resched;
+static int fix_unaligned __P((struct proc *p, struct trapframe *frame));
+
void
trap(frame)
struct trapframe *frame;
@@ -261,8 +263,10 @@
break;
case EXC_ALI|EXC_USER:
-/* XXX temporarily */
- trapsignal(p, SIGBUS, EXC_ALI);
+ if (fix_unaligned(p, frame) != 0)
+ trapsignal(p, SIGBUS, EXC_ALI);
+ else
+ frame->srr0 += 4;
break;
case EXC_PGM|EXC_USER:
@@ -530,3 +534,52 @@
return 0;
}
+
+/*
+ * For now, this only deals with the particular unaligned access case
+ * that gcc tends to generate. Eventually it should handle all of the
+ * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
+ */
+
+static int
+fix_unaligned(p, frame)
+ struct proc *p;
+ struct trapframe *frame;
+{
+ int indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr);
+
+ switch (indicator) {
+ case EXC_ALI_LFD:
+ case EXC_ALI_STFD:
+ {
+ int reg = EXC_ALI_RST(frame->dsisr);
+ double *fpr = &p->p_addr->u_pcb.pcb_fpu.fpr[reg];
+
+ /* Juggle the FPU to ensure that we've initialized
+ * the FPRs, and that their current state is in
+ * the PCB.
+ */
+ if (fpuproc != p) {
+ if (fpuproc)
+ save_fpu(fpuproc);
+ enable_fpu(p);
+ }
+ save_fpu(p);
+
+ if (indicator == EXC_ALI_LFD) {
+ if (copyin((void *)frame->dar, fpr,
+ sizeof(double)) != 0)
+ return -1;
+ enable_fpu(p);
+ } else {
+ if (copyout(fpr, (void *)frame->dar,
+ sizeof(double)) != 0)
+ return -1;
+ }
+ return 0;
+ }
+ break;
+ }
+
+ return -1;
+}
Home |
Main Index |
Thread Index |
Old Index