home *** CD-ROM | disk | FTP | other *** search
- #
- # Floating point support code. What a crock!
- #
- # A float looks like:
- #
- # |S|E.x.p ... |M.a.n.t.i.s.s.a ... |
- # +-+----------+--------------------+
- #
- # where s is the sign bit, Exp is 8 bits of exponent, interpreted
- # as E + 126, and Mantissa is 23 bits of fraction, with a
- # hidden bit. The point is to the left of the hidden bit.
- # Doubles have another word of mantissa following.
- #
- # All these routines have calling sequences like c routines,
- # ie args on stack in backwards order, return values in d0
- #
-
- # union double_di { double d; int i[2]; };
- # union flt_or_int { int i; float f; };
- #
- ## #ifdef L_divdf3
- ## double
- ## _divdf3 (a, b)
- ## double a, b;
- ## {
- ## return a / b;
- ## }
- ## #endif
- #.text
- # .even
- #.globl ___divdf3
- #__divdf3:
- # movel sp@(12),sp@-
- # movel sp@(8),sp@-
- # jsr __divsf3
- # addql #8,sp
- # clrl d1 | kludge!!!
- # rts | sigh
- ##
- ## #ifdef L_muldf3
- ## double
- ## _muldf3 (a, b)
- ## double a, b;
- ## {
- ## return a * b;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __muldf3
- #__muldf3:
- # movel sp@(12),sp@-
- # movel sp@(8),sp@-
- # jsr __mulsf3
- # addql #8,sp
- # clrl d1 | kludge!!!
- # rts | sigh
- ##
- ## #ifdef L_negdf2
- ## double
- ## _negdf2 (a)
- ## double a;
- ## {
- ## return -a;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __negdf2
- #__negdf2:
- # movel sp@(8),d1 | get a lo
- # movel sp@(4),d0 | get a hi
- # beq negdf2_z | zero, leave it
- # eorl #0x80000000,d0 | twiddle sign
- #negdf2_z:
- # rts
- ##
- ## #ifdef L_adddf3
- ## double
- ## _adddf3 (a, b)
- ## double a, b;
- ## {
- ## return a + b;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __adddf3
- #__adddf3:
- # movel sp@(12),sp@-
- # movel sp@(8),sp@-
- # jsr __addsf3
- # addql #8,sp
- # clrl d1 | kludge!!!
- # rts | sigh
- ##
- ## #ifdef L_subdf3
- ## double
- ## _subdf3 (a, b)
- ## double a, b;
- ## {
- ## return a - b;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __subdf3
- #__subdf3:
- # movel sp@(12),sp@-
- # movel sp@(8),sp@-
- # jsr __subsf3
- # addql #8,sp
- # clrl d1 | kludge!!!
- # rts | sigh
- ##
- ## #ifdef L_cmpdf2
- ## int
- ## _cmpdf2 (a, b)
- ## double a, b;
- ## {
- ## if (a > b)
- ## return 1;
- ## else if (a < b)
- ## return -1;
- ## return 0;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __cmpdf2
- #__cmpdf2:
- # movel sp@(4),d0 | get b hi
- # movel sp@(12),d1 | get a hi
- #|
- #| crockery. If both neg and not equal, this algorithm lose. find a better one!
- #|
- # bpl cmpdf2_p
- # tstl d0
- # bpl cmpdf2_p
- # cmpl d1,d0
- # bgt cmpdf2_m
- # blt cmpdf2_1
- # beq cmpdf2_z
- #cmpdf2_p:
- # cmpl d1,d0 | get a hi
- # beq cmpdf2_z | if eq, return 0
- # bgt cmpdf2_1 | if greater, return 1
- #cmpdf2_m:
- # movel #-1,d0 | else return -1
- # rts
- #cmpdf2_z:
- # clrl d0
- # rts
- #cmpdf2_1:
- # movel #1,d0
- # rts | sigh
- ##
- ## #ifdef L_fixunsdfsi
- ## _fixunsdfsi (a)
- ## double a;
- ## {
- ## return (unsigned int) a;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __fixunsdfsi
- #__fixunsdfsi:
- # clrl d0
- # clrl d1
- # rts | sigh
- ##
- ## #ifdef L_fixunsdfdi
- ## double
- ## _fixunsdfdi (a)
- ## double a;
- ## {
- ## union double_di u;
- ## u.i[LOW] = (unsigned int) a;
- ## u.i[HIGH] = 0;
- ## return u.d;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __fixunsdfdi
- #__fixunsdfdi:
- # clrl d0
- # clrl d1
- # rts | sigh
- ##
- ## #ifdef L_fixdfsi
- ## _fixdfsi (a)
- ## double a;
- ## {
- ## return (int) a;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __fixdfsi
- #__fixdfsi:
- # link a6,#0
- # movel d2,sp@- | save reg
- # clrl d2 | sign flag
- # movel a6@(8),d0 | get the float
- # beq fixdfsi_ret
- # bpl fixdfsi_1
- # addql #1,d2
- #fixdfsi_1:
- # movel d0,d1 | snag the exp
- # lsrl #7,d1
- # lsrl #8,d1
- # lsrl #8,d1
- # andl #0xFF,d1
- # subl #126,d1
- # andl #0x7FFFFF,d0 | zap cruft
- # orl #0x800000,d0 | put back hidden bit
- #|
- #| at this point the mantissa looks like 2^24 * integer value.
- #| if Exp is 24, were done. If its less, we shift right,
- #| else left
- #|
- #fixdfsi_2:
- # cmpl #24,d1
- # beq fixdfsi_4 | were done
- # bmi fixdfsi_3 | less, shift right
- # lsll #1,d0 | greater, shift it left one
- # subql #1,d1 | and dec exp
- # bra fixdfsi_2
- #fixdfsi_3:
- # lsrl #1,d0 | shift right one
- # addql #1,d1 | and inc exp
- # bra fixdfsi_2
- #fixdfsi_4:
- # tstl d2 | negative?
- # beq fixdfsi_ret
- # negl d0
- #fixdfsi_ret:
- # movel sp@+,d2 | get d2 back
- # unlk a6
- # rts
- ##
- ## #ifdef L_fixdfdi
- ## double
- ## _fixdfdi (a)
- ## double a;
- ## {
- ## union double_di u;
- ## u.i[LOW] = (int) a;
- ## u.i[HIGH] = (int) a < 0 ? -1 : 0;
- ## return u.d;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __fixdfdi
- #__fixdfdi:
- # clrl d0
- # clrl d1
- # rts | sigh
- ##
- ## #ifdef L_floatsidf
- ## double
- ## _floatsidf (a)
- ## int a;
- ## {
- ## return (double) a;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __floatsidf
- #__floatsidf:
- # link a6,#0 | set up frame
- # movel d2,sp@- | save d2; sign flag
- # clrl d2 | not negative yet
- # movel #24,d1 | exponent so far
- # movel a6@(8),d0 | get the int
- # beq floatsidf_ret | zero?
- # bpl floatsidf_1 | pos, its ok
- # negl d0 | negate it
- # addql #1,d2 | bump sign
- #floatsidf_1:
- #|
- #| normalize right if necessary
- #|
- # cmpl #0xFFFFFF,d0 | too big?
- # ble floatsidf_2 | nope, see if need to slide left
- # addql #1,d1 | bump exp
- # lsrl #1,d0 | and slide mantissa right one
- # bra floatsidf_1
- #floatsidf_2:
- # btst #23,d0 | got a bit up here yet?
- # bne floatsidf_3 | nope, go left
- # subql #1,d1 | dec exp
- # lsll #1,d0 | and slide mantissa left one
- # bra floatsidf_2
- #floatsidf_3:
- #|
- #| now put it all together
- #|
- # andl #0x7FFFFF,d0 | zap hidden bit
- # addl #126,d1 | offset exp
- # andl #0xFF,d1 | trim it
- # lsll #8,d1 | shift up
- # lsll #8,d1
- # lsll #7,d1
- # orl d1,d0 | stuff it in
- # tstl d2 | negative?
- # beq floatsidf_ret
- # orl #0x80000000,d0
- #floatsidf_ret:
- # movel sp@+,d2
- # clrl d1 | ???
- # unlk a6
- # rts | sigh
- ##
- ## #ifdef L_floatdidf
- ## double
- ## _floatdidf (u)
- ## union double_di u;
- ## {
- ## register double hi
- ## = ((double) u.i[HIGH]) * (double) 0x10000 * (double) 0x10000;
- ## register double low = (unsigned int) u.i[LOW];
- ## return hi + low;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __floatdidf
- #__floatdidf:
- # clrl d0
- # clrl d1
- # rts | sigh
- ##
- # #define INTIFY(FLOATVAL) (intify.f = (FLOATVAL), intify.i)
- #
- # #ifdef L_addsf3
- # int
- # _addsf3 (a, b)
- # union flt_or_int a, b;
- # {
- # union flt_or_int intify;
- # return INTIFY (a.f + b.f);
- # }
- # #endif
-
- .text
- .even
- .globl ___addsf3
- .globl __addsf3
- ___addsf3:
- __addsf3:
- link a6,#0 | dont need any locals
- moveml #0x3F00,sp@- | save all data registers
- movel a6@(8),d0 | get a
- beq addsf_ret_b | zero .. just return b
- movel #23,d6 | shift count
- movel d0,d2 | get the exponent
- lsrl d6,d2 | and shift right
- andl #0xFF,d2 | no sign bit
- subl #126,d2 | offset the exponent
- movel a6@(12),d1 | get b
- beq addsf_ret_a
- movel d1,d3 | get the exponent for b
- lsrl d6,d3 | and shift right, with implicit extend
- andl #0xFF,d3 | make sure we didnt get a sign bit
- subl #126,d3 | off set this one too
-
- andl #0x7FFFFF,d0 | mask a for mantissa
- orl #0x800000,d0 | and put in hidden bit
- tstl a6@(8) | test the original value
- bpl addsf_1 | pos, ok
- negl d0 | neg, negate the mantissa
- addsf_1:
- andl #0x7FFFFF,d1 | mask b for mantissa
- orl #0x800000,d1 | ditto
- tstl a6@(12) | test ...
- bpl addsf_2
- negl d1 | negate this one
- addsf_2:
- cmpl d2,d3 | compare Ea to Eb
- blt addsf_3 | Ea > Eb
-
- movel d3,d5 | get Eb
- subl d2,d5 | subtract Ea
- asrl d5,d0 | yielding count to shift Ma right
- movel d3,d5 | use this as resultant exponent
- bra addsf_4 | and go rejoin common part
- addsf_3:
- movel d2,d5 | get Ea
- subl d3,d5 | subtract Eb
- asrl d5,d1 | yielding count to shift Mb right
- movel d2,d5 | use this as resultant exponent
-
- addsf_4:
- clrl d7 | zap sign flag
- addl d1,d0 | add Mb to Ma
-
-
- beq addsf_z | zero? ok, go return zero
- bpl addsf_5 | positive? ok, go scale it
- negl d0 | negate Mr
- movel #1,d7 | remember sign
- addsf_5:
- btst #24,d0 | carry?
- beq addsf_6 | nope, its ok as is
- asrl #1,d0 | shift right one
- addql #1,d5 | inc exp
-
- | zzz check for overflow in here someplace
-
- addsf_6:
- btst #23,d0 | got a bit in the right place yet?
- bne addsf_7 | yes, were done
- lsll #1,d0 | shift left one
- subql #1,d5 | dec exponent
- bra addsf_6
- addsf_7:
- andl #0x7FFFFF,d0 | zap out hidden bit
- addl #126,d5 | add offset to exp
- andl #0xFF,d5 | zap to 8 bits
- movel #23,d6 | shift count
- lsll d6,d5 | shift the exp up
- orl d5,d0 | stick the exp in
- tstl d7 | negative?
- beq addsf_ret_a
- orl #0x80000000,d0 | yup, negate it
- bra addsf_ret_a
- addsf_z:
- clrl d0
- bra addsf_ret_a
- addsf_ret_b:
- movel a6@(12),d0
- addsf_ret_a:
- moveml sp@+,#0x00FC | snarf back all regs
- unlk a6
- rts | sigh
- #
- # #ifdef L_negsf2
- # int
- # _negsf2 (a)
- # union flt_or_int a;
- # {
- # union flt_or_int intify;
- # return INTIFY (-a.f);
- # }
- # #endif
-
- .text
- .even
- .globl ___negsf2
- .globl __negsf2
- ___negsf2:
- __negsf2:
- movel sp@(4),d0
- beq negsf2_z
- eorl #0x80000000,d0
- negsf2_z:
- rts | sigh
- #
- # #ifdef L_subsf3
- # int
- # _subsf3 (a, b)
- # union flt_or_int a, b;
- # {
- # union flt_or_int intify;
- # return INTIFY (a.f - b.f);
- # }
- # #endif
-
- .text
- .even
- .globl ___subsf3
- .globl __subsf3
- ___subsf3:
- __subsf3:
- tstl sp@(8) | kludge. just negate b and add
- beq subsf_bz | zero. dont bother
- eorl #0x80000000,sp@(8) | negate it
- jmp ___addsf3
- subsf_bz:
- movel sp@(4),d0
- rts
-
- #
- # #ifdef L_cmpsf2
- # int
- # _cmpsf2 (a, b)
- # union flt_or_int a, b;
- # {
- # union flt_or_int intify;
- # if (a.f > b.f)
- # return 1;
- # else if (a.f < b.f)
- # return -1;
- # return 0;
- # }
- # #endif
-
- .text
- .even
- .globl ___cmpsf2
- .globl __cmpsf2
- ___cmpsf2:
- __cmpsf2:
- movel sp@(4),d0
- movel sp@(12),d1 | get a hi
- |
- | crockery. If both neg and not equal, this algorithm lose. find a better one!
- |
- bpl cmpsf2_p
- tstl d0
- bpl cmpsf2_p
- cmpl d1,d0
- bgt cmpsf2_m
- blt cmpsf2_1
- beq cmpsf2_z
- cmpsf2_p:
- cmpl d1,d0
- beq cmpsf2_z
- bgt cmpsf2_1
- cmpsf2_m:
- movel #-1,d0
- rts
- cmpsf2_z:
- clrl d0
- rts
- cmpsf2_1:
- movel #1,d0
- rts | sigh
- #
- # #ifdef L_mulsf3
- # int
- # _mulsf3 (a, b)
- # union flt_or_int a, b;
- # {
- # union flt_or_int intify;
- # return INTIFY (a.f * b.f);
- # }
- # #endif
-
- .text
- .even
- .globl ___mulsf3
- .globl __mulsf3
- ___mulsf3:
- __mulsf3:
- |
- | multiply. take the numbers apart. shift each exponent down to
- | 16 bits. unsigned multiply those. shift that down to 24 bits.
- | exponent is Ea + Eb.
- |
-
- link a6,#-8 | 64 bit accum for mult
- moveml #0x3F00,sp@- | save all data registers
- movel a6@(8),d0 | get a
- beq mulsf3_z
- movel a6@(12),d1 | get b
- beq mulsf3_z
- movel #23,d6 | shift count
- movel d0,d2 | get the exponent
- lsrl d6,d2 | and shift right
- andl #0xFF,d2
- subl #126,d2 | offset the exponent
- movel d1,d3 | get the exponent for b
- lsrl d6,d3 | and shift right
- andl #0xFF,d2
- subl #126,d3 | off set this one too
-
- clrl d7 | negative result flag
- andl #0x7FFFFF,d0 | mask a for mantissa
- orl #0x800000,d0 | and put in hidden bit
- tstl a6@(8) | test the original value
- bpl mulsf3_1 | pos, ok
- eorl #1,d7 | remember negative
- mulsf3_1:
- andl #0x7FFFFF,d1 | mask b for mantissa
- orl #0x800000,d1 | ditto
- tstl a6@(12) | test ...
- bpl mulsf3_2
- eorl #1,d7
- mulsf3_2:
- | lsrl #8,d1 | shift this one down
- | lsrl #8,d0 | this one too...
- | mulu d1,d0 | do the multiply
-
- | beq mulsf3_ret | zero? ok, just return
- | lsrl #8,d0 | shift right again
-
- |
- | we have mantissas as follows:
- |
- | |...ah...|...al...| |...bh...|...bl...|
- |
- | product is composed as:
- |
- | |....al * bl....|
- | |....al * bh....|
- | |....ah * bl....|
- | |....ah * bh....|
- |
- | then take the 24 bit chunk thats 16 bits in.
-
- movel d0,d4
- andl #0xFFFF,d4 | al
- movel d1,d5
- andl #0xFFFF,d5 | bl
- mulu d5,d4 | thats al * bl
- movel d4,a6@(-4) | into the accum
- clrl a6@(-8) | zap the top part
-
- movel d0,d4
- andl #0xFFFF,d4 | al
- movel d1,d5
- movel #16,d6 | shift count
- lsrl d6,d5 | bh
- mulu d5,d4 | al * bh
- addl d4,a6@(-6)
-
- movel d0,d4
- lsrl d6,d4 | ah
- movel d1,d5
- andl #0xFFFF,d5 | bl
- mulu d5,d4 | ah * bl
- addl d4,a6@(-6)
-
- movel d0,d4
- lsrl d6,d4 | ah
- movel d1,d5
- lsrl d6,d5 | bh
- mulu d5,d4 | ah * bh
- addl d4,a6@(-8)
-
- movel a6@(-6),d0 | get the relevant part
- lsrl #8,d0 | and shift it down
-
- mulsf3_norm:
- btst #23,d0 | normalized?
- bne mulsf3_ok
- lsll #1,d0
- subql #1,d2
- bra mulsf3_norm
-
- mulsf3_ok:
- andl #0x7FFFFF,d0 | zap hidden bit
- addl d3,d2 | add Eb to Ea
- addl #126,d2 | fix offset
- andl #0xFF,d2 | whack to 8 bits
- movel #23,d6 | shift count
- lsll d6,d2 | shift up to right place
- orl d2,d0 | shove it in
- tstl d7 | sign neg?
- beq mulsf3_ret
- orl #0x80000000,d0 | set sign bit
- bra mulsf3_ret
- mulsf3_z:
- clrl d0
- mulsf3_ret:
- moveml sp@+,#0x00FC | snarf back all regs
- unlk a6
- rts | sigh
- #
- # #ifdef L_divsf3
- # int
- # _divsf3 (a, b)
- # union flt_or_int a, b;
- # {
- # union flt_or_int intify;
- # return INTIFY (a.f / b.f);
- # }
- # #endif
-
- .text
- .even
- .globl ___divsf3
- .globl __divsf3
- ___divsf3:
- __divsf3:
- |
- | divide. sort of like mult, exc we do shifts and subtracts to
- | do the division of the mantissa. resultant exponent is Ea - Eb.
- |
-
- link a6,#0 | dont need any locals
- moveml #0x3F00,sp@- | save all data registers
- movel a6@(8),d0 | get a
- movel a6@(12),d1 | get b
- movel #23,d6 | shift count
- movel d0,d2 | get the exponent
- lsrl d6,d2 | and shift right
- andl #0xFF,d2
- subl #127,d2 | offset the exponent
- movel d1,d3 | get the exponent for b
- lsrl d6,d3 | and shift right
- andl #0xFF,d3
- subl #127,d3 | off set this one too
-
- clrl d7 | negative result flag
- andl #0x7FFFFF,d0 | mask a for mantissa
- orl #0x800000,d0 | and put in hidden bit
- tstl a6@(8) | test the original value
- bpl divsf3_1 | pos, ok
- eorl #1,d7 | remember negative
- divsf3_1:
- andl #0x7FFFFF,d1 | mask b for mantissa
- orl #0x800000,d1 | ditto
- tstl a6@(12) | test ...
- bpl divsf3_2
- eorl #1,d7
- divsf3_2:
- |
- | for now, kludge. shift Ma left and Mb right, then do an unsigned divide
- | and shift the result left. Blech
- |
-
- | lsrl #8,d1 | shift this one down
- | lsll #7,d0 | this one up
- | divu d1,d0 | do the divide
- | andl #0xFFFF,d0 | and mask off cruft
-
- | beq divsf3_ret | zero? ok, just return
- | lsll #8,d0 | shift left again
-
- | same sort of trick as long divide, exc its easier here, cause
- | the numbers (mantissas) are already bit-aligned.
-
- clrl d4 | accumulator
- movel #0x800000,d5 | bit
- lsll #7,d0 | buy a little extra accuracy...
- lsll #7,d1
- divsf3_2a:
- cmpl d1,d0 | compare dividend to divisor
- bmi divsf3_2b | nope, no bit here
- orl d5,d4 | put in the bit
- subl d1,d0 | and subtract
- divsf3_2b:
- lsrl #1,d1 | slide divisor down
- lsrl #1,d5 | slide bit down
- bne divsf3_2a | and go round again
- movel d4,d0 | leave the result here
-
- divsf3_3:
- btst #23,d0 | right place yet?
- bne divsf3_4
- lsll #1,d0
- subql #1,d2
- bra divsf3_3
- divsf3_4:
- andl #0x7FFFFF,d0 | zap hidden bit
- subl d3,d2 | sub Eb from Ea
- addl #127,d2 | fix offset
- andl #0xFF,d2 | whack to 8 bits
- lsll d6,d2 | shift up to right place
- orl d2,d0 | shove it in
- tstl d7 | sign neg?
- beq divsf3_ret
- orl #0x80000000,d0 | set sign bit
- divsf3_ret:
- moveml sp@+,#0x00FC | snarf back all regs
- unlk a6
-
- rts | sigh
- ##
- ## #ifdef L_truncdfsf2
- ## int
- ## _truncdfsf2 (a)
- ## double a;
- ## {
- ## union flt_or_int intify;
- ## return INTIFY (a);
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __truncdfsf2
- #__truncdfsf2:
- # movel sp@(4),d0
- # rts
- #
- ##
- ## #ifdef L_extendsfdf2
- ## double
- ## _extendsfdf2 (a)
- ## union flt_or_int a;
- ## {
- ## union flt_or_int intify;
- ## return a.f;
- ## }
- ## #endif
- #
- #.text
- # .even
- #.globl __extendsfdf2
- #__extendsfdf2:
- # movel sp@(4),d0
- # clrl d1
- # rts | sigh
- # .even
- #.text
-
-