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