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:

  1. Use the input value (N) to calculate the offset within the table.
  2. Add this offset to the table’s starting address.
  3. 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.