Back to home page

LXR

 
 

    


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