Look-Up Tables (LUTs): Trading Memory for Speed
A Look-Up Table (LUT) is a pre-calculated block of data stored in memory. Instead of performing a time-consuming calculation (like a sine function or a multiplication), the CPU simply uses the input value as an index to quickly read the pre-computed result.
How to Use a LUT:
- Use the input value (N) to calculate the offset within the table.
- Add this offset to the table’s starting address.
- Read the byte (result) at that final calculated address.
Example: 10-Value Square Root Table
SQRT_TABLE:
DB 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 ; Results for 0 through 9
LOOKUP:
LD L, INPUT_VALUE ; Use input value as index/offset
LD H, 0 ; Clear high byte (HL = offset)
; Add the offset (HL) to the table's base address (in DE)
LD DE, SQRT_TABLE
ADD HL, DE ; HL now holds the address of the result
LD A, (HL) ; Read the pre-calculated result into A
Self-Modifying Code (SMC)
Self-Modifying Code is a powerful, though controversial, optimization where the program modifies its own instruction stream while it’s running. This is used to make loops faster by pre-calculating an address within the loop itself.
The Principle: Replace slow address calculation inside a loop with a one-time instruction replacement outside the loop.
Example: Modifying a Jump Address
If you have a function that always jumps to an address based on a register, you can change the address of the JP
instruction itself.
; Assume HL holds the new destination address
LD (JUMP_TARGET + 1), L ; Change the low byte of the target address
LD (JUMP_TARGET + 2), H ; Change the high byte of the target address
JUMP_TARGET:
JP 0000H ; This instruction's address (0000H) is overwritten!
Warning: SMC is difficult to debug and often disallowed in protected memory environments, but it offers max speed on bare Z80 hardware.