The final djnz branch happens when the previous add changes ecnt from -2 to 0, which is the first unsigned carry. The next time round
the add changes ecnt from -1 to +1 and the djnz falls through.
[edit: the wc can alternatively be on the djnz instruction]
[EDIT: Then I had another thought:
blank .....
blank_ret ret ' blank routine at a lower address than foo
'-----------------------------
mov ecnt, #29-2
foo call #blank
djnz ecnt, #blank ' nice tight loop for NC calls
jmpret blank_ret, foo wc ' indirect via the source field of the call instruction at foo
'-----------------------------
Which shortens the inner loop, yay!
[EDIT AGAIN: I'm wrong about moving the blank routine, the values compared are instructions, so this will do:
'-----------------------------
mov ecnt, #29-2
foo call #blank wz ' WZ sets a bit high in the instruction making it larger in value than a plain ret instruction!
djnz ecnt, #blank ' nice tight loop for NC calls
jmpret blank_ret, foo wc ' indirect via the source field of the call instruction at foo, compare values of the two instructions to set C
'-----------------------------
@Mark_T: Congratulations! That even beats my version in runtime (I didn't exploit the fact the the return address remains set so you can jump directly). As for the last call, that's what I was after. But you don't have to force wz on the call itself. A call insn has its wr bit set while a ret doesn't. This makes it automatically unsigned greater.
Yes, well spotted. I made a test harness (attached) now with my (corrected) attempts to get the timings and verify. Addictive puzzle that - on the surface so simple...
I must be missing something. The first call happens at foo, which sets up the return address. Then 27 "calls" via the djnz. And finally one call via the jmpret. That's 29.
Which is why its not generally used for looping zero or more times, since to excute the body zero times it would have to jump -1 times which is a little too quantum for the Prop.
Comments
The final djnz branch happens when the previous add changes ecnt from -2 to 0, which is the first unsigned carry. The next time round
the add changes ecnt from -1 to +1 and the djnz falls through.
[edit: the wc can alternatively be on the djnz instruction]
[EDIT: Then I had another thought: Which shortens the inner loop, yay!
[EDIT AGAIN: I'm wrong about moving the blank routine, the values compared are instructions, so this will do:
Minor nitpick, it's still mov ecnt, #29-1.
-Phil
-Phil
-Phil