root/arch/m68k/fpsp040/skeleton.S

/* [<][>][^][v][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 |       For details on the license for this file, please see the
  34 |       file, README, in this same directory.
  35 
  36 |
  37 |       Modified for Linux-1.3.x by Jes Sorensen (jds@kom.auc.dk)
  38 |
  39 
  40 #include <linux/linkage.h>
  41 #include <asm/entry.h>
  42 #include <asm/asm-offsets.h>
  43 
  44 |SKELETON       idnt    2,1 | Motorola 040 Floating Point Software Package
  45 
  46         |section 15
  47 |
  48 |       The following counters are used for standalone testing
  49 |
  50 
  51         |section 8
  52 
  53 #include "fpsp.h"
  54 
  55         |xref   b1238_fix
  56 
  57 |
  58 |       Divide by Zero exception
  59 |
  60 |       All dz exceptions are 'real', hence no fpsp_dz entry point.
  61 |
  62         .global dz
  63         .global real_dz
  64 dz:
  65 real_dz:
  66         link            %a6,#-LOCAL_SIZE
  67         fsave           -(%sp)
  68         bclrb           #E1,E_BYTE(%a6)
  69         frestore        (%sp)+
  70         unlk            %a6
  71 
  72         SAVE_ALL_INT
  73         GET_CURRENT(%d0)
  74         movel   %sp,%sp@-               | stack frame pointer argument
  75         bsrl    trap_c
  76         addql   #4,%sp
  77         bral    ret_from_exception
  78 
  79 |
  80 |       Inexact exception
  81 |
  82 |       All inexact exceptions are real, but the 'real' handler
  83 |       will probably want to clear the pending exception.
  84 |       The provided code will clear the E3 exception (if pending),
  85 |       otherwise clear the E1 exception.  The frestore is not really
  86 |       necessary for E1 exceptions.
  87 |
  88 | Code following the 'inex' label is to handle bug #1232.  In this
  89 | bug, if an E1 snan, ovfl, or unfl occurred, and the process was
  90 | swapped out before taking the exception, the exception taken on
  91 | return was inex, rather than the correct exception.  The snan, ovfl,
  92 | and unfl exception to be taken must not have been enabled.  The
  93 | fix is to check for E1, and the existence of one of snan, ovfl,
  94 | or unfl bits set in the fpsr.  If any of these are set, branch
  95 | to the appropriate  handler for the exception in the fpsr.  Note
  96 | that this fix is only for d43b parts, and is skipped if the
  97 | version number is not $40.
  98 |
  99 |
 100         .global real_inex
 101         .global inex
 102 inex:
 103         link            %a6,#-LOCAL_SIZE
 104         fsave           -(%sp)
 105         cmpib           #VER_40,(%sp)           |test version number
 106         bnes            not_fmt40
 107         fmovel          %fpsr,-(%sp)
 108         btstb           #E1,E_BYTE(%a6)         |test for E1 set
 109         beqs            not_b1232
 110         btstb           #snan_bit,2(%sp) |test for snan
 111         beq             inex_ckofl
 112         addl            #4,%sp
 113         frestore        (%sp)+
 114         unlk            %a6
 115         bra             snan
 116 inex_ckofl:
 117         btstb           #ovfl_bit,2(%sp) |test for ovfl
 118         beq             inex_ckufl
 119         addl            #4,%sp
 120         frestore        (%sp)+
 121         unlk            %a6
 122         bra             ovfl
 123 inex_ckufl:
 124         btstb           #unfl_bit,2(%sp) |test for unfl
 125         beq             not_b1232
 126         addl            #4,%sp
 127         frestore        (%sp)+
 128         unlk            %a6
 129         bra             unfl
 130 
 131 |
 132 | We do not have the bug 1232 case.  Clean up the stack and call
 133 | real_inex.
 134 |
 135 not_b1232:
 136         addl            #4,%sp
 137         frestore        (%sp)+
 138         unlk            %a6
 139 
 140 real_inex:
 141 
 142         link            %a6,#-LOCAL_SIZE
 143         fsave           -(%sp)
 144 not_fmt40:
 145         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 146         beqs            inex_cke1
 147 |
 148 | Clear dirty bit on dest resister in the frame before branching
 149 | to b1238_fix.
 150 |
 151         moveml          %d0/%d1,USER_DA(%a6)
 152         bfextu          CMDREG1B(%a6){#6:#3},%d0                |get dest reg no
 153         bclrb           %d0,FPR_DIRTY_BITS(%a6) |clr dest dirty bit
 154         bsrl            b1238_fix               |test for bug1238 case
 155         moveml          USER_DA(%a6),%d0/%d1
 156         bras            inex_done
 157 inex_cke1:
 158         bclrb           #E1,E_BYTE(%a6)
 159 inex_done:
 160         frestore        (%sp)+
 161         unlk            %a6
 162 
 163         SAVE_ALL_INT
 164         GET_CURRENT(%d0)
 165         movel   %sp,%sp@-               | stack frame pointer argument
 166         bsrl    trap_c
 167         addql   #4,%sp
 168         bral    ret_from_exception
 169 
 170 |
 171 |       Overflow exception
 172 |
 173         |xref   fpsp_ovfl
 174         .global real_ovfl
 175         .global ovfl
 176 ovfl:
 177         jmp     fpsp_ovfl
 178 real_ovfl:
 179 
 180         link            %a6,#-LOCAL_SIZE
 181         fsave           -(%sp)
 182         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 183         bnes            ovfl_done
 184         bclrb           #E1,E_BYTE(%a6)
 185 ovfl_done:
 186         frestore        (%sp)+
 187         unlk            %a6
 188 
 189         SAVE_ALL_INT
 190         GET_CURRENT(%d0)
 191         movel   %sp,%sp@-               | stack frame pointer argument
 192         bsrl    trap_c
 193         addql   #4,%sp
 194         bral    ret_from_exception
 195 
 196 |
 197 |       Underflow exception
 198 |
 199         |xref   fpsp_unfl
 200         .global real_unfl
 201         .global unfl
 202 unfl:
 203         jmp     fpsp_unfl
 204 real_unfl:
 205 
 206         link            %a6,#-LOCAL_SIZE
 207         fsave           -(%sp)
 208         bclrb           #E3,E_BYTE(%a6)         |clear and test E3 flag
 209         bnes            unfl_done
 210         bclrb           #E1,E_BYTE(%a6)
 211 unfl_done:
 212         frestore        (%sp)+
 213         unlk            %a6
 214 
 215         SAVE_ALL_INT
 216         GET_CURRENT(%d0)
 217         movel   %sp,%sp@-               | stack frame pointer argument
 218         bsrl    trap_c
 219         addql   #4,%sp
 220         bral    ret_from_exception
 221 
 222 |
 223 |       Signalling NAN exception
 224 |
 225         |xref   fpsp_snan
 226         .global real_snan
 227         .global snan
 228 snan:
 229         jmp     fpsp_snan
 230 real_snan:
 231         link            %a6,#-LOCAL_SIZE
 232         fsave           -(%sp)
 233         bclrb           #E1,E_BYTE(%a6) |snan is always an E1 exception
 234         frestore        (%sp)+
 235         unlk            %a6
 236 
 237         SAVE_ALL_INT
 238         GET_CURRENT(%d0)
 239         movel   %sp,%sp@-               | stack frame pointer argument
 240         bsrl    trap_c
 241         addql   #4,%sp
 242         bral    ret_from_exception
 243 
 244 |
 245 |       Operand Error exception
 246 |
 247         |xref   fpsp_operr
 248         .global real_operr
 249         .global operr
 250 operr:
 251         jmp     fpsp_operr
 252 real_operr:
 253         link            %a6,#-LOCAL_SIZE
 254         fsave           -(%sp)
 255         bclrb           #E1,E_BYTE(%a6) |operr is always an E1 exception
 256         frestore        (%sp)+
 257         unlk            %a6
 258 
 259         SAVE_ALL_INT
 260         GET_CURRENT(%d0)
 261         movel   %sp,%sp@-               | stack frame pointer argument
 262         bsrl    trap_c
 263         addql   #4,%sp
 264         bral    ret_from_exception
 265 
 266 
 267 |
 268 |       BSUN exception
 269 |
 270 |       This sample handler simply clears the nan bit in the FPSR.
 271 |
 272         |xref   fpsp_bsun
 273         .global real_bsun
 274         .global bsun
 275 bsun:
 276         jmp     fpsp_bsun
 277 real_bsun:
 278         link            %a6,#-LOCAL_SIZE
 279         fsave           -(%sp)
 280         bclrb           #E1,E_BYTE(%a6) |bsun is always an E1 exception
 281         fmovel          %FPSR,-(%sp)
 282         bclrb           #nan_bit,(%sp)
 283         fmovel          (%sp)+,%FPSR
 284         frestore        (%sp)+
 285         unlk            %a6
 286 
 287         SAVE_ALL_INT
 288         GET_CURRENT(%d0)
 289         movel   %sp,%sp@-               | stack frame pointer argument
 290         bsrl    trap_c
 291         addql   #4,%sp
 292         bral    ret_from_exception
 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         .global real_fline
 303         .global fline
 304 fline:
 305         jmp     fpsp_fline
 306 real_fline:
 307 
 308         SAVE_ALL_INT
 309         GET_CURRENT(%d0)
 310         movel   %sp,%sp@-               | stack frame pointer argument
 311         bsrl    trap_c
 312         addql   #4,%sp
 313         bral    ret_from_exception
 314 
 315 |
 316 |       Unsupported data type exception
 317 |
 318         |xref   fpsp_unsupp
 319         .global real_unsupp
 320         .global unsupp
 321 unsupp:
 322         jmp     fpsp_unsupp
 323 real_unsupp:
 324         link            %a6,#-LOCAL_SIZE
 325         fsave           -(%sp)
 326         bclrb           #E1,E_BYTE(%a6) |unsupp is always an E1 exception
 327         frestore        (%sp)+
 328         unlk            %a6
 329 
 330         SAVE_ALL_INT
 331         GET_CURRENT(%d0)
 332         movel   %sp,%sp@-               | stack frame pointer argument
 333         bsrl    trap_c
 334         addql   #4,%sp
 335         bral    ret_from_exception
 336 
 337 |
 338 |       Trace exception
 339 |
 340         .global real_trace
 341 real_trace:
 342         |
 343         bral    trap
 344 
 345 |
 346 |       fpsp_fmt_error --- exit point for frame format error
 347 |
 348 |       The fpu stack frame does not match the frames existing
 349 |       or planned at the time of this writing.  The fpsp is
 350 |       unable to handle frame sizes not in the following
 351 |       version:size pairs:
 352 |
 353 |       {4060, 4160} - busy frame
 354 |       {4028, 4130} - unimp frame
 355 |       {4000, 4100} - idle frame
 356 |
 357 |       This entry point simply holds an f-line illegal value.
 358 |       Replace this with a call to your kernel panic code or
 359 |       code to handle future revisions of the fpu.
 360 |
 361         .global fpsp_fmt_error
 362 fpsp_fmt_error:
 363 
 364         .long   0xf27f0000      |f-line illegal
 365 
 366 |
 367 |       fpsp_done --- FPSP exit point
 368 |
 369 |       The exception has been handled by the package and we are ready
 370 |       to return to user mode, but there may be OS specific code
 371 |       to execute before we do.  If there is, do it now.
 372 |
 373 |
 374 
 375         .global fpsp_done
 376 fpsp_done:
 377         btst    #0x5,%sp@               | supervisor bit set in saved SR?
 378         beq     .Lnotkern
 379         rte
 380 .Lnotkern:
 381         SAVE_ALL_INT
 382         GET_CURRENT(%d0)
 383         | deliver signals, reschedule etc..
 384         jra     ret_from_exception
 385 
 386 |
 387 |       mem_write --- write to user or supervisor address space
 388 |
 389 | Writes to memory while in supervisor mode.  copyout accomplishes
 390 | this via a 'moves' instruction.  copyout is a UNIX SVR3 (and later) function.
 391 | If you don't have copyout, use the local copy of the function below.
 392 |
 393 |       a0 - supervisor source address
 394 |       a1 - user destination address
 395 |       d0 - number of bytes to write (maximum count is 12)
 396 |
 397 | The supervisor source address is guaranteed to point into the supervisor
 398 | stack.  The result is that a UNIX
 399 | process is allowed to sleep as a consequence of a page fault during
 400 | copyout.  The probability of a page fault is exceedingly small because
 401 | the 68040 always reads the destination address and thus the page
 402 | faults should have already been handled.
 403 |
 404 | If the EXC_SR shows that the exception was from supervisor space,
 405 | then just do a dumb (and slow) memory move.  In a UNIX environment
 406 | there shouldn't be any supervisor mode floating point exceptions.
 407 |
 408         .global mem_write
 409 mem_write:
 410         btstb   #5,EXC_SR(%a6)  |check for supervisor state
 411         beqs    user_write
 412 super_write:
 413         moveb   (%a0)+,(%a1)+
 414         subql   #1,%d0
 415         bnes    super_write
 416         rts
 417 user_write:
 418         movel   %d1,-(%sp)      |preserve d1 just in case
 419         movel   %d0,-(%sp)
 420         movel   %a1,-(%sp)
 421         movel   %a0,-(%sp)
 422         jsr             copyout
 423         addw    #12,%sp
 424         movel   (%sp)+,%d1
 425         rts
 426 |
 427 |       mem_read --- read from user or supervisor address space
 428 |
 429 | Reads from memory while in supervisor mode.  copyin accomplishes
 430 | this via a 'moves' instruction.  copyin is a UNIX SVR3 (and later) function.
 431 | If you don't have copyin, use the local copy of the function below.
 432 |
 433 | The FPSP calls mem_read to read the original F-line instruction in order
 434 | to extract the data register number when the 'Dn' addressing mode is
 435 | used.
 436 |
 437 |Input:
 438 |       a0 - user source address
 439 |       a1 - supervisor destination address
 440 |       d0 - number of bytes to read (maximum count is 12)
 441 |
 442 | Like mem_write, mem_read always reads with a supervisor
 443 | destination address on the supervisor stack.  Also like mem_write,
 444 | the EXC_SR is checked and a simple memory copy is done if reading
 445 | from supervisor space is indicated.
 446 |
 447         .global mem_read
 448 mem_read:
 449         btstb   #5,EXC_SR(%a6)  |check for supervisor state
 450         beqs    user_read
 451 super_read:
 452         moveb   (%a0)+,(%a1)+
 453         subql   #1,%d0
 454         bnes    super_read
 455         rts
 456 user_read:
 457         movel   %d1,-(%sp)      |preserve d1 just in case
 458         movel   %d0,-(%sp)
 459         movel   %a1,-(%sp)
 460         movel   %a0,-(%sp)
 461         jsr     copyin
 462         addw    #12,%sp
 463         movel   (%sp)+,%d1
 464         rts
 465 
 466 |
 467 | Use these routines if your kernel doesn't have copyout/copyin equivalents.
 468 | Assumes that D0/D1/A0/A1 are scratch registers. copyout overwrites DFC,
 469 | and copyin overwrites SFC.
 470 |
 471 copyout:
 472         movel   4(%sp),%a0      | source
 473         movel   8(%sp),%a1      | destination
 474         movel   12(%sp),%d0     | count
 475         subl    #1,%d0          | dec count by 1 for dbra
 476         movel   #1,%d1
 477 
 478 |       DFC is already set
 479 |       movec   %d1,%DFC                | set dfc for user data space
 480 moreout:
 481         moveb   (%a0)+,%d1      | fetch supervisor byte
 482 out_ea:
 483         movesb  %d1,(%a1)+      | write user byte
 484         dbf     %d0,moreout
 485         rts
 486 
 487 copyin:
 488         movel   4(%sp),%a0      | source
 489         movel   8(%sp),%a1      | destination
 490         movel   12(%sp),%d0     | count
 491         subl    #1,%d0          | dec count by 1 for dbra
 492         movel   #1,%d1
 493 |       SFC is already set
 494 |       movec   %d1,%SFC                | set sfc for user space
 495 morein:
 496 in_ea:
 497         movesb  (%a0)+,%d1      | fetch user byte
 498         moveb   %d1,(%a1)+      | write supervisor byte
 499         dbf     %d0,morein
 500         rts
 501 
 502         .section .fixup,#alloc,#execinstr
 503         .even
 504 1:
 505         jbra    fpsp040_die
 506 
 507         .section __ex_table,#alloc
 508         .align  4
 509 
 510         .long   in_ea,1b
 511         .long   out_ea,1b
 512 
 513         |end

/* [<][>][^][v][top][bottom][index][help] */