123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676 |
- |
- | get_op.sa 3.6 5/19/92
- |
- | get_op.sa 3.5 4/26/91
- |
- | Description: This routine is called by the unsupported format/data
- | type exception handler ('unsupp' - vector 55) and the unimplemented
- | instruction exception handler ('unimp' - vector 11). 'get_op'
- | determines the opclass (0, 2, or 3) and branches to the
- | opclass handler routine. See 68881/2 User's Manual table 4-11
- | for a description of the opclasses.
- |
- | For UNSUPPORTED data/format (exception vector 55) and for
- | UNIMPLEMENTED instructions (exception vector 11) the following
- | applies:
- |
- | - For unnormalized numbers (opclass 0, 2, or 3) the
- | number(s) is normalized and the operand type tag is updated.
- |
- | - For a packed number (opclass 2) the number is unpacked and the
- | operand type tag is updated.
- |
- | - For denormalized numbers (opclass 0 or 2) the number(s) is not
- | changed but passed to the next module. The next module for
- | unimp is do_func, the next module for unsupp is res_func.
- |
- | For UNSUPPORTED data/format (exception vector 55) only the
- | following applies:
- |
- | - If there is a move out with a packed number (opclass 3) the
- | number is packed and written to user memory. For the other
- | opclasses the number(s) are written back to the fsave stack
- | and the instruction is then restored back into the '040. The
- | '040 is then able to complete the instruction.
- |
- | For example:
- | fadd.x fpm,fpn where the fpm contains an unnormalized number.
- | The '040 takes an unsupported data trap and gets to this
- | routine. The number is normalized, put back on the stack and
- | then an frestore is done to restore the instruction back into
- | the '040. The '040 then re-executes the fadd.x fpm,fpn with
- | a normalized number in the source and the instruction is
- | successful.
- |
- | Next consider if in the process of normalizing the un-
- | normalized number it becomes a denormalized number. The
- | routine which converts the unnorm to a norm (called mk_norm)
- | detects this and tags the number as a denorm. The routine
- | res_func sees the denorm tag and converts the denorm to a
- | norm. The instruction is then restored back into the '040
- | which re_executes the instruction.
- |
- |
- | Copyright (C) Motorola, Inc. 1990
- | All Rights Reserved
- |
- | For details on the license for this file, please see the
- | file, README, in this same directory.
- GET_OP: |idnt 2,1 | Motorola 040 Floating Point Software Package
- |section 8
- #include "fpsp.h"
- .global PIRN,PIRZRM,PIRP
- .global SMALRN,SMALRZRM,SMALRP
- .global BIGRN,BIGRZRM,BIGRP
- PIRN:
- .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
- PIRZRM:
- .long 0x40000000,0xc90fdaa2,0x2168c234 |pi
- PIRP:
- .long 0x40000000,0xc90fdaa2,0x2168c235 |pi
- |round to nearest
- SMALRN:
- .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
- .long 0x40000000,0xadf85458,0xa2bb4a9a |e
- .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
- .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
- .long 0x00000000,0x00000000,0x00000000 |0.0
- | round to zero;round to negative infinity
- SMALRZRM:
- .long 0x3ffd0000,0x9a209a84,0xfbcff798 |log10(2)
- .long 0x40000000,0xadf85458,0xa2bb4a9a |e
- .long 0x3fff0000,0xb8aa3b29,0x5c17f0bb |log2(e)
- .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
- .long 0x00000000,0x00000000,0x00000000 |0.0
- | round to positive infinity
- SMALRP:
- .long 0x3ffd0000,0x9a209a84,0xfbcff799 |log10(2)
- .long 0x40000000,0xadf85458,0xa2bb4a9b |e
- .long 0x3fff0000,0xb8aa3b29,0x5c17f0bc |log2(e)
- .long 0x3ffd0000,0xde5bd8a9,0x37287195 |log10(e)
- .long 0x00000000,0x00000000,0x00000000 |0.0
- |round to nearest
- BIGRN:
- .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
- .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
- .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
- .global PTENRN
- PTENRN:
- .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
- .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
- .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
- .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
- .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
- .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
- .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
- .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
- .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
- .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
- .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
- .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
- .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
- |round to minus infinity
- BIGRZRM:
- .long 0x3ffe0000,0xb17217f7,0xd1cf79ab |ln(2)
- .long 0x40000000,0x935d8ddd,0xaaa8ac16 |ln(10)
- .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
- .global PTENRM
- PTENRM:
- .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
- .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
- .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
- .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
- .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
- .long 0x40690000,0x9DC5ADA8,0x2B70B59D |10 ^ 32
- .long 0x40D30000,0xC2781F49,0xFFCFA6D5 |10 ^ 64
- .long 0x41A80000,0x93BA47C9,0x80E98CDF |10 ^ 128
- .long 0x43510000,0xAA7EEBFB,0x9DF9DE8D |10 ^ 256
- .long 0x46A30000,0xE319A0AE,0xA60E91C6 |10 ^ 512
- .long 0x4D480000,0xC9767586,0x81750C17 |10 ^ 1024
- .long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 |10 ^ 2048
- .long 0x75250000,0xC4605202,0x8A20979A |10 ^ 4096
- |round to positive infinity
- BIGRP:
- .long 0x3ffe0000,0xb17217f7,0xd1cf79ac |ln(2)
- .long 0x40000000,0x935d8ddd,0xaaa8ac17 |ln(10)
- .long 0x3fff0000,0x80000000,0x00000000 |10 ^ 0
- .global PTENRP
- PTENRP:
- .long 0x40020000,0xA0000000,0x00000000 |10 ^ 1
- .long 0x40050000,0xC8000000,0x00000000 |10 ^ 2
- .long 0x400C0000,0x9C400000,0x00000000 |10 ^ 4
- .long 0x40190000,0xBEBC2000,0x00000000 |10 ^ 8
- .long 0x40340000,0x8E1BC9BF,0x04000000 |10 ^ 16
- .long 0x40690000,0x9DC5ADA8,0x2B70B59E |10 ^ 32
- .long 0x40D30000,0xC2781F49,0xFFCFA6D6 |10 ^ 64
- .long 0x41A80000,0x93BA47C9,0x80E98CE0 |10 ^ 128
- .long 0x43510000,0xAA7EEBFB,0x9DF9DE8E |10 ^ 256
- .long 0x46A30000,0xE319A0AE,0xA60E91C7 |10 ^ 512
- .long 0x4D480000,0xC9767586,0x81750C18 |10 ^ 1024
- .long 0x5A920000,0x9E8B3B5D,0xC53D5DE6 |10 ^ 2048
- .long 0x75250000,0xC4605202,0x8A20979B |10 ^ 4096
- |xref nrm_zero
- |xref decbin
- |xref round
- .global get_op
- .global uns_getop
- .global uni_getop
- get_op:
- clrb DY_MO_FLG(%a6)
- tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state
- beq uni_getop
- uns_getop:
- btstb #direction_bit,CMDREG1B(%a6)
- bne opclass3 |branch if a fmove out (any kind)
- btstb #6,CMDREG1B(%a6)
- beqs uns_notpacked
- bfextu CMDREG1B(%a6){#3:#3},%d0
- cmpb #3,%d0
- beq pack_source |check for a packed src op, branch if so
- uns_notpacked:
- bsr chk_dy_mo |set the dyadic/monadic flag
- tstb DY_MO_FLG(%a6)
- beqs src_op_ck |if monadic, go check src op
- | ;else, check dst op (fall through)
- btstb #7,DTAG(%a6)
- beqs src_op_ck |if dst op is norm, check src op
- bras dst_ex_dnrm |else, handle destination unnorm/dnrm
- uni_getop:
- bfextu CMDREG1B(%a6){#0:#6},%d0 |get opclass and src fields
- cmpil #0x17,%d0 |if op class and size fields are $17,
- | ;it is FMOVECR; if not, continue
- |
- | If the instruction is fmovecr, exit get_op. It is handled
- | in do_func and smovecr.sa.
- |
- bne not_fmovecr |handle fmovecr as an unimplemented inst
- rts
- not_fmovecr:
- btstb #E1,E_BYTE(%a6) |if set, there is a packed operand
- bne pack_source |check for packed src op, branch if so
- | The following lines of are coded to optimize on normalized operands
- moveb STAG(%a6),%d0
- orb DTAG(%a6),%d0 |check if either of STAG/DTAG msb set
- bmis dest_op_ck |if so, some op needs to be fixed
- rts
- dest_op_ck:
- btstb #7,DTAG(%a6) |check for unsupported data types in
- beqs src_op_ck |the destination, if not, check src op
- bsr chk_dy_mo |set dyadic/monadic flag
- tstb DY_MO_FLG(%a6) |
- beqs src_op_ck |if monadic, check src op
- |
- | At this point, destination has an extended denorm or unnorm.
- |
- dst_ex_dnrm:
- movew FPTEMP_EX(%a6),%d0 |get destination exponent
- andiw #0x7fff,%d0 |mask sign, check if exp = 0000
- beqs src_op_ck |if denorm then check source op.
- | ;denorms are taken care of in res_func
- | ;(unsupp) or do_func (unimp)
- | ;else unnorm fall through
- leal FPTEMP(%a6),%a0 |point a0 to dop - used in mk_norm
- bsr mk_norm |go normalize - mk_norm returns:
- | ;L_SCR1{7:5} = operand tag
- | ; (000 = norm, 100 = denorm)
- | ;L_SCR1{4} = fpte15 or ete15
- | ; 0 = exp > $3fff
- | ; 1 = exp <= $3fff
- | ;and puts the normalized num back
- | ;on the fsave stack
- |
- moveb L_SCR1(%a6),DTAG(%a6) |write the new tag & fpte15
- | ;to the fsave stack and fall
- | ;through to check source operand
- |
- src_op_ck:
- btstb #7,STAG(%a6)
- beq end_getop |check for unsupported data types on the
- | ;source operand
- btstb #5,STAG(%a6)
- bnes src_sd_dnrm |if bit 5 set, handle sgl/dbl denorms
- |
- | At this point only unnorms or extended denorms are possible.
- |
- src_ex_dnrm:
- movew ETEMP_EX(%a6),%d0 |get source exponent
- andiw #0x7fff,%d0 |mask sign, check if exp = 0000
- beq end_getop |if denorm then exit, denorms are
- | ;handled in do_func
- leal ETEMP(%a6),%a0 |point a0 to sop - used in mk_norm
- bsr mk_norm |go normalize - mk_norm returns:
- | ;L_SCR1{7:5} = operand tag
- | ; (000 = norm, 100 = denorm)
- | ;L_SCR1{4} = fpte15 or ete15
- | ; 0 = exp > $3fff
- | ; 1 = exp <= $3fff
- | ;and puts the normalized num back
- | ;on the fsave stack
- |
- moveb L_SCR1(%a6),STAG(%a6) |write the new tag & ete15
- rts |end_getop
- |
- | At this point, only single or double denorms are possible.
- | If the inst is not fmove, normalize the source. If it is,
- | do nothing to the input.
- |
- src_sd_dnrm:
- btstb #4,CMDREG1B(%a6) |differentiate between sgl/dbl denorm
- bnes is_double
- is_single:
- movew #0x3f81,%d1 |write bias for sgl denorm
- bras common |goto the common code
- is_double:
- movew #0x3c01,%d1 |write the bias for a dbl denorm
- common:
- btstb #sign_bit,ETEMP_EX(%a6) |grab sign bit of mantissa
- beqs pos
- bset #15,%d1 |set sign bit because it is negative
- pos:
- movew %d1,ETEMP_EX(%a6)
- | ;put exponent on stack
- movew CMDREG1B(%a6),%d1
- andw #0xe3ff,%d1 |clear out source specifier
- orw #0x0800,%d1 |set source specifier to extended prec
- movew %d1,CMDREG1B(%a6) |write back to the command word in stack
- | ;this is needed to fix unsupp data stack
- leal ETEMP(%a6),%a0 |point a0 to sop
- bsr mk_norm |convert sgl/dbl denorm to norm
- moveb L_SCR1(%a6),STAG(%a6) |put tag into source tag reg - d0
- rts |end_getop
- |
- | At this point, the source is definitely packed, whether
- | instruction is dyadic or monadic is still unknown
- |
- pack_source:
- movel FPTEMP_LO(%a6),ETEMP(%a6) |write ms part of packed
- | ;number to etemp slot
- bsr chk_dy_mo |set dyadic/monadic flag
- bsr unpack
- tstb DY_MO_FLG(%a6)
- beqs end_getop |if monadic, exit
- | ;else, fix FPTEMP
- pack_dya:
- bfextu CMDREG1B(%a6){#6:#3},%d0 |extract dest fp reg
- movel #7,%d1
- subl %d0,%d1
- clrl %d0
- bsetl %d1,%d0 |set up d0 as a dynamic register mask
- fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
- btstb #7,DTAG(%a6) |check dest tag for unnorm or denorm
- bne dst_ex_dnrm |else, handle the unnorm or ext denorm
- |
- | Dest is not denormalized. Check for norm, and set fpte15
- | accordingly.
- |
- moveb DTAG(%a6),%d0
- andib #0xf0,%d0 |strip to only dtag:fpte15
- tstb %d0 |check for normalized value
- bnes end_getop |if inf/nan/zero leave get_op
- movew FPTEMP_EX(%a6),%d0
- andiw #0x7fff,%d0
- cmpiw #0x3fff,%d0 |check if fpte15 needs setting
- bges end_getop |if >= $3fff, leave fpte15=0
- orb #0x10,DTAG(%a6)
- bras end_getop
- |
- | At this point, it is either an fmoveout packed, unnorm or denorm
- |
- opclass3:
- clrb DY_MO_FLG(%a6) |set dyadic/monadic flag to monadic
- bfextu CMDREG1B(%a6){#4:#2},%d0
- cmpib #3,%d0
- bne src_ex_dnrm |if not equal, must be unnorm or denorm
- | ;else it is a packed move out
- | ;exit
- end_getop:
- rts
- |
- | Sets the DY_MO_FLG correctly. This is used only on if it is an
- | unsupported data type exception. Set if dyadic.
- |
- chk_dy_mo:
- movew CMDREG1B(%a6),%d0
- btstl #5,%d0 |testing extension command word
- beqs set_mon |if bit 5 = 0 then monadic
- btstl #4,%d0 |know that bit 5 = 1
- beqs set_dya |if bit 4 = 0 then dyadic
- andiw #0x007f,%d0 |get rid of all but extension bits {6:0}
- cmpiw #0x0038,%d0 |if extension = $38 then fcmp (dyadic)
- bnes set_mon
- set_dya:
- st DY_MO_FLG(%a6) |set the inst flag type to dyadic
- rts
- set_mon:
- clrb DY_MO_FLG(%a6) |set the inst flag type to monadic
- rts
- |
- | MK_NORM
- |
- | Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
- | exception if denorm.
- |
- | CASE opclass 0x0 unsupp
- | mk_norm till msb set
- | set tag = norm
- |
- | CASE opclass 0x0 unimp
- | mk_norm till msb set or exp = 0
- | if integer bit = 0
- | tag = denorm
- | else
- | tag = norm
- |
- | CASE opclass 011 unsupp
- | mk_norm till msb set or exp = 0
- | if integer bit = 0
- | tag = denorm
- | set unfl_nmcexe = 1
- | else
- | tag = norm
- |
- | if exp <= $3fff
- | set ete15 or fpte15 = 1
- | else set ete15 or fpte15 = 0
- | input:
- | a0 = points to operand to be normalized
- | output:
- | L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
- | L_SCR1{4} = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
- | the normalized operand is placed back on the fsave stack
- mk_norm:
- clrl L_SCR1(%a6)
- bclrb #sign_bit,LOCAL_EX(%a0)
- sne LOCAL_SGN(%a0) |transform into internal extended format
- cmpib #0x2c,1+EXC_VEC(%a6) |check if unimp
- bnes uns_data |branch if unsupp
- bsr uni_inst |call if unimp (opclass 0x0)
- bras reload
- uns_data:
- btstb #direction_bit,CMDREG1B(%a6) |check transfer direction
- bnes bit_set |branch if set (opclass 011)
- bsr uns_opx |call if opclass 0x0
- bras reload
- bit_set:
- bsr uns_op3 |opclass 011
- reload:
- cmpw #0x3fff,LOCAL_EX(%a0) |if exp > $3fff
- bgts end_mk | fpte15/ete15 already set to 0
- bsetb #4,L_SCR1(%a6) |else set fpte15/ete15 to 1
- | ;calling routine actually sets the
- | ;value on the stack (along with the
- | ;tag), since this routine doesn't
- | ;know if it should set ete15 or fpte15
- | ;ie, it doesn't know if this is the
- | ;src op or dest op.
- end_mk:
- bfclr LOCAL_SGN(%a0){#0:#8}
- beqs end_mk_pos
- bsetb #sign_bit,LOCAL_EX(%a0) |convert back to IEEE format
- end_mk_pos:
- rts
- |
- | CASE opclass 011 unsupp
- |
- uns_op3:
- bsr nrm_zero |normalize till msb = 1 or exp = zero
- btstb #7,LOCAL_HI(%a0) |if msb = 1
- bnes no_unfl |then branch
- set_unfl:
- orw #dnrm_tag,L_SCR1(%a6) |set denorm tag
- bsetb #unfl_bit,FPSR_EXCEPT(%a6) |set unfl exception bit
- no_unfl:
- rts
- |
- | CASE opclass 0x0 unsupp
- |
- uns_opx:
- bsr nrm_zero |normalize the number
- btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
- beqs uns_den |if clear then now have a denorm
- uns_nrm:
- orb #norm_tag,L_SCR1(%a6) |set tag to norm
- rts
- uns_den:
- orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
- rts
- |
- | CASE opclass 0x0 unimp
- |
- uni_inst:
- bsr nrm_zero
- btstb #7,LOCAL_HI(%a0) |check if integer bit (j-bit) is set
- beqs uni_den |if clear then now have a denorm
- uni_nrm:
- orb #norm_tag,L_SCR1(%a6) |set tag to norm
- rts
- uni_den:
- orb #dnrm_tag,L_SCR1(%a6) |set tag to denorm
- rts
- |
- | Decimal to binary conversion
- |
- | Special cases of inf and NaNs are completed outside of decbin.
- | If the input is an snan, the snan bit is not set.
- |
- | input:
- | ETEMP(a6) - points to packed decimal string in memory
- | output:
- | fp0 - contains packed string converted to extended precision
- | ETEMP - same as fp0
- unpack:
- movew CMDREG1B(%a6),%d0 |examine command word, looking for fmove's
- andw #0x3b,%d0
- beq move_unpack |special handling for fmove: must set FPSR_CC
- movew ETEMP(%a6),%d0 |get word with inf information
- bfextu %d0{#20:#12},%d1 |get exponent into d1
- cmpiw #0x0fff,%d1 |test for inf or NaN
- bnes try_zero |if not equal, it is not special
- bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
- cmpiw #7,%d1 |SE and y bits must be on for special
- bnes try_zero |if not on, it is not special
- |input is of the special cases of inf and NaN
- tstl ETEMP_HI(%a6) |check ms mantissa
- bnes fix_nan |if non-zero, it is a NaN
- tstl ETEMP_LO(%a6) |check ls mantissa
- bnes fix_nan |if non-zero, it is a NaN
- bra finish |special already on stack
- fix_nan:
- btstb #signan_bit,ETEMP_HI(%a6) |test for snan
- bne finish
- orl #snaniop_mask,USER_FPSR(%a6) |always set snan if it is so
- bra finish
- try_zero:
- movew ETEMP_EX+2(%a6),%d0 |get word 4
- andiw #0x000f,%d0 |clear all but last ni(y)bble
- tstw %d0 |check for zero.
- bne not_spec
- tstl ETEMP_HI(%a6) |check words 3 and 2
- bne not_spec
- tstl ETEMP_LO(%a6) |check words 1 and 0
- bne not_spec
- tstl ETEMP(%a6) |test sign of the zero
- bges pos_zero
- movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
- clrl ETEMP_HI(%a6)
- clrl ETEMP_LO(%a6)
- bra finish
- pos_zero:
- clrl ETEMP(%a6)
- clrl ETEMP_HI(%a6)
- clrl ETEMP_LO(%a6)
- bra finish
- not_spec:
- fmovemx %fp0-%fp1,-(%a7) |save fp0 - decbin returns in it
- bsr decbin
- fmovex %fp0,ETEMP(%a6) |put the unpacked sop in the fsave stack
- fmovemx (%a7)+,%fp0-%fp1
- fmovel #0,%FPSR |clr fpsr from decbin
- bra finish
- |
- | Special handling for packed move in: Same results as all other
- | packed cases, but we must set the FPSR condition codes properly.
- |
- move_unpack:
- movew ETEMP(%a6),%d0 |get word with inf information
- bfextu %d0{#20:#12},%d1 |get exponent into d1
- cmpiw #0x0fff,%d1 |test for inf or NaN
- bnes mtry_zero |if not equal, it is not special
- bfextu %d0{#17:#3},%d1 |get SE and y bits into d1
- cmpiw #7,%d1 |SE and y bits must be on for special
- bnes mtry_zero |if not on, it is not special
- |input is of the special cases of inf and NaN
- tstl ETEMP_HI(%a6) |check ms mantissa
- bnes mfix_nan |if non-zero, it is a NaN
- tstl ETEMP_LO(%a6) |check ls mantissa
- bnes mfix_nan |if non-zero, it is a NaN
- |input is inf
- orl #inf_mask,USER_FPSR(%a6) |set I bit
- tstl ETEMP(%a6) |check sign
- bge finish
- orl #neg_mask,USER_FPSR(%a6) |set N bit
- bra finish |special already on stack
- mfix_nan:
- orl #nan_mask,USER_FPSR(%a6) |set NaN bit
- moveb #nan_tag,STAG(%a6) |set stag to NaN
- btstb #signan_bit,ETEMP_HI(%a6) |test for snan
- bnes mn_snan
- orl #snaniop_mask,USER_FPSR(%a6) |set snan bit
- btstb #snan_bit,FPCR_ENABLE(%a6) |test for snan enabled
- bnes mn_snan
- bsetb #signan_bit,ETEMP_HI(%a6) |force snans to qnans
- mn_snan:
- tstl ETEMP(%a6) |check for sign
- bge finish |if clr, go on
- orl #neg_mask,USER_FPSR(%a6) |set N bit
- bra finish
- mtry_zero:
- movew ETEMP_EX+2(%a6),%d0 |get word 4
- andiw #0x000f,%d0 |clear all but last ni(y)bble
- tstw %d0 |check for zero.
- bnes mnot_spec
- tstl ETEMP_HI(%a6) |check words 3 and 2
- bnes mnot_spec
- tstl ETEMP_LO(%a6) |check words 1 and 0
- bnes mnot_spec
- tstl ETEMP(%a6) |test sign of the zero
- bges mpos_zero
- orl #neg_mask+z_mask,USER_FPSR(%a6) |set N and Z
- movel #0x80000000,ETEMP(%a6) |write neg zero to etemp
- clrl ETEMP_HI(%a6)
- clrl ETEMP_LO(%a6)
- bras finish
- mpos_zero:
- orl #z_mask,USER_FPSR(%a6) |set Z
- clrl ETEMP(%a6)
- clrl ETEMP_HI(%a6)
- clrl ETEMP_LO(%a6)
- bras finish
- mnot_spec:
- fmovemx %fp0-%fp1,-(%a7) |save fp0 ,fp1 - decbin returns in fp0
- bsr decbin
- fmovex %fp0,ETEMP(%a6)
- | ;put the unpacked sop in the fsave stack
- fmovemx (%a7)+,%fp0-%fp1
- finish:
- movew CMDREG1B(%a6),%d0 |get the command word
- andw #0xfbff,%d0 |change the source specifier field to
- | ;extended (was packed).
- movew %d0,CMDREG1B(%a6) |write command word back to fsave stack
- | ;we need to do this so the 040 will
- | ;re-execute the inst. without taking
- | ;another packed trap.
- fix_stag:
- |Converted result is now in etemp on fsave stack, now set the source
- |tag (stag)
- | if (ete =$7fff) then INF or NAN
- | if (etemp = $x.0----0) then
- | stag = INF
- | else
- | stag = NAN
- | else
- | if (ete = $0000) then
- | stag = ZERO
- | else
- | stag = NORM
- |
- | Note also that the etemp_15 bit (just right of the stag) must
- | be set accordingly.
- |
- movew ETEMP_EX(%a6),%d1
- andiw #0x7fff,%d1 |strip sign
- cmpw #0x7fff,%d1
- bnes z_or_nrm
- movel ETEMP_HI(%a6),%d1
- bnes is_nan
- movel ETEMP_LO(%a6),%d1
- bnes is_nan
- is_inf:
- moveb #0x40,STAG(%a6)
- movel #0x40,%d0
- rts
- is_nan:
- moveb #0x60,STAG(%a6)
- movel #0x60,%d0
- rts
- z_or_nrm:
- tstw %d1
- bnes is_nrm
- is_zro:
- | For a zero, set etemp_15
- moveb #0x30,STAG(%a6)
- movel #0x20,%d0
- rts
- is_nrm:
- | For a norm, check if the exp <= $3fff; if so, set etemp_15
- cmpiw #0x3fff,%d1
- bles set_bit15
- moveb #0,STAG(%a6)
- bras end_is_nrm
- set_bit15:
- moveb #0x10,STAG(%a6)
- end_is_nrm:
- movel #0,%d0
- end_fix:
- rts
- end_get:
- rts
- |end
|