diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 4f64bad7be..65c4306057 100644 --- a/rtl/i386/i386.inc +++ b/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 diff --git a/rtl/i386/stringss.inc b/rtl/i386/stringss.inc index 800252dfcc..09c54515e8 100644 --- a/rtl/i386/stringss.inc +++ b/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