This will depend greatly on the rest of your ISA, but in general adding stuff isn't free.
Adding an operand-less pop
instruction reduces the available opcode space for other instructions.
Sure, you can create some baroque, x86-inspired scheme to support infinite instructions, but then you have to actually implement that, and pay the additional associated costs.
Also, is it limited to only word-sized pop
s, or can it do byte-pop
s, half-word-pop
s, and double-word-pop
s as well? With a register operand, the size of the register could indicate how many bits to pop
. Without any operands, you'd have to use multiple opcodes to support different sized pop
s. Or support just a default size and force direct stack pointer manipulation for anything else.
It's another instruction that needs to be implemented.
That means more time and money spent designing and testing the implementation. In hardware implementations, it probably means more circuitry, resulting in a larger, more expensive, hotter, slower product. Software implementations require more code, resulting in more space for bugs, and possibly requiring a more powerful (i.e. more expensive) target platform.
There's really not much benefit.
As you've already pointed out, it's redundant. sub $SP, 4
or similar basically already does the same thing. Yeah, maybe it's slightly more convenient than manual stack pointer manipulation in the rare occasion that it's applicable, but we've known for decades that assembly language is not what you use when you want to code with high productivity. If you're worried about productivity, port a C compiler to your ISA, or better yet, something like D or Rust. Maybe even get some high level non-systems languages running on it. Leave the assembly to the rare times it's necessary, or for educational purposes.
If it comes for free, then maybe leave it there, rather than spending extra work to remove it.
MIPS gets something similar for free. Or would, if it had a pop
instruction. MIPS's $0
register is hardcoded to 0 and discards writes. A hypothetical pop
instruction for MIPS would still take an operand, but, if you specify register $0
, then you'd get your stack pointer adjustment without saving the popped value. This way you wouldn't need an extra pop
opcode for a particular edge case, and it could just reuse the same dataflow infrastructure used by every other instruction that writes to a register.
Dedicating a register to zero does have it's own costs, notably that it reduces the number of other, more versatile registers that can be made available, and that it's a special case register. The former is only significant if your ISA is already limited on available registers. The latter is offset by the fact that it's an exceedingly simple special case. Depending on the implementation, it may in fact be less expensive in some ways than a general purpose register (no need for memory logic, no need for any input connections...).