Blackfin: move string functions to normal lib/ assembly
Robin Getz [Mon, 3 May 2010 17:23:20 +0000 (17:23 +0000)]
Since 'extern inline' doesn't work correctly in the context of the Linux
kernel (too many overriding defines), move the string functions to normal
lib/ assembly files (like the existing mem funcs).  This avoids the forced
inline all over the kernel and allows us to place them constantly in L1.

This also avoids some module failures when gcc inserts calls to string
functions but the kernel build system doesn't fully consult the library
archives.

Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>

arch/blackfin/Kconfig
arch/blackfin/include/asm/string.h
arch/blackfin/kernel/bfin_ksyms.c
arch/blackfin/lib/strcmp.S [new file with mode: 0644]
arch/blackfin/lib/strcmp.c [deleted file]
arch/blackfin/lib/strcpy.S [new file with mode: 0644]
arch/blackfin/lib/strcpy.c [deleted file]
arch/blackfin/lib/strncmp.S [new file with mode: 0644]
arch/blackfin/lib/strncmp.c [deleted file]
arch/blackfin/lib/strncpy.S [new file with mode: 0644]
arch/blackfin/lib/strncpy.c [deleted file]

index 405bdaa..7b9fc9c 100644 (file)
@@ -791,6 +791,34 @@ config MEMCPY_L1
          If enabled, the memcpy function is linked
          into L1 instruction memory. (less latency)
 
+config STRCMP_L1
+       bool "locate strcmp function in L1 Memory"
+       default y
+       help
+         If enabled, the strcmp function is linked
+         into L1 instruction memory (less latency).
+
+config STRNCMP_L1
+       bool "locate strncmp function in L1 Memory"
+       default y
+       help
+         If enabled, the strncmp function is linked
+         into L1 instruction memory (less latency).
+
+config STRCPY_L1
+       bool "locate strcpy function in L1 Memory"
+       default y
+       help
+         If enabled, the strcpy function is linked
+         into L1 instruction memory (less latency).
+
+config STRNCPY_L1
+       bool "locate strncpy function in L1 Memory"
+       default y
+       help
+         If enabled, the strncpy function is linked
+         into L1 instruction memory (less latency).
+
 config SYS_BFIN_SPINLOCK_L1
        bool "Locate sys_bfin_spinlock function in L1 Memory"
        default y
index d7f0ccb..423c099 100644 (file)
 #ifdef __KERNEL__              /* only set these up for kernel code */
 
 #define __HAVE_ARCH_STRCPY
-extern inline char *strcpy(char *dest, const char *src)
-{
-       char *xdest = dest;
-       char temp = 0;
-
-       __asm__ __volatile__ (
-               "1:"
-               "%2 = B [%1++] (Z);"
-               "B [%0++] = %2;"
-               "CC = %2;"
-               "if cc jump 1b (bp);"
-               : "+&a" (dest), "+&a" (src), "=&d" (temp)
-               :
-               : "memory", "CC");
-
-       return xdest;
-}
+extern char *strcpy(char *dest, const char *src);
 
 #define __HAVE_ARCH_STRNCPY
-extern inline char *strncpy(char *dest, const char *src, size_t n)
-{
-       char *xdest = dest;
-       char temp = 0;
-
-       if (n == 0)
-               return xdest;
-
-       __asm__ __volatile__ (
-               "1:"
-               "%3 = B [%1++] (Z);"
-               "B [%0++] = %3;"
-               "CC = %3;"
-               "if ! cc jump 2f;"
-               "%2 += -1;"
-               "CC = %2 == 0;"
-               "if ! cc jump 1b (bp);"
-               "jump 4f;"
-               "2:"
-               /* if src is shorter than n, we need to null pad bytes now */
-               "%3 = 0;"
-               "3:"
-               "%2 += -1;"
-               "CC = %2 == 0;"
-               "if cc jump 4f;"
-               "B [%0++] = %3;"
-               "jump 3b;"
-               "4:"
-               : "+&a" (dest), "+&a" (src), "+&da" (n), "=&d" (temp)
-               :
-               : "memory", "CC");
-
-       return xdest;
-}
+extern char *strncpy(char *dest, const char *src, size_t n);
 
 #define __HAVE_ARCH_STRCMP
-extern inline int strcmp(const char *cs, const char *ct)
-{
-       /* need to use int's here so the char's in the assembly don't get
-        * sign extended incorrectly when we don't want them to be
-        */
-       int __res1, __res2;
-
-       __asm__ __volatile__ (
-               "1:"
-               "%2 = B[%0++] (Z);"      /* get *cs */
-               "%3 = B[%1++] (Z);"      /* get *ct */
-               "CC = %2 == %3;"         /* compare a byte */
-               "if ! cc jump 2f;"       /* not equal, break out */
-               "CC = %2;"               /* at end of cs? */
-               "if cc jump 1b (bp);"    /* no, keep going */
-               "jump.s 3f;"             /* strings are equal */
-               "2:"
-               "%2 = %2 - %3;"          /* *cs - *ct */
-               "3:"
-               : "+&a" (cs), "+&a" (ct), "=&d" (__res1), "=&d" (__res2)
-               :
-               : "memory", "CC");
-
-       return __res1;
-}
+extern int strcmp(const char *cs, const char *ct);
 
 #define __HAVE_ARCH_STRNCMP
