4 ms·
If you take a look at the master's thesis on designing the compressed opcode format[1] (expressing instructions in a 16 bit encoding, similar to ARM Thumb, to i
by lambda 12y ago
If you take a look at the master's thesis on designing the compressed opcode format[1] (expressing instructions in a 16 bit encoding, similar to ARM Thumb, to increase efficiency of instruction cache utilization), in which they counted what registers were used most often in order to determine which to allow access to in the compressed format, you'll see that the 0 register is the 5th most common register, making up approximately 9% of all registers referenced in instructions. Dynamically, in terms of instructions actually executed as opposed to merely present, it's a little less common at closer to 4%, but still common enough to be worth choosing as one of the 8 registers accessible in the compressed format (actually, they only allow it for some operands of particular instructions where it is particularly useful in the compressed format, allowing other operands to have access to one more real register).
It's useful for several things. One is as a no-op instruction; as you point out, AND, OR, XOR, etc. with zero are no-ops, and no-ops are sometimes useful for achieving certain alignment in code, or leaving space for instructions to be patched out with other code (which is common for debugging, tracing, and hot-patching of code).
It can also be used for copying from one register to another, without another instruction. "ADD rd, rs1, 0" is a way to write "MOVE rd, rs", so you don't need to waste an extra instruction on that.
0 is also one of the most common values that you want to compare against (many loops can be turned into decrementing a value until it becomes zero, or you're just walking along a data structure or string until you encounter a null value), and so their branch instructions work by comparing two registers and branching to a particular offset. Having a dedicated 0 register means you can always do a compare against 0 and branch in a single instruction, without having to have separate instructions for comparisons against immediates versus comparison of two registers.
[1]: http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-63.pdf http://www.eecs.berkeley.edu/Pubs/TechRpts/2011/EECS-2011-63...
- PythonicAlpha 12y agoI did not think about comparisons ... that is right. The other examples are also valid, but rather special to RISC architectures ... but of course it does the trick.