0

I am preparing for a University Exam and i don't understand why the immediate field in the I-type gets extended from 16 bit to 32 bit is there an explanation I need to know or is it just something that you have to know that happens in the architecture without knowing why?

Also while calculating the branch address

PC <– PC + 4 + (sign_ext(Imm16) << 2)

Why does the immediate get shifted by 2?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
DRE
  • 263
  • 8
  • 35
  • 6
    It's shifted by 2 because each instruction is 4 bytes so it's pointless to store the two least significant bits. In other words, the count is not bytes, but instructions. It's extended to 32 bits because PC is 32 bits, and it's sign extended to allow negative offsets (backward jumps) as well. PS: your title talks about load/store but the question itself is about jumps. – Jester Mar 18 '20 at 15:15
  • so let me check if i understood correctly it gets extended to 32 bit because the alu process only 32 bit and not 16 right? i still don't get the shifted by 2 – DRE Mar 18 '20 at 15:17
  • 5
    The lowest two bits of the PC must always be zero. What's the point of allowing a 16-bit immediate and either a) ignoring two of the bits or b) having a problem if they're non-zero. By shifting by 2 you allow all 16 bits to be useful and you support a wider range of jump targets. – Damien_The_Unbeliever Mar 18 '20 at 15:19
  • 2
    You can think of the immediate meaning number of instructions to jump. Since each instruction is 4 bytes and the PC counts in bytes, that means you need to multiply by 4. I hope you know that shifting by 2 bits is multiplying by 4. – Jester Mar 18 '20 at 15:21
  • What i don't get now is that when i extend the immediate from 16 to 32 bit it's already 4 bytes so why we shift by 2? I am sorry if i don't understand i am totally new to this topic. – DRE Mar 18 '20 at 15:33
  • 1
    Which part is unclear? The shifting is due to the instruction size. As I said, think of the immediate meaning number of instructions to jump. To convert to bytes, you need to shift by 2. Or think of the formula as multiplying by 4 if you are uncomfortable with shifts. – Jester Mar 18 '20 at 15:36
  • 1
    So the first 16 bit represent the number of instructions i want to jump, when i shift them by 2 (multiply by 4) is just like multipling the number of instuctions i want to jump with the size of an instruction am i right? and i extend the sign to allow the possibility of backwards jump right? – DRE Mar 18 '20 at 15:41
  • 3
    Yes that is correct. – Jester Mar 18 '20 at 15:44
  • Related: [How to Calculate Jump Target Address and Branch Target Address?](https://stackoverflow.com/q/6950230) – Peter Cordes Mar 18 '20 at 17:13

1 Answers1

3

As already answered in the many comments...

Although MIPS does have a 16 bit instruction format the instruction set everyone is familiar with is a 32 bit fixed length instruction set, on aligned boundaries.

The various operations use 32 bit operands.

You cannot have a 32 bit immediate in an instruction set that is fixed 32 bits; there would be no bits left for an opcode. So MIPS has different instruction formats with different immediate sizes to balance a rich array of instructions without as much pain at using immediates or forcing all immediates to be loaded from a nearby pool. Worst case you can fall back on that but for a good number of things you can use the instructions as designed.

So the immediate fields are much less than 32 bits, but the operands they represent are generally 32 bits, so they need to be extended in some way, either shifted 16 and padded with zeros at the bottom or extended from the top unsigned or not (speaking generically not just for this type of mips) to make a 32 bit value.

How the immediate is used should be looked up per instruction in the documentation.

Why do branches shift the immediate by 2?

The instructions are on aligned 32 bit boundaries which means the lower 2 bits are always zero. If you encoded those zeros into the immediate you would always have to make them zero and basically lose four times the possible range of your pc relative branch. Think of the immediate in this case to be the number of INSTRUCTIONS I want to branch rather than number of BYTES of address.

Being signed allows for forward or back branching.

nextPC <– PC + 4 + (sign_ext(Imm16) << 2)

The + 4 is part of a pipeline illusion, different cores have their own pipe designs so there must be a standard to have the ISA not be crazy to use (very typical design choice across many ISAs to have the PC at execution time point at the next instruction). So nextPC is the PC of the next instruction plus the signed offset number of instructions in the immediate (by shifting left two making the lower two bits zero). If the condition is met or if unconditional (I don't know all the I format instructions, I don't need to in order to answer this question) then nextPC is used by the logic otherwise PC + 4 is used for the next instruction.

Edit

Yes, you are correct; the sign extension does already make it a 32 bit value. The additional shift is to maximize the range that the branch can take, giving us four times as far forward or backward to branch with this instruction format. The upper sign extended bits are all either 0s or 1s and there are more than 2 bits of extension so shifting the temporary 32 bit value two more bits does no harm to that value.

With a 16 bit signed immediate if I wanted to not do that shift of two then 0x00007FFC is the maximum distance I could branch forward and to be a valid instruction the lower two bits would have to be zeros. With the shift I can now branch 0x1FFFC forward and I can use all of the immediate bits.

halfer
  • 19,824
  • 17
  • 99
  • 186
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Another way to see the value of requiring left shifting as part of decoding: otherwise the low 2 bits of every branch instruction would always be required to be 0 to maintain PC alignment, essentially wasting them. – Peter Cordes Mar 18 '20 at 19:55
  • Oh, nvm, that's there in the middle of your answer. I was giving an alternate explanation to the part you added as an edit at the bottom. But you did already explain it both ways. I already knew the answer so I didn't fully read yours. – Peter Cordes Mar 18 '20 at 20:02