It's true that self-modifying code is necessary if you want to load an arbitrary 12-bit address in one cycle. Depending on the specific circumstances, there may be simpler alternatives:
- just use `i:=NNN` to set a base address and then add an offset with `i += vx`. This is sufficient for many kinds of array indexing.
- If your array is no more than 256b and elements are wider than 1 byte, you might be able to use pre-multiplied offsets.
- If you need an array that is larger than 256b and elements are wider than 1 byte, use `i:=NNN` to set a base address and then add your offset several times: twice for 2-byte-wide elements, 4 times for 4-byte-wide elements, etc.
- If you only need to choose between a handful of 12-bit addresses, you could use conditionals or a jump table dispatched via `jump0`.
I have some examples and more discussion in the Chip8 programming techniques guide