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