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