ソースを参照

* fixed all implementations of strpas

Jonas Maebe 24 年 前
コミット
18de59f50c
2 ファイル変更78 行追加42 行削除
  1. 71 38
      rtl/i386/i386.inc
  2. 7 4
      rtl/i386/stringss.inc

+ 71 - 38
rtl/i386/i386.inc

@@ -847,43 +847,76 @@ end;
 {$define FPC_SYSTEM_HAS_FPC_PCHAR_TO_SHORTSTR}
 function strpas(p:pchar):shortstring;[public,alias:'FPC_PCHAR_TO_SHORTSTR'];
 begin
-  asm
-        cld
-        movl    p,%edi
-        movl    $0xff,%ecx
-        orl     %edi,%edi
-        jnz     .LStrPasNotNil
-        decl    %ecx
-        jmp     .LStrPasNil
-.LStrPasNotNil:
-        xorl    %eax,%eax
-        movl    %edi,%esi
-        repne
-        scasb
-.LStrPasNil:
-        movl    %ecx,%eax
+asm
+        movl    p,%esi
         movl    __RESULT,%edi
-        notb    %al
-        decl    %eax
-        stosb
-        cmpl    $7,%eax
-        jl      .LStrPas2
-        movl    %edi,%ecx       { Align on 32bits }
-        negl    %ecx
-        andl    $3,%ecx
-        subl    %ecx,%eax
-        rep
-        movsb
-        movl    %eax,%ecx
-        andl    $3,%eax
-        shrl    $2,%ecx
-        rep
-        movsl
-.LStrPas2:
-        movl    %eax,%ecx
-        rep
-        movsb
-  end ['ECX','EAX','ESI','EDI'];
+        leal    3(%esi),%edx
+        movl    $1,%ecx
+        andl    $-4,%edx
+        // skip length byte
+        incl    %edi
+        subl    %esi,%edx
+        jz      .LStrPasAligned
+        // align source to multiple of 4 (not dest, because we can't read past
+        // the end of the source, since that may be past the end of the heap
+        // -> sigsegv!!)
+.LStrPasAlignLoop:
+        movb    (%esi),%al
+        incl    %esi
+        testb   %al,%al
+        jz      .LStrPasDone
+        incl    %edi
+        incb    %cl
+        decb    %dl
+        movb    %al,-1(%edi)
+        jne     .LStrPasAlignLoop
+        .balign  16
+.LStrPasAligned:
+        movl    (%esi),%ebx
+        addl    $4,%edi
+        leal    0x0fefefeff(%ebx),%eax
+        movl    %ebx,%edx
+        addl    $4,%esi
+        notl    %edx
+        andl    %edx,%eax
+        addl    $4,%ecx
+        andl    $0x080808080,%eax
+        movl    %ebx,-4(%edi)
+        jnz     .LStrPasEndFound
+        cmpl    $252,%ecx
+        ja      .LStrPasPreEndLoop
+        jmp     .LStrPasAligned
+.LStrPasEndFound:
+        subl    $4,%ecx
+        // this won't overwrite data since the result = 255 char string
+        // and we never process more than the first 255 chars of p
+        shrl    $8,%eax
+        jc      .LStrPasDone
+        incl    %ecx
+        shrl    $8,%eax
+        jc      .LStrPasDone
+        incl    %ecx
+        shrl    $8,%eax
+        jc      .LStrPasDone
+        incl    %ecx
+        jmp     .LStrPasDone
+.LStrPasPreEndLoop:
+        testb   %cl,%cl
+        jz      .LStrPasDone
+        movl    (%esi),%eax
+.LStrPasEndLoop:
+        testb   %al,%al
+        jz      .LStrPasDone
+        movb    %al,(%edi)
+        shrl    $8,%eax
+        incl    %edi
+        incb    %cl
+        jnz     .LStrPasEndLoop
+.LStrPasDone:
+        movl    __RESULT,%edi
+        addb    $255,%cl
+        movb    %cl,(%edi)
+end ['EAX','EBX','ECX','EDX','ESI','EDI'];
 end;
 
 
@@ -1164,8 +1197,8 @@ procedure inclocked(var l : longint);assembler;
 
 {
   $Log$
-  Revision 1.6  2001-03-03 12:41:22  jonas
-    * simplified and optimized range checking code, FPC_BOUNDCHECK is no longer necessary
+  Revision 1.7  2001-03-04 17:31:34  jonas
+    * fixed all implementations of strpas
 
   Revision 1.5  2000/11/12 23:23:34  florian
     * interfaces basically running

+ 7 - 4
rtl/i386/stringss.inc

@@ -61,13 +61,13 @@ asm
         // this won't overwrite data since the result = 255 char string
         // and we never process more than the first 255 chars of p
         shrl    $8,%eax
-        jz      .LStrPasDone
+        jc      .LStrPasDone
         incl    %ecx
         shrl    $8,%eax
-        jz      .LStrPasDone
+        jc      .LStrPasDone
         incl    %ecx
         shrl    $8,%eax
-        jz      .LStrPasDone
+        jc      .LStrPasDone
         incl    %ecx
         jmp     .LStrPasDone
 .LStrPasPreEndLoop:
@@ -106,7 +106,10 @@ end ['EDI','EAX','ECX'];
 
 {
   $Log$
-  Revision 1.4  2001-03-04 12:42:18  jonas
+  Revision 1.5  2001-03-04 17:31:35  jonas
+    * fixed all implementations of strpas
+
+  Revision 1.4  2001/03/04 12:42:18  jonas
     * fixed strpas (was limited to 254 chars) and made it overall slightly faster
 
   Revision 1.3  2001/02/10 16:08:46  jonas