sll $rd, $rt, shift_amt sllv $rd, $rt, $rs srl $rd, $rt, shift_amt srlv $rd, $rt, $rs sra $rd, $rt, shift_amt srav $rd, $rt, $rsWe'll explain sll and sllv, then point out differences with the right-shifted versions.
In sll, the semantics are:
R[d] <- R[t]31-shift_amt::0shift_amt
where the copy of the contents of register t are shifted
left (the uppermost bits fall off). Zeroes are shifted in.
The shift amount is recorded in the shift amount field of the instruction (bits B10-6).
Notice register s is unused.
In sllv, the semantics are
R[d] <- R[t](31-R[s]4-0)--0::0R[s]4-0
This complicated expression just means to take the low (32 -
R[s]4-0) bits and shift it left by
R[s]4-0 bits where R[s]4-0 is
interpreted using 5-bit UB (thus the value of
R[s]4-0 ranges from 00000 to 11111).
Recall that shifting left by k bits is like multiplying a number by 2k. This is true in UB or in 2C, which is why there is no such thing as an arithmetic left shift.
Here are the key differences for right-shifted versions.
Shifting in the sign-bit does the "right thing" for 2C. That is, by shifting in the sign bit, you are dividing by 2k for 2C.
| Instruction | B31-26 | B25-21 | B20-16 | B15-11 | B10-6 | B5-0 |
| opcode | register s | register t | register d | shift amount | function | |
| sll $rd, $rt, shift_amt | 000 000 (SPECIAL) | unused | - | - | shift_amt | 000 000 |
| sllv $rd, $rt, $rs | 000 000 (SPECIAL) | - | - | - | 00000 | 000 100 |
| srl $rd, $rt, <shift_amt> | 000 000 (SPECIAL) | unused | - | - | shift_amt | 000 010 |
| srlv $rd, $rt, $rs | 000 000 (SPECIAL) | - | - | - | 00000 | 000 110 |
| sra $rd, $rt, <shift_amt> | 000 000 (SPECIAL) | unused | - | - | shift_amt | 000 011 |
| srav $rd, $rt, $rs | 000 000 (SPECIAL) | - | - | - | 00000 | 000 111 |
The dashes are filled in with 5-bit encoding of the registers (in UB), as usual.