1* $NetBSD: skeleton.sa,v 1.4 2001/09/16 16:34:32 wiz Exp $ 2 3* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 4* M68000 Hi-Performance Microprocessor Division 5* M68040 Software Package 6* 7* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 8* All rights reserved. 9* 10* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 11* To the maximum extent permitted by applicable law, 12* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 13* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 14* PARTICULAR PURPOSE and any warranty against infringement with 15* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 16* and any accompanying written materials. 17* 18* To the maximum extent permitted by applicable law, 19* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 20* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 21* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 22* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 23* SOFTWARE. Motorola assumes no responsibility for the maintenance 24* and support of the SOFTWARE. 25* 26* You are hereby granted a copyright license to use, modify, and 27* distribute the SOFTWARE so long as this entire notice is retained 28* without alteration in any modified and/or redistributed versions, 29* and that such modified versions are clearly identified as such. 30* No licenses are granted by implication, estoppel or otherwise 31* under any patents or trademarks of Motorola, Inc. 32 33* 34* skeleton.sa 3.2 4/26/91 35* 36* This file contains code that is system dependent and will 37* need to be modified to install the FPSP. 38* 39* Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'. 40* Put any target system specific handling that must be done immediately 41* before the jump instruction. If there no handling necessary, then 42* the 'fpsp_xxxx' handler entry point should be placed in the exception 43* table so that the 'jmp' can be eliminated. If the FPSP determines that the 44* exception is one that must be reported then there will be a 45* return from the package by a 'jmp real_xxxx'. At that point 46* the machine state will be identical to the state before 47* the FPSP was entered. In particular, whatever condition 48* that caused the exception will still be pending when the FPSP 49* package returns. Thus, there will be system specific code 50* to handle the exception. 51* 52* If the exception was completely handled by the package, then 53* the return will be via a 'jmp fpsp_done'. Unless there is 54* OS specific work to be done (such as handling a context switch or 55* interrupt) the user program can be resumed via 'rte'. 56* 57* In the following skeleton code, some typical 'real_xxxx' handling 58* code is shown. This code may need to be moved to an appropriate 59* place in the target system, or rewritten. 60* 61 62SKELETON IDNT 2,1 Motorola 040 Floating Point Software Package 63 64 section 15 65* 66* The following counters are used for standalone testing 67* 68sigunimp dc.l 0 69sigbsun dc.l 0 70siginex dc.l 0 71sigdz dc.l 0 72sigunfl dc.l 0 73sigovfl dc.l 0 74sigoperr dc.l 0 75sigsnan dc.l 0 76sigunsupp dc.l 0 77 78 section 8 79 80 include fpsp.h 81 82 xref b1238_fix 83 84* 85* Divide by Zero exception 86* 87* All dz exceptions are 'real', hence no fpsp_dz entry point. 88* 89 xdef dz 90 xdef real_dz 91dz: 92real_dz: 93 link a6,#-LOCAL_SIZE 94 fsave -(sp) 95 bclr.b #E1,E_BYTE(a6) 96 frestore (sp)+ 97 unlk a6 98 99 add.l #1,sigdz ;for standalone testing 100 101 rte 102* 103* Inexact exception 104* 105* All inexact exceptions are real, but the 'real' handler 106* will probably want to clear the pending exception. 107* The provided code will clear the E3 exception (if pending), 108* otherwise clear the E1 exception. The frestore is not really 109* necessary for E1 exceptions. 110* 111* Code following the 'inex' label is to handle bug #1232. In this 112* bug, if an E1 snan, ovfl, or unfl occurred, and the process was 113* swapped out before taking the exception, the exception taken on 114* return was inex, rather than the correct exception. The snan, ovfl, 115* and unfl exception to be taken must not have been enabled. The 116* fix is to check for E1, and the existence of one of snan, ovfl, 117* or unfl bits set in the fpsr. If any of these are set, branch 118* to the appropriate handler for the exception in the fpsr. Note 119* that this fix is only for d43b parts, and is skipped if the 120* version number is not $40. 121* 122* 123 xdef real_inex 124 xdef inex 125inex: 126 link a6,#-LOCAL_SIZE 127 fsave -(sp) 128 cmpi.b #VER_40,(sp) ;test version number 129 bne.b not_fmt40 130 fmove.l fpsr,-(sp) 131 btst.b #E1,E_BYTE(a6) ;test for E1 set 132 beq.b not_b1232 133 btst.b #snan_bit,2(sp) ;test for snan 134 beq inex_ckofl 135 add.l #4,sp 136 frestore (sp)+ 137 unlk a6 138 bra snan 139inex_ckofl: 140 btst.b #ovfl_bit,2(sp) ;test for ovfl 141 beq inex_ckufl 142 add.l #4,sp 143 frestore (sp)+ 144 unlk a6 145 bra ovfl 146inex_ckufl: 147 btst.b #unfl_bit,2(sp) ;test for unfl 148 beq not_b1232 149 add.l #4,sp 150 frestore (sp)+ 151 unlk a6 152 bra unfl 153 154* 155* We do not have the bug 1232 case. Clean up the stack and call 156* real_inex. 157* 158not_b1232: 159 add.l #4,sp 160 frestore (sp)+ 161 unlk a6 162 163real_inex: 164 165 add.l #1,siginex ;for standalone testing 166 167 link a6,#-LOCAL_SIZE 168 fsave -(sp) 169not_fmt40: 170 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 171 beq.b inex_cke1 172* 173* Clear dirty bit on dest resister in the frame before branching 174* to b1238_fix. 175* 176 movem.l d0/d1,USER_DA(a6) 177 bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no 178 bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 179 bsr.l b1238_fix ;test for bug1238 case 180 movem.l USER_DA(a6),d0/d1 181 bra.b inex_done 182inex_cke1: 183 bclr.b #E1,E_BYTE(a6) 184inex_done: 185 frestore (sp)+ 186 unlk a6 187 rte 188 189* 190* Overflow exception 191* 192 xref fpsp_ovfl 193 xdef real_ovfl 194 xdef ovfl 195ovfl: 196 jmp fpsp_ovfl 197real_ovfl: 198 199 add.l #1,sigovfl ;for standalone testing 200 201 link a6,#-LOCAL_SIZE 202 fsave -(sp) 203 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 204 bne.b ovfl_done 205 bclr.b #E1,E_BYTE(a6) 206ovfl_done: 207 frestore (sp)+ 208 unlk a6 209 rte 210 211* 212* Underflow exception 213* 214 xref fpsp_unfl 215 xdef real_unfl 216 xdef unfl 217unfl: 218 jmp fpsp_unfl 219real_unfl: 220 221 add.l #1,sigunfl ;for standalone testing 222 223 link a6,#-LOCAL_SIZE 224 fsave -(sp) 225 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 226 bne.b unfl_done 227 bclr.b #E1,E_BYTE(a6) 228unfl_done: 229 frestore (sp)+ 230 unlk a6 231 rte 232 233* 234* Signalling NAN exception 235* 236 xref fpsp_snan 237 xdef real_snan 238 xdef snan 239snan: 240 jmp fpsp_snan 241real_snan: 242 link a6,#-LOCAL_SIZE 243 fsave -(sp) 244 bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception 245 frestore (sp)+ 246 unlk a6 247 248 add.l #1,sigsnan ;for standalone testing 249 rte 250 251* 252* Operand Error exception 253* 254 xref fpsp_operr 255 xdef real_operr 256 xdef operr 257operr: 258 jmp fpsp_operr 259real_operr: 260 link a6,#-LOCAL_SIZE 261 fsave -(sp) 262 bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception 263 frestore (sp)+ 264 unlk a6 265 266 add.l #1,sigoperr ;for standalone testing 267 268 rte 269 270* 271* BSUN exception 272* 273* This sample handler simply clears the nan bit in the FPSR. 274* 275 xref fpsp_bsun 276 xdef real_bsun 277 xdef bsun 278bsun: 279 jmp fpsp_bsun 280real_bsun: 281 link a6,#-LOCAL_SIZE 282 fsave -(sp) 283 bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception 284 fmove.l FPSR,-(sp) 285 bclr.b #nan_bit,(sp) 286 fmove.l (sp)+,FPSR 287 frestore (sp)+ 288 unlk a6 289 290 add.l #1,sigbsun ;for standalone testing 291 292 rte 293 294* 295* F-line exception 296* 297* A 'real' F-line exception is one that the FPSP isn't supposed to 298* handle. E.g. an instruction with a co-processor ID that is not 1. 299* 300* 301 xref fpsp_fline 302 xdef real_fline 303 xdef fline 304fline: 305 jmp fpsp_fline 306real_fline: 307 308 add.l #1,sigunimp ;for standalone testing 309 310 rte 311 312* 313* Unsupported data type exception 314* 315 xref fpsp_unsupp 316 xdef real_unsupp 317 xdef unsupp 318unsupp: 319 jmp fpsp_unsupp 320real_unsupp: 321 link a6,#-LOCAL_SIZE 322 fsave -(sp) 323 bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception 324 frestore (sp)+ 325 unlk a6 326 327 add.l #1,sigunsupp ;for standalone testing 328 329 rte 330 331* 332* Trace exception 333* 334 xdef real_trace 335real_trace: 336 rte 337 338* 339* fpsp_fmt_error --- exit point for frame format error 340* 341* The fpu stack frame does not match the frames existing 342* or planned at the time of this writing. The fpsp is 343* unable to handle frame sizes not in the following 344* version:size pairs: 345* 346* {4060, 4160} - busy frame 347* {4028, 4130} - unimp frame 348* {4000, 4100} - idle frame 349* 350* This entry point simply holds an f-line illegal value. 351* Replace this with a call to your kernel panic code or 352* code to handle future revisions of the fpu. 353* 354 xdef fpsp_fmt_error 355fpsp_fmt_error: 356 357 dc.l $f27f0000 ;f-line illegal 358 359* 360* fpsp_done --- FPSP exit point 361* 362* The exception has been handled by the package and we are ready 363* to return to user mode, but there may be OS specific code 364* to execute before we do. If there is, do it now. 365* 366* 367 xdef fpsp_done 368fpsp_done: 369 rte 370 371* 372* mem_write --- write to user or supervisor address space 373* 374* Writes to memory while in supervisor mode. copyout accomplishes 375* this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. 376* If you don't have copyout, use the local copy of the function below. 377* 378* a0 - supervisor source address 379* a1 - user destination address 380* d0 - number of bytes to write (maximum count is 12) 381* 382* The supervisor source address is guaranteed to point into the supervisor 383* stack. The result is that a UNIX 384* process is allowed to sleep as a consequence of a page fault during 385* copyout. The probability of a page fault is exceedingly small because 386* the 68040 always reads the destination address and thus the page 387* faults should have already been handled. 388* 389* If the EXC_SR shows that the exception was from supervisor space, 390* then just do a dumb (and slow) memory move. In a UNIX environment 391* there shouldn't be any supervisor mode floating point exceptions. 392* 393 xdef mem_write 394mem_write: 395 btst.b #5,EXC_SR(a6) ;check for supervisor state 396 beq.b user_write 397super_write: 398 move.b (a0)+,(a1)+ 399 subq.l #1,d0 400 bne.b super_write 401 rts 402user_write: 403 move.l d1,-(sp) ;preserve d1 just in case 404 move.l d0,-(sp) 405 move.l a1,-(sp) 406 move.l a0,-(sp) 407 jsr copyout 408 add.l #12,sp 409 move.l (sp)+,d1 410 rts 411* 412* mem_read --- read from user or supervisor address space 413* 414* Reads from memory while in supervisor mode. copyin accomplishes 415* this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. 416* If you don't have copyin, use the local copy of the function below. 417* 418* The FPSP calls mem_read to read the original F-line instruction in order 419* to extract the data register number when the 'Dn' addressing mode is 420* used. 421* 422*Input: 423* a0 - user source address 424* a1 - supervisor destination address 425* d0 - number of bytes to read (maximum count is 12) 426* 427* Like mem_write, mem_read always reads with a supervisor 428* destination address on the supervisor stack. Also like mem_write, 429* the EXC_SR is checked and a simple memory copy is done if reading 430* from supervisor space is indicated. 431* 432 xdef mem_read 433mem_read: 434 btst.b #5,EXC_SR(a6) ;check for supervisor state 435 beq.b user_read 436super_read: 437 move.b (a0)+,(a1)+ 438 subq.l #1,d0 439 bne.b super_read 440 rts 441user_read: 442 move.l d1,-(sp) ;preserve d1 just in case 443 move.l d0,-(sp) 444 move.l a1,-(sp) 445 move.l a0,-(sp) 446 jsr copyin 447 add.l #12,sp 448 move.l (sp)+,d1 449 rts 450 451* 452* Use these routines if your kernel doesn't have copyout/copyin equivalents. 453* Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC, 454* and copyin overwrites SFC. 455* 456copyout: 457 move.l 4(sp),a0 ; source 458 move.l 8(sp),a1 ; destination 459 move.l 12(sp),d0 ; count 460 sub.l #1,d0 ; dec count by 1 for dbra 461 move.l #1,d1 462 movec d1,DFC ; set dfc for user data space 463moreout: 464 move.b (a0)+,d1 ; fetch supervisor byte 465 moves.b d1,(a1)+ ; write user byte 466 dbf.w d0,moreout 467 rts 468 469copyin: 470 move.l 4(sp),a0 ; source 471 move.l 8(sp),a1 ; destination 472 move.l 12(sp),d0 ; count 473 sub.l #1,d0 ; dec count by 1 for dbra 474 move.l #1,d1 475 movec d1,SFC ; set sfc for user space 476morein: 477 moves.b (a0)+,d1 ; fetch user byte 478 move.b d1,(a1)+ ; write supervisor byte 479 dbf.w d0,morein 480 rts 481 482 end 483