lkml.org 
[lkml]   [1998]   [Aug]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectFixes for the i386 __asm__ mess
Here is a patch that fixes all sorts of problems with the current i386
inline assembly statements in the 2.1.117 kernel.

Problems:
- Many asm statements used registers as input or output and recorded them
as clobbered at the same time. This is invalid, and can lead GCC to
generate incorrect code silently. This affects all versions of GCC, even
2.7.2.
- Some asm statements were lacking "memory" clobbers. memmove was one of
them.
- The popad bug check used "eax" and "edx" as register constraints instead
of "a" and "d".
- Finally, I fixed a small problem in lib/string.c exposed by the string
test program that comes with glibc.

I removed some of the rarely used string functions (strpbrk, etc.), the
C functions should work fast enough for those.

One file is not completely converted: arch/i386/lib/chksum.c. I have my doubts
whether it's possible to do that with legal asm statements, and since there
is hardly any C code in that file, I suggest replacing it with a new file
chksum.S.

This patch was tested with a modified version of glibc-2.0.95/string/tester.c.
If someone is interested in the program I used, I can send it. I also compiled
the kernel; it booted, started X, and did nothing obviously bad to the
filesystem (e2fsck didn't complain except about the usual zero dtime inodes).

Bernd


*** ./arch/i386/lib/delay.c.orig-1 Thu Jun 11 14:02:52 1998
--- ./arch/i386/lib/delay.c Tue Aug 25 10:07:15 1998
***************
*** 17,35 ****

void __delay(unsigned long loops)
{
__asm__ __volatile__(
"1:\tdecl %0\n\tjns 1b"
! :/* no outputs */
! :"a" (loops)
! :"ax");
}

inline void __const_udelay(unsigned long xloops)
{
__asm__("mull %0"
! :"=d" (xloops)
! :"a" (xloops),"0" (current_cpu_data.loops_per_sec)
! :"ax");
__delay(xloops);
}

--- 17,35 ----

void __delay(unsigned long loops)
{
+ int d0;
__asm__ __volatile__(
"1:\tdecl %0\n\tjns 1b"
! :"=&a" (d0)
! :"0" (loops));
}

inline void __const_udelay(unsigned long xloops)
{
+ int d0;
__asm__("mull %0"
! :"=d" (xloops), "=&a" (d0)
! :"1" (xloops),"0" (current_cpu_data.loops_per_sec));
__delay(xloops);
}

*** ./arch/i386/lib/checksum.c.orig-1 Tue Aug 25 09:45:47 1998
--- ./arch/i386/lib/checksum.c Tue Aug 25 10:07:15 1998
***************
*** 31,37 ****

#if CPU!=686

! unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) {
/*
* Experiments with Ethernet and SLIP connections show that buff
* is aligned on either a 2-byte or 4-byte boundary. We get at
--- 31,39 ----

#if CPU!=686

! unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
! {
! int d0, d1, d2, d3;
/*
* Experiments with Ethernet and SLIP connections show that buff
* is aligned on either a 2-byte or 4-byte boundary. We get at
*************** unsigned int csum_partial(const unsigned
*** 96,111 ****
6: addl %%ecx,%%eax
adcl $0, %%eax
7: "
! : "=a"(sum)
! : "0"(sum), "c"(len), "S"(buff)
! : "bx", "cx", "dx", "si");
return(sum);
}

#else /* 686 */

! unsigned int csum_partial(const unsigned char * buf, int len, unsigned int sum) {
! __asm__ ("
testl $2, %%esi
jnz 30f
10:
--- 98,114 ----
6: addl %%ecx,%%eax
adcl $0, %%eax
7: "
! : "=a"(sum), "=&b "(d0), "=&c" (d1), "=&S" (d2), "=&d" (d3)
! : "0"(sum), "2"(len), "3"(buff));
return(sum);
}

#else /* 686 */

! unsigned int csum_partial(const unsigned char * buf, int len, unsigned int sum)
! {
! int d0, d1, d2, d3;
! __asm__ ("
testl $2, %%esi
jnz 30f
10:
*************** unsigned int csum_partial(const unsigned
*** 189,197 ****
addl %%ebx,%%eax
adcl $0,%%eax
80: "
! : "=a"(sum)
! : "0"(sum), "c"(len), "S"(buf)
! : "bx", "cx", "dx", "si");
return(sum);
}

--- 192,199 ----
addl %%ebx,%%eax
adcl $0,%%eax
80: "
! : "=a"(sum), "=&c" (d0), "=&S" (d1), "=&b" (d2), "=&d" (d3)
! : "0"(sum), "1" (len), "2" (buf));
return(sum);
}

