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