File Index
Files and directories
Sign in
FILE

x_unfl.S

File preview with syntax highlighting.

linux-6.19.14/arch/m68k/fpsp040/x_unfl.S S
  1|
  2|	x_unfl.sa 3.4 7/1/91
  3|
  4|	fpsp_unfl --- FPSP handler for underflow exception
  5|
  6| Trap disabled results
  7|	For 881/2 compatibility, sw must denormalize the intermediate
  8| result, then store the result.  Denormalization is accomplished
  9| by taking the intermediate result (which is always normalized) and
 10| shifting the mantissa right while incrementing the exponent until
 11| it is equal to the denormalized exponent for the destination
 12| format.  After denormalization, the result is rounded to the
 13| destination format.
 14|
 15| Trap enabled results
 16|	All trap disabled code applies.	In addition the exceptional
 17| operand needs to made available to the user with a bias of $6000
 18| added to the exponent.
 19|
 20
 21|		Copyright (C) Motorola, Inc. 1990
 22|			All Rights Reserved
 23|
 24|       For details on the license for this file, please see the
 25|       file, README, in this same directory.
 26
 27X_UNFL:	|idnt    2,1 | Motorola 040 Floating Point Software Package
 28
 29	|section	8
 30
 31#include "fpsp.h"
 32
 33	|xref	denorm
 34	|xref	round
 35	|xref	store
 36	|xref	g_rndpr
 37	|xref	g_opcls
 38	|xref	g_dfmtou
 39	|xref	real_unfl
 40	|xref	real_inex
 41	|xref	fpsp_done
 42	|xref	b1238_fix
 43
 44	.global	fpsp_unfl
 45fpsp_unfl:
 46	link		%a6,#-LOCAL_SIZE
 47	fsave		-(%a7)
 48	moveml		%d0-%d1/%a0-%a1,USER_DA(%a6)
 49	fmovemx	%fp0-%fp3,USER_FP0(%a6)
 50	fmoveml	%fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
 51
 52|
 53	bsrl		unf_res	|denormalize, round & store interm op
 54|
 55| If underflow exceptions are not enabled, check for inexact
 56| exception
 57|
 58	btstb		#unfl_bit,FPCR_ENABLE(%a6)
 59	beqs		ck_inex
 60
 61	btstb		#E3,E_BYTE(%a6)
 62	beqs		no_e3_1
 63|
 64| Clear dirty bit on dest resister in the frame before branching
 65| to b1238_fix.
 66|
 67	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
 68	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
 69	bsrl		b1238_fix		|test for bug1238 case
 70	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
 71	orl		#sx_mask,E_BYTE(%a6)
 72no_e3_1:
 73	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
 74	fmovemx	USER_FP0(%a6),%fp0-%fp3
 75	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
 76	frestore	(%a7)+
 77	unlk		%a6
 78	bral		real_unfl
 79|
 80| It is possible to have either inex2 or inex1 exceptions with the
 81| unfl.  If the inex enable bit is set in the FPCR, and either
 82| inex2 or inex1 occurred, we must clean up and branch to the
 83| real inex handler.
 84|
 85ck_inex:
 86	moveb		FPCR_ENABLE(%a6),%d0
 87	andb		FPSR_EXCEPT(%a6),%d0
 88	andib		#0x3,%d0
 89	beqs		unfl_done
 90
 91|
 92| Inexact enabled and reported, and we must take an inexact exception
 93|
 94take_inex:
 95	btstb		#E3,E_BYTE(%a6)
 96	beqs		no_e3_2
 97|
 98| Clear dirty bit on dest resister in the frame before branching
 99| to b1238_fix.
