File indexing completed on 2025-05-11 08:23:48
0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 // gen_except.sa 3.7 1/16/92
0005 //
0006 // gen_except --- FPSP routine to detect reportable exceptions
0007 //
0008 // This routine compares the exception enable byte of the
0009 // user_fpcr on the stack with the exception status byte
0010 // of the user_fpsr.
0011 //
0012 // Any routine which may report an exceptions must load
0013 // the stack frame in memory with the exceptional operand(s).
0014 //
0015 // Priority for exceptions is:
0016 //
0017 // Highest: bsun
0018 // snan
0019 // operr
0020 // ovfl
0021 // unfl
0022 // dz
0023 // inex2
0024 // Lowest: inex1
0025 //
0026 // Note: The IEEE standard specifies that inex2 is to be
0027 // reported if ovfl occurs and the ovfl enable bit is not
0028 // set but the inex2 enable bit is.
0029 //
0030 //
0031 // Copyright (C) Motorola, Inc. 1990
0032 // All Rights Reserved
0033 //
0034 // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0035 // The copyright notice above does not evidence any
0036 // actual or intended publication of such source code.
0037
0038 GEN_EXCEPT: //idnt 2,1 | Motorola 040 Floating Point Software Package
0039
0040 |section 8
0041
0042 #include "fpsp.defs"
0043
0044 |xref real_trace
0045 |xref fpsp_done
0046 |xref fpsp_fmt_error
0047
0048 exc_tbl:
0049 .long bsun_exc
0050 .long commonE1
0051 .long commonE1
0052 .long ovfl_unfl
0053 .long ovfl_unfl
0054 .long commonE1
0055 .long commonE3
0056 .long commonE3
0057 .long no_match
0058
0059 .global gen_except
0060 gen_except:
0061 cmpib #IDLE_SIZE-4,1(%a7) //test for idle frame
0062 beq do_check //go handle idle frame
0063 cmpib #UNIMP_40_SIZE-4,1(%a7) //test for orig unimp frame
0064 beqs unimp_x //go handle unimp frame
0065 cmpib #UNIMP_41_SIZE-4,1(%a7) //test for rev unimp frame
0066 beqs unimp_x //go handle unimp frame
0067 cmpib #BUSY_SIZE-4,1(%a7) //if size <> $60, fmt error
0068 bnel fpsp_fmt_error
0069 leal BUSY_SIZE+LOCAL_SIZE(%a7),%a1 //init a1 so fpsp.h
0070 // ;equates will work
0071 // Fix up the new busy frame with entries from the unimp frame
0072 //
0073 movel ETEMP_EX(%a6),ETEMP_EX(%a1) //copy etemp from unimp
0074 movel ETEMP_HI(%a6),ETEMP_HI(%a1) //frame to busy frame
0075 movel ETEMP_LO(%a6),ETEMP_LO(%a1)
0076 movel CMDREG1B(%a6),CMDREG1B(%a1) //set inst in frame to unimp
0077 movel CMDREG1B(%a6),%d0 //fix cmd1b to make it
0078 andl #0x03c30000,%d0 //work for cmd3b
0079 bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2
0080 lsll #5,%d1
0081 swap %d1
0082 orl %d1,%d0 //put it in the right place
0083 bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5
0084 lsll #2,%d1
0085 swap %d1
0086 orl %d1,%d0 //put them in the right place
0087 movel %d0,CMDREG3B(%a1) //in the busy frame
0088 //
0089 // Or in the FPSR from the emulation with the USER_FPSR on the stack.
0090 //
0091 fmovel %FPSR,%d0
0092 orl %d0,USER_FPSR(%a6)
0093 movel USER_FPSR(%a6),FPSR_SHADOW(%a1) //set exc bits
0094 orl #sx_mask,E_BYTE(%a1)
0095 bra do_clean
0096
0097 //
0098 // Frame is an unimp frame possible resulting from an fmove <ea>,fp0
0099 // that caused an exception
0100 //
0101 // a1 is modified to point into the new frame allowing fpsp equates
0102 // to be valid.
0103 //
0104 unimp_x:
0105 cmpib #UNIMP_40_SIZE-4,1(%a7) //test for orig unimp frame
0106 bnes test_rev
0107 leal UNIMP_40_SIZE+LOCAL_SIZE(%a7),%a1
0108 bras unimp_con
0109 test_rev:
0110 cmpib #UNIMP_41_SIZE-4,1(%a7) //test for rev unimp frame
0111 bnel fpsp_fmt_error //if not $28 or $30
0112 leal UNIMP_41_SIZE+LOCAL_SIZE(%a7),%a1
0113
0114 unimp_con:
0115 //
0116 // Fix up the new unimp frame with entries from the old unimp frame
0117 //
0118 movel CMDREG1B(%a6),CMDREG1B(%a1) //set inst in frame to unimp
0119 //
0120 // Or in the FPSR from the emulation with the USER_FPSR on the stack.
0121 //
0122 fmovel %FPSR,%d0
0123 orl %d0,USER_FPSR(%a6)
0124 bra do_clean
0125
0126 //
0127 // Frame is idle, so check for exceptions reported through
0128 // USER_FPSR and set the unimp frame accordingly.
0129 // A7 must be incremented to the point before the
0130 // idle fsave vector to the unimp vector.
0131 //
0132
0133 do_check:
0134 addl #4,%a7 //point A7 back to unimp frame
0135 //
0136 // Or in the FPSR from the emulation with the USER_FPSR on the stack.
0137 //
0138 fmovel %FPSR,%d0
0139 orl %d0,USER_FPSR(%a6)
0140 //
0141 // On a busy frame, we must clear the nmnexc bits.
0142 //
0143 cmpib #BUSY_SIZE-4,1(%a7) //check frame type
0144 bnes check_fr //if busy, clr nmnexc
0145 clrw NMNEXC(%a6) //clr nmnexc & nmcexc
0146 btstb #5,CMDREG1B(%a6) //test for fmove out
0147 bnes frame_com
0148 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) //set exc bits
0149 orl #sx_mask,E_BYTE(%a6)
0150 bras frame_com
0151 check_fr:
0152 cmpb #UNIMP_40_SIZE-4,1(%a7)
0153 beqs frame_com
0154 clrw NMNEXC(%a6)
0155 frame_com:
0156 moveb FPCR_ENABLE(%a6),%d0 //get fpcr enable byte
0157 andb FPSR_EXCEPT(%a6),%d0 //and in the fpsr exc byte
0158 bfffo %d0{#24:#8},%d1 //test for first set bit
0159 leal exc_tbl,%a0 //load jmp table address
0160 subib #24,%d1 //normalize bit offset to 0-8
0161 movel (%a0,%d1.w*4),%a0 //load routine address based
0162 // ;based on first enabled exc
0163 jmp (%a0) //jump to routine
0164 //
0165 // Bsun is not possible in unimp or unsupp
0166 //
0167 bsun_exc:
0168 bra do_clean
0169 //
0170 // The typical work to be done to the unimp frame to report an
0171 // exception is to set the E1/E3 byte and clr the U flag.
0172 // commonE1 does this for E1 exceptions, which are snan,
0173 // operr, and dz. commonE3 does this for E3 exceptions, which
0174 // are inex2 and inex1, and also clears the E1 exception bit
0175 // left over from the unimp exception.
0176 //
0177 commonE1:
0178 bsetb #E1,E_BYTE(%a6) //set E1 flag
0179 bra commonE //go clean and exit
0180
0181 commonE3:
0182 tstb UFLG_TMP(%a6) //test flag for unsup/unimp state
0183 bnes unsE3
0184 uniE3:
0185 bsetb #E3,E_BYTE(%a6) //set E3 flag
0186 bclrb #E1,E_BYTE(%a6) //clr E1 from unimp
0187 bra commonE
0188
0189 unsE3:
0190 tstb RES_FLG(%a6)
0191 bnes unsE3_0
0192 unsE3_1:
0193 bsetb #E3,E_BYTE(%a6) //set E3 flag
0194 unsE3_0:
0195 bclrb #E1,E_BYTE(%a6) //clr E1 flag
0196 movel CMDREG1B(%a6),%d0
0197 andl #0x03c30000,%d0 //work for cmd3b
0198 bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2
0199 lsll #5,%d1
0200 swap %d1
0201 orl %d1,%d0 //put it in the right place
0202 bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5
0203 lsll #2,%d1
0204 swap %d1
0205 orl %d1,%d0 //put them in the right place
0206 movel %d0,CMDREG3B(%a6) //in the busy frame
0207
0208 commonE:
0209 bclrb #UFLAG,T_BYTE(%a6) //clr U flag from unimp
0210 bra do_clean //go clean and exit
0211 //
0212 // No bits in the enable byte match existing exceptions. Check for
0213 // the case of the ovfl exc without the ovfl enabled, but with
0214 // inex2 enabled.
0215 //
0216 no_match:
0217 btstb #inex2_bit,FPCR_ENABLE(%a6) //check for ovfl/inex2 case
0218 beqs no_exc //if clear, exit
0219 btstb #ovfl_bit,FPSR_EXCEPT(%a6) //now check ovfl
0220 beqs no_exc //if clear, exit
0221 bras ovfl_unfl //go to unfl_ovfl to determine if
0222 // ;it is an unsupp or unimp exc
0223
0224 // No exceptions are to be reported. If the instruction was
0225 // unimplemented, no FPU restore is necessary. If it was
0226 // unsupported, we must perform the restore.
0227 no_exc:
0228 tstb UFLG_TMP(%a6) //test flag for unsupp/unimp state
0229 beqs uni_no_exc
0230 uns_no_exc:
0231 tstb RES_FLG(%a6) //check if frestore is needed
0232 bne do_clean //if clear, no frestore needed
0233 uni_no_exc:
0234 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
0235 fmovemx USER_FP0(%a6),%fp0-%fp3
0236 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0237 unlk %a6
0238 bra finish_up
0239 //
0240 // Unsupported Data Type Handler:
0241 // Ovfl:
0242 // An fmoveout that results in an overflow is reported this way.
0243 // Unfl:
0244 // An fmoveout that results in an underflow is reported this way.
0245 //
0246 // Unimplemented Instruction Handler:
0247 // Ovfl:
0248 // Only scosh, setox, ssinh, stwotox, and scale can set overflow in
0249 // this manner.
0250 // Unfl:
0251 // Stwotox, setox, and scale can set underflow in this manner.
0252 // Any of the other Library Routines such that f(x)=x in which
0253 // x is an extended denorm can report an underflow exception.
0254 // It is the responsibility of the exception-causing exception
0255 // to make sure that WBTEMP is correct.
0256 //
0257 // The exceptional operand is in FP_SCR1.
0258 //
0259 ovfl_unfl:
0260 tstb UFLG_TMP(%a6) //test flag for unsupp/unimp state
0261 beqs ofuf_con
0262 //
0263 // The caller was from an unsupported data type trap. Test if the
0264 // caller set CU_ONLY. If so, the exceptional operand is expected in
0265 // FPTEMP, rather than WBTEMP.
0266 //
0267 tstb CU_ONLY(%a6) //test if inst is cu-only
0268 beq unsE3
0269 // move.w #$fe,CU_SAVEPC(%a6)
0270 clrb CU_SAVEPC(%a6)
0271 bsetb #E1,E_BYTE(%a6) //set E1 exception flag
0272 movew ETEMP_EX(%a6),FPTEMP_EX(%a6)
0273 movel ETEMP_HI(%a6),FPTEMP_HI(%a6)
0274 movel ETEMP_LO(%a6),FPTEMP_LO(%a6)
0275 bsetb #fptemp15_bit,DTAG(%a6) //set fpte15
0276 bclrb #UFLAG,T_BYTE(%a6) //clr U flag from unimp
0277 bra do_clean //go clean and exit
0278
0279 ofuf_con:
0280 moveb (%a7),VER_TMP(%a6) //save version number
0281 cmpib #BUSY_SIZE-4,1(%a7) //check for busy frame
0282 beqs busy_fr //if unimp, grow to busy
0283 cmpib #VER_40,(%a7) //test for orig unimp frame
0284 bnes try_41 //if not, test for rev frame
0285 moveql #13,%d0 //need to zero 14 lwords
0286 bras ofuf_fin
0287 try_41:
0288 cmpib #VER_41,(%a7) //test for rev unimp frame
0289 bnel fpsp_fmt_error //if neither, exit with error
0290 moveql #11,%d0 //need to zero 12 lwords
0291
0292 ofuf_fin:
0293 clrl (%a7)
0294 loop1:
0295 clrl -(%a7) //clear and dec a7
0296 dbra %d0,loop1
0297 moveb VER_TMP(%a6),(%a7)
0298 moveb #BUSY_SIZE-4,1(%a7) //write busy fmt word.
0299 busy_fr:
0300 movel FP_SCR1(%a6),WBTEMP_EX(%a6) //write
0301 movel FP_SCR1+4(%a6),WBTEMP_HI(%a6) //exceptional op to
0302 movel FP_SCR1+8(%a6),WBTEMP_LO(%a6) //wbtemp
0303 bsetb #E3,E_BYTE(%a6) //set E3 flag
0304 bclrb #E1,E_BYTE(%a6) //make sure E1 is clear
0305 bclrb #UFLAG,T_BYTE(%a6) //clr U flag
0306 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
0307 orl #sx_mask,E_BYTE(%a6)
0308 movel CMDREG1B(%a6),%d0 //fix cmd1b to make it
0309 andl #0x03c30000,%d0 //work for cmd3b
0310 bfextu CMDREG1B(%a6){#13:#1},%d1 //extract bit 2
0311 lsll #5,%d1
0312 swap %d1
0313 orl %d1,%d0 //put it in the right place
0314 bfextu CMDREG1B(%a6){#10:#3},%d1 //extract bit 3,4,5
0315 lsll #2,%d1
0316 swap %d1
0317 orl %d1,%d0 //put them in the right place
0318 movel %d0,CMDREG3B(%a6) //in the busy frame
0319
0320 //
0321 // Check if the frame to be restored is busy or unimp.
0322 /
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470