9cddaf1b59
* String functions optimised A few functions have been tweaked, but the biggest changes are in strlen, strskip and toWS, which take around two third of the cycles they used to (although strskip has more overhead). 10 bytes saved total. toWS had two bytes added inlining the isWS call, and a jump to unsetZ was inlined too, saving a byte. This saved 29 cycles, with the original function being 90 cycles. I looked at other uses of isWS and it's difficult to inline it effectively in every situation, so I haven't inlined it elsewhere. rdWS had a byte and two cycles saved by inlining a jump to unsetZ. strskip is the same size, with the loop cut down from 35 cycles to 21 cycles, but 18 cycles are added outside the loop. I expect one character strings are in the minority, so this should save cycles overall. strlen had 8 bytes saved, with the loop cut down from 38 cycles to 21 cycles, and 18 cycles removed outside the loop. * Fixed strskip Strskip wasn't preserving a properly. The new code uses the shadow af register, so whilst a byte and 4 cycles have been added outside the loop, it's safer and cleaner. The flags register isn't affected, but since the search goes for up to 64Kb I think it's safe to say the end of the string will always be reached. * Remove inlining of isWS
108 lines
2.0 KiB
NASM
108 lines
2.0 KiB
NASM
; Sets Z is A is ' ' or '\t' (whitespace)
|
|
isWS:
|
|
cp ' '
|
|
ret z
|
|
cp 0x09
|
|
ret
|
|
|
|
; Advance HL to next WS.
|
|
; Set Z if WS found, unset if end-of-string.
|
|
toWS:
|
|
ld a, (hl)
|
|
call isWS
|
|
ret z
|
|
cp 0x01 ; if a is null, carries and unsets z
|
|
ret c
|
|
inc hl
|
|
jr toWS
|
|
|
|
; Consume following whitespaces in HL until a non-WS is hit.
|
|
; Set Z if non-WS found, unset if end-of-string.
|
|
rdWS:
|
|
ld a, (hl)
|
|
call isWS
|
|
jr nz, .ok
|
|
cp 0x01 ; if a is null, carries and unsets z
|
|
ret c
|
|
inc hl
|
|
jr rdWS
|
|
.ok:
|
|
cp a ; ensure Z
|
|
ret
|
|
|
|
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
|
; encountered. The null char is also copied.
|
|
; HL and DE point to the char right after the null char.
|
|
strcpyM:
|
|
ld a, (hl)
|
|
ld (de), a
|
|
inc hl
|
|
inc de
|
|
or a
|
|
jr nz, strcpyM
|
|
ret
|
|
|
|
; Like strcpyM, but preserve HL and DE
|
|
strcpy:
|
|
push hl
|
|
push de
|
|
call strcpyM
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
; Compares strings pointed to by HL and DE until one of them hits its null char.
|
|
; If equal, Z is set. If not equal, Z is reset.
|
|
strcmp:
|
|
push hl
|
|
push de
|
|
|
|
.loop:
|
|
ld a, (de)
|
|
cp (hl)
|
|
jr nz, .end ; not equal? break early. NZ is carried out
|
|
; to the caller
|
|
or a ; If our chars are null, stop the cmp
|
|
inc hl
|
|
inc de
|
|
jr nz, .loop ; Z is carried through
|
|
|
|
.end:
|
|
pop de
|
|
pop hl
|
|
; Because we don't call anything else than CP that modify the Z flag,
|
|
; our Z value will be that of the last cp (reset if we broke the loop
|
|
; early, set otherwise)
|
|
ret
|
|
|
|
; Given a string at (HL), move HL until it points to the end of that string.
|
|
strskip:
|
|
push bc
|
|
ex af, af'
|
|
xor a ; look for null char
|
|
ld b, a
|
|
ld c, a
|
|
cpir ; advances HL regardless of comparison, so goes one too far
|
|
dec hl
|
|
ex af, af'
|
|
pop bc
|
|
ret
|
|
|
|
; Returns length of string at (HL) in A.
|
|
; Doesn't include null termination.
|
|
strlen:
|
|
push bc
|
|
xor a ; look for null char
|
|
ld b, a
|
|
ld c, a
|
|
cpir ; advances HL to the char after the null
|
|
.found:
|
|
; How many char do we have? We have strlen=(NEG BC)-1, since BC started
|
|
; at 0 and decreased at each CPIR loop. In this routine,
|
|
; we stay in the 8-bit realm, so C only.
|
|
add hl, bc
|
|
sub c
|
|
dec a
|
|
pop bc
|
|
ret
|