Why is permitted shift value of LSL [0, 31] and permitted shift value of LSR is [1, 32]?
How is shifting 0 bits in LSL useful for any application? Why is 0 shift not allowed in LSR? Why doesn't LSL allow 32-bit shifts?
This restriction applies to shifts by immediates. Shifts by registers are not subject to such restrictions.
LSL
by 0 is permitted to indicate “no shift.” This is a special case in that the C
flag of a flag setting instruction is not modified.
LSR
and ASR
by 0 would behave the same way as LSL
by 0, so the CPU designers decided to make an immediate operand of 0 indicate a shift by 32, enabling additional functionality. For the case of ROR
, a shift by 0 instead indicates the special “rotate right extended” instruction RRX
as a rotate by 32 would not be very useful.
Refer e.g. to the ARM7TDMI datasheet where it says:
Note LSL #0 is a special case, where the shifter carry out is the old value of the CPSR C flag. The contents of Rm are used directly as the second operand.
The form of the shift field which might be expected to correspond to LSR #0 is used to encode LSR #32, which has a zero result with bit 31 of Rm as the carry output. Logical shift right zero is redundant as it is the same as logical shift left zero, so the assembler will convert LSR #0 (and ASR #0 and ROR #0) into LSL #0, and allow LSR #32 to be specified.
The form of the shift field which might be expected to give ASR #0 is used to encode ASR #32. Bit 31 of Rm is again used as the carry output, and each bit of operand 2 is also equal to bit 31 of Rm. The result is therefore all ones or all zeros, according to the value of bit 31 of Rm.
The form of the shift field which might be expected to give ROR #0 is used to encode a special function of the barrel shifter, rotate right extended (RRX). This is a rotate right by one bit position of the 33 bit quantity formed by appending the CPSR C flag to the most significant end of the contents of Rm [...].
In Thumb (T32) mode, the convention was adapted. Thumb lacks a distinct MOVS Rd, Rn
instruction, so LSLS Rd, Rn, #0
is used for this purpose. LSR Rd, Rn, #imm5
and ASR Rd, Rn, #imm5
behave the same way they do in A32 mode. An immediate of #32
is encoded by setting the five-bit immediate field to zero. The hypothetical instruction ROR Rd, Rn, #imm5
does not exist since the opcode space it would be found at is used to encode
ADDS Rd, Rn, Rm
SUBS Rd, Rn, Rm
ADDS Rd, Rn, #imm3
SUBS Rd, Rn, #imm3
instead.