linux/arch/m68k/fpsp040/get_op.S
<<
>>
Prefs
   1|
   2|       get_op.sa 3.6 5/19/92
   3|
   4|       get_op.sa 3.5 4/26/91
   5|
   6|  Description: This routine is called by the unsupported format/data
   7| type exception handler ('unsupp' - vector 55) and the unimplemented
   8| instruction exception handler ('unimp' - vector 11).  'get_op'
   9| determines the opclass (0, 2, or 3) and branches to the
  10| opclass handler routine.  See 68881/2 User's Manual table 4-11
  11| for a description of the opclasses.
  12|
  13| For UNSUPPORTED data/format (exception vector 55) and for
  14| UNIMPLEMENTED instructions (exception vector 11) the following
  15| applies:
  16|
  17| - For unnormalized numbers (opclass 0, 2, or 3) the
  18| number(s) is normalized and the operand type tag is updated.
  19|
  20| - For a packed number (opclass 2) the number is unpacked and the
  21| operand type tag is updated.
  22|
  23| - For denormalized numbers (opclass 0 or 2) the number(s) is not
  24| changed but passed to the next module.  The next module for
  25| unimp is do_func, the next module for unsupp is res_func.
  26|
  27| For UNSUPPORTED data/format (exception vector 55) only the
  28| following applies:
  29|
  30| - If there is a move out with a packed number (opclass 3) the
  31| number is packed and written to user memory.  For the other
  32| opclasses the number(s) are written back to the fsave stack
  33| and the instruction is then restored back into the '040.  The
  34| '040 is then able to complete the instruction.
  35|
  36| For example:
  37| fadd.x fpm,fpn where the fpm contains an unnormalized number.
  38| The '040 takes an unsupported data trap and gets to this
  39| routine.  The number is normalized, put back on the stack and
  40| then an frestore is done to restore the instruction back into
  41| the '040.  The '040 then re-executes the fadd.x fpm,fpn with
  42| a normalized number in the source and the instruction is
  43| successful.
  44|
  45| Next consider if in the process of normalizing the un-
  46| normalized number it becomes a denormalized number.  The
  47| routine which converts the unnorm to a norm (called mk_norm)
  48| detects this and tags the number as a denorm.  The routine
  49| res_func sees the denorm tag and converts the denorm to a
  50| norm.  The instruction is then restored back into the '040
  51| which re_executes the instruction.
  52|
  53|
  54|               Copyright (C) Motorola, Inc. 1990
  55|                       All Rights Reserved
  56|
  57|       For details on the license for this file, please see the
  58|       file, README, in this same directory.
  59
  60GET_OP:    |idnt    2,1 | Motorola 040 Floating Point Software Package
  61
  62        |section        8
  63
  64#include "fpsp.h"
  65
  66        .global PIRN,PIRZRM,PIRP
  67        .global SMALRN,SMALRZRM,SMALRP
  68        .global BIGRN,BIGRZRM,BIGRP
  69
  70PIRN:
  71        .long 0x40000000,0xc90fdaa2,0x2168c235    |pi
  72PIRZRM:
  73        .long 0x40000000,0xc90fdaa2,0x2168c234    |pi
  74PIRP:
  75        .long 0x40000000,0xc90fdaa2,0x2168c235    |pi
  76
  77|round to nearest
  78SMALRN:
  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
  85SMALRZRM:
  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
  92SMALRP:
  93        .long 0x3ffd0000,0x9a209a84,0xfbcff799    |log10(2)
  94        .long 0x40000000,0xadf85458,0xa2bb4a9b    |e
  95        .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc    |log2(e)
  96        .long 0x3ffd0000,0xde5bd8a9,0x37287195    |log10(e)
  97        .long 0x00000000,0x00000000,0x00000000    |0.0
  98
  99|round to nearest
 100BIGRN:
 101        .long 0x3ffe0000,0xb17217f7,0xd1cf79ac    |ln(2)
 102        .long 0x40000000,0x935d8ddd,0xaaa8ac17    |ln(10)
 103        .long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
 104
 105        .global PTENRN
 106PTENRN:
 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
 121BIGRZRM:
 122        .long 0x3ffe0000,0xb17217f7,0xd1cf79ab    |ln(2)
 123        .long 0x40000000,0x935d8ddd,0xaaa8ac16    |ln(10)
 124        .long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
 125
 126        .global PTENRM
 127PTENRM:
 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
 142BIGRP:
 143        .long 0x3ffe0000,0xb17217f7,0xd1cf79ac    |ln(2)
 144        .long 0x40000000,0x935d8ddd,0xaaa8ac17    |ln(10)
 145        .long 0x3fff0000,0x80000000,0x00000000    |10 ^ 0
 146
 147        .global PTENRP
 148PTENRP:
 149        .long 0x40020000,0xA0000000,0x00000000    |10 ^ 1
 150        .long 0x40050000,0xC8000000,0x00000000    |10 ^ 2
 151        .long 0x400C0000,0x9C400000,0x00000000    |10 ^ 4
 152        .long 0x40190000,0xBEBC2000,0x00000000    |10 ^ 8
 153        .long 0x40340000,0x8E1BC9BF,0x04000000    |10 ^ 16
 154        .long 0x40690000,0x9DC5ADA8,0x2B70B59E    |10 ^ 32
 155        .long 0x40D30000,0xC2781F49,0xFFCFA6D6    |10 ^ 64
 156        .long 0x41A80000,0x93BA47C9,0x80E98CE0    |10 ^ 128
 157        .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E    |10 ^ 256
 158        .long 0x46A30000,0xE319A0AE,0xA60E91C7    |10 ^ 512
 159        .long 0x4D480000,0xC9767586,0x81750C18    |10 ^ 1024
 160        .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6    |10 ^ 2048
 161        .long 0x75250000,0xC4605202,0x8A20979B    |10 ^ 4096
 162
 163        |xref   nrm_zero
 164        |xref   decbin
 165        |xref   round
 166
 167        .global    get_op
 168        .global    uns_getop
 169        .global    uni_getop
 170get_op:
 171        clrb    DY_MO_FLG(%a6)
 172        tstb    UFLG_TMP(%a6)   |test flag for unsupp/unimp state
 173        beq     uni_getop
 174
 175uns_getop:
 176        btstb   #direction_bit,CMDREG1B(%a6)
 177        bne     opclass3        |branch if a fmove out (any kind)
 178        btstb   #6,CMDREG1B(%a6)
 179        beqs    uns_notpacked
 180
 181        bfextu  CMDREG1B(%a6){#3:#3},%d0
 182        cmpb    #3,%d0
 183        beq     pack_source     |check for a packed src op, branch if so
 184uns_notpacked:
 185        bsr     chk_dy_mo       |set the dyadic/monadic flag
 186        tstb    DY_MO_FLG(%a6)
 187        beqs    src_op_ck       |if monadic, go check src op
 188|                               ;else, check dst op (fall through)
 189
 190        btstb   #7,DTAG(%a6)
 191        beqs    src_op_ck       |if dst op is norm, check src op
 192        bras    dst_ex_dnrm     |else, handle destination unnorm/dnrm
 193
 194uni_getop:
 195        bfextu  CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
 196        cmpil   #0x17,%d0               |if op class and size fields are $17,
 197|                               ;it is FMOVECR; if not, continue
 198|
 199| If the instruction is fmovecr, exit get_op.  It is handled
 200| in do_func and smovecr.sa.
 201|
 202        bne     not_fmovecr     |handle fmovecr as an unimplemented inst
 203        rts
 204
 205not_fmovecr:
 206        btstb   #E1,E_BYTE(%a6) |if set, there is a packed operand
 207        bne     pack_source     |check for packed src op, branch if so
 208
 209| The following lines of are coded to optimize on normalized operands
 210        moveb   STAG(%a6),%d0
 211        orb     DTAG(%a6),%d0   |check if either of STAG/DTAG msb set
 212        bmis    dest_op_ck      |if so, some op needs to be fixed
 213        rts
 214
 215dest_op_ck:
 216        btstb   #7,DTAG(%a6)    |check for unsupported data types in
 217        beqs    src_op_ck       |the destination, if not, check src op
 218        bsr     chk_dy_mo       |set dyadic/monadic flag
 219        tstb    DY_MO_FLG(%a6)  |
 220        beqs    src_op_ck       |if monadic, check src op
 221|
 222| At this point, destination has an extended denorm or unnorm.
 223|
 224dst_ex_dnrm:
 225        movew   FPTEMP_EX(%a6),%d0 |get destination exponent
 226        andiw   #0x7fff,%d0     |mask sign, check if exp = 0000
 227        beqs    src_op_ck       |if denorm then check source op.
 228|                               ;denorms are taken care of in res_func
 229|                               ;(unsupp) or do_func (unimp)
 230|                               ;else unnorm fall through
 231        leal    FPTEMP(%a6),%a0 |point a0 to dop - used in mk_norm
 232        bsr     mk_norm         |go normalize - mk_norm returns:
 233|                               ;L_SCR1{7:5} = operand tag
 234|                               ;       (000 = norm, 100 = denorm)
 235|                               ;L_SCR1{4} = fpte15 or ete15
 236|                               ;       0 = exp >  $3fff
 237|                               ;       1 = exp <= $3fff
 238|                               ;and puts the normalized num back
 239|                               ;on the fsave stack
 240|
 241        moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15
 242|                               ;to the fsave stack and fall
 243|                               ;through to check source operand
 244|
 245src_op_ck:
 246        btstb   #7,STAG(%a6)
 247        beq     end_getop       |check for unsupported data types on the
 248|                               ;source operand
 249        btstb   #5,STAG(%a6)
 250        bnes    src_sd_dnrm     |if bit 5 set, handle sgl/dbl denorms
 251|
 252| At this point only unnorms or extended denorms are possible.
 253|
 254src_ex_dnrm:
 255        movew   ETEMP_EX(%a6),%d0 |get source exponent
 256        andiw   #0x7fff,%d0     |mask sign, check if exp = 0000
 257        beq     end_getop       |if denorm then exit, denorms are
 258|                               ;handled in do_func
 259        leal    ETEMP(%a6),%a0  |point a0 to sop - used in mk_norm
 260        bsr     mk_norm         |go normalize - mk_norm returns:
 261|                               ;L_SCR1{7:5} = operand tag
 262|                               ;       (000 = norm, 100 = denorm)
 263|                               ;L_SCR1{4} = fpte15 or ete15
 264|                               ;       0 = exp >  $3fff
 265|                               ;       1 = exp <= $3fff
 266|                               ;and puts the normalized num back
 267|                               ;on the fsave stack
 268|
 269        moveb   L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
 270        rts                     |end_getop
 271
 272|
 273| At this point, only single or double denorms are possible.
 274| If the inst is not fmove, normalize the source.  If it is,
 275| do nothing to the input.
 276|
 277src_sd_dnrm:
 278        btstb   #4,CMDREG1B(%a6)        |differentiate between sgl/dbl denorm
 279        bnes    is_double
 280is_single:
 281        movew   #0x3f81,%d1     |write bias for sgl denorm
 282        bras    common          |goto the common code
 283is_double:
 284        movew   #0x3c01,%d1     |write the bias for a dbl denorm
 285common:
 286        btstb   #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
 287        beqs    pos
 288        bset    #15,%d1         |set sign bit because it is negative
 289pos:
 290        movew   %d1,ETEMP_EX(%a6)
 291|                               ;put exponent on stack
 292
 293        movew   CMDREG1B(%a6),%d1
 294        andw    #0xe3ff,%d1     |clear out source specifier
 295        orw     #0x0800,%d1     |set source specifier to extended prec
 296        movew   %d1,CMDREG1B(%a6)       |write back to the command word in stack
 297|                               ;this is needed to fix unsupp data stack
 298        leal    ETEMP(%a6),%a0  |point a0 to sop
 299
 300        bsr     mk_norm         |convert sgl/dbl denorm to norm
 301        moveb   L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
 302        rts                     |end_getop
 303|
 304| At this point, the source is definitely packed, whether
 305| instruction is dyadic or monadic is still unknown
 306|
 307pack_source:
 308        movel   FPTEMP_LO(%a6),ETEMP(%a6)       |write ms part of packed
 309|                               ;number to etemp slot
 310        bsr     chk_dy_mo       |set dyadic/monadic flag
 311        bsr     unpack
 312
 313        tstb    DY_MO_FLG(%a6)
 314        beqs    end_getop       |if monadic, exit
 315|                               ;else, fix FPTEMP
 316pack_dya:
 317        bfextu  CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
 318        movel   #7,%d1
 319        subl    %d0,%d1
 320        clrl    %d0
 321        bsetl   %d1,%d0         |set up d0 as a dynamic register mask
 322        fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
 323
 324        btstb   #7,DTAG(%a6)    |check dest tag for unnorm or denorm
 325        bne     dst_ex_dnrm     |else, handle the unnorm or ext denorm
 326|
 327| Dest is not denormalized.  Check for norm, and set fpte15
 328| accordingly.
 329|
 330        moveb   DTAG(%a6),%d0
 331        andib   #0xf0,%d0               |strip to only dtag:fpte15
 332        tstb    %d0             |check for normalized value
 333        bnes    end_getop       |if inf/nan/zero leave get_op
 334        movew   FPTEMP_EX(%a6),%d0
 335        andiw   #0x7fff,%d0
 336        cmpiw   #0x3fff,%d0     |check if fpte15 needs setting
 337        bges    end_getop       |if >= $3fff, leave fpte15=0
 338        orb     #0x10,DTAG(%a6)
 339        bras    end_getop
 340
 341|
 342| At this point, it is either an fmoveout packed, unnorm or denorm
 343|
 344opclass3:
 345        clrb    DY_MO_FLG(%a6)  |set dyadic/monadic flag to monadic
 346        bfextu  CMDREG1B(%a6){#4:#2},%d0
 347        cmpib   #3,%d0
 348        bne     src_ex_dnrm     |if not equal, must be unnorm or denorm
 349|                               ;else it is a packed move out
 350|                               ;exit
 351end_getop:
 352        rts
 353
 354|
 355| Sets the DY_MO_FLG correctly. This is used only on if it is an
 356| unsupported data type exception.  Set if dyadic.
 357|
 358chk_dy_mo:
 359        movew   CMDREG1B(%a6),%d0
 360        btstl   #5,%d0          |testing extension command word
 361        beqs    set_mon         |if bit 5 = 0 then monadic
 362        btstl   #4,%d0          |know that bit 5 = 1
 363        beqs    set_dya         |if bit 4 = 0 then dyadic
 364        andiw   #0x007f,%d0     |get rid of all but extension bits {6:0}
 365        cmpiw   #0x0038,%d0     |if extension = $38 then fcmp (dyadic)
 366        bnes    set_mon
 367set_dya:
 368        st      DY_MO_FLG(%a6)  |set the inst flag type to dyadic
 369        rts
 370set_mon:
 371        clrb    DY_MO_FLG(%a6)  |set the inst flag type to monadic
 372        rts
 373|
 374|       MK_NORM
 375|
 376| Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
 377| exception if denorm.
 378|
 379| CASE opclass 0x0 unsupp
 380|       mk_norm till msb set
 381|       set tag = norm
 382|
 383| CASE opclass 0x0 unimp
 384|       mk_norm till msb set or exp = 0
 385|       if integer bit = 0
 386|          tag = denorm
 387|       else
 388|          tag = norm
 389|
 390| CASE opclass 011 unsupp
 391|       mk_norm till msb set or exp = 0
 392|       if integer bit = 0
 393|          tag = denorm
 394|          set unfl_nmcexe = 1
 395|       else
 396|          tag = norm
 397|
 398| if exp <= $3fff
 399|   set ete15 or fpte15 = 1
 400| else set ete15 or fpte15 = 0
 401
 402| input:
 403|       a0 = points to operand to be normalized
 404| output:
 405|       L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
 406|       L_SCR1{4}   = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
 407|       the normalized operand is placed back on the fsave stack
 408mk_norm:
 409        clrl    L_SCR1(%a6)
 410        bclrb   #sign_bit,LOCAL_EX(%a0)
 411        sne     LOCAL_SGN(%a0)  |transform into internal extended format
 412
 413        cmpib   #0x2c,1+EXC_VEC(%a6) |check if unimp
 414        bnes    uns_data        |branch if unsupp
 415        bsr     uni_inst        |call if unimp (opclass 0x0)
 416        bras    reload
 417uns_data:
 418        btstb   #direction_bit,CMDREG1B(%a6) |check transfer direction
 419        bnes    bit_set         |branch if set (opclass 011)
 420        bsr     uns_opx         |call if opclass 0x0
 421        bras    reload
 422bit_set:
 423        bsr     uns_op3         |opclass 011
 424reload:
 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.
 434end_mk:
 435        bfclr   LOCAL_SGN(%a0){#0:#8}
 436        beqs    end_mk_pos
 437        bsetb   #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
 438end_mk_pos:
 439        rts
 440|
 441|     CASE opclass 011 unsupp
 442|
 443uns_op3:
 444        bsr     nrm_zero        |normalize till msb = 1 or exp = zero
 445        btstb   #7,LOCAL_HI(%a0)        |if msb = 1
 446        bnes    no_unfl         |then branch
 447set_unfl:
 448        orw     #dnrm_tag,L_SCR1(%a6) |set denorm tag
 449        bsetb   #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
 450no_unfl:
 451        rts
 452|
 453|     CASE opclass 0x0 unsupp
 454|
 455uns_opx:
 456        bsr     nrm_zero        |normalize the number
 457        btstb   #7,LOCAL_HI(%a0)        |check if integer bit (j-bit) is set
 458        beqs    uns_den         |if clear then now have a denorm
 459uns_nrm:
 460        orb     #norm_tag,L_SCR1(%a6) |set tag to norm
 461        rts
 462uns_den:
 463        orb     #dnrm_tag,L_SCR1(%a6) |set tag to denorm
 464        rts
 465|
 466|     CASE opclass 0x0 unimp
 467|
 468uni_inst:
 469        bsr     nrm_zero
 470        btstb   #7,LOCAL_HI(%a0)        |check if integer bit (j-bit) is set
 471        beqs    uni_den         |if clear then now have a denorm
 472uni_nrm:
 473        orb     #norm_tag,L_SCR1(%a6) |set tag to norm
 474        rts
 475uni_den:
 476        orb     #dnrm_tag,L_SCR1(%a6) |set tag to denorm
 477        rts
 478
 479|
 480|       Decimal to binary conversion
 481|
 482| Special cases of inf and NaNs are completed outside of decbin.
 483| If the input is an snan, the snan bit is not set.
 484|
 485| input:
 486|       ETEMP(a6)       - points to packed decimal string in memory
 487| output:
 488|       fp0     - contains packed string converted to extended precision
 489|       ETEMP   - same as fp0
 490unpack:
 491        movew   CMDREG1B(%a6),%d0       |examine command word, looking for fmove's
 492        andw    #0x3b,%d0
 493        beq     move_unpack     |special handling for fmove: must set FPSR_CC
 494
 495        movew   ETEMP(%a6),%d0  |get word with inf information
 496        bfextu  %d0{#20:#12},%d1        |get exponent into d1
 497        cmpiw   #0x0fff,%d1     |test for inf or NaN
 498        bnes    try_zero        |if not equal, it is not special
 499        bfextu  %d0{#17:#3},%d1 |get SE and y bits into d1
 500        cmpiw   #7,%d1          |SE and y bits must be on for special
 501        bnes    try_zero        |if not on, it is not special
 502|input is of the special cases of inf and NaN
 503        tstl    ETEMP_HI(%a6)   |check ms mantissa
 504        bnes    fix_nan         |if non-zero, it is a NaN
 505        tstl    ETEMP_LO(%a6)   |check ls mantissa
 506        bnes    fix_nan         |if non-zero, it is a NaN
 507        bra     finish          |special already on stack
 508fix_nan:
 509        btstb   #signan_bit,ETEMP_HI(%a6) |test for snan
 510        bne     finish
 511        orl     #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
 512        bra     finish
 513try_zero:
 514        movew   ETEMP_EX+2(%a6),%d0 |get word 4
 515        andiw   #0x000f,%d0     |clear all but last ni(y)bble
 516        tstw    %d0             |check for zero.
 517        bne     not_spec
 518        tstl    ETEMP_HI(%a6)   |check words 3 and 2
 519        bne     not_spec
 520        tstl    ETEMP_LO(%a6)   |check words 1 and 0
 521        bne     not_spec
 522        tstl    ETEMP(%a6)      |test sign of the zero
 523        bges    pos_zero
 524        movel   #0x80000000,ETEMP(%a6) |write neg zero to etemp
 525        clrl    ETEMP_HI(%a6)
 526        clrl    ETEMP_LO(%a6)
 527        bra     finish
 528pos_zero:
 529        clrl    ETEMP(%a6)
 530        clrl    ETEMP_HI(%a6)
 531        clrl    ETEMP_LO(%a6)
 532        bra     finish
 533
 534not_spec:
 535        fmovemx %fp0-%fp1,-(%a7)        |save fp0 - decbin returns in it
 536        bsr     decbin
 537        fmovex %fp0,ETEMP(%a6)  |put the unpacked sop in the fsave stack
 538        fmovemx (%a7)+,%fp0-%fp1
 539        fmovel  #0,%FPSR                |clr fpsr from decbin
 540        bra     finish
 541
 542|
 543| Special handling for packed move in:  Same results as all other
 544| packed cases, but we must set the FPSR condition codes properly.
 545|
 546move_unpack:
 547        movew   ETEMP(%a6),%d0  |get word with inf information
 548        bfextu  %d0{#20:#12},%d1        |get exponent into d1
 549        cmpiw   #0x0fff,%d1     |test for inf or NaN
 550        bnes    mtry_zero       |if not equal, it is not special
 551        bfextu  %d0{#17:#3},%d1 |get SE and y bits into d1
 552        cmpiw   #7,%d1          |SE and y bits must be on for special
 553        bnes    mtry_zero       |if not on, it is not special
 554|input is of the special cases of inf and NaN
 555        tstl    ETEMP_HI(%a6)   |check ms mantissa
 556        bnes    mfix_nan                |if non-zero, it is a NaN
 557        tstl    ETEMP_LO(%a6)   |check ls mantissa
 558        bnes    mfix_nan                |if non-zero, it is a NaN
 559|input is inf
 560        orl     #inf_mask,USER_FPSR(%a6) |set I bit
 561        tstl    ETEMP(%a6)      |check sign
 562        bge     finish
 563        orl     #neg_mask,USER_FPSR(%a6) |set N bit
 564        bra     finish          |special already on stack
 565mfix_nan:
 566        orl     #nan_mask,USER_FPSR(%a6) |set NaN bit
 567        moveb   #nan_tag,STAG(%a6)      |set stag to NaN
 568        btstb   #signan_bit,ETEMP_HI(%a6) |test for snan
 569        bnes    mn_snan
 570        orl     #snaniop_mask,USER_FPSR(%a6) |set snan bit
 571        btstb   #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
 572        bnes    mn_snan
 573        bsetb   #signan_bit,ETEMP_HI(%a6) |force snans to qnans
 574mn_snan:
 575        tstl    ETEMP(%a6)      |check for sign
 576        bge     finish          |if clr, go on
 577        orl     #neg_mask,USER_FPSR(%a6) |set N bit
 578        bra     finish
 579
 580mtry_zero:
 581        movew   ETEMP_EX+2(%a6),%d0 |get word 4
 582        andiw   #0x000f,%d0     |clear all but last ni(y)bble
 583        tstw    %d0             |check for zero.
 584        bnes    mnot_spec
 585        tstl    ETEMP_HI(%a6)   |check words 3 and 2
 586        bnes    mnot_spec
 587        tstl    ETEMP_LO(%a6)   |check words 1 and 0
 588        bnes    mnot_spec
 589        tstl    ETEMP(%a6)      |test sign of the zero
 590        bges    mpos_zero
 591        orl     #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
 592        movel   #0x80000000,ETEMP(%a6) |write neg zero to etemp
 593        clrl    ETEMP_HI(%a6)
 594        clrl    ETEMP_LO(%a6)
 595        bras    finish
 596mpos_zero:
 597        orl     #z_mask,USER_FPSR(%a6) |set Z
 598        clrl    ETEMP(%a6)
 599        clrl    ETEMP_HI(%a6)
 600        clrl    ETEMP_LO(%a6)
 601        bras    finish
 602
 603mnot_spec:
 604        fmovemx %fp0-%fp1,-(%a7)        |save fp0 ,fp1 - decbin returns in fp0
 605        bsr     decbin
 606        fmovex %fp0,ETEMP(%a6)
 607|                               ;put the unpacked sop in the fsave stack
 608        fmovemx (%a7)+,%fp0-%fp1
 609
 610finish:
 611        movew   CMDREG1B(%a6),%d0       |get the command word
 612        andw    #0xfbff,%d0     |change the source specifier field to
 613|                               ;extended (was packed).
 614        movew   %d0,CMDREG1B(%a6)       |write command word back to fsave stack
 615|                               ;we need to do this so the 040 will
 616|                               ;re-execute the inst. without taking
 617|                               ;another packed trap.
 618
 619fix_stag:
 620|Converted result is now in etemp on fsave stack, now set the source
 621|tag (stag)
 622|       if (ete =$7fff) then INF or NAN
 623|               if (etemp = $x.0----0) then
 624|                       stag = INF
 625|               else
 626|                       stag = NAN
 627|       else
 628|               if (ete = $0000) then
 629|                       stag = ZERO
 630|               else
 631|                       stag = NORM
 632|
 633| Note also that the etemp_15 bit (just right of the stag) must
 634| be set accordingly.
 635|
 636        movew           ETEMP_EX(%a6),%d1
 637        andiw           #0x7fff,%d1   |strip sign
 638        cmpw            #0x7fff,%d1
 639        bnes            z_or_nrm
 640        movel           ETEMP_HI(%a6),%d1
 641        bnes            is_nan
 642        movel           ETEMP_LO(%a6),%d1
 643        bnes            is_nan
 644is_inf:
 645        moveb           #0x40,STAG(%a6)
 646        movel           #0x40,%d0
 647        rts
 648is_nan:
 649        moveb           #0x60,STAG(%a6)
 650        movel           #0x60,%d0
 651        rts
 652z_or_nrm:
 653        tstw            %d1
 654        bnes            is_nrm
 655is_zro:
 656| For a zero, set etemp_15
 657        moveb           #0x30,STAG(%a6)
 658        movel           #0x20,%d0
 659        rts
 660is_nrm:
 661| For a norm, check if the exp <= $3fff; if so, set etemp_15
 662        cmpiw           #0x3fff,%d1
 663        bles            set_bit15
 664        moveb           #0,STAG(%a6)
 665        bras            end_is_nrm
 666set_bit15:
 667        moveb           #0x10,STAG(%a6)
 668end_is_nrm:
 669        movel           #0,%d0
 670end_fix:
 671        rts
 672
 673end_get:
 674        rts
 675        |end
 676