xref: /netbsd/sys/arch/m68k/fpsp/util.sa (revision bf9ec67e)
1*	$NetBSD: util.sa,v 1.4 2001/12/09 01:43:13 briggs Exp $
2
3*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4*	M68000 Hi-Performance Microprocessor Division
5*	M68040 Software Package
6*
7*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
8*	All rights reserved.
9*
10*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11*	To the maximum extent permitted by applicable law,
12*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14*	PARTICULAR PURPOSE and any warranty against infringement with
15*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16*	and any accompanying written materials.
17*
18*	To the maximum extent permitted by applicable law,
19*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
24*	and support of the SOFTWARE.
25*
26*	You are hereby granted a copyright license to use, modify, and
27*	distribute the SOFTWARE so long as this entire notice is retained
28*	without alteration in any modified and/or redistributed versions,
29*	and that such modified versions are clearly identified as such.
30*	No licenses are granted by implication, estoppel or otherwise
31*	under any patents or trademarks of Motorola, Inc.
32
33*
34*	util.sa 3.7 7/29/91
35*
36*	This file contains routines used by other programs.
37*
38*	ovf_res: used by overflow to force the correct
39*		 result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
40*		 derivatives of this routine.
41*	get_fline: get user's opcode word
42*	g_dfmtou: returns the destination format.
43*	g_opcls: returns the opclass of the float instruction.
44*	g_rndpr: returns the rounding precision.
45*	reg_dest: write byte, word, or long data to Dn
46*
47
48UTIL	IDNT    2,1 Motorola 040 Floating Point Software Package
49
50	section	8
51
52	include	fpsp.h
53
54	xref	mem_read
55
56	xdef	g_dfmtou
57	xdef	g_opcls
58	xdef	g_rndpr
59	xdef	get_fline
60	xdef	reg_dest
61
62*
63* Final result table for ovf_res. Note that the negative counterparts
64* are unnecessary as ovf_res always returns the sign separately from
65* the exponent.
66*					;+inf
67EXT_PINF	dc.l	$7fff0000,$00000000,$00000000,$00000000
68*					;largest +ext
69EXT_PLRG	dc.l	$7ffe0000,$ffffffff,$ffffffff,$00000000
70*					;largest magnitude +sgl in ext
71SGL_PLRG	dc.l	$407e0000,$ffffff00,$00000000,$00000000
72*					;largest magnitude +dbl in ext
73DBL_PLRG	dc.l	$43fe0000,$ffffffff,$fffff800,$00000000
74*					;largest -ext
75
76tblovfl:
77	dc.l	EXT_RN
78	dc.l	EXT_RZ
79	dc.l	EXT_RM
80	dc.l	EXT_RP
81	dc.l	SGL_RN
82	dc.l	SGL_RZ
83	dc.l	SGL_RM
84	dc.l	SGL_RP
85	dc.l	DBL_RN
86	dc.l	DBL_RZ
87	dc.l	DBL_RM
88	dc.l	DBL_RP
89	dc.l	error
90	dc.l	error
91	dc.l	error
92	dc.l	error
93
94
95*
96*	ovf_r_k --- overflow result calculation
97*
98* This entry point is used by kernel_ex.
99*
100* This forces the destination precision to be extended
101*
102* Input:	operand in ETEMP
103* Output:	a result is in ETEMP (internal extended format)
104*
105	xdef	ovf_r_k
106ovf_r_k:
107	lea	ETEMP(a6),a0	;a0 points to source operand
108	bclr.b	#sign_bit,ETEMP_EX(a6)
109	sne	ETEMP_SGN(a6)	;convert to internal IEEE format
110
111*
112*	ovf_r_x2 --- overflow result calculation
113*
114* This entry point used by x_ovfl.  (opclass 0 and 2)
115*
116* Input		a0  points to an operand in the internal extended format
117* Output	a0  points to the result in the internal extended format
118*
119* This sets the round precision according to the user's FPCR unless the
120* instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
121* fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
122* If the instruction is fsgldiv of fsglmul, the rounding precision must be
123* extended.  If the instruction is not fsgldiv or fsglmul but a force-
124* precision instruction, the rounding precision is then set to the force
125* precision.
126
127	xdef	ovf_r_x2
128ovf_r_x2:
129	btst.b	#E3,E_BYTE(a6)		;check for nu exception
130	beq.l	ovf_e1_exc		;it is cu exception
131ovf_e3_exc:
132	move.w	CMDREG3B(a6),d0		;get the command word
133	andi.w	#$00000060,d0		;clear all bits except 6 and 5
134	cmpi.l	#$00000040,d0
135	beq.l	ovff_sgl		;force precision is single
136	cmpi.l	#$00000060,d0
137	beq.l	ovff_dbl		;force precision is double
138	move.w	CMDREG3B(a6),d0		;get the command word again
139	andi.l	#$7f,d0			;clear all except operation
140	cmpi.l	#$33,d0
141	beq.l	ovf_fsgl		;fsglmul or fsgldiv
142	cmpi.l	#$30,d0
143	beq.l	ovf_fsgl
144	bra	ovf_fpcr		;instruction is none of the above
145*					;use FPCR
146ovf_e1_exc:
147	move.w	CMDREG1B(a6),d0		;get command word
148	andi.l	#$00000044,d0		;clear all bits except 6 and 2
149	cmpi.l	#$00000040,d0
150	beq.l	ovff_sgl		;the instruction is force single
151	cmpi.l	#$00000044,d0
152	beq.l	ovff_dbl		;the instruction is force double
153	move.w	CMDREG1B(a6),d0		;again get the command word
154	andi.l	#$0000007f,d0		;clear all except the op code
155	cmpi.l	#$00000027,d0
156	beq.l	ovf_fsgl		;fsglmul
157	cmpi.l 	#$00000024,d0
158	beq.l	ovf_fsgl		;fsgldiv
159	bra	ovf_fpcr		;none of the above, use FPCR
160*
161*
162* Inst is either fsgldiv or fsglmul.  Force extended precision.
163*
164ovf_fsgl:
165	clr.l	d0
166	bra.b	short_ovf_res
167
168ovff_sgl:
169	move.l	#$00000001,d0		;set single
170	bra.b	short_ovf_res
171ovff_dbl:
172	move.l	#$00000002,d0		;set double
173	bra.b	short_ovf_res
174*
175* The precision is in the fpcr.
176*
177ovf_fpcr:
178	bfextu	FPCR_MODE(a6){0:2},d0 ;set round precision
179	bra.b	short_ovf_res
180
181*
182*
183*	ovf_r_x3 --- overflow result calculation
184*
185* This entry point used by x_ovfl. (opclass 3 only)
186*
187* Input		a0  points to an operand in the internal extended format
188* Output	a0  points to the result in the internal extended format
189*
190* This sets the round precision according to the destination size.
191*
192	xdef	ovf_r_x3
193ovf_r_x3:
194	bsr	g_dfmtou	;get dest fmt in d0{1:0}
195*				;for fmovout, the destination format
196*				;is the rounding precision
197
198*
199*	ovf_res --- overflow result calculation
200*
201* Input:
202*	a0 	points to operand in internal extended format
203* Output:
204*	a0 	points to result in internal extended format
205*
206	xdef	ovf_res
207ovf_res:
208short_ovf_res:
209	lsl.l	#2,d0		;move round precision to d0{3:2}
210	bfextu	FPCR_MODE(a6){2:2},d1 ;set round mode
211	or.l	d1,d0		;index is fmt:mode in d0{3:0}
212	lea.l	tblovfl,a1	;load a1 with table address
213	move.l	(a1,d0*4),a1	;use d0 as index to the table
214	jmp	(a1)		;go to the correct routine
215*
216*case DEST_FMT = EXT
217*
218EXT_RN:
219	lea.l	EXT_PINF,a1	;answer is +/- infinity
220	bset.b	#inf_bit,FPSR_CC(a6)
221	bra	set_sign	;now go set the sign
222EXT_RZ:
223	lea.l	EXT_PLRG,a1	;answer is +/- large number
224	bra	set_sign	;now go set the sign
225EXT_RM:
226	tst.b	LOCAL_SGN(a0)	;if negative overflow
227	beq.b	e_rm_pos
228e_rm_neg:
229	lea.l	EXT_PINF,a1	;answer is negative infinity
230	or.l	#neginf_mask,USER_FPSR(a6)
231	bra	end_ovfr
232e_rm_pos:
233	lea.l	EXT_PLRG,a1	;answer is large positive number
234	bra	end_ovfr
235EXT_RP:
236	tst.b	LOCAL_SGN(a0)	;if negative overflow
237	beq.b	e_rp_pos
238e_rp_neg:
239	lea.l	EXT_PLRG,a1	;answer is large negative number
240	bset.b	#neg_bit,FPSR_CC(a6)
241	bra	end_ovfr
242e_rp_pos:
243	lea.l	EXT_PINF,a1	;answer is positive infinity
244	bset.b	#inf_bit,FPSR_CC(a6)
245	bra	end_ovfr
246*
247*case DEST_FMT = DBL
248*
249DBL_RN:
250	lea.l	EXT_PINF,a1	;answer is +/- infinity
251	bset.b	#inf_bit,FPSR_CC(a6)
252	bra	set_sign
253DBL_RZ:
254	lea.l	DBL_PLRG,a1	;answer is +/- large number
255	bra	set_sign	;now go set the sign
256DBL_RM:
257	tst.b	LOCAL_SGN(a0)	;if negative overflow
258	beq.b	d_rm_pos
259d_rm_neg:
260	lea.l	EXT_PINF,a1	;answer is negative infinity
261	or.l	#neginf_mask,USER_FPSR(a6)
262	bra	end_ovfr	;inf is same for all precisions (ext,dbl,sgl)
263d_rm_pos:
264	lea.l	DBL_PLRG,a1	;answer is large positive number
265	bra	end_ovfr
266DBL_RP:
267	tst.b	LOCAL_SGN(a0)	;if negative overflow
268	beq.b	d_rp_pos
269d_rp_neg:
270	lea.l	DBL_PLRG,a1	;answer is large negative number
271	bset.b	#neg_bit,FPSR_CC(a6)
272	bra	end_ovfr
273d_rp_pos:
274	lea.l	EXT_PINF,a1	;answer is positive infinity
275	bset.b	#inf_bit,FPSR_CC(a6)
276	bra	end_ovfr
277*
278*case DEST_FMT = SGL
279*
280SGL_RN:
281	lea.l	EXT_PINF,a1	;answer is +/-  infinity
282	bset.b	#inf_bit,FPSR_CC(a6)
283	bra.b	set_sign
284SGL_RZ:
285	lea.l	SGL_PLRG,a1	;anwer is +/- large number
286	bra.b	set_sign
287SGL_RM:
288	tst.b	LOCAL_SGN(a0)	;if negative overflow
289	beq.b	s_rm_pos
290s_rm_neg:
291	lea.l	EXT_PINF,a1	;answer is negative infinity
292	or.l	#neginf_mask,USER_FPSR(a6)
293	bra.b	end_ovfr
294s_rm_pos:
295	lea.l	SGL_PLRG,a1	;answer is large positive number
296	bra.b	end_ovfr
297SGL_RP:
298	tst.b	LOCAL_SGN(a0)	;if negative overflow
299	beq.b	s_rp_pos
300s_rp_neg:
301	lea.l	SGL_PLRG,a1	;answer is large negative number
302	bset.b	#neg_bit,FPSR_CC(a6)
303	bra.b	end_ovfr
304s_rp_pos:
305	lea.l	EXT_PINF,a1	;answer is postive infinity
306	bset.b	#inf_bit,FPSR_CC(a6)
307	bra.b	end_ovfr
308
309set_sign:
310	tst.b	LOCAL_SGN(a0)	;if negative overflow
311	beq.b	end_ovfr
312neg_sign:
313	bset.b	#neg_bit,FPSR_CC(a6)
314
315end_ovfr:
316	move.w	LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign
317	move.l	LOCAL_HI(a1),LOCAL_HI(a0)
318	move.l	LOCAL_LO(a1),LOCAL_LO(a0)
319	rts
320
321
322*
323*	ERROR
324*
325error:
326	rts
327*
328*	get_fline --- get f-line opcode of interrupted instruction
329*
330*	Returns opcode in the low word of d0.
331*
332get_fline:
333	move.l	USER_FPIAR(a6),a0	;opcode address
334	clr.l	-(a7)		;reserve a word on the stack
335	lea.l	2(a7),a1	;point to low word of temporary
336	move.l	#2,d0		;count
337	bsr.l	mem_read
338	move.l	(a7)+,d0
339	rts
340*
341* 	g_rndpr --- put rounding precision in d0{1:0}
342*
343*	valid return codes are:
344*		00 - extended
345*		01 - single
346*		10 - double
347*
348* begin
349* get rounding precision (cmdreg3b{6:5})
350* begin
351*  case	opclass = 011 (move out)
352*	get destination format - this is the also the rounding precision
353*
354*  case	opclass = 0x0
355*	if E3
356*	    *case RndPr(from cmdreg3b{6:5} = 11  then RND_PREC = DBL
357*	    *case RndPr(from cmdreg3b{6:5} = 10  then RND_PREC = SGL
358*	     case RndPr(from cmdreg3b{6:5} = 00 | 01
359*		use precision from FPCR{7:6}
360*			case 00 then RND_PREC = EXT
361*			case 01 then RND_PREC = SGL
362*			case 10 then RND_PREC = DBL
363*	else E1
364*	     use precision in FPCR{7:6}
365*	     case 00 then RND_PREC = EXT
366*	     case 01 then RND_PREC = SGL
367*	     case 10 then RND_PREC = DBL
368* end
369*
370g_rndpr:
371	bsr.w	g_opcls		;get opclass in d0{2:0}
372	cmp.w	#$0003,d0	;check for opclass 011
373	bne.b	op_0x0
374
375*
376* For move out instructions (opclass 011) the destination format
377* is the same as the rounding precision.  Pass results from g_dfmtou.
378*
379	bsr.w 	g_dfmtou
380	rts
381op_0x0:
382	btst.b	#E3,E_BYTE(a6)
383	beq.l	unf_e1_exc	;branch to e1 underflow
384unf_e3_exc:
385	move.l	CMDREG3B(a6),d0	;rounding precision in d0{10:9}
386	bfextu	d0{9:2},d0	;move the rounding prec bits to d0{1:0}
387	cmpi.l	#$2,d0
388	beq.l	unff_sgl	;force precision is single
389	cmpi.l	#$3,d0		;force precision is double
390	beq.l	unff_dbl
391	move.w	CMDREG3B(a6),d0	;get the command word again
392	andi.l	#$7f,d0		;clear all except operation
393	cmpi.l	#$33,d0
394	beq.l	unf_fsgl	;fsglmul or fsgldiv
395	cmpi.l	#$30,d0
396	beq.l	unf_fsgl	;fsgldiv or fsglmul
397	bra	unf_fpcr
398unf_e1_exc:
399	move.l	CMDREG1B(a6),d0	;get 32 bits off the stack, 1st 16 bits
400*				;are the command word
401	andi.l	#$00440000,d0	;clear all bits except bits 6 and 2
402	cmpi.l	#$00400000,d0
403	beq.l	unff_sgl	;force single
404	cmpi.l	#$00440000,d0	;force double
405	beq.l	unff_dbl
406	move.l	CMDREG1B(a6),d0	;get the command word again
407	andi.l	#$007f0000,d0	;clear all bits except the operation
408	cmpi.l	#$00270000,d0
409	beq.l	unf_fsgl	;fsglmul
410	cmpi.l	#$00240000,d0
411	beq.l	unf_fsgl	;fsgldiv
412	bra	unf_fpcr
413
414*
415* Convert to return format.  The values from cmdreg3b and the return
416* values are:
417*	cmdreg3b	return	     precision
418*	--------	------	     ---------
419*	  00,01		  0		ext
420*	   10		  1		sgl
421*	   11		  2		dbl
422* Force single
423*
424unff_sgl:
425	move.l	#1,d0		;return 1
426	rts
427*
428* Force double
429*
430unff_dbl:
431	move.l	#2,d0		;return 2
432	rts
433*
434* Force extended
435*
436unf_fsgl:
437	clr.l	d0
438	rts
439*
440* Get rounding precision set in FPCR{7:6}.
441*
442unf_fpcr:
443	move.l	USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6}
444	bfextu	d0{24:2},d0	;move the rounding prec bits to d0{1:0}
445	rts
446*
447*	g_opcls --- put opclass in d0{2:0}
448*
449g_opcls:
450	btst.b	#E3,E_BYTE(a6)
451	beq.b	opc_1b		;if set, go to cmdreg1b
452opc_3b:
453	clr.l	d0		;if E3, only opclass 0x0 is possible
454	rts
455opc_1b:
456	move.l	CMDREG1B(a6),d0
457	bfextu	d0{0:3},d0	;shift opclass bits d0{31:29} to d0{2:0}
458	rts
459*
460*	g_dfmtou --- put destination format in d0{1:0}
461*
462*	If E1, the format is from cmdreg1b{12:10}
463*	If E3, the format is extended.
464*
465*	Dest. Fmt.
466*		extended  010 -> 00
467*		single    001 -> 01
468*		double    101 -> 10
469*
470g_dfmtou:
471	btst.b	#E3,E_BYTE(a6)
472	beq.b	op011
473	clr.l	d0		;if E1, size is always ext
474	rts
475op011:
476	move.l	CMDREG1B(a6),d0
477	bfextu	d0{3:3},d0	;dest fmt from cmdreg1b{12:10}
478	cmp.b	#1,d0		;check for single
479	bne.b	not_sgl
480	move.l	#1,d0
481	rts
482not_sgl:
483	cmp.b	#5,d0		;check for double
484	bne.b	not_dbl
485	move.l	#2,d0
486	rts
487not_dbl:
488	clr.l	d0		;must be extended
489	rts
490
491*
492*
493* Final result table for unf_sub. Note that the negative counterparts
494* are unnecessary as unf_sub always returns the sign separately from
495* the exponent.
496*					;+zero
497EXT_PZRO	dc.l	$00000000,$00000000,$00000000,$00000000
498*					;+zero
499SGL_PZRO	dc.l	$3f810000,$00000000,$00000000,$00000000
500*					;+zero
501DBL_PZRO	dc.l	$3c010000,$00000000,$00000000,$00000000
502*					;smallest +ext denorm
503EXT_PSML	dc.l	$00000000,$00000000,$00000001,$00000000
504*					;smallest +sgl denorm
505SGL_PSML	dc.l	$3f810000,$00000100,$00000000,$00000000
506*					;smallest +dbl denorm
507DBL_PSML	dc.l	$3c010000,$00000000,$00000800,$00000000
508*
509*	UNF_SUB --- underflow result calculation
510*
511* Input:
512*	d0 	contains round precision
513*	a0	points to input operand in the internal extended format
514*
515* Output:
516*	a0 	points to correct internal extended precision result.
517*
518
519tblunf:
520	dc.l	uEXT_RN
521	dc.l	uEXT_RZ
522	dc.l	uEXT_RM
523	dc.l	uEXT_RP
524	dc.l	uSGL_RN
525	dc.l	uSGL_RZ
526	dc.l	uSGL_RM
527	dc.l	uSGL_RP
528	dc.l	uDBL_RN
529	dc.l	uDBL_RZ
530	dc.l	uDBL_RM
531	dc.l	uDBL_RP
532	dc.l	uDBL_RN
533	dc.l	uDBL_RZ
534	dc.l	uDBL_RM
535	dc.l	uDBL_RP
536
537	xdef	unf_sub
538unf_sub:
539	lsl.l	#2,d0		;move round precision to d0{3:2}
540	bfextu	FPCR_MODE(a6){2:2},d1 ;set round mode
541	or.l	d1,d0		;index is fmt:mode in d0{3:0}
542	lea.l	tblunf,a1	;load a1 with table address
543	move.l	(a1,d0*4),a1	;use d0 as index to the table
544	jmp	(a1)		;go to the correct routine
545*
546*case DEST_FMT = EXT
547*
548uEXT_RN:
549	lea.l	EXT_PZRO,a1	;answer is +/- zero
550	bset.b	#z_bit,FPSR_CC(a6)
551	bra	uset_sign	;now go set the sign
552uEXT_RZ:
553	lea.l	EXT_PZRO,a1	;answer is +/- zero
554	bset.b	#z_bit,FPSR_CC(a6)
555	bra	uset_sign	;now go set the sign
556uEXT_RM:
557	tst.b	LOCAL_SGN(a0)	;if negative underflow
558	beq.b	ue_rm_pos
559ue_rm_neg:
560	lea.l	EXT_PSML,a1	;answer is negative smallest denorm
561	bset.b	#neg_bit,FPSR_CC(a6)
562	bra	end_unfr
563ue_rm_pos:
564	lea.l	EXT_PZRO,a1	;answer is positive zero
565	bset.b	#z_bit,FPSR_CC(a6)
566	bra	end_unfr
567uEXT_RP:
568	tst.b	LOCAL_SGN(a0)	;if negative underflow
569	beq.b	ue_rp_pos
570ue_rp_neg:
571	lea.l	EXT_PZRO,a1	;answer is negative zero
572	ori.l	#negz_mask,USER_FPSR(a6)
573	bra	end_unfr
574ue_rp_pos:
575	lea.l	EXT_PSML,a1	;answer is positive smallest denorm
576	bra	end_unfr
577*
578*case DEST_FMT = DBL
579*
580uDBL_RN:
581	lea.l	DBL_PZRO,a1	;answer is +/- zero
582	bset.b	#z_bit,FPSR_CC(a6)
583	bra	uset_sign
584uDBL_RZ:
585	lea.l	DBL_PZRO,a1	;answer is +/- zero
586	bset.b	#z_bit,FPSR_CC(a6)
587	bra	uset_sign	;now go set the sign
588uDBL_RM:
589	tst.b	LOCAL_SGN(a0)	;if negative overflow
590	beq.b	ud_rm_pos
591ud_rm_neg:
592	lea.l	DBL_PSML,a1	;answer is smallest denormalized negative
593	bset.b	#neg_bit,FPSR_CC(a6)
594	bra	end_unfr
595ud_rm_pos:
596	lea.l	DBL_PZRO,a1	;answer is positive zero
597	bset.b	#z_bit,FPSR_CC(a6)
598	bra	end_unfr
599uDBL_RP:
600	tst.b	LOCAL_SGN(a0)	;if negative overflow
601	beq.b	ud_rp_pos
602ud_rp_neg:
603	lea.l	DBL_PZRO,a1	;answer is negative zero
604	ori.l	#negz_mask,USER_FPSR(a6)
605	bra	end_unfr
606ud_rp_pos:
607	lea.l	DBL_PSML,a1	;answer is smallest denormalized negative
608	bra	end_unfr
609*
610*case DEST_FMT = SGL
611*
612uSGL_RN:
613	lea.l	SGL_PZRO,a1	;answer is +/- zero
614	bset.b	#z_bit,FPSR_CC(a6)
615	bra.b	uset_sign
616uSGL_RZ:
617	lea.l	SGL_PZRO,a1	;answer is +/- zero
618	bset.b	#z_bit,FPSR_CC(a6)
619	bra.b	uset_sign
620uSGL_RM:
621	tst.b	LOCAL_SGN(a0)	;if negative overflow
622	beq.b	us_rm_pos
623us_rm_neg:
624	lea.l	SGL_PSML,a1	;answer is smallest denormalized negative
625	bset.b	#neg_bit,FPSR_CC(a6)
626	bra.b	end_unfr
627us_rm_pos:
628	lea.l	SGL_PZRO,a1	;answer is positive zero
629	bset.b	#z_bit,FPSR_CC(a6)
630	bra.b	end_unfr
631uSGL_RP:
632	tst.b	LOCAL_SGN(a0)	;if negative overflow
633	beq.b	us_rp_pos
634us_rp_neg:
635	lea.l	SGL_PZRO,a1	;answer is negative zero
636	ori.l	#negz_mask,USER_FPSR(a6)
637	bra.b	end_unfr
638us_rp_pos:
639	lea.l	SGL_PSML,a1	;answer is smallest denormalized positive
640	bra.b	end_unfr
641
642uset_sign:
643	tst.b	LOCAL_SGN(a0)	;if negative overflow
644	beq.b	end_unfr
645uneg_sign:
646	bset.b	#neg_bit,FPSR_CC(a6)
647
648end_unfr:
649	move.w	LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign
650	move.l	LOCAL_HI(a1),LOCAL_HI(a0)
651	move.l	LOCAL_LO(a1),LOCAL_LO(a0)
652	rts
653*
654*	reg_dest --- write byte, word, or long data to Dn
655*
656*
657* Input:
658*	L_SCR1: Data
659*	d1:     data size and dest register number formatted as:
660*
661*	32		5    4     3     2     1     0
662*       -----------------------------------------------
663*       |        0        |    Size   |  Dest Reg #   |
664*       -----------------------------------------------
665*
666*	Size is:
667*		0 - Byte
668*		1 - Word
669*		2 - Long/Single
670*
671pregdst:
672	dc.l	byte_d0
673	dc.l	byte_d1
674	dc.l	byte_d2
675	dc.l	byte_d3
676	dc.l	byte_d4
677	dc.l	byte_d5
678	dc.l	byte_d6
679	dc.l	byte_d7
680	dc.l	word_d0
681	dc.l	word_d1
682	dc.l	word_d2
683	dc.l	word_d3
684	dc.l	word_d4
685	dc.l	word_d5
686	dc.l	word_d6
687	dc.l	word_d7
688	dc.l	long_d0
689	dc.l	long_d1
690	dc.l	long_d2
691	dc.l	long_d3
692	dc.l	long_d4
693	dc.l	long_d5
694	dc.l	long_d6
695	dc.l	long_d7
696
697reg_dest:
698	lea.l	pregdst,a0
699	move.l	(a0,d1*4),a0
700	jmp	(a0)
701
702byte_d0:
703	move.b	L_SCR1(a6),USER_D0+3(a6)
704	rts
705byte_d1:
706	move.b	L_SCR1(a6),USER_D1+3(a6)
707	rts
708byte_d2:
709	move.b	L_SCR1(a6),d2
710	rts
711byte_d3:
712	move.b	L_SCR1(a6),d3
713	rts
714byte_d4:
715	move.b	L_SCR1(a6),d4
716	rts
717byte_d5:
718	move.b	L_SCR1(a6),d5
719	rts
720byte_d6:
721	move.b	L_SCR1(a6),d6
722	rts
723byte_d7:
724	move.b	L_SCR1(a6),d7
725	rts
726word_d0:
727	move.w	L_SCR1(a6),USER_D0+2(a6)
728	rts
729word_d1:
730	move.w	L_SCR1(a6),USER_D1+2(a6)
731	rts
732word_d2:
733	move.w	L_SCR1(a6),d2
734	rts
735word_d3:
736	move.w	L_SCR1(a6),d3
737	rts
738word_d4:
739	move.w	L_SCR1(a6),d4
740	rts
741word_d5:
742	move.w	L_SCR1(a6),d5
743	rts
744word_d6:
745	move.w	L_SCR1(a6),d6
746	rts
747word_d7:
748	move.w	L_SCR1(a6),d7
749	rts
750long_d0:
751	move.l	L_SCR1(a6),USER_D0(a6)
752	rts
753long_d1:
754	move.l	L_SCR1(a6),USER_D1(a6)
755	rts
756long_d2:
757	move.l	L_SCR1(a6),d2
758	rts
759long_d3:
760	move.l	L_SCR1(a6),d3
761	rts
762long_d4:
763	move.l	L_SCR1(a6),d4
764	rts
765long_d5:
766	move.l	L_SCR1(a6),d5
767	rts
768long_d6:
769	move.l	L_SCR1(a6),d6
770	rts
771long_d7:
772	move.l	L_SCR1(a6),d7
773	rts
774	end
775