703 lines
21 KiB
Plaintext
703 lines
21 KiB
Plaintext
* $NetBSD: get_op.sa,v 1.4 2001/12/09 01:43:13 briggs Exp $
|
|
|
|
* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
|
|
* M68000 Hi-Performance Microprocessor Division
|
|
* M68040 Software Package
|
|
*
|
|
* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
|
|
* All rights reserved.
|
|
*
|
|
* THE SOFTWARE is provided on an "AS IS" basis and without warranty.
|
|
* To the maximum extent permitted by applicable law,
|
|
* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
|
|
* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
|
|
* PARTICULAR PURPOSE and any warranty against infringement with
|
|
* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
|
|
* and any accompanying written materials.
|
|
*
|
|
* To the maximum extent permitted by applicable law,
|
|
* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
|
|
* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
|
|
* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
|
|
* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
|
|
* SOFTWARE. Motorola assumes no responsibility for the maintenance
|
|
* and support of the SOFTWARE.
|
|
*
|
|
* You are hereby granted a copyright license to use, modify, and
|
|
* distribute the SOFTWARE so long as this entire notice is retained
|
|
* without alteration in any modified and/or redistributed versions,
|
|
* and that such modified versions are clearly identified as such.
|
|
* No licenses are granted by implication, estoppel or otherwise
|
|
* under any patents or trademarks of Motorola, Inc.
|
|
|
|
*
|
|
* 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 unnormormalized 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_executess the instruction.
|
|
*
|
|
|
|
GET_OP IDNT 2,1 Motorola 040 Floating Point Software Package
|
|
|
|
section 8
|
|
|
|
include fpsp.h
|
|
|
|
xdef PIRN,PIRZRM,PIRP
|
|
xdef SMALRN,SMALRZRM,SMALRP
|
|
xdef BIGRN,BIGRZRM,BIGRP
|
|
|
|
PIRN:
|
|
dc.l $40000000,$c90fdaa2,$2168c235 ;pi
|
|
PIRZRM:
|
|
dc.l $40000000,$c90fdaa2,$2168c234 ;pi
|
|
PIRP:
|
|
dc.l $40000000,$c90fdaa2,$2168c235 ;pi
|
|
|
|
*round to nearest
|
|
SMALRN:
|
|
dc.l $3ffd0000,$9a209a84,$fbcff798 ;log10(2)
|
|
dc.l $40000000,$adf85458,$a2bb4a9a ;e
|
|
dc.l $3fff0000,$b8aa3b29,$5c17f0bc ;log2(e)
|
|
dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
|
|
dc.l $00000000,$00000000,$00000000 ;0.0
|
|
* round to zero;round to negative infinity
|
|
SMALRZRM:
|
|
dc.l $3ffd0000,$9a209a84,$fbcff798 ;log10(2)
|
|
dc.l $40000000,$adf85458,$a2bb4a9a ;e
|
|
dc.l $3fff0000,$b8aa3b29,$5c17f0bb ;log2(e)
|
|
dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
|
|
dc.l $00000000,$00000000,$00000000 ;0.0
|
|
* round to positive infinity
|
|
SMALRP:
|
|
dc.l $3ffd0000,$9a209a84,$fbcff799 ;log10(2)
|
|
dc.l $40000000,$adf85458,$a2bb4a9b ;e
|
|
dc.l $3fff0000,$b8aa3b29,$5c17f0bc ;log2(e)
|
|
dc.l $3ffd0000,$de5bd8a9,$37287195 ;log10(e)
|
|
dc.l $00000000,$00000000,$00000000 ;0.0
|
|
|
|
*round to nearest
|
|
BIGRN:
|
|
dc.l $3ffe0000,$b17217f7,$d1cf79ac ;ln(2)
|
|
dc.l $40000000,$935d8ddd,$aaa8ac17 ;ln(10)
|
|
dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
|
|
|
|
xdef PTENRN
|
|
PTENRN:
|
|
dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
|
|
dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
|
|
dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
|
|
dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
|
|
dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
|
|
dc.l $40690000,$9DC5ADA8,$2B70B59E ;10 ^ 32
|
|
dc.l $40D30000,$C2781F49,$FFCFA6D5 ;10 ^ 64
|
|
dc.l $41A80000,$93BA47C9,$80E98CE0 ;10 ^ 128
|
|
dc.l $43510000,$AA7EEBFB,$9DF9DE8E ;10 ^ 256
|
|
dc.l $46A30000,$E319A0AE,$A60E91C7 ;10 ^ 512
|
|
dc.l $4D480000,$C9767586,$81750C17 ;10 ^ 1024
|
|
dc.l $5A920000,$9E8B3B5D,$C53D5DE5 ;10 ^ 2048
|
|
dc.l $75250000,$C4605202,$8A20979B ;10 ^ 4096
|
|
*round to minus infinity
|
|
BIGRZRM:
|
|
dc.l $3ffe0000,$b17217f7,$d1cf79ab ;ln(2)
|
|
dc.l $40000000,$935d8ddd,$aaa8ac16 ;ln(10)
|
|
dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
|
|
|
|
xdef PTENRM
|
|
PTENRM:
|
|
dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
|
|
dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
|
|
dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
|
|
dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
|
|
dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
|
|
dc.l $40690000,$9DC5ADA8,$2B70B59D ;10 ^ 32
|
|
dc.l $40D30000,$C2781F49,$FFCFA6D5 ;10 ^ 64
|
|
dc.l $41A80000,$93BA47C9,$80E98CDF ;10 ^ 128
|
|
dc.l $43510000,$AA7EEBFB,$9DF9DE8D ;10 ^ 256
|
|
dc.l $46A30000,$E319A0AE,$A60E91C6 ;10 ^ 512
|
|
dc.l $4D480000,$C9767586,$81750C17 ;10 ^ 1024
|
|
dc.l $5A920000,$9E8B3B5D,$C53D5DE5 ;10 ^ 2048
|
|
dc.l $75250000,$C4605202,$8A20979A ;10 ^ 4096
|
|
*round to positive infinity
|
|
BIGRP:
|
|
dc.l $3ffe0000,$b17217f7,$d1cf79ac ;ln(2)
|
|
dc.l $40000000,$935d8ddd,$aaa8ac17 ;ln(10)
|
|
dc.l $3fff0000,$80000000,$00000000 ;10 ^ 0
|
|
|
|
xdef PTENRP
|
|
PTENRP:
|
|
dc.l $40020000,$A0000000,$00000000 ;10 ^ 1
|
|
dc.l $40050000,$C8000000,$00000000 ;10 ^ 2
|
|
dc.l $400C0000,$9C400000,$00000000 ;10 ^ 4
|
|
dc.l $40190000,$BEBC2000,$00000000 ;10 ^ 8
|
|
dc.l $40340000,$8E1BC9BF,$04000000 ;10 ^ 16
|
|
dc.l $40690000,$9DC5ADA8,$2B70B59E ;10 ^ 32
|
|
dc.l $40D30000,$C2781F49,$FFCFA6D6 ;10 ^ 64
|
|
dc.l $41A80000,$93BA47C9,$80E98CE0 ;10 ^ 128
|
|
dc.l $43510000,$AA7EEBFB,$9DF9DE8E ;10 ^ 256
|
|
dc.l $46A30000,$E319A0AE,$A60E91C7 ;10 ^ 512
|
|
dc.l $4D480000,$C9767586,$81750C18 ;10 ^ 1024
|
|
dc.l $5A920000,$9E8B3B5D,$C53D5DE6 ;10 ^ 2048
|
|
dc.l $75250000,$C4605202,$8A20979B ;10 ^ 4096
|
|
|
|
xref nrm_zero
|
|
xref decbin
|
|
xref round
|
|
|
|
xdef get_op
|
|
xdef uns_getop
|
|
xdef uni_getop
|
|
get_op:
|
|
clr.b DY_MO_FLG(a6)
|
|
tst.b UFLG_TMP(a6) ;test flag for unsupp/unimp state
|
|
beq.b short_uni_getop
|
|
|
|
uns_getop:
|
|
btst.b #direction_bit,CMDREG1B(a6)
|
|
bne.w opclass3 ;branch if a fmove out (any kind)
|
|
btst.b #6,CMDREG1B(a6)
|
|
beq.b uns_notpacked
|
|
|
|
bfextu CMDREG1B(a6){3:3},d0
|
|
cmp.b #3,d0
|
|
beq.w pack_source ;check for a packed src op, branch if so
|
|
uns_notpacked:
|
|
bsr chk_dy_mo ;set the dyadic/monadic flag
|
|
tst.b DY_MO_FLG(a6)
|
|
beq.b src_op_ck ;if monadic, go check src op
|
|
* ;else, check dst op (fall through)
|
|
|
|
btst.b #7,DTAG(a6)
|
|
beq.b src_op_ck ;if dst op is norm, check src op
|
|
bra.b dst_ex_dnrm ;else, handle destination unnorm/dnrm
|
|
|
|
uni_getop:
|
|
short_uni_getop:
|
|
bfextu CMDREG1B(a6){0:6},d0 ;get opclass and src fields
|
|
cmpi.l #$17,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.w not_fmovecr ;handle fmovecr as an unimplemented inst
|
|
rts
|
|
|
|
not_fmovecr:
|
|
btst.b #E1,E_BYTE(a6) ;if set, there is a packed operand
|
|
bne.w pack_source ;check for packed src op, branch if so
|
|
|
|
* The following lines of are coded to optimize on normalized operands
|
|
move.b STAG(a6),d0
|
|
or.b DTAG(a6),d0 ;check if either of STAG/DTAG msb set
|
|
bmi.b dest_op_ck ;if so, some op needs to be fixed
|
|
rts
|
|
|
|
dest_op_ck:
|
|
btst.b #7,DTAG(a6) ;check for unsupported data types in
|
|
beq.b src_op_ck ;the destination, if not, check src op
|
|
bsr chk_dy_mo ;set dyadic/monadic flag
|
|
tst.b DY_MO_FLG(a6) ;
|
|
beq.b src_op_ck ;if monadic, check src op
|
|
*
|
|
* At this point, destination has an extended denorm or unnorm.
|
|
*
|
|
dst_ex_dnrm:
|
|
move.w FPTEMP_EX(a6),d0 ;get destination exponent
|
|
andi.w #$7fff,d0 ;mask sign, check if exp = 0000
|
|
beq.b 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
|
|
lea.l 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
|
|
*
|
|
move.b L_SCR1(a6),DTAG(a6) ;write the new tag & fpte15
|
|
* ;to the fsave stack and fall
|
|
* ;through to check source operand
|
|
*
|
|
src_op_ck:
|
|
btst.b #7,STAG(a6)
|
|
beq.w end_getop ;check for unsupported data types on the
|
|
* ;source operand
|
|
btst.b #5,STAG(a6)
|
|
bne.b src_sd_dnrm ;if bit 5 set, handle sgl/dbl denorms
|
|
*
|
|
* At this point only unnorms or extended denorms are possible.
|
|
*
|
|
src_ex_dnrm:
|
|
move.w ETEMP_EX(a6),d0 ;get source exponent
|
|
andi.w #$7fff,d0 ;mask sign, check if exp = 0000
|
|
beq.w end_getop ;if denorm then exit, denorms are
|
|
* ;handled in do_func
|
|
lea.l 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
|
|
*
|
|
move.b 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:
|
|
btst.b #4,CMDREG1B(a6) ;differentiate between sgl/dbl denorm
|
|
bne.b is_double
|
|
is_single:
|
|
move.w #$3f81,d1 ;write bias for sgl denorm
|
|
bra.b common ;goto the common code
|
|
is_double:
|
|
move.w #$3c01,d1 ;write the bias for a dbl denorm
|
|
common:
|
|
btst.b #sign_bit,ETEMP_EX(a6) ;grab sign bit of mantissa
|
|
beq.b pos
|
|
bset #15,d1 ;set sign bit because it is negative
|
|
pos:
|
|
move.w d1,ETEMP_EX(a6)
|
|
* ;put exponent on stack
|
|
|
|
move.w CMDREG1B(a6),d1
|
|
and.w #$e3ff,d1 ;clear out source specifier
|
|
or.w #$0800,d1 ;set source specifier to extended prec
|
|
move.w d1,CMDREG1B(a6) ;write back to the command word in stack
|
|
* ;this is needed to fix unsupp data stack
|
|
lea.l ETEMP(a6),a0 ;point a0 to sop
|
|
|
|
bsr mk_norm ;convert sgl/dbl denorm to norm
|
|
move.b 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:
|
|
move.l FPTEMP_LO(a6),ETEMP(a6) ;write ms part of packed
|
|
* ;number to etemp slot
|
|
bsr chk_dy_mo ;set dyadic/monadic flag
|
|
bsr unpack
|
|
|
|
tst.b DY_MO_FLG(a6)
|
|
beq.b end_getop ;if monadic, exit
|
|
* ;else, fix FPTEMP
|
|
pack_dya:
|
|
bfextu CMDREG1B(a6){6:3},d0 ;extract dest fp reg
|
|
move.l #7,d1
|
|
sub.l d0,d1
|
|
clr.l d0
|
|
bset.l d1,d0 ;set up d0 as a dynamic register mask
|
|
fmovem.x d0,FPTEMP(a6) ;write to FPTEMP
|
|
|
|
btst.b #7,DTAG(a6) ;check dest tag for unnorm or denorm
|
|
bne.w dst_ex_dnrm ;else, handle the unnorm or ext denorm
|
|
*
|
|
* Dest is not denormalized. Check for norm, and set fpte15
|
|
* accordingly.
|
|
*
|
|
move.b DTAG(a6),d0
|
|
andi.b #$f0,d0 ;strip to only dtag:fpte15
|
|
tst.b d0 ;check for normalized value
|
|
bne.b end_getop ;if inf/nan/zero leave get_op
|
|
move.w FPTEMP_EX(a6),d0
|
|
andi.w #$7fff,d0
|
|
cmpi.w #$3fff,d0 ;check if fpte15 needs setting
|
|
bge.b end_getop ;if >= $3fff, leave fpte15=0
|
|
or.b #$10,DTAG(a6)
|
|
bra.b end_getop
|
|
|
|
*
|
|
* At this point, it is either an fmoveout packed, unnorm or denorm
|
|
*
|
|
opclass3:
|
|
clr.b DY_MO_FLG(a6) ;set dyadic/monadic flag to monadic
|
|
bfextu CMDREG1B(a6){4:2},d0
|
|
cmpi.b #3,d0
|
|
bne.w 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
|
|
* unuspported data type exception. Set if dyadic.
|
|
*
|
|
chk_dy_mo:
|
|
move.w CMDREG1B(a6),d0
|
|
btst.l #5,d0 ;testing extension command word
|
|
beq.b set_mon ;if bit 5 = 0 then monadic
|
|
btst.l #4,d0 ;know that bit 5 = 1
|
|
beq.b set_dya ;if bit 4 = 0 then dyadic
|
|
andi.w #$007f,d0 ;get rid of all but extension bits {6:0}
|
|
cmpi.w #$0038,d0 ;if extension = $38 then fcmp (dyadic)
|
|
bne.b set_mon
|
|
set_dya:
|
|
st.b DY_MO_FLG(a6) ;set the inst flag type to dyadic
|
|
rts
|
|
set_mon:
|
|
clr.b 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:
|
|
clr.l L_SCR1(a6)
|
|
bclr.b #sign_bit,LOCAL_EX(a0)
|
|
sne LOCAL_SGN(a0) ;transform into internal extended format
|
|
|
|
cmpi.b #$2c,1+EXC_VEC(a6) ;check if unimp
|
|
bne.b uns_data ;branch if unsupp
|
|
bsr uni_inst ;call if unimp (opclass 0x0)
|
|
bra.b reload
|
|
uns_data:
|
|
btst.b #direction_bit,CMDREG1B(a6) ;check transfer direction
|
|
bne.b bit_set ;branch if set (opclass 011)
|
|
bsr uns_opx ;call if opclass 0x0
|
|
bra.b reload
|
|
bit_set:
|
|
bsr uns_op3 ;opclass 011
|
|
reload:
|
|
cmp.w #$3fff,LOCAL_EX(a0) ;if exp > $3fff
|
|
bgt.b end_mk ; fpte15/ete15 already set to 0
|
|
bset.b #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}
|
|
beq.b end_mk_pos
|
|
bset.b #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
|
|
btst.b #7,LOCAL_HI(a0) ;if msb = 1
|
|
bne.b no_unfl ;then branch
|
|
set_unfl:
|
|
or.b #dnrm_tag,L_SCR1(a6) ;set denorm tag
|
|
bset.b #unfl_bit,FPSR_EXCEPT(a6) ;set unfl exception bit
|
|
no_unfl:
|
|
rts
|
|
*
|
|
* CASE opclass 0x0 unsupp
|
|
*
|
|
uns_opx:
|
|
bsr nrm_zero ;normalize the number
|
|
btst.b #7,LOCAL_HI(a0) ;check if integer bit (j-bit) is set
|
|
beq.b uns_den ;if clear then now have a denorm
|
|
uns_nrm:
|
|
or.b #norm_tag,L_SCR1(a6) ;set tag to norm
|
|
rts
|
|
uns_den:
|
|
or.b #dnrm_tag,L_SCR1(a6) ;set tag to denorm
|
|
rts
|
|
*
|
|
* CASE opclass 0x0 unimp
|
|
*
|
|
uni_inst:
|
|
bsr nrm_zero
|
|
btst.b #7,LOCAL_HI(a0) ;check if integer bit (j-bit) is set
|
|
beq.b uni_den ;if clear then now have a denorm
|
|
uni_nrm:
|
|
or.b #norm_tag,L_SCR1(a6) ;set tag to norm
|
|
rts
|
|
uni_den:
|
|
or.b #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:
|
|
move.w CMDREG1B(a6),d0 ;examine command word, looking for fmove's
|
|
and.w #$3b,d0
|
|
beq move_unpack ;special handling for fmove: must set FPSR_CC
|
|
|
|
move.w ETEMP(a6),d0 ;get word with inf information
|
|
bfextu d0{20:12},d1 ;get exponent into d1
|
|
cmpi.w #$0fff,d1 ;test for inf or NaN
|
|
bne.b try_zero ;if not equal, it is not special
|
|
bfextu d0{17:3},d1 ;get SE and y bits into d1
|
|
cmpi.w #7,d1 ;SE and y bits must be on for special
|
|
bne.b try_zero ;if not on, it is not special
|
|
*input is of the special cases of inf and NaN
|
|
tst.l ETEMP_HI(a6) ;check ms mantissa
|
|
bne.b fix_nan ;if non-zero, it is a NaN
|
|
tst.l ETEMP_LO(a6) ;check ls mantissa
|
|
bne.b fix_nan ;if non-zero, it is a NaN
|
|
bra.w finish ;special already on stack
|
|
fix_nan:
|
|
btst.b #signan_bit,ETEMP_HI(a6) ;test for snan
|
|
bne.w finish
|
|
or.l #snaniop_mask,USER_FPSR(a6) ;always set snan if it is so
|
|
bra.w finish
|
|
try_zero:
|
|
move.w ETEMP_EX+2(a6),d0 ;get word 4
|
|
andi.w #$000f,d0 ;clear all but last ni(y)bble
|
|
tst.w d0 ;check for zero.
|
|
bne.w not_spec
|
|
tst.l ETEMP_HI(a6) ;check words 3 and 2
|
|
bne.w not_spec
|
|
tst.l ETEMP_LO(a6) ;check words 1 and 0
|
|
bne.w not_spec
|
|
tst.l ETEMP(a6) ;test sign of the zero
|
|
bge.b pos_zero
|
|
move.l #$80000000,ETEMP(a6) ;write neg zero to etemp
|
|
clr.l ETEMP_HI(a6)
|
|
clr.l ETEMP_LO(a6)
|
|
bra.w finish
|
|
pos_zero:
|
|
clr.l ETEMP(a6)
|
|
clr.l ETEMP_HI(a6)
|
|
clr.l ETEMP_LO(a6)
|
|
bra.w finish
|
|
|
|
not_spec:
|
|
fmovem.x fp0-fp1,-(a7) ;save fp0 - decbin returns in it
|
|
bsr decbin
|
|
fmove.x fp0,ETEMP(a6) ;put the unpacked sop in the fsave stack
|
|
fmovem.x (a7)+,fp0-fp1
|
|
fmove.l #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:
|
|
move.w ETEMP(a6),d0 ;get word with inf information
|
|
bfextu d0{20:12},d1 ;get exponent into d1
|
|
cmpi.w #$0fff,d1 ;test for inf or NaN
|
|
bne.b mtry_zero ;if not equal, it is not special
|
|
bfextu d0{17:3},d1 ;get SE and y bits into d1
|
|
cmpi.w #7,d1 ;SE and y bits must be on for special
|
|
bne.b mtry_zero ;if not on, it is not special
|
|
*input is of the special cases of inf and NaN
|
|
tst.l ETEMP_HI(a6) ;check ms mantissa
|
|
bne.b mfix_nan ;if non-zero, it is a NaN
|
|
tst.l ETEMP_LO(a6) ;check ls mantissa
|
|
bne.b mfix_nan ;if non-zero, it is a NaN
|
|
*input is inf
|
|
or.l #inf_mask,USER_FPSR(a6) ;set I bit
|
|
tst.l ETEMP(a6) ;check sign
|
|
bge.w finish
|
|
or.l #neg_mask,USER_FPSR(a6) ;set N bit
|
|
bra.w finish ;special already on stack
|
|
mfix_nan:
|
|
or.l #nan_mask,USER_FPSR(a6) ;set NaN bit
|
|
move.b #nan_tag,STAG(a6) ;set stag to NaN
|
|
btst.b #signan_bit,ETEMP_HI(a6) ;test for snan
|
|
bne.b mn_snan
|
|
or.l #snaniop_mask,USER_FPSR(a6) ;set snan bit
|
|
btst.b #snan_bit,FPCR_ENABLE(a6) ;test for snan enabled
|
|
bne.b mn_snan
|
|
bset.b #signan_bit,ETEMP_HI(a6) ;force snans to qnans
|
|
mn_snan:
|
|
tst.l ETEMP(a6) ;check for sign
|
|
bge.w finish ;if clr, go on
|
|
or.l #neg_mask,USER_FPSR(a6) ;set N bit
|
|
bra.w finish
|
|
|
|
mtry_zero:
|
|
move.w ETEMP_EX+2(a6),d0 ;get word 4
|
|
andi.w #$000f,d0 ;clear all but last ni(y)bble
|
|
tst.w d0 ;check for zero.
|
|
bne.b mnot_spec
|
|
tst.l ETEMP_HI(a6) ;check words 3 and 2
|
|
bne.b mnot_spec
|
|
tst.l ETEMP_LO(a6) ;check words 1 and 0
|
|
bne.b mnot_spec
|
|
tst.l ETEMP(a6) ;test sign of the zero
|
|
bge.b mpos_zero
|
|
or.l #neg_mask+z_mask,USER_FPSR(a6) ;set N and Z
|
|
move.l #$80000000,ETEMP(a6) ;write neg zero to etemp
|
|
clr.l ETEMP_HI(a6)
|
|
clr.l ETEMP_LO(a6)
|
|
bra.b finish
|
|
mpos_zero:
|
|
or.l #z_mask,USER_FPSR(a6) ;set Z
|
|
clr.l ETEMP(a6)
|
|
clr.l ETEMP_HI(a6)
|
|
clr.l ETEMP_LO(a6)
|
|
bra.b finish
|
|
|
|
mnot_spec:
|
|
fmovem.x fp0-fp1,-(a7) ;save fp0 ,fp1 - decbin returns in fp0
|
|
bsr decbin
|
|
fmove.x fp0,ETEMP(a6)
|
|
* ;put the unpacked sop in the fsave stack
|
|
fmovem.x (a7)+,fp0-fp1
|
|
|
|
finish:
|
|
move.w CMDREG1B(a6),d0 ;get the command word
|
|
and.w #$fbff,d0 ;change the source specifier field to
|
|
* ;extended (was packed).
|
|
move.w 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.
|
|
*
|
|
move.w ETEMP_EX(a6),d1
|
|
andi.w #$7fff,d1 ;strip sign
|
|
cmp.w #$7fff,d1
|
|
bne.b z_or_nrm
|
|
move.l ETEMP_HI(a6),d1
|
|
bne.b is_nan
|
|
move.l ETEMP_LO(a6),d1
|
|
bne.b is_nan
|
|
is_inf:
|
|
move.b #$40,STAG(a6)
|
|
move.l #$40,d0
|
|
rts
|
|
is_nan:
|
|
move.b #$60,STAG(a6)
|
|
move.l #$60,d0
|
|
rts
|
|
z_or_nrm:
|
|
tst.w d1
|
|
bne.b is_nrm
|
|
is_zro:
|
|
* For a zero, set etemp_15
|
|
move.b #$30,STAG(a6)
|
|
move.l #$20,d0
|
|
rts
|
|
is_nrm:
|
|
* For a norm, check if the exp <= $3fff; if so, set etemp_15
|
|
cmpi.w #$3fff,d1
|
|
ble.b set_bit15
|
|
clr.b STAG(a6)
|
|
bra.b end_is_nrm
|
|
set_bit15:
|
|
move.b #$10,STAG(a6)
|
|
end_is_nrm:
|
|
clr.l d0
|
|
end_fix:
|
|
rts
|
|
|
|
end_get:
|
|
rts
|
|
end
|