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