-extern inline int strncmp(const char *cs, const char *ct, size_t count)
-{
-       /* need to use int's here so the char's in the assembly don't get
-        * sign extended incorrectly when we don't want them to be
-        */
-       int __res1, __res2;
-
-       if (!count)
-               return 0;
-
-       __asm__ __volatile__ (
-               "1:"
-               "%3 = B[%0++] (Z);"      /* get *cs */
-               "%4 = B[%1++] (Z);"      /* get *ct */
-               "CC = %3 == %4;"         /* compare a byte */
-               "if ! cc jump 3f;"       /* not equal, break out */
-               "CC = %3;"               /* at end of cs? */
-               "if ! cc jump 4f;"       /* yes, all done */
-               "%2 += -1;"              /* no, adjust count */
-               "CC = %2 == 0;"
-               "if ! cc jump 1b;"       /* more to do, keep going */
-               "2:"
-               "%3 = 0;"                /* strings are equal */
-               "jump.s 4f;"
-               "3:"
-               "%3 = %3 - %4;"          /* *cs - *ct */
-               "4:"
-               : "+&a" (cs), "+&a" (ct), "+&da" (count), "=&d" (__res1), "=&d" (__res2)
-               :
-               : "memory", "CC");
-
-       return __res1;
-}
+extern int strncmp(const char *cs, const char *ct, size_t count);
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *s, int c, size_t count);
index ed8392c..2c264b5 100644 (file)
@@ -33,6 +33,18 @@ EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memchr);
 
 /*
+ * Because string functions are both inline and exported functions and
+ * folder arch/blackfin/lib is configured as a library path in Makefile,
+ * symbols exported in folder lib  is not linked into built-in.o but
+ * inlined only. In order to export string symbols to kernel module
+ * properly, they should be exported here.
+ */
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+
+/*
  * libgcc functions - functions that are used internally by the
  * compiler...  (prototypes are not correct though, but that
  * doesn't really matter since they're not versioned).
diff --git a/arch/blackfin/lib/strcmp.S b/arch/blackfin/lib/strcmp.S
new file mode 100644 (file)
index 0000000..d7c1d15
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
+#include <linux/linkage.h>
+
+/* void *strcmp(char *s1, const char *s2);
+ * R0 = address (s1)
+ * R1 = address (s2)
+ *
+ * Returns an integer less than, equal to, or greater than zero if s1
+ *  (or the first n  bytes thereof) is found, respectively, to be less
+ *  than, to match, or be greater than s2.
+ */
+
+#ifdef CONFIG_STRCMP_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2
+
+ENTRY(_strcmp)
+       P0 = R0 ;       /* s1 */
+       P1 = R1 ;       /* s2 */
+
+1:
+       R0 = B[P0++] (Z);      /* get *s1 */
+       R1 = B[P1++] (Z);      /* get *s2 */
+       CC = R0 == R1;         /* compare a byte */
+       if ! cc jump 2f;       /* not equal, break out */
+       CC = R0;               /* at end of s1? */
+       if cc jump 1b (bp);    /* no, keep going */
+       jump.s 3f;             /* strings are equal */
+2:
+       R0 = R0 - R1;          /* *s1 - *s2 */
+3:
+       RTS;
+
+ENDPROC(_strcmp)
diff --git a/arch/blackfin/lib/strcmp.c b/arch/blackfin/lib/strcmp.c
deleted file mode 100644 (file)
index fde39a1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Provide symbol in case str func is not inlined.
- *
- * Copyright (c) 2006-2007 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define strcmp __inline_strcmp
-#include <asm/string.h>
-#undef strcmp
-
-#include <linux/module.h>
-
-int strcmp(const char *dest, const char *src)
-{
-       return __inline_strcmp(dest, src);
-}
-EXPORT_SYMBOL(strcmp);
diff --git a/arch/blackfin/lib/strcpy.S b/arch/blackfin/lib/strcpy.S
new file mode 100644 (file)
index 0000000..a6a0c63
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
+#include <linux/linkage.h>
+
+/* void *strcpy(char *dest, const char *src);
+ * R0 = address (dest)
+ * R1 = address (src)
+ *
+ * Returns a pointer to the destination string dest
+ */
+
+#ifdef CONFIG_STRCPY_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2
+
+ENTRY(_strcpy)
+       P0 = R0 ;       /* dst*/
+       P1 = R1 ;       /* src*/
+
+1:
+       R1 = B [P1++] (Z);
+       B [P0++] = R1;
+       CC = R1;
+       if cc jump 1b (bp);
+       RTS;
+
+ENDPROC(_strcpy)
diff --git a/arch/blackfin/lib/strcpy.c b/arch/blackfin/lib/strcpy.c
deleted file mode 100644 (file)
index 2a8836b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Provide symbol in case str func is not inlined.
- *
- * Copyright (c) 2006-2007 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define strcpy __inline_strcpy
-#include <asm/string.h>
-#undef strcpy
-
-#include <linux/module.h>
-
-char *strcpy(char *dest, const char *src)
-{
-       return __inline_strcpy(dest, src);
-}
-EXPORT_SYMBOL(strcpy);
diff --git a/arch/blackfin/lib/strncmp.S b/arch/blackfin/lib/strncmp.S
new file mode 100644 (file)
index 0000000..6da37c3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
+#include <linux/linkage.h>
+
+/* void *strncpy(char *s1, const char *s2, size_t n);
+ * R0 = address (dest)
+ * R1 = address (src)
+ * R2 = size (n)
+ * Returns a pointer to the destination string dest
+ */
+
+#ifdef CONFIG_STRNCMP_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2
+
+ENTRY(_strncmp)
+       CC = R2 == 0;
+       if CC JUMP 5f;
+
+       P0 = R0 ;       /* s1 */
+       P1 = R1 ;       /* s2 */
+1:
+       R0 = B[P0++] (Z);      /* get *s1 */
+       R1 = B[P1++] (Z);      /* get *s2 */
+       CC = R0 == R1;         /* compare a byte */
+       if ! cc jump 3f;       /* not equal, break out */
+       CC = R0;               /* at end of s1? */
+       if ! cc jump 4f;       /* yes, all done */
+       R2 += -1;              /* no, adjust count */
+       CC = R2 == 0;
+       if ! cc jump 1b (bp);  /* more to do, keep going */
+2:
+       R0 = 0;                /* strings are equal */
+       jump.s 4f;
+3:
+       R0 = R0 - R1;          /* *s1 - *s2 */
+4:
+       RTS;
+
+5:
+       R0 = 0;
+       RTS;
+
+ENDPROC(_strncmp)
diff --git a/arch/blackfin/lib/strncmp.c b/arch/blackfin/lib/strncmp.c
deleted file mode 100644 (file)
index 46518b1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Provide symbol in case str func is not inlined.
- *
- * Copyright (c) 2006-2007 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define strncmp __inline_strncmp
-#include <asm/string.h>
-#include <linux/module.h>
-#undef strncmp
-
-int strncmp(const char *cs, const char *ct, size_t count)
-{
-       return __inline_strncmp(cs, ct, count);
-}
-EXPORT_SYMBOL(strncmp);
diff --git a/arch/blackfin/lib/strncpy.S b/arch/blackfin/lib/strncpy.S
new file mode 100644 (file)
index 0000000..39fbbe6
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
+ */
+
+#include <linux/linkage.h>
+
+/* void *strncpy(char *dest, const char *src, size_t n);
+ * R0 = address (dest)
+ * R1 = address (src)
+ * R2 = size
+ * Returns a pointer to the destination string dest
+ */
+
+#ifdef CONFIG_STRNCPY_L1
+.section .l1.text
+#else
+.text
+#endif
+
+.align 2
+
+ENTRY(_strncpy)
+       CC = R2 == 0;
+       if CC JUMP 4f;
+       P0 = R0 ;       /* dst*/
+       P1 = R1 ;       /* src*/
+
+1:
+       R1 = B [P1++] (Z);
+       B [P0++] = R1;
+       CC = R1;
+       if ! cc jump 2f;
+       R2 += -1;
+       CC = R2 == 0;
+       if ! cc jump 1b (bp);
+       jump 4f;
+2:
+       /* if src is shorter than n, we need to null pad bytes in dest */
+       R1 = 0;
+3:
+       R2 += -1;
+       CC = R2 == 0;
+       if cc jump 4f;
+       B [P0++] = R1;
+       jump 3b;
+
+4:
+       RTS;
+
+ENDPROC(_strncpy)
diff --git a/arch/blackfin/lib/strncpy.c b/arch/blackfin/lib/strncpy.c
deleted file mode 100644 (file)
index ea1dc6b..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Provide symbol in case str func is not inlined.
- *
- * Copyright (c) 2006-2007 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define strncpy __inline_strncpy
-#include <asm/string.h>
-#undef strncpy
-
-#include <linux/module.h>
-
-char *strncpy(char *dest, const char *src, size_t n)
-{
-       return __inline_strncpy(dest, src, n);
-}
-EXPORT_SYMBOL(strncpy);