From cd8913b88e630a662235ab48ad3f716b8873b3a0 Mon Sep 17 00:00:00 2001 From: florian Date: Fri, 3 Jun 2011 20:35:55 +0000 Subject: [PATCH] * improved Compare(D)Word as well git-svn-id: trunk@17651 - --- rtl/i386/i386.inc | 110 ++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 38 deletions(-) diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index bfff83a982..a6b451cad8 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -481,30 +481,44 @@ end; {$endif FPC_SYSTEM_HAS_COMPAREBYTE} - {$ifndef FPC_SYSTEM_HAS_COMPAREWORD} {$define FPC_SYSTEM_HAS_COMPAREWORD} -function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; -var - saveesi,saveedi,saveebx : longint; +function CompareWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe; asm - movl %edi,saveedi - movl %esi,saveesi - movl %ebx,saveebx + cmpl $32,%ecx { empirical average value, on a Athlon XP the + break even is at 14, on a Core 2 Duo > 100 } + jg .LCmpWordFull + testl %ecx,%ecx + je .LCmpWordZero + + pushl %ebx +.LCmpWordLoop: + movw (%eax),%bx + cmpw (%edx),%bx + leal 2(%eax),%eax + leal 2(%edx),%edx + jne .LCmpWordExitFast + decl %ecx + jne .LCmpWordLoop +.LCmpWordExitFast: + movzwl -2(%edx),%ecx { Compare last position } + movzwl %bx,%eax + subl %ecx,%eax + popl %ebx + ret + +.LCmpWordZero: + movl $0,%eax + ret + +.LCmpWordFull: + pushl %esi + pushl %edi + pushl %ebx cld -{$ifdef REGCALL} movl %eax,%edi movl %edx,%esi movl %ecx,%eax -{$else} - movl buf2,%esi { Load params} - movl buf1,%edi - movl len,%eax -{$endif} - testl %eax,%eax {We address -2(%esi), so we have to deal with len=0} - je .LCmpwordExit - cmpl $5,%eax {<5 (3 bytes align + 4 bytes cmpsl = 4 words} - jl .LCmpword2 { not worth aligning and go through all trouble} movl (%edi),%ebx // Compare alignment bytes. cmpl (%esi),%ebx jne .LCmpword2 // Aligning will go wrong already. Max 2 words will be scanned Branch NOW @@ -543,35 +557,55 @@ asm movzwl -2(%edi),%eax // Compare failing (or equal) position subl %ecx,%eax // calculate end result. .LCmpwordExit: - movl saveedi,%edi - movl saveesi,%esi - movl saveebx,%ebx + popl %ebx + popl %edi + popl %esi end; {$endif FPC_SYSTEM_HAS_COMPAREWORD} {$ifndef FPC_SYSTEM_HAS_COMPAREDWORD} {$define FPC_SYSTEM_HAS_COMPAREDWORD} -function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; -var - saveesi,saveedi,saveebx : longint; +function CompareDWord(Const buf1,buf2;len:SizeInt):SizeInt; assembler; nostackframe; asm - movl %edi,saveedi - movl %esi,saveesi + cmpl $32,%ecx { empirical average value, on a Athlon XP the + break even is at 12, on a Core 2 Duo > 100 } + jg .LCmpDWordFull + testl %ecx,%ecx + je .LCmpDWordZero + + pushl %ebx +.LCmpDWordLoop: + movl (%eax),%ebx + cmpl (%edx),%ebx + leal 4(%eax),%eax + leal 4(%edx),%edx + jne .LCmpDWordExitFast + decl %ecx + jne .LCmpDWordLoop +.LCmpDWordExitFast: + xorl %eax,%eax + movl -4(%edx),%edx // Compare failing (or equal) position + subl %edx,%ebx // calculate end result. + setb %dl + seta %cl + addb %cl,%al + subb %dl,%al + movsbl %al,%eax + + popl %ebx + ret + +.LCmpDWordZero: + movl $0,%eax + ret + +.LCmpDWordFull: + pushl %esi + pushl %edi cld -{$ifdef REGCALL} movl %eax,%edi movl %edx,%esi - movl %ecx,%eax -{$else} - movl buf2,%esi { Load params} - movl buf1,%edi - movl len,%eax - movl %eax,%ecx -{$endif} - testl %eax,%eax - je .LCmpDwordExit - movl %eax,%ecx xorl %eax,%eax rep { Compare entire DWords} cmpsl @@ -583,8 +617,8 @@ asm subb %dl,%al movsbl %al,%eax .LCmpDwordExit: - movl saveedi,%edi - movl saveesi,%esi + popl %edi + popl %esi end; {$endif FPC_SYSTEM_HAS_COMPAREDWORD}