xref: /netbsd-src/sys/arch/m68k/fpsp/get_op.sa (revision 4d7e773266e3c3f48566c86c0ad52d51c6454fd1)
1*	$NetBSD: get_op.sa,v 1.3 1994/10/26 07:49:09 cgd 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*	get_op.sa 3.6 5/19/92
35*
36*	get_op.sa 3.5 4/26/91
37*
38*  Description: This routine is called by the unsupported format/data
39* type exception handler ('unsupp' - vector 55) and the unimplemented
40* instruction exception handler ('unimp' - vector 11).  'get_op'
41* determines the opclass (0, 2, or 3) and branches to the
42* opclass handler routine.  See 68881/2 User's Manual table 4-11
43* for a description of the opclasses.
44*
45* For UNSUPPORTED data/format (exception vector 55) and for
46* UNIMPLEMENTED instructions (exception vector 11) the following
47* applies:
48*
49* - For unnormormalized numbers (opclass 0, 2, or 3) the
50* number(s) is normalized and the operand type tag is updated.
51*
52* - For a packed number (opclass 2) the number is unpacked and the
53* operand type tag is updated.
54*
55* - For denormalized numbers (opclass 0 or 2) the number(s) is not
56* changed but passed to the next module.  The next module for
57* unimp is do_func, the next module for unsupp is res_func.
58*
59* For UNSUPPORTED data/format (exception vector 55) only the
60* following applies:
61*
62* - If there is a move out with a packed number (opclass 3) the
63* number is packed and written to user memory.  For the other
64* opclasses the number(s) are written back to the fsave stack
65* and the instruction is then restored back into the '040.  The
66* '040 is then able to complete the instruction.
67*
68* For example:
69* fadd.x fpm,fpn where the fpm contains an unnormalized number.
70* The '040 takes an unsupported data trap and gets to this
71* routine.  The number is normalized, put back on the stack and
72* then an frestore is done to restore the instruction back into
73* the '040.  The '040 then re-executes the fadd.x fpm,fpn with
74* a normalized number in the source and the instruction is
75* successful.
76*
77* Next consider if in the process of normalizing the un-
78* normalized number it becomes a denormalized number.  The
79* routine which converts the unnorm to a norm (called mk_norm)
80* detects this and tags the number as a denorm.  The routine
81* res_func sees the denorm tag and converts the denorm to a
82* norm.  The instruction is then restored back into the '040
83* which re_executess the instruction.
84*
85
86GET_OP    IDNT    2,1 Motorola 040 Floating Point Software Package
87
88	section	8
89
90	include	fpsp.h
91
92	xdef	PIRN,PIRZRM,PIRP
93	xdef	SMALRN,SMALRZRM,SMALRP
94	xdef	BIGRN,BIGRZRM,BIGRP
95
96PIRN:
97	dc.l $40000000,$c90fdaa2,$2168c235    ;pi
98PIRZRM:
99	dc.l $40000000,$c90fdaa2,$2168c234    ;pi
100PIRP:
101	dc.l $40000000,$c90fdaa2,$2168c235    ;pi
102
103*round to nearest
104SMALRN:
105	dc.l $3ffd0000,$9a209a84,$fbcff798    ;log10(2)
106	dc.l $40000000,$adf85458,$a2bb4a9a    ;e
107	dc.l $3fff0000,$b8aa3b29,$5c17f0bc    ;log2(e)
108	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
109	dc.l $00000000,$00000000,$00000000    ;0.0
110* round to zero;round to negative infinity
111SMALRZRM:
112	dc.l $3ffd0000,$9a209a84,$fbcff798    ;log10(2)
113	dc.l $40000000,$adf85458,$a2bb4a9a    ;e
114	dc.l $3fff0000,$b8aa3b29,$5c17f0bb    ;log2(e)
115	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
116	dc.l $00000000,$00000000,$00000000    ;0.0
117* round to positive infinity
118SMALRP:
119	dc.l $3ffd0000,$9a209a84,$fbcff799    ;log10(2)
120	dc.l $40000000,$adf85458,$a2bb4a9b    ;e
121	dc.l $3fff0000,$b8aa3b29,$5c17f0bc    ;log2(e)
122	dc.l $3ffd0000,$de5bd8a9,$37287195    ;log10(e)
123	dc.l $00000000,$00000000,$00000000    ;0.0
124
125*round to nearest
126BIGRN:
127	dc.l $3ffe0000,$b17217f7,$d1cf79ac    ;ln(2)
128	dc.l $40000000,$935d8ddd,$aaa8ac17    ;ln(10)
129	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
130
131	xdef	PTENRN
132PTENRN:
133	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
134	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
135	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
136	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
137	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
138	dc.l $40690000,$9DC5ADA8,$2B70B59E    ;10 ^ 32
139	dc.l $40D30000,$C2781F49,$FFCFA6D5    ;10 ^ 64
140	dc.l $41A80000,$93BA47C9,$80E98CE0    ;10 ^ 128
141	dc.l $43510000,$AA7EEBFB,$9DF9DE8E    ;10 ^ 256
142	dc.l $46A30000,$E319A0AE,$A60E91C7    ;10 ^ 512
143	dc.l $4D480000,$C9767586,$81750C17    ;10 ^ 1024
144	dc.l $5A920000,$9E8B3B5D,$C53D5DE5    ;10 ^ 2048
145	dc.l $75250000,$C4605202,$8A20979B    ;10 ^ 4096
146*round to minus infinity
147BIGRZRM:
148	dc.l $3ffe0000,$b17217f7,$d1cf79ab    ;ln(2)
149	dc.l $40000000,$935d8ddd,$aaa8ac16    ;ln(10)
150	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
151
152	xdef	PTENRM
153PTENRM:
154	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
155	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
156	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
157	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
158	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
159	dc.l $40690000,$9DC5ADA8,$2B70B59D    ;10 ^ 32
160	dc.l $40D30000,$C2781F49,$FFCFA6D5    ;10 ^ 64
161	dc.l $41A80000,$93BA47C9,$80E98CDF    ;10 ^ 128
162	dc.l $43510000,$AA7EEBFB,$9DF9DE8D    ;10 ^ 256
163	dc.l $46A30000,$E319A0AE,$A60E91C6    ;10 ^ 512
164	dc.l $4D480000,$C9767586,$81750C17    ;10 ^ 1024
165	dc.l $5A920000,$9E8B3B5D,$C53D5DE5    ;10 ^ 2048
166	dc.l $75250000,$C4605202,$8A20979A    ;10 ^ 4096
167*round to positive infinity
168BIGRP:
169	dc.l $3ffe0000,$b17217f7,$d1cf79ac    ;ln(2)
170	dc.l $40000000,$935d8ddd,$aaa8ac17    ;ln(10)
171	dc.l $3fff0000,$80000000,$00000000    ;10 ^ 0
172
173	xdef	PTENRP
174PTENRP:
175	dc.l $40020000,$A0000000,$00000000    ;10 ^ 1
176	dc.l $40050000,$C8000000,$00000000    ;10 ^ 2
177	dc.l $400C0000,$9C400000,$00000000    ;10 ^ 4
178	dc.l $40190000,$BEBC2000,$00000000    ;10 ^ 8
179	dc.l $40340000,$8E1BC9BF,$04000000    ;10 ^ 16
180	dc.l $40690000,$9DC5ADA8,$2B70B59E    ;10 ^ 32
181	dc.l $40D30000,$C2781F49,$FFCFA6D6    ;10 ^ 64
182	dc.l $41A80000,$93BA47C9,$80E98CE0    ;10 ^ 128
183	dc.l $43510000,$AA7EEBFB,$9DF9DE8E    ;10 ^ 256
184	dc.l $46A30000,$E319A0AE,$A60E91C7    ;10 ^ 512
185	dc.l $4D480000,$C9767586,$81750C18    ;10 ^ 1024
186	dc.l $5A920000,$9E8B3B5D,$C53D5DE6    ;10 ^ 2048
187	dc.l $75250000,$C4605202,$8A20979B    ;10 ^ 4096
188
189	xref	nrm_zero
190	xref	decbin
191	xref	round
192
193	xdef    get_op
194	xdef    uns_getop
195	xdef    uni_getop
196get_op:
197	clr.b	DY_MO_FLG(a6)
198	tst.b	UFLG_TMP(a6)	;test flag for unsupp/unimp state
199	beq.b	uni_getop
200
201uns_getop:
202	btst.b	#direction_bit,CMDREG1B(a6)
203	bne.w	opclass3	;branch if a fmove out (any kind)
204	btst.b	#6,CMDREG1B(a6)
205	beq.b	uns_notpacked
206
207	bfextu	CMDREG1B(a6){3:3},d0
208	cmp.b	#3,d0
209	beq.w	pack_source	;check for a packed src op, branch if so
210uns_notpacked:
211	bsr	chk_dy_mo	;set the dyadic/monadic flag
212	tst.b	DY_MO_FLG(a6)
213	beq.b	src_op_ck	;if monadic, go check src op
214*				;else, check dst op (fall through)
215
216	btst.b	#7,DTAG(a6)
217	beq.b	src_op_ck	;if dst op is norm, check src op
218	bra.b	dst_ex_dnrm	;else, handle destination unnorm/dnrm
219
220uni_getop:
221	bfextu	CMDREG1B(a6){0:6},d0 ;get opclass and src fields
222	cmpi.l	#$17,d0		;if op class and size fields are $17,
223*				;it is FMOVECR; if not, continue
224*
225* If the instruction is fmovecr, exit get_op.  It is handled
226* in do_func and smovecr.sa.
227*
228	bne.w	not_fmovecr	;handle fmovecr as an unimplemented inst
229	rts
230
231not_fmovecr:
232	btst.b	#E1,E_BYTE(a6)	;if set, there is a packed operand
233	bne.w	pack_source	;check for packed src op, branch if so
234
235* The following lines of are coded to optimize on normalized operands
236	move.b	STAG(a6),d0
237	or.b	DTAG(a6),d0	;check if either of STAG/DTAG msb set
238	bmi.b	dest_op_ck	;if so, some op needs to be fixed
239	rts
240
241dest_op_ck:
242	btst.b	#7,DTAG(a6)	;check for unsupported data types in
243	beq.b	src_op_ck	;the destination, if not, check src op
244	bsr	chk_dy_mo	;set dyadic/monadic flag
245	tst.b	DY_MO_FLG(a6)	;
246	beq.b	src_op_ck	;if monadic, check src op
247*
248* At this point, destination has an extended denorm or unnorm.
249*
250dst_ex_dnrm:
251	move.w	FPTEMP_EX(a6),d0 ;get destination exponent
252	andi.w	#$7fff,d0	;mask sign, check if exp = 0000
253	beq.b	src_op_ck	;if denorm then check source op.
254*				;denorms are taken care of in res_func
255*				;(unsupp) or do_func (unimp)
256*				;else unnorm fall through
257	lea.l	FPTEMP(a6),a0	;point a0 to dop - used in mk_norm
258	bsr	mk_norm		;go normalize - mk_norm returns:
259*				;L_SCR1{7:5} = operand tag
260*				;	(000 = norm, 100 = denorm)
261*				;L_SCR1{4} = fpte15 or ete15
262*				;	0 = exp >  $3fff
263*				;	1 = exp <= $3fff
264*				;and puts the normalized num back
265*				;on the fsave stack
266*
267	move.b L_SCR1(a6),DTAG(a6) ;write the new tag & fpte15
268*				;to the fsave stack and fall
269*				;through to check source operand
270*
271src_op_ck:
272	btst.b	#7,STAG(a6)
273	beq.w	end_getop	;check for unsupported data types on the
274*				;source operand
275	btst.b	#5,STAG(a6)
276	bne.b	src_sd_dnrm	;if bit 5 set, handle sgl/dbl denorms
277*
278* At this point only unnorms or extended denorms are possible.
279*
280src_ex_dnrm:
281	move.w	ETEMP_EX(a6),d0 ;get source exponent
282	andi.w	#$7fff,d0	;mask sign, check if exp = 0000
283	beq.w	end_getop	;if denorm then exit, denorms are
284*				;handled in do_func
285	lea.l	ETEMP(a6),a0	;point a0 to sop - used in mk_norm
286	bsr	mk_norm		;go normalize - mk_norm returns:
287*				;L_SCR1{7:5} = operand tag
288*				;	(000 = norm, 100 = denorm)
289*				;L_SCR1{4} = fpte15 or ete15
290*				;	0 = exp >  $3fff
291*				;	1 = exp <= $3fff
292*				;and puts the normalized num back
293*				;on the fsave stack
294*
295	move.b	L_SCR1(a6),STAG(a6) ;write the new tag & ete15
296	rts			;end_getop
297
298*
299* At this point, only single or double denorms are possible.
300* If the inst is not fmove, normalize the source.  If it is,
301* do nothing to the input.
302*
303src_sd_dnrm:
304	btst.b	#4,CMDREG1B(a6)	;differentiate between sgl/dbl denorm
305	bne.b	is_double
306is_single:
307	move.w	#$3f81,d1	;write bias for sgl denorm
308	bra.b	common		;goto the common code
309is_double:
310	move.w	#$3c01,d1	;write the bias for a dbl denorm
311common:
312	btst.b	#sign_bit,ETEMP_EX(a6) ;grab sign bit of mantissa
313	beq.b	pos
314	bset	#15,d1		;set sign bit because it is negative
315pos:
316	move.w	d1,ETEMP_EX(a6)
317*				;put exponent on stack
318
319	move.w	CMDREG1B(a6),d1
320	and.w	#$e3ff,d1	;clear out source specifier
321	or.w	#$0800,d1	;set source specifier to extended prec
322	move.w	d1,CMDREG1B(a6)	;write back to the command word in stack
323*				;this is needed to fix unsupp data stack
324	lea.l	ETEMP(a6),a0	;point a0 to sop
325
326	bsr	mk_norm		;convert sgl/dbl denorm to norm
327	move.b	L_SCR1(a6),STAG(a6) ;put tag into source tag reg - d0
328	rts			;end_getop
329*
330* At this point, the source is definitely packed, whether
331* instruction is dyadic or monadic is still unknown
332*
333pack_source:
334	move.l	FPTEMP_LO(a6),ETEMP(a6)	;write ms part of packed
335*				;number to etemp slot
336	bsr	chk_dy_mo	;set dyadic/monadic flag
337	bsr	unpack
338
339	tst.b	DY_MO_FLG(a6)
340	beq.b	end_getop	;if monadic, exit
341*				;else, fix FPTEMP
342pack_dya:
343	bfextu	CMDREG1B(a6){6:3},d0 ;extract dest fp reg
344	move.l	#7,d1
345	sub.l	d0,d1
346	clr.l	d0
347	bset.l	d1,d0		;set up d0 as a dynamic register mask
348	fmovem.x d0,FPTEMP(a6)	;write to FPTEMP
349
350	btst.b	#7,DTAG(a6)	;check dest tag for unnorm or denorm
351	bne.w	dst_ex_dnrm	;else, handle the unnorm or ext denorm
352*
353* Dest is not denormalized.  Check for norm, and set fpte15
354* accordingly.
355*
356	move.b	DTAG(a6),d0
357	andi.b	#$f0,d0		;strip to only dtag:fpte15
358	tst.b	d0		;check for normalized value
359	bne.b	end_getop	;if inf/nan/zero leave get_op
360	move.w	FPTEMP_EX(a6),d0
361	andi.w	#$7fff,d0
362	cmpi.w	#$3fff,d0	;check if fpte15 needs setting
363	bge.b	end_getop	;if >= $3fff, leave fpte15=0
364	or.b	#$10,DTAG(a6)
365	bra.b	end_getop
366
367*
368* At this point, it is either an fmoveout packed, unnorm or denorm
369*
370opclass3:
371	clr.b	DY_MO_FLG(a6)	;set dyadic/monadic flag to monadic
372	bfextu	CMDREG1B(a6){4:2},d0
373	cmpi.b	#3,d0
374	bne.w	src_ex_dnrm	;if not equal, must be unnorm or denorm
375*				;else it is a packed move out
376*				;exit
377end_getop:
378	rts
379
380*
381* Sets the DY_MO_FLG correctly. This is used only on if it is an
382* unuspported data type exception.  Set if dyadic.
383*
384chk_dy_mo:
385	move.w	CMDREG1B(a6),d0
386	btst.l	#5,d0		;testing extension command word
387	beq.b	set_mon		;if bit 5 = 0 then monadic
388	btst.l	#4,d0		;know that bit 5 = 1
389	beq.b	set_dya		;if bit 4 = 0 then dyadic
390	andi.w	#$007f,d0	;get rid of all but extension bits {6:0}
391	cmpi.w 	#$0038,d0	;if extension = $38 then fcmp (dyadic)
392	bne.b	set_mon
393set_dya:
394	st.b	DY_MO_FLG(a6)	;set the inst flag type to dyadic
395	rts
396set_mon:
397	clr.b	DY_MO_FLG(a6)	;set the inst flag type to monadic
398	rts
399*
400*	MK_NORM
401*
402* Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
403* exception if denorm.
404*
405* CASE opclass 0x0 unsupp
406*	mk_norm till msb set
407*	set tag = norm
408*
409* CASE opclass 0x0 unimp
410*	mk_norm till msb set or exp = 0
411*	if integer bit = 0
412*	   tag = denorm
413*	else
414*	   tag = norm
415*
416* CASE opclass 011 unsupp
417*	mk_norm till msb set or exp = 0
418*	if integer bit = 0
419*	   tag = denorm
420*	   set unfl_nmcexe = 1
421*	else
422*	   tag = norm
423*
424* if exp <= $3fff
425*   set ete15 or fpte15 = 1
426* else set ete15 or fpte15 = 0
427
428* input:
429*	a0 = points to operand to be normalized
430* output:
431*	L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
432*	L_SCR1{4}   = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
433*	the normalized operand is placed back on the fsave stack
434mk_norm:
435	clr.l	L_SCR1(a6)
436	bclr.b	#sign_bit,LOCAL_EX(a0)
437	sne	LOCAL_SGN(a0)	;transform into internal extended format
438
439	cmpi.b	#$2c,1+EXC_VEC(a6) ;check if unimp
440	bne.b	uns_data	;branch if unsupp
441	bsr	uni_inst	;call if unimp (opclass 0x0)
442	bra.b	reload
443uns_data:
444	btst.b	#direction_bit,CMDREG1B(a6) ;check transfer direction
445	bne.b	bit_set		;branch if set (opclass 011)
446	bsr	uns_opx		;call if opclass 0x0
447	bra.b	reload
448bit_set:
449	bsr	uns_op3		;opclass 011
450reload:
451	cmp.w	#$3fff,LOCAL_EX(a0) ;if exp > $3fff
452	bgt.b	end_mk		;   fpte15/ete15 already set to 0
453	bset.b	#4,L_SCR1(a6)	;else set fpte15/ete15 to 1
454*				;calling routine actually sets the
455*				;value on the stack (along with the
456*				;tag), since this routine doesn't
457*				;know if it should set ete15 or fpte15
458*				;ie, it doesn't know if this is the
459*				;src op or dest op.
460end_mk:
461	bfclr	LOCAL_SGN(a0){0:8}
462	beq.b	end_mk_pos
463	bset.b	#sign_bit,LOCAL_EX(a0) ;convert back to IEEE format
464end_mk_pos:
465	rts
466*
467*     CASE opclass 011 unsupp
468*
469uns_op3:
470	bsr	nrm_zero	;normalize till msb = 1 or exp = zero
471	btst.b	#7,LOCAL_HI(a0)	;if msb = 1
472	bne.b	no_unfl		;then branch
473set_unfl:
474	or.b	#dnrm_tag,L_SCR1(a6) ;set denorm tag
475	bset.b	#unfl_bit,FPSR_EXCEPT(a6) ;set unfl exception bit
476no_unfl:
477	rts
478*
479*     CASE opclass 0x0 unsupp
480*
481uns_opx:
482	bsr	nrm_zero	;normalize the number
483	btst.b	#7,LOCAL_HI(a0)	;check if integer bit (j-bit) is set
484	beq.b	uns_den		;if clear then now have a denorm
485uns_nrm:
486	or.b	#norm_tag,L_SCR1(a6) ;set tag to norm
487	rts
488uns_den:
489	or.b	#dnrm_tag,L_SCR1(a6) ;set tag to denorm
490	rts
491*
492*     CASE opclass 0x0 unimp
493*
494uni_inst:
495	bsr	nrm_zero
496	btst.b	#7,LOCAL_HI(a0)	;check if integer bit (j-bit) is set
497	beq.b	uni_den		;if clear then now have a denorm
498uni_nrm:
499	or.b	#norm_tag,L_SCR1(a6) ;set tag to norm
500	rts
501uni_den:
502	or.b	#dnrm_tag,L_SCR1(a6) ;set tag to denorm
503	rts
504
505*
506*	Decimal to binary conversion
507*
508* Special cases of inf and NaNs are completed outside of decbin.
509* If the input is an snan, the snan bit is not set.
510*
511* input:
512*	ETEMP(a6)	- points to packed decimal string in memory
513* output:
514*	fp0	- contains packed string converted to extended precision
515*	ETEMP	- same as fp0
516unpack:
517	move.w	CMDREG1B(a6),d0	;examine command word, looking for fmove's
518	and.w	#$3b,d0
519	beq	move_unpack	;special handling for fmove: must set FPSR_CC
520
521	move.w	ETEMP(a6),d0	;get word with inf information
522	bfextu	d0{20:12},d1	;get exponent into d1
523	cmpi.w	#$0fff,d1	;test for inf or NaN
524	bne.b	try_zero	;if not equal, it is not special
525	bfextu	d0{17:3},d1	;get SE and y bits into d1
526	cmpi.w	#7,d1		;SE and y bits must be on for special
527	bne.b	try_zero	;if not on, it is not special
528*input is of the special cases of inf and NaN
529	tst.l	ETEMP_HI(a6)	;check ms mantissa
530	bne.b	fix_nan		;if non-zero, it is a NaN
531	tst.l	ETEMP_LO(a6)	;check ls mantissa
532	bne.b	fix_nan		;if non-zero, it is a NaN
533	bra.w	finish		;special already on stack
534fix_nan:
535	btst.b	#signan_bit,ETEMP_HI(a6) ;test for snan
536	bne.w	finish
537	or.l	#snaniop_mask,USER_FPSR(a6) ;always set snan if it is so
538	bra.w	finish
539try_zero:
540	move.w	ETEMP_EX+2(a6),d0 ;get word 4
541	andi.w	#$000f,d0	;clear all but last ni(y)bble
542	tst.w	d0		;check for zero.
543	bne.w	not_spec
544	tst.l	ETEMP_HI(a6)	;check words 3 and 2
545	bne.w	not_spec
546	tst.l	ETEMP_LO(a6)	;check words 1 and 0
547	bne.w	not_spec
548	tst.l	ETEMP(a6)	;test sign of the zero
549	bge.b	pos_zero
550	move.l	#$80000000,ETEMP(a6) ;write neg zero to etemp
551	clr.l	ETEMP_HI(a6)
552	clr.l	ETEMP_LO(a6)
553	bra.w	finish
554pos_zero:
555	clr.l	ETEMP(a6)
556	clr.l	ETEMP_HI(a6)
557	clr.l	ETEMP_LO(a6)
558	bra.w	finish
559
560not_spec:
561	fmovem.x fp0-fp1,-(a7)	;save fp0 - decbin returns in it
562	bsr	decbin
563	fmove.x fp0,ETEMP(a6)	;put the unpacked sop in the fsave stack
564	fmovem.x (a7)+,fp0-fp1
565	fmove.l	#0,FPSR		;clr fpsr from decbin
566	bra	finish
567
568*
569* Special handling for packed move in:  Same results as all other
570* packed cases, but we must set the FPSR condition codes properly.
571*
572move_unpack:
573	move.w	ETEMP(a6),d0	;get word with inf information
574	bfextu	d0{20:12},d1	;get exponent into d1
575	cmpi.w	#$0fff,d1	;test for inf or NaN
576	bne.b	mtry_zero	;if not equal, it is not special
577	bfextu	d0{17:3},d1	;get SE and y bits into d1
578	cmpi.w	#7,d1		;SE and y bits must be on for special
579	bne.b	mtry_zero	;if not on, it is not special
580*input is of the special cases of inf and NaN
581	tst.l	ETEMP_HI(a6)	;check ms mantissa
582	bne.b	mfix_nan		;if non-zero, it is a NaN
583	tst.l	ETEMP_LO(a6)	;check ls mantissa
584	bne.b	mfix_nan		;if non-zero, it is a NaN
585*input is inf
586	or.l	#inf_mask,USER_FPSR(a6) ;set I bit
587	tst.l	ETEMP(a6)	;check sign
588	bge.w	finish
589	or.l	#neg_mask,USER_FPSR(a6) ;set N bit
590	bra.w	finish		;special already on stack
591mfix_nan:
592	or.l	#nan_mask,USER_FPSR(a6) ;set NaN bit
593	move.b	#nan_tag,STAG(a6)	;set stag to NaN
594	btst.b	#signan_bit,ETEMP_HI(a6) ;test for snan
595	bne.b	mn_snan
596	or.l	#snaniop_mask,USER_FPSR(a6) ;set snan bit
597	btst.b	#snan_bit,FPCR_ENABLE(a6) ;test for snan enabled
598	bne.b	mn_snan
599	bset.b	#signan_bit,ETEMP_HI(a6) ;force snans to qnans
600mn_snan:
601	tst.l	ETEMP(a6)	;check for sign
602	bge.w	finish		;if clr, go on
603	or.l	#neg_mask,USER_FPSR(a6) ;set N bit
604	bra.w	finish
605
606mtry_zero:
607	move.w	ETEMP_EX+2(a6),d0 ;get word 4
608	andi.w	#$000f,d0	;clear all but last ni(y)bble
609	tst.w	d0		;check for zero.
610	bne.b	mnot_spec
611	tst.l	ETEMP_HI(a6)	;check words 3 and 2
612	bne.b	mnot_spec
613	tst.l	ETEMP_LO(a6)	;check words 1 and 0
614	bne.b	mnot_spec
615	tst.l	ETEMP(a6)	;test sign of the zero
616	bge.b	mpos_zero
617	or.l	#neg_mask+z_mask,USER_FPSR(a6) ;set N and Z
618	move.l	#$80000000,ETEMP(a6) ;write neg zero to etemp
619	clr.l	ETEMP_HI(a6)
620	clr.l	ETEMP_LO(a6)
621	bra.b	finish
622mpos_zero:
623	or.l	#z_mask,USER_FPSR(a6) ;set Z
624	clr.l	ETEMP(a6)
625	clr.l	ETEMP_HI(a6)
626	clr.l	ETEMP_LO(a6)
627	bra.b	finish
628
629mnot_spec:
630	fmovem.x fp0-fp1,-(a7)	;save fp0 ,fp1 - decbin returns in fp0
631	bsr	decbin
632	fmove.x fp0,ETEMP(a6)
633*				;put the unpacked sop in the fsave stack
634	fmovem.x (a7)+,fp0-fp1
635
636finish:
637	move.w	CMDREG1B(a6),d0	;get the command word
638	and.w	#$fbff,d0	;change the source specifier field to
639*				;extended (was packed).
640	move.w	d0,CMDREG1B(a6)	;write command word back to fsave stack
641*				;we need to do this so the 040 will
642*				;re-execute the inst. without taking
643*				;another packed trap.
644
645fix_stag:
646*Converted result is now in etemp on fsave stack, now set the source
647*tag (stag)
648*	if (ete =$7fff) then INF or NAN
649*		if (etemp = $x.0----0) then
650*			stag = INF
651*		else
652*			stag = NAN
653*	else
654*		if (ete = $0000) then
655*			stag = ZERO
656*		else
657*			stag = NORM
658*
659* Note also that the etemp_15 bit (just right of the stag) must
660* be set accordingly.
661*
662	move.w		ETEMP_EX(a6),d1
663	andi.w		#$7fff,d1   ;strip sign
664	cmp.w  		#$7fff,d1
665	bne.b  		z_or_nrm
666	move.l		ETEMP_HI(a6),d1
667	bne.b		is_nan
668	move.l		ETEMP_LO(a6),d1
669	bne.b		is_nan
670is_inf:
671	move.b		#$40,STAG(a6)
672	move.l		#$40,d0
673	rts
674is_nan:
675	move.b		#$60,STAG(a6)
676	move.l		#$60,d0
677	rts
678z_or_nrm:
679	tst.w		d1
680	bne.b		is_nrm
681is_zro:
682* For a zero, set etemp_15
683	move.b		#$30,STAG(a6)
684	move.l		#$20,d0
685	rts
686is_nrm:
687* For a norm, check if the exp <= $3fff; if so, set etemp_15
688	cmpi.w		#$3fff,d1
689	ble.b		set_bit15
690	clr.b		STAG(a6)
691	bra.b		end_is_nrm
692set_bit15:
693	move.b		#$10,STAG(a6)
694end_is_nrm:
695	clr.l		d0
696end_fix:
697	rts
698
699end_get:
700	rts
701	end
702