I'm working on tweaking ABC-800 BASIC II machine code, and there's a routine there that does a "256-byte" equivalent of LDIR. B is not used, C=0 transfers 256 bytes, C=1 transfers 1 byte, etc.
The existing code is:
0000 ; C - length (0=256 bytes)
0000 ; DE - destination
0000 ; HL - source
653D .ORG 653dh
653D ED A0 BLKTF: LDI
653F AF XOR A
6540 B1 OR C
6541 20 FA JR NZ,BLKTF
6543 C9 RET
That is nice, compact code, but obviously using LDIR could be faster. The best I could come up with is one byte longer:
653D .ORG 653dh
653D AF BLKTF: XOR A ; clear A
653E B9 CP C ; CF=0 if C was zero
653F 3F CCF ; CF=1 if C was zero
6540 17 RLA ; rotate C into A
6541 47 LD B,A ; now BC = 1..256
6542 ED B0 LDIR
6544 C9 RET
Is there a way to do better, retaining the same API?
LDIR
is famously slow. It may make code clearer, quicker to write, or possibly a smaller binary, etc. I do not know if it would be slower than the code you're starting with though.On the Z80, LDIR is not as fast as unrolling the loop to produce a block of LDI instructions. You can jump into the middle of the block at count % blocksize to copy sizes which are not a round number. This was a fairly common game trick
- Oh, that's actually a circular link.