Most emulators store the number of cycles a particular instruction takes in an array, and then adds any conditional cycles if needed (when crossing page boundaries, for example).
I'm wondering if there is a way to procedurally determine the number of cycles an instruction will take based solely on addressing mode and memory reads/writes.
To give an example, I've noticed that all instructions that use immediate or relative addressing take 2 cycles.
All zero-page instructions take 3 cycles, plus an additional 2 cycles if altering memory in-place.
All indexed zero-page instructions take 4 cycles, plus an additional 2 cycles if altering memory in-place.
...And so on.
So, is there some fully documented, procedural way of determining the number of cycles for an instruction like the above? Are there exceptions that would break determinism in such a formula?