root/arch/m68k/fpsp040/skeleton.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 |
   2 |       skeleton.sa 3.2 4/26/91
   3 |
   4 |       This file contains code that is system dependent and will
   5 |       need to be modified to install the FPSP.
   6 |
   7 |       Each entry point for exception 'xxxx' begins with a 'jmp fpsp_xxxx'.
   8 |       Put any target system specific handling that must be done immediately
   9 |       before the jump instruction.  If there no handling necessary, then
  10 |       the 'fpsp_xxxx' handler entry point should be placed in the exception
  11 |       table so that the 'jmp' can be eliminated. If the FPSP determines that the
  12 |       exception is one that must be reported then there will be a
  13 |       return from the package by a 'jmp real_xxxx'.  At that point
  14 |       the machine state will be identical to the state before
  15 |       the FPSP was entered.  In particular, whatever condition
  16 |       that caused the exception will still be pending when the FPSP
  17 |       package returns.  Thus, there will be system specific code
  18 |       to handle the exception.
  19 |
  20 |       If the exception was completely handled by the package, then
  21 |       the return will be via a 'jmp fpsp_done'.  Unless there is 
  22 |       OS specific work to be done (such as handling a context switch or
  23 |       interrupt) the user program can be resumed via 'rte'.
  24 |
  25 |       In the following skeleton code, some typical 'real_xxxx' handling
  26 |       code is shown.  This code may need to be moved to an appropriate
  27 |       place in the target system, or rewritten.
  28 |       
  29 
  30 |               Copyright (C) Motorola, Inc. 1990
  31 |                       All Rights Reserved
  32 |
  33 |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  34 |       The copyright notice above does not evidence any  
  35 |       actual or intended publication of such source code.
  36 
  37 |
  38 |       Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
  39 |
  40 
  41 #include <linux/linkage.h>
  42 
  43 |SKELETON       idnt    2,1 | Motorola 040 Floating Point Software Package
  44 
  45         |section 15
  46 |
  47 |       The following counters are used for standalone testing
  48 |
  49 sigunimp:       .long   0
  50 sigbsun:                .long   0
  51 siginex:                .long   0
  52 sigdz:          .long   0
  53 sigunfl:                .long   0
  54 sigovfl:                .long   0
  55 sigoperr:       .long   0
  56 sigsnan:                .long   0
  57 sigunsupp:      .long   0
  58 
  59         |section 8
  60  
  61         .include "fpsp.h"
  62 
  63 LOFF_ORIG_D0    = 0x20
  64 
  65 #define SAVE_ALL                                \
  66         clrl    %sp@-;     /* stk_adj */        \
  67         movel   %d0,%sp@-; /* orig d0 */        \
  68         movel   %d0,%sp@-; /* d0 */             \
  69         moveml  %d1-%d5/%a0-%a1,%sp@-
  70 
  71         |xref   b1238_fix
  72 
  73 |
  74 |       Divide by Zero exception
  75 |
  76 |       All dz exceptions are 'real', hence no fpsp_dz entry point.
  77 |
  78         .global dz
  79         .global real_dz
  80 dz:
  81 real_dz:
  82         link            %a6,#-LOCAL_SIZE
  83         fsave           -(%sp)
  84         bclrb           #E1,E_BYTE(%a6)
  85         frestore        (%sp)+
  86         unlk            %a6
  87 
  88         addl    #1,sigdz                |for standalone testing
  89 
  90         SAVE_ALL
  91         moveq   #-1,%d0
  92         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
  93                                         | signifies that the stack frame
  94                                         | is NOT for syscall
  95         movel   %sp,%sp@-               | stack frame pointer argument
  96         bsrl    SYMBOL_NAME(trap_c)
  97         addql   #4,%sp
  98         bral    SYMBOL_NAME(ret_from_exception)
  99 
 100 |
 101 |       Inexact exception
 102 |
 103 |       All inexact exceptions are real, but the 'real' handler
 104 |       will probably want to clear the pending exception.
 105 |       The provided code will clear the E3 exception (if pending), 
 106 |       otherwise clear the E1 exception.  The frestore is not really
 107 |       necessary for E1 exceptions.
 108 |
 109 | Code following the 'inex' label is to handle bug #1232.  In this
 110 | bug, if an E1 snan, ovfl, or unfl occurred, and the process was
 111 | swapped out before taking the exception, the exception taken on
 112 | return was inex, rather than the correct exception.  The snan, ovfl,
 113 | and unfl exception to be taken must not have been enabled.  The
 114 | fix is to check for E1, and the existence of one of snan, ovfl,
 115 | or unfl bits set in the fpsr.  If any of these are set, branch
 116 | to the appropriate  handler for the exception in the fpsr.  Note
 117 | that this fix is only for d43b parts, and is skipped if the
 118 | version number is not $40.
 119 | 
 120 |
 121         .global real_inex
 122         .global inex
 123 inex:
 124         link            %a6,#-LOCAL_SIZE
 125         fsave           -(%sp)
 126         cmpib           #VER_40,(%sp)           |test version number
 127         bnes            not_fmt40
 128         fmovel          %fpsr,-(%sp)
 129         btstb           #E1,E_BYTE(%a6)         |test for E1 set
 130         beqs            not_b1232
 131         btstb           #snan_bit,2(%sp) |test for snan
 132         beq             inex_ckofl
 133         addl            #4,%sp
 134         frestore        (%sp)+
 135         unlk            %a6
 136         bra             snan
 137 inex_ckofl:
 138         btstb           #ovfl_bit,2(%sp) |test for ovfl
 139         beq             inex_ckufl 
 140         addl            #4,%sp
 141         frestore        (%sp)+
 142         unlk            %a6
 143         bra             ovfl
 144 inex_ckufl:
 145         btstb           #unfl_bit,2(%sp) |test for unfl
 146         beq             not_b1232
 147         addl            #4,%sp
 148         frestore        (%sp)+
 149         unlk            %a6
 150         bra             unfl
 151 
 152 |
 153 | We do not have the bug 1232 case.  Clean up the stack and call
 154 | real_inex.
 155 |
 156 not_b1232:
 157         addl            #4,%sp
 158         frestore        (%sp)+
 159         unlk            %a6
 160 
 161 real_inex:
 162 
 163         addl            #1,siginex              |for standalone testing
 164 
 165         link            %a6,#-LOCAL_SIZE
 166         fsave           -(%sp)
 167 not_fmt40:
 168         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 169         beqs            inex_cke1
 170 |
 171 | Clear dirty bit on dest resister in the frame before branching
 172 | to b1238_fix.
 173 |
 174         moveml          %d0/%d1,USER_DA(%a6)
 175         bfextu          CMDREG1B(%a6){#6:#3},%d0                |get dest reg no
 176         bclrb           %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
 177         bsrl            b1238_fix               |test for bug1238 case
 178         moveml          USER_DA(%a6),%d0/%d1
 179         bras            inex_done
 180 inex_cke1:
 181         bclrb           #E1,E_BYTE(%a6)
 182 inex_done:
 183         frestore        (%sp)+
 184         unlk            %a6
 185 
 186         SAVE_ALL
 187         moveq   #-1,%d0
 188         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 189                                         | signifies that the stack frame
 190                                         | is NOT for syscall
 191         movel   %sp,%sp@-               | stack frame pointer argument
 192         bsrl    SYMBOL_NAME(trap_c)
 193         addql   #4,%sp
 194         bral    SYMBOL_NAME(ret_from_exception)
 195         
 196 |
 197 |       Overflow exception
 198 |
 199         |xref   fpsp_ovfl
 200         .global real_ovfl
 201         .global ovfl
 202 ovfl:
 203         jmp     fpsp_ovfl
 204 real_ovfl:
 205 
 206         addl            #1,sigovfl              |for standalone testing
 207 
 208         link            %a6,#-LOCAL_SIZE
 209         fsave           -(%sp)
 210         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 211         bnes            ovfl_done
 212         bclrb           #E1,E_BYTE(%a6)
 213 ovfl_done:
 214         frestore        (%sp)+
 215         unlk            %a6
 216 
 217         SAVE_ALL
 218         moveq   #-1,%d0
 219         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 220                                         | signifies that the stack frame
 221                                         | is NOT for syscall
 222         movel   %sp,%sp@-               | stack frame pointer argument
 223         bsrl    SYMBOL_NAME(trap_c)
 224         addql   #4,%sp
 225         bral    SYMBOL_NAME(ret_from_exception)
 226         
 227 |
 228 |       Underflow exception
 229 |
 230         |xref   fpsp_unfl
 231         .global real_unfl
 232         .global unfl
 233 unfl:
 234         jmp     fpsp_unfl
 235 real_unfl:
 236 
 237         addl            #1,sigunfl              |for standalone testing
 238 
 239         link            %a6,#-LOCAL_SIZE
 240         fsave           -(%sp)
 241         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 242         bnes            unfl_done
 243         bclrb           #E1,E_BYTE(%a6)
 244 unfl_done:
 245         frestore        (%sp)+
 246         unlk            %a6
 247 
 248         SAVE_ALL
 249         moveq   #-1,%d0
 250         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 251                                         | signifies that the stack frame
 252                                         | is NOT for syscall
 253         movel   %sp,%sp@-               | stack frame pointer argument
 254         bsrl    SYMBOL_NAME(trap_c)
 255         addql   #4,%sp
 256         bral    SYMBOL_NAME(ret_from_exception)
 257         
 258 |
 259 |       Signalling NAN exception
 260 |
 261         |xref   fpsp_snan
 262         .global real_snan
 263         .global snan
 264 snan:
 265         jmp     fpsp_snan
 266 real_snan:
 267         link            %a6,#-LOCAL_SIZE
 268         fsave           -(%sp)
 269         bclrb           #E1,E_BYTE(%a6) |snan is always an E1 exception
 270         frestore        (%sp)+
 271         unlk            %a6
 272 
 273         addl            #1,sigsnan              |for standalone testing
 274 
 275         SAVE_ALL
 276         moveq   #-1,%d0
 277         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 278                                         | signifies that the stack frame
 279                                         | is NOT for syscall
 280         movel   %sp,%sp@-               | stack frame pointer argument
 281         bsrl    SYMBOL_NAME(trap_c)
 282         addql   #4,%sp
 283         bral    SYMBOL_NAME(ret_from_exception)
 284         
 285 |
 286 |       Operand Error exception
 287 |
 288         |xref   fpsp_operr
 289         .global real_operr
 290         .global operr
 291 operr:
 292         jmp     fpsp_operr
 293 real_operr:
 294         link            %a6,#-LOCAL_SIZE
 295         fsave           -(%sp)
 296         bclrb           #E1,E_BYTE(%a6) |operr is always an E1 exception
 297         frestore        (%sp)+
 298         unlk            %a6
 299 
 300         addl            #1,sigoperr             |for standalone testing
 301 
 302 
 303         SAVE_ALL
 304         moveq   #-1,%d0
 305         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 306                                         | signifies that the stack frame
 307                                         | is NOT for syscall
 308         movel   %sp,%sp@-               | stack frame pointer argument
 309         bsrl    SYMBOL_NAME(trap_c)
 310         addql   #4,%sp
 311         bral    SYMBOL_NAME(ret_from_exception)
 312 
 313         
 314 |
 315 |       BSUN exception
 316 |
 317 |       This sample handler simply clears the nan bit in the FPSR.
 318 |
 319         |xref   fpsp_bsun
 320         .global real_bsun
 321         .global bsun
 322 bsun:
 323         jmp     fpsp_bsun
 324 real_bsun:
 325         link            %a6,#-LOCAL_SIZE
 326         fsave           -(%sp)
 327         bclrb           #E1,E_BYTE(%a6) |bsun is always an E1 exception
 328         fmovel          %FPSR,-(%sp)
 329         bclrb           #nan_bit,(%sp)
 330         fmovel          (%sp)+,%FPSR
 331         frestore        (%sp)+
 332         unlk            %a6
 333 
 334         addl            #1,sigbsun              |for standalone testing
 335 
 336 
 337 
 338         SAVE_ALL
 339         moveq   #-1,%d0
 340         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 341                                         | signifies that the stack frame
 342                                         | is NOT for syscall
 343         movel   %sp,%sp@-               | stack frame pointer argument
 344         bsrl    SYMBOL_NAME(trap_c)
 345         addql   #4,%sp
 346         bral    SYMBOL_NAME(ret_from_exception)
 347 
 348 |
 349 |       F-line exception
 350 |
 351 |       A 'real' F-line exception is one that the FPSP isn't supposed to 
 352 |       handle. E.g. an instruction with a co-processor ID that is not 1.
 353 |
 354 |
 355         |xref   fpsp_fline
 356         .global real_fline
 357         .global fline
 358 fline:
 359         jmp     fpsp_fline
 360 real_fline:
 361 
 362         addl            #1,sigunimp             |for standalone testing
 363 
 364 
 365         SAVE_ALL
 366         moveq   #-1,%d0
 367         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 368                                         | signifies that the stack frame
 369                                         | is NOT for syscall
 370         movel   %sp,%sp@-               | stack frame pointer argument
 371         bsrl    SYMBOL_NAME(trap_c)
 372         addql   #4,%sp
 373         bral    SYMBOL_NAME(ret_from_exception)
 374 
 375 |
 376 |       Unsupported data type exception
 377 |
 378         |xref   fpsp_unsupp
 379         .global real_unsupp
 380         .global unsupp
 381 unsupp:
 382         jmp     fpsp_unsupp
 383 real_unsupp:
 384         link            %a6,#-LOCAL_SIZE
 385         fsave           -(%sp)
 386         bclrb           #E1,E_BYTE(%a6) |unsupp is always an E1 exception
 387         frestore        (%sp)+
 388         unlk            %a6
 389 
 390         addl            #1,sigunsupp            |for standalone testing
 391 
 392 
 393         SAVE_ALL
 394         moveq   #-1,%d0
 395         movel   %d0,%sp@(LOFF_ORIG_D0)    | a -1 in the ORIG_D0 field
 396                                         | signifies that the stack frame
 397                                         | is NOT for syscall
 398         movel   %sp,%sp@-               | stack frame pointer argument
 399         bsrl    SYMBOL_NAME(trap_c)
 400         addql   #4,%sp
 401         bral    SYMBOL_NAME(ret_from_exception)
 402 
 403 |
 404 |       Trace exception
 405 |
 406         .global real_trace
 407 real_trace:
 408         |
 409         bral    SYMBOL_NAME(trap)
 410 
 411 |
 412 |       fpsp_fmt_error --- exit point for frame format error
 413 |
 414 |       The fpu stack frame does not match the frames existing
 415 |       or planned at the time of this writing.  The fpsp is
 416 |       unable to handle frame sizes not in the following
 417 |       version:size pairs:
 418 |
 419 |       {4060, 4160} - busy frame
 420 |       {4028, 4130} - unimp frame
 421 |       {4000, 4100} - idle frame
 422 |
 423 |       This entry point simply holds an f-line illegal value.  
 424 |       Replace this with a call to your kernel panic code or
 425 |       code to handle future revisions of the fpu.
 426 |
 427         .global fpsp_fmt_error
 428 fpsp_fmt_error:
 429 
 430         .long   0xf27f0000      |f-line illegal 
 431 
 432 |
 433 |       fpsp_done --- FPSP exit point
 434 |
 435 |       The exception has been handled by the package and we are ready
 436 |       to return to user mode, but there may be OS specific code
 437 |       to execute before we do.  If there is, do it now.
 438 |
 439 |
 440 
 441         .global fpsp_done
 442 fpsp_done:
 443         btst    #0x5,%sp@               | supervisor bit set in saved SR?
 444         beq     Lnotkern
 445         rte
 446 Lnotkern:
 447         tstl    SYMBOL_NAME(need_resched)
 448         bne     Lmustsched
 449         rte
 450 Lmustsched:
 451         SAVE_ALL
 452         moveq   #-1,%d0
 453         movel   %d0,%sp@(LOFF_ORIG_D0)    | indicate stack frame not for syscall
 454         bral    SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc..
 455         
 456 
 457 |
 458 |       mem_write --- write to user or supervisor address space
 459 |
 460 | Writes to memory while in supervisor mode.  copyout accomplishes
 461 | this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
 462 | If you don't have copyout, use the local copy of the function below.
 463 |
 464 |       a0 - supervisor source address
 465 |       a1 - user destination address
 466 |       d0 - number of bytes to write (maximum count is 12)
 467 |
 468 | The supervisor source address is guaranteed to point into the supervisor
 469 | stack.  The result is that a UNIX
 470 | process is allowed to sleep as a consequence of a page fault during
 471 | copyout.  The probability of a page fault is exceedingly small because
 472 | the 68040 always reads the destination address and thus the page
 473 | faults should have already been handled.
 474 |
 475 | If the EXC_SR shows that the exception was from supervisor space,
 476 | then just do a dumb (and slow) memory move.  In a UNIX environment
 477 | there shouldn't be any supervisor mode floating point exceptions.
 478 |
 479         .global mem_write
 480 mem_write:
 481         btstb   #5,EXC_SR(%a6)  |check for supervisor state
 482         beqs    user_write
 483 super_write:
 484         moveb   (%a0)+,(%a1)+
 485         subql   #1,%d0
 486         bnes    super_write
 487         rts
 488 user_write:
 489         movel   %d1,-(%sp)      |preserve d1 just in case
 490         movel   %d0,-(%sp)
 491         movel   %a1,-(%sp)
 492         movel   %a0,-(%sp)
 493         jsr             copyout
 494         addw    #12,%sp
 495         movel   (%sp)+,%d1
 496         rts
 497 |
 498 |       mem_read --- read from user or supervisor address space
 499 |
 500 | Reads from memory while in supervisor mode.  copyin accomplishes
 501 | this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
 502 | If you don't have copyin, use the local copy of the function below.
 503 |
 504 | The FPSP calls mem_read to read the original F-line instruction in order
 505 | to extract the data register number when the 'Dn' addressing mode is
 506 | used.
 507 |
 508 |Input:
 509 |       a0 - user source address
 510 |       a1 - supervisor destination address
 511 |       d0 - number of bytes to read (maximum count is 12)
 512 |
 513 | Like mem_write, mem_read always reads with a supervisor 
 514 | destination address on the supervisor stack.  Also like mem_write,
 515 | the EXC_SR is checked and a simple memory copy is done if reading
 516 | from supervisor space is indicated.
 517 |
 518         .global mem_read
 519 mem_read:
 520         btstb   #5,EXC_SR(%a6)  |check for supervisor state
 521         beqs    user_read
 522 super_read:
 523         moveb   (%a0)+,(%a1)+
 524         subql   #1,%d0
 525         bnes    super_read
 526         rts
 527 user_read:
 528         movel   %d1,-(%sp)      |preserve d1 just in case
 529         movel   %d0,-(%sp)
 530         movel   %a1,-(%sp)
 531         movel   %a0,-(%sp)
 532         jsr             copyin
 533         addw    #12,%sp
 534         movel   (%sp)+,%d1
 535         rts
 536 
 537 |
 538 | Use these routines if your kernel doesn't have copyout/copyin equivalents.
 539 | Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
 540 | and copyin overwrites SFC.
 541 |
 542 copyout:
 543         movel   4(%sp),%a0      | source
 544         movel   8(%sp),%a1      | destination
 545         movel   12(%sp),%d0     | count
 546         subl    #1,%d0          | dec count by 1 for dbra
 547         movel   #1,%d1
 548         movec   %d1,%DFC                | set dfc for user data space
 549 moreout:
 550         moveb   (%a0)+,%d1      | fetch supervisor byte
 551         movesb  %d1,(%a1)+      | write user byte
 552         dbf     %d0,moreout
 553         rts
 554 
 555 copyin:
 556         movel   4(%sp),%a0      | source
 557         movel   8(%sp),%a1      | destination
 558         movel   12(%sp),%d0     | count
 559         subl    #1,%d0          | dec count by 1 for dbra
 560         movel   #1,%d1
 561         movec   %d1,%SFC                | set sfc for user space
 562 morein:
 563         movesb  (%a0)+,%d1      | fetch user byte
 564         moveb   %d1,(%a1)+      | write supervisor byte
 565         dbf     %d0,morein
 566         rts
 567 
 568         |end

/* [previous][next][first][last][top][bottom][index][help] */