kernels/linux-2.4.0/arch/parisc/kernel/traps.c
/* Handle a floating point exception.  Return zero if the faulting
   instruction can be completed successfully. */
Handle a floating point exception.  Return zero if the faulting
instruction can be completed successfully.
Handle a floating point exception . Return zero if the faulting instruction can be completed successfully .
int
handle_fpe(struct pt_regs *regs)
{
	struct siginfo si;
	union {
		struct fpsw {
			unsigned int fv : 1;
			unsigned int fz : 1;
			unsigned int fo : 1;
			unsigned int fu : 1;
			unsigned int fi : 1;
			unsigned int c : 1;
			unsigned int pad1 : 4;
			unsigned int cq : 11;
			unsigned int rm : 2;
			unsigned int pad2 : 2;
			unsigned int t : 1;
			unsigned int d : 1;
			unsigned int ev : 1;
			unsigned int ez : 1;
			unsigned int eo : 1;
			unsigned int eu : 1;
			unsigned int ei : 1;
		} status;
		u32 word;
	} sw;
	struct exc_reg excepts[7];
	unsigned int code = 0;
	unsigned int throw;
	memcpy(&sw, regs->fr, sizeof(sw));
	memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts));
	if (fp_emul_insn(&sw.word, excepts[1], regs) == -1)
		goto send_sigill;
	throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word);
	if (throw == 0)
		goto success; 
	else if (throw & FPSW_V)
		code = FPE_FLTINV;
	else if (throw & FPSW_Z)
		code = FPE_FLTDIV;
	else if (throw & FPSW_O)
		code = FPE_FLTOVF;
	else if (throw & FPSW_U)
		code = FPE_FLTUND;
	else if (throw & FPSW_I)
		code = FPE_FLTRES;
#if 1 
	printk("Unemulated floating point exception, pid=%d (%s)\n",
	       current->pid, current->comm);
	show_regs(regs);
	{
		int i;
		printk("FP Status: %08x\n", sw.word);
		printk("FP Exceptions:\n");
		for (i = 0; i < 7; i++) {
			printk("\tExcept%d: exception %03x insn %06x\n",
			       i, excepts[i].exception, excepts[i].ei);
		}
	}
#endif
	si.si_signo = SIGFPE;
	si.si_errno = 0;
	si.si_code = code;
	si.si_addr = (void *) regs->iaoq[0];
	force_sig_info(SIGFPE, &si, current);
	return -1;
 send_sigill:
	si.si_signo = SIGILL;
	si.si_errno = 0;
	si.si_code = ILL_COPROC;
	si.si_addr = (void *) regs->iaoq[0];
	force_sig_info(SIGILL, &si, current);
	return -1;
 success:
	sw.status.t = 0;
	memset(excepts, 0, sizeof(excepts));
	memcpy(regs->fr, &sw, sizeof(sw));
	memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));
	return 0;
}
int handle_fpe ( struct pt_regs * regs ) { struct siginfo si ; union { struct fpsw { unsigned int fv : 1 ; unsigned int fz : 1 ; unsigned int fo : 1 ; unsigned int fu : 1 ; unsigned int fi : 1 ; unsigned int c : 1 ; unsigned int pad1 : 4 ; unsigned int cq : 11 ; unsigned int rm : 2 ; unsigned int pad2 : 2 ; unsigned int t : 1 ; unsigned int d : 1 ; unsigned int ev : 1 ; unsigned int ez : 1 ; unsigned int eo : 1 ; unsigned int eu : 1 ; unsigned int ei : 1 ; } status ; u32 word ; } sw ; struct exc_reg excepts [ 7 ] ; unsigned int code = 0 ; unsigned int throw ; memcpy ( & sw , regs -> fr , sizeof ( sw ) ) ; memcpy ( excepts , ( ( char * ) regs -> fr ) + 4 , sizeof ( excepts ) ) ; if ( fp_emul_insn ( & sw . word , excepts [ 1 ] , regs ) == -1 ) goto send_sigill ; throw = FPSW_FLAGS ( sw . word ) & FPSW_ENABLE ( sw . word ) ; if ( throw == 0 ) goto success ; else if ( throw & FPSW_V ) code = FPE_FLTINV ; else if ( throw & FPSW_Z ) code = FPE_FLTDIV ; else if ( throw & FPSW_O ) code = FPE_FLTOVF ; else if ( throw & FPSW_U ) code = FPE_FLTUND ; else if ( throw & FPSW_I ) code = FPE_FLTRES ; #if 1 printk ( " \n " , current -> pid , current -> comm ) ; show_regs ( regs ) ; { int i ; printk ( " \n " , sw . word ) ; printk ( " \n " ) ; for ( i = 0 ; i < 7 ; i ++ ) { printk ( " \t \n " , i , excepts [ i ] . exception , excepts [ i ] . ei ) ; } } #endif si . si_signo = SIGFPE ; si . si_errno = 0 ; si . si_code = code ; si . si_addr = ( void * ) regs -> iaoq [ 0 ] ; force_sig_info ( SIGFPE , & si , current ) ; return -1 ; send_sigill : si . si_signo = SIGILL ; si . si_errno = 0 ; si . si_code = ILL_COPROC ; si . si_addr = ( void * ) regs -> iaoq [ 0 ] ; force_sig_info ( SIGILL , & si , current ) ; return -1 ; success : sw . status . t = 0 ; memset ( excepts , 0 , sizeof ( excepts ) ) ; memcpy ( regs -> fr , & sw , sizeof ( sw ) ) ; memcpy ( ( ( char * ) regs -> fr ) + 4 , excepts , sizeof ( excepts ) ) ; return 0 ; }
Handle a floating point exception.
Handle a floating point exception .
/* flag bits */ /* enable bits */ /* Status word = FR0L. */ /* Exception words = FR0R-FR3R. */ /* This is all CPU dependent.  Since there is no public
           documentation on the PA2.0 processors we will just assume
           everything is like the 7100/7100LC/7300LC for now.

	   Specifically: All exceptions are marked as "unimplemented"
	   in the exception word, and the only exception word used is
	   excepts[1]. */ /* Try to emulate the instruction.  Also determine if it is
           really an illegal instruction in the process.

	   FIXME: fp_emul_insn() only checks for the "unimplemented"
	   exceptions at the moment.  So this may break horribly on
	   PA2.0, where we may want to also check to see if we should
	   just send SIGFPE (or maybe not, let's see the documentation
	   first...) */ /* Take the intersection of the flag bits in the FPSW and the
           enable bits in the FPSW. */ /* Concoct an appropriate si_code.  Of course we don't know
           what to do if multiple exceptions were enabled and multiple
           flags were set.  Maybe that's why HP/UX doesn't implement
           feenableexcept(). */ /* Duh. */ /* Debugging... */ /* FIXME: Should we clear the flag bits, T bit, and exception
           registers here? */ /* We absolutely have to clear the T bit and exception
           registers to allow the process to recover.  Otherwise every
           subsequent floating point instruction will trap. */