Thumb Instruction Details
A6.4
Shifts applied to a register
ARM register offset load/store word and unsigned byte instructions can apply a wide range of different
constant shifts to the offset register. Both Thumb and ARM data-processing instructions can apply the same
range of different constant shifts to the second operand register. See Constant shifts for details.
ARM data-processing instructions can apply a register-controlled shift to the second operand register.
A6.4.1
Constant shifts
These are the same in Thumb and ARM instructions, except that the input bits come from different
positions.
<shift> is an optional shift to be applied to <Rm>. It can be any one of:
(omitted)
Equivalent to LSL #0.
LSL
#<n>
logical shift left <n> bits. 0 <= <n> <= 31.
LSR
#<n>
logical shift right <n> bits. 1 <= <n> <= 32.
ASR
#<n>
arithmetic shift right <n> bits. 1 <= <n> <= 32.
ROR
#<n>
rotate right <n> bits. 1 <= <n> <= 31.
rotate right one bit, with extend. bit [0] is written to shifter_carry_out, bits [31:1] are
shifted right one bit, and the Carry Flag is shifted into bit [31].
RRX
Encoding
The assembler encodes <shift> into two type bits and five immediate bits, as follows:
(omitted)
type = 0b00, immediate = 0.
LSL
#<n>
type = 0b00, immediate = <n>.
LSR
#<n>
type = 0b01.
If <n> < 32, immediate = <n>.
If <n> == 32, immediate = 0.
ASR
#<n>
type = 0b10.
If <n> < 32, immediate = <n>.
If <n> == 32, immediate = 0.
ROR
RRX
A6-12
#<n>
type = 0b11, immediate = <n>.
type = 0b11, immediate = 0.
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
ARM DDI 0403C
Restricted Access
Thumb Instruction Details
A6.4.2
Register controlled shifts
These are only available in ARM instructions.
<type> is the type of shift to apply to the value read from <Rm>. It must be one of:
Arithmetic shift right, encoded as type = 0b10
Logical shift left, encoded as type = 0b00
Logical shift right, encoded as type = 0b01
Rotate right, encoded as type = 0b11.
ASR
LSL
LSR
ROR
The bottom byte of <Rs> contains the shift amount.
A6.4.3
Shift operations
// DecodeImmShift()
// ================
(SRType, integer) DecodeImmShift(bits(2) type, bits(5) imm5)
case type of
when ’00’
shift_t = SRType_LSL; shift_n = UInt(imm5);
when ’01’
shift_t = SRType_LSR; shift_n = if imm5 == ’00000’ then 32 else UInt(imm5);
when ’10’
shift_t = SRType_ASR; shift_n = if imm5 == ’00000’ then 32 else UInt(imm5);
when ’11’
if imm5 == ’00000’ then
shift_t = SRType_RRX; shift_n = 1;
else
shift_t = SRType_ROR; shift_n = UInt(imm5);
return (shift_t, shift_n);
// DecodeRegShift()
// ================
SRType DecodeRegShift(bits(2) type)
case type of
when ’00’ shift_t = SRType_LSL;
when ’01’ shift_t = SRType_LSR;
when ’10’ shift_t = SRType_ASR;
when ’11’ shift_t = SRType_ROR;
return shift_t;
// Shift()
// =======
bits(N) Shift(bits(N) value, SRType type, integer amount, bit carry_in)
(result, -) = Shift_C(value, type, amount, carry_in);
return result;
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-13
Thumb Instruction Details
// Shift_C()
// =========
(bits(N), bit) Shift_C(bits(N) value, SRType type, integer amount, bit carry_in)
assert !(type == SRType_RRX && amount != 1);
if amount == 0 then
(result, carry_out) = (value,
else
case type of
when SRType_LSL
(result, carry_out) =
when SRType_LSR
(result, carry_out) =
when SRType_ASR
(result, carry_out) =
when SRType_ROR
(result, carry_out) =
when SRType_RRX
(result, carry_out) =
carry_in);
LSL_C(value, amount);
LSR_C(value, amount);
ASR_C(value, amount);
ROR_C(value, amount);
RRX_C(value, carry_in);
return (result, carry_out);
A6-14
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
ARM DDI 0403C
Restricted Access
Thumb Instruction Details
A6.5
Memory accesses
The following addressing modes are commonly permitted for memory access instructions:
Offset addressing
The offset value is added to or subtracted from an address obtained from the base register.
The result is used as the address for the memory access. The base register is unaltered.
The assembly language syntax for this mode is:
[<Rn>,<offset>]
Pre-indexed addressing
The offset value is applied to an address obtained from the base register. The result is used
as the address for the memory access, and written back into the base register.
The assembly language syntax for this mode is:
[<Rn>,<offset>]!
Post-indexed addressing
The address obtained from the base register is used, unaltered, as the address for the memory
access. The offset value is applied to the address, and written back into the base register.
The assembly language syntax for this mode is:
[<Rn>],<offset>
In each case, <Rn> is the base register. <offset> can be:
•
an immediate constant, such as <imm8> or <imm12>
•
an index register, <Rm>
•
a shifted index register, such as <Rm>, LSL #<shift>.
For information about unaligned access, endianness, and exclusive access, see:
•
Alignment support on page A3-3
•
Endian support on page A3-5
•
Synchronization and semaphores on page A3-8
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-15
Thumb Instruction Details
if P == ’0’ && W == ’0’ then UNDEFINED;
t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Assembler syntax
LDR<c><q>
<Rt>, [<Rn> {, #+/-<imm>}]
LDR<c><q>
<Rt>, [<Rn>, #+/-<imm>]!
LDR<c><q>
<Rt>, [<Rn>], #+/-<imm>
Offset: index==TRUE, wback==FALSE
Pre-indexed: index==TRUE, wback==TRUE
Post-indexed: index==FALSE, wback==TRUE
where:
<c><q>
See Standard assembler syntax fields on page A6-7.
<Rt>
Specifies the destination register. This register is allowed to be the SP. It is also allowed to
be the PC, provided the instruction is either outside an IT block or the last instruction of an
IT block. If it is the PC, it causes a branch to the address (data) loaded into the PC.
<Rn>
Specifies the base register. This register is allowed to be the SP. If this register is the PC, see
LDR (literal) on page A6-90.
+/-
Is + or omitted to indicate that the immediate offset is added to the base register value
(add == TRUE), or – to indicate that the offset is to be subtracted (add == FALSE). Different
instructions are generated for #0 and #-0.
<imm>
Specifies the immediate offset added to or subtracted from the value of <Rn> to form the
address. Allowed values are multiples of 4 in the range 0-124 for encoding T1, multiples of
4 in the range 0-1020 for encoding T2, any value in the range 0-4095 for encoding T3, and
any value in the range 0-255 for encoding T4. For the offset addressing syntax, <imm> can be
omitted, meaning an offset of 0.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
address = if index then offset_addr else R[n];
data = MemU[address,4];
if wback then R[n] = offset_addr;
if t == 15 then
if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
else
R[t] = data;
Exceptions
UsageFault, MemManage, BusFault.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-89
Thumb Instruction Details
If the offset is negative, imm32 is equal to minus the offset and add == FALSE. Negative offset
is not available in encoding T1.
Note
In code examples in this manual, the syntax =<value> is used for the label of a memory word
whose contents are constant and equal to <value>. The actual syntax for such a label is
assembler-dependent.
The alternative syntax permits the addition or subtraction of the offset and the immediate offset to be
specified separately, including permitting a subtraction of 0 that cannot be specified using the normal
syntax. For more information, see Use of labels in UAL instruction syntax on page A4-5.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
base = Align(PC,4);
address = if add then (base + imm32) else (base - imm32);
data = MemU[address,4];
if t == 15 then
if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
else
R[t] = data;
Exceptions
UsageFault, MemManage, BusFault.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-91
Thumb Instruction Details
Assembler syntax
LDR<c><q>
<Rt>, [<Rn>, <Rm> {, LSL #<shift>}]
where:
<c><q>
See Standard assembler syntax fields on page A6-7.
<Rt>
Specifies the destination register. This register is allowed to be the SP. It is also allowed to
be the PC, provided the instruction is either outside an IT block or the last instruction of an
IT block. If it is the PC, it causes a branch to the address (data) loaded into the PC.
<Rn>
Specifies the register that contains the base value. This register is allowed to be the SP.
<Rm>
Contains the offset that is shifted left and added to the value of <Rn> to form the address.
<shift>
Specifies the number of bits the value from <Rm> is shifted left, in the range 0-3. If this option
is omitted, a shift by 0 is assumed and both encodings are permitted. If this option is
specified, only encoding T2 is permitted.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
offset = Shift(R[m], shift_t, shift_n, APSR.C);
offset_addr = if add then (R[n] + offset) else (R[n] - offset);
address = if index then offset_addr else R[n];
data = MemU[address,4];
if wback then R[n] = offset_addr;
if t == 15 then
if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
else
R[t] = data;
Exceptions
UsageFault, MemManage, BusFault.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-93
Thumb Instruction Details
Assembler syntax
MOV{S}<c><q>
MOVW<c><q>
<Rd>, #<const>
<Rd>, #<const>
All encodings permitted
Only encoding T3 permitted
where:
S
If present, specifies that the instruction updates the flags. Otherwise, the instruction does not
update the flags.
<c><q>
See Standard assembler syntax fields on page A6-7.
<Rd>
Specifies the destination register.
<const>
Specifies the immediate value to be placed in <Rd>. The range of allowed values is 0-255 for
encoding T1 and 0-65535 for encoding T3. See Modified immediate constants in Thumb
instructions on page A5-15 for the range of allowed values for encoding T2.
When both 32-bit encodings are available for an instruction, encoding T2 is preferred to
encoding T3 (if encoding T3 is required, use the MOVW syntax).
The pre-UAL syntax MOV<c>S is equivalent to MOVS<c>.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
result = imm32;
R[d] = result;
if setflags then
APSR.N = result<31>;
APSR.Z = IsZeroBit(result);
APSR.C = carry;
// APSR.V unchanged
Exceptions
None.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-149
Thumb Instruction Details
A6.7.77 MOV (shifted register)
Move (shifted register) is a synonym for ASR, LSL, LSR, ROR, and RRX.
See the following sections for details:
•
ASR (immediate) on page A6-36
•
ASR (register) on page A6-38
•
LSL (immediate) on page A6-134
•
LSL (register) on page A6-136
•
LSR (immediate) on page A6-138
•
LSR (register) on page A6-140
•
ROR (immediate) on page A6-194
•
ROR (register) on page A6-196
•
RRX on page A6-198.
Assembler syntax
Table A6-4 shows the equivalences between MOV (shifted register) and other instructions.
Table A6-4 MOV (shift, register shift) equivalences)
MOV instruction
Canonical form
MOV{S} <Rd>,<Rm>,ASR #<n>
ASR{S} <Rd>,<Rm>,#<n>
MOV{S} <Rd>,<Rm>,LSL #<n>
LSL{S} <Rd>,<Rm>,#<n>
MOV{S} <Rd>,<Rm>,LSR #<n>
LSR{S} <Rd>,<Rm>,#<n>
MOV{S} <Rd>,<Rm>,ROR #<n>
ROR{S} <Rd>,<Rm>,#<n>
MOV{S} <Rd>,<Rm>,ASR <Rs>
ASR{S} <Rd>,<Rm>,<Rs>
MOV{S} <Rd>,<Rm>,LSL <Rs>
LSL{S} <Rd>,<Rm>,<Rs>
MOV{S} <Rd>,<Rm>,LSR <Rs>
LSR{S} <Rd>,<Rm>,<Rs>
MOV{S} <Rd>,<Rm>,ROR <Rs>
ROR{S} <Rd>,<Rm>,<Rs>
MOV{S} <Rd>,<Rm>,RRX
RRX{S} <Rd>,<Rm>
The canonical form of the instruction is produced on disassembly.
Exceptions
None.
A6-152
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
ARM DDI 0403C
Restricted Access
Thumb Instruction Details
A6.7.119 STR (immediate)
Store Register (immediate) calculates an address from a base register value and an immediate offset, and
stores a word from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. See
Memory accesses on page A6-15 for information about memory accesses.
Encoding T1
All versions of the Thumb ISA.
STR<c> <Rt>, [<Rn>{,#<imm5>}]
15 14 13 12 11 10 9 8 7
0 1 1 0 0
t = UInt(Rt);
index = TRUE;
6 5 4 3 2
imm5
Rn
1 0
Rt
n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
add = TRUE; wback = FALSE;
Encoding T2
All versions of the Thumb ISA.
STR<c> <Rt>,[SP,#<imm8>]
15 14 13 12 11 10 9 8 7
1 0 0 1 0
t = UInt(Rt);
index = TRUE;
Encoding T3
6 5 4 3 2
Rt
1 0
imm8
n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
add = TRUE; wback = FALSE;
ARMv7-M
STR<c>.W <Rt>,[<Rn>,#<imm12>]
15 14 13 12 11 10 9 8 7
6 5 4 3 2
1 1 1 1 1 0 0 0 1 1 0 0
1 0 15 14 13 12 11 10 9 8
Rn
Rt
7 6 5 4 3 2
1 0
imm12
if Rn == ’1111’ then UNDEFINED;
t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
index = TRUE; add = TRUE; wback = FALSE;
if t == 15 then UNPREDICTABLE;
Encoding T4
ARMv7-M
STR<c> <Rt>,[<Rn>,#-<imm8>]
STR<c> <Rt>,[<Rn>],#+/-<imm8>
STR<c> <Rt>,[<Rn>,#+/-<imm8>]!
15 14 13 12 11 10 9 8 7
6 5 4 3 2
1 1 1 1 1 0 0 0 0 1 0 0
1 0 15 14 13 12 11 10 9 8
Rn
Rt
1 P U W
7 6 5 4 3 2
1 0
imm8
if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
if t == 15 || (wback && n == t) then UNPREDICTABLE;
A6-222
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
ARM DDI 0403C
Restricted Access
Thumb Instruction Details
Assembler syntax
STR<c><q>
<Rt>, [<Rn> {, #+/-<imm>}]
STR<c><q>
<Rt>, [<Rn>, #+/-<imm>]!
STR<c><q>
<Rt>, [<Rn>], #+/-<imm>
Offset: index==TRUE, wback==FALSE
Pre-indexed: index==TRUE, wback==TRUE
Post-indexed: index==FALSE, wback==TRUE
where:
<c><q>
See Standard assembler syntax fields on page A6-7.
<Rt>
Specifies the source register. This register is allowed to be the SP.
<Rn>
Specifies the base register. This register is allowed to be the SP.
+/-
Is + or omitted to indicate that the immediate offset is added to the base register value
(add == TRUE), or – to indicate that the offset is to be subtracted (add == FALSE). Different
instructions are generated for #0 and #-0.
<imm>
Specifies the immediate offset added to or subtracted from the value of <Rn> to form the
address. Allowed values are multiples of 4 in the range 0-124 for encoding T1, multiples of
4 in the range 0-1020 for encoding T2, any value in the range 0-4095 for encoding T3, and
any value in the range 0-255 for encoding T4. For the offset addressing syntax, <imm> can be
omitted, meaning an offset of 0.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
address = if index then offset_addr else R[n];
MemU[address,4] = R[t];
if wback then R[n] = offset_addr;
Exceptions
UsageFault, MemManage, BusFault.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-223
Thumb Instruction Details
Assembler syntax
STR<c><q>
<Rt>, [<Rn>, <Rm> {, LSL #<shift>}]
where:
<c><q>
See Standard assembler syntax fields on page A6-7.
<Rt>
Specifies the source register. This register is allowed to be the SP.
<Rn>
Specifies the register that contains the base value. This register is allowed to be the SP.
<Rm>
Contains the offset that is shifted left and added to the value of <Rn> to form the address.
<shift>
Specifies the number of bits the value from <Rm> is shifted left, in the range 0-3. If this option
is omitted, a shift by 0 is assumed and both encodings are permitted. If this option is
specified, only encoding T2 is permitted.
Operation
if ConditionPassed() then
EncodingSpecificOperations();
offset = Shift(R[m], shift_t, shift_n, APSR.C);
address = R[n] + offset;
data = R[t];
MemU[address,4] = data;
Exceptions
UsageFault, MemManage, BusFault.
ARM DDI 0403C
Restricted Access
Copyright © 2006-2008 ARM Limited. All rights reserved.
Non-Confidential
A6-225
Printed by Andrew Sterian
test.c
May 18, 11 18:21
/* PC: R15
* LR: R14
* SP: R13
* IP: R12
* FP: R11 */
int s1(void)
{
return 0xFF;
//
mov
//
bx
}
Page 1/2
r0, #255
lr
int s2(void)
{
return 0x101;
//
movw
r0, #257
//
bx
lr
}
int s3(void)
{
return 0x12345;
//
ldr
r0, .L9
//
bx
lr
//
.align 2
//.L9:
//
.word
74565
}
int c1(int i, int j)
{
return i < j;
//
cmp
r0, r1
//
ite
ge
//
movge
r0, #0
//
movlt
r0, #1
//
bx
lr
}
int c2(unsigned
{
return i < j;
//
cmp
//
ite
//
movcs
//
movcc
//
bx
}
int i, unsigned int j)
r0, r1
cs
r0, #0
r0, #1
lr
int a1(int arr[])
{
return arr[5];
//
ldr
r0, [r0, #20]
//
bx
lr
}
int a2(int arr[])
{
Wednesday May 18, 2011
1/2
Printed by Andrew Sterian
May 18, 11 18:21
return arr[5000];
//
add
r0, r0, #19968
//
ldr
r0, [r0, #32]
//
bx
lr
}
test.c
Page 2/2
int a3(int arr[], unsigned char n)
{
return arr[n];
//
ldr
r0, [r0, r1, lsl #2]
//
bx
lr
}
unsigned char a4(unsigned char arr[], int n)
{
return arr[n];
//
ldrb
r0, [r0, r1]
@ zero_extendqisi2
//
bx
lr
}
typedef struct {
int a,b,c;
} t_test;
int getc(t_test *ptr)
{
return ptr−>c;
//
ldr
r0, [r0, #8]
//
bx
lr
}
int getc2(t_test *ptr, int n)
{
return ptr[n].c;
//
movs
r3, #12
//
mla
r3, r3, r1, r0
//
ldr
r0, [r3, #8]
//
bx
lr
}
2/2
Wednesday May 18, 2011