Z80 jump tables
Sometimes you want to jump to a subroutine depending on a value. A jump table is ideal for this. However, addresses are 16-bit which can become messy to compute, so you'll ideally want a simpler approach.
The trick here is the jr
(jump relative) instruction: its
operand is a byte long which indicates how many bytes forward to jump (or
backward, if negative). The idea is to put the jump table right after it,
and then overwrite this operand to jump to the entry we want each time.
Assuming the index is in the A register, it'd look like this (note that
$
is the address of the current instruction, if you're left
wondering):
; Multiply index by 3 (the size
; of a JP instruction)
ld b, a
add a, b
add a, b
; Overwrite the following jump
; with the index and then run
; into it (which will jump into
; the jump table below)
ld ($+4), a
jr $
; Jump table goes here
jp Routine1
jp Routine2
jp Routine3
...
Further remarks:
- The maximum index you can address this way is 42 (larger than this and the value will overflow when multiplied). For most purposes it should be more than enough.
- You can keep the index already premultiplied by 3 (especially if you're going to use it often), in this case you can avoid the multiplication by 3 at the beginning and shave off some cycles.