String functions optimised (#86)

* 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
This commit is contained in:
Clanmaster21 2020-01-10 01:10:27 +00:00 committed by Virgil Dupras
parent 66744c0026
commit 9cddaf1b59
1 changed files with 22 additions and 28 deletions

View File

@ -11,8 +11,8 @@ toWS:
ld a, (hl) ld a, (hl)
call isWS call isWS
ret z ret z
or a cp 0x01 ; if a is null, carries and unsets z
jp z, unsetZ ret c
inc hl inc hl
jr toWS jr toWS
@ -22,8 +22,8 @@ rdWS:
ld a, (hl) ld a, (hl)
call isWS call isWS
jr nz, .ok jr nz, .ok
or a cp 0x01 ; if a is null, carries and unsets z
jp z, unsetZ ret c
inc hl inc hl
jr rdWS jr rdWS
.ok: .ok:
@ -61,13 +61,11 @@ strcmp:
ld a, (de) ld a, (de)
cp (hl) cp (hl)
jr nz, .end ; not equal? break early. NZ is carried out jr nz, .end ; not equal? break early. NZ is carried out
; to the called ; to the caller
or a ; If our chars are null, stop the cmp or a ; If our chars are null, stop the cmp
jr z, .end ; The positive result will be carried to the
; caller
inc hl inc hl
inc de inc de
jr .loop jr nz, .loop ; Z is carried through
.end: .end:
pop de pop de
@ -79,35 +77,31 @@ strcmp:
; Given a string at (HL), move HL until it points to the end of that string. ; Given a string at (HL), move HL until it points to the end of that string.
strskip: strskip:
push af push bc
ex af, af'
xor a ; look for null char xor a ; look for null char
.loop: ld b, a
cp (hl) ld c, a
jp z, .found cpir ; advances HL regardless of comparison, so goes one too far
inc hl dec hl
jr .loop ex af, af'
.found: pop bc
pop af
ret ret
; Returns length of string at (HL) in A. ; Returns length of string at (HL) in A.
; Doesn't include null termination. ; Doesn't include null termination.
strlen: strlen:
push bc push bc
push hl
ld bc, 0
xor a ; look for null char xor a ; look for null char
.loop: ld b, a
cpi ld c, a
jp z, .found cpir ; advances HL to the char after the null
jr .loop
.found: .found:
; How many char do we have? the (NEG BC)-1, which started at 0 and ; How many char do we have? We have strlen=(NEG BC)-1, since BC started
; decreased at each CPI call. In this routine, we stay in the 8-bit ; at 0 and decreased at each CPIR loop. In this routine,
; realm, so C only. ; we stay in the 8-bit realm, so C only.
ld a, c add hl, bc
neg sub c
dec a dec a
pop hl
pop bc pop bc
ret ret