====== Dispatching on a Byte ======
//by White Flame and Krill//
The need to dispatch to one of many possible routines based on the value of a byte comes up regularly if you're doing complex data-oriented routines like decompression or scripting, and most often needs to be as fast as possible.
All but the Stack Dispatch routine use self-modification, which will run 1 cycle faster and 1 byte leaner if the dispatch routine itself is in zeropage.
===== General Table Dispatch =====
==== 128 entries or less ====
sta :+ +1
: jmp (table)
table:
.word handler0, handler2, handler4, ...
* 9 cycles, 8 if from zeropage
* Align opcodes and table low-word, or use ''SBC''/''ASL'' to adjust
* Maximum of 128 entries
==== More than 128 entries ====
asl
bcs :++
; Dispatch 0-127
sta :+ +1
: jmp (table)
; Dispatch 128-255
: sta :+ +1
: jmp (table + $0100)
table: .word handler0, handler1, ..., handler127, handler128, ...
* 13 cycles for 0-127, 14 cycles for 128-255. Subtract 1 cycle if from zeropage.
===== Stack Dispatch =====
tax
txs
rts
* 8 or 10 cycles, depending on if ''TAX'' is necessary
* Table of vectors at $0100
* Maximum of 128 entries
* Handlers cannot use stack, or must reposition it to not trample the table
===== Low-Address Dispatch =====
sta :+ +1
: jmp routine ; Low byte is overwritten, high byte remains
* 7 cycles, 6 if in zeropage
* All handlers start in the same memory page
* Byte codes match specific addresses with little flexibility
===== High-Address Dispatch =====
sta :+ +2
: jmp $0000 ; High byte is overwritten, low byte remains
* 7 cycles, 6 if in zeropage
* All handlers start on their own page, at the same low byte
* Byte codes constrained to ranges based on memory map
===== Relative Branch Dispatch =====
sta :+ +1
: bne * ; If Z corresponds to A, otherwise use appropriate BRA
* 7 cycles, 6 if in zeropage
* Similar to low-address dispatch but allows page-crosses at the cost of one cycle
* Saves one cycle for the fall-through case