File indexing completed on 2025-05-11 08:23:48
0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 // get_op.sa 3.6 5/19/92
0005 //
0006 // get_op.sa 3.5 4/26/91
0007 //
0008 // Description: This routine is called by the unsupported format/data
0009 // type exception handler ('unsupp' - vector 55) and the unimplemented
0010 // instruction exception handler ('unimp' - vector 11). 'get_op'
0011 // determines the opclass (0, 2, or 3) and branches to the
0012 // opclass handler routine. See 68881/2 User's Manual table 4-11
0013 // for a description of the opclasses.
0014 //
0015 // For UNSUPPORTED data/format (exception vector 55) and for
0016 // UNIMPLEMENTED instructions (exception vector 11) the following
0017 // applies:
0018 //
0019 // - For unnormalized numbers (opclass 0, 2, or 3) the
0020 // number(s) is normalized and the operand type tag is updated.
0021 //
0022 // - For a packed number (opclass 2) the number is unpacked and the
0023 // operand type tag is updated.
0024 //
0025 // - For denormalized numbers (opclass 0 or 2) the number(s) is not
0026 // changed but passed to the next module. The next module for
0027 // unimp is do_func, the next module for unsupp is res_func.
0028 //
0029 // For UNSUPPORTED data/format (exception vector 55) only the
0030 // following applies:
0031 //
0032 // - If there is a move out with a packed number (opclass 3) the
0033 // number is packed and written to user memory. For the other
0034 // opclasses the number(s) are written back to the fsave stack
0035 // and the instruction is then restored back into the '040. The
0036 // '040 is then able to complete the instruction.
0037 //
0038 // For example:
0039 // fadd.x fpm,fpn where the fpm contains an unnormalized number.
0040 // The '040 takes an unsupported data trap and gets to this
0041 // routine. The number is normalized, put back on the stack and
0042 // then an frestore is done to restore the instruction back into
0043 // the '040. The '040 then re-executes the fadd.x fpm,fpn with
0044 // a normalized number in the source and the instruction is
0045 // successful.
0046 //
0047 // Next consider if in the process of normalizing the un-
0048 // normalized number it becomes a denormalized number. The
0049 // routine which converts the unnorm to a norm (called mk_norm)
0050 // detects this and tags the number as a denorm. The routine
0051 // res_func sees the denorm tag and converts the denorm to a
0052 // norm. The instruction is then restored back into the '040
0053 // which re_executes the instruction.
0054 //
0055 //
0056 // Copyright (C) Motorola, Inc. 1990
0057 // All Rights Reserved
0058 //
0059 // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0060 // The copyright notice above does not evidence any
0061 // actual or intended publication of such source code.
0062
0063 GET_OP: //idnt 2,1 | Motorola 040 Floating Point Software Package
0064
0065 |section 8
0066
0067 #include "fpsp.defs"
0068
0069 .global PIRN,PIRZRM,PIRP
0070 .global SMALRN,SMALRZRM,SMALRP
0071 .global BIGRN,BIGRZRM,BIGRP
0072
0073 PIRN:
0074 .long 0x40000000,0xc90fdaa2,0x2168c235 //pi
0075 PIRZRM:
0076 .long 0x40000000,0xc90fdaa2,0x2168c234 //pi
0077 PIRP:
0078 .long 0x40000000,0xc90fdaa2,0x2168c235 //pi
0079
0080 //round to nearest
0081 SMALRN:
0082 .long 0x3ffd0000,0x9a209a84,0xfbcff798 //log10(2)
0083 .long 0x40000000,0xadf85458,0xa2bb4a9a //e
0084 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc //log2(e)
0085 .long 0x3ffd0000,0xde5bd8a9,0x37287195 //log10(e)
0086 .long 0x00000000,0x00000000,0x00000000 //0.0
0087 // round to zero;round to negative infinity
0088 SMALRZRM:
0089 .long 0x3ffd0000,0x9a209a84,0xfbcff798 //log10(2)
0090 .long 0x40000000,0xadf85458,0xa2bb4a9a //e
0091 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bb //log2(e)
0092 .long 0x3ffd0000,0xde5bd8a9,0x37287195 //log10(e)
0093 .long 0x00000000,0x00000000,0x00000000 //0.0
0094 // round to positive infinity
0095 SMALRP:
0096 .long 0x3ffd0000,0x9a209a84,0xfbcff799 //log10(2)
0097 .long 0x40000000,0xadf85458,0xa2bb4a9b //e
0098 .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc //log2(e)
0099 .long 0x3ffd0000,0xde5bd8a9,0x37287195 //log10(e)
0100 .long 0x00000000,0x00000000,0x00000000 //0.0
0101
0102 //round to nearest
0103 BIGRN:
0104 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac //ln(2)
0105 .long 0x40000000,0x935d8ddd,0xaaa8ac17 //ln(10)
0106 .long 0x3fff0000,0x80000000,0x00000000 //10 ^ 0
0107
0108 .global PTENRN
0109 PTENRN:
0110 .long 0x40020000,0xA0000000,0x00000000 //10 ^ 1
0111 .long 0x40050000,0xC8000000,0x00000000 //10 ^ 2
0112 .long 0x400C0000,0x9C400000,0x00000000 //10 ^ 4
0113 .long 0x40190000,0xBEBC2000,0x00000000 //10 ^ 8
0114 .long 0x40340000,0x8E1BC9BF,0x04000000 //10 ^ 16
0115 .long 0x40690000,0x9DC5ADA8,0x2B70B59E //10 ^ 32
0116 .long 0x40D30000,0xC2781F49,0xFFCFA6D5 //10 ^ 64
0117 .long 0x41A80000,0x93BA47C9,0x80E98CE0 //10 ^ 128
0118 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E //10 ^ 256
0119 .long 0x46A30000,0xE319A0AE,0xA60E91C7 //10 ^ 512
0120 .long 0x4D480000,0xC9767586,0x81750C17 //10 ^ 1024
0121 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 //10 ^ 2048
0122 .long 0x75250000,0xC4605202,0x8A20979B //10 ^ 4096
0123 //round to minus infinity
0124 BIGRZRM:
0125 .long 0x3ffe0000,0xb17217f7,0xd1cf79ab //ln(2)
0126 .long 0x40000000,0x935d8ddd,0xaaa8ac16 //ln(10)
0127 .long 0x3fff0000,0x80000000,0x00000000 //10 ^ 0
0128
0129 .global PTENRM
0130 PTENRM:
0131 .long 0x40020000,0xA0000000,0x00000000 //10 ^ 1
0132 .long 0x40050000,0xC8000000,0x00000000 //10 ^ 2
0133 .long 0x400C0000,0x9C400000,0x00000000 //10 ^ 4
0134 .long 0x40190000,0xBEBC2000,0x00000000 //10 ^ 8
0135 .long 0x40340000,0x8E1BC9BF,0x04000000 //10 ^ 16
0136 .long 0x40690000,0x9DC5ADA8,0x2B70B59D //10 ^ 32
0137 .long 0x40D30000,0xC2781F49,0xFFCFA6D5 //10 ^ 64
0138 .long 0x41A80000,0x93BA47C9,0x80E98CDF //10 ^ 128
0139 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8D //10 ^ 256
0140 .long 0x46A30000,0xE319A0AE,0xA60E91C6 //10 ^ 512
0141 .long 0x4D480000,0xC9767586,0x81750C17 //10 ^ 1024
0142 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 //10 ^ 2048
0143 .long 0x75250000,0xC4605202,0x8A20979A //10 ^ 4096
0144 //round to positive infinity
0145 BIGRP:
0146 .long 0x3ffe0000,0xb17217f7,0xd1cf79ac //ln(2)
0147 .long 0x40000000,0x935d8ddd,0xaaa8ac17 //ln(10)
0148 .long 0x3fff0000,0x80000000,0x00000000 //10 ^ 0
0149
0150 .global PTENRP
0151 PTENRP:
0152 .long 0x40020000,0xA0000000,0x00000000 //10 ^ 1
0153 .long 0x40050000,0xC8000000,0x00000000 //10 ^ 2
0154 .long 0x400C0000,0x9C400000,0x00000000 //10 ^ 4
0155 .long 0x40190000,0xBEBC2000,0x00000000 //10 ^ 8
0156 .long 0x40340000,0x8E1BC9BF,0x04000000 //10 ^ 16
0157 .long 0x40690000,0x9DC5ADA8,0x2B70B59E //10 ^ 32
0158 .long 0x40D30000,0xC2781F49,0xFFCFA6D6 //10 ^ 64
0159 .long 0x41A80000,0x93BA47C9,0x80E98CE0 //10 ^ 128
0160 .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E //10 ^ 256
0161 .long 0x46A30000,0xE319A0AE,0xA60E91C7 //10 ^ 512
0162 .long 0x4D480000,0xC9767586,0x81750C18 //10 ^ 1024
0163 .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6 //10 ^ 2048
0164 .long 0x75250000,0xC4605202,0x8A20979B //10 ^ 4096
0165
0166 |xref nrm_zero
0167 |xref decbin
0168 |xref round
0169
0170 .global get_op
0171 .global uns_getop
0172 .global uni_getop
0173 get_op:
0174 clrb DY_MO_FLG(%a6)
0175 tstb UFLG_TMP(%a6) //test flag for unsupp/unimp state
0176 beq uni_getop
0177
0178 uns_getop:
0179 btstb #direction_bit,CMDREG1B(%a6)
0180 bne opclass3 //branch if a fmove out (any kind)
0181 btstb #6,CMDREG1B(%a6)
0182 beqs uns_notpacked
0183
0184 bfextu CMDREG1B(%a6){#3:#3},%d0
0185 cmpb #3,%d0
0186 beq pack_source //check for a packed src op, branch if so
0187 uns_notpacked:
0188 bsr chk_dy_mo //set the dyadic/monadic flag
0189 tstb DY_MO_FLG(%a6)
0190 beqs src_op_ck //if monadic, go check src op
0191 // ;else, check dst op (fall through)
0192
0193 btstb #7,DTAG(%a6)
0194 beqs src_op_ck //if dst op is norm, check src op
0195 bras dst_ex_dnrm //else, handle destination unnorm/dnrm
0196
0197 uni_getop:
0198 bfextu CMDREG1B(%a6){#0:#6},%d0 //get opclass and src fields
0199 cmpil #0x17,%d0 //if op class and size fields are $17,
0200 // ;it is FMOVECR; if not, continue
0201 //
0202 // If the instruction is fmovecr, exit get_op. It is handled
0203 // in do_func and smovecr.sa.
0204 //
0205 bne not_fmovecr //handle fmovecr as an unimplemented inst
0206 rts
0207
0208 not_fmovecr:
0209 btstb #E1,E_BYTE(%a6) //if set, there is a packed operand
0210 bne pack_source //check for packed src op, branch if so
0211
0212 // The following lines of are coded to optimize on normalized operands
0213 moveb STAG(%a6),%d0
0214 orb DTAG(%a6),%d0 //check if either of STAG/DTAG msb set
0215 bmis dest_op_ck //if so, some op needs to be fixed
0216 rts
0217
0218 dest_op_ck:
0219 btstb #7,DTAG(%a6) //check for unsupported data types in
0220 beqs src_op_ck //the destination, if not, check src op
0221 bsr chk_dy_mo //set dyadic/monadic flag
0222 tstb DY_MO_FLG(%a6) //
0223 beqs src_op_ck //if monadic, check src op
0224 //
0225 // At this point, destination has an extended denorm or unnorm.
0226 //
0227 dst_ex_dnrm:
0228 movew FPTEMP_EX(%a6),%d0 //get destination exponent
0229 andiw #0x7fff,%d0 //mask sign, check if exp = 0000
0230 beqs src_op_ck //if denorm then check source op.
0231 // ;denorms are taken care of in res_func
0232 // ;(unsupp) or do_func (unimp)
0233 // ;else unnorm fall through
0234 leal FPTEMP(%a6),%a0 //point a0 to dop - used in mk_norm
0235 bsr mk_norm //go normalize - mk_norm returns:
0236 // ;L_SCR1{7:5} = operand tag
0237 // ; (000 = norm, 100 = denorm)
0238 // ;L_SCR1{4} = fpte15 or ete15
0239 // ; 0 = exp > $3fff
0240 // ; 1 = exp <= $3fff
0241 // ;and puts the normalized num back
0242 // ;on the fsave stack
0243 //
0244 moveb L_SCR1(%a6),DTAG(%a6) //write the new tag & fpte15
0245 // ;to the fsave stack and fall
0246 // ;through to check source operand
0247 //
0248 src_op_ck:
0249 btstb #7,STAG(%a6)
0250 beq end_getop //check for unsupported data types on the
0251 // ;source operand
0252 btstb #5,STAG(%a6)
0253 bnes src_sd_dnrm //if bit 5 set, handle sgl/dbl denorms
0254 //
0255 // At this point only unnorms or extended denorms are possible.
0256 //
0257 src_ex_dnrm:
0258 movew ETEMP_EX(%a6),%d0 //get source exponent
0259 andiw #0x7fff,%d0 //mask sign, check if exp = 0000
0260 beq end_getop //if denorm then exit, denorms are
0261 // ;handled in do_func
0262 leal ETEMP(%a6),%a0 //point a0 to sop - used in mk_norm
0263 bsr mk_norm //go normalize - mk_norm returns:
0264 // ;L_SCR1{7:5} = operand tag
0265 // ; (000 = norm, 100 = denorm)
0266 // ;L_SCR1{4} = fpte15 or ete15
0267 // ; 0 = exp > $3fff
0268 // ; 1 = exp <= $3fff
0269 // ;and puts the normalized num back
0270 // ;on the fsave stack
0271 //
0272 moveb L_SCR1(%a6),STAG(%a6) //write the new tag & ete15
0273 rts //end_getop
0274
0275 //
0276 // At this point, only single or double denorms are possible.
0277 // If the inst is not fmove, normalize the source. If it is,
0278 // do nothing to the input.
0279 //
0280 src_sd_dnrm:
0281 btstb #4,CMDREG1B(%a6) //differentiate between sgl/dbl denorm
0282 bnes is_double
0283 is_single:
0284 movew #0x3f81,%d1 //write bias for sgl denorm
0285 bras common //goto the common code
0286 is_double:
0287 movew #0x3c01,%d1 //write the bias for a dbl denorm
0288 common:
0289 btstb #sign_bit,ETEMP_EX(%a6) //grab sign bit of mantissa
0290 beqs pos
0291 bset #15,%d1 //set sign bit because it is negative
0292 pos:
0293 movew %d1,ETEMP_EX(%a6)
0294 // ;put exponent on stack
0295
0296 movew CMDREG1B(%a6),%d1
0297 andw #0xe3ff,%d1 //clear out source specifier
0298 orw #0x0800,%d1 //set source specifier to extended prec
0299 movew %d1,CMDREG1B(%a6) //write back to the command word in stack
0300 // ;this is needed to fix unsupp data stack
0301 leal ETEMP(%a6),%a0 //point a0 to sop
0302
0303 bsr mk_norm //convert sgl/dbl denorm to norm
0304 moveb L_SCR1(%a6),STAG(%a6) //put tag into source tag reg - d0
0305 rts //end_getop
0306 //
0307 // At this point, the source is definitely packed, whether
0308 // instruction is dyadic or monadic is still unknown
0309 //
0310 pack_source:
0311 movel FPTEMP_LO(%a6),ETEMP(%a6) //write ms part of packed
0312 // ;number to etemp slot
0313 bsr chk_dy_mo //set dyadic/monadic flag
0314 bsr unpack
0315
0316 tstb DY_MO_FLG(%a6)
0317 beqs end_getop //if monadic, exit
0318 // ;else, fix FPTEMP
0319 pack_dya:
0320 bfextu CMDREG1B(%a6){#6:#3},%d0 //extract dest fp reg
0321 movel #7,%d1
0322 subl %d0,%d1
0323 clrl %d0
0324 bsetl %d1,%d0 //set up d0 as a dynamic register mask
0325 fmovemx %d0,FPTEMP(%a6) //write to FPTEMP
0326
0327 btstb #7,DTAG(%a6) //check dest tag for unnorm or denorm
0328 bne dst_ex_dnrm //else, handle the unnorm or ext denorm
0329 //
0330 // Dest is not denormalized. Check for norm, and set fpte15
0331 // accordingly.
0332 //
0333 moveb DTAG(%a6),%d0
0334 andib #0xf0,%d0 //strip to only dtag:fpte15
0335 tstb %d0 //check for normalized value
0336 bnes end_getop //if inf/nan/zero leave get_op
0337 movew FPTEMP_EX(%a6),%d0
0338 andiw #0x7fff,%d0
0339 cmpiw #0x3fff,%d0 //check if fpte15 needs setting
0340 bges end_getop //if >= $3fff, leave fpte15=0
0341 orb #0x10,DTAG(%a6)
0342 bras end_getop
0343
0344 //
0345 // At this point, it is either an fmoveout packed, unnorm or denorm
0346 //
0347 opclass3:
0348 clrb DY_MO_FLG(%a6) //set dyadic/monadic flag to monadic
0349 bfextu CMDREG1B(%a6){#4:#2},%d0
0350 cmpib #3,%d0
0351 bne src_ex_dnrm //if not equal, must be unnorm or denorm
0352 // ;else it is a packed move out
0353 // ;exit
0354 end_getop:
0355 rts
0356
0357 //
0358 // Sets the DY_MO_FLG correctly. This is used only on if it is an
0359 // unsupported data type exception. Set if dyadic.
0360 //
0361 chk_dy_mo:
0362 movew CMDREG1B(%a6),%d0
0363 btstl #5,%d0 //testing extension command word
0364 beqs set_mon //if bit 5 = 0 then monadic
0365 btstl #4,%d0 //know that bit 5 = 1
0366 beqs set_dya //if bit 4 = 0 then dyadic
0367 andiw #0x007f,%d0 //get rid of all but extension bits {6:0}
0368 cmpiw #0x0038,%d0 //if extension = $38 then fcmp (dyadic)
0369 bnes set_mon
0370 set_dya:
0371 st DY_MO_FLG(%a6) //set the inst flag type to dyadic
0372 rts
0373 set_mon:
0374 clrb DY_MO_FLG(%a6) //set the inst flag type to monadic
0375 rts
0376 //
0377 // MK_NORM
0378 //
0379 // Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
0380 // exception if denorm.
0381 //
0382 // CASE opclass 0x0 unsupp
0383 // mk_norm till msb set
0384 // set tag = norm
0385 //
0386 // CASE opclass 0x0 unimp
0387 // mk_norm till msb set or exp = 0
0388 // if integer bit = 0
0389 // tag = denorm
0390 // else
0391 // tag = norm
0392 //
0393 // CASE opclass 011 unsupp
0394 // mk_norm till msb set or exp = 0
0395 // if integer bit = 0
0396 // tag = denorm
0397 // set unfl_nmcexe = 1
0398 // else
0399 // tag = norm
0400 //
0401 // if exp <= $3fff
0402 // set ete15 or fpte15 = 1
0403 // else set ete15 or fpte15 = 0
0404
0405 // input:
0406 // a0 = points to operand to be normalized
0407 // output:
0408 // L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
0409 // L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
0410 // the normalized operand is placed back on the fsave stack
0411 mk_norm:
0412 clrl L_SCR1(%a6)
0413 bclrb #sign_bit,LOCAL_EX(%a0)
0414 sne LOCAL_SGN(%a0) //transform into internal extended format
0415
0416 cmpib #0x2c,1+EXC_VEC(%a6) //check if unimp
0417 bnes uns_data //branch if unsupp
0418 bsr uni_inst //call if unimp (opclass 0x0)
0419 bras reload
0420 uns_data:
0421 btstb #direction_bit,CMDREG1B(%a6) //check transfer direction
0422 bnes bit_set //branch if set (opclass 011)
0423 bsr uns_opx //call if opclass 0x0
0424 bras reload
0425 bit_set:
0426 bsr uns_op3 //opclass 011
0427 reload:
0428 cmpw #0x3fff,LOCAL_EX(%a0) //if exp > $3fff
0429 bgts end_mk // fpte15/ete15 already set to 0
0430 bsetb #4,L_SCR1(%a6) //else set fpte15/ete15 to 1
0431 // ;calling routine actually sets the
0432 // ;value on the stack (along with the
0433 // ;tag), since this routine doesn't
0434 // ;know if it should set ete15 or fpte15
0435 // ;ie, it doesn't know if this is the
0436 // ;src op or dest op.
0437 end_mk:
0438 bfclr LOCAL_SGN(%a0){#0:#8}
0439 beqs end_mk_pos
0440 bsetb #sign_bit,LOCAL_EX(%a0) //convert back to IEEE format
0441 end_mk_pos:
0442 rts
0443 //
0444 // CASE opclass 011 unsupp
0445 //
0446 uns_op3:
0447 bsr nrm_zero //normalize till msb = 1 or exp = zero
0448 btstb #7,LOCAL_HI(%a0) //if msb = 1
0449 bnes no_unfl //then branch
0450 set_unfl:
0451 orw #dnrm_tag,L_SCR1(%a6) //set denorm tag
0452 bsetb #unfl_bit,FPSR_EXCEPT(%a6) //set unfl exception bit
0453 no_unfl:
0454 rts
0455 //
0456 // CASE opclass 0x0 unsupp
0457 //
0458 uns_opx:
0459 bsr nrm_zero //normalize the number
0460 btstb #7,LOCAL_HI(%a0) //check if integer bit (j-bit) is set
0461 beqs uns_den //if clear then now have a denorm
0462 uns_nrm:
0463 orb #norm_tag,L_SCR1(%a6) //set tag to norm
0464 rts
0465 uns_den:
0466 orb #dnrm_tag,L_SCR1(%a6) //set tag to denorm
0467 rts
0468 //
0469 // CASE opclass 0x0 unimp
0470 //
0471 uni_inst:
0472 bsr nrm_zero
0473 btstb #7,LOCAL_HI(%a0) //check if integer bit (j-bit) is set
0474 beqs uni_den //if clear then now have a denorm
0475 uni_nrm:
0476 orb #norm_tag,L_SCR1(%a6) //set tag to norm
0477 rts
0478 uni_den:
0479 orb #dnrm_tag,L_SCR1(%a6) //set tag to denorm
0480 rts
0481
0482 //
0483 // Decimal to binary conversion
0484 //
0485 // Special cases of inf and NaNs are completed outside of decbin.
0486 // If the input is an snan, the snan bit is not set.
0487 //
0488 // input:
0489 // ETEMP(a6) - points to packed decimal string in memory
0490 // output:
0491 // fp0 - contains packed string converted to extended precision
0492 // ETEMP - same as fp0
0493 unpack:
0494 movew CMDREG1B(%a6),%d0 //examine command word, looking for fmove's
0495 andw #0x3b,%d0
0496 beq move_unpack //special handling for fmove: must set FPSR_CC
0497
0498 movew ETEMP(%a6),%d0 //get word with inf information
0499 bfextu %d0{#20:#12},%d1 //get exponent into d1
0500 cmpiw #0x0fff,%d1 //test for inf or NaN
0501 bnes try_zero //if not equal, it is not special
0502 bfextu %d0{#17:#3},%d1 //get SE and y bits into d1
0503 cmpiw #7,%d1 //SE and y bits must be on for special
0504 bnes try_zero //if not on, it is not special
0505 //input is of the special cases of inf and NaN
0506 tstl ETEMP_HI(%a6) //check ms mantissa
0507 bnes fix_nan //if non-zero, it is a NaN
0508 tstl ETEMP_LO(%a6) //check ls mantissa
0509 bnes fix_nan //if non-zero, it is a NaN
0510 bra finish //special already on stack
0511 fix_nan:
0512 btstb #signan_bit,ETEMP_HI(%a6) //test for snan
0513 bne finish
0514 orl #snaniop_mask,USER_FPSR(%a6) //always set snan if it is so
0515 bra finish
0516 try_zero:
0517 movew ETEMP_EX+2(%a6),%d0 //get word 4
0518 andiw #0x000f,%d0 //clear all but last ni(y)bble
0519 tstw %d0 //check for zero.
0520 bne not_spec
0521 tstl ETEMP_HI(%a6) //check words 3 and 2
0522 bne not_spec
0523 tstl ETEMP_LO(%a6) //check words 1 and 0
0524 bne not_spec
0525 tstl ETEMP(%a6) //test sign of the zero
0526 bges pos_zero
0527 movel #0x80000000,ETEMP(%a6) //write neg zero to etemp
0528 clrl ETEMP_HI(%a6)
0529 clrl ETEMP_LO(%a6)
0530 bra finish
0531 pos_zero:
0532 clrl ETEMP(%a6)
0533 clrl ETEMP_HI(%a6)
0534 clrl ETEMP_LO(%a6)
0535 bra finish
0536
0537 not_spec:
0538 fmovemx %fp0-%fp1,-(%a7) //save fp0 - decbin returns in it
0539 bsr decbin
0540 fmovex %fp0,ETEMP(%a6) //put the unpacked sop in the fsave stack
0541 fmovemx (%a7)+,%fp0-%fp1
0542 fmovel #0,%FPSR //clr fpsr from decbin
0543 bra finish
0544
0545 //
0546 // Special handling for packed move in: Same results as all other
0547 // packed cases, but we must set the FPSR condition codes properly.
0548 //
0549 move_unpack:
0550 movew ETEMP(%a6),%d0 //get word with inf information
0551 bfextu %d0{#20:#12},%d1 //get exponent into d1
0552 cmpiw #0x0fff,%d1 //test for inf or NaN
0553 bnes mtry_zero //if not equal, it is not special
0554 bfextu %d0{#17:#3},%d1 //get SE and y bits into d1
0555 cmpiw #7,%d1 //SE and y bits must be on for special
0556 bnes mtry_zero //if not on, it is not special
0557 //input is of the special cases of inf and NaN
0558 tstl ETEMP_HI(%a6) //check ms mantissa
0559 bnes mfix_nan //if non-zero, it is a NaN
0560 tstl ETEMP_LO(%a6) //check ls mantissa
0561 bnes mfix_nan //if non-zero, it is a NaN
0562 //input is inf
0563 orl #inf_mask,USER_FPSR(%a6) //set I bit
0564 tstl ETEMP(%a6) //check sign
0565 bge finish
0566 orl #neg_mask,USER_FPSR(%a6) //set N bit
0567 bra finish //special already on stack
0568 mfix_nan:
0569 orl #nan_mask,USER_FPSR(%a6) //set NaN bit
0570 moveb #nan_tag,STAG(%a6) //set stag to NaN
0571 btstb #signan_bit,ETEMP_HI(%a6) //test for snan
0572 bnes mn_snan
0573 orl #snaniop_mask,USER_FPSR(%a6) //set snan bit
0574 btstb #snan_bit,FPCR_ENABLE(%a6) //test for snan enabled
0575 bnes mn_snan
0576 bsetb #signan_bit,ETEMP_HI(%a6) //force snans to qnans
0577 mn_snan:
0578 tstl ETEMP(%a6) //check for sign
0579 bge finish //if clr, go on
0580 orl #neg_mask,USER_FPSR(%a6) //set N bit
0581 bra finish
0582
0583 mtry_zero:
0584 movew ETEMP_EX+2(%a6),%d0 //get word 4
0585 andiw #0x000f,%d0 //clear all but last ni(y)bble
0586 tstw %d0 //check for zero.
0587 bnes mnot_spec
0588 tstl ETEMP_HI(%a6) //check words 3 and 2
0589 bnes mnot_spec
0590 tstl ETEMP_LO(%a6) //check words 1 and 0
0591 bnes mnot_spec
0592 tstl ETEMP(%a6) //test sign of the zero
0593 bges mpos_zero
0594 orl #neg_mask+z_mask,USER_FPSR(%a6) //set N and Z
0595 movel #0x80000000,ETEMP(%a6) //write neg zero to etemp
0596 clrl ETEMP_HI(%a6)
0597 clrl ETEMP_LO(%a6)
0598 bras finish
0599 mpos_zero:
0600 orl #z_mask,USER_FPSR(%a6) //set Z
0601 clrl ETEMP(%a6)
0602 clrl ETEMP_HI(%a6)
0603 clrl ETEMP_LO(%a6)
0604 bras finish
0605
0606 mnot_spec:
0607 fmovemx %fp0-%fp1,-(%a7) //save fp0 ,fp1 - decbin returns in fp0
0608 bsr decbin
0609 fmovex %fp0,ETEMP(%a6)
0610 // ;put the unpacked sop in the fsave stack
0611 fmovemx (%a7)+,%fp0-%fp1
0612
0613 finish:
0614 movew CMDREG1B(%a6),%d0 //get the command word
0615 andw #0xfbff,%d0 //change the source specifier field to
0616 // ;extended (was packed).
0617 movew %d0,CMDREG1B(%a6) //write command word back to fsave stack
0618 // ;we need to do this so the 040 will
0619 // ;re-execute the inst. without taking
0620 // ;another packed trap.
0621
0622 fix_stag:
0623 //Converted result is now in etemp on fsave stack, now set the source
0624 //tag (stag)
0625 // if (ete =$7fff) then INF or NAN
0626 // if (etemp = $x.0----0) then
0627 // stag = INF
0628 // else
0629 // stag = NAN
0630 // else
0631 // if (ete = $0000) then
0632 // stag = ZERO
0633 // else
0634 // stag = NORM
0635 //
0636 // Note also that the etemp_15 bit (just right of the stag) must
0637 // be set accordingly.
0638 //
0639 movew ETEMP_EX(%a6),%d1
0640 andiw #0x7fff,%d1 //strip sign
0641 cmpw #0x7fff,%d1
0642 bnes z_or_nrm
0643 movel ETEMP_HI(%a6),%d1
0644 bnes is_nan
0645 movel ETEMP_LO(%a6),%d1
0646 bnes is_nan
0647 is_inf:
0648 moveb #0x40,STAG(%a6)
0649 movel #0x40,%d0
0650 rts
0651 is_nan:
0652 moveb #0x60,STAG(%a6)
0653 movel #0x60,%d0
0654 rts
0655 z_or_nrm:
0656 tstw %d1
0657 bnes is_nrm
0658 is_zro:
0659 // For a zero, set etemp_15
0660 moveb #0x30,STAG(%a6)
0661 movel #0x20,%d0
0662 rts
0663 is_nrm:
0664 // For a norm, check if the exp <= $3fff; if so, set etemp_15
0665 cmpiw #0x3fff,%d1
0666 bles set_bit15
0667 moveb #0,STAG(%a6)
0668 bras end_is_nrm
0669 set_bit15:
0670 moveb #0x10,STAG(%a6)
0671 end_is_nrm:
0672 movel #0,%d0
0673 end_fix:
0674 rts
0675
0676 end_get:
0677 rts
0678 |end