1 * $NetBSD: netbsd.sa,v 1.6 2024/09/20 19:38:53 andvar 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 62 SKELETON IDNT 2,1 Motorola 040 Floating Point Software Package 63 64 section 15 65 * 66 * The following counters are used for standalone testing 67 * 68 69 section 8 70 71 include fpsp.h 72 73 * 74 * XXX Note, this is NOT valid Motorola syntax, but what else can we do? 75 * 76 #include <machine/asm.h> 77 78 xref b1238_fix 79 xref _C_LABEL(mmutype) 80 81 * 82 * Divide by Zero exception 83 * 84 * All dz exceptions are 'real', hence no fpsp_dz entry point. 85 * 86 xdef dz 87 xdef real_dz 88 dz: 89 cmp.l #-2,_C_LABEL(mmutype) 90 bne.l _C_LABEL(fpfault) 91 real_dz: 92 link a6,#-LOCAL_SIZE 93 fsave -(sp) 94 bclr.b #E1,E_BYTE(a6) 95 frestore (sp)+ 96 unlk a6 97 jmp _C_LABEL(fpfault) 98 99 * 100 * Inexact exception 101 * 102 * All inexact exceptions are real, but the 'real' handler 103 * will probably want to clear the pending exception. 104 * The provided code will clear the E3 exception (if pending), 105 * otherwise clear the E1 exception. The frestore is not really 106 * necessary for E1 exceptions. 107 * 108 * Code following the 'inex' label is to handle bug #1232. In this 109 * bug, if an E1 snan, ovfl, or unfl occurred, and the process was 110 * swapped out before taking the exception, the exception taken on 111 * return was inex, rather than the correct exception. The snan, ovfl, 112 * and unfl exception to be taken must not have been enabled. The 113 * fix is to check for E1, and the existence of one of snan, ovfl, 114 * or unfl bits set in the fpsr. If any of these are set, branch 115 * to the appropriate handler for the exception in the fpsr. Note 116 * that this fix is only for d43b parts, and is skipped if the 117 * version number is not $40. 118 * 119 * 120 xdef real_inex 121 xdef inex 122 inex: 123 cmp.l #-2,_C_LABEL(mmutype) 124 bne.l _C_LABEL(fpfault) 125 link a6,#-LOCAL_SIZE 126 fsave -(sp) 127 cmpi.b #VER_40,(sp) ;test version number 128 bne.b not_fmt40 129 fmove.l fpsr,-(sp) 130 btst.b #E1,E_BYTE(a6) ;test for E1 set 131 beq.b not_b1232 132 btst.b #snan_bit,2(sp) ;test for snan 133 beq inex_ckofl 134 addq.l #4,sp 135 frestore (sp)+ 136 unlk a6 137 bra snan 138 inex_ckofl: 139 btst.b #ovfl_bit,2(sp) ;test for ovfl 140 beq inex_ckufl 141 addq.l #4,sp 142 frestore (sp)+ 143 unlk a6 144 bra ovfl 145 inex_ckufl: 146 btst.b #unfl_bit,2(sp) ;test for unfl 147 beq not_b1232 148 addq.l #4,sp 149 frestore (sp)+ 150 unlk a6 151 bra unfl 152 153 * 154 * We do not have the bug 1232 case. Clean up the stack and call 155 * real_inex. 156 * 157 not_b1232: 158 addq.l #4,sp 159 frestore (sp)+ 160 unlk a6 161 162 real_inex: 163 link a6,#-LOCAL_SIZE 164 fsave -(sp) 165 not_fmt40: 166 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 167 beq.b inex_cke1 168 * 169 * Clear dirty bit on dest register in the frame before branching 170 * to b1238_fix. 171 * 172 movem.l d0/d1,USER_DA(a6) 173 bfextu CMDREG1B(a6){6:3},d0 ;get dest reg no 174 bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 175 bsr.l b1238_fix ;test for bug1238 case 176 movem.l USER_DA(a6),d0/d1 177 bra.b inex_done 178 inex_cke1: 179 bclr.b #E1,E_BYTE(a6) 180 inex_done: 181 frestore (sp)+ 182 unlk a6 183 jmp _C_LABEL(fpfault) 184 185 * 186 * Overflow exception 187 * 188 xref fpsp_ovfl 189 xdef real_ovfl 190 xdef ovfl 191 ovfl: 192 cmp.l #-2,_C_LABEL(mmutype) 193 beq.l fpsp_ovfl 194 jmp _C_LABEL(fpfault) 195 real_ovfl: 196 link a6,#-LOCAL_SIZE 197 fsave -(sp) 198 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 199 bne.b ovfl_done 200 bclr.b #E1,E_BYTE(a6) 201 ovfl_done: 202 frestore (sp)+ 203 unlk a6 204 jmp _C_LABEL(fpfault) 205 206 * 207 * Underflow exception 208 * 209 xref fpsp_unfl 210 xdef real_unfl 211 xdef unfl 212 unfl: 213 cmp.l #-2,_C_LABEL(mmutype) 214 beq.l fpsp_unfl 215 jmp _C_LABEL(fpfault) 216 real_unfl: 217 link a6,#-LOCAL_SIZE 218 fsave -(sp) 219 bclr.b #E3,E_BYTE(a6) ;clear and test E3 flag 220 bne.b unfl_done 221 bclr.b #E1,E_BYTE(a6) 222 unfl_done: 223 frestore (sp)+ 224 unlk a6 225 jmp _C_LABEL(fpfault) 226 227 * 228 * Signalling NAN exception 229 * 230 xref fpsp_snan 231 xdef real_snan 232 xdef snan 233 snan: 234 cmp.l #-2,_C_LABEL(mmutype) 235 beq.l fpsp_snan 236 jmp _C_LABEL(fpfault) 237 real_snan: 238 link a6,#-LOCAL_SIZE 239 fsave -(sp) 240 bclr.b #E1,E_BYTE(a6) ;snan is always an E1 exception 241 frestore (sp)+ 242 unlk a6 243 jmp _C_LABEL(fpfault) 244 245 * 246 * Operand Error exception 247 * 248 xref fpsp_operr 249 xdef real_operr 250 xdef operr 251 operr: 252 cmp.l #-2,_C_LABEL(mmutype) 253 beq.l fpsp_operr 254 jmp _C_LABEL(fpfault) 255 real_operr: 256 link a6,#-LOCAL_SIZE 257 fsave -(sp) 258 bclr.b #E1,E_BYTE(a6) ;operr is always an E1 exception 259 frestore (sp)+ 260 unlk a6 261 jmp _C_LABEL(fpfault) 262 263 * 264 * BSUN exception 265 * 266 * This sample handler simply clears the nan bit in the FPSR. 267 * 268 xref fpsp_bsun 269 xdef real_bsun 270 xdef bsun 271 bsun: 272 cmp.l #-2,_C_LABEL(mmutype) 273 beq.l fpsp_bsun 274 jmp _C_LABEL(fpfault) 275 real_bsun: 276 link a6,#-LOCAL_SIZE 277 fsave -(sp) 278 bclr.b #E1,E_BYTE(a6) ;bsun is always an E1 exception 279 fmove.l FPSR,-(sp) 280 bclr.b #nan_bit,(sp) 281 fmove.l (sp)+,FPSR 282 frestore (sp)+ 283 unlk a6 284 jmp _C_LABEL(fpfault) 285 286 * 287 * F-line exception 288 * 289 * A 'real' F-line exception is one that the FPSP isn't supposed to 290 * handle. E.g. an instruction with a co-processor ID that is not 1. 291 * 292 * 293 xref fpsp_fline 294 xdef real_fline 295 xdef fline 296 fline: 297 cmp.l #-2,_C_LABEL(mmutype) 298 beq.l fpsp_fline 299 jmp _C_LABEL(fpfault) 300 real_fline: 301 jmp _C_LABEL(fpfault) 302 303 * 304 * Unsupported data type exception 305 * 306 xref fpsp_unsupp 307 xdef real_unsupp 308 xdef unsupp 309 unsupp: 310 cmp.l #-2,_C_LABEL(mmutype) 311 beq.l fpsp_unsupp 312 jmp _C_LABEL(fpfault) 313 real_unsupp: 314 link a6,#-LOCAL_SIZE 315 fsave -(sp) 316 bclr.b #E1,E_BYTE(a6) ;unsupp is always an E1 exception 317 frestore (sp)+ 318 unlk a6 319 jmp _C_LABEL(fpfault) 320 321 * 322 * Trace exception 323 * 324 xdef real_trace 325 real_trace: 326 rte 327 328 * 329 * fpsp_fmt_error --- exit point for frame format error 330 * 331 * The fpu stack frame does not match the frames existing 332 * or planned at the time of this writing. The fpsp is 333 * unable to handle frame sizes not in the following 334 * version:size pairs: 335 * 336 * {4060, 4160} - busy frame 337 * {4028, 4130} - unimp frame 338 * {4000, 4100} - idle frame 339 * 340 * This entry point simply holds an f-line illegal value. 341 * Replace this with a call to your kernel panic code or 342 * code to handle future revisions of the fpu. 343 * 344 xdef fpsp_fmt_error 345 fpsp_fmt_error: 346 pea 1f 347 jsr _C_LABEL(panic) 348 dc.l $f27f0000 ;f-line illegal 349 1: 350 .asciz "bad floating point stack frame" 351 .even 352 353 * 354 * fpsp_done --- FPSP exit point 355 * 356 * The exception has been handled by the package and we are ready 357 * to return to user mode, but there may be OS specific code 358 * to execute before we do. If there is, do it now. 359 * 360 * 361 xref _ASM_LABEL(rei) 362 xdef fpsp_done 363 fpsp_done: 364 jmp _ASM_LABEL(rei) 365 366 * 367 * mem_write --- write to user or supervisor address space 368 * 369 * Writes to memory while in supervisor mode. copyout accomplishes 370 * this via a 'moves' instruction. copyout is a UNIX SVR3 (and later) function. 371 * If you don't have copyout, use the local copy of the function below. 372 * 373 * a0 - supervisor source address 374 * a1 - user destination address 375 * d0 - number of bytes to write (maximum count is 12) 376 * 377 * The supervisor source address is guaranteed to point into the supervisor 378 * stack. The result is that a UNIX 379 * process is allowed to sleep as a consequence of a page fault during 380 * copyout. The probability of a page fault is exceedingly small because 381 * the 68040 always reads the destination address and thus the page 382 * faults should have already been handled. 383 * 384 * If the EXC_SR shows that the exception was from supervisor space, 385 * then just do a dumb (and slow) memory move. In a UNIX environment 386 * there shouldn't be any supervisor mode floating point exceptions. 387 * 388 xdef mem_write 389 mem_write: 390 btst.b #5,EXC_SR(a6) ;check for supervisor state 391 beq.b user_write 392 super_write: 393 move.b (a0)+,(a1)+ 394 subq.l #1,d0 395 bne.b super_write 396 rts 397 user_write: 398 move.l d1,-(sp) ;preserve d1 just in case 399 move.l d0,-(sp) 400 move.l a1,-(sp) 401 move.l a0,-(sp) 402 jsr _C_LABEL(copyout) 403 add.l #12,sp 404 move.l (sp)+,d1 405 rts 406 407 * 408 * mem_read --- read from user or supervisor address space 409 * 410 * Reads from memory while in supervisor mode. copyin accomplishes 411 * this via a 'moves' instruction. copyin is a UNIX SVR3 (and later) function. 412 * If you don't have copyin, use the local copy of the function below. 413 * 414 * The FPSP calls mem_read to read the original F-line instruction in order 415 * to extract the data register number when the 'Dn' addressing mode is 416 * used. 417 * 418 *Input: 419 * a0 - user source address 420 * a1 - supervisor destination address 421 * d0 - number of bytes to read (maximum count is 12) 422 * 423 * Like mem_write, mem_read always reads with a supervisor 424 * destination address on the supervisor stack. Also like mem_write, 425 * the EXC_SR is checked and a simple memory copy is done if reading 426 * from supervisor space is indicated. 427 * 428 xdef mem_read 429 mem_read: 430 btst.b #5,EXC_SR(a6) ;check for supervisor state 431 beq.b user_read 432 super_read: 433 move.b (a0)+,(a1)+ 434 subq.l #1,d0 435 bne.b super_read 436 rts 437 user_read: 438 move.l d1,-(sp) ;preserve d1 just in case 439 move.l d0,-(sp) 440 move.l a1,-(sp) 441 move.l a0,-(sp) 442 jsr _C_LABEL(copyin) 443 add.l #12,sp 444 move.l (sp)+,d1 445 rts 446 447 end 448