patch-2.3.35 linux/arch/sparc64/kernel/traps.c

Next file: linux/arch/sparc64/kernel/ttable.S
Previous file: linux/arch/sparc64/kernel/trampoline.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.62 1999/08/31 19:25:35 davem Exp $
+/* $Id: traps.c,v 1.64 1999/12/19 23:53:13 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller ([email protected])
@@ -26,6 +26,7 @@
 #include <asm/uaccess.h>
 #include <asm/fpumacro.h>
 #include <asm/lsu.h>
+#include <asm/psrcompat.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -519,8 +520,22 @@
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	} else {
+		unsigned long fsr = current->thread.xfsr[0];
+
 		current->thread.sig_address = regs->tpc;
 		current->thread.sig_desc = SUBSIG_FPERROR;
+		if ((fsr & 0x1c000) == (1 << 14)) {
+			if (fsr & 0x01)
+				current->thread.sig_desc = SUBSIG_FPINEXACT;
+			else if (fsr & 0x02)
+				current->thread.sig_desc = SUBSIG_FPDIVZERO;
+			else if (fsr & 0x04)
+				current->thread.sig_desc = SUBSIG_FPUNFLOW;
+			else if (fsr & 0x08)
+				current->thread.sig_desc = SUBSIG_FPOVFLOW;
+			else if (fsr & 0x10)
+				current->thread.sig_desc = SUBSIG_FPINTOVFL;
+		}
 		send_sig(SIGFPE, current, 1);
 	}
 }
@@ -564,7 +579,9 @@
 
 void do_div0(struct pt_regs *regs)
 {
-	send_sig(SIGILL, current, 1);
+	current->thread.sig_address = regs->tpc;
+	current->thread.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 void instruction_dump (unsigned int *pc)
@@ -712,10 +729,12 @@
 	send_sig(SIGILL, current, 1);
 }
 
-void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
+void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
+		       unsigned long npc, unsigned long psr)
 {
-	send_sig(SIGILL, current, 1);
+	current->thread.sig_address = regs->tpc;
+	current->thread.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 /* Trap level 1 stuff or other traps we should never see... */
@@ -841,6 +860,13 @@
 #endif
 }
 #endif
+
+void do_getpsr(struct pt_regs *regs)
+{
+	regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
+	regs->tpc   = regs->tnpc;
+	regs->tnpc += 4;
+}
 
 void trap_init(void)
 {

FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])