Browse Source

* new fixed and faster strpas (previous version only returned the first
254 chars when the pchar was aligned on a 4 byte boundary and was >=
255 chars)

Jonas Maebe 25 years ago
parent
commit
93f4c7a312
1 changed files with 70 additions and 32 deletions
  1. 70 32
      rtl/i386/stringss.inc

+ 70 - 32
rtl/i386/stringss.inc

@@ -18,43 +18,76 @@
 function strpas(p : pchar) : string;
 function strpas(p : pchar) : string;
 begin
 begin
 {$ifndef NEWATT}
 {$ifndef NEWATT}
-  strpas:='';
+  strpasopt:='';
 {$endif}
 {$endif}
-  asm
-        cld
-        movl    p,%edi
-        movl    $0xff,%ecx
-        xorl    %eax,%eax
-        movl    %edi,%esi
-        repne
-        scasb
-        movl    %ecx,%eax
+asm
 {$ifdef NEWATT}
 {$ifdef NEWATT}
         movl    __RESULT,%edi
         movl    __RESULT,%edi
 {$else}
 {$else}
         movl    8(%ebp),%edi
         movl    8(%ebp),%edi
 {$endif}
 {$endif}
-        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'];
+        movl    p,%esi
+        // at the end, add 255 to cl to get the string length (byte(1+255) = 0)
+        movb    $1,%cl
+        // skip length byte -> align dest to multiple of 4
+        movl    (%esi),%eax
+        testl   $0x0ff,%eax
+        jz      .LStrPasDone
+        // we only need the first 3 chars currently
+        shll    $8,%eax
+        incb    %cl
+        addl    $3,%esi
+        // Store everything already, since the temp string = 255 chars anyway
+        // The length byte will contain zero this way, but it will be
+        // overwritten at the end, so it doesn't matter       
+        movl    %eax,(%edi)
+        // test the second char (we shifted left 8 bits)
+        testl   $0x0ff0000,%eax
+        jz      .LStrPasDone
+        // for pairing, add 4 to edi here already
+        addl    $4,%edi
+        incb    %cl
+        // test the third char (we shifted left 8 bits)
+        testl   $0x0ff000000,%eax
+        jz      .LStrPasDone
+        incb    %cl
+        .align  16
+.LStrPasLoop:
+        movl    (%esi),%eax
+        addl    $4,%esi
+        // this won't overwrite data since the result = 255 char string
+        movl    %eax,(%edi)
+        testl   $0x0ff,%eax
+        jz      .LStrPasDone
+        testl   $0x0ff00,%eax
+        jz      .LStrPasByte
+        testl   $0x0ff0000,%eax
+        jz      .LStrPasWord
+        testl   $0x0ff000000,%eax
+        jz      .LStrPas3Bytes
+        addl    $4,%edi
+        addb    $4,%cl
+        // since cl = 4 at the start of the loop, it will always count
+        // upto exactly 0
+        jnz     .LStrPasLoop
+        jmp     .LStrPasDone
+.LStrPas3Bytes:
+        addb     $3,%cl
+        jmp     .LStrPasDone
+.LStrPasWord:
+        addb    $2,%cl
+        jmp     .LStrPasDone
+.LStrPasByte:
+        incb    %cl
+.LStrPasDone:
+{$ifdef NEWATT}
+        movl    __RESULT,%edi
+{$else}
+        movl    8(%ebp),%edi
+{$endif}
+        addb    $255,%cl
+        movb    %cl,(%edi)
+end ['EAX','ECX','ESI','EDI'];
 end;
 end;
 
 
 
 
@@ -76,7 +109,12 @@ end ['EDI','EAX','ECX'];
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.10  2000-03-28 11:14:33  jonas
+  Revision 1.11  2000-06-12 08:33:26  jonas
+    * new fixed and faster strpas (previous version only returned the first
+      254 chars when the pchar was aligned on a 4 byte boundary and was >=
+      255 chars)
+
+  Revision 1.10  2000/03/28 11:14:33  jonas
     * added missing register that is destroyed by strecopy
     * added missing register that is destroyed by strecopy
     + some destroyed register lists for procedures that didn't have one yet
     + some destroyed register lists for procedures that didn't have one yet