skeleton.sa revision 1.1
11.1Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 21.1Smycroft* M68000 Hi-Performance Microprocessor Division 31.1Smycroft* M68040 Software Package 41.1Smycroft* 51.1Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 61.1Smycroft* All rights reserved. 71.1Smycroft* 81.1Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 91.1Smycroft* To the maximum extent permitted by applicable law, 101.1Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 111.1Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 121.1Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 131.1Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 141.1Smycroft* and any accompanying written materials. 151.1Smycroft* 161.1Smycroft* To the maximum extent permitted by applicable law, 171.1Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 181.1Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 191.1Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 201.1Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 211.1Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 221.1Smycroft* and support of the SOFTWARE. 231.1Smycroft* 241.1Smycroft* You are hereby granted a copyright license to use, modify, and 251.1Smycroft* distribute the SOFTWARE so long as this entire notice is retained 261.1Smycroft* without alteration in any modified and/or redistributed versions, 271.1Smycroft* and that such modified versions are clearly identified as such. 281.1Smycroft* No licenses are granted by implication, estoppel or otherwise 291.1Smycroft* under any patents or trademarks of Motorola, Inc. 301.1Smycroft 311.1Smycroft* 321.1Smycroft* skeleton.sa 3.2 4/26/91 331.1Smycroft* 341.1Smycroft* This file contains code that is system dependent and will 351.1Smycroft* need to be modified to install the FPSP. 361.1Smycroft* 371.1Smycroft* Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. 381.1Smycroft* Put any target system specific handling that must be done immediately 391.1Smycroft* before the jump instruction. If there no handling necessary, then 401.1Smycroft* the 'fpsp_xxxx' handler entry point should be placed in the exception 411.1Smycroft* table so that the 'jmp' can be eliminated. If the FPSP determines that the 421.1Smycroft* exception is one that must be reported then there will be a 431.1Smycroft* return from the package by a 'jmp real_xxxx'. At that point 441.1Smycroft* the machine state will be identical to the state before 451.1Smycroft* the FPSP was entered. In particular, whatever condition 461.1Smycroft* that caused the exception will still be pending when the FPSP 471.1Smycroft* package returns. Thus, there will be system specific code 481.1Smycroft* to handle the exception. 491.1Smycroft* 501.1Smycroft* If the exception was completely handled by the package, then 511.1Smycroft* the return will be via a 'jmp fpsp_done'. Unless there is 521.1Smycroft* OS specific work to be done (such as handling a context switch or 531.1Smycroft* interrupt) the user program can be resumed via 'rte'. 541.1Smycroft* 551.1Smycroft* In the following skeleton code, some typical 'real_xxxx' handling 561.1Smycroft* code is shown. This code may need to be moved to an appropriate 571.1Smycroft* place in the target system, or rewritten. 581.1Smycroft* 591.1Smycroft 601.1SmycroftSKELETON IDNT 2,1 Motorola 040 Floating Point Software Package 611.1Smycroft 621.1Smycroft section 15 631.1Smycroft* 641.1Smycroft* The following counters are used for standalone testing 651.1Smycroft* 661.1Smycroftsigunimp dc.l 0 671.1Smycroftsigbsun dc.l 0 681.1Smycroftsiginex dc.l 0 691.1Smycroftsigdz dc.l 0 701.1Smycroftsigunfl dc.l 0 711.1Smycroftsigovfl dc.l 0 721.1Smycroftsigoperr dc.l 0 731.1Smycroftsigsnan dc.l 0 741.1Smycroftsigunsupp dc.l 0 751.1Smycroft 761.1Smycroft section 8 771.1Smycroft 781.1Smycroft include fpsp.h 791.1Smycroft 801.1Smycroft xref b1238_fix 811.1Smycroft 821.1Smycroft* 831.1Smycroft* Divide by Zero exception 841.1Smycroft* 851.1Smycroft* All dz exceptions are 'real', hence no fpsp_dz entry point. 861.1Smycroft* 871.1Smycroft xdef dz 881.1Smycroft xdef real_dz 891.1Smycroftdz: 901.1Smycroftreal_dz: 911.1Smycroft link a6,#-LOCAL_SIZE 921.1Smycroft fsave -(sp) 931.1Smycroft bclr.b #E1,E_BYTE(a6) 941.1Smycroft frestore (sp)+ 951.1Smycroft unlk a6 961.1Smycroft 971.1Smycroft add.l #1,sigdz ;for standalone testing 981.1Smycroft 991.1Smycroft rte 1001.1Smycroft* 1011.1Smycroft* Inexact exception 1021.1Smycroft* 1031.1Smycroft* All inexact exceptions are real, but the 'real' handler 1041.1Smycroft* will probably want to clear the pending exception. 1051.1Smycroft* The provided code will clear the E3 exception (if pending), 1061.1Smycroft* otherwise clear the E1 exception. The frestore is not really 1071.1Smycroft* necessary for E1 exceptions. 1081.1Smycroft* 1091.1Smycroft* Code following the 'inex' label is to handle bug #1232. In this 1101.1Smycroft* bug, if an E1 snan, ovfl, or unfl occured, and the process was 1111.1Smycroft* swapped out before taking the exception, the exception taken on 1121.1Smycroft* return was inex, rather than the correct exception. The snan, ovfl, 1131.1Smycroft* and unfl exception to be taken must not have been enabled. The 1141.1Smycroft* fix is to check for E1, and the existence of one of snan, ovfl, 1151.1Smycroft* or unfl bits set in the fpsr. If any of these are set, branch 1161.1Smycroft* to the appropriate handler for the exception in the fpsr. Note 1171.1Smycroft* that this fix is only for d43b parts, and is skipped if the 1181.1Smycroft* version number is not $40. 1191.1Smycroft* 1201.1Smycroft* 1211.1Smycroft xdef real_inex 1221.1Smycroft xdef inex 1231.1Smycroftinex: 1241.1Smycroft link a6,#-LOCAL_SIZE 1251.1Smycroft fsave -(sp) 1261.1Smycroft cmpi.b #VER_40,(sp) ;test version number 1271.1Smycroft bne.b not_fmt40 1281.1Smycroft fmove.l fpsr,-(sp) 1291.1Smycroft btst.b #E1,E_BYTE(a6) ;test for E1 set 1301.1Smycroft beq.b not_b1232 1311.1Smycroft btst.b #snan_bit,2(sp) ;test for snan 1321.1Smycroft beq inex_ckofl 1331.1Smycroft add.l #4,sp 1341.1Smycroft frestore (sp)+ 1351.1Smycroft unlk a6 1361.1Smycroft bra snan 1371.1Smycroftinex_ckofl: 1381.1Smycroft btst.b #ovfl_bit,2(sp) ;test for ovfl 1391.1Smycroft beq inex_ckufl 1401.1Smycroft add.l #4,sp 1411.1Smycroft frestore (sp)+ 1421.1Smycroft unlk a6 1431.1Smycroft bra ovfl 1441.1Smycroftinex_ckufl: 1451.1Smycroft btst.b #unfl_bit,2(sp) ;test for unfl 1461.1Smycroft beq not_b1232 1471.1Smycroft add.l #4,sp 1481.1Smycroft frestore (sp)+ 1491.1Smycroft unlk a6 1501.1Smycroft bra unfl 1511.1Smycroft 1521.1Smycroft* 1531.1Smycroft* We do not have the bug 1232 case. Clean up the stack and call 1541.1Smycroft* real_inex. 1551.1Smycroft* 1561.1Smycroftnot_b1232: 1571.1Smycroft add.l #4,sp 1581.1Smycroft frestore (sp)+ 1591.1Smycroft unlk a6 1601.1Smycroft 1611.1Smycroftreal_inex: 1621.1Smycroft 1631.1Smycroft add.l #1,siginex ;for standalone testing 1641.1Smycroft 1651.1Smycroft link a6,#-LOCAL_SIZE 1661.1Smycroft fsave -(sp) 1671.1Smycroftnot_fmt40: 1681.1Smycroft bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 1691.1Smycroft beq.b inex_cke1 1701.1Smycroft* 1711.1Smycroft* Clear dirty bit on dest resister in the frame before branching 1721.1Smycroft* to b1238_fix. 1731.1Smycroft* 1741.1Smycroft movem.l d0/d1,USER_DA(a6) 1751.1Smycroft bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no 1761.1Smycroft bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 1771.1Smycroft bsr.l b1238_fix ;test for bug1238 case 1781.1Smycroft movem.l USER_DA(a6),d0/d1 1791.1Smycroft bra.b inex_done 1801.1Smycroftinex_cke1: 1811.1Smycroft bclr.b #E1,E_BYTE(a6) 1821.1Smycroftinex_done: 1831.1Smycroft frestore (sp)+ 1841.1Smycroft unlk a6 1851.1Smycroft rte 1861.1Smycroft 1871.1Smycroft* 1881.1Smycroft* Overflow exception 1891.1Smycroft* 1901.1Smycroft xref fpsp_ovfl 1911.1Smycroft xdef real_ovfl 1921.1Smycroft xdef ovfl 1931.1Smycroftovfl: 1941.1Smycroft jmp fpsp_ovfl 1951.1Smycroftreal_ovfl: 1961.1Smycroft 1971.1Smycroft add.l #1,sigovfl ;for standalone testing 1981.1Smycroft 1991.1Smycroft link a6,#-LOCAL_SIZE 2001.1Smycroft fsave -(sp) 2011.1Smycroft bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 2021.1Smycroft bne.b ovfl_done 2031.1Smycroft bclr.b #E1,E_BYTE(a6) 2041.1Smycroftovfl_done: 2051.1Smycroft frestore (sp)+ 2061.1Smycroft unlk a6 2071.1Smycroft rte 2081.1Smycroft 2091.1Smycroft* 2101.1Smycroft* Underflow exception 2111.1Smycroft* 2121.1Smycroft xref fpsp_unfl 2131.1Smycroft xdef real_unfl 2141.1Smycroft xdef unfl 2151.1Smycroftunfl: 2161.1Smycroft jmp fpsp_unfl 2171.1Smycroftreal_unfl: 2181.1Smycroft 2191.1Smycroft add.l #1,sigunfl ;for standalone testing 2201.1Smycroft 2211.1Smycroft link a6,#-LOCAL_SIZE 2221.1Smycroft fsave -(sp) 2231.1Smycroft bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 2241.1Smycroft bne.b unfl_done 2251.1Smycroft bclr.b #E1,E_BYTE(a6) 2261.1Smycroftunfl_done: 2271.1Smycroft frestore (sp)+ 2281.1Smycroft unlk a6 2291.1Smycroft rte 2301.1Smycroft 2311.1Smycroft* 2321.1Smycroft* Signalling NAN exception 2331.1Smycroft* 2341.1Smycroft xref fpsp_snan 2351.1Smycroft xdef real_snan 2361.1Smycroft xdef snan 2371.1Smycroftsnan: 2381.1Smycroft jmp fpsp_snan 2391.1Smycroftreal_snan: 2401.1Smycroft link a6,#-LOCAL_SIZE 2411.1Smycroft fsave -(sp) 2421.1Smycroft bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception 2431.1Smycroft frestore (sp)+ 2441.1Smycroft unlk a6 2451.1Smycroft 2461.1Smycroft add.l #1,sigsnan ;for standalone testing 2471.1Smycroft rte 2481.1Smycroft 2491.1Smycroft* 2501.1Smycroft* Operand Error exception 2511.1Smycroft* 2521.1Smycroft xref fpsp_operr 2531.1Smycroft xdef real_operr 2541.1Smycroft xdef operr 2551.1Smycroftoperr: 2561.1Smycroft jmp fpsp_operr 2571.1Smycroftreal_operr: 2581.1Smycroft link a6,#-LOCAL_SIZE 2591.1Smycroft fsave -(sp) 2601.1Smycroft bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception 2611.1Smycroft frestore (sp)+ 2621.1Smycroft unlk a6 2631.1Smycroft 2641.1Smycroft add.l #1,sigoperr ;for standalone testing 2651.1Smycroft 2661.1Smycroft rte 2671.1Smycroft 2681.1Smycroft* 2691.1Smycroft* BSUN exception 2701.1Smycroft* 2711.1Smycroft* This sample handler simply clears the nan bit in the FPSR. 2721.1Smycroft* 2731.1Smycroft xref fpsp_bsun 2741.1Smycroft xdef real_bsun 2751.1Smycroft xdef bsun 2761.1Smycroftbsun: 2771.1Smycroft jmp fpsp_bsun 2781.1Smycroftreal_bsun: 2791.1Smycroft link a6,#-LOCAL_SIZE 2801.1Smycroft fsave -(sp) 2811.1Smycroft bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception 2821.1Smycroft fmove.l FPSR,-(sp) 2831.1Smycroft bclr.b #nan_bit,(sp) 2841.1Smycroft fmove.l (sp)+,FPSR 2851.1Smycroft frestore (sp)+ 2861.1Smycroft unlk a6 2871.1Smycroft 2881.1Smycroft add.l #1,sigbsun ;for standalone testing 2891.1Smycroft 2901.1Smycroft rte 2911.1Smycroft 2921.1Smycroft* 2931.1Smycroft* F-line exception 2941.1Smycroft* 2951.1Smycroft* A 'real' F-line exception is one that the FPSP isn't supposed to 2961.1Smycroft* handle. E.g. an instruction with a co-processor ID that is not 1. 2971.1Smycroft* 2981.1Smycroft* 2991.1Smycroft xref fpsp_fline 3001.1Smycroft xdef real_fline 3011.1Smycroft xdef fline 3021.1Smycroftfline: 3031.1Smycroft jmp fpsp_fline 3041.1Smycroftreal_fline: 3051.1Smycroft 3061.1Smycroft add.l #1,sigunimp ;for standalone testing 3071.1Smycroft 3081.1Smycroft rte 3091.1Smycroft 3101.1Smycroft* 3111.1Smycroft* Unsupported data type exception 3121.1Smycroft* 3131.1Smycroft xref fpsp_unsupp 3141.1Smycroft xdef real_unsupp 3151.1Smycroft xdef unsupp 3161.1Smycroftunsupp: 3171.1Smycroft jmp fpsp_unsupp 3181.1Smycroftreal_unsupp: 3191.1Smycroft link a6,#-LOCAL_SIZE 3201.1Smycroft fsave -(sp) 3211.1Smycroft bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception 3221.1Smycroft frestore (sp)+ 3231.1Smycroft unlk a6 3241.1Smycroft 3251.1Smycroft add.l #1,sigunsupp ;for standalone testing 3261.1Smycroft 3271.1Smycroft rte 3281.1Smycroft 3291.1Smycroft* 3301.1Smycroft* Trace exception 3311.1Smycroft* 3321.1Smycroft xdef real_trace 3331.1Smycroftreal_trace: 3341.1Smycroft rte 3351.1Smycroft 3361.1Smycroft* 3371.1Smycroft* fpsp_fmt_error --- exit point for frame format error 3381.1Smycroft* 3391.1Smycroft* The fpu stack frame does not match the frames existing 3401.1Smycroft* or planned at the time of this writing. The fpsp is 3411.1Smycroft* unable to handle frame sizes not in the following 3421.1Smycroft* version:size pairs: 3431.1Smycroft* 3441.1Smycroft* {4060, 4160} - busy frame 3451.1Smycroft* {4028, 4130} - unimp frame 3461.1Smycroft* {4000, 4100} - idle frame 3471.1Smycroft* 3481.1Smycroft* This entry point simply holds an f-line illegal value. 3491.1Smycroft* Replace this with a call to your kernel panic code or 3501.1Smycroft* code to handle future revisions of the fpu. 3511.1Smycroft* 3521.1Smycroft xdef fpsp_fmt_error 3531.1Smycroftfpsp_fmt_error: 3541.1Smycroft 3551.1Smycroft dc.l $f27f0000 ;f-line illegal 3561.1Smycroft 3571.1Smycroft* 3581.1Smycroft* fpsp_done --- FPSP exit point 3591.1Smycroft* 3601.1Smycroft* The exception has been handled by the package and we are ready 3611.1Smycroft* to return to user mode, but there may be OS specific code 3621.1Smycroft* to execute before we do. If there is, do it now. 3631.1Smycroft* 3641.1Smycroft* 3651.1Smycroft xdef fpsp_done 3661.1Smycroftfpsp_done: 3671.1Smycroft rte 3681.1Smycroft 3691.1Smycroft* 3701.1Smycroft* mem_write --- write to user or supervisor address space 3711.1Smycroft* 3721.1Smycroft* Writes to memory while in supervisor mode. copyout accomplishes 3731.1Smycroft* this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. 3741.1Smycroft* If you don't have copyout, use the local copy of the function below. 3751.1Smycroft* 3761.1Smycroft* a0 - supervisor source address 3771.1Smycroft* a1 - user destination address 3781.1Smycroft* d0 - number of bytes to write (maximum count is 12) 3791.1Smycroft* 3801.1Smycroft* The supervisor source address is guaranteed to point into the supervisor 3811.1Smycroft* stack. The result is that a UNIX 3821.1Smycroft* process is allowed to sleep as a consequence of a page fault during 3831.1Smycroft* copyout. The probability of a page fault is exceedingly small because 3841.1Smycroft* the 68040 always reads the destination address and thus the page 3851.1Smycroft* faults should have already been handled. 3861.1Smycroft* 3871.1Smycroft* If the EXC_SR shows that the exception was from supervisor space, 3881.1Smycroft* then just do a dumb (and slow) memory move. In a UNIX environment 3891.1Smycroft* there shouldn't be any supervisor mode floating point exceptions. 3901.1Smycroft* 3911.1Smycroft xdef mem_write 3921.1Smycroftmem_write: 3931.1Smycroft btst.b #5,EXC_SR(a6) ;check for supervisor state 3941.1Smycroft beq.b user_write 3951.1Smycroftsuper_write: 3961.1Smycroft move.b (a0)+,(a1)+ 3971.1Smycroft subq.l #1,d0 3981.1Smycroft bne.b super_write 3991.1Smycroft rts 4001.1Smycroftuser_write: 4011.1Smycroft move.l d1,-(sp) ;preserve d1 just in case 4021.1Smycroft move.l d0,-(sp) 4031.1Smycroft move.l a1,-(sp) 4041.1Smycroft move.l a0,-(sp) 4051.1Smycroft jsr copyout 4061.1Smycroft add.w #12,sp 4071.1Smycroft move.l (sp)+,d1 4081.1Smycroft rts 4091.1Smycroft* 4101.1Smycroft* mem_read --- read from user or supervisor address space 4111.1Smycroft* 4121.1Smycroft* Reads from memory while in supervisor mode. copyin accomplishes 4131.1Smycroft* this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. 4141.1Smycroft* If you don't have copyin, use the local copy of the function below. 4151.1Smycroft* 4161.1Smycroft* The FPSP calls mem_read to read the original F-line instruction in order 4171.1Smycroft* to extract the data register number when the 'Dn' addressing mode is 4181.1Smycroft* used. 4191.1Smycroft* 4201.1Smycroft*Input: 4211.1Smycroft* a0 - user source address 4221.1Smycroft* a1 - supervisor destination address 4231.1Smycroft* d0 - number of bytes to read (maximum count is 12) 4241.1Smycroft* 4251.1Smycroft* Like mem_write, mem_read always reads with a supervisor 4261.1Smycroft* destination address on the supervisor stack. Also like mem_write, 4271.1Smycroft* the EXC_SR is checked and a simple memory copy is done if reading 4281.1Smycroft* from supervisor space is indicated. 4291.1Smycroft* 4301.1Smycroft xdef mem_read 4311.1Smycroftmem_read: 4321.1Smycroft btst.b #5,EXC_SR(a6) ;check for supervisor state 4331.1Smycroft beq.b user_read 4341.1Smycroftsuper_read: 4351.1Smycroft move.b (a0)+,(a1)+ 4361.1Smycroft subq.l #1,d0 4371.1Smycroft bne.b super_read 4381.1Smycroft rts 4391.1Smycroftuser_read: 4401.1Smycroft move.l d1,-(sp) ;preserve d1 just in case 4411.1Smycroft move.l d0,-(sp) 4421.1Smycroft move.l a1,-(sp) 4431.1Smycroft move.l a0,-(sp) 4441.1Smycroft jsr copyin 4451.1Smycroft add.w #12,sp 4461.1Smycroft move.l (sp)+,d1 4471.1Smycroft rts 4481.1Smycroft 4491.1Smycroft* 4501.1Smycroft* Use these routines if your kernel doesn't have copyout/copyin equivalents. 4511.1Smycroft* Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC, 4521.1Smycroft* and copyin overwrites SFC. 4531.1Smycroft* 4541.1Smycroftcopyout: 4551.1Smycroft move.l 4(sp),a0 ; source 4561.1Smycroft move.l 8(sp),a1 ; destination 4571.1Smycroft move.l 12(sp),d0 ; count 4581.1Smycroft sub.l #1,d0 ; dec count by 1 for dbra 4591.1Smycroft move.l #1,d1 4601.1Smycroft movec d1,DFC ; set dfc for user data space 4611.1Smycroftmoreout: 4621.1Smycroft move.b (a0)+,d1 ; fetch supervisor byte 4631.1Smycroft moves.b d1,(a1)+ ; write user byte 4641.1Smycroft dbf.w d0,moreout 4651.1Smycroft rts 4661.1Smycroft 4671.1Smycroftcopyin: 4681.1Smycroft move.l 4(sp),a0 ; source 4691.1Smycroft move.l 8(sp),a1 ; destination 4701.1Smycroft move.l 12(sp),d0 ; count 4711.1Smycroft sub.l #1,d0 ; dec count by 1 for dbra 4721.1Smycroft move.l #1,d1 4731.1Smycroft movec d1,SFC ; set sfc for user space 4741.1Smycroftmorein: 4751.1Smycroft moves.b (a0)+,d1 ; fetch user byte 4761.1Smycroft move.b d1,(a1)+ ; write supervisor byte 4771.1Smycroft dbf.w d0,morein 4781.1Smycroft rts 4791.1Smycroft 4801.1Smycroft end 481