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