Skip to content

Commit

Permalink
Blackfin: move string functions to normal lib/ assembly
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rgetz authored and vapier committed May 22, 2010
1 parent 80fcdb9 commit 479ba60
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 184 deletions.
28 changes: 28 additions & 0 deletions arch/blackfin/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
113 changes: 4 additions & 109 deletions arch/blackfin/include/asm/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,121 +12,16 @@
#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);
Expand Down
12 changes: 12 additions & 0 deletions arch/blackfin/kernel/bfin_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ EXPORT_SYMBOL(memcmp);
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
Expand Down
43 changes: 43 additions & 0 deletions arch/blackfin/lib/strcmp.S
Original file line number Diff line number Diff line change
@@ -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)
19 changes: 0 additions & 19 deletions arch/blackfin/lib/strcmp.c

This file was deleted.

35 changes: 35 additions & 0 deletions arch/blackfin/lib/strcpy.S
Original file line number Diff line number Diff line change
@@ -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)
19 changes: 0 additions & 19 deletions arch/blackfin/lib/strcpy.c

This file was deleted.

52 changes: 52 additions & 0 deletions arch/blackfin/lib/strncmp.S
Original file line number Diff line number Diff line change
@@ -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)
18 changes: 0 additions & 18 deletions arch/blackfin/lib/strncmp.c

This file was deleted.

Loading

0 comments on commit 479ba60

Please sign in to comment.