100|
101	bfextu		CMDREG3B(%a6){#6:#3},%d0	|get dest reg no
102	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
103	bsrl		b1238_fix		|test for bug1238 case
104	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
105	orl		#sx_mask,E_BYTE(%a6)
106no_e3_2:
107	moveb		#INEX_VEC,EXC_VEC+1(%a6)
108	moveml         USER_DA(%a6),%d0-%d1/%a0-%a1
109	fmovemx        USER_FP0(%a6),%fp0-%fp3
110	fmoveml        USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
111	frestore        (%a7)+
112	unlk            %a6
113	bral		real_inex
114
115unfl_done:
116	bclrb		#E3,E_BYTE(%a6)
117	beqs		e1_set		|if set then branch
118|
119| Clear dirty bit on dest resister in the frame before branching
120| to b1238_fix.
121|
122	bfextu		CMDREG3B(%a6){#6:#3},%d0		|get dest reg no
123	bclrb		%d0,FPR_DIRTY_BITS(%a6)	|clr dest dirty bit
124	bsrl		b1238_fix		|test for bug1238 case
125	movel		USER_FPSR(%a6),FPSR_SHADOW(%a6)
126	orl		#sx_mask,E_BYTE(%a6)
127	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
128	fmovemx	USER_FP0(%a6),%fp0-%fp3
129	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
130	frestore	(%a7)+
131	unlk		%a6
132	bral		fpsp_done
133e1_set:
134	moveml		USER_DA(%a6),%d0-%d1/%a0-%a1
135	fmovemx	USER_FP0(%a6),%fp0-%fp3
136	fmoveml	USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
137	unlk		%a6
138	bral		fpsp_done
139|
140|	unf_res --- underflow result calculation
141|
142unf_res:
143	bsrl		g_rndpr		|returns RND_PREC in d0 0=ext,
144|					;1=sgl, 2=dbl
145|					;we need the RND_PREC in the
146|					;upper word for round
147	movew		#0,-(%a7)
148	movew		%d0,-(%a7)	|copy RND_PREC to stack
149|
150|
151| If the exception bit set is E3, the exceptional operand from the
152| fpu is in WBTEMP; else it is in FPTEMP.
153|
154	btstb		#E3,E_BYTE(%a6)
155	beqs		unf_E1
156unf_E3:
157	lea		WBTEMP(%a6),%a0	|a0 now points to operand
158|
159| Test for fsgldiv and fsglmul.  If the inst was one of these, then
160| force the precision to extended for the denorm routine.  Use
161| the user's precision for the round routine.
162|
163	movew		CMDREG3B(%a6),%d1	|check for fsgldiv or fsglmul
164	andiw		#0x7f,%d1
165	cmpiw		#0x30,%d1		|check for sgldiv
166	beqs		unf_sgl
167	cmpiw		#0x33,%d1		|check for sglmul
168	bnes		unf_cont	|if not, use fpcr prec in round
169unf_sgl:
170	clrl		%d0
171	movew		#0x1,(%a7)	|override g_rndpr precision
172|					;force single
173	bras		unf_cont
174unf_E1:
175	lea		FPTEMP(%a6),%a0	|a0 now points to operand
176unf_cont:
177	bclrb		#sign_bit,LOCAL_EX(%a0)	|clear sign bit
178	sne		LOCAL_SGN(%a0)		|store sign
179
180	bsrl		denorm		|returns denorm, a0 points to it
181|
182| WARNING:
183|				;d0 has guard,round sticky bit
184|				;make sure that it is not corrupted
185|				;before it reaches the round subroutine
186|				;also ensure that a0 isn't corrupted
187
188|
189| Set up d1 for round subroutine d1 contains the PREC/MODE
190| information respectively on upper/lower register halves.
191|
192	bfextu		FPCR_MODE(%a6){#2:#2},%d1	|get mode from FPCR
193|						;mode in lower d1
194	addl		(%a7)+,%d1		|merge PREC/MODE
195|
196| WARNING: a0 and d0 are assumed to be intact between the denorm and
197| round subroutines. All code between these two subroutines
198| must not corrupt a0 and d0.
199|
200|
201| Perform Round
202|	Input:		a0 points to input operand
203|			d0{31:29} has guard, round, sticky
204|			d1{01:00} has rounding mode
205|			d1{17:16} has rounding precision
206|	Output:		a0 points to rounded operand
207|
208
209	bsrl		round		|returns rounded denorm at (a0)
210|
211| Differentiate between store to memory vs. store to register
212|
213unf_store:
214	bsrl		g_opcls		|returns opclass in d0{2:0}
215	cmpib		#0x3,%d0
216	bnes		not_opc011
217|
218| At this point, a store to memory is pending
219|
220opc011:
221	bsrl		g_dfmtou
222	tstb		%d0
223	beqs		ext_opc011	|If extended, do not subtract
224|				;If destination format is sgl/dbl,
225	tstb		LOCAL_HI(%a0)	|If rounded result is normal,don't
226|					;subtract
227	bmis		ext_opc011
228	subqw		#1,LOCAL_EX(%a0)	|account for denorm bias vs.
229|				;normalized bias
230|				;          normalized   denormalized
231|				;single       $7f           $7e
232|				;double       $3ff          $3fe
233|
234ext_opc011:
235	bsrl		store		|stores to memory
236	bras		unf_done	|finish up
237
238|
239| At this point, a store to a float register is pending
240|
241not_opc011:
242	bsrl		store	|stores to float register
243|				;a0 is not corrupted on a store to a
244|				;float register.
245|
246| Set the condition codes according to result
247|
248	tstl		LOCAL_HI(%a0)	|check upper mantissa
249	bnes		ck_sgn
250	tstl		LOCAL_LO(%a0)	|check lower mantissa
251	bnes		ck_sgn
252	bsetb		#z_bit,FPSR_CC(%a6) |set condition codes if zero
253ck_sgn:
254	btstb		#sign_bit,LOCAL_EX(%a0)	|check the sign bit
255	beqs		unf_done
256	bsetb		#neg_bit,FPSR_CC(%a6)
257
258|
259| Finish.
260|
261unf_done:
262	btstb		#inex2_bit,FPSR_EXCEPT(%a6)
263	beqs		no_aunfl
264	bsetb		#aunfl_bit,FPSR_AEXCEPT(%a6)
265no_aunfl:
266	rts
267
268	|end
~/ Read-only file preview.