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 
60 GET_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 
70 PIRN:
71 	.long 0x40000000,0xc90fdaa2,0x2168c235    |pi
72 PIRZRM:
73 	.long 0x40000000,0xc90fdaa2,0x2168c234    |pi
74 PIRP:
75 	.long 0x40000000,0xc90fdaa2,0x2168c235    |pi
76 
77 |round to nearest
78 SMALRN:
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
85 SMALRZRM:
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
92 SMALRP:
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
100 BIGRN:
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
106 PTENRN:
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
121 BIGRZRM:
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
127 PTENRM:
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
142 BIGRP:
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
148 PTENRP:
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
170 get_op:
171 	clrb	DY_MO_FLG(%a6)
172 	tstb	UFLG_TMP(%a6)	|test flag for unsupp/unimp state
173 	beq	uni_getop
174 
175 uns_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
184 uns_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 
194 uni_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 
205 not_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 
215 dest_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 |
224 dst_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 |
245 src_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 |
254 src_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 |
277 src_sd_dnrm:
278 	btstb	#4,CMDREG1B(%a6)	|differentiate between sgl/dbl denorm
279 	bnes	is_double
280 is_single:
281 	movew	#0x3f81,%d1	|write bias for sgl denorm
282 	bras	common		|goto the common code
283 is_double:
284 	movew	#0x3c01,%d1	|write the bias for a dbl denorm
285 common:
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
289 pos:
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 |
307 pack_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
316 pack_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 |
344 opclass3:
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
351 end_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 |
358 chk_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
367 set_dya:
368 	st	DY_MO_FLG(%a6)	|set the inst flag type to dyadic
369 	rts
370 set_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
408 mk_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
417 uns_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
422 bit_set:
423 	bsr	uns_op3		|opclass 011
424 reload:
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.
434 end_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
438 end_mk_pos:
439 	rts
440 |
441 |     CASE opclass 011 unsupp
442 |
443 uns_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
447 set_unfl:
448 	orw	#dnrm_tag,L_SCR1(%a6) |set denorm tag
449 	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
450 no_unfl:
451 	rts
452 |
453 |     CASE opclass 0x0 unsupp
454 |
455 uns_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
459 uns_nrm:
460 	orb	#norm_tag,L_SCR1(%a6) |set tag to norm
461 	rts
462 uns_den:
463 	orb	#dnrm_tag,L_SCR1(%a6) |set tag to denorm
464 	rts
465 |
466 |     CASE opclass 0x0 unimp
467 |
468 uni_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
472 uni_nrm:
473 	orb	#norm_tag,L_SCR1(%a6) |set tag to norm
474 	rts
475 uni_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
490 unpack:
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
508 fix_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
513 try_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
528 pos_zero:
529 	clrl	ETEMP(%a6)
530 	clrl	ETEMP_HI(%a6)
531 	clrl	ETEMP_LO(%a6)
532 	bra	finish
533 
534 not_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 |
546 move_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
565 mfix_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
574 mn_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 
580 mtry_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
596 mpos_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 
603 mnot_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 
610 finish:
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 
619 fix_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
644 is_inf:
645 	moveb		#0x40,STAG(%a6)
646 	movel		#0x40,%d0
647 	rts
648 is_nan:
649 	moveb		#0x60,STAG(%a6)
650 	movel		#0x60,%d0
651 	rts
652 z_or_nrm:
653 	tstw		%d1
654 	bnes		is_nrm
655 is_zro:
656 | For a zero, set etemp_15
657 	moveb		#0x30,STAG(%a6)
658 	movel		#0x20,%d0
659 	rts
660 is_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
666 set_bit15:
667 	moveb		#0x10,STAG(%a6)
668 end_is_nrm:
669 	movel		#0,%d0
670 end_fix:
671 	rts
672 
673 end_get:
674 	rts
675 	|end
676