I'm making a project where time is critical so I can't rely on timers because, depending of the instruction being interrupted, the number of cycles after interrupt may differ.
I made a small assembler routine that "wastes" time by executing MOVC A,@A+DPTR instruction in a loop. The reference guide states that it takes 6 cycles to execute this instruction at max speed (48 MHz) with prefetch, but it actually takes 5 cycles after branch, and 4/5 (I guess it's because prefetch is 2 bytes, and the instruction is 3 bytes so it sometimes takes an extra cycle) if it's executed consecutively. Also DJNZ takes 4 if the jump is taken, and not 5. I noticed it because the routine was executed faster than I expected. I saw in the guide that clock frequency could vary 1.5%, but this was much more than that (6%). So I used debugger with timer and it showed that the guide is wrong. When taken different timings into account, I got that 6% difference.
Did someone else encounter this?
On devices with a flash prefetch engine, the instruction execution time may actually be less than the maximum based on where the jump/destination addresses are located (if they're on a particular address boundary). So, 6 cycles may be the absolute worst case if the instruction is at a non-optimal address. This article has more information: https://www.silabs.com/community/mcu/8-bit/knowledge-base.entry.html/2016/10/07/branch_instructionv-wJQ1