[PATCH] Fix carry bug in 128-bit unsigned integer adding

Liu Yu Yu.Liu at freescale.com
Mon Jan 7 01:26:14 EST 2008


This bug exists in math emulation for powerpc.
The macro define are mainly used by multiplication.

When adding two unsigned operands ( r = x + y ),
the carry bit can be counted by whether r is less than x.
However, when adding three unsigned operands, this method does not work.

The original code below uses this method to count carry,
it apparently overlook the case of three operands. 
Assume all the operands is 32-bit wide,
( r = x + y + last_carry , x = 0, y = 0xffffffff, last_carry = 1),
then r is no less than x but it actually gets a carry.

I tried to fix this bug, but this patch seems not that pretty.
Are there any better ideas? 
Comments are always welcomed!


Signed-off-by: Liu Yu <Yu.Liu at freescale.com>
---
 arch/powerpc/math-emu/op-4.h |   22 ++++++++++++++--------
 1 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h
index fcdd6d0..93c7390 100644
--- a/arch/powerpc/math-emu/op-4.h
+++ b/arch/powerpc/math-emu/op-4.h
@@ -195,18 +195,24 @@
 
 #ifndef __FP_FRAC_ADD_4
 #define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  (r0 = x0 + y0,							\
-   r1 = x1 + y1 + (r0 < x0),						\
-   r2 = x2 + y2 + (r1 < x1),						\
-   r3 = x3 + y3 + (r2 < x2))
+   do {									\
+	_FP_W_TYPE _x0 = x0, _x1 = x1, _x2 = x2, _y1 = y1, _y2 = y2; 	\
+	r0 = x0 + y0;							\
+	r1 = x1 + y1 + (r0 < _x0);					\
+	r2 = x2 + y2 + (r1 < _x1 || (r1 == _x1 && !(_y1 + 1)));		\
+	r3 = x3 + y3 + (r2 < _x2 || (r2 == _x2 && !(_y2 + 1)));		\
+   } while(0)
 #endif
 
 #ifndef __FP_FRAC_SUB_4
 #define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  (r0 = x0 - y0,                                                        \
-   r1 = x1 - y1 - (r0 > x0),                                            \
-   r2 = x2 - y2 - (r1 > x1),                                            \
-   r3 = x3 - y3 - (r2 > x2))
+   do {									\
+	_FP_W_TYPE _x0 = x0, _x1 = x1, _x2 = x2, _y1 = y1, _y2 = y2; 	\
+	r0 = x0 - y0;							\
+	r1 = x1 - y1 - (r0 > _x0);					\
+	r2 = x2 - y2 - (r1 > _x1 || (r1 == _x1 && !(_y1 + 1)));		\
+	r3 = x3 - y3 - (r2 > _x2 || (r2 == _x2 && !(_y2 + 1)));		\
+   } while(0)
 #endif
 
 #ifndef __FP_FRAC_ADDI_4
-- 




More information about the Linuxppc-dev mailing list