Z80 optimisation tricks |
[16 jun 2001] |
 
Tricks collection |
Arithmetic | |
Clear accumulator | |
xor a | Both methods are equivalent |
sub a | |
Carry trick | |
sbc a,a | A=$00 if carry was clear A=$ff if carry was set useful for sign extending after byte operation |
if (A>B) goto label | |
inc a cp b jr nc,label |
assumed that A will never overflow jr c,label give you (A<=B) |
16 bit compare (< or >=) | |
ld a,l sub e ld a,h sbc a,d |
CF if HL<DE |
16 bit addition | |
ld a,l add a,e ld l,a ld a,h adc a,d ld h,a |
CF is valid,ZF is not |
16 bit subtraction | |
ld a,l sub e ld l,a ld a,h sbc a,d ld h,a |
CF is valid,ZF is not |
Calculate A = constant-A | |
cpl add a,constant+1 |
constant can be signed or unsigned |
Calculate hl = hl+a (unsigned) | |
add a,l ld l,a adc a,h sub l ld h,a |
A = unsigned index |
Calculate hl = -hl | |
xor a sub l ld l,a sbc a,h sub l ld h,a |
6 cycles... world's fastest ;) |
Calculate hl = -l | |
xor a sub l ld l,a sbc a,a ld h,a |
5 cycles... even faster if you don't worry about high byte |
Lookup through aligned 256 byte table without registers usage | |
ld [*+4],a ld a,[$xxyy] |
index in A replaced the yy. Selfmodified => working in RAM only |
Hide code inside a long instruction | |
jump to $0000: $0000 AF xor a $0001 013EFF ld bc,$ff3e jump to $0002: $0002 3EFF ld a,$ff |
I saw one Amiga compiler used the same, (bad for debugging) approarch. |
Binary<=>Text Conversion |
Fast binary to ASCII conversion | |
Convert nibble(4bit) to ASCII in HEX format | |
add a,$90 daa adc a,$40 daa |
transform nibble directly to ASCII code low nibble contain value to convert (0x00 ..0x0f), high must be cleared if you want to know how it works, look below |
Convert packed BCD ($99) to 1 byte binary [$00-$63] | |
ld b,a and $0f ld c,a xor b rrca ld b,a rrca rrca add a,b add a,c |
It just split 2 nibbles and multiply higher by 10 then add lower nibble. |
How the nibble => HEX conversion is working:
case 1:
;a=$0x (x = 0 to 9) add a,$90 daa ;a=$9x; (both nibbles are less then 10) => carry=0, half-carry=0 adc a,$40 ;a=$dx + carry(0) daa ; (9+4 gives 13) ;a=$3x => ASCII codes for 'A'->'F' case 2:
;a=$0x (x = $a to $f) add a,$90 daa ;(x+1)>10 => (9+1)=10 ;a=$0x; lower nibble (>10) is overflowed and will generate half-carry flag. ;this cause the higher nibble to be overflowed too, so carry will be set to 1 adc a,$40 ;a=$4x + carry(1) daa ; ;a=$4x+1 => ASCII codes for 'A'->'F'
DarkLair 16 jun 2001