Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:48

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  skeleton.sa 3.2 4/26/91
0005 //
0006 //  This file contains code that is system dependent and will
0007 //  need to be modified to install the FPSP.
0008 //
0009 //  Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
0010 //  Put any target system specific handling that must be done immediately
0011 //  before the jump instruction.  If there no handling necessary, then
0012 //  the 'fpsp_xxxx' handler entry point should be placed in the exception
0013 //  table so that the 'jmp' can be eliminated. If the FPSP determines that the
0014 //  exception is one that must be reported then there will be a
0015 //  return from the package by a 'jmp real_xxxx'.  At that point
0016 //  the machine state will be identical to the state before
0017 //  the FPSP was entered.  In particular, whatever condition
0018 //  that caused the exception will still be pending when the FPSP
0019 //  package returns.  Thus, there will be system specific code
0020 //  to handle the exception.
0021 //
0022 //  If the exception was completely handled by the package, then
0023 //  the return will be via a 'jmp fpsp_done'.  Unless there is
0024 //  OS specific work to be done (such as handling a context switch or
0025 //  interrupt) the user program can be resumed via 'rte'.
0026 //
0027 //  In the following skeleton code, some typical 'real_xxxx' handling
0028 //  code is shown.  This code may need to be moved to an appropriate
0029 //  place in the target system, or rewritten.
0030 //
0031 
0032 //      Copyright (C) Motorola, Inc. 1990
0033 //          All Rights Reserved
0034 //
0035 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0036 //  The copyright notice above does not evidence any
0037 //  actual or intended publication of such source code.
0038 
0039 
0040 //
0041 //  Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
0042 //  Modified for RTEMS 4.0.0 by Eric Norum (eric@snorum.ca)
0043 //
0044 
0045 #include <rtems/asm.h>
0046 
0047 //SKELETON  idnt    2,1 | Motorola 040 Floating Point Software Package
0048 
0049 #include "fpsp.defs"
0050 
0051 //
0052 //  Divide by Zero exception
0053 //
0054 //  All dz exceptions are 'real', hence no fpsp_dz entry point.
0055 //
0056     .global SYM(_fpspEntry_dz)
0057 SYM(_fpspEntry_dz):
0058     link        a6,#-LOCAL_SIZE
0059     fsave       -(sp)
0060     bclrb       #E1,E_BYTE(a6)
0061     frestore    (sp)+
0062     unlk        a6
0063     jmp     ([SYM(M68040FPSPUserExceptionHandlers)+3*4],%za0)
0064 
0065 //
0066 //  Inexact exception
0067 //
0068 //  All inexact exceptions are real, but the 'real' handler
0069 //  will probably want to clear the pending exception.
0070 //  The provided code will clear the E3 exception (if pending),
0071 //  otherwise clear the E1 exception.  The frestore is not really
0072 //  necessary for E1 exceptions.
0073 //
0074 // Code following the 'inex' label is to handle bug #1232.  In this
0075 // bug, if an E1 snan, ovfl, or unfl occurred, and the process was
0076 // swapped out before taking the exception, the exception taken on
0077 // return was inex, rather than the correct exception.  The snan, ovfl,
0078 // and unfl exception to be taken must not have been enabled.  The
0079 // fix is to check for E1, and the existence of one of snan, ovfl,
0080 // or unfl bits set in the fpsr.  If any of these are set, branch
0081 // to the appropriate  handler for the exception in the fpsr.  Note
0082 // that this fix is only for d43b parts, and is skipped if the
0083 // version number is not $40.
0084 //
0085 //
0086     .global SYM(_fpspEntry_inex)
0087     .global real_inex
0088 SYM(_fpspEntry_inex):
0089     link        a6,#-LOCAL_SIZE
0090     fsave       -(sp)
0091     cmpib       #VER_40,(sp)        //test version number
0092     bnes        not_fmt40
0093     fmovel      fpsr,-(sp)
0094     btstb       #E1,E_BYTE(a6)      //test for E1 set
0095     beqs        not_b1232
0096     btstb       #snan_bit,2(sp) //test for snan
0097     beq     inex_ckofl
0098     addl        #4,sp
0099     frestore    (sp)+
0100     unlk        a6
0101     bra     snan
0102 inex_ckofl:
0103     btstb       #ovfl_bit,2(sp) //test for ovfl
0104     beq     inex_ckufl
0105     addl        #4,sp
0106     frestore    (sp)+
0107     unlk        a6
0108     bra     SYM(_fpspEntry_ovfl)
0109 inex_ckufl:
0110     btstb       #unfl_bit,2(sp) //test for unfl
0111     beq     not_b1232
0112     addl        #4,sp
0113     frestore    (sp)+
0114     unlk        a6
0115     bra     SYM(_fpspEntry_unfl)
0116 
0117 //
0118 // We do not have the bug 1232 case.  Clean up the stack and call
0119 // real_inex.
0120 //
0121 not_b1232:
0122     addl        #4,sp
0123     frestore    (sp)+
0124     unlk        a6
0125 
0126 real_inex:
0127     link        a6,#-LOCAL_SIZE
0128     fsave       -(sp)
0129 not_fmt40:
0130     bclrb       #E3,E_BYTE(a6)      //clear and test E3 flag
0131     beqs        inex_cke1
0132 //
0133 // Clear dirty bit on dest resister in the frame before branching
0134 // to b1238_fix.
0135 //
0136     moveml      d0/d1,USER_DA(a6)
0137     bfextu      CMDREG1B(a6){#6:#3},d0      //get dest reg no
0138     bclrb       d0,FPR_DIRTY_BITS(a6)   //clr dest dirty bit
0139     bsrl        b1238_fix       //test for bug1238 case
0140     moveml      USER_DA(a6),d0/d1
0141     bras        inex_done
0142 inex_cke1:
0143     bclrb       #E1,E_BYTE(a6)
0144 inex_done:
0145     frestore    (sp)+
0146     unlk        a6
0147     jmp ([SYM(M68040FPSPUserExceptionHandlers)+2*4],%za0)
0148 
0149 //
0150 //  Overflow exception
0151 //
0152     .global SYM(_fpspEntry_ovfl)
0153     .global real_ovfl
0154 SYM(_fpspEntry_ovfl):
0155     jmp fpsp_ovfl
0156 real_ovfl:
0157     link        a6,#-LOCAL_SIZE
0158     fsave       -(sp)
0159     bclrb       #E3,E_BYTE(a6)      //clear and test E3 flag
0160     bnes        ovfl_done
0161     bclrb       #E1,E_BYTE(a6)
0162 ovfl_done:
0163     frestore    (sp)+
0164     unlk        a6
0165     jmp ([SYM(M68040FPSPUserExceptionHandlers)+6*4],%za0)
0166 
0167 //
0168 //  Underflow exception
0169 //
0170     .global SYM(_fpspEntry_unfl)
0171     .global real_unfl
0172 SYM(_fpspEntry_unfl):
0173     jmp fpsp_unfl
0174 real_unfl:
0175     link        a6,#-LOCAL_SIZE
0176     fsave       -(sp)
0177     bclrb       #E3,E_BYTE(a6)      //clear and test E3 flag
0178     bnes        unfl_done
0179     bclrb       #E1,E_BYTE(a6)
0180 unfl_done:
0181     frestore    (sp)+
0182     unlk        a6
0183     jmp ([SYM(M68040FPSPUserExceptionHandlers)+4*4],%za0)
0184 
0185 //
0186 //  Signalling NAN exception
0187 //
0188     .global SYM(_fpspEntry_snan)
0189     .global real_snan
0190 SYM(_fpspEntry_snan):
0191 snan:
0192     jmp fpsp_snan
0193 real_snan:
0194     link        a6,#-LOCAL_SIZE
0195     fsave       -(sp)
0196     bclrb       #E1,E_BYTE(a6)  //snan is always an E1 exception
0197     frestore    (sp)+
0198     unlk        a6
0199     jmp ([SYM(M68040FPSPUserExceptionHandlers)+7*4],%za0)
0200 
0201 //
0202 //  Operand Error exception
0203 //
0204     .global SYM(_fpspEntry_operr)
0205     .global real_operr
0206 SYM(_fpspEntry_operr):
0207     jmp fpsp_operr
0208 real_operr:
0209     link        a6,#-LOCAL_SIZE
0210     fsave       -(sp)
0211     bclrb       #E1,E_BYTE(a6)  //operr is always an E1 exception
0212     frestore    (sp)+
0213     unlk        a6
0214     jmp ([SYM(M68040FPSPUserExceptionHandlers)+5*4],%za0)
0215 
0216 //
0217 //  BSUN exception
0218 //
0219 //  This sample handler simply clears the nan bit in the FPSR.
0220 //
0221     .global SYM(_fpspEntry_bsun)
0222     .global real_bsun
0223 SYM(_fpspEntry_bsun):
0224     jmp fpsp_bsun
0225 real_bsun:
0226     link        a6,#-LOCAL_SIZE
0227     fsave       -(sp)
0228     bclrb       #E1,E_BYTE(a6)  //bsun is always an E1 exception
0229     fmovel      fpsr,-(sp)
0230     bclrb       #nan_bit,(sp)
0231     fmovel      (sp)+,fpsr
0232     frestore    (sp)+
0233     unlk        a6
0234     jmp ([SYM(M68040FPSPUserExceptionHandlers)+1*4],%za0)
0235 
0236 //
0237 //  F-line exception
0238 //
0239 //  A 'real' F-line exception is one that the FPSP is not supposed to
0240 //  handle. E.g. an instruction with a co-processor ID that is not 1.
0241 //
0242     .global SYM(_fpspEntry_fline)
0243     .global real_fline
0244 SYM(_fpspEntry_fline):
0245     jmp fpsp_fline
0246 real_fline:
0247     jmp ([SYM(M68040FPSPUserExceptionHandlers)+0*4],%za0)
0248 
0249 //
0250 //  Unsupported data type exception
0251 //
0252     .global SYM(_fpspEntry_unsupp)
0253     .global real_unsupp
0254 SYM(_fpspEntry_unsupp):
0255     jmp fpsp_unsupp
0256 real_unsupp:
0257     link        a6,#-LOCAL_SIZE
0258     fsave       -(sp)
0259     bclrb       #E1,E_BYTE(a6)  //unsupp is always an E1 exception
0260     frestore    (sp)+
0261     unlk        a6
0262     jmp ([SYM(M68040FPSPUserExceptionHandlers)+8*4],%za0)
0263 
0264 //
0265 //  Trace exception
0266 //
0267     .global real_trace
0268 real_trace:
0269     trap    #10
0270 
0271 //
0272 //  fpsp_fmt_error --- exit point for frame format error
0273 //
0274 //  The fpu stack frame does not match the frames existing
0275 //  or planned at the time of this writing.  The fpsp is
0276 //  unable to handle frame sizes not in the following
0277 //  version:size pairs:
0278 //
0279 //  {4060, 4160} - busy frame
0280 //  {4028, 4130} - unimp frame
0281 //  {4000, 4100} - idle frame
0282 //
0283     .global fpsp_fmt_error
0284 fpsp_fmt_error:
0285     trap    #11
0286 
0287 //
0288 //  fpsp_done --- FPSP exit point
0289 //
0290 //  The exception has been handled by the package and we are ready
0291 //  to return to user mode, but there may be OS specific code
0292 //  to execute before we do.  If there is, do it now.
0293 //
0294 // For now, the RTEMS does not bother looking at the
0295 // possibility that it is time to reschedule....
0296 //
0297 
0298     .global fpsp_done
0299 fpsp_done:
0300     rte
0301 
0302 //
0303 //  mem_write --- write to user or supervisor address space
0304 //
0305 // Writes to memory while in supervisor mode.
0306 //
0307 //  a0 - supervisor source address
0308 //  a1 - user/supervisor destination address
0309 //  d0 - number of bytes to write (maximum count is 12)
0310 //
0311     .global mem_write
0312 mem_write:
0313     btstb   #5,EXC_SR(a6)   //check for supervisor state
0314     beqs    user_write
0315 super_write:
0316     moveb   (a0)+,(a1)+
0317     subql   #1,d0
0318     bnes    super_write
0319     rts
0320 user_write:
0321     movel   d1,-(sp)    //preserve d1 just in case
0322     movel   d0,-(sp)
0323     movel   a1,-(sp)
0324     movel   a0,-(sp)
0325     jsr     copyout
0326     addw    #12,sp
0327     movel   (sp)+,d1
0328     rts
0329 //
0330 //  mem_read --- read from user or supervisor address space
0331 //
0332 // Reads from memory while in supervisor mode.
0333 //
0334 // The FPSP calls mem_read to read the original F-line instruction in order
0335 // to extract the data register number when the 'Dn' addressing mode is
0336 // used.
0337 //
0338 //Input:
0339 //  a0 - user/supervisor source address
0340 //  a1 - supervisor destination address
0341 //  d0 - number of bytes to read (maximum count is 12)
0342 //
0343 // Like mem_write, mem_read always reads with a supervisor
0344 // destination address on the supervisor stack.  Also like mem_write,
0345 // the EXC_SR is checked and a simple memory copy is done if reading
0346 // from supervisor space is indicated.
0347 //
0348     .global mem_read
0349 mem_read:
0350     btstb   #5,EXC_SR(a6)   //check for supervisor state
0351     beqs    user_read
0352 super_read:
0353     moveb   (a0)+,(a1)+
0354     subql   #1,d0
0355     bnes    super_read
0356     rts
0357 user_read:
0358     movel   d1,-(sp)    //preserve d1 just in case
0359     movel   d0,-(sp)
0360     movel   a1,-(sp)
0361     movel   a0,-(sp)
0362     jsr     copyin
0363     addw    #12,sp
0364     movel   (sp)+,d1
0365     rts
0366 
0367 //
0368 // Use these routines if your kernel does not have copyout/copyin equivalents.
0369 // Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
0370 // and copyin overwrites SFC.
0371 //
0372 copyout:
0373     movel   4(sp),a0    // source
0374     movel   8(sp),a1    // destination
0375     movel   12(sp),d0   // count
0376     subl    #1,d0       // dec count by 1 for dbra
0377     movel   #1,d1
0378     movec   d1,dfc      // set dfc for user data space
0379 moreout:
0380     moveb   (a0)+,d1    // fetch supervisor byte
0381     movesb  d1,(a1)+    // write user byte
0382     dbf d0,moreout
0383     rts
0384 
0385 copyin:
0386     movel   4(sp),a0    // source
0387     movel   8(sp),a1    // destination
0388     movel   12(sp),d0   // count
0389     subl    #1,d0       // dec count by 1 for dbra
0390     movel   #1,d1
0391     movec   d1,sfc      // set sfc for user space
0392 morein:
0393     movesb  (a0)+,d1    // fetch user byte
0394     moveb   d1,(a1)+    // write supervisor byte
0395     dbf d0,morein
0396     rts
0397 
0398     |end