From 40e668e9f79ffb466ac7845504016d9ddc94825d Mon Sep 17 00:00:00 2001 From: Brendan Fletcher Date: Mon, 26 Feb 2024 23:43:19 -0500 Subject: [PATCH] Fix/optimize str[n]casecmp, remove buggy OS tolower/toupper --- src/libc/os.src | 2 - src/libc/strcasecmp.src | 95 ++++++++++++++++++++++++++++++++++++++++ src/libc/strncasecmp.src | 48 -------------------- src/libc/tolower.src | 16 +++---- src/libc/toupper.src | 16 +++---- 5 files changed, 107 insertions(+), 70 deletions(-) create mode 100644 src/libc/strcasecmp.src delete mode 100644 src/libc/strncasecmp.src diff --git a/src/libc/os.src b/src/libc/os.src index 053f9bb1a..2a8c8dd2c 100644 --- a/src/libc/os.src +++ b/src/libc/os.src @@ -30,8 +30,6 @@ _strlen := 0000D4h _strncat := 0000D8h public _strncmp _strncmp := 0000DCh - public _strcasecmp -_strcasecmp := 021E3Ch public _strncpy _strncpy := 0000E0h public _strpbrk diff --git a/src/libc/strcasecmp.src b/src/libc/strcasecmp.src new file mode 100644 index 000000000..d04a8ef7d --- /dev/null +++ b/src/libc/strcasecmp.src @@ -0,0 +1,95 @@ + assume adl=1 + + section .text + public _strcasecmp + +if PREFER_OS_LIBC + +_strcasecmp := 021E3Ch + +else + +_strcasecmp: + pop iy + pop de + ex (sp), hl + push de + ld b, 1+'z'-'a' + ld c, 'a'-'A' + jr .loop_entry +.loop: + cp a, (hl) + jr z, .done +.loop_nonnull: + inc hl + inc de +.loop_entry: + ld a, (de) + xor a, (hl) + jr z, .loop + cp a, c + jr nz, .mismatch + or a, (hl) + sub a, 'a' + cp a, b + jr c, .loop_nonnull + +end if + + section .text + public _strcasecmp.mismatch + public _strcasecmp.done +_strcasecmp.mismatch: + ld l, (hl) + call _tolower.internal + ex de, hl + ld l, (hl) + call _tolower.internal + ld a, l + sub a, e +_strcasecmp.done: + sbc hl, hl + ld l, a + jp (iy) + + section .text + public _strncasecmp +_strncasecmp: + pop iy + pop de + pop hl + pop bc + push bc + push de + push hl + + scf + sbc hl, hl + add hl, bc + ex (sp), hl + + call c, .loop_entry + jr c, _strcasecmp.mismatch + sbc hl, hl + jp (iy) + +.checkcase: + or a, (hl) + sub a, 'a' + add a, -(1+'z'-'a') + ret c +.loop: + cpi + ret po + ret z + inc de +.loop_entry: + ld a, (de) + xor a, (hl) + jr z, .loop + cp a, 'a'-'A' + jr z, .checkcase + scf + ret + + extern _tolower.internal diff --git a/src/libc/strncasecmp.src b/src/libc/strncasecmp.src deleted file mode 100644 index 95b6d299e..000000000 --- a/src/libc/strncasecmp.src +++ /dev/null @@ -1,48 +0,0 @@ - assume adl=1 - - section .text - public _strncasecmp - -_strncasecmp: - push ix - ld ix,0 - add ix,sp - dec sp -loop: - ld hl,(ix+12) - add hl,de - or a,a - sbc hl,de - jr z,done - dec hl - ld (ix+12),hl - ld hl,(ix+6) - ld c,(hl) - inc hl - ld (ix+6),hl - push bc - call _tolower - pop bc - ld (ix-1),l - ld hl,(ix+9) - ld c,(hl) - inc hl - ld (ix+9),hl - push bc - call _tolower - pop bc - ex de,hl - sub a,a - sbc hl,hl - ld l,(ix-1) - sbc hl,de - jr nz,done - ld a,(ix-1) - or a,e - jr nz,loop -done: - ld sp,ix - pop ix - ret - - extern _tolower diff --git a/src/libc/tolower.src b/src/libc/tolower.src index 23f09a04a..823c07ec3 100644 --- a/src/libc/tolower.src +++ b/src/libc/tolower.src @@ -3,24 +3,20 @@ section .text public _tolower -if PREFER_OS_LIBC - -_tolower := 021E34h - -else - _tolower: pop de ex (sp), hl push de + require _tolower.internal + section .text + public _tolower.internal + ; ASM interface: input/output char in L, destroys AF +_tolower.internal: ld a, l sub a, 'A' cp a, 1+'Z'-'A' ret nc - add a, 'a' - ld l, a + set 5, l ret - -end if diff --git a/src/libc/toupper.src b/src/libc/toupper.src index aa28ddb05..0781ba7b0 100644 --- a/src/libc/toupper.src +++ b/src/libc/toupper.src @@ -3,24 +3,20 @@ section .text public _toupper -if PREFER_OS_LIBC - -_toupper := 021E38h - -else - _toupper: pop de ex (sp), hl push de + require _toupper.internal + section .text + public _toupper.internal + ; ASM interface: input/output char in L, destroys AF +.internal: ld a, l sub a, 'a' cp a, 1+'z'-'a' ret nc - add a, 'A' - ld l, a + res 5, l ret - -end if