Skip to main content

There's no real optimisation — LDIR (or indeed LDDR, which goes downward instead of upwards) is the complete inner loop. It will always load from DEHL, store to HLDE, increment both and decrement BC. Then if BC is non-zero it will repeat.

Annoyingly it will repeat almost exactly by just decrementing the PC by 2. So it'll read the full instruction again. Which means that 50% of memory accesses are it reading the opcode for the entire loop. No doubt that's to keep refresh going but oneThe advantage is that interrupts can imaginebe accommodated while a better solutiontransfer is in progress.

Cost is 21 cycles for each time around the loop that does lead to a repetition, then 16 cycles on the final go. Four cycles opcode fetch, four cycles opcode fetch, three cycles reading from the address pointed to by DEHL, then a long five cycle write to the address pointed to by HLDE. Then five cycles without a bus access if repeating.

Unrolled LDIs will be faster if you have the space as they always cost the flat 16 cycles. E.g. put 16 of them in a row with a conditional jump at the end and if the number of bytes you want to copy is n then jump into the loop n mod 16 steps from the repetition test for the first iteration.

Alternatively, if you're writing for a computer with slower RAM access that ROM access (e.g. because RAM is shared with video) then a top tip is to look for the three-byte sequence LDIR RET anywhere in ROM and call it.

There's no real optimisation — LDIR (or indeed LDDR, which goes downward instead of upwards) is the complete inner loop. It will always load from DE, store to HL, increment both and decrement BC. Then if BC is non-zero it will repeat.

Annoyingly it will repeat almost exactly by just decrementing the PC by 2. So it'll read the full instruction again. Which means that 50% of memory accesses are it reading the opcode for the entire loop. No doubt that's to keep refresh going but one can imagine a better solution.

Cost is 21 cycles for each time around the loop that does lead to a repetition, then 16 cycles on the final go. Four cycles opcode fetch, four cycles opcode fetch, three cycles reading from the address pointed to by DE, then a long five cycle write to the address pointed to by HL. Then five cycles without a bus access if repeating.

Unrolled LDIs will be faster if you have the space as they always cost the flat 16 cycles. E.g. put 16 of them in a row with a conditional jump at the end and if the number of bytes you want to copy is n then jump into the loop n mod 16 steps from the repetition test for the first iteration.

Alternatively, if you're writing for a computer with slower RAM access that ROM access (e.g. because RAM is shared with video) then a top tip is to look for the three-byte sequence LDIR RET anywhere in ROM and call it.

There's no real optimisation — LDIR (or indeed LDDR, which goes downward instead of upwards) is the complete inner loop. It will always load from HL, store to DE, increment both and decrement BC. Then if BC is non-zero it will repeat.

Annoyingly it will repeat exactly by just decrementing the PC by 2. So it'll read the full instruction again. Which means that 50% of memory accesses are it reading the opcode for the entire loop. The advantage is that interrupts can be accommodated while a transfer is in progress.

Cost is 21 cycles for each time around the loop that does lead to a repetition, then 16 cycles on the final go. Four cycles opcode fetch, four cycles opcode fetch, three cycles reading from the address pointed to by HL, then a long five cycle write to the address pointed to by DE. Then five cycles without a bus access if repeating.

Unrolled LDIs will be faster if you have the space as they always cost the flat 16 cycles. E.g. put 16 of them in a row with a conditional jump at the end and if the number of bytes you want to copy is n then jump into the loop n mod 16 steps from the repetition test for the first iteration.

Alternatively, if you're writing for a computer with slower RAM access that ROM access (e.g. because RAM is shared with video) then a top tip is to look for the three-byte sequence LDIR RET anywhere in ROM and call it.

Source Link
Tommy
  • 38.1k
  • 3
  • 128
  • 176

There's no real optimisation — LDIR (or indeed LDDR, which goes downward instead of upwards) is the complete inner loop. It will always load from DE, store to HL, increment both and decrement BC. Then if BC is non-zero it will repeat.

Annoyingly it will repeat almost exactly by just decrementing the PC by 2. So it'll read the full instruction again. Which means that 50% of memory accesses are it reading the opcode for the entire loop. No doubt that's to keep refresh going but one can imagine a better solution.

Cost is 21 cycles for each time around the loop that does lead to a repetition, then 16 cycles on the final go. Four cycles opcode fetch, four cycles opcode fetch, three cycles reading from the address pointed to by DE, then a long five cycle write to the address pointed to by HL. Then five cycles without a bus access if repeating.

Unrolled LDIs will be faster if you have the space as they always cost the flat 16 cycles. E.g. put 16 of them in a row with a conditional jump at the end and if the number of bytes you want to copy is n then jump into the loop n mod 16 steps from the repetition test for the first iteration.

Alternatively, if you're writing for a computer with slower RAM access that ROM access (e.g. because RAM is shared with video) then a top tip is to look for the three-byte sequence LDIR RET anywhere in ROM and call it.