|
@@ -0,0 +1,515 @@
|
|
|
|
+{
|
|
|
|
+ $Id$
|
|
|
|
+ This file is part of the Free Pascal run time library.
|
|
|
|
+ Copyright (c) 2000 by Jonas Maebe, member of the
|
|
|
|
+ Free Pascal development team
|
|
|
|
+
|
|
|
|
+ Processor dependent part of strings.pp, that can be shared with
|
|
|
|
+ sysutils unit.
|
|
|
|
+
|
|
|
|
+ See the file COPYING.FPC, included in this distribution,
|
|
|
|
+ for details about the copyright.
|
|
|
|
+
|
|
|
|
+ This program is distributed in the hope that it will be useful,
|
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
+
|
|
|
|
+ **********************************************************************}
|
|
|
|
+
|
|
|
|
+{ Note: the implementation of these routines is for BIG ENDIAN only!! (JM) }
|
|
|
|
+
|
|
|
|
+function strcopy(dest,source : pchar) : pchar;assembler;
|
|
|
|
+{ in: dest in r3, source in r4 }
|
|
|
|
+{ out: result (dest) in r3 }
|
|
|
|
+asm
|
|
|
|
+ { empty/invalid string? }
|
|
|
|
+ cmpli r3,0
|
|
|
|
+ { if yes, do nothing }
|
|
|
|
+ beq .LStrCopyDone
|
|
|
|
+ { clear two lowest bits of source address }
|
|
|
|
+ rlwminm r28,r4,0,0,31-2
|
|
|
|
+ { get # of misaligned bytes }
|
|
|
|
+ sub. r28,r28,r4
|
|
|
|
+ { since we have to return dest intact, use another register for }
|
|
|
|
+ { dest in the copy loop }
|
|
|
|
+ mr r29,r3
|
|
|
|
+ beq .LStrCopyAligned
|
|
|
|
+.LStrCopyAlignLoop:
|
|
|
|
+ { decrease misaligned bytes counter (do it here already to improve }
|
|
|
|
+ { jump prediction) }
|
|
|
|
+ subic. r28,1
|
|
|
|
+ { load next byte }
|
|
|
|
+ lbz r27,(r4)
|
|
|
|
+ { end of string? }
|
|
|
|
+ cmpli cr1,r27,0
|
|
|
|
+ { point to next source byte }
|
|
|
|
+ addi r4,r4,1
|
|
|
|
+ { store byte }
|
|
|
|
+ stb r27,(r29)
|
|
|
|
+ { point to next dest address }
|
|
|
|
+ addi r29,r29,1
|
|
|
|
+ { stop if end of string }
|
|
|
|
+ beq cr1,.LStrCopyDone
|
|
|
|
+ bne .LStrCopyAlignLoop
|
|
|
|
+ .balign 16
|
|
|
|
+.LStrCopyAligned:
|
|
|
|
+ { load next 4 bytes }
|
|
|
|
+ lwz r27,(r4)
|
|
|
|
+ { first/highest byte zero? (big endian!) }
|
|
|
|
+ andis. r28,r27,0x0ff00
|
|
|
|
+ addi r4,r4,4
|
|
|
|
+ beq .LStrCopyByte
|
|
|
|
+ { second byte zero? }
|
|
|
|
+ andis. r28,r27,0x00ff
|
|
|
|
+ beq .LStrCopyWord
|
|
|
|
+ { third byte zero? }
|
|
|
|
+ andi. r28,r27,0xff00
|
|
|
|
+ beq .LStrCopy3Bytes
|
|
|
|
+ { fourth byte zero? }
|
|
|
|
+ andi. r28,r27,0x00ff
|
|
|
|
+ { store next 4 bytes }
|
|
|
|
+ stw r27,(r29)
|
|
|
|
+ { increase dest address }
|
|
|
|
+ addi r29,r29,4
|
|
|
|
+ beq .LStrCopyDone
|
|
|
|
+ b .LStrCopyAligned
|
|
|
|
+{ store left-overs }
|
|
|
|
+.LStrCopy3Bytes:
|
|
|
|
+ sth r27,(r29)
|
|
|
|
+ li r27,0
|
|
|
|
+ stb r27,2(r29)
|
|
|
|
+ b .LStrCopyDone
|
|
|
|
+.LStrCopyWord:
|
|
|
|
+ sth r27,(r29)
|
|
|
|
+ b .LStrCopyDone
|
|
|
|
+.LStrCopyByte:
|
|
|
|
+ stb r27,(r29)
|
|
|
|
+.LStrCopyDone:
|
|
|
|
+ { r3 still contains dest here }
|
|
|
|
+end ['r4','r27','r28','r29','cr0','cr1'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strecopy(dest,source : pchar) : pchar;assembler;
|
|
|
|
+{ in: dest in r3, source in r4 }
|
|
|
|
+{ out: result (end of new dest) in r3 }
|
|
|
|
+asm
|
|
|
|
+ { empty/invalid string? }
|
|
|
|
+ cmpli r3,0
|
|
|
|
+ { if yes, do nothing }
|
|
|
|
+ beq .LStreCopyDone
|
|
|
|
+ { clear two lowest bits of source address }
|
|
|
|
+ rlwminm r28,r4,0,0,31-2
|
|
|
|
+ { get # of misaligned bytes }
|
|
|
|
+ sub. r28,r28,r4
|
|
|
|
+ beq .LStreCopyAligned
|
|
|
|
+.LStreCopyAlignLoop:
|
|
|
|
+ { decrease misaligned bytes counter (do it here already to improve }
|
|
|
|
+ { jump prediction) }
|
|
|
|
+ subic. r28,1
|
|
|
|
+ { load next byte }
|
|
|
|
+ lbz r27,(r4)
|
|
|
|
+ { end of string? }
|
|
|
|
+ cmpli cr1,r27,0
|
|
|
|
+ { point to next source byte }
|
|
|
|
+ addi r4,r4,1
|
|
|
|
+ { store byte }
|
|
|
|
+ stb r27,(r3)
|
|
|
|
+ { stop if end of string }
|
|
|
|
+ beq cr1,.LStreCopyDone
|
|
|
|
+ { point to next dest address }
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ { loop if misaligned bytes left }
|
|
|
|
+ bne .LStreCopyAlignLoop
|
|
|
|
+ .balign 16
|
|
|
|
+.LStreCopyAligned:
|
|
|
|
+ { load next 4 bytes }
|
|
|
|
+ lwz r27,(r4)
|
|
|
|
+ { first/highest byte zero? (big endian!) }
|
|
|
|
+ andis. r28,r27,0x0ff00
|
|
|
|
+ addi r4,r4,4
|
|
|
|
+ beq .LStreCopyByte
|
|
|
|
+ { second byte zero? }
|
|
|
|
+ andis. r28,r27,0x00ff
|
|
|
|
+ beq .LStreCopyWord
|
|
|
|
+ { third byte zero? }
|
|
|
|
+ andi. r28,r27,0xff00
|
|
|
|
+ beq .LStreCopy3Bytes
|
|
|
|
+ { fourth byte zero? }
|
|
|
|
+ andi. r28,r27,0x00ff
|
|
|
|
+ { store next 4 bytes }
|
|
|
|
+ stw r27,(r3)
|
|
|
|
+ { increase dest address }
|
|
|
|
+ { the result must point to the terminating #0, so only add 3 }
|
|
|
|
+ addi r3,r3,3
|
|
|
|
+ beq .LStreCopyDone
|
|
|
|
+ { add another 1 for next char }
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ b .LStreCopyAligned
|
|
|
|
+{ store left-overs }
|
|
|
|
+.LStreCopy3Bytes:
|
|
|
|
+ sth r27,(r3)
|
|
|
|
+ li r27,0
|
|
|
|
+ stbu r27,2(r3)
|
|
|
|
+ b .LStrCopyDone
|
|
|
|
+.LStreCopyWord:
|
|
|
|
+ sth r27,(r3)
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ b .LStrCopyDone
|
|
|
|
+.LStreCopyByte:
|
|
|
|
+ stb r27,(r3)
|
|
|
|
+.LStreCopyDone:
|
|
|
|
+ { r3 contains end of new string now }
|
|
|
|
+end ['r3','r4','r27','r28','cr0','cr1'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strlcopy(dest,source : pchar;maxlen : longint) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+{ in: dest in r3, source in r4, maxlen in r5 }
|
|
|
|
+{ out: result (dest) in r3 }
|
|
|
|
+asm
|
|
|
|
+ { empty/invalid string? }
|
|
|
|
+ cmpli r3,0
|
|
|
|
+ { if yes, do nothing }
|
|
|
|
+ beq .LStrlCopyDone
|
|
|
|
+ { maxlen in counter }
|
|
|
|
+ mtctr r5
|
|
|
|
+ { clear two lowest bits of source address }
|
|
|
|
+ rlwminm r28,r4,0,0,31-2
|
|
|
|
+ { get # of misaligned bytes }
|
|
|
|
+ sub. r28,r28,r4
|
|
|
|
+ { since we have to return dest intact, use another register for }
|
|
|
|
+ { dest in the copy loop }
|
|
|
|
+ mr r29,r3
|
|
|
|
+ beq .LStrlCopyAligned
|
|
|
|
+.LStrlCopyAlignLoop:
|
|
|
|
+ { if decreased maxlen counter = 0 (dz), stop }
|
|
|
|
+ bdz .LStrlCopyByte
|
|
|
|
+ { decrease misaligned bytes counter (do it here already to improve }
|
|
|
|
+ { jump prediction) }
|
|
|
|
+ subic. r28,1
|
|
|
|
+ { load next byte }
|
|
|
|
+ lbz r27,(r4)
|
|
|
|
+ { end of string? }
|
|
|
|
+ cmpli cr1,r27,0
|
|
|
|
+ { point to next source byte }
|
|
|
|
+ addi r4,r4,1
|
|
|
|
+ { store byte }
|
|
|
|
+ stb r27,(r29)
|
|
|
|
+ { point to next dest address }
|
|
|
|
+ addi r29,r29,1
|
|
|
|
+ { stop if end of string }
|
|
|
|
+ beq cr1,.LStrlCopyDone
|
|
|
|
+ { loop while unaligned byte counter <> 0 }
|
|
|
|
+ bne .LStrlCopyAlignLoop
|
|
|
|
+ .balign 16
|
|
|
|
+.LStrlCopyAligned:
|
|
|
|
+ { load next 4 bytes }
|
|
|
|
+ lwz r27,(r4)
|
|
|
|
+ { first/highest byte zero? (big endian!) }
|
|
|
|
+ andis. r28,r27,0x0ff00
|
|
|
|
+ addi r4,r4,4
|
|
|
|
+ { if decremented maxlen counter not zero (dnz) and no #0 (ne), }
|
|
|
|
+ { continue (and hint that the most likely case is jump taken) }
|
|
|
|
+ bdnzne+ .LNoStrlCopyByte
|
|
|
|
+ b .LStrlCopyByte
|
|
|
|
+.LNoStrlCopyByte:
|
|
|
|
+ { second byte zero? }
|
|
|
|
+ andis. r28,r27,0x00ff
|
|
|
|
+ bdnzne+ .LNoStrlCopyWord
|
|
|
|
+ b .LStrlCopyWord
|
|
|
|
+.LNoStrlCopyWord:
|
|
|
|
+ { third byte zero? }
|
|
|
|
+ andi. r28,r27,0xff00
|
|
|
|
+ bdnzne+ .LNoStrlCopy3Bytes
|
|
|
|
+ b .LStrlCopy3Bytes
|
|
|
|
+.LNoStrlCopy3Bytes:
|
|
|
|
+ { fourth byte zero? }
|
|
|
|
+ andi. r28,r27,0x00ff
|
|
|
|
+ { store next 4 bytes }
|
|
|
|
+ stw r27,(r29)
|
|
|
|
+ { increase dest address }
|
|
|
|
+ addi r29,r29,4
|
|
|
|
+ bdnzne .LStrlCopyAligned
|
|
|
|
+ { replace last char with a #0 in case we stopped because the maxlen }
|
|
|
|
+ { was reached }
|
|
|
|
+ li r27,0
|
|
|
|
+ stb r27,-1(r29)
|
|
|
|
+ b .LStrlCopyDone
|
|
|
|
+{ store left-overs }
|
|
|
|
+.LStrlCopy3Bytes:
|
|
|
|
+ { big endian! So move upper 16bits to lower 16bits}
|
|
|
|
+ srwi r27,r27,16
|
|
|
|
+ sth r27,(r29)
|
|
|
|
+ li r27,0
|
|
|
|
+ stb r27,2(r29)
|
|
|
|
+ b .LStrlCopyDone
|
|
|
|
+.LStrlCopyWord:
|
|
|
|
+ { clear lower 8 bits of low 16 bits }
|
|
|
|
+ andi r27,r27,0x0ff00
|
|
|
|
+ sth r27,(r29)
|
|
|
|
+ b .LStrlCopyDone
|
|
|
|
+.LStrlCopyByte:
|
|
|
|
+ li r27,0
|
|
|
|
+ stb r27,(r29)
|
|
|
|
+.LStrlCopyDone:
|
|
|
|
+ { r3 still contains dest here }
|
|
|
|
+end ['r4','r27','r28','r29','cr0','cr1','ctr'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strlen(p : pchar) : longint;assembler;
|
|
|
|
+{ in: p in r3 }
|
|
|
|
+{ out: result (length) in r3 }
|
|
|
|
+{ WARNING: if the used registers change here, also change strend!! (JM) }
|
|
|
|
+asm
|
|
|
|
+ { empty/invalid string? }
|
|
|
|
+ cmpli r3,0
|
|
|
|
+ { if yes, do nothing }
|
|
|
|
+ beq .LStrLenNil
|
|
|
|
+ { clear two lowest bits of source address }
|
|
|
|
+ rlwminm r28,r3,0,0,31-2
|
|
|
|
+ { get # of misaligned bytes }
|
|
|
|
+ sub. r28,r28,r3
|
|
|
|
+ { at the end, we substract r29 from r3 to get the length }
|
|
|
|
+ mr r29,r3
|
|
|
|
+ beq .LStrLenAligned
|
|
|
|
+.LStrLenAlignLoop:
|
|
|
|
+ { decrease misaligned bytes counter (do it here already to improve }
|
|
|
|
+ { jump prediction) }
|
|
|
|
+ subic. r28,1
|
|
|
|
+ { load next byte }
|
|
|
|
+ lbz r27,(r3)
|
|
|
|
+ { end of string? }
|
|
|
|
+ cmpli cr1,r27,0
|
|
|
|
+ { stop if end of string }
|
|
|
|
+ beq cr1,.LStrLenDone
|
|
|
|
+ { point to next source byte }
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ bne .LStrLenAlignLoop
|
|
|
|
+ .balign 16
|
|
|
|
+.LStrLenAligned:
|
|
|
|
+ { load next 4 bytes }
|
|
|
|
+ lwz r27,(r3)
|
|
|
|
+ { first/highest byte zero? (big endian!) }
|
|
|
|
+ andis. r28,r27,0x0ff00
|
|
|
|
+ beq .LStrLenDone
|
|
|
|
+ { second byte zero? }
|
|
|
|
+ andis. r28,r27,0x00ff
|
|
|
|
+ { increase length }
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ beq .LStrLenDone
|
|
|
|
+ { third byte zero? }
|
|
|
|
+ andi. r28,r27,0xff00
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ beq .LStrLenDone
|
|
|
|
+ { fourth byte zero? }
|
|
|
|
+ andi. r28,r27,0x00ff
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ beq .LStrLenDone
|
|
|
|
+ addi r3,r3,1
|
|
|
|
+ b .LStrLenAligned
|
|
|
|
+.LStrLenDone:
|
|
|
|
+ sub r3,r29,r3
|
|
|
|
+.LStrLenNil:
|
|
|
|
+end ['r3','r27','r28','r29','cr0','cr1'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strend(p : pchar) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+ mr r26,r3
|
|
|
|
+ mflr r25
|
|
|
|
+ bl strlen
|
|
|
|
+ mtlr r25
|
|
|
|
+ add r3,r26,r3
|
|
|
|
+end ['r3','r25','r26','r27','r28','r29','cr0','cr1'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strcomp(str1,str2 : pchar) : longint;assembler;
|
|
|
|
+{ in: str1 in r3, str2 in r4 }
|
|
|
|
+{ out: result (= 0 if strings equal, < 0 if str1 < str2, > 0 if str1 > str2 }
|
|
|
|
+{ in r3 }
|
|
|
|
+asm
|
|
|
|
+ { !!! }
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strlcomp(str1,str2 : pchar;l : longint) : longint;assembler;
|
|
|
|
+{ (same as strcomp, but maximally compare until l'th character) }
|
|
|
|
+{ in: str1 in r3, str2 in r4, l in r5 }
|
|
|
|
+{ out: result (= 0 if strings equal, < 0 if str1 < str2, > 0 if str1 > str2 }
|
|
|
|
+{ in r3 }
|
|
|
|
+asm
|
|
|
|
+ { !!! }
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function stricomp(str1,str2 : pchar) : longint;assembler;
|
|
|
|
+{ in: str1 in r3, str2 in r4 }
|
|
|
|
+{ out: result (= index of first differing character) in r3 }
|
|
|
|
+asm
|
|
|
|
+ { !!! }
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strlicomp(str1,str2 : pchar;l : longint) : longint;assembler;
|
|
|
|
+{ (same as stricomp, but maximally compare until l'th character) }
|
|
|
|
+{ in: str1 in r3, str2 in r4, l in r5 }
|
|
|
|
+{ out: result (= index of first differing character) in r3 }
|
|
|
|
+asm
|
|
|
|
+ { !!! }
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strscan(p : pchar;c : char) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+ movl p,%eax
|
|
|
|
+ xorl %ecx,%ecx
|
|
|
|
+ testl %eax,%eax
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+// align
|
|
|
|
+ movb c,%cl
|
|
|
|
+ movl %eax,%esi
|
|
|
|
+ andl $0xfffffff8,%eax
|
|
|
|
+ movl $0xff,%edx
|
|
|
|
+ movl p,%edi
|
|
|
|
+ subl %eax,%esi
|
|
|
|
+ jz .LSTRSCANLOOP
|
|
|
|
+ xorl %eax,%eax
|
|
|
|
+.LSTRSCANALIGNLOOP:
|
|
|
|
+ movb (%edi),%al
|
|
|
|
+// at .LSTRSCANFOUND, one is substracted from edi to calculate the position,
|
|
|
|
+// so add 1 here already (not after .LSTRSCAN, because then the test/jz and
|
|
|
|
+// cmp/je can't be paired)
|
|
|
|
+ incl %edi
|
|
|
|
+ testb %al,%al
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+ cmpb %cl,%al
|
|
|
|
+ je .LSTRSCANFOUND
|
|
|
|
+ decl %esi
|
|
|
|
+ jnz .LSTRSCANALIGNLOOP
|
|
|
|
+ jmp .LSTRSCANLOOP
|
|
|
|
+ .balign 16
|
|
|
|
+.LSTRSCANLOOP:
|
|
|
|
+ movl (%edi),%eax
|
|
|
|
+ movl %eax,%esi
|
|
|
|
+// first char
|
|
|
|
+ andl %edx,%eax
|
|
|
|
+// end of string -> stop
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+ shrl $8,%esi
|
|
|
|
+ cmpl %ecx,%eax
|
|
|
|
+ movl %esi,%eax
|
|
|
|
+ je .LSTRSCANFOUND1
|
|
|
|
+// second char
|
|
|
|
+ andl %edx,%eax
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+ shrl $8,%esi
|
|
|
|
+ cmpl %ecx,%eax
|
|
|
|
+ movl %esi,%eax
|
|
|
|
+ je .LSTRSCANFOUND2
|
|
|
|
+// third char
|
|
|
|
+ andl %edx,%eax
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+ shrl $8,%esi
|
|
|
|
+ cmpl %ecx,%eax
|
|
|
|
+ movl %esi,%eax
|
|
|
|
+ je .LSTRSCANFOUND3
|
|
|
|
+// fourth char
|
|
|
|
+// all upper bits have already been cleared
|
|
|
|
+ testl %eax,%eax
|
|
|
|
+ jz .LSTRSCAN
|
|
|
|
+ addl $4,%edi
|
|
|
|
+ cmpl %ecx,%eax
|
|
|
|
+ je .LSTRSCANFOUND
|
|
|
|
+ jmp .LSTRSCANLOOP
|
|
|
|
+.LSTRSCANFOUND3:
|
|
|
|
+ leal 2(%edi),%eax
|
|
|
|
+ jmp .LSTRSCAN
|
|
|
|
+.LSTRSCANFOUND2:
|
|
|
|
+ leal 1(%edi),%eax
|
|
|
|
+ jmp .LSTRSCAN
|
|
|
|
+.LSTRSCANFOUND1:
|
|
|
|
+ movl %edi,%eax
|
|
|
|
+ jmp .LSTRSCAN
|
|
|
|
+.LSTRSCANFOUND:
|
|
|
|
+ leal -1(%edi),%eax
|
|
|
|
+.LSTRSCAN:
|
|
|
|
+end ['EAX','ECX','ESI','EDI','EDX'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strrscan(p : pchar;c : char) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+ xorl %eax,%eax
|
|
|
|
+ movl p,%edi
|
|
|
|
+ orl %edi,%edi
|
|
|
|
+ jz .LSTRRSCAN
|
|
|
|
+ movl $0xffffffff,%ecx
|
|
|
|
+ cld
|
|
|
|
+ xorb %al,%al
|
|
|
|
+ repne
|
|
|
|
+ scasb
|
|
|
|
+ not %ecx
|
|
|
|
+ movb c,%al
|
|
|
|
+ movl p,%edi
|
|
|
|
+ addl %ecx,%edi
|
|
|
|
+ decl %edi
|
|
|
|
+ std
|
|
|
|
+ repne
|
|
|
|
+ scasb
|
|
|
|
+ cld
|
|
|
|
+ movl $0,%eax
|
|
|
|
+ jnz .LSTRRSCAN
|
|
|
|
+ movl %edi,%eax
|
|
|
|
+ incl %eax
|
|
|
|
+.LSTRRSCAN:
|
|
|
|
+end ['EAX','ECX','EDI'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strupper(p : pchar) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+ movl p,%esi
|
|
|
|
+ orl %esi,%esi
|
|
|
|
+ jz .LStrUpperNil
|
|
|
|
+ movl %esi,%edi
|
|
|
|
+.LSTRUPPER1:
|
|
|
|
+ lodsb
|
|
|
|
+ cmpb $97,%al
|
|
|
|
+ jb .LSTRUPPER3
|
|
|
|
+ cmpb $122,%al
|
|
|
|
+ ja .LSTRUPPER3
|
|
|
|
+ subb $0x20,%al
|
|
|
|
+.LSTRUPPER3:
|
|
|
|
+ stosb
|
|
|
|
+ orb %al,%al
|
|
|
|
+ jnz .LSTRUPPER1
|
|
|
|
+.LStrUpperNil:
|
|
|
|
+ movl p,%eax
|
|
|
|
+end ['EAX','ESI','EDI'];
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function strlower(p : pchar) : pchar;assembler;
|
|
|
|
+asm
|
|
|
|
+ movl p,%esi
|
|
|
|
+ orl %esi,%esi
|
|
|
|
+ jz .LStrLowerNil
|
|
|
|
+ movl %esi,%edi
|
|
|
|
+.LSTRLOWER1:
|
|
|
|
+ lodsb
|
|
|
|
+ cmpb $65,%al
|
|
|
|
+ jb .LSTRLOWER3
|
|
|
|
+ cmpb $90,%al
|
|
|
|
+ ja .LSTRLOWER3
|
|
|
|
+ addb $0x20,%al
|
|
|
|
+.LSTRLOWER3:
|
|
|
|
+ stosb
|
|
|
|
+ orb %al,%al
|
|
|
|
+ jnz .LSTRLOWER1
|
|
|
|
+.LStrLowerNil:
|
|
|
|
+ movl p,%eax
|
|
|
|
+end ['EAX','ESI','EDI'];
|
|
|
|
+
|
|
|
|
+{
|
|
|
|
+ $Log$
|
|
|
|
+ Revision 1.1 2000-11-05 17:17:08 jonas
|
|
|
|
+ + first implementation, not yet finished
|
|
|
|
+
|
|
|
|
+}
|