For 1, I have no special knowledge about the original design of x86, but I suspect that the reason we don't have cmp %reg, $imm
is because of the relationship between cmp
and sub
. The instruction cmp $imm, %reg
behaves exactly like sub $imm, %reg
, with the one exception that for cmp
the result of the subtraction is not written to the destination %reg
, but instead is discarded. But the result of the subtraction is still computed internally by the CPU and used to set the flags. (At least this is true conceptually, and early CPUs almost certainly did the full subtraction; modern CPUs might have some optimizations that I don't know about.)
So this means that cmp
could be implemented nearly for free once you had sub
. You could use almost exactly the same circuitry and/or microcode. But you still have to decode the instruction, and so they made this easy as well by giving cmp
almost the same encodings as sub
, differing only in one bit. For instance, sub %reg, %reg/mem
is opcodes 28h/29h and cmp %reg, %reg/mem
is opcodes 38h/39h, differing only in bit 4. That one bit just signals the CPU whether to write the result to the destination operand or discard it.
This made it natural to give cmp
exactly the same forms as sub
:
We have sub %reg, %reg
so there is cmp %reg, %reg
.
We have sub %reg, mem
so there is cmp %reg, mem
.
We have sub mem, %reg
so there is cmp mem, %reg
.
We have sub $imm, %reg
so there is cmp $imm, %reg
.
There is even a special short encoding of sub $imm, %al/%ax/%eax/%rax
which has a parallel cmp $imm, %al/%ax/%eax/%rax
.
But there is no encoding of sub %reg, $imm
because that would be nonsense, so cmp %reg, $imm
would have needed a new encoding that wouldn't be parallel to an existing one for sub
. The designers presumably decided not to waste decoding transistors and opcode space on creating one, because after all it wouldn't really provide any new functionality: cmp
is practically always used in conjunction with a conditional jump (or later, conditional set), and in that case you can always achieve the same thing by using cmp $imm, %reg
and reversing the test in the subsequent conditional jump/set.