Z80 optimisation tricks

[16 jun 2001]

Contents:
Assembler
- Tricks collection
- Binary to ASCII conversion

 

 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
Post your comments to vvid@mail.ru