*** ./arch/i386/lib/usercopy.c.orig-1 Thu Jun 11 14:05:01 1998
--- ./arch/i386/lib/usercopy.c Tue Aug 25 10:07:15 1998
*************** __generic_copy_from_user(void *to, const
*** 29,34 ****
--- 29,36 ----
*/

#define __do_strncpy_from_user(dst,src,count,res) \
+ do { \
+ int __d0, __d1, __d2; \
__asm__ __volatile__( \
" testl %1,%1\n" \
" jz 2f\n" \
*************** __generic_copy_from_user(void *to, const
*** 41,56 ****
"1: subl %1,%0\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: movl %2,%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
".previous" \
! : "=d"(res), "=c"(count) \
! : "i"(-EFAULT), "0"(count), "1"(count), "S"(src), "D"(dst) \
! : "si", "di", "ax", "memory")

long
__strncpy_from_user(char *dst, const char *src, long count)
--- 43,60 ----
"1: subl %1,%0\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: movl %5,%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .long 0b,3b\n" \
".previous" \
! : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
! "=&D" (__d2) \
! : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
! : "memory"); \
! } while (0)

long
__strncpy_from_user(char *dst, const char *src, long count)
*************** strncpy_from_user(char *dst, const char
*** 74,87 ****
* Zero Userspace
*/

! #define __do_clear_user(addr,size) \
! __asm__ __volatile__( \
"0: rep; stosl\n" \
! " movl %1,%0\n" \
"1: rep; stosb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: lea 0(%1,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
--- 78,93 ----
* Zero Userspace
*/

! #define __do_clear_user(addr,size) \
! do { \
! int __d0; \
! __asm__ __volatile__( \
"0: rep; stosl\n" \
! " movl %2,%0\n" \
"1: rep; stosb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: lea 0(%2,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
*************** strncpy_from_user(char *dst, const char
*** 89,97 ****
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
! : "=&c"(size) \
! : "r"(size & 3), "0"(size / 4), "D"(addr), "a"(0) \
! : "di")

unsigned long
clear_user(void *to, unsigned long n)
--- 95,103 ----
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
! : "=&c"(size), "=&D" (__d0) \
! : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \
! } while (0)

unsigned long
clear_user(void *to, unsigned long n)
*** ./arch/i386/mm/init.c.orig-1 Tue Aug 25 09:45:47 1998
--- ./arch/i386/mm/init.c Tue Aug 25 10:07:15 1998
*************** int do_check_pgt_cache(int low, int high
*** 120,143 ****
pte_t * __bad_pagetable(void)
{
extern char empty_bad_page_table[PAGE_SIZE];

! __asm__ __volatile__("cld ; rep ; stosl":
! :"a" (pte_val(BAD_PAGE)),
! "D" ((long) empty_bad_page_table),
! "c" (PAGE_SIZE/4)
! :"di","cx");
return (pte_t *) empty_bad_page_table;
}

pte_t __bad_page(void)
{
extern char empty_bad_page[PAGE_SIZE];

! __asm__ __volatile__("cld ; rep ; stosl":
! :"a" (0),
! "D" ((long) empty_bad_page),
! "c" (PAGE_SIZE/4)
! :"di","cx");
return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
}

--- 120,147 ----
pte_t * __bad_pagetable(void)
{
extern char empty_bad_page_table[PAGE_SIZE];
+ int d0, d1;

! __asm__ __volatile__("cld ; rep ; stosl"
! : "=&D" (d0), "=&c" (d1)
! : "a" (pte_val(BAD_PAGE)),
! "0" ((long) empty_bad_page_table),
! "1" (PAGE_SIZE/4)
! : "memory");
return (pte_t *) empty_bad_page_table;
}

pte_t __bad_page(void)
{
extern char empty_bad_page[PAGE_SIZE];
+ int d0, d1;

! __asm__ __volatile__("cld ; rep ; stosl"
! : "=&D" (d0), "=&c" (d1)
! : "a" (0),
! "0" ((long) empty_bad_page),
! "1" (PAGE_SIZE/4)
! : "memory");
return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
}

*** ./lib/string.c.orig-1 Tue Aug 25 10:27:19 1998
--- ./lib/string.c Tue Aug 25 10:27:45 1998
*************** void * memmove(void * dest,const void *s
*** 266,275 ****
int memcmp(const void * cs,const void * ct,size_t count)
{
const unsigned char *su1, *su2;
! signed char res = 0;

for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
! if ((res = *su1 - *su2) != 0)
break;
return res;
}
--- 266,275 ----
int memcmp(const void * cs,const void * ct,size_t count)
{
const unsigned char *su1, *su2;
! int res = 0;

for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
! if ((res = (int)*su1 - (int)*su2) != 0)
break;
return res;
}
*** ./include/asm-i386/bugs.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/bugs.h Tue Aug 25 10:07:15 1998
*************** __initfunc(static void check_popad(void)
*** 143,151 ****
printk(KERN_INFO "Checking for popad bug... ");
__asm__ __volatile__(
"movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
! : "=eax" (res)
! : "edx" (inp)
! : "eax", "ecx", "edx", "edi" );
/* If this fails, it means that any user program may lock the CPU hard. Too bad. */
if (res != 12345678) printk( "Buggy.\n" );
else printk( "OK.\n" );
--- 143,151 ----
printk(KERN_INFO "Checking for popad bug... ");
__asm__ __volatile__(
"movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
! : "=&a" (res)
! : "d" (inp)
! : "ecx", "edi" );
/* If this fails, it means that any user program may lock the CPU hard. Too bad. */
if (res != 12345678) printk( "Buggy.\n" );
else printk( "OK.\n" );
*** ./include/asm-i386/string.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/string.h Tue Aug 25 10:31:34 1998
***************
*** 30,49 ****
#define __HAVE_ARCH_STRCPY
extern inline char * strcpy(char * dest,const char *src)
{
__asm__ __volatile__(
"cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
! : /* no output */
! :"S" (src),"D" (dest):"si","di","ax","memory");
return dest;
}

#define __HAVE_ARCH_STRNCPY
extern inline char * strncpy(char * dest,const char *src,size_t count)
{
__asm__ __volatile__(
"cld\n"
"1:\tdecl %2\n\t"
--- 30,51 ----
#define __HAVE_ARCH_STRCPY
extern inline char * strcpy(char * dest,const char *src)
{
+ int d0, d1, d2;
__asm__ __volatile__(
"cld\n"
"1:\tlodsb\n\t"
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
! : "=&S" (d0), "=&D" (d1), "=&a" (d2)
! :"0" (src),"1" (dest) : "memory");
return dest;
}

#define __HAVE_ARCH_STRNCPY
extern inline char * strncpy(char * dest,const char *src,size_t count)
{
+ int d0, d1, d2, d3;
__asm__ __volatile__(
"cld\n"
"1:\tdecl %2\n\t"
*************** __asm__ __volatile__(
*** 55,68 ****
"rep\n\t"
"stosb\n"
"2:"
! : /* no output */
! :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory");
return dest;
}

#define __HAVE_ARCH_STRCAT
extern inline char * strcat(char * dest,const char * src)
{
__asm__ __volatile__(
"cld\n\t"
"repne\n\t"
--- 57,71 ----
"rep\n\t"
"stosb\n"
"2:"
! : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
! :"0" (src),"1" (dest),"2" (count) : "memory");
return dest;
}

#define __HAVE_ARCH_STRCAT
extern inline char * strcat(char * dest,const char * src)
{
+ int d0, d1, d2, d3;
__asm__ __volatile__(
"cld\n\t"
"repne\n\t"
*************** __asm__ __volatile__(
*** 72,91 ****
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
! : /* no output */
! :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
return dest;
}

#define __HAVE_ARCH_STRNCAT
extern inline char * strncat(char * dest,const char * src,size_t count)
{
__asm__ __volatile__(
"cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
! "movl %4,%3\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
--- 75,95 ----
"stosb\n\t"
"testb %%al,%%al\n\t"
"jne 1b"
! : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
! : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory");
return dest;
}

#define __HAVE_ARCH_STRNCAT
extern inline char * strncat(char * dest,const char * src,size_t count)
{
+ int d0, d1, d2, d3;
__asm__ __volatile__(
"cld\n\t"
"repne\n\t"
"scasb\n\t"
"decl %1\n\t"
! "movl %8,%3\n"
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
*************** __asm__ __volatile__(
*** 94,108 ****
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
! : /* no output */
! :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
! :"si","di","ax","cx","memory");
return dest;
}

#define __HAVE_ARCH_STRCMP
extern inline int strcmp(const char * cs,const char * ct)
{
register int __res;
__asm__ __volatile__(
"cld\n"
--- 98,113 ----
"jne 1b\n"
"2:\txorl %2,%2\n\t"
"stosb"
! : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
! : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count)
! : "memory");
return dest;
}

#define __HAVE_ARCH_STRCMP
extern inline int strcmp(const char * cs,const char * ct)
{
+ int d0, d1;
register int __res;
__asm__ __volatile__(
"cld\n"
*************** __asm__ __volatile__(
*** 116,122 ****
"2:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"3:"
! :"=a" (__res):"S" (cs),"D" (ct):"si","di");
return __res;
}

--- 121,128 ----
"2:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"3:"
! :"=a" (__res), "=&S" (d0), "=&D" (d1)
! :"1" (cs),"2" (ct));
return __res;
}

*************** return __res;
*** 124,129 ****
--- 130,136 ----
extern inline int strncmp(const char * cs,const char * ct,size_t count)
{
register int __res;
+ int d0, d1, d2;
__asm__ __volatile__(
"cld\n"
"1:\tdecl %3\n\t"
*************** __asm__ __volatile__(
*** 138,150 ****
"3:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
! :"=a" (__res):"S" (cs),"D" (ct),"c" (count):"si","di","cx");
return __res;
}

#define __HAVE_ARCH_STRCHR
extern inline char * strchr(const char * s, int c)
{
register char * __res;
__asm__ __volatile__(
"cld\n\t"
--- 145,159 ----
"3:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
! :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
! :"1" (cs),"2" (ct),"3" (count));
return __res;
}

#define __HAVE_ARCH_STRCHR
extern inline char * strchr(const char * s, int c)
{
+ int d0;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
*************** __asm__ __volatile__(
*** 157,169 ****
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
! :"=a" (__res):"S" (s),"0" (c):"si");
return __res;
}

#define __HAVE_ARCH_STRRCHR
extern inline char * strrchr(const char * s, int c)
{
register char * __res;
__asm__ __volatile__(
"cld\n\t"
--- 166,179 ----
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
! :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
return __res;
}

#define __HAVE_ARCH_STRRCHR
extern inline char * strrchr(const char * s, int c)
{
+ int d0, d1;
register char * __res;
__asm__ __volatile__(
"cld\n\t"
*************** __asm__ __volatile__(
*** 174,277 ****
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
! :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
! return __res;
! }
!
! #define __HAVE_ARCH_STRSPN
! extern inline size_t strspn(const char * cs, const char * ct)
! {
! register char * __res;
! __asm__ __volatile__(
! "cld\n\t"
! "movl %4,%%edi\n\t"
! "repne\n\t"
! "scasb\n\t"
! "notl %%ecx\n\t"
! "decl %%ecx\n\t"
! "movl %%ecx,%%edx\n"
! "1:\tlodsb\n\t"
! "testb %%al,%%al\n\t"
! "je 2f\n\t"
! "movl %4,%%edi\n\t"
! "movl %%edx,%%ecx\n\t"
! "repne\n\t"
! "scasb\n\t"
! "je 1b\n"
! "2:\tdecl %0"
! :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
! :"ax","cx","dx","di");
! return __res-cs;
! }
!
! #define __HAVE_ARCH_STRCSPN
! extern inline size_t strcspn(const char * cs, const char * ct)
! {
! register char * __res;
! __asm__ __volatile__(
! "cld\n\t"
! "movl %4,%%edi\n\t"
! "repne\n\t"
! "scasb\n\t"
! "notl %%ecx\n\t"
! "decl %%ecx\n\t"
! "movl %%ecx,%%edx\n"
! "1:\tlodsb\n\t"
! "testb %%al,%%al\n\t"
! "je 2f\n\t"
! "movl %4,%%edi\n\t"
! "movl %%edx,%%ecx\n\t"
! "repne\n\t"
! "scasb\n\t"
! "jne 1b\n"
! "2:\tdecl %0"
! :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
! :"ax","cx","dx","di");
! return __res-cs;
! }
!
! #define __HAVE_ARCH_STRPBRK
! extern inline char * strpbrk(const char * cs,const char * ct)
! {
! register char * __res;
! __asm__ __volatile__(
! "cld\n\t"
! "movl %4,%%edi\n\t"
! "repne\n\t"
! "scasb\n\t"
! "notl %%ecx\n\t"
! "decl %%ecx\n\t"
! "movl %%ecx,%%edx\n"
! "1:\tlodsb\n\t"
! "testb %%al,%%al\n\t"
! "je 2f\n\t"
! "movl %4,%%edi\n\t"
! "movl %%edx,%%ecx\n\t"
! "repne\n\t"
! "scasb\n\t"
! "jne 1b\n\t"
! "decl %0\n\t"
! "jmp 3f\n"
! "2:\txorl %0,%0\n"
! "3:"
! :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
! :"ax","cx","dx","di");
return __res;
}

#define __HAVE_ARCH_STRSTR
extern inline char * strstr(const char * cs,const char * ct)
{
register char * __res;
__asm__ __volatile__(
"cld\n\t" \
! "movl %4,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
! "1:\tmovl %4,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
--- 184,207 ----
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
! :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
return __res;
}

#define __HAVE_ARCH_STRSTR
extern inline char * strstr(const char * cs,const char * ct)
{
+ int d0, d1, d2, d3;
register char * __res;
__asm__ __volatile__(
"cld\n\t" \
! "movl %8,%%edi\n\t"
"repne\n\t"
"scasb\n\t"
"notl %%ecx\n\t"
"decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
"movl %%ecx,%%edx\n"
! "1:\tmovl %8,%%edi\n\t"
"movl %%esi,%%eax\n\t"
"movl %%edx,%%ecx\n\t"
"repe\n\t"
*************** __asm__ __volatile__(
*** 283,296 ****
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
! :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
! :"cx","dx","di","si");
return __res;
}

#define __HAVE_ARCH_STRLEN
extern inline size_t strlen(const char * s)
{
register int __res;
__asm__ __volatile__(
"cld\n\t"
--- 213,226 ----
"jne 1b\n\t"
"xorl %%eax,%%eax\n\t"
"2:"
! :"=a" (__res), "=&c" (d0), "=&S" (d1), "=&d" (d2), "=&D" (d3) : "0" (0),"1" (0xffffffff),"2" (cs),"g" (ct));
return __res;
}

#define __HAVE_ARCH_STRLEN
extern inline size_t strlen(const char * s)
{
+ int d0;
register int __res;
__asm__ __volatile__(
"cld\n\t"
*************** __asm__ __volatile__(
*** 298,383 ****
"scasb\n\t"
"notl %0\n\t"
"decl %0"
! :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
! return __res;
! }
!
! #define __HAVE_ARCH_STRTOK
! extern inline char * strtok(char * s,const char * ct)
! {
! register char * __res;
! __asm__ __volatile__(
! "testl %1,%1\n\t"
! "jne 1f\n\t"
! "testl %0,%0\n\t"
! "je 8f\n\t"
! "movl %0,%1\n"
! "1:\txorl %0,%0\n\t"
! "movl $-1,%%ecx\n\t"
! "xorl %%eax,%%eax\n\t"
! "cld\n\t"
! "movl %4,%%edi\n\t"
! "repne\n\t"
! "scasb\n\t"
! "notl %%ecx\n\t"
! "decl %%ecx\n\t"
! "je 7f\n\t" /* empty delimiter-string */
! "movl %%ecx,%%edx\n"
! "2:\tlodsb\n\t"
! "testb %%al,%%al\n\t"
! "je 7f\n\t"
! "movl %4,%%edi\n\t"
! "movl %%edx,%%ecx\n\t"
! "repne\n\t"
! "scasb\n\t"
! "je 2b\n\t"
! "decl %1\n\t"
! "cmpb $0,(%1)\n\t"
! "je 7f\n\t"
! "movl %1,%0\n"
! "3:\tlodsb\n\t"
! "testb %%al,%%al\n\t"
! "je 5f\n\t"
! "movl %4,%%edi\n\t"
! "movl %%edx,%%ecx\n\t"
! "repne\n\t"
! "scasb\n\t"
! "jne 3b\n\t"
! "decl %1\n\t"
! "cmpb $0,(%1)\n\t"
! "je 5f\n\t"
! "movb $0,(%1)\n\t"
! "incl %1\n\t"
! "jmp 6f\n"
! "5:\txorl %1,%1\n"
! "6:\tcmpb $0,(%0)\n\t"
! "jne 7f\n\t"
! "xorl %0,%0\n"
! "7:\ttestl %0,%0\n\t"
! "jne 8f\n\t"
! "movl %0,%1\n"
! "8:"
! :"=b" (__res),"=S" (___strtok)
! :"0" (___strtok),"1" (s),"g" (ct)
! :"ax","cx","dx","di","memory");
return __res;
}

extern inline void * __memcpy(void * to, const void * from, size_t n)
{
__asm__ __volatile__(
"cld\n\t"
"rep ; movsl\n\t"
! "testb $2,%b1\n\t"
"je 1f\n\t"
"movsw\n"
! "1:\ttestb $1,%b1\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
! : /* no output */
! :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from)
! : "cx","di","si","memory");
return (to);
}

--- 228,253 ----
"scasb\n\t"
"notl %0\n\t"
"decl %0"
! :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
return __res;
}

extern inline void * __memcpy(void * to, const void * from, size_t n)
{
+ int d0, d1, d2;
__asm__ __volatile__(
"cld\n\t"
"rep ; movsl\n\t"
! "testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
! "1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n"
"2:"
! : "=&c" (d0), "=&D" (d1), "=&S" (d2)
! :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
! : "memory");
return (to);
}

*************** extern inline void * __constant_memcpy(v
*** 431,449 ****
return to;
}
#define COMMON(x) \
! __asm__("cld\n\t" \
"rep ; movsl" \
x \
! : /* no outputs */ \
! : "c" (n/4),"D" ((long) to),"S" ((long) from) \
! : "cx","di","si","memory");
!
switch (n % 4) {
case 0: COMMON(""); return to;
case 1: COMMON("\n\tmovsb"); return to;
case 2: COMMON("\n\tmovsw"); return to;
default: COMMON("\n\tmovsw\n\tmovsb"); return to;
}
#undef COMMON
}

--- 301,323 ----
return to;
}
#define COMMON(x) \
! __asm__ __volatile__( \
! "cld\n\t" \
"rep ; movsl" \
x \
! : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
! : "0" (n/4),"1" ((long) to),"2" ((long) from) \
! : "memory");
! {
! int d0, d1, d2;
switch (n % 4) {
case 0: COMMON(""); return to;
case 1: COMMON("\n\tmovsb"); return to;
case 2: COMMON("\n\tmovsw"); return to;
default: COMMON("\n\tmovsw\n\tmovsb"); return to;
}
+ }
+
#undef COMMON
}

*************** __asm__("cld\n\t" \
*** 456,480 ****
#define __HAVE_ARCH_MEMMOVE
extern inline void * memmove(void * dest,const void * src, size_t n)
{
if (dest<src)
__asm__ __volatile__(
"cld\n\t"
"rep\n\t"
"movsb"
! : /* no output */
! :"c" (n),"S" (src),"D" (dest)
! :"cx","si","di");
else
__asm__ __volatile__(
"std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
! : /* no output */
! :"c" (n),
! "S" (n-1+(const char *)src),
! "D" (n-1+(char *)dest)
! :"cx","si","di","memory");
return dest;
}

--- 330,355 ----
#define __HAVE_ARCH_MEMMOVE
extern inline void * memmove(void * dest,const void * src, size_t n)
{
+ int d0, d1, d2;
if (dest<src)
__asm__ __volatile__(
"cld\n\t"
"rep\n\t"
"movsb"
! : "=&c" (d0), "=&S" (d1), "=&D" (d2)
! :"0" (n),"1" (src),"2" (dest)
! : "memory");
else
__asm__ __volatile__(
"std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
! : "=&c" (d0), "=&S" (d1), "=&D" (d2)
! :"0" (n),
! "1" (n-1+(const char *)src),
! "2" (n-1+(char *)dest)
! :"memory");
return dest;
}

*************** return dest;
*** 483,488 ****
--- 358,364 ----
#define __HAVE_ARCH_MEMCHR
extern inline void * memchr(const void * cs,int c,size_t count)
{
+ int d0;
register void * __res;
if (!count)
return NULL;
*************** __asm__ __volatile__(
*** 493,512 ****
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
! :"=D" (__res):"a" (c),"D" (cs),"c" (count)
! :"cx");
return __res;
}

extern inline void * __memset_generic(void * s, char c,size_t count)
{
__asm__ __volatile__(
"cld\n\t"
"rep\n\t"
"stosb"
! : /* no output */
! :"a" (c),"D" (s),"c" (count)
! :"cx","di","memory");
return s;
}

--- 369,388 ----
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
! :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
return __res;
}

extern inline void * __memset_generic(void * s, char c,size_t count)
{
+ int d0, d1;
__asm__ __volatile__(
"cld\n\t"
"rep\n\t"
"stosb"
! : "=&c" (d0), "=&D" (d1)
! :"a" (c),"1" (s),"0" (count)
! :"memory");
return s;
}

*************** return s;
*** 520,538 ****
*/
extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
{
__asm__ __volatile__(
"cld\n\t"
"rep ; stosl\n\t"
! "testb $2,%b1\n\t"
"je 1f\n\t"
"stosw\n"
! "1:\ttestb $1,%b1\n\t"
"je 2f\n\t"
"stosb\n"
"2:"
! : /* no output */
! :"a" (c), "q" (count), "c" (count/4), "D" ((long) s)
! :"cx","di","memory");
return (s);
}

--- 396,415 ----
*/
extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
{
+ int d0, d1;
__asm__ __volatile__(
"cld\n\t"
"rep ; stosl\n\t"
! "testb $2,%b3\n\t"
"je 1f\n\t"
"stosw\n"
! "1:\ttestb $1,%b3\n\t"
"je 2f\n\t"
"stosb\n"
"2:"
! : "=&c" (d0), "=&D" (d1)
! :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
! :"memory");
return (s);
}

*************** return (s);
*** 540,559 ****
#define __HAVE_ARCH_STRNLEN
extern inline size_t strnlen(const char * s, size_t count)
{
register int __res;
__asm__ __volatile__(
! "movl %1,%0\n\t"
"jmp 2f\n"
"1:\tcmpb $0,(%0)\n\t"
"je 3f\n\t"
"incl %0\n"
! "2:\tdecl %2\n\t"
! "cmpl $-1,%2\n\t"
"jne 1b\n"
! "3:\tsubl %1,%0"
! :"=a" (__res)
! :"c" (s),"d" (count)
! :"dx");
return __res;
}
/* end of additional stuff */
--- 417,436 ----
#define __HAVE_ARCH_STRNLEN
extern inline size_t strnlen(const char * s, size_t count)
{
+ int d0;
register int __res;
__asm__ __volatile__(
! "movl %2,%0\n\t"
"jmp 2f\n"
"1:\tcmpb $0,(%0)\n\t"
"je 3f\n\t"
"incl %0\n"
! "2:\tdecl %1\n\t"
! "cmpl $-1,%1\n\t"
"jne 1b\n"
! "3:\tsubl %2,%0"
! :"=a" (__res), "=&d" (d0)
! :"c" (s),"1" (count));
return __res;
}
/* end of additional stuff */
*************** extern inline void * __constant_c_and_co
*** 582,600 ****
return s;
}
#define COMMON(x) \
! __asm__("cld\n\t" \
"rep ; stosl" \
x \
! : /* no outputs */ \
! : "a" (pattern),"c" (count/4),"D" ((long) s) \
! : "cx","di","memory")
!
switch (count % 4) {
case 0: COMMON(""); return s;
case 1: COMMON("\n\tstosb"); return s;
case 2: COMMON("\n\tstosw"); return s;
default: COMMON("\n\tstosw\n\tstosb"); return s;
}
#undef COMMON
}

--- 459,480 ----
return s;
}
#define COMMON(x) \
! __asm__ __volatile__("cld\n\t" \
"rep ; stosl" \
x \
! : "=&c" (d0), "=&D" (d1) \
! : "a" (pattern),"0" (count/4),"1" ((long) s) \
! : "memory")
! {
! int d0, d1;
switch (count % 4) {
case 0: COMMON(""); return s;
case 1: COMMON("\n\tstosb"); return s;
case 2: COMMON("\n\tstosw"); return s;
default: COMMON("\n\tstosw\n\tstosb"); return s;
}
+ }
+
#undef COMMON
}

*** ./include/asm-i386/system.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/system.h Tue Aug 25 10:07:15 1998
*************** extern void __global_restore_flags(unsig
*** 228,242 ****
#endif

#define _set_gate(gate_addr,type,dpl,addr) \
! __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
! "movw %2,%%dx\n\t" \
"movl %%eax,%0\n\t" \
"movl %%edx,%1" \
:"=m" (*((long *) (gate_addr))), \
! "=m" (*(1+(long *) (gate_addr))) \
:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
! "d" ((char *) (addr)),"a" (__KERNEL_CS << 16) \
! :"ax","dx")

#define set_intr_gate(n,addr) \
_set_gate(idt+(n),14,0,addr)
--- 228,245 ----
#endif

#define _set_gate(gate_addr,type,dpl,addr) \
! do { \
! int __d0, __d1; \
! __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
! "movw %4,%%dx\n\t" \
"movl %%eax,%0\n\t" \
"movl %%edx,%1" \
:"=m" (*((long *) (gate_addr))), \
! "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
:"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
! "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
! } while (0)
!

#define set_intr_gate(n,addr) \
_set_gate(idt+(n),14,0,addr)
*** ./include/asm-i386/uaccess.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/uaccess.h Tue Aug 25 10:31:46 1998
*************** do { \
*** 250,262 ****

/* Generic arbitrary sized copy. */
#define __copy_user(to,from,size) \
__asm__ __volatile__( \
"0: rep; movsl\n" \
! " movl %1,%0\n" \
"1: rep; movsb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: lea 0(%1,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
--- 250,264 ----

/* Generic arbitrary sized copy. */
#define __copy_user(to,from,size) \
+ do { \
+ int __d0, __d1; \
__asm__ __volatile__( \
"0: rep; movsl\n" \
! " movl %3,%0\n" \
"1: rep; movsb\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
! "3: lea 0(%3,%0,4),%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
*************** do { \
*** 264,272 ****
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
! : "=&c"(size) \
! : "r"(size & 3), "0"(size / 4), "D"(to), "S"(from) \
! : "di", "si", "memory")

/* We let the __ versions of copy_from/to_user inline, because they're often
* used in fast paths and have only a small space overhead.
--- 266,275 ----
" .long 0b,3b\n" \
" .long 1b,2b\n" \
".previous" \
! : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \
! : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \
! : "memory"); \
! } while (0)

/* We let the __ versions of copy_from/to_user inline, because they're often
* used in fast paths and have only a small space overhead.
*************** __generic_copy_to_user_nocheck(void *to,
*** 289,294 ****
--- 292,298 ----
/* Optimize just a little bit when we know the size of the move. */
#define __constant_copy_user(to, from, size) \
do { \
+ int __d0, __d1; \
switch (size & 3) { \
default: \
__asm__ __volatile__( \
*************** do { \
*** 302,310 ****
" .align 4\n" \
" .long 0b,2b\n" \
".previous" \
! : "=c"(size) \
! : "S"(from), "D"(to), "0"(size/4) \
! : "di", "si", "memory"); \
break; \
case 1: \
__asm__ __volatile__( \
--- 306,314 ----
" .align 4\n" \
" .long 0b,2b\n" \
".previous" \
! : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
! : "1"(from), "2"(to), "0"(size/4) \
! : "memory"); \
break; \
case 1: \
__asm__ __volatile__( \
*************** do { \
*** 321,329 ****
" .long 0b,3b\n" \
" .long 1b,4b\n" \
".previous" \
! : "=c"(size) \
! : "S"(from), "D"(to), "0"(size/4) \
! : "di", "si", "memory"); \
break; \
case 2: \
__asm__ __volatile__( \
--- 325,333 ----
" .long 0b,3b\n" \
" .long 1b,4b\n" \
".previous" \
! : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
! : "1"(from), "2"(to), "0"(size/4) \
! : "memory"); \
break; \
case 2: \
__asm__ __volatile__( \
*************** do { \
*** 340,348 ****
" .long 0b,3b\n" \
" .long 1b,4b\n" \
".previous" \
! : "=c"(size) \
! : "S"(from), "D"(to), "0"(size/4) \
! : "di", "si", "memory"); \
break; \
case 3: \
__asm__ __volatile__( \
--- 344,352 ----
" .long 0b,3b\n" \
" .long 1b,4b\n" \
".previous" \
! : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
! : "1"(from), "2"(to), "0"(size/4) \
! : "memory"); \
break; \
case 3: \
__asm__ __volatile__( \
*************** do { \
*** 362,370 ****
" .long 1b,5b\n" \
" .long 2b,6b\n" \
".previous" \
! : "=c"(size) \
! : "S"(from), "D"(to), "0"(size/4) \
! : "di", "si", "memory"); \
break; \
} \
} while (0)
--- 366,374 ----
" .long 1b,5b\n" \
" .long 2b,6b\n" \
".previous" \
! : "=c"(size), "=&S" (__d0), "=&D" (__d1)\
! : "1"(from), "2"(to), "0"(size/4) \
! : "memory"); \
break; \
} \
} while (0)
*** ./include/asm-i386/bitops.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/bitops.h Tue Aug 25 10:07:15 1998
*************** extern __inline__ int __test_bit(int nr,
*** 127,132 ****
--- 127,133 ----
*/
extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
{
+ int d0, d1, d2;
int res;

if (!size)
*************** extern __inline__ int find_first_zero_bi
*** 142,150 ****
"1:\tsubl %%ebx,%%edi\n\t"
"shll $3,%%edi\n\t"
"addl %%edi,%%edx"
! :"=d" (res)
! :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
! :"ax", "cx", "di");
return res;
}

--- 143,150 ----
"1:\tsubl %%ebx,%%edi\n\t"
"shll $3,%%edi\n\t"
"addl %%edi,%%edx"
! :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
! :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
return res;
}

*** ./include/asm-i386/posix_types.h.orig-1 Tue Aug 25 09:45:47 1998
--- ./include/asm-i386/posix_types.h Tue Aug 25 10:07:15 1998
*************** typedef struct {
*** 59,68 ****

#undef __FD_ZERO
#define __FD_ZERO(fdsetp) \
! __asm__ __volatile__("cld ; rep ; stosl" \
! :"=m" (*(__kernel_fd_set *) (fdsetp)) \
! :"a" (0), "c" (__FDSET_LONGS), \
! "D" ((__kernel_fd_set *) (fdsetp)) :"cx","di")

#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */

--- 59,72 ----

#undef __FD_ZERO
#define __FD_ZERO(fdsetp) \
! do { \
! int __d0, __d1; \
! __asm__ __volatile__("cld ; rep ; stosl" \
! :"=m" (*(__kernel_fd_set *) (fdsetp)), \
! "=&c" (__d0), "=&D" (__d1) \
! :"a" (0), "1" (__FDSET_LONGS), \
! "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
! } while (0)

#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html

\
 
 \ /
  Last update: 2005-03-22 13:44    [W:0.048 / U:0.248 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site