From: IrgendwerA8 Date: Sat, 25 Feb 2017 19:19:34 +0000 (+0100) Subject: Optimization of two string functions (size & speed). X-Git-Tag: V2.16~8^2~6 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=6afcc370edbd77d494fc6378a20de0023be6981f;p=cc65 Optimization of two string functions (size & speed). --- diff --git a/libsrc/common/strcat.s b/libsrc/common/strcat.s index 7784d89f7..279bfe65b 100644 --- a/libsrc/common/strcat.s +++ b/libsrc/common/strcat.s @@ -1,5 +1,6 @@ ; ; Ullrich von Bassewitz, 31.05.1998 +; Christian Krueger: 2013-Jul-24, minor optimization ; ; char* strcat (char* dest, const char* src); ; @@ -12,44 +13,35 @@ _strcat: sta ptr1 ; Save src stx ptr1+1 jsr popax ; Get dest - sta ptr2 - stx ptr2+1 sta tmp3 ; Remember for function return - ldy #0 - -; find end of dest + tay + lda #0 + sta ptr2 ; access from page start, y contains low byte + stx ptr2+1 -sc1: lda (ptr2),y - beq sc2 +findEndOfDest: + lda (ptr2),y + beq endOfDestFound iny - bne sc1 - inc ptr2+1 - bne sc1 - -; end found, get offset in y into pointer - -sc2: tya - clc - adc ptr2 - sta ptr2 - bcc sc3 + bne findEndOfDest inc ptr2+1 + bne findEndOfDest -; copy src +endOfDestFound: + sty ptr2 ; advance pointer to last y position + ldy #0 ; reset new y-offset -sc3: ldy #0 -sc4: lda (ptr1),y +copyByte: + lda (ptr1),y sta (ptr2),y - beq sc5 + beq done iny - bne sc4 + bne copyByte inc ptr1+1 inc ptr2+1 - bne sc4 + bne copyByte ; like bra here -; done, return pointer to dest - -sc5: lda tmp3 ; X does still contain high byte +; return pointer to dest +done: lda tmp3 ; X does still contain high byte rts - diff --git a/libsrc/common/strchr.s b/libsrc/common/strchr.s index 308381b06..0bd55d0e1 100644 --- a/libsrc/common/strchr.s +++ b/libsrc/common/strchr.s @@ -1,5 +1,6 @@ ; ; Ullrich von Bassewitz, 31.05.1998 +; Christian Krueger, 2013-Aug-04, minor optimization ; ; const char* strchr (const char* s, int c); ; @@ -9,40 +10,38 @@ .importzp ptr1, tmp1 _strchr: - sta tmp1 ; Save c - jsr popax ; get s - sta ptr1 - stx ptr1+1 - ldy #0 - -Loop: lda (ptr1),y ; Get next char - beq EOS ; Jump on end of string - cmp tmp1 ; Found? - beq Found ; Jump if yes + sta tmp1 ; Save c + jsr popax ; get s + tay ; low byte of pointer to y + stx ptr1+1 + lda #0 + sta ptr1 ; ptr access page wise + +Loop: lda (ptr1),y ; Get next char + beq EOS ; Jump on end of string + cmp tmp1 ; Found? + beq Found ; Jump if yes iny - bne Loop - inc ptr1+1 - bne Loop ; Branch always + bne Loop + inc ptr1+1 + bne Loop ; Branch always ; End of string. Check if we're searching for the terminating zero -EOS: lda tmp1 ; Get the char we're searching for - bne NotFound ; Jump if not searching for terminator +EOS: + lda tmp1 ; Get the char we're searching for + bne NotFound ; Jump if not searching for terminator -; Found. Calculate pointer to c. +; Found. Set pointer to c. -Found: ldx ptr1+1 ; Load high byte of pointer - tya ; Low byte offset - clc - adc ptr1 - bcc Found1 - inx -Found1: rts +Found: + ldx ptr1+1 ; Load high byte of pointer + tya ; low byte is in y + rts ; Not found, return NULL NotFound: - lda #0 + lda #0 tax rts - diff --git a/testcode/lib/strcat-test.c b/testcode/lib/strcat-test.c new file mode 100644 index 000000000..edd614fc4 --- /dev/null +++ b/testcode/lib/strcat-test.c @@ -0,0 +1,93 @@ +#include +#include +#include + +#define SourceStringSize 257 // test correct page passing (>256) + +static char SourceString[SourceStringSize+1]; // +1 room for terminating null +static char DestinationString[2*SourceStringSize+1]; // will contain two times the source buffer + + +int main (void) +{ + unsigned i,j; + char* p; + + /* Print a header */ + printf ("strcat(): "); + + for (i=0; i < SourceStringSize; ++i) + SourceString[i] = (i%128)+1; + + SourceString[i] = 0; + + if (strlen(SourceString) != SourceStringSize) + { + printf ("Fail: Source string initialization or 'strlen()' problem!\n"); + printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(SourceString)); + exit (EXIT_FAILURE); + } + + /* Ensure empty destination string */ + DestinationString[0] = 0; + + if (strlen(DestinationString) != 0) + { + printf ("Fail: Destination string initialization or 'strlen()' problem!\n"); + printf ("Expected length: %u but is %u!\n", 0, strlen(DestinationString)); + exit (EXIT_FAILURE); + } + + /* Test concatenation to empty buffer */ + + p = strcat(DestinationString, SourceString); + + if (strlen(DestinationString) != SourceStringSize) + { + printf ("Fail: String concatenation to empty buffer!\n"); + printf ("Expected length: %u but is %u!\n", SourceStringSize, strlen(DestinationString)); + exit (EXIT_FAILURE); + } + + /* Test concatenation to non empty buffer */ + + p = strcat(DestinationString, SourceString); + + if (strlen(DestinationString) != 2*SourceStringSize) + { + printf ("Fail: String concatenation to non-empty buffer!\n"); + printf ("Expected length: %u but is %u!\n", 2*SourceStringSize, strlen(DestinationString)); + exit (EXIT_FAILURE); + } + + /* Test return value */ + + if (p != DestinationString) + { + printf ("Invalid return value!\n"); + exit (EXIT_FAILURE); + } + + /* Test contents */ + + for(j=0; j <2; ++j) + for(i=0; i < SourceStringSize; ++i) + { + unsigned position = j*SourceStringSize+i; + unsigned current = DestinationString[position]; + unsigned expected = (i%128)+1; + if (current != expected) + { + printf ("Fail: Unexpected destination buffer contents at position %u!\n", position); + printf ("Expected %u, but is %u!\n", expected, current); + exit (EXIT_FAILURE); + } + } + + /* Test passed */ + printf ("Passed\n"); + return EXIT_SUCCESS; +} + + +