patch-2.0.7 linux/arch/alpha/lib/csum_partial_copy.c

Next file: linux/arch/i386/boot/compressed/misc.c
Previous file: linux/arch/alpha/kernel/lca.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.6/linux/arch/alpha/lib/csum_partial_copy.c linux/arch/alpha/lib/csum_partial_copy.c
@@ -8,10 +8,10 @@
  */
 
 #define ldq_u(x,y) \
-__asm__("ldq_u %0,%1":"=r" (x):"m" (*(unsigned long *)(y)))
+__asm__ __volatile__("ldq_u %0,%1":"=r" (x):"m" (*(unsigned long *)(y)))
 
 #define stq_u(x,y) \
-__asm__("stq_u %1,%0":"=m" (*(unsigned long *)(y)):"r" (x))
+__asm__ __volatile__("stq_u %1,%0":"=m" (*(unsigned long *)(y)):"r" (x))
 
 #define extql(x,y,z) \
 __asm__ __volatile__("extql %1,%2,%0":"=r" (z):"r" (x),"r" (y))
@@ -36,12 +36,11 @@
  */
 static inline unsigned long csum_partial_copy_aligned(
 	unsigned long *src, unsigned long *dst,
-	long len, unsigned long checksum)
+	long len, unsigned long checksum,
+	unsigned long word)
 {
-	unsigned long word, carry = 0;
+	unsigned long carry = 0;
 
-	len -= 8;
-	word = *src;
 	while (len >= 0) {
 		checksum += carry;
 		src++;
@@ -73,34 +72,33 @@
 static inline unsigned long csum_partial_copy_dest_aligned(
 	unsigned long *src, unsigned long *dst,
 	unsigned long soff,
-	long len, unsigned long checksum)
+	long len, unsigned long checksum,
+	unsigned long first)
 {
-	unsigned long first, word, carry = 0;
+	unsigned long word, carry = 0;
 
-	len -= 8;
-	first = src[0];
 	while (len >= 0) {
 		unsigned long second;
 
-		second = src[1];
+		ldq_u(second, src+1);
 		extql(first, soff, word);
 		len -= 8;
-		extqh(second, soff, first);
 		src++;
-		word |= first;
+		extqh(second, soff, first);
 		checksum += carry;
+		word |= first;
 		first = second;
 		checksum += word;
 		*dst = word;
-		carry = checksum < word;
 		dst++;
+		carry = checksum < word;
 	}
 	len += 8;
 	checksum += carry;
 	if (len) {
 		unsigned long tmp;
 		unsigned long second;
-		second = src[1];
+		ldq_u(second, src+1);
 		tmp = *dst;
 		extql(first, soff, word);
 		extqh(second, soff, first);
@@ -121,24 +119,22 @@
 static inline unsigned long csum_partial_copy_src_aligned(
 	unsigned long *src, unsigned long *dst,
 	unsigned long doff,
-	long len, unsigned long checksum)
+	long len, unsigned long checksum,
+	unsigned long word,
+	unsigned long partial_dest)
 {
-	unsigned long word, carry = 0;
-	unsigned long partial_dest;
+	unsigned long carry = 0;
 
-	partial_dest = *dst;
-	len -= 8;
 	mskql(partial_dest, doff, partial_dest);
-	word = *src;
 	while (len >= 0) {
 		unsigned long second_dest;
 
 		len -= 8;
+		insql(word, doff, second_dest);
 		checksum += carry;
+		stq_u(partial_dest | second_dest, dst);
 		src++;
 		checksum += word;
-		insql(word, doff, second_dest);
-		*dst = partial_dest | second_dest;
 		insqh(word, doff, partial_dest);
 		carry = checksum < word;
 		word = *src;
@@ -150,25 +146,27 @@
 		unsigned long second_dest;
 
 		mskql(word, len-doff, word);
-		len -= 8;
 		src++;
 		checksum += word;
 		insql(word, doff, second_dest);
-		*dst = partial_dest | second_dest;
-		insqh(word, doff, partial_dest);
+		stq_u(partial_dest | second_dest, dst);
 		carry = checksum < word;
-		word = *src;
-		dst++;
+		if (len) {
+			ldq_u(second_dest, dst+1);
+			insqh(word, doff, partial_dest);
+			mskqh(second_dest, len, second_dest);
+			stq_u(partial_dest | second_dest, dst+1);
+		}
 		checksum += carry;
 	} else if (len & 7) {
 		unsigned long second_dest;
-		second_dest = *dst;
+		ldq_u(second_dest, dst);
 		mskql(word, len-doff, word);
 		checksum += word;
 		mskqh(second_dest, len, second_dest);
 		carry = checksum < word;
 		insql(word, doff, word);
-		*dst = partial_dest | word | second_dest;
+		stq_u(partial_dest | word | second_dest, dst);
 		checksum += carry;
 	}
 	return checksum;
@@ -181,30 +179,27 @@
 static inline unsigned long csum_partial_copy_unaligned(
 	unsigned long * src, unsigned long * dst,
 	unsigned long soff, unsigned long doff,
-	long len, unsigned long checksum)
+	long len, unsigned long checksum,
+	unsigned long first, unsigned long partial_dest)
 {
-	unsigned long first, carry = 0;
-	unsigned long partial_dest;
+	unsigned long carry = 0;
 
-	partial_dest = dst[0];
-	len -= 8;
-	first = src[0];
 	mskql(partial_dest, doff, partial_dest);
 	while (len >= 0) {
 		unsigned long second, word;
 		unsigned long second_dest;
 
-		second = src[1];
+		ldq_u(second, src+1);
 		extql(first, soff, word);
-		len -= 8;
 		checksum += carry;
-		src++;
+		len -= 8;
 		extqh(second, soff, first);
+		src++;
 		word |= first;
 		first = second;
-		checksum += word;
 		insql(word, doff, second_dest);
-		*dst = partial_dest | second_dest;
+		checksum += word;
+		stq_u(partial_dest | second_dest, dst);
 		carry = checksum < word;
 		insqh(word, doff, partial_dest);
 		dst++;
@@ -214,35 +209,40 @@
 	if (len >= 0) {
 		unsigned long second, word;
 		unsigned long second_dest;
-
-		second = src[1];
+		
+		ldq_u(second, src+1);
 		extql(first, soff, word);
-		len -= 8;
-		src++;
 		extqh(second, soff, first);
 		word |= first;
+		src++;
 		first = second;
 		mskql(word, len-doff, word);
 		checksum += word;
 		insql(word, doff, second_dest);
-		*dst = partial_dest | second_dest;
 		carry = checksum < word;
-		insqh(word, doff, partial_dest);
-		dst++;
+		stq_u(partial_dest | second_dest, dst);
+		if (len) {
+			ldq_u(second_dest, dst+1);
+			insqh(word, doff, partial_dest);
+			mskqh(second_dest, len, second_dest);
+			stq_u(partial_dest | second_dest, dst+1);
+		}
+		checksum += carry;			
 	} else if (len & 7) {
 		unsigned long second, word;
 		unsigned long second_dest;
-		second = src[1];
+
+		ldq_u(second, src+1);
 		extql(first, soff, word);
 		extqh(second, soff, first);
 		word |= first;
-		second_dest = *dst;
+		ldq_u(second_dest, dst);
 		mskql(word, len-doff, word);
 		checksum += word;
 		mskqh(second_dest, len, second_dest);
 		carry = checksum < word;
 		insql(word, doff, word);
-		*dst = partial_dest | word | second_dest;
+		stq_u(partial_dest | word | second_dest, dst);
 		checksum += carry;
 	}
 	return checksum;
@@ -254,31 +254,35 @@
 	unsigned long soff = 7 & (unsigned long) src;
 	unsigned long doff = 7 & (unsigned long) dst;
 
-	src = (char *) (~7UL & (unsigned long) src);
-	dst = (char *) (~7UL & (unsigned long) dst);
 	if (len) {
-		if (!soff) {
-			if (!doff)
+		unsigned long first;
+		ldq_u(first, src);
+		if (!doff) {
+			if (!soff)
 				checksum = csum_partial_copy_aligned(
 					(unsigned long *) src,
 					(unsigned long *) dst,
-					len, checksum);
+					len-8, checksum, first);
 			else
-				checksum = csum_partial_copy_src_aligned(
+				checksum = csum_partial_copy_dest_aligned(
 					(unsigned long *) src,
 					(unsigned long *) dst,
-					doff, len, checksum);
+					soff, len-8, checksum, first);
 		} else {
-			if (!doff)
-				checksum = csum_partial_copy_dest_aligned(
+			unsigned long partial_dest;
+			ldq_u(partial_dest, dst);
+			if (!soff)
+				checksum = csum_partial_copy_src_aligned(
 					(unsigned long *) src,
 					(unsigned long *) dst,
-					soff, len, checksum);
+					doff, len-8, checksum,
+					first, partial_dest);
 			else
 				checksum = csum_partial_copy_unaligned(
 					(unsigned long *) src,
 					(unsigned long *) dst,
-					soff, doff, len, checksum);
+					soff, doff, len-8, checksum,
+					first, partial_dest);
 		}
 		/* 64 -> 33 bits */
 		checksum = (checksum & 0xffffffff) + (checksum >> 32);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov