From 6bc516b2e7faf89a33be1dd9e6af90c7f9a79a1e Mon Sep 17 00:00:00 2001 From: Clanmaster21 <asalukehopkins@gmail.com> Date: Sun, 13 Oct 2019 13:10:51 +0100 Subject: [PATCH] Optimised parsing functions and other minor optimisations UnsetZ has been reduced by a byte, and between 17 and 28 cycles saved based on branching. Since branching is based on a being 0, it shouldn't have to branch very often and so be 28 cycles saved most the time. Including the initial call, the old version was 60 cycles, so this should be nearly twice as fast. fmtHex has been reduced by 4 bytes and between 3 and 8 cycles based on branching. fmtHexPair had a redundant "and" removed, saving two bytes and seven cycles. parseHex has been reduced by 7 bytes. Due to so much branching, it's hard to say if it's faster, but it should be since it's fewer operations and now conditional returns are used which are a cycle faster than conditional jumps. I think there's more to improve here, but I haven't come up with anything yet. --- kernel/core.asm | 32 +++++++++++++++++++------------- kernel/parse.asm | 29 ++++++++++++----------------- 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/kernel/core.asm b/kernel/core.asm index f23475a..643c832 100644 --- a/kernel/core.asm +++ b/kernel/core.asm @@ -126,14 +126,16 @@ callIY: jp (iy) ; Ensures that Z is unset (more complicated than it sounds...) +; There are often better inline alternatives, either replacing rets with +; appropriate jmps, or if an 8 bit register is known to not be 0, an inc +; then a dec. If a is nonzero, 'or a' is optimal. unsetZ: - push bc - ld b, a - inc b - cp b - pop bc + or a ;if a nonzero, Z reset + ret nz + cp 1 ;if a is zero, Z reset ret + ; *** STRINGS *** ; Fill B bytes at (HL) with A @@ -179,15 +181,19 @@ findchar: pop bc ret + ; Format the lower nibble of A into a hex char and stores the result in A. +; daa does the following operation if we were working in a high level language: +; a += (2*N-1)*(0x60*(a >= 0xa0) + 0x06*((a & 0x0f) >= 0x0a)) +; N is the Negative flag. The C and H flags are also taken into account, but we +; clear both so this is a good enough description for our purposes. fmtHex: - and 0xf - cp 10 - jr nc, .alpha ; if >= 10, we have alpha - add a, '0' - ret -.alpha: - add a, 'A'-10 + ; we need to make the upper nibble a known value + ; also clears the N, C and H flags for daa + or 0xf0 + daa ; now a =0x50 + the original value + 0x06 if >= 0xfa + add a, 0xa0 ; cause a carry for the values that were >=0x0a + adc a, 0x40 ret ; Formats value in A into a string hex pair. Stores it in the memory location @@ -204,7 +210,6 @@ fmtHexPair: dec hl pop af push af - and 0xf0 rra \ rra \ rra \ rra call fmtHex ld (hl), a @@ -212,6 +217,7 @@ fmtHexPair: pop af ret + ; Compares strings pointed to by HL and DE up to A count of characters. If ; equal, Z is set. If not equal, Z is reset. strncmp: diff --git a/kernel/parse.asm b/kernel/parse.asm index 1bd81b2..9c97992 100644 --- a/kernel/parse.asm +++ b/kernel/parse.asm @@ -11,26 +11,21 @@ ; On success, the carry flag is reset. On error, it is set. parseHex: ; First, let's see if we have an easy 0-9 case - cp '0' - jr c, .error ; if < '0', we have a problem - cp '9'+1 - jr nc, .alpha ; if >= '9'+1, we might have alpha - ; We are in the 0-9 range - sub '0' ; C is clear - ret + sub '0' + ret c + cp 10 + ccf + ret nc .alpha: - call upcase - cp 'A' - jr c, .error ; if < 'A', we have a problem - cp 'F'+1 - jr nc, .error ; if >= 'F', we have a problem + and 0xdf ; converts uppercase to lowercase + sub 0x11 ; C if <'A' + ret c + cp 6 ; not C if >'F' + ccf + ret c ; We have alpha. - sub 'A'-10 ; C is clear - ret - -.error: - scf + add a, 10 ; C is clear ret ; Parses 2 characters of the string pointed to by HL and returns the numerical