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