patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / m68k / fpsp040 / get_op.S
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
61 GET_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
71 PIRN:
72         .long 0x40000000,0xc90fdaa2,0x2168c235    |pi
73 PIRZRM:
74         .long 0x40000000,0xc90fdaa2,0x2168c234    |pi
75 PIRP:
76         .long 0x40000000,0xc90fdaa2,0x2168c235    |pi
77
78 |round to nearest
79 SMALRN:
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
86 SMALRZRM:
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
93 SMALRP:
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
101 BIGRN:
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
107 PTENRN:
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
122 BIGRZRM:
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
128 PTENRM:
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
143 BIGRP:
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
149 PTENRP:
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
171 get_op:
172         clrb    DY_MO_FLG(%a6)
173         tstb    UFLG_TMP(%a6)   |test flag for unsupp/unimp state
174         beq     uni_getop
175
176 uns_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
185 uns_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
195 uni_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
206 not_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
216 dest_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 |
225 dst_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 |
246 src_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 |
255 src_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 |
278 src_sd_dnrm:
279         btstb   #4,CMDREG1B(%a6)        |differentiate between sgl/dbl denorm
280         bnes    is_double
281 is_single:
282         movew   #0x3f81,%d1     |write bias for sgl denorm
283         bras    common          |goto the common code
284 is_double:
285         movew   #0x3c01,%d1     |write the bias for a dbl denorm
286 common:
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
290 pos:
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 |
308 pack_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
317 pack_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 |
345 opclass3:
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
352 end_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 |
359 chk_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
368 set_dya:
369         st      DY_MO_FLG(%a6)  |set the inst flag type to dyadic
370         rts
371 set_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
409 mk_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
418 uns_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
423 bit_set:
424         bsr     uns_op3         |opclass 011
425 reload:
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.
435 end_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
439 end_mk_pos:
440         rts
441 |
442 |     CASE opclass 011 unsupp
443 |
444 uns_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
448 set_unfl:
449         orw     #dnrm_tag,L_SCR1(%a6) |set denorm tag
450         bsetb   #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
451 no_unfl:
452         rts
453 |
454 |     CASE opclass 0x0 unsupp
455 |
456 uns_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
460 uns_nrm:
461         orb     #norm_tag,L_SCR1(%a6) |set tag to norm
462         rts
463 uns_den:
464         orb     #dnrm_tag,L_SCR1(%a6) |set tag to denorm
465         rts
466 |
467 |     CASE opclass 0x0 unimp
468 |
469 uni_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
473 uni_nrm:
474         orb     #norm_tag,L_SCR1(%a6) |set tag to norm
475         rts
476 uni_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
491 unpack:
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
509 fix_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
514 try_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
529 pos_zero:
530         clrl    ETEMP(%a6)
531         clrl    ETEMP_HI(%a6)
532         clrl    ETEMP_LO(%a6)
533         bra     finish
534
535 not_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 |
547 move_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
566 mfix_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
575 mn_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
581 mtry_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
597 mpos_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
604 mnot_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
611 finish:
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
620 fix_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
645 is_inf:
646         moveb           #0x40,STAG(%a6)
647         movel           #0x40,%d0
648         rts
649 is_nan:
650         moveb           #0x60,STAG(%a6)
651         movel           #0x60,%d0
652         rts
653 z_or_nrm:
654         tstw            %d1
655         bnes            is_nrm
656 is_zro:
657 | For a zero, set etemp_15
658         moveb           #0x30,STAG(%a6)
659         movel           #0x20,%d0
660         rts
661 is_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
667 set_bit15:
668         moveb           #0x10,STAG(%a6)
669 end_is_nrm:
670         movel           #0,%d0
671 end_fix:
672         rts
673
674 end_get:
675         rts
676         |end