* $NetBSD: netbsd.sa,v 1.5 2001/10/02 06:34:52 chs Exp $ * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP * M68000 Hi-Performance Microprocessor Division * M68040 Software Package * * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. * All rights reserved. * * THE SOFTWARE is provided on an "AS IS" basis and without warranty. * To the maximum extent permitted by applicable law, * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A * PARTICULAR PURPOSE and any warranty against infringement with * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) * and any accompanying written materials. * * To the maximum extent permitted by applicable law, * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE * SOFTWARE. Motorola assumes no responsibility for the maintenance * and support of the SOFTWARE. * * You are hereby granted a copyright license to use, modify, and * distribute the SOFTWARE so long as this entire notice is retained * without alteration in any modified and/or redistributed versions, * and that such modified versions are clearly identified as such. * No licenses are granted by implication, estoppel or otherwise * under any patents or trademarks of Motorola, Inc. * * skeleton.sa 3.2 4/26/91 * * This file contains code that is system dependent and will * need to be modified to install the FPSP. * * Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. * Put any target system specific handling that must be done immediately * before the jump instruction. If there no handling necessary, then * the 'fpsp_xxxx' handler entry point should be placed in the exception * table so that the 'jmp' can be eliminated. If the FPSP determines that the * exception is one that must be reported then there will be a * return from the package by a 'jmp real_xxxx'. At that point * the machine state will be identical to the state before * the FPSP was entered. In particular, whatever condition * that caused the exception will still be pending when the FPSP * package returns. Thus, there will be system specific code * to handle the exception. * * If the exception was completely handled by the package, then * the return will be via a 'jmp fpsp_done'. Unless there is * OS specific work to be done (such as handling a context switch or * interrupt) the user program can be resumed via 'rte'. * * In the following skeleton code, some typical 'real_xxxx' handling * code is shown. This code may need to be moved to an appropriate * place in the target system, or rewritten. * SKELETON IDNT 2,1 Motorola 040 Floating Point Software Package section 15 * * The following counters are used for standalone testing * section 8 include fpsp.h * * XXX Note, this is NOT valid Motorola syntax, but what else can we do? * #include xref b1238_fix xref _C_LABEL(mmutype) * * Divide by Zero exception * * All dz exceptions are 'real', hence no fpsp_dz entry point. * xdef dz xdef real_dz dz: cmp.l #-2,_C_LABEL(mmutype) bne.l _C_LABEL(fpfault) real_dz: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E1,E_BYTE(a6) frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Inexact exception * * All inexact exceptions are real, but the 'real' handler * will probably want to clear the pending exception. * The provided code will clear the E3 exception (if pending), * otherwise clear the E1 exception. The frestore is not really * necessary for E1 exceptions. * * Code following the 'inex' label is to handle bug #1232. In this * bug, if an E1 snan, ovfl, or unfl occurred, and the process was * swapped out before taking the exception, the exception taken on * return was inex, rather than the correct exception. The snan, ovfl, * and unfl exception to be taken must not have been enabled. The * fix is to check for E1, and the existence of one of snan, ovfl, * or unfl bits set in the fpsr. If any of these are set, branch * to the appropriate handler for the exception in the fpsr. Note * that this fix is only for d43b parts, and is skipped if the * version number is not $40. * * xdef real_inex xdef inex inex: cmp.l #-2,_C_LABEL(mmutype) bne.l _C_LABEL(fpfault) link a6,#-LOCAL_SIZE fsave -(sp) cmpi.b #VER_40,(sp) ;test version number bne.b not_fmt40 fmove.l fpsr,-(sp) btst.b #E1,E_BYTE(a6) ;test for E1 set beq.b not_b1232 btst.b #snan_bit,2(sp) ;test for snan beq inex_ckofl addq.l #4,sp frestore (sp)+ unlk a6 bra snan inex_ckofl: btst.b #ovfl_bit,2(sp) ;test for ovfl beq inex_ckufl addq.l #4,sp frestore (sp)+ unlk a6 bra ovfl inex_ckufl: btst.b #unfl_bit,2(sp) ;test for unfl beq not_b1232 addq.l #4,sp frestore (sp)+ unlk a6 bra unfl * * We do not have the bug 1232 case. Clean up the stack and call * real_inex. * not_b1232: addq.l #4,sp frestore (sp)+ unlk a6 real_inex: link a6,#-LOCAL_SIZE fsave -(sp) not_fmt40: bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag beq.b inex_cke1 * * Clear dirty bit on dest resister in the frame before branching * to b1238_fix. * movem.l d0/d1,USER_DA(a6) bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit bsr.l b1238_fix ;test for bug1238 case movem.l USER_DA(a6),d0/d1 bra.b inex_done inex_cke1: bclr.b #E1,E_BYTE(a6) inex_done: frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Overflow exception * xref fpsp_ovfl xdef real_ovfl xdef ovfl ovfl: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_ovfl jmp _C_LABEL(fpfault) real_ovfl: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag bne.b ovfl_done bclr.b #E1,E_BYTE(a6) ovfl_done: frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Underflow exception * xref fpsp_unfl xdef real_unfl xdef unfl unfl: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_unfl jmp _C_LABEL(fpfault) real_unfl: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag bne.b unfl_done bclr.b #E1,E_BYTE(a6) unfl_done: frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Signalling NAN exception * xref fpsp_snan xdef real_snan xdef snan snan: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_snan jmp _C_LABEL(fpfault) real_snan: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Operand Error exception * xref fpsp_operr xdef real_operr xdef operr operr: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_operr jmp _C_LABEL(fpfault) real_operr: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * BSUN exception * * This sample handler simply clears the nan bit in the FPSR. * xref fpsp_bsun xdef real_bsun xdef bsun bsun: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_bsun jmp _C_LABEL(fpfault) real_bsun: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception fmove.l FPSR,-(sp) bclr.b #nan_bit,(sp) fmove.l (sp)+,FPSR frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * F-line exception * * A 'real' F-line exception is one that the FPSP isn't supposed to * handle. E.g. an instruction with a co-processor ID that is not 1. * * xref fpsp_fline xdef real_fline xdef fline fline: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_fline jmp _C_LABEL(fpfault) real_fline: jmp _C_LABEL(fpfault) * * Unsupported data type exception * xref fpsp_unsupp xdef real_unsupp xdef unsupp unsupp: cmp.l #-2,_C_LABEL(mmutype) beq.l fpsp_unsupp jmp _C_LABEL(fpfault) real_unsupp: link a6,#-LOCAL_SIZE fsave -(sp) bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception frestore (sp)+ unlk a6 jmp _C_LABEL(fpfault) * * Trace exception * xdef real_trace real_trace: rte * * fpsp_fmt_error --- exit point for frame format error * * The fpu stack frame does not match the frames existing * or planned at the time of this writing. The fpsp is * unable to handle frame sizes not in the following * version:size pairs: * * {4060, 4160} - busy frame * {4028, 4130} - unimp frame * {4000, 4100} - idle frame * * This entry point simply holds an f-line illegal value. * Replace this with a call to your kernel panic code or * code to handle future revisions of the fpu. * xdef fpsp_fmt_error fpsp_fmt_error: pea 1f jsr _C_LABEL(panic) dc.l $f27f0000 ;f-line illegal 1: .asciz "bad floating point stack frame" .even * * fpsp_done --- FPSP exit point * * The exception has been handled by the package and we are ready * to return to user mode, but there may be OS specific code * to execute before we do. If there is, do it now. * * xref _ASM_LABEL(rei) xdef fpsp_done fpsp_done: jmp _ASM_LABEL(rei) * * mem_write --- write to user or supervisor address space * * Writes to memory while in supervisor mode. copyout accomplishes * this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. * If you don't have copyout, use the local copy of the function below. * * a0 - supervisor source address * a1 - user destination address * d0 - number of bytes to write (maximum count is 12) * * The supervisor source address is guaranteed to point into the supervisor * stack. The result is that a UNIX * process is allowed to sleep as a consequence of a page fault during * copyout. The probability of a page fault is exceedingly small because * the 68040 always reads the destination address and thus the page * faults should have already been handled. * * If the EXC_SR shows that the exception was from supervisor space, * then just do a dumb (and slow) memory move. In a UNIX environment * there shouldn't be any supervisor mode floating point exceptions. * xdef mem_write mem_write: btst.b #5,EXC_SR(a6) ;check for supervisor state beq.b user_write super_write: move.b (a0)+,(a1)+ subq.l #1,d0 bne.b super_write rts user_write: move.l d1,-(sp) ;preserve d1 just in case move.l d0,-(sp) move.l a1,-(sp) move.l a0,-(sp) jsr _C_LABEL(copyout) add.l #12,sp move.l (sp)+,d1 rts * * mem_read --- read from user or supervisor address space * * Reads from memory while in supervisor mode. copyin accomplishes * this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. * If you don't have copyin, use the local copy of the function below. * * The FPSP calls mem_read to read the original F-line instruction in order * to extract the data register number when the 'Dn' addressing mode is * used. * *Input: * a0 - user source address * a1 - supervisor destination address * d0 - number of bytes to read (maximum count is 12) * * Like mem_write, mem_read always reads with a supervisor * destination address on the supervisor stack. Also like mem_write, * the EXC_SR is checked and a simple memory copy is done if reading * from supervisor space is indicated. * xdef mem_read mem_read: btst.b #5,EXC_SR(a6) ;check for supervisor state beq.b user_read super_read: move.b (a0)+,(a1)+ subq.l #1,d0 bne.b super_read rts user_read: move.l d1,-(sp) ;preserve d1 just in case move.l d0,-(sp) move.l a1,-(sp) move.l a0,-(sp) jsr _C_LABEL(copyin) add.l #12,sp move.l (sp)+,d1 rts end