[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