Why did MIPS include shamt and distinguish funct/opcode?

Question Detail: 

I'm confused as to why the MIPS designers would include 5 bits dedicated to shifting and have separate opcode and function bits.

Because MIPS is so RISC I assume that only shifting would be done in a few instructions, so those 5 bits seem like they're wasting space when they could be put in the immediate. I assume that opcodes and funct are seperate for distinguishing R- and I- type instructions, but this could be done by extending the opcode by 1 bit. With both of these R-type instructions could be 22 bits long. This won't work if the I-type and J-type instructions want to keep their immediate and address, but both seem unnecessary.

Asked By : qwr
Best Answer from StackOverflow

Question Source : http://cs.stackexchange.com/questions/28126

Answered By : Wandering Logic

There are a few different trade-offs going on here.

First, we want the instructions to be fixed width (32-bits). This guarantees that instructions are cache-block and page aligned which simplifies cache and page presence and permission checks.

Second we want the various instruction fields (opcode/source regs/immediates) to be fixed width and fixed position. This makes them faster/less logic to decode and they are needed in the early stages of the pipeline. (The destination register isn't needed until the end of the pipeline, so it can be in different places in R and I instructions.) The position and width of the function field matters a little less because that needs to control the function of the ALU, but that's in the third pipeline stage, so you have a little time to work with it if needed.

But now we have a tension between number of possible instructions and the sizes of the immediates. We want the immediates in the I and J instructions to be long as possible. This is a 32-bit architecture, and the J instruction has only a 26-bit address. It gets two zero low-order bits added to it (another benefit of fixed width instructions) but you can still only jump a maximum distance of $2^{28}$ bytes, which makes life difficult for the linker. (A call of a procedure that is more than $2^{28}$ bytes distant needs to be done with a triple instruction: load-upper-immediate, add-immediate, jump-and-link-register, instead of just a jump-and-link.) The 16-bit immediate in I instructions is also nice for compiler/linker writers. (On the SPARC, where the immediate field was only 12 bits they had to add an entire special load-high instruction class with a 20 bit immediate.)

So we really don't want to make the opcode 7 bits (because it will cut into immediates) but with 6-bits we only have $2^6=64$ possible different instructions, which is way too few. The compromise is: there are exactly two type J instructions (jump and jump-and-link), and only one or two type R instructions, with the remaining 60-or-so opcodes being used for I instructions.

But that leaves some wiggle room with the R instructions. Aside from the 6-bit opcode, these only need 15 additional bits for register specification, which leaves 11 bits for the extended opcode and/or shift-amount.

You should think of the function field as being an extended opcode for the R instruction. There's only one R instruction opcode, but there are 64 different functions that the R instruction can perform.

Okay. We have 60 different I instructions and 64 different R instructions, so where should we put the shift-immediate instructions?

Well, not only are there fewer I instructions, but there are way more things we want to do with I instructions. Recall that all the branch instructions need to be I instructions because they have a relative (immediate) offset. Also all the load and store instructions are I format on MIPS. And finally we need the load-upper-immediate instruction to be an I instruction. Not only that, but the R instructions still have 5 additional unused bits, (which is what we need for the immediate of a shift-immediate on this architecture), so this gives further incentive to making the shift-immediates into special (weird) R instructions.

A lot of these decisions are more art than science, but there is an underlying logic that can be discerned. The key goal is not to make the number of instructions as small as possible, it is to make a high-performance pipeline fit on a single chip (so that tiny companies, like MIPS and Sun were in the 1980s, could compete with IBM and DEC). (The name RISC, invented by David Patterson, is somewhat unfortunate. It caught on because it was cute, not because "reduced instructions" is an accurate description of what the MIPS and SPARC architectures were really trying to do.) So you want the instructions fixed width (and relatively small so that you get better I-cache behavior) to make fetch, paging and decode simpler and faster. You want the parts of the instruction that need to be decoded early (the opcode, the two source registers, and the sign-extended immediate) to be a fixed width and in a fixed position. You want immediates to be as long as possible, and you want as many different kinds of instructions as will fit, given all those other constraints.

No comments

Powered by Blogger.