root/arch/m68k/fpsp040/gen_except.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 |
   2 |       gen_except.sa 3.7 1/16/92
   3 |
   4 |       gen_except --- FPSP routine to detect reportable exceptions
   5 |       
   6 |       This routine compares the exception enable byte of the
   7 |       user_fpcr on the stack with the exception status byte
   8 |       of the user_fpsr. 
   9 |
  10 |       Any routine which may report an exceptions must load
  11 |       the stack frame in memory with the exceptional operand(s).
  12 |
  13 |       Priority for exceptions is:
  14 |
  15 |       Highest:        bsun
  16 |                       snan
  17 |                       operr
  18 |                       ovfl
  19 |                       unfl
  20 |                       dz
  21 |                       inex2
  22 |       Lowest:         inex1
  23 |
  24 |       Note: The IEEE standard specifies that inex2 is to be
  25 |       reported if ovfl occurs and the ovfl enable bit is not
  26 |       set but the inex2 enable bit is.  
  27 |
  28 |
  29 |               Copyright (C) Motorola, Inc. 1990
  30 |                       All Rights Reserved
  31 |
  32 |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA 
  33 |       The copyright notice above does not evidence any  
  34 |       actual or intended publication of such source code.
  35 
  36 GEN_EXCEPT:    |idnt    2,1 | Motorola 040 Floating Point Software Package
  37 
  38         |section 8
  39 
  40         .include "fpsp.h"
  41 
  42         |xref   real_trace
  43         |xref   fpsp_done
  44         |xref   fpsp_fmt_error
  45 
  46 exc_tbl:
  47         .long   bsun_exc
  48         .long   commonE1
  49         .long   commonE1
  50         .long   ovfl_unfl
  51         .long   ovfl_unfl
  52         .long   commonE1
  53         .long   commonE3
  54         .long   commonE3
  55         .long   no_match
  56 
  57         .global gen_except
  58 gen_except:
  59         cmpib   #IDLE_SIZE-4,1(%a7)     |test for idle frame
  60         beq     do_check                |go handle idle frame
  61         cmpib   #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
  62         beqs    unimp_x                 |go handle unimp frame
  63         cmpib   #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
  64         beqs    unimp_x                 |go handle unimp frame
  65         cmpib   #BUSY_SIZE-4,1(%a7)     |if size <> $60, fmt error
  66         bnel    fpsp_fmt_error
  67         leal    BUSY_SIZE+LOCAL_SIZE(%a7),%a1 |init a1 so fpsp.h
  68 |                                       ;equates will work
  69 | Fix up the new busy frame with entries from the unimp frame
  70 |
  71         movel   ETEMP_EX(%a6),ETEMP_EX(%a1) |copy etemp from unimp
  72         movel   ETEMP_HI(%a6),ETEMP_HI(%a1) |frame to busy frame
  73         movel   ETEMP_LO(%a6),ETEMP_LO(%a1) 
  74         movel   CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
  75         movel   CMDREG1B(%a6),%d0               |fix cmd1b to make it
  76         andl    #0x03c30000,%d0         |work for cmd3b
  77         bfextu  CMDREG1B(%a6){#13:#1},%d1       |extract bit 2
  78         lsll    #5,%d1                  
  79         swap    %d1
  80         orl     %d1,%d0                 |put it in the right place
  81         bfextu  CMDREG1B(%a6){#10:#3},%d1       |extract bit 3,4,5
  82         lsll    #2,%d1
  83         swap    %d1
  84         orl     %d1,%d0                 |put them in the right place
  85         movel   %d0,CMDREG3B(%a1)               |in the busy frame
  86 |
  87 | Or in the FPSR from the emulation with the USER_FPSR on the stack.
  88 |
  89         fmovel  %FPSR,%d0               
  90         orl     %d0,USER_FPSR(%a6)
  91         movel   USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
  92         orl     #sx_mask,E_BYTE(%a1)
  93         bra     do_clean
  94 
  95 |
  96 | Frame is an unimp frame possible resulting from an fmove <ea>,fp0
  97 | that caused an exception
  98 |
  99 | a1 is modified to point into the new frame allowing fpsp equates
 100 | to be valid.
 101 |
 102 unimp_x:
 103         cmpib   #UNIMP_40_SIZE-4,1(%a7) |test for orig unimp frame
 104         bnes    test_rev
 105         leal    UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1
 106         bras    unimp_con
 107 test_rev:
 108         cmpib   #UNIMP_41_SIZE-4,1(%a7) |test for rev unimp frame
 109         bnel    fpsp_fmt_error          |if not $28 or $30
 110         leal    UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1
 111         
 112 unimp_con:
 113 |
 114 | Fix up the new unimp frame with entries from the old unimp frame
 115 |
 116         movel   CMDREG1B(%a6),CMDREG1B(%a1) |set inst in frame to unimp
 117 |
 118 | Or in the FPSR from the emulation with the USER_FPSR on the stack.
 119 |
 120         fmovel  %FPSR,%d0               
 121         orl     %d0,USER_FPSR(%a6)
 122         bra     do_clean
 123 
 124 |
 125 | Frame is idle, so check for exceptions reported through
 126 | USER_FPSR and set the unimp frame accordingly.  
 127 | A7 must be incremented to the point before the
 128 | idle fsave vector to the unimp vector.
 129 |
 130         
 131 do_check:
 132         addl    #4,%a7                  |point A7 back to unimp frame
 133 |
 134 | Or in the FPSR from the emulation with the USER_FPSR on the stack.
 135 |
 136         fmovel  %FPSR,%d0               
 137         orl     %d0,USER_FPSR(%a6)
 138 |
 139 | On a busy frame, we must clear the nmnexc bits.
 140 |
 141         cmpib   #BUSY_SIZE-4,1(%a7)     |check frame type
 142         bnes    check_fr                |if busy, clr nmnexc
 143         clrw    NMNEXC(%a6)             |clr nmnexc & nmcexc
 144         btstb   #5,CMDREG1B(%a6)                |test for fmove out
 145         bnes    frame_com
 146         movel   USER_FPSR(%a6),FPSR_SHADOW(%a6) |set exc bits
 147         orl     #sx_mask,E_BYTE(%a6)
 148         bras    frame_com
 149 check_fr:
 150         cmpb    #UNIMP_40_SIZE-4,1(%a7)
 151         beqs    frame_com
 152         clrw    NMNEXC(%a6)
 153 frame_com:
 154         moveb   FPCR_ENABLE(%a6),%d0    |get fpcr enable byte
 155         andb    FPSR_EXCEPT(%a6),%d0    |and in the fpsr exc byte
 156         bfffo   %d0{#24:#8},%d1         |test for first set bit
 157         leal    exc_tbl,%a0             |load jmp table address
 158         subib   #24,%d1                 |normalize bit offset to 0-8
 159         movel   (%a0,%d1.w*4),%a0               |load routine address based
 160 |                                       ;based on first enabled exc
 161         jmp     (%a0)                   |jump to routine
 162 |
 163 | Bsun is not possible in unimp or unsupp
 164 |
 165 bsun_exc:
 166         bra     do_clean
 167 |
 168 | The typical work to be done to the unimp frame to report an 
 169 | exception is to set the E1/E3 byte and clr the U flag.
 170 | commonE1 does this for E1 exceptions, which are snan, 
 171 | operr, and dz.  commonE3 does this for E3 exceptions, which 
 172 | are inex2 and inex1, and also clears the E1 exception bit
 173 | left over from the unimp exception.
 174 |
 175 commonE1:
 176         bsetb   #E1,E_BYTE(%a6)         |set E1 flag
 177         bra     commonE                 |go clean and exit
 178 
 179 commonE3:
 180         tstb    UFLG_TMP(%a6)           |test flag for unsup/unimp state
 181         bnes    unsE3
 182 uniE3:
 183         bsetb   #E3,E_BYTE(%a6)         |set E3 flag
 184         bclrb   #E1,E_BYTE(%a6)         |clr E1 from unimp
 185         bra     commonE
 186 
 187 unsE3:
 188         tstb    RES_FLG(%a6)
 189         bnes    unsE3_0 
 190 unsE3_1:
 191         bsetb   #E3,E_BYTE(%a6)         |set E3 flag
 192 unsE3_0:
 193         bclrb   #E1,E_BYTE(%a6)         |clr E1 flag
 194         movel   CMDREG1B(%a6),%d0
 195         andl    #0x03c30000,%d0         |work for cmd3b
 196         bfextu  CMDREG1B(%a6){#13:#1},%d1       |extract bit 2
 197         lsll    #5,%d1                  
 198         swap    %d1
 199         orl     %d1,%d0                 |put it in the right place
 200         bfextu  CMDREG1B(%a6){#10:#3},%d1       |extract bit 3,4,5
 201         lsll    #2,%d1
 202         swap    %d1
 203         orl     %d1,%d0                 |put them in the right place
 204         movel   %d0,CMDREG3B(%a6)               |in the busy frame
 205 
 206 commonE:
 207         bclrb   #UFLAG,T_BYTE(%a6)      |clr U flag from unimp
 208         bra     do_clean                |go clean and exit
 209 |
 210 | No bits in the enable byte match existing exceptions.  Check for
 211 | the case of the ovfl exc without the ovfl enabled, but with
 212 | inex2 enabled.
 213 |
 214 no_match:
 215         btstb   #inex2_bit,FPCR_ENABLE(%a6) |check for ovfl/inex2 case
 216         beqs    no_exc                  |if clear, exit
 217         btstb   #ovfl_bit,FPSR_EXCEPT(%a6) |now check ovfl
 218         beqs    no_exc                  |if clear, exit
 219         bras    ovfl_unfl               |go to unfl_ovfl to determine if
 220 |                                       ;it is an unsupp or unimp exc
 221         
 222 | No exceptions are to be reported.  If the instruction was 
 223 | unimplemented, no FPU restore is necessary.  If it was
 224 | unsupported, we must perform the restore.
 225 no_exc:
 226         tstb    UFLG_TMP(%a6)   |test flag for unsupp/unimp state
 227         beqs    uni_no_exc
 228 uns_no_exc:
 229         tstb    RES_FLG(%a6)    |check if frestore is needed
 230         bne     do_clean        |if clear, no frestore needed
 231 uni_no_exc:
 232         moveml  USER_DA(%a6),%d0-%d1/%a0-%a1
 233         fmovemx USER_FP0(%a6),%fp0-%fp3
 234         fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
 235         unlk    %a6
 236         bra     finish_up
 237 |
 238 | Unsupported Data Type Handler:
 239 | Ovfl:
 240 |   An fmoveout that results in an overflow is reported this way.
 241 | Unfl:
 242 |   An fmoveout that results in an underflow is reported this way.
 243 |
 244 | Unimplemented Instruction Handler:
 245 | Ovfl:
 246 |   Only scosh, setox, ssinh, stwotox, and scale can set overflow in 
 247 |   this manner.
 248 | Unfl:
 249 |   Stwotox, setox, and scale can set underflow in this manner.
 250 |   Any of the other Library Routines such that f(x)=x in which
 251 |   x is an extended denorm can report an underflow exception. 
 252 |   It is the responsibility of the exception-causing exception 
 253 |   to make sure that WBTEMP is correct.
 254 |
 255 |   The exceptional operand is in FP_SCR1.
 256 |
 257 ovfl_unfl:
 258         tstb    UFLG_TMP(%a6)   |test flag for unsupp/unimp state
 259         beqs    ofuf_con
 260 |
 261 | The caller was from an unsupported data type trap.  Test if the
 262 | caller set CU_ONLY.  If so, the exceptional operand is expected in
 263 | FPTEMP, rather than WBTEMP.
 264 |
 265         tstb    CU_ONLY(%a6)            |test if inst is cu-only
 266         beq     unsE3
 267 |       move.w  #$fe,CU_SAVEPC(%a6)
 268         clrb    CU_SAVEPC(%a6)
 269         bsetb   #E1,E_BYTE(%a6)         |set E1 exception flag
 270         movew   ETEMP_EX(%a6),FPTEMP_EX(%a6)
 271         movel   ETEMP_HI(%a6),FPTEMP_HI(%a6)
 272         movel   ETEMP_LO(%a6),FPTEMP_LO(%a6)
 273         bsetb   #fptemp15_bit,DTAG(%a6) |set fpte15
 274         bclrb   #UFLAG,T_BYTE(%a6)      |clr U flag from unimp
 275         bra     do_clean                |go clean and exit
 276 
 277 ofuf_con:
 278         moveb   (%a7),VER_TMP(%a6)      |save version number
 279         cmpib   #BUSY_SIZE-4,1(%a7)     |check for busy frame
 280         beqs    busy_fr                 |if unimp, grow to busy
 281         cmpib   #VER_40,(%a7)           |test for orig unimp frame
 282         bnes    try_41                  |if not, test for rev frame
 283         moveql  #13,%d0                 |need to zero 14 lwords
 284         bras    ofuf_fin
 285 try_41:
 286         cmpib   #VER_41,(%a7)           |test for rev unimp frame
 287         bnel    fpsp_fmt_error          |if neither, exit with error
 288         moveql  #11,%d0                 |need to zero 12 lwords
 289 
 290 ofuf_fin:
 291         clrl    (%a7)
 292 loop1:
 293         clrl    -(%a7)                  |clear and dec a7
 294         dbra    %d0,loop1
 295         moveb   VER_TMP(%a6),(%a7)
 296         moveb   #BUSY_SIZE-4,1(%a7)             |write busy fmt word.
 297 busy_fr:
 298         movel   FP_SCR1(%a6),WBTEMP_EX(%a6)     |write
 299         movel   FP_SCR1+4(%a6),WBTEMP_HI(%a6)   |exceptional op to
 300         movel   FP_SCR1+8(%a6),WBTEMP_LO(%a6)   |wbtemp
 301         bsetb   #E3,E_BYTE(%a6)                 |set E3 flag
 302         bclrb   #E1,E_BYTE(%a6)                 |make sure E1 is clear
 303         bclrb   #UFLAG,T_BYTE(%a6)              |clr U flag
 304         movel   USER_FPSR(%a6),FPSR_SHADOW(%a6)
 305         orl     #sx_mask,E_BYTE(%a6)
 306         movel   CMDREG1B(%a6),%d0               |fix cmd1b to make it
 307         andl    #0x03c30000,%d0         |work for cmd3b
 308         bfextu  CMDREG1B(%a6){#13:#1},%d1       |extract bit 2
 309         lsll    #5,%d1                  
 310         swap    %d1
 311         orl     %d1,%d0                 |put it in the right place
 312         bfextu  CMDREG1B(%a6){#10:#3},%d1       |extract bit 3,4,5
 313         lsll    #2,%d1
 314         swap    %d1
 315         orl     %d1,%d0                 |put them in the right place
 316         movel   %d0,CMDREG3B(%a6)               |in the busy frame
 317 
 318 |
 319 | Check if the frame to be restored is busy or unimp.
 320 |** NOTE *** Bug fix for errata (0d43b #3)
 321 | If the frame is unimp, we must create a busy frame to 
 322 | fix the bug with the nmnexc bits in cases in which they
 323 | are set by a previous instruction and not cleared by
 324 | the save. The frame will be unimp only if the final 
 325 | instruction in an emulation routine caused the exception
 326 | by doing an fmove <ea>,fp0.  The exception operand, in
 327 | internal format, is in fptemp.
 328 |
 329 do_clean:
 330         cmpib   #UNIMP_40_SIZE-4,1(%a7)
 331         bnes    do_con
 332         moveql  #13,%d0                 |in orig, need to zero 14 lwords
 333         bras    do_build
 334 do_con:
 335         cmpib   #UNIMP_41_SIZE-4,1(%a7)
 336         bnes    do_restore              |frame must be busy
 337         moveql  #11,%d0                 |in rev, need to zero 12 lwords
 338 
 339 do_build:
 340         moveb   (%a7),VER_TMP(%a6)
 341         clrl    (%a7)
 342 loop2:
 343         clrl    -(%a7)                  |clear and dec a7
 344         dbra    %d0,loop2
 345 |
 346 | Use a1 as pointer into new frame.  a6 is not correct if an unimp or
 347 | busy frame was created as the result of an exception on the final
 348 | instruction of an emulation routine.
 349 |
 350 | We need to set the nmcexc bits if the exception is E1. Otherwise,
 351 | the exc taken will be inex2.
 352 |
 353         leal    BUSY_SIZE+LOCAL_SIZE(%a7),%a1   |init a1 for new frame
 354         moveb   VER_TMP(%a6),(%a7)      |write busy fmt word
 355         moveb   #BUSY_SIZE-4,1(%a7)
 356         movel   FP_SCR1(%a6),WBTEMP_EX(%a1)     |write
 357         movel   FP_SCR1+4(%a6),WBTEMP_HI(%a1)   |exceptional op to
 358         movel   FP_SCR1+8(%a6),WBTEMP_LO(%a1)   |wbtemp
 359 |       btst.b  #E1,E_BYTE(%a1)
 360 |       beq.b   do_restore
 361         bfextu  USER_FPSR(%a6){#17:#4},%d0      |get snan/operr/ovfl/unfl bits
 362         bfins   %d0,NMCEXC(%a1){#4:#4}  |and insert them in nmcexc
 363         movel   USER_FPSR(%a6),FPSR_SHADOW(%a1) |set exc bits
 364         orl     #sx_mask,E_BYTE(%a1)
 365         
 366 do_restore:
 367         moveml  USER_DA(%a6),%d0-%d1/%a0-%a1
 368         fmovemx USER_FP0(%a6),%fp0-%fp3
 369         fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
 370         frestore (%a7)+
 371         tstb    RES_FLG(%a6)    |RES_FLG indicates a "continuation" frame
 372         beq     cont
 373         bsr     bug1384
 374 cont:
 375         unlk    %a6
 376 |
 377 | If trace mode enabled, then go to trace handler.  This handler 
 378 | cannot have any fp instructions.  If there are fp inst's and an 
 379 | exception has been restored into the machine then the exception 
 380 | will occur upon execution of the fp inst.  This is not desirable 
 381 | in the kernel (supervisor mode).  See MC68040 manual Section 9.3.8.
 382 |
 383 finish_up:
 384         btstb   #7,(%a7)                |test T1 in SR
 385         bnes    g_trace
 386         btstb   #6,(%a7)                |test T0 in SR
 387         bnes    g_trace
 388         bral    fpsp_done
 389 |
 390 | Change integer stack to look like trace stack
 391 | The address of the instruction that caused the
 392 | exception is already in the integer stack (is
 393 | the same as the saved friar)
 394 |
 395 | If the current frame is already a 6-word stack then all
 396 | that needs to be done is to change the vector# to TRACE.
 397 | If the frame is only a 4-word stack (meaning we got here
 398 | on an Unsupported data type exception), then we need to grow
 399 | the stack an extra 2 words and get the FPIAR from the FPU.
 400 |
 401 g_trace:
 402         bftst   EXC_VEC-4(%sp){#0:#4}
 403         bne     g_easy
 404 
 405         subw    #4,%sp          | make room
 406         movel   4(%sp),(%sp)
 407         movel   8(%sp),4(%sp)
 408         subw    #BUSY_SIZE,%sp
 409         fsave   (%sp)
 410         fmovel  %fpiar,BUSY_SIZE+EXC_EA-4(%sp)
 411         frestore (%sp)
 412         addw    #BUSY_SIZE,%sp
 413 
 414 g_easy:
 415         movew   #TRACE_VEC,EXC_VEC-4(%a7)
 416         bral    real_trace
 417 |
 418 |  This is a work-around for hardware bug 1384.
 419 |
 420 bug1384:
 421         link    %a5,#0
 422         fsave   -(%sp)
 423         cmpib   #0x41,(%sp)     | check for correct frame
 424         beq     frame_41
 425         bgt     nofix           | if more advanced mask, do nada
 426 
 427 frame_40:
 428         tstb    1(%sp)          | check to see if idle
 429         bne     notidle
 430 idle40:
 431         clrl    (%sp)           | get rid of old fsave frame
 432         movel  %d1,USER_D1(%a6)  | save d1
 433         movew   #8,%d1          | place unimp frame instead
 434 loop40: clrl    -(%sp)
 435         dbra    %d1,loop40
 436         movel  USER_D1(%a6),%d1  | restore d1
 437         movel   #0x40280000,-(%sp)
 438         frestore (%sp)+
 439         unlk    %a5     
 440         rts
 441 
 442 frame_41:
 443         tstb    1(%sp)          | check to see if idle
 444         bne     notidle 
 445 idle41:
 446         clrl    (%sp)           | get rid of old fsave frame
 447         movel  %d1,USER_D1(%a6)  | save d1
 448         movew   #10,%d1         | place unimp frame instead
 449 loop41: clrl    -(%sp)
 450         dbra    %d1,loop41
 451         movel  USER_D1(%a6),%d1  | restore d1
 452         movel   #0x41300000,-(%sp)
 453         frestore (%sp)+
 454         unlk    %a5     
 455         rts
 456 
 457 notidle:
 458         bclrb   #etemp15_bit,-40(%a5) 
 459         frestore (%sp)+
 460         unlk    %a5     
 461         rts
 462 
 463 nofix:
 464         frestore (%sp)+
 465         unlk    %a5     
 466         rts
 467 
 468         |end

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