2 | get_op.sa 3.6 5/19/92
4 | get_op.sa 3.5 4/26/91
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.
13 | For UNSUPPORTED data/format (exception vector 55) and for
14 | UNIMPLEMENTED instructions (exception vector 11) the following
17 | - For unnormalized numbers (opclass 0, 2, or 3) the
18 | number(s) is normalized and the operand type tag is updated.
20 | - For a packed number (opclass 2) the number is unpacked and the
21 | operand type tag is updated.
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.
27 | For UNSUPPORTED data/format (exception vector 55) only the
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.
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
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.
54 | Copyright (C) Motorola, Inc. 1990
57 | For details on the license for this file, please see the
58 | file, README, in this same directory.
60 GET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package
66 .global PIRN,PIRZRM,PIRP
67 .global SMALRN,SMALRZRM,SMALRP
68 .global BIGRN,BIGRZRM,BIGRP
71 .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
73 .long 0x40000000,0xc90fdaa2,0x2168c234 |pi
75 .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
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
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
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
101 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
102 .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
103 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
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
122 .long 0x3ffe0000,0xb17217f7,0xd1cf79ab |ln(2)
123 .long 0x40000000,0x935d8ddd,0xaaa8ac16 |ln(10)
124 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
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
143 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
144 .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
145 .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
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
172 tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
176 btstb #direction_bit,CMDREG1B(%a6)
177 bne opclass3 |branch if a fmove out (any kind)
178 btstb #6,CMDREG1B(%a6)
181 bfextu CMDREG1B(%a6){#3:#3},%d0
183 beq pack_source |check for a packed src op, branch if so
185 bsr chk_dy_mo |set the dyadic/monadic flag
187 beqs src_op_ck |if monadic, go check src op
188 | ;else, check dst op (fall through)
191 beqs src_op_ck |if dst op is norm, check src op
192 bras dst_ex_dnrm |else, handle destination unnorm/dnrm
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
199 | If the instruction is fmovecr, exit get_op. It is handled
200 | in do_func and smovecr.sa.
202 bne not_fmovecr |handle fmovecr as an unimplemented inst
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
209 | The following lines of are coded to optimize on normalized operands
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
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
222 | At this point, destination has an extended denorm or unnorm.
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
238 | ;and puts the normalized num back
239 | ;on the fsave stack
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
247 beq end_getop |check for unsupported data types on the
250 bnes src_sd_dnrm |if bit 5 set, handle sgl/dbl denorms
252 | At this point only unnorms or extended denorms are possible.
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
266 | ;and puts the normalized num back
267 | ;on the fsave stack
269 moveb L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
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.
278 btstb #4,CMDREG1B(%a6) |differentiate between sgl/dbl denorm
281 movew #0x3f81,%d1 |write bias for sgl denorm
282 bras common |goto the common code
284 movew #0x3c01,%d1 |write the bias for a dbl denorm
286 btstb #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
288 bset #15,%d1 |set sign bit because it is negative
290 movew %d1,ETEMP_EX(%a6)
291 | ;put exponent on stack
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
300 bsr mk_norm |convert sgl/dbl denorm to norm
301 moveb L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
304 | At this point, the source is definitely packed, whether
305 | instruction is dyadic or monadic is still unknown
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
314 beqs end_getop |if monadic, exit
317 bfextu CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
321 bsetl %d1,%d0 |set up d0 as a dynamic register mask
322 fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
324 btstb #7,DTAG(%a6) |check dest tag for unnorm or denorm
325 bne dst_ex_dnrm |else, handle the unnorm or ext denorm
327 | Dest is not denormalized. Check for norm, and set fpte15
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
336 cmpiw #0x3fff,%d0 |check if fpte15 needs setting
337 bges end_getop |if >= $3fff, leave fpte15=0
342 | At this point, it is either an fmoveout packed, unnorm or denorm
345 clrb DY_MO_FLG(%a6) |set dyadic/monadic flag to monadic
346 bfextu CMDREG1B(%a6){#4:#2},%d0
348 bne src_ex_dnrm |if not equal, must be unnorm or denorm
349 | ;else it is a packed move out
355 | Sets the DY_MO_FLG correctly. This is used only on if it is an
356 | unsupported data type exception. Set if dyadic.
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)
368 st DY_MO_FLG(%a6) |set the inst flag type to dyadic
371 clrb DY_MO_FLG(%a6) |set the inst flag type to monadic
376 | Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
377 | exception if denorm.
379 | CASE opclass 0x0 unsupp
380 | mk_norm till msb set
383 | CASE opclass 0x0 unimp
384 | mk_norm till msb set or exp = 0
390 | CASE opclass 011 unsupp
391 | mk_norm till msb set or exp = 0
394 | set unfl_nmcexe = 1
399 | set ete15 or fpte15 = 1
400 | else set ete15 or fpte15 = 0
403 | a0 = points to operand to be normalized
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
410 bclrb #sign_bit,LOCAL_EX(%a0)
411 sne LOCAL_SGN(%a0) |transform into internal extended format
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)
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
423 bsr uns_op3 |opclass 011
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.
435 bfclr LOCAL_SGN(%a0){#0:#8}
437 bsetb #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
441 | CASE opclass 011 unsupp
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
448 orw #dnrm_tag,L_SCR1(%a6) |set denorm tag
449 bsetb #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
453 | CASE opclass 0x0 unsupp
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
460 orb #norm_tag,L_SCR1(%a6) |set tag to norm
463 orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
466 | CASE opclass 0x0 unimp
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
473 orb #norm_tag,L_SCR1(%a6) |set tag to norm
476 orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
480 | Decimal to binary conversion
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.
486 | ETEMP(a6) - points to packed decimal string in memory
488 | fp0 - contains packed string converted to extended precision
489 | ETEMP - same as fp0
491 movew CMDREG1B(%a6),%d0 |examine command word, looking for fmove's
493 beq move_unpack |special handling for fmove: must set FPSR_CC
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
509 btstb #signan_bit,ETEMP_HI(%a6) |test for snan
511 orl #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
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.
518 tstl ETEMP_HI(%a6) |check words 3 and 2
520 tstl ETEMP_LO(%a6) |check words 1 and 0
522 tstl ETEMP(%a6) |test sign of the zero
524 movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
535 fmovemx %fp0-%fp1,-(%a7) |save fp0 - decbin returns in it
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
543 | Special handling for packed move in: Same results as all other
544 | packed cases, but we must set the FPSR condition codes properly.
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
560 orl #inf_mask,USER_FPSR(%a6) |set I bit
561 tstl ETEMP(%a6) |check sign
563 orl #neg_mask,USER_FPSR(%a6) |set N bit
564 bra finish |special already on stack
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
570 orl #snaniop_mask,USER_FPSR(%a6) |set snan bit
571 btstb #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
573 bsetb #signan_bit,ETEMP_HI(%a6) |force snans to qnans
575 tstl ETEMP(%a6) |check for sign
576 bge finish |if clr, go on
577 orl #neg_mask,USER_FPSR(%a6) |set N bit
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.
585 tstl ETEMP_HI(%a6) |check words 3 and 2
587 tstl ETEMP_LO(%a6) |check words 1 and 0
589 tstl ETEMP(%a6) |test sign of the zero
591 orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
592 movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
597 orl #z_mask,USER_FPSR(%a6) |set Z
604 fmovemx %fp0-%fp1,-(%a7) |save fp0 ,fp1 - decbin returns in fp0
606 fmovex %fp0,ETEMP(%a6)
607 | ;put the unpacked sop in the fsave stack
608 fmovemx (%a7)+,%fp0-%fp1
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.
620 |Converted result is now in etemp on fsave stack, now set the source
622 | if (ete =$7fff) then INF or NAN
623 | if (etemp = $x.0----0) then
628 | if (ete = $0000) then
633 | Note also that the etemp_15 bit (just right of the stag) must
634 | be set accordingly.
636 movew ETEMP_EX(%a6),%d1
637 andiw #0x7fff,%d1 |strip sign
640 movel ETEMP_HI(%a6),%d1
642 movel ETEMP_LO(%a6),%d1
645 moveb #0x40,STAG(%a6)
649 moveb #0x60,STAG(%a6)
656 | For a zero, set etemp_15
657 moveb #0x30,STAG(%a6)
661 | For a norm, check if the exp <= $3fff; if so, set etemp_15
667 moveb #0x10,STAG(%a6)