[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [MiNT] MiNTLib for ColdFire
Here is a patch for the few floating point routines written in assembly
inside the MiNTLib. I used ifdefs everywhere, so absolutely nothing has been
changed in the 680x0 code, there will be no regression.
I wasn't familiar with the FPU, neither with IEEE-754. It appears that the
ColdFire has a basic FPU, with less instructions than the 68881. So I didn't
use the ColdFire FPU for the implementation of the 3 functions patched here.
I patched the basic 68000 versions, and I had big difficulties. In most
cases, ColdFire patches are easy to do (movem, add.w ...). But since
IEEE-754 requires a lot of bit-manipulation, the 68000 versions uses a lot
of tricks with BYTE and WORD optimizations, where the ColdFire is very bad.
In that case, it is necessary to have at least a basic understanding of the
whole code, in order to know what can be safely changed or not. That
floating point stuff gave me nightmares, but it seems to be OK now. I found
some testcases for these functions in the NewLib, they all pass, so the new
ColdFire implementation is probably mostly correct.
Next step will be... startup code.
Alan, you can commit this patch as well as the previous about other assembly
files. I you prefer, you can wait for all the patches before committing, it
doesn't matter.
--
Vincent Rivière
diff -aurN -x CVS mintlib.orig/mintlib/_normdf.S mintlib/mintlib/_normdf.S
--- mintlib.orig/mintlib/_normdf.S 2002-02-22 23:51:23.000000000 +0100
+++ mintlib/mintlib/_normdf.S 2009-05-27 21:59:43.125000000 +0200
@@ -67,8 +67,15 @@
| double __normdf(long long mant, int exp, int sign, int rbits);
___normdf:
lea sp@(4),a0 | parameter pointer
+#ifdef __mcoldfire__
+ lea sp@(-24),sp
+ moveml d2-d7,sp@ | save working registers
+ movel a0@+,d4 | get mantissa
+ movel a0@+,d5
+#else
moveml d2-d7,sp@- | save working registers
moveml a0@+,d4-d5 | get mantissa
+#endif
# ifdef __MSHORT__
movew a0@+,d0 | get exponent
@@ -93,6 +100,12 @@
| d0=u.exp, d2=u.sign, d1=rounding bits, d4/d5=mantissa
| registers d2-d7 must be saved on the stack !
___norm_df:
+#ifdef __mcoldfire__
+ movel #0xffff,d3 | clean high words of arguments
+ andl d3,d0
+ andl d3,d1
+ andl d3,d2
+#endif
movel d4,d3 | rounding and u.mant == 0 ?
orl d5,d3
jne 1f
@@ -108,45 +121,95 @@
swap d5
movew d5,d4
moveb d1,d5 | some doubt about this one !
+#ifdef __mcoldfire__
+ movew d5,d3
+ lsll #8,d3
+ movew d3,d5
+#else
lslw #8,d5
+#endif
clrw d1
+#ifdef __mcoldfire__
+ subl #16,d0 | account for swap
+#else
subw #16,d0 | account for swap
+#endif
jra 1b
2:
+#ifdef __mcoldfire__
+ andil #0xffffff00,d2 | sticky byte
+#else
clrb d2 | sticky byte
+#endif
movel #0xffe00000,d6
3: tstw d0 | divide (shift)
jle 0f | denormalized number
movel d4,d3
andl d6,d3 | or until no bits above 53
jeq 4f
+#ifdef __mcoldfire__
+0: addl #1,d0 | increment exponent
+ movew d4,d3 | backup bit 0 of highest long
+ lsrl #1,d4
+ lsrl #1,d5
+ lsrl #1,d1 | shift into rounding bits
+ btst #0,d3
+ jeq 33f
+ bset #31,d5
+ bset #7,d1
+33: orl d1,d2 | set sticky
+#else
0: addw #1,d0 | increment exponent
lsrl #1,d4
roxrl #1,d5
orb d1,d2 | set sticky
roxrb #1,d1 | shift into rounding bits
+#endif
jra 3b
4:
+#ifdef __mcoldfire__
+ andl #0xffffff01,d2
+ movel d2,d3
+ andil #1,d3
+ orl d3,d1 | make least sig bit sticky
+#else
andb #1,d2
orb d2,d1 | make least sig bit sticky
+#endif
asrl #1,d6 | #0xfff00000 -> d6
5: movel d4,d3 | multiply (shift) until
andl d6,d3 | one in implied position
jne 6f
+#ifdef __mcoldfire__
+ subl #1,d0 | decrement exponent
+#else
subw #1,d0 | decrement exponent
+#endif
jeq 6f | too small. store as denormalized number
+#ifdef __mcoldfire__
+ addl d1,d1 | some doubt about this one *
+#else
addb d1,d1 | some doubt about this one *
+#endif
addxl d5,d5
addxl d4,d4
jra 5b
6:
tstb d1 | check rounding bits
jge 8f | round down - no action neccessary
+#ifdef __mcoldfire__
+ cmpb #0x80,d1
+ jne 7f | round up
+ movew d5,d1 | tie case - round to even
+ | dont need rounding bits any more
+ andl #1,d1 | check if even
+#else
negb d1
jvc 7f | round up
movew d5,d1 | tie case - round to even
| dont need rounding bits any more
andw #1,d1 | check if even
+#endif
jeq 8f | mantissa is even - no action necessary
| fall through
7:
@@ -155,7 +218,11 @@
addxl d1,d4
tstw d0
jne 0f | renormalize if number was denormalized
+#ifdef __mcoldfire__
+ addl #1,d0 | correct exponent for denormalized numbers
+#else
addw #1,d0 | correct exponent for denormalized numbers
+#endif
jra 2b
0: movel d4,d3 | check for rounding overflow
asll #1,d6 | #0xffe00000 -> d3
@@ -170,16 +237,31 @@
cmpw #2047,d0
jge oflow
+#ifdef __mcoldfire__
+ swap d0 | map to upper word
+ lsll #4,d0 | re-position exponent
+ andil #0x7ff00000,d0
+ btst #15,d2
+ jeq 9f
+ bset #31,d0
+9:
+#else
lslw #5,d0 | re-position exponent - one bit too high
lslw #1,d2 | get X bit
roxrw #1,d0 | shift it into sign position
swap d0 | map to upper word
clrw d0
+#endif
andl #0x0fffff,d4 | top mantissa bits
orl d0,d4 | insert exponent and sign
movel d4,d0
movel d5,d1
+#ifdef __mcoldfire__
+ moveml sp@,d2-d7
+ lea sp@(24),sp
+#else
moveml sp@+,d2-d7
+#endif
rts
retz:
@@ -188,9 +270,17 @@
retzok:
moveq #0,d0 | return zero value
movel d0,d1
+#ifdef __mcoldfire__
+ movw d2,d0
+ swap d0
+ andil #0x80000000,d0
+0: moveml sp@,d2-d7
+ lea sp@(24),sp
+#else
lslw #1,d2 | set value of extension
roxrl #1,d0 | and move it to hight bit of d0
0: moveml sp@+,d2-d7
+#endif
rts
oflow:
@@ -204,12 +294,22 @@
#endif /* ERROR_CHECK */
| moveml pc@(__infinitydf),d0-d1 | return infinity value
+#ifdef __mcoldfire__
+ movel __infinitydf,d0 | return infinty value
+ movel __infinitydf+4,d1
+#else
moveml __infinitydf,d0-d1 | return infinty value
+#endif
tstw d2
jpl 1f
bset #31,d0
1:
+#ifdef __mcoldfire__
+ moveml sp@,d2-d7 | should really cause trap ?!? (mjr: why?)
+ lea sp@(24),sp
+#else
moveml sp@+,d2-d7 | should really cause trap ?!? (mjr: why?)
+#endif
rts
#endif /* __M68881__ */
diff -aurN -x CVS mintlib.orig/mintlib/frexp.S mintlib/mintlib/frexp.S
--- mintlib.orig/mintlib/frexp.S 2002-02-22 23:51:23.000000000 +0100
+++ mintlib/mintlib/frexp.S 2009-05-22 23:47:04.062500000 +0200
@@ -42,18 +42,31 @@
2: | return here when looping
swap d0 | sign and exponent into lower 16 bits
movew d0,d2 | set d2 for norm_df
+#ifdef __mcoldfire__
+ andil #0x7fff,d0 | kill sign bit
+ lsrl #4,d0
+#else
bclr #15,d0 | kill sign bit
lsrw #4,d0
+#endif
cmpw #BIAS8,d0 | get out of loop if finally (a1) in [0.5,1.0)
jeq 3f
moveq #0x0f,d1 | remove exponent from value.mantissa
+#ifdef __mcoldfire__
+ andl d2,d1 | four upper bits of value in d1
+#else
andb d2,d1 | four upper bits of value in d1
+#endif
bset #4,d1 | implied leading 1
tstw d0 | check for zero exponent
jne 1f
+#ifdef __mcoldfire__
+ addql #1,d0
+#else
addqw #1,d0
+#endif
bclr #4,d1 | nah, we do not need stinkin leadin 1
1: movew d1,a1@ | save results of our efforts
@@ -61,7 +74,11 @@
orl a1@(4),d1
jeq 3f | if zero, all done : exp = 0, num = 0.0
| sign of zero is correct
+#ifdef __mcoldfire__
+ subl #BIAS8,d0 | remove bias
+#else
subw #BIAS8,d0 | remove bias
+#endif
#ifdef __MSHORT__
addw d0,a0@ | add current exponent in
#else
@@ -72,7 +89,12 @@
movew #BIAS8,d0 | set bias for return value
clrw d1 | rounding = 0
pea L0 | call to norm_df (dirty, but dont ...
+#ifdef __mcoldfire__
+ lea sp@(-24),sp
+ moveml d2-d7,sp@ | ... need to copy with -mshort)
+#else
moveml d2-d7,sp@- | ... need to copy with -mshort)
+#endif
moveml a1@,d4-d5
jmp ___norm_df | normalize result
L0: | norm_df does not affect a0 or a1
diff -aurN -x CVS mintlib.orig/mintlib/ldexp.S mintlib/mintlib/ldexp.S
--- mintlib.orig/mintlib/ldexp.S 2002-02-22 23:51:24.000000000 +0100
+++ mintlib/mintlib/ldexp.S 2009-05-23 17:18:11.515625000 +0200
@@ -46,19 +46,37 @@
|-----------------------------------------------------------------------------
lea sp@(4),a1
+#ifdef __mcoldfire__
+ lea sp@(-24),sp
+ moveml d2-d7,sp@ | save d2-d7
+#else
moveml d2-d7,sp@- | save d2-d7
+#endif
movew a1@,d0 | extract value.exp
movew d0,d2 | extract value.sign
+#ifdef __mcoldfire__
+ andil #0x7fff,d0 | kill sign bit
+ lsrl #4,d0
+#else
bclr #15,d0 | kill sign bit
lsrw #4,d0
+#endif
moveq #0x0f,d3 | remove exponent from value.mantissa
+#ifdef __mcoldfire__
+ andl d2,d3 | four upper bits of value in d3
+#else
andb d2,d3 | four upper bits of value in d3
+#endif
bset #4,d3 | implied leading 1
tstw d0 | check for zero exponent
jne 1f
+#ifdef __mcoldfire__
+ addql #1,d0
+#else
addqw #1,d0
+#endif
bclr #4,d3 | nah, we do not need stinkin leadin 1
1: movew d3,a1@ | save results of our efforts
#ifdef __MSHORT__
@@ -80,8 +98,14 @@
retz:
moveq #0,d0 | zero return value
movel d0,d1
+#ifdef __mcoldfire__
+ btst #15,d2
+ jeq L0
+ bset #31,d0
+#else
lslw #1,d2 | transfer argument sign
roxrl #1,d0
+#endif
jra L0
rangerr:
@@ -95,12 +119,22 @@
addql #8,a7 |
#endif /* ERROR_CHECK */
+#ifdef __mcoldfire__
+ movel __infinitydf,d0 | return HUGE_VAL (same as in <math.h>)
+ movel __infinitydf+4,d1
+#else
moveml __infinitydf,d0-d1 | return HUGE_VAL (same as in <math.h>)
+#endif
tstw d2
jge L0
bset #31,d0
L0:
+#ifdef __mcoldfire__
+ moveml sp@,d2-d7 | pop saved reggies
+ lea sp@(24),sp
+#else
moveml sp@+,d2-d7 | pop saved reggies
+#endif
rts
#else /* __M68881__ || sfp004 */
diff -aurN -x CVS mintlib.orig/mintlib/modf.S mintlib/mintlib/modf.S
--- mintlib.orig/mintlib/modf.S 2002-02-22 23:51:24.000000000 +0100
+++ mintlib/mintlib/modf.S 2009-05-23 17:39:02.171875000 +0200
@@ -23,14 +23,26 @@
.globl _modf
_modf:
lea sp@(4),a0 | a0 -> float argument
+#ifdef __mcoldfire__
+ lea sp@(-24),sp
+ moveml d2-d7,sp@ | save d2-d7
+ movel a0@+,d0
+ movel a0@+,d1
+#else
moveml d2-d7,sp@- | save d2-d7
moveml a0@+,d0-d1
+#endif
movel a0@,a1 | a1 -> ipart result
movel d0,d2 | calculate exponent
swap d2
+#ifdef __mcoldfire__
+ andil #0x7fff,d2 | kill sign bit
+ lsrl #4,d2
+#else
bclr #15,d2 | kill sign bit
lsrw #4,d2 | exponent in lower 12 bits of d2
+#endif
cmpw #BIAS8,d2
jgt 1f | fabs(value) >= 1.0
@@ -39,12 +51,22 @@
clrl a1@ | make integer part 0
0:
+#ifdef __mcoldfire__
+ moveml sp@,d2-d7 | restore saved d2-d7
+ lea sp@(24),sp
+#else
moveml sp@+,d2-d7 | restore saved d2-d7
+#endif
rts
1:
+#ifdef __mcoldfire__
+ movel #BIAS8+53,d3
+ subl d2,d3 | compute position of "binary point"
+#else
movew #BIAS8+53,d3
subw d2,d3 | compute position of "binary point"
+#endif
jgt 2f | branch if we do have fractional part
moveml d0-d1,a1@ | store entire value as the integer part
@@ -58,7 +80,11 @@
cmpw d6,d3
jlt 3f | jump if "binary point" in a lower part
movel d0,d4
+#ifdef __mcoldfire__
+ subl d6,d3
+#else
subw d6,d3
+#endif
moveq #0,d6 | compute mask for splitting
bset d3,d6
negl d6
@@ -79,7 +105,13 @@
moveml d0-d1,a1@ | store computed integer part
swap d0
+#ifdef __mcoldfire__
+ movl d2,d3 | set registers for norm_df
+ movl d0,d2
+ movl d3,d0
+#else
exg d0,d2 | set registers for norm_df
+#endif
clrw d1 | rounding = 0
| | normalize fractional part
jmp ___norm_df | norm_df will pop d2/d7 we saved before