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