Blackfin: move string functions to normal lib/ assembly

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>

authored by Robin Getz and committed by Mike Frysinger 479ba603 80fcdb95

+226 -184
+28
arch/blackfin/Kconfig
··· 791 791 If enabled, the memcpy function is linked 792 792 into L1 instruction memory. (less latency) 793 793 794 + config STRCMP_L1 795 + bool "locate strcmp function in L1 Memory" 796 + default y 797 + help 798 + If enabled, the strcmp function is linked 799 + into L1 instruction memory (less latency). 800 + 801 + config STRNCMP_L1 802 + bool "locate strncmp function in L1 Memory" 803 + default y 804 + help 805 + If enabled, the strncmp function is linked 806 + into L1 instruction memory (less latency). 807 + 808 + config STRCPY_L1 809 + bool "locate strcpy function in L1 Memory" 810 + default y 811 + help 812 + If enabled, the strcpy function is linked 813 + into L1 instruction memory (less latency). 814 + 815 + config STRNCPY_L1 816 + bool "locate strncpy function in L1 Memory" 817 + default y 818 + help 819 + If enabled, the strncpy function is linked 820 + into L1 instruction memory (less latency). 821 + 794 822 config SYS_BFIN_SPINLOCK_L1 795 823 bool "Locate sys_bfin_spinlock function in L1 Memory" 796 824 default y
+4 -109
arch/blackfin/include/asm/string.h
··· 12 12 #ifdef __KERNEL__ /* only set these up for kernel code */ 13 13 14 14 #define __HAVE_ARCH_STRCPY 15 - extern inline char *strcpy(char *dest, const char *src) 16 - { 17 - char *xdest = dest; 18 - char temp = 0; 19 - 20 - __asm__ __volatile__ ( 21 - "1:" 22 - "%2 = B [%1++] (Z);" 23 - "B [%0++] = %2;" 24 - "CC = %2;" 25 - "if cc jump 1b (bp);" 26 - : "+&a" (dest), "+&a" (src), "=&d" (temp) 27 - : 28 - : "memory", "CC"); 29 - 30 - return xdest; 31 - } 15 + extern char *strcpy(char *dest, const char *src); 32 16 33 17 #define __HAVE_ARCH_STRNCPY 34 - extern inline char *strncpy(char *dest, const char *src, size_t n) 35 - { 36 - char *xdest = dest; 37 - char temp = 0; 38 - 39 - if (n == 0) 40 - return xdest; 41 - 42 - __asm__ __volatile__ ( 43 - "1:" 44 - "%3 = B [%1++] (Z);" 45 - "B [%0++] = %3;" 46 - "CC = %3;" 47 - "if ! cc jump 2f;" 48 - "%2 += -1;" 49 - "CC = %2 == 0;" 50 - "if ! cc jump 1b (bp);" 51 - "jump 4f;" 52 - "2:" 53 - /* if src is shorter than n, we need to null pad bytes now */ 54 - "%3 = 0;" 55 - "3:" 56 - "%2 += -1;" 57 - "CC = %2 == 0;" 58 - "if cc jump 4f;" 59 - "B [%0++] = %3;" 60 - "jump 3b;" 61 - "4:" 62 - : "+&a" (dest), "+&a" (src), "+&da" (n), "=&d" (temp) 63 - : 64 - : "memory", "CC"); 65 - 66 - return xdest; 67 - } 18 + extern char *strncpy(char *dest, const char *src, size_t n); 68 19 69 20 #define __HAVE_ARCH_STRCMP 70 - extern inline int strcmp(const char *cs, const char *ct) 71 - { 72 - /* need to use int's here so the char's in the assembly don't get 73 - * sign extended incorrectly when we don't want them to be 74 - */ 75 - int __res1, __res2; 76 - 77 - __asm__ __volatile__ ( 78 - "1:" 79 - "%2 = B[%0++] (Z);" /* get *cs */ 80 - "%3 = B[%1++] (Z);" /* get *ct */ 81 - "CC = %2 == %3;" /* compare a byte */ 82 - "if ! cc jump 2f;" /* not equal, break out */ 83 - "CC = %2;" /* at end of cs? */ 84 - "if cc jump 1b (bp);" /* no, keep going */ 85 - "jump.s 3f;" /* strings are equal */ 86 - "2:" 87 - "%2 = %2 - %3;" /* *cs - *ct */ 88 - "3:" 89 - : "+&a" (cs), "+&a" (ct), "=&d" (__res1), "=&d" (__res2) 90 - : 91 - : "memory", "CC"); 92 - 93 - return __res1; 94 - } 21 + extern int strcmp(const char *cs, const char *ct); 95 22 96 23 #define __HAVE_ARCH_STRNCMP 97 - extern inline int strncmp(const char *cs, const char *ct, size_t count) 98 - { 99 - /* need to use int's here so the char's in the assembly don't get 100 - * sign extended incorrectly when we don't want them to be 101 - */ 102 - int __res1, __res2; 103 - 104 - if (!count) 105 - return 0; 106 - 107 - __asm__ __volatile__ ( 108 - "1:" 109 - "%3 = B[%0++] (Z);" /* get *cs */ 110 - "%4 = B[%1++] (Z);" /* get *ct */ 111 - "CC = %3 == %4;" /* compare a byte */ 112 - "if ! cc jump 3f;" /* not equal, break out */ 113 - "CC = %3;" /* at end of cs? */ 114 - "if ! cc jump 4f;" /* yes, all done */ 115 - "%2 += -1;" /* no, adjust count */ 116 - "CC = %2 == 0;" 117 - "if ! cc jump 1b;" /* more to do, keep going */ 118 - "2:" 119 - "%3 = 0;" /* strings are equal */ 120 - "jump.s 4f;" 121 - "3:" 122 - "%3 = %3 - %4;" /* *cs - *ct */ 123 - "4:" 124 - : "+&a" (cs), "+&a" (ct), "+&da" (count), "=&d" (__res1), "=&d" (__res2) 125 - : 126 - : "memory", "CC"); 127 - 128 - return __res1; 129 - } 24 + extern int strncmp(const char *cs, const char *ct, size_t count); 130 25 131 26 #define __HAVE_ARCH_MEMSET 132 27 extern void *memset(void *s, int c, size_t count);
+12
arch/blackfin/kernel/bfin_ksyms.c
··· 33 33 EXPORT_SYMBOL(memchr); 34 34 35 35 /* 36 + * Because string functions are both inline and exported functions and 37 + * folder arch/blackfin/lib is configured as a library path in Makefile, 38 + * symbols exported in folder lib is not linked into built-in.o but 39 + * inlined only. In order to export string symbols to kernel module 40 + * properly, they should be exported here. 41 + */ 42 + EXPORT_SYMBOL(strcpy); 43 + EXPORT_SYMBOL(strncpy); 44 + EXPORT_SYMBOL(strcmp); 45 + EXPORT_SYMBOL(strncmp); 46 + 47 + /* 36 48 * libgcc functions - functions that are used internally by the 37 49 * compiler... (prototypes are not correct though, but that 38 50 * doesn't really matter since they're not versioned).
+43
arch/blackfin/lib/strcmp.S
··· 1 + /* 2 + * Copyright 2005-2010 Analog Devices Inc. 3 + * 4 + * Licensed under the ADI BSD license or the GPL-2 (or later) 5 + */ 6 + 7 + #include <linux/linkage.h> 8 + 9 + /* void *strcmp(char *s1, const char *s2); 10 + * R0 = address (s1) 11 + * R1 = address (s2) 12 + * 13 + * Returns an integer less than, equal to, or greater than zero if s1 14 + * (or the first n bytes thereof) is found, respectively, to be less 15 + * than, to match, or be greater than s2. 16 + */ 17 + 18 + #ifdef CONFIG_STRCMP_L1 19 + .section .l1.text 20 + #else 21 + .text 22 + #endif 23 + 24 + .align 2 25 + 26 + ENTRY(_strcmp) 27 + P0 = R0 ; /* s1 */ 28 + P1 = R1 ; /* s2 */ 29 + 30 + 1: 31 + R0 = B[P0++] (Z); /* get *s1 */ 32 + R1 = B[P1++] (Z); /* get *s2 */ 33 + CC = R0 == R1; /* compare a byte */ 34 + if ! cc jump 2f; /* not equal, break out */ 35 + CC = R0; /* at end of s1? */ 36 + if cc jump 1b (bp); /* no, keep going */ 37 + jump.s 3f; /* strings are equal */ 38 + 2: 39 + R0 = R0 - R1; /* *s1 - *s2 */ 40 + 3: 41 + RTS; 42 + 43 + ENDPROC(_strcmp)
-19
arch/blackfin/lib/strcmp.c
··· 1 - /* 2 - * Provide symbol in case str func is not inlined. 3 - * 4 - * Copyright (c) 2006-2007 Analog Devices Inc. 5 - * 6 - * Licensed under the GPL-2 or later. 7 - */ 8 - 9 - #define strcmp __inline_strcmp 10 - #include <asm/string.h> 11 - #undef strcmp 12 - 13 - #include <linux/module.h> 14 - 15 - int strcmp(const char *dest, const char *src) 16 - { 17 - return __inline_strcmp(dest, src); 18 - } 19 - EXPORT_SYMBOL(strcmp);
+35
arch/blackfin/lib/strcpy.S
··· 1 + /* 2 + * Copyright 2005-2010 Analog Devices Inc. 3 + * 4 + * Licensed under the ADI BSD license or the GPL-2 (or later) 5 + */ 6 + 7 + #include <linux/linkage.h> 8 + 9 + /* void *strcpy(char *dest, const char *src); 10 + * R0 = address (dest) 11 + * R1 = address (src) 12 + * 13 + * Returns a pointer to the destination string dest 14 + */ 15 + 16 + #ifdef CONFIG_STRCPY_L1 17 + .section .l1.text 18 + #else 19 + .text 20 + #endif 21 + 22 + .align 2 23 + 24 + ENTRY(_strcpy) 25 + P0 = R0 ; /* dst*/ 26 + P1 = R1 ; /* src*/ 27 + 28 + 1: 29 + R1 = B [P1++] (Z); 30 + B [P0++] = R1; 31 + CC = R1; 32 + if cc jump 1b (bp); 33 + RTS; 34 + 35 + ENDPROC(_strcpy)
-19
arch/blackfin/lib/strcpy.c
··· 1 - /* 2 - * Provide symbol in case str func is not inlined. 3 - * 4 - * Copyright (c) 2006-2007 Analog Devices Inc. 5 - * 6 - * Licensed under the GPL-2 or later. 7 - */ 8 - 9 - #define strcpy __inline_strcpy 10 - #include <asm/string.h> 11 - #undef strcpy 12 - 13 - #include <linux/module.h> 14 - 15 - char *strcpy(char *dest, const char *src) 16 - { 17 - return __inline_strcpy(dest, src); 18 - } 19 - EXPORT_SYMBOL(strcpy);
+52
arch/blackfin/lib/strncmp.S
··· 1 + /* 2 + * Copyright 2005-2010 Analog Devices Inc. 3 + * 4 + * Licensed under the ADI BSD license or the GPL-2 (or later) 5 + */ 6 + 7 + #include <linux/linkage.h> 8 + 9 + /* void *strncpy(char *s1, const char *s2, size_t n); 10 + * R0 = address (dest) 11 + * R1 = address (src) 12 + * R2 = size (n) 13 + * Returns a pointer to the destination string dest 14 + */ 15 + 16 + #ifdef CONFIG_STRNCMP_L1 17 + .section .l1.text 18 + #else 19 + .text 20 + #endif 21 + 22 + .align 2 23 + 24 + ENTRY(_strncmp) 25 + CC = R2 == 0; 26 + if CC JUMP 5f; 27 + 28 + P0 = R0 ; /* s1 */ 29 + P1 = R1 ; /* s2 */ 30 + 1: 31 + R0 = B[P0++] (Z); /* get *s1 */ 32 + R1 = B[P1++] (Z); /* get *s2 */ 33 + CC = R0 == R1; /* compare a byte */ 34 + if ! cc jump 3f; /* not equal, break out */ 35 + CC = R0; /* at end of s1? */ 36 + if ! cc jump 4f; /* yes, all done */ 37 + R2 += -1; /* no, adjust count */ 38 + CC = R2 == 0; 39 + if ! cc jump 1b (bp); /* more to do, keep going */ 40 + 2: 41 + R0 = 0; /* strings are equal */ 42 + jump.s 4f; 43 + 3: 44 + R0 = R0 - R1; /* *s1 - *s2 */ 45 + 4: 46 + RTS; 47 + 48 + 5: 49 + R0 = 0; 50 + RTS; 51 + 52 + ENDPROC(_strncmp)
-18
arch/blackfin/lib/strncmp.c
··· 1 - /* 2 - * Provide symbol in case str func is not inlined. 3 - * 4 - * Copyright (c) 2006-2007 Analog Devices Inc. 5 - * 6 - * Licensed under the GPL-2 or later. 7 - */ 8 - 9 - #define strncmp __inline_strncmp 10 - #include <asm/string.h> 11 - #include <linux/module.h> 12 - #undef strncmp 13 - 14 - int strncmp(const char *cs, const char *ct, size_t count) 15 - { 16 - return __inline_strncmp(cs, ct, count); 17 - } 18 - EXPORT_SYMBOL(strncmp);
+52
arch/blackfin/lib/strncpy.S
··· 1 + /* 2 + * Copyright 2005-2010 Analog Devices Inc. 3 + * 4 + * Licensed under the ADI BSD license or the GPL-2 (or later) 5 + */ 6 + 7 + #include <linux/linkage.h> 8 + 9 + /* void *strncpy(char *dest, const char *src, size_t n); 10 + * R0 = address (dest) 11 + * R1 = address (src) 12 + * R2 = size 13 + * Returns a pointer to the destination string dest 14 + */ 15 + 16 + #ifdef CONFIG_STRNCPY_L1 17 + .section .l1.text 18 + #else 19 + .text 20 + #endif 21 + 22 + .align 2 23 + 24 + ENTRY(_strncpy) 25 + CC = R2 == 0; 26 + if CC JUMP 4f; 27 + P0 = R0 ; /* dst*/ 28 + P1 = R1 ; /* src*/ 29 + 30 + 1: 31 + R1 = B [P1++] (Z); 32 + B [P0++] = R1; 33 + CC = R1; 34 + if ! cc jump 2f; 35 + R2 += -1; 36 + CC = R2 == 0; 37 + if ! cc jump 1b (bp); 38 + jump 4f; 39 + 2: 40 + /* if src is shorter than n, we need to null pad bytes in dest */ 41 + R1 = 0; 42 + 3: 43 + R2 += -1; 44 + CC = R2 == 0; 45 + if cc jump 4f; 46 + B [P0++] = R1; 47 + jump 3b; 48 + 49 + 4: 50 + RTS; 51 + 52 + ENDPROC(_strncpy)
-19
arch/blackfin/lib/strncpy.c
··· 1 - /* 2 - * Provide symbol in case str func is not inlined. 3 - * 4 - * Copyright (c) 2006-2007 Analog Devices Inc. 5 - * 6 - * Licensed under the GPL-2 or later. 7 - */ 8 - 9 - #define strncpy __inline_strncpy 10 - #include <asm/string.h> 11 - #undef strncpy 12 - 13 - #include <linux/module.h> 14 - 15 - char *strncpy(char *dest, const char *src, size_t n) 16 - { 17 - return __inline_strncpy(dest, src, n); 18 - } 19 - EXPORT_SYMBOL(strncpy);