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