为什么 ARM LSL 与 LSR 的允许移位值范围不同?

Why different ranges of permitted shift values for ARM LSL vs LSR?

为什么LSL的允许移位值为[0, 31],而LSR的允许移位值为[1, 32]?

在 LSL 中移 0 位对任何应用程序有何用处?为什么 LSR 不允许 0 移位?为什么 LSL 不允许 32 位移位?

此限制适用于立即数的移位。寄存器的移位不受此类限制。

LSL by 0 允许表示“无偏移”。这是一个特殊情况,因为标志设置指令的 C 标志未被修改。

LSRASR by 0 的行为方式与 LSL by 0 的行为相同,因此 CPU 设计者决定使立即操作数 0 表示移位 32,启用附加功能。对于 ROR 的情况,移位 0 表示特殊的“循环右扩展”指令 RRX 因为循环 32 不是很有用。

参考例如到 ARM7TDMI 数据表,其中显示:

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 [...].

在 Thumb (T32) 模式下,约定已修改。 Thumb 缺少明确的 MOVS Rd, Rn 指令,因此 LSLS Rd, Rn, #0 用于此目的。 LSR Rd, Rn, #imm5ASR Rd, Rn, #imm5 的行为与它们在 A32 模式下的行为相同。 #32 的立即数通过将五位立即数字段设置为零来编码。假设的指令 ROR Rd, Rn, #imm5 不存在,因为它所在的操作码 space 用于编码

ADDS Rd, Rn, Rm
SUBS Rd, Rn, Rm
ADDS Rd, Rn, #imm3
SUBS Rd, Rn, #imm3

相反。