To understand the MIPS I instruction formats, you need to understand the MIPS pipeline and also think back to CPU implementation technology circa 1985. If you look at the diagram (you know the one), you'll see that register file reading is in the ID stage, right after IF.
For the purpose of an R-type instruction, the ID stage needs to do the following tasks:
- Determine that it actually is an R-type instruction.
- If so, tell the register file to load values from registers.
For the purpose of this discussion, it's the first task that you have to think about. If there's a lot of instruction decoding work that you have to do to even work out if you need any values from registers, this increases the delay before you can start the register reads. It also increases the complexity of the ID stage. By reserving a single opcode for all R-type instructions, you keep the complexity to a minimum.
It does seem a little strange that you dedicate five bits just to shifting. I can think of a few possible explanations. One is that it simplifies the routing (those five bits are ALWAYS fed straight into the register file, those five bits are ALWAYS fed into the barrel shifter, those six bits are ALWAYS routed through to the ALU to determine which function to perform).
They may have been thinking of introducing combined shift-left-and-add instructions in the future. This would presumably be of the form:
$d = $s + ($t << shamt)
This is a surprisingly useful instruction to have around, as any x86 assembly programmer can tell you. You can use it to implement fast multiplications by $2^s+1$ for various values of $s$, or you can use it to index arrays where the size of an element is a power of two (which is a very common case). But it's still RISC enough that you could implement it without significant penalty.
Today, we probably wouldn't think twice about having a more complex decoding stage, especially since register file accesses tend to happen later in the pipeline of a typical superscalar CPU. Many modern CPUs even do some coarse instruction decoding at the time an instruction is inserted in the L1 cache. You make the I-cache lines a few bits wider to store the extra information (thanks to Moore's Law, you have lots of transistors to waste) to make "proper" instruction decoding simpler and faster.
One reason why they probably wanted to keep the opcode field as small as possible is so that it didn't penalise J-type instructions unduly. As you probably know, J-type instructions use pseudo-direct addressing. For the benefit of anyone playing along at home, I'll briefly explain it.
The address field of a J-type instruction is 26 bits. Because instructions are always 4-byte aligned, you don't need to store the least significant two bits, which means you effectively have 28 bits of address. However, the address space in MIPS I is 32-bits. So the top four bits of the jump location is taken from the program counter.
This means that you can't directly jump to a location where the most significant four bits of the PC location are different. You would have to do a more expensive three-instruction jump through a scratch register instead:
lui $r,target >> 16
ori $r,$r,target & 0xFFFF
That's not too bad today, but in 1985, it's a lot of clock cycles.
Stealing a bit from the address field would reduce the effective range of a direct jump even further. You can see how this might be too high a price to pay.