What does “extend immediate to 32 bits” mean in MIPS?

你离开我真会死。 提交于 2019-12-02 10:10:41

On a 32-bit CPU, most of the operations you do (like adding, subtracting, dereferencing a pointer) are done with 32-bit numbers. When you have a number with fewer bits, you need to somehow decide what those other bits are going to be when you want to use that number in one of those operations. The act of deciding what those new high bits are is called "extending".

Assuming you are just doing a standard zero extension or sign extension, extending is very cheap. However, it does require some circuitry, so it makes sense that a description of the MIPS datapath would mention it.

26-bit immediates are only in jump instructions, and aren't sign- or zero-extended to 32 bit, because they're not displacements to be added/subtracted.

I-type instructions with 16-bit immediates are different.

  • addi / addui immediates are sign-extended (by duplicating the top/sign bit of the immediate to all higher bits).
    https://en.wikipedia.org/wiki/Two%27s_complement#Sign_extension
    This allows 2's complement numbers from -2^15 .. +2^15-1 to be encoded.
    (0xFFFF8000 to 0x00007FFF)
  • ori/andi/xori boolean immediates are zero-extended (by setting all higher bits to zero)
    This allows unsigned / 2's complement numbers from 0 .. 2^16-1 to be encoded.
    (0x00000000 to 0x0000FFFF)

This makes it possible to use 16-bit immediates as inputs to a 32-bit binary operation that only makes sense with 2 equal-width inputs. (In a simple classic MIPS pipeline, the decode stage fetches operands from registers and/or immediates. Register inputs are always going to be 32-bit, so the ALU is wired up for 32-bit inputs. Extending immediates to 32-bit means the rest of the CPU doesn't have to care whether the data came from an immediate or a register.)

Also sign-extended:

  • offsets in the reg+imm16 addressing mode used by lw/sw and other load/store instructions
  • relative branches (PC += imm16<<2)

maybe others, check the manual for instructions I didn't mention to see if they sign- or zero- extend.


You might be wondering "why does addiu sign-extend its immediate even though it's unsigned?"

Remember that there's no subiu, only addiu with a negative immediate. Being able to add or subtract numbers in the range -2^15 .. +2^15-1 is more useful than only being able to add 0 .. 2^16-1.

And usually you don't want to raise an exception on signed overflow, so normally compilers use addu / addiu even on signed integers. addu is badly named: it's not "for unsigned integers", it's just a wrapping-allowed / never-faulting version of add/addi. It sort of makes sense if you think of C, where signed overflow is undefined behaviour (and thus could use add and raise an exception in that case if the compiler wanted to implement it that way), but unsigned integers have well-defined overflow behaviour: base 2 wraparound.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!