|
| 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
.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
bne opclass3 |branch if a fmove out (any kind)
btstb
beqs uns_notpacked
bfextu CMDREG1B(%a6){
cmpb
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
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){
cmpil
| ;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
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
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
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
beq end_getop |check for unsupported data types on the
| ;source operand
btstb
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
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
bnes is_double
is_single:
movew
bras common |goto the common code
is_double:
movew
common:
btstb
beqs pos
bset
pos:
movew %d1,ETEMP_EX(%a6)
| ;put exponent on stack
movew CMDREG1B(%a6),%d1
andw
orw
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){
movel
subl %d0,%d1
clrl %d0
bsetl %d1,%d0 |set up d0 as a dynamic register mask
fmovemx %d0,FPTEMP(%a6) |write to FPTEMP
btstb
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
tstb %d0 |check for normalized value
bnes end_getop |if inf/nan/zero leave get_op
movew FPTEMP_EX(%a6),%d0
andiw
cmpiw
bges end_getop |if >= $3fff, leave fpte15=0
orb
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){
cmpib
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
beqs set_mon |if bit 5 = 0 then monadic
btstl
beqs set_dya |if bit 4 = 0 then dyadic
andiw
cmpiw
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
sne LOCAL_SGN(%a0) |transform into internal extended format
cmpib
bnes uns_data |branch if unsupp
bsr uni_inst |call if unimp (opclass 0x0)
bras reload
uns_data:
btstb
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
bgts end_mk | fpte15/ete15 already set to 0
bsetb
| ;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){
beqs end_mk_pos
bsetb
end_mk_pos:
rts
|
| CASE opclass 011 unsupp
|
uns_op3:
bsr nrm_zero |normalize till msb = 1 or exp = zero
btstb
bnes no_unfl |then branch
set_unfl:
orw
bsetb
no_unfl:
rts
|
| CASE opclass 0x0 unsupp
|
uns_opx:
bsr nrm_zero |normalize the number
btstb
beqs uns_den |if clear then now have a denorm
uns_nrm:
orb
rts
uns_den:
orb
rts
|
| CASE opclass 0x0 unimp
|
uni_inst:
bsr nrm_zero
btstb
beqs uni_den |if clear then now have a denorm
uni_nrm:
orb
rts
uni_den:
orb
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
beq move_unpack |special handling for fmove: must set FPSR_CC
movew ETEMP(%a6),%d0 |get word with inf information
bfextu %d0{
cmpiw
bnes try_zero |if not equal, it is not special
bfextu %d0{
cmpiw
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
bne finish
orl
bra finish
try_zero:
movew ETEMP_EX+2(%a6),%d0 |get word 4
andiw
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
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
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{
cmpiw
bnes mtry_zero |if not equal, it is not special
bfextu %d0{
cmpiw
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
tstl ETEMP(%a6) |check sign
bge finish
orl
bra finish |special already on stack
mfix_nan:
orl
moveb
btstb
bnes mn_snan
orl
btstb
bnes mn_snan
bsetb
mn_snan:
tstl ETEMP(%a6) |check for sign
bge finish |if clr, go on
orl
bra finish
mtry_zero:
movew ETEMP_EX+2(%a6),%d0 |get word 4
andiw
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
movel
clrl ETEMP_HI(%a6)
clrl ETEMP_LO(%a6)
bras finish
mpos_zero:
orl
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
| ;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
cmpw
bnes z_or_nrm
movel ETEMP_HI(%a6),%d1
bnes is_nan
movel ETEMP_LO(%a6),%d1
bnes is_nan
is_inf:
moveb
movel
rts
is_nan:
moveb
movel
rts
z_or_nrm:
tstw %d1
bnes is_nrm
is_zro:
| For a zero, set etemp_15
moveb
movel
rts
is_nrm:
| For a norm, check if the exp <= $3fff; if so, set etemp_15
cmpiw
bles set_bit15
moveb
bras end_is_nrm
set_bit15:
moveb
end_is_nrm:
movel
end_fix:
rts
end_get:
rts
|end