]> git.sur5r.net Git - cc65/commitdiff
Optimization of two string functions (size & speed).
authorIrgendwerA8 <c.krueger.b@web.de>
Sat, 25 Feb 2017 19:19:34 +0000 (20:19 +0100)
committerIrgendwerA8 <c.krueger.b@web.de>
Sat, 25 Feb 2017 19:19:50 +0000 (20:19 +0100)
libsrc/common/strcat.s
libsrc/common/strchr.s
testcode/lib/strcat-test.c [new file with mode: 0644]

index 7784d89f762bc42be2577a4393976bad49c4c7d4..279bfe65b8b2d71e8d2f91f73d0a59d1f3f4581f 100644 (file)
@@ -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
 
-
index 308381b06e1954fa6612076dd4a144ecea811df0..0bd55d0e148321d5f1241823b7268589e472b2b2 100644 (file)
@@ -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);
 ;
         .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 (file)
index 0000000..edd614f
--- /dev/null
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}
+
+
+