The problem is really whether to indulge bad programmers who don't respect the ABI at the cost of a minimal sliver of performance (even though it's not taking up an execution port the extra instruction still takes up cache space, bandwidth, and decode). Yeah they should probably zero the register before they zero the pointer but they shouldn't have to if other people respected the ABI.
In RISC-like machines, most of the operations are register-register, and you have load/store instructions for referencing memory.
To use an immediate operand (literal constant in the code itself), you may have to load it into a register, like
move r7, #42
add r1, r1, r7 ;; ok, now we have 42 in r7, we can increment r1 by 42.
Whereas in a CISC you would have add r1, #42 ;; two operand form
or maybe add r1, r1, #42 ;; three operand form
When you need a zero, you just use the immediate operand zero, and thus you don't need to to pick some register to clear.In summary, zero registers in RISC-like instruction set architectures effectively provide a literal zero that can be used wherever a register is required, which helps because only register operands can be used in many instructions.
What would an "actual zero" be -- a literal?
It strikes me as somehow the compiler is making assumptions that aren't being enforced by the ... OS? Language? not sure what, but it's assuming functions restore registers used but that isn't enforced by anything. From my (long ago) time there was PUSHA and POPA but I assume those take quite a bit of "oomph" and are avoided if possible.
One case of this problem was in a handwritten assembly file. The other was a compiler bug.
This is a case where the ABI requires that if you use a certain register you must save its previous value and restore it afterwords; the two independent bugs were cases of forgetting to look after a certain register.
An ABI is simply an agreement as to how things should work: what registers you are free to clobber, which you must look after when you use, how certain data must be laid out in memory, etc. ABIs are typically language specific, though there may be a lot of commonality at the very high level (i.e. how you use sections in an ELF file) and low (anybody using unboxed integers probably will do the same thing).
You are welcome to violate the ABI as you see fit in your own code. The OS doesn't care; it has its own constraints (how to make a system call, how to pass arguments to each -- though cf above when I talked about ints). So, say, a Lisp compiler can lay out stack frames differently from a C++ compiler because of the languages' different semantics) but if your Lisp program wants to call a library written in C++ it must make sure memory at the call site follows the C++ ABI because that's what the C++ compiler will have assumed.
I, for one, hate debugging asm. I do it a lot, and would prefer bugs be caught automatically, preferably soon after they are introduced.
It's not clear to me how to write such a tool as assembly code is the opposite of structured.
Adding an implicit zero may make sense for some instructions but probably not all.
MOVEQ can move more than a zero. It can move any small number (-128 to 127), so 0 is not "special" here.
Also check out the CLR instruction (though that may be what you meant by "a mnemonic for some or all of the instructions that assume zero").
However, moving a zero to a register does take time. Time that would otherwise be used operating with the zero value already present in the zero register.
The second best is what moto did. As you point out, there is the instruction fetch, which could be the intended operation, rather than developing the zero itself.
On par with that is having enough registers to just hold a zero, and whether that made sense depended on the need and developer strategy.
I am a big fan of the moto CPU's, starting with the 6809. Just to be clear.
Say we are zeroing memory. No advantage there. Coupla cycles right at the start, then a ton of writes.
Say we are forming a bitmask. Could be an advantage there in that having a zero handy in a register means no fetching one. When a lot of dynamically created masks are needed, this can be a nice gain.
I'm sure we can come up with more. It's not always important, and like you mention with the moto designs, may not matter too much due to many other optimizations possible given a good instruction set.
Some people would rather have the register free for general use! I'm one of those, but if there is a zero register, I use it to get the benefit of it when I can. On the devices I've seen, there are generally a lot of registers so the marginal impact of having a zero register isn't significant. There are plenty to work with.
Maybe I should be clear here too. I personally don't care whether there is one. If it's there, I do things in ways that leverage it, and was just pointing out why devices that have one, ahem... have one! Those that don't may or may not have options that make sense. The way moto did it is very good, and there are other pretty great optimizations possible with their ISA, abusing the stack to write memory, etc...
If not, then I do other things. It's assembly language! Work the chip, right?