mirror of
https://github.com/cc65/cc65.git
synced 2025-02-24 09:29:07 +00:00
Optimization of two string functions (size & speed).
This commit is contained in:
parent
97e64c388c
commit
6afcc370ed
@ -1,5 +1,6 @@
|
|||||||
;
|
;
|
||||||
; Ullrich von Bassewitz, 31.05.1998
|
; Ullrich von Bassewitz, 31.05.1998
|
||||||
|
; Christian Krueger: 2013-Jul-24, minor optimization
|
||||||
;
|
;
|
||||||
; char* strcat (char* dest, const char* src);
|
; char* strcat (char* dest, const char* src);
|
||||||
;
|
;
|
||||||
@ -12,44 +13,35 @@ _strcat:
|
|||||||
sta ptr1 ; Save src
|
sta ptr1 ; Save src
|
||||||
stx ptr1+1
|
stx ptr1+1
|
||||||
jsr popax ; Get dest
|
jsr popax ; Get dest
|
||||||
sta ptr2
|
|
||||||
stx ptr2+1
|
|
||||||
sta tmp3 ; Remember for function return
|
sta tmp3 ; Remember for function return
|
||||||
ldy #0
|
tay
|
||||||
|
lda #0
|
||||||
|
sta ptr2 ; access from page start, y contains low byte
|
||||||
|
stx ptr2+1
|
||||||
|
|
||||||
; find end of dest
|
findEndOfDest:
|
||||||
|
lda (ptr2),y
|
||||||
sc1: lda (ptr2),y
|
beq endOfDestFound
|
||||||
beq sc2
|
|
||||||
iny
|
iny
|
||||||
bne sc1
|
bne findEndOfDest
|
||||||
inc ptr2+1
|
inc ptr2+1
|
||||||
bne sc1
|
bne findEndOfDest
|
||||||
|
|
||||||
; end found, get offset in y into pointer
|
endOfDestFound:
|
||||||
|
sty ptr2 ; advance pointer to last y position
|
||||||
|
ldy #0 ; reset new y-offset
|
||||||
|
|
||||||
sc2: tya
|
copyByte:
|
||||||
clc
|
lda (ptr1),y
|
||||||
adc ptr2
|
|
||||||
sta ptr2
|
|
||||||
bcc sc3
|
|
||||||
inc ptr2+1
|
|
||||||
|
|
||||||
; copy src
|
|
||||||
|
|
||||||
sc3: ldy #0
|
|
||||||
sc4: lda (ptr1),y
|
|
||||||
sta (ptr2),y
|
sta (ptr2),y
|
||||||
beq sc5
|
beq done
|
||||||
iny
|
iny
|
||||||
bne sc4
|
bne copyByte
|
||||||
inc ptr1+1
|
inc ptr1+1
|
||||||
inc ptr2+1
|
inc ptr2+1
|
||||||
bne sc4
|
bne copyByte ; like bra here
|
||||||
|
|
||||||
; done, return pointer to dest
|
; return pointer to dest
|
||||||
|
done: lda tmp3 ; X does still contain high byte
|
||||||
sc5: lda tmp3 ; X does still contain high byte
|
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
;
|
;
|
||||||
; Ullrich von Bassewitz, 31.05.1998
|
; Ullrich von Bassewitz, 31.05.1998
|
||||||
|
; Christian Krueger, 2013-Aug-04, minor optimization
|
||||||
;
|
;
|
||||||
; const char* strchr (const char* s, int c);
|
; const char* strchr (const char* s, int c);
|
||||||
;
|
;
|
||||||
@ -9,40 +10,38 @@
|
|||||||
.importzp ptr1, tmp1
|
.importzp ptr1, tmp1
|
||||||
|
|
||||||
_strchr:
|
_strchr:
|
||||||
sta tmp1 ; Save c
|
sta tmp1 ; Save c
|
||||||
jsr popax ; get s
|
jsr popax ; get s
|
||||||
sta ptr1
|
tay ; low byte of pointer to y
|
||||||
stx ptr1+1
|
stx ptr1+1
|
||||||
ldy #0
|
lda #0
|
||||||
|
sta ptr1 ; ptr access page wise
|
||||||
|
|
||||||
Loop: lda (ptr1),y ; Get next char
|
Loop: lda (ptr1),y ; Get next char
|
||||||
beq EOS ; Jump on end of string
|
beq EOS ; Jump on end of string
|
||||||
cmp tmp1 ; Found?
|
cmp tmp1 ; Found?
|
||||||
beq Found ; Jump if yes
|
beq Found ; Jump if yes
|
||||||
iny
|
iny
|
||||||
bne Loop
|
bne Loop
|
||||||
inc ptr1+1
|
inc ptr1+1
|
||||||
bne Loop ; Branch always
|
bne Loop ; Branch always
|
||||||
|
|
||||||
; End of string. Check if we're searching for the terminating zero
|
; End of string. Check if we're searching for the terminating zero
|
||||||
|
|
||||||
EOS: lda tmp1 ; Get the char we're searching for
|
EOS:
|
||||||
bne NotFound ; Jump if not searching for terminator
|
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
|
Found:
|
||||||
tya ; Low byte offset
|
ldx ptr1+1 ; Load high byte of pointer
|
||||||
clc
|
tya ; low byte is in y
|
||||||
adc ptr1
|
rts
|
||||||
bcc Found1
|
|
||||||
inx
|
|
||||||
Found1: rts
|
|
||||||
|
|
||||||
; Not found, return NULL
|
; Not found, return NULL
|
||||||
|
|
||||||
NotFound:
|
NotFound:
|
||||||
lda #0
|
lda #0
|
||||||
tax
|
tax
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
93
testcode/lib/strcat-test.c
Normal file
93
testcode/lib/strcat-test.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user