Little strdup optimisation

-12 bytes on disk
-20 cycles per strdup
-6 cycles per strlen called from strdup
This commit is contained in:
Colin Leroy-Mira
2024-01-05 19:39:03 +01:00
parent 169c9c0da0
commit 3a439e0e1b
4 changed files with 51 additions and 73 deletions

View File

@@ -1,85 +1,62 @@
;
; Ullrich von Bassewitz, 18.07.2000
; Colin Leroy-Mira, 05.01.2024
;
; char* __fastcall__ strdup (const char* S);
;
; Note: The code knowns which zero page locations are used by malloc.
; Note: The code knowns which zero page locations are used by malloc,
; memcpy and strlen.
;
.importzp sp, tmp1, ptr4
.import pushax, decsp4, incsp4
.import _strlen, _malloc, _memcpy
.importzp ptr2, ptr3, ptr4, tmp1, tmp2, tmp3
.import _strlen_ptr4, _malloc, _memcpy, pushax
.export _strdup
.macpack cpu
.macpack generic
_strdup:
; Get length (and store source in ptr4)
sta ptr4
stx ptr4+1
stx tmp1 ; Backup high byte, which
jsr _strlen_ptr4 ; strlen may increment
; Since we need some place to store the intermediate results, allocate a
; stack frame. To make this somewhat more efficient, create the stackframe
; as needed for the final call to the memcpy function.
pha ; decsp will destroy A (but not X)
jsr decsp4 ; Target/source
; Store the pointer into the source slot
ldy #1
txa
sta (sp),y
pla
.if (.cpu .bitand CPU_ISET_65SC02)
sta (sp)
; Add null byte for terminator
.if (.cpu .bitand ::CPU_ISET_65SC02)
inc a
.else
dey
sta (sp),y
clc
adc #1
.endif
; Get length of S (which is still in a/x)
jsr _strlen
; Calculate strlen(S)+1 (the space needed)
add #1
bcc @L1
bne :+
inx
; Save the space we're about to allocate in ptr4
@L1: sta ptr4
stx ptr4+1
; Allocate memory. _malloc will not use ptr4
; Store length
: sta tmp2
stx tmp3
; Allocate memory
jsr _malloc
; Store the result into the target stack slot
ldy #2
sta (sp),y ; Store low byte
sta tmp1
txa ; Get high byte
iny
sta (sp),y ; Store high byte
; Check for a NULL pointer
ora tmp1
; Check for NULL
bne :+
cpx #$00
beq OutOfMemory
; Copy the string. memcpy will return the target string which is exactly
; what we need here. It will also drop the allocated stack frame.
; Push dest
: jsr pushax
; Push source
lda ptr4
ldx ptr4+1 ; Load size
jmp _memcpy ; Copy string, drop stackframe
ldx tmp1
jsr pushax
; Out of memory, return NULL (A = 0)
; Push length
lda tmp2
ldx tmp3
; Copy and return the dest pointer
jmp _memcpy
OutOfMemory:
tax
jmp incsp4 ; Drop stack frame
rts