From a9faf34ba120d9d39ff0c7656ee3de12a110e22a Mon Sep 17 00:00:00 2001 From: Kurt Mahan Date: Wed, 31 Oct 2007 16:57:05 -0600 Subject: [PATCH] Core Coldfire/MCF5445x arch lib changes. LTIBName: mcfv4e-arch-lib-mods Signed-off-by: Kurt Mahan --- arch/m68k/lib/checksum.c | 124 +++++++++++++++++++++++ arch/m68k/lib/muldi3.c | 10 ++ arch/m68k/lib/semaphore.S | 25 +++++ arch/m68k/lib/string.c | 64 ++++++++++++ arch/m68k/lib/uaccess.c | 242 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 465 insertions(+), 0 deletions(-) --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -39,8 +39,131 @@ * computes a partial checksum, e.g. for TCP/UDP fragments */ +#ifdef CONFIG_COLDFIRE + +static inline unsigned short from32to16(unsigned long x) +{ + /* add up 16-bit and 16-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static unsigned long do_csum(const unsigned char *buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +__sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + return ~do_csum(iph, ihl*4); +} +EXPORT_SYMBOL(ip_fast_csum); + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ __wsum csum_partial(const void *buff, int len, __wsum sum) { + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + if (sum > result) + result += 1; + return result; +} +EXPORT_SYMBOL(csum_partial); + +/* + * copy from fs while checksumming, otherwise like csum_partial + */ + +__wsum +csum_partial_copy_from_user(const void __user *src, void *dst, int len, + __wsum sum, int *csum_err) +{ + if (csum_err) *csum_err = 0; + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} +EXPORT_SYMBOL(csum_partial_copy_from_user); + +/* + * copy from ds while checksumming, otherwise like csum_partial + */ + +__wsum +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +{ + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} +EXPORT_SYMBOL(csum_partial_copy_nocheck); + +#else /* !CONFIG_COLDFIRE */ + +unsigned int +csum_partial(const unsigned char *buff, int len, unsigned int sum) +{ unsigned long tmp1, tmp2; /* * Experiments with ethernet and slip connections show that buff @@ -423,3 +546,4 @@ csum_partial_copy_nocheck(const void *sr return(sum); } EXPORT_SYMBOL(csum_partial_copy_nocheck); +#endif /* CONFIG_COLDFIRE */ --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -21,12 +21,22 @@ Boston, MA 02111-1307, USA. */ #define BITS_PER_UNIT 8 +#ifdef CONFIG_COLDFIRE +#define umul_ppmm(w1, w0, u, v) \ + do { \ + unsigned long long x; \ + x = (unsigned long long)u * v; \ + w0 = (unsigned long)(x & 0x00000000ffffffff); \ + w1 = (unsigned long)(x & 0xffffffff00000000) >> 32; \ + } while (0) +#else /* CONFIG_COLDFIRE */ #define umul_ppmm(w1, w0, u, v) \ __asm__ ("mulu%.l %3,%1:%0" \ : "=d" ((USItype)(w0)), \ "=d" ((USItype)(w1)) \ : "%0" ((USItype)(u)), \ "dmi" ((USItype)(v))) +#endif /* CONFIG_COLDFIRE */ #define __umulsidi3(u, v) \ ({DIunion __w; \ --- a/arch/m68k/lib/semaphore.S +++ b/arch/m68k/lib/semaphore.S @@ -16,11 +16,24 @@ * there is contention on the semaphore. */ ENTRY(__down_failed) +#ifndef CONFIG_COLDFIRE moveml %a0/%d0/%d1,-(%sp) +#else + movel %a0,-(%sp) + movel %d0,-(%sp) + movel %d1,-(%sp) +#endif movel %a1,-(%sp) jbsr __down movel (%sp)+,%a1 +#ifndef CONFIG_COLDFIRE moveml (%sp)+,%a0/%d0/%d1 +#else + movel (%sp)+,%d1 + movel (%sp)+,%d0 + movel (%sp)+,%a0 +#endif + rts ENTRY(__down_failed_interruptible) @@ -44,10 +57,22 @@ ENTRY(__down_failed_trylock) rts ENTRY(__up_wakeup) +#ifndef CONFIG_COLDFIRE moveml %a0/%d0/%d1,-(%sp) +#else + movel %a0,-(%sp) + movel %d0,-(%sp) + movel %d1,-(%sp) +#endif movel %a1,-(%sp) jbsr __up movel (%sp)+,%a1 +#ifndef CONFIG_COLDFIRE moveml (%sp)+,%a0/%d0/%d1 +#else + movel (%sp)+,%d1 + movel (%sp)+,%d0 + movel (%sp)+,%a0 +#endif rts --- a/arch/m68k/lib/string.c +++ b/arch/m68k/lib/string.c @@ -15,6 +15,7 @@ char *strcpy(char *dest, const char *src } EXPORT_SYMBOL(strcpy); +#ifndef CONFIG_COLDFIRE void *memset(void *s, int c, size_t count) { void *xs = s; @@ -143,6 +144,69 @@ void *memcpy(void *to, const void *from, } EXPORT_SYMBOL(memcpy); +#else /* CONFIG_COLDFIRE */ + +void *memset(void *s, int c, size_t count) +{ + unsigned long x; + void *originalTo; + + for (x = 0; x < count; x++) + *(unsigned char *)s++ = (unsigned char)c; + + return originalTo; +} +EXPORT_SYMBOL(memset); + +void *memcpy(void *to, const void *from, size_t n) +{ + void *xto = to; + size_t temp; + + if (!n) + return xto; + if ((long) to & 1) { + char *cto = to; + const char *cfrom = from; + *cto++ = *cfrom++; + to = cto; + from = cfrom; + n--; + } + if (n > 2 && (long) to & 2) { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + n -= 2; + } + temp = n >> 2; + if (temp) { + long *lto = to; + const long *lfrom = from; + for (; temp; temp--) + *lto++ = *lfrom++; + to = lto; + from = lfrom; + } + if (n & 2) { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + } + if (n & 1) { + char *cto = to; + const char *cfrom = from; + *cto = *cfrom; + } + return xto; +} +EXPORT_SYMBOL(memcpy); +#endif /* CONFIG_COLDFIRE */ + void *memmove(void *dest, const void *src, size_t n) { void *xdest = dest; --- a/arch/m68k/lib/uaccess.c +++ b/arch/m68k/lib/uaccess.c @@ -5,6 +5,7 @@ */ #include +#ifndef CONFIG_COLDFIRE #include unsigned long __generic_copy_from_user(void *to, const void __user *from, @@ -220,3 +221,244 @@ unsigned long __clear_user(void __user * return res; } EXPORT_SYMBOL(__clear_user); + +#else /* CONFIG_COLDFIRE */ + +#include + +unsigned long __generic_copy_from_user(void *to, const void *from, + unsigned long n) +{ + unsigned long tmp; + __asm__ __volatile__ + (" tstl %2\n" + " jeq 2f\n" + "1: movel (%1)+,%3\n" + " movel %3,(%0)+\n" + " subql #1,%2\n" + " jne 1b\n" + "2: movel %4,%2\n" + " bclr #1,%2\n" + " jeq 4f\n" + "3: movew (%1)+,%3\n" + " movew %3,(%0)+\n" + "4: bclr #0,%2\n" + " jeq 6f\n" + "5: moveb (%1)+,%3\n" + " moveb %3,(%0)+\n" + "6:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "7: movel %2,%%d0\n" + "71:clrl (%0)+\n" + " subql #1,%%d0\n" + " jne 71b\n" + " lsll #2,%2\n" + " addl %4,%2\n" + " btst #1,%4\n" + " jne 81f\n" + " btst #0,%4\n" + " jne 91f\n" + " jra 6b\n" + "8: addql #2,%2\n" + "81:clrw (%0)+\n" + " btst #0,%4\n" + " jne 91f\n" + " jra 6b\n" + "9: addql #1,%2\n" + "91:clrb (%0)+\n" + " jra 6b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,7b\n" + " .long 3b,8b\n" + " .long 5b,9b\n" + ".previous" + : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp) + : "d"(n & 3), "0"(to), "1"(from), "2"(n/4) + : "d0", "memory"); + return n; +} +EXPORT_SYMBOL(__generic_copy_from_user); + + +unsigned long __generic_copy_to_user(void *to, const void *from, + unsigned long n) +{ + unsigned long tmp; + __asm__ __volatile__ + (" tstl %2\n" + " jeq 3f\n" + "1: movel (%1)+,%3\n" + "22:movel %3,(%0)+\n" + "2: subql #1,%2\n" + " jne 1b\n" + "3: movel %4,%2\n" + " bclr #1,%2\n" + " jeq 4f\n" + " movew (%1)+,%3\n" + "24:movew %3,(%0)+\n" + "4: bclr #0,%2\n" + " jeq 5f\n" + " moveb (%1)+,%3\n" + "25:moveb %3,(%0)+\n" + "5:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "60:addql #1,%2\n" + "6: lsll #2,%2\n" + " addl %4,%2\n" + " jra 5b\n" + "7: addql #2,%2\n" + " jra 5b\n" + "8: addql #1,%2\n" + " jra 5b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,60b\n" + " .long 22b,6b\n" + " .long 2b,6b\n" + " .long 24b,7b\n" + " .long 3b,60b\n" + " .long 4b,7b\n" + " .long 25b,8b\n" + " .long 5b,8b\n" + ".previous" + : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp) + : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4) + : "memory"); + return n; +} +EXPORT_SYMBOL(__generic_copy_to_user); + +/* + * Copy a null terminated string from userspace. + */ + +long strncpy_from_user(char *dst, const char *src, long count) +{ + long res = -EFAULT; + if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */ + return res; + if (count == 0) return count; + __asm__ __volatile__ + ("1: moveb (%2)+,%%d0\n" + "12:moveb %%d0,(%1)+\n" + " jeq 2f\n" + " subql #1,%3\n" + " jne 1b\n" + "2: subl %3,%0\n" + "3:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "4: movel %4,%0\n" + " jra 3b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,4b\n" + " .long 12b,4b\n" + ".previous" + : "=d"(res), "=a"(dst), "=a"(src), "=d"(count) + : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count) + : "d0", "memory"); + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char *src, long n) +{ + long res = -EFAULT; + if (!(access_ok(VERIFY_READ, src, 1))) /* --tym-- */ + return res; + + res = -(long)src; + __asm__ __volatile__ + ("1:\n" + " tstl %2\n" + " jeq 3f\n" + "2: moveb (%1)+,%%d0\n" + "22:\n" + " subql #1,%2\n" + " tstb %%d0\n" + " jne 1b\n" + " jra 4f\n" + "3:\n" + " addql #1,%0\n" + "4:\n" + " addl %1,%0\n" + "5:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "6: moveq %3,%0\n" + " jra 5b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,6b\n" + " .long 22b,6b\n" + ".previous" + : "=d"(res), "=a"(src), "=d"(n) + : "i"(0), "0"(res), "1"(src), "2"(n) + : "d0"); + return res; +} +EXPORT_SYMBOL(strnlen_user); + + +/* + * Zero Userspace + */ + +unsigned long __clear_user(void *to, unsigned long n) +{ + __asm__ __volatile__ + (" tstl %1\n" + " jeq 3f\n" + "1: movel %3,(%0)+\n" + "2: subql #1,%1\n" + " jne 1b\n" + "3: movel %2,%1\n" + " bclr #1,%1\n" + " jeq 4f\n" + "24:movew %3,(%0)+\n" + "4: bclr #0,%1\n" + " jeq 5f\n" + "25:moveb %3,(%0)+\n" + "5:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "61:addql #1,%1\n" + "6: lsll #2,%1\n" + " addl %2,%1\n" + " jra 5b\n" + "7: addql #2,%1\n" + " jra 5b\n" + "8: addql #1,%1\n" + " jra 5b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,61b\n" + " .long 2b,6b\n" + " .long 3b,61b\n" + " .long 24b,7b\n" + " .long 4b,7b\n" + " .long 25b,8b\n" + " .long 5b,8b\n" + ".previous" + : "=a"(to), "=d"(n) + : "r"(n & 3), "d"(0), "0"(to), "1"(n/4)); + return n; +} +EXPORT_SYMBOL(__clear_user); + +#endif /* CONFIG_COLDFIRE */ +