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