Messages in this thread Patch in this message | | | Date | Thu, 2 Oct 1997 23:24:52 +0100 (MET) | From | Gabriel Paubert <> | Subject | Re: AMD K6 |
| |
On Thu, 2 Oct 1997, Aaron Tiensivu wrote:
> > WHERE can I find PGCC ??? > > ftp.goof.com > > > Does it compile the kernel without problems? > > AFAICT.
It won't compile correctly the following network drivers:
de4x5, depca, ewrk3
(tested on 970924 pgcc release).
I have a patch (attached) which seems to work, and hope it does not break anything else. The file to patch is linux/include/asm-i386/string.h.
I had myself problems to believe that this could be the cause. Code generated without the patch is _obviously_ wrong at the machine code level where inlined strstr() are used. See the attached example.
If anybody uses one of these network drivers, please tell me the result. This patch could do very bad things it it has a glitch. But I have the impression that I have finally learnt to use inline assembly constraints correctly.
BTW: I have seen that there is a single ___strtok global variable in the whole kernel (even 2.1.56). Is it SMP safe ?
Gabriel.The following code: for (i=0; i<siglen; i++) { if (strstr(name,de4x5_signatures[i])!=NULL) break; }
generates (see what happens to %edi):
00004c68 <PCI_signature+94> xorl %ebx,%ebx 00004c6a <PCI_signature+96> cmpl $0x5,%ebx 00004c6d <PCI_signature+99> jnl 00004cae <PCI_signature+da> 00004c6f <PCI_signature+9b> leal 0x18(%esp,1),%ecx 00004c73 <PCI_signature+9f> movl %ecx,0x10(%esp,1) 00004c77 <PCI_signature+a3> xorl %eax,%eax 00004c79 <PCI_signature+a5> movl $0xffffffff,%ecx 00004c7e <PCI_signature+aa> movl %ebp,%esi 00004c80 <PCI_signature+ac> movl 0x10(%esp,1),%edi 00004c84 <PCI_signature+b0> cld 00004c85 <PCI_signature+b1> movl (%edi,%ebx,4),%edi 00004c88 <PCI_signature+b4> repnz scasb %es:(%edi),%al 00004c8a <PCI_signature+b6> notl %ecx 00004c8c <PCI_signature+b8> decl %ecx 00004c8d <PCI_signature+b9> movl %ecx,%edx 00004c8f <PCI_signature+bb> movl (%edi,%ebx,4),%edi 00004c92 <PCI_signature+be> movl %esi,%eax 00004c94 <PCI_signature+c0> movl %edx,%ecx 00004c96 <PCI_signature+c2> repz cmpsb %ds:(%esi),%es:(%edi) 00004c98 <PCI_signature+c4> je 00004ca4 <PCI_signature+d0> 00004c9a <PCI_signature+c6> xchgl %eax,%esi 00004c9b <PCI_signature+c7> incl %esi 00004c9c <PCI_signature+c8> cmpb $0x0,0xffffffff(%eax) 00004ca0 <PCI_signature+cc> jne 00004c8f <PCI_signature+bb> 00004ca2 <PCI_signature+ce> xorl %eax,%eax 00004ca4 <PCI_signature+d0> testl %eax,%eax 00004ca6 <PCI_signature+d2> jne 00004cae <PCI_signature+da> 00004ca8 <PCI_signature+d4> incl %ebx 00004ca9 <PCI_signature+d5> cmpl $0x5,%ebx 00004cac <PCI_signature+d8> jl 00004c77 <PCI_signature+a3> --- linux-2.0.30/include/asm-i386/string.h.virgin Wed Oct 1 10:55:48 1997 +++ linux-2.0.30/include/asm-i386/string.h Thu Oct 2 21:52:47 1997 @@ -26,6 +26,23 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +/* + * Found a serious problem with constraints revealed by compiling with pgcc. + * + * First attempt to fix it by G.Paubert, paubert@iram.es, 1997 + * + * Consider for now this code as experimentation on gcc inline assembly. + * Use at your own risk. + * + * I have also the feeling that many "memory" are superfluous: + * when passing a char *, resp. a const char *, the compiler should assume + * that the value or array pointed to is modified, resp referenced. + * The fact that the function is declared extern inline should not change + * these semantics. + * + */ + + #define __HAVE_ARCH_STRCPY extern inline char * strcpy(char * dest,const char *src) { @@ -36,7 +53,7 @@ "testb %%al,%%al\n\t" "jne 1b" : /* no output */ - :"S" (src),"D" (dest):"si","di","ax","memory"); + :"S" (src),"D" (dest):"si","di","ax"/*,"memory"*/); return dest; } @@ -55,7 +72,7 @@ "stosb\n" "2:" : /* no output */ - :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx","memory"); + :"S" (src),"D" (dest),"c" (count):"si","di","ax","cx"/*,"memory"*/); return dest; } @@ -95,7 +112,7 @@ "stosb" : /* no output */ :"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) - :"si","di","ax","cx","memory"); + :"si","di","ax","cx"/*,"memory"*/); return dest; } @@ -181,25 +198,29 @@ extern inline size_t strspn(const char * cs, const char * ct) { register char * __res; +const char * __ct; +int __len; __asm__ __volatile__( "cld\n\t" - "movl %4,%%edi\n\t" + "movl %6,%%edi\n\t" "repne\n\t" "scasb\n\t" "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" + "leal -1(%%ecx),%1\n\t" "1:\tlodsb\n\t" "testb %%al,%%al\n\t" "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" + "movl %6,%%edi\n\t" + "movl %1,%%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"); + /* This constraint set leaves few choices to gcc, but usually works. + Change "=&r" (__len) to "=&rm" (__len) if the compiler complains. */ + :"=S" (__res), "=&r" (__len), "=&D" (__ct) + :"a" (0),"c" (0xffffffff),"0" (cs), "g" (ct) + :"ax","cx"); return __res-cs; } @@ -207,83 +228,95 @@ extern inline size_t strcspn(const char * cs, const char * ct) { register char * __res; +const char * __ct; +int __len; __asm__ __volatile__( "cld\n\t" - "movl %4,%%edi\n\t" + "movl %6,%%edi\n\t" "repne\n\t" "scasb\n\t" "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" + "leal -1(%%ecx),%1\n\t" "1:\tlodsb\n\t" "testb %%al,%%al\n\t" "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" + "movl %6,%%edi\n\t" + "movl %1,%%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"); + /* This constraint set leaves few choices to gcc, but usually works. + Change "=&r" (__len) to "=&rm" (__len) if the compiler complains. */ + :"=S" (__res), "=&r" (__len), "=&D" (__ct) + :"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) + :"ax","cx"); return __res-cs; } #define __HAVE_ARCH_STRPBRK extern inline char * strpbrk(const char * cs,const char * ct) { -register char * __res; +char * __res; +const char * __ct; +int __len; __asm__ __volatile__( "cld\n\t" - "movl %4,%%edi\n\t" + "movl %6,%%edi\n\t" "repne\n\t" "scasb\n\t" "notl %%ecx\n\t" - "decl %%ecx\n\t" - "movl %%ecx,%%edx\n" + "leal -1(%%ecx),%1\n\t" "1:\tlodsb\n\t" "testb %%al,%%al\n\t" - "je 2f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" + "je 2f\n\t" /* Here %eax is zero if branch taken ! */ + "movl %6,%%edi\n\t" + "movl %1,%%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"); + "leal -1(%%esi),%%eax\n\t" + "2:" + /* This constraint set leaves few choices to gcc, but usually works. + Change "=&r" (__len) to "=&rm" (__len) if the compiler complains. */ + :"=a" (__res), "=&r" (__len), "=&D" (__ct) + :"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) + :"cx","si"); return __res; } #define __HAVE_ARCH_STRSTR extern inline char * strstr(const char * cs,const char * ct) { -register char * __res; +char * __res; +const char *__ct; +int __len; __asm__ __volatile__( - "cld\n\t" \ - "movl %4,%%edi\n\t" + "cld\n\t" + "movl %6,%%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 %%ecx,%1\n" + "1:\tmovl %6,%%edi\n\t" "movl %%esi,%%eax\n\t" - "movl %%edx,%%ecx\n\t" "repe\n\t" "cmpsb\n\t" "je 2f\n\t" /* also works for empty string, see above */ "xchgl %%eax,%%esi\n\t" + "movl %1,%%ecx\n\t" "incl %%esi\n\t" "cmpb $0,-1(%%eax)\n\t" "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "2:" - :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) - :"cx","dx","di","si"); + /* This constraint set leaves few choices to gcc, but usually works, + and pgcc complains with impossible constraints if __len is declared + as "=&r" when compiling de4x5.c ! */ + :"=a" (__res), "=&rm" (__len), "=&D" (__ct) + :"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) + :"cx","si"); return __res; } @@ -304,7 +337,9 @@ #define __HAVE_ARCH_STRTOK extern inline char * strtok(char * s,const char * ct) { -register char * __res; +char * __res; +const char * __ct; +int __len, __cnt, __val; __asm__ __volatile__( "testl %1,%1\n\t" "jne 1f\n\t" @@ -315,18 +350,18 @@ "movl $-1,%%ecx\n\t" "xorl %%eax,%%eax\n\t" "cld\n\t" - "movl %4,%%edi\n\t" + "movl %8,%%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" + "movl %%ecx,%2\n" "2:\tlodsb\n\t" "testb %%al,%%al\n\t" "je 7f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" + "movl %8,%%edi\n\t" + "movl %2,%%ecx\n\t" "repne\n\t" "scasb\n\t" "je 2b\n\t" @@ -337,8 +372,8 @@ "3:\tlodsb\n\t" "testb %%al,%%al\n\t" "je 5f\n\t" - "movl %4,%%edi\n\t" - "movl %%edx,%%ecx\n\t" + "movl %8,%%edi\n\t" + "movl %2,%%ecx\n\t" "repne\n\t" "scasb\n\t" "jne 3b\n\t" @@ -356,9 +391,12 @@ "jne 8f\n\t" "movl %0,%1\n" "8:" - :"=b" (__res),"=S" (___strtok) - :"0" (___strtok),"1" (s),"g" (ct) - :"ax","cx","dx","di","memory"); + /* This constraint set is frightening: if I were the compiler, + I would try to eat the source file to avoid seeing it again :-). + Change "=&r" (__len) to "=&rm" (__len) if the compiler complains. */ + :"=b" (__res),"=S" (___strtok), "=&r" (__len), "=&D" (__ct), + "=&c" (__cnt), "=&a" (__val) + :"0" (___strtok),"1" (s),"g" (ct)); return __res; }
| |