* Question on ARM/Thumb-16 Disassembly
@ 2011-06-20 15:35 Jeffrey Walton
2011-06-20 16:14 ` Matthew Gretton-Dann
0 siblings, 1 reply; 5+ messages in thread
From: Jeffrey Walton @ 2011-06-20 15:35 UTC (permalink / raw)
To: GDB Users
Hi All,
A couple of questions for ARM/Thumb-2. I'm working on a live iPhone,
so I'm using Apple's GAS.
I've got a function generated for Thumb-16 which performs a branch
(immediately after an ADD) based on Carry. For some reason, I'm
getting unexpected results after the ADD - the carry flag is always
high (ie, CY = 1 in CPSR), even when adding 0 + 0, 1 + 1, etc.
Under GDB, I perform a disassembly looking for something I might have
munged (or unexpected code generation and interactions). The first
thing I noticed is some instructions are 4 bytes despite being in
Thumb-16 mode (shown below). For example, the MOV at 0x00002334 is 4
bytes.
(1) Has anyone encountered a situation where a status flag gets
pinned? The ARM Instruction Reference states the status flags are
updated in Thumb mode (except when one or more high registers are
specified as operands).
(2) Are 4 byte instructions expected when GCC generates Thumb-16 code?
The ARM Instruction Reference seems to state otherwise.
Jeff
(gdb) disassemble
Dump of assembler code for function add_u32:
0x00002328 <add_u32+0>: push {r4, r5, r6, r7, lr}
0x0000232a <add_u32+2>: add r7, sp, #12
0x0000232c <add_u32+4>: sub sp, #20
0x0000232e <add_u32+6>: str r0, [sp, #8]
0x00002330 <add_u32+8>: str r1, [sp, #4]
0x00002332 <add_u32+10>: str r2, [sp, #0]
0x00002334 <add_u32+12>: mov.w r3, #1 ; 0x1
0x00002338 <add_u32+16>: str r3, [sp, #16]
0x0000233a <add_u32+18>: mov.w r3, #0 ; 0x0
0x0000233e <add_u32+22>: str r3, [sp, #12]
0x00002340 <add_u32+24>: ldr r4, [sp, #8]
0x00002342 <add_u32+26>: ldr r5, [sp, #4]
0x00002344 <add_u32+28>: add r5, r4
0x00002346 <add_u32+30>: bcc.n 0x234e <add_u32+38>
0x00002348 <add_u32+32>: mov.w r6, #0 ; 0x0
0x0000234c <add_u32+36>: str r6, [sp, #16]
0x0000234e <add_u32+38>: str r5, [sp, #12]
0x00002350 <add_u32+40>: ldr r3, [sp, #0]
0x00002352 <add_u32+42>: cmp r3, #0
0x00002354 <add_u32+44>: beq.n 0x235c <add_u32+52>
0x00002356 <add_u32+46>: ldr r2, [sp, #12]
0x00002358 <add_u32+48>: ldr r3, [sp, #0]
0x0000235a <add_u32+50>: str r2, [r3, #0]
0x0000235c <add_u32+52>: ldr r3, [sp, #16]
0x0000235e <add_u32+54>: mov r0, r3
0x00002360 <add_u32+56>: sub.w sp, r7, #12 ; 0xc
0x00002364 <add_u32+60>: pop {r4, r5, r6, r7, pc}
End of assembler dump.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Question on ARM/Thumb-16 Disassembly
2011-06-20 15:35 Question on ARM/Thumb-16 Disassembly Jeffrey Walton
@ 2011-06-20 16:14 ` Matthew Gretton-Dann
2011-06-21 3:05 ` Jeffrey Walton
0 siblings, 1 reply; 5+ messages in thread
From: Matthew Gretton-Dann @ 2011-06-20 16:14 UTC (permalink / raw)
To: noloader; +Cc: GDB Users
Jeffrey,
On 20/06/11 16:35, Jeffrey Walton wrote:
> Hi All,
>
> A couple of questions for ARM/Thumb-2. I'm working on a live iPhone,
> so I'm using Apple's GAS.
It would be useful if you could give the command line you are using - as
I can't give precise answers without that info. Most of the comments I
make below are based upon the behaviour of the vanilla FSF tools, Apple
may have changed their behaviours in ways I am unaware of.
> I've got a function generated for Thumb-16 which performs a branch
> (immediately after an ADD) based on Carry. For some reason, I'm
> getting unexpected results after the ADD - the carry flag is always
> high (ie, CY = 1 in CPSR), even when adding 0 + 0, 1 + 1, etc.
>
> Under GDB, I perform a disassembly looking for something I might have
> munged (or unexpected code generation and interactions). The first
> thing I noticed is some instructions are 4 bytes despite being in
> Thumb-16 mode (shown below). For example, the MOV at 0x00002334 is 4
> bytes.
>
> (1) Has anyone encountered a situation where a status flag gets
> pinned? The ARM Instruction Reference states the status flags are
> updated in Thumb mode (except when one or more high registers are
> specified as operands).
There are two types of assembly language syntax in GAS for ARM:
1. 'divided' syntax - where add instruction has different semantics
depending on whether you are in Thumb or ARM state.
2. 'unified' syntax - where the add instruction has the same semantics
in ARM and Thumb state.
(Look for a .syntax directive in your assembly source).
My guess is that you have written something like the following in your
assembly code:
add r0, r1, r2
Which would set the flags in Thumb-1 code when using divided syntax but
does not when using unified syntax.
So the fix is to do the following instead:
adds r0, r1, r2
[The additional 's' means set the flags].
> (2) Are 4 byte instructions expected when GCC generates Thumb-16 code?
> The ARM Instruction Reference seems to state otherwise.
GCC will generate code using all the features available in the
instruction set for the CPU/architecture it is compiling for. Therefore
if you are compiling for Cortex-A8 (say) and specify -mthumb on the
command line it will use both 16-bit and 32-bit Thumb instructions (as
they will be available). There is no way to tell GCC to compile for a
CPU supporting Thumb-2 but restrict itself to just Thumb-1 instructions.
I hope this helps.
Thanks,
Matt
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Question on ARM/Thumb-16 Disassembly
2011-06-20 16:14 ` Matthew Gretton-Dann
@ 2011-06-21 3:05 ` Jeffrey Walton
2011-06-21 4:53 ` Jeffrey Walton
0 siblings, 1 reply; 5+ messages in thread
From: Jeffrey Walton @ 2011-06-21 3:05 UTC (permalink / raw)
To: Matthew Gretton-Dann; +Cc: GDB Users
On Mon, Jun 20, 2011 at 12:14 PM, Matthew Gretton-Dann
<matthew.gretton-dann@arm.com> wrote:
> On 20/06/11 16:35, Jeffrey Walton wrote:
>> A couple of questions for ARM/Thumb-2. I'm working on a live iPhone,
>> so I'm using Apple's GAS.
My bad: Thumb-16.
> It would be useful if you could give the command line you are using - as I
> can't give precise answers without that info. Most of the comments I make
> below are based upon the behaviour of the vanilla FSF tools, Apple may have
> changed their behaviors in ways I am unaware of.
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -x c
-arch armv6 -fmessage-length=0 -pipe -std=c99 -Wno-trigraphs
-fpascal-strings -O0 -Wreturn-type -Wunused-variable -isysroot
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk
-fvisibility=hidden -gdwarf-2 -mthumb -miphoneos-version-min=3.2
-iquote /Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/iDevice-generated-files.hmap
-I/Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/iDevice-own-target-headers.hmap
-I/Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/iDevice-all-target-headers.hmap
-iquote /Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/iDevice-project-headers.hmap
-F/Users/jeffrey/Desktop/intoverflow/build/Debug-iphoneos
-I/Users/jeffrey/Desktop/intoverflow/build/Debug-iphoneos/include
-I/Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/DerivedSources/armv6
-I/Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/DerivedSources
-include /var/folders/dC/dCfs8ij4HeWN-ZqbDcAWyU+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/iDevice-Prefix-fqqgplseposzlsgjezeqayjmdnny/iDevice-Prefix.pch
-c /Users/jeffrey/Desktop/intoverflow/intoverflow-add.c -o
/Users/jeffrey/Desktop/intoverflow/build/iDevice.build/Debug-iphoneos/iDevice.build/Objects-normal/armv6/intoverflow-add.o
For completeness:
$ /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/as -v
Apple Inc version cctools-797~183, GNU assembler version 1.38
And in Xcode 3.2.6, "Compile for thumb" is checked (its the default
setting). Note that vanilla ARM (ie, unchecking) works/assembles fine.
Also, ARM6 is selected.
>> I've got a function generated for Thumb-16 which performs a branch
>> (immediately after an ADD) based on Carry. For some reason, I'm
>> getting unexpected results after the ADD - the carry flag is always
>> high (ie, CY = 1 in CPSR), even when adding 0 + 0, 1 + 1, etc.
>>
>> Under GDB, I perform a disassembly looking for something I might have
>> munged (or unexpected code generation and interactions). The first
>> thing I noticed is some instructions are 4 bytes despite being in
>> Thumb-16 mode (shown below). For example, the MOV at 0x00002334 is 4
>> bytes.
>>
>> (1) Has anyone encountered a situation where a status flag gets
>> pinned? The ARM Instruction Reference states the status flags are
>> updated in Thumb mode (except when one or more high registers are
>> specified as operands).
>
> There are two types of assembly language syntax in GAS for ARM:
>
> 1. 'divided' syntax - where add instruction has different semantics
> depending on whether you are in Thumb or ARM state.
> 2. 'unified' syntax - where the add instruction has the same semantics in
> ARM and Thumb state.
Not sure about this - its inline assembly.
> (Look for a .syntax directive in your assembly source).
>
> My guess is that you have written something like the following in your
> assembly code:
> add r0, r1, r2
Yes.
> Which would set the flags in Thumb-1 code when using divided syntax but does
> not when using unified syntax.
>
> So the fix is to do the following instead:
> adds r0, r1, r2
>
> [The additional 's' means set the flags].
OK - got that. Neither of the following will assemble, so I moved to
the non-condition updating ADD.
"adds r6, r5, r4 ;" // R6 = R5 + R4, sets carry
"adds r5, r4 ;" // R5 += R4, sets carry
Both result in:
{standard input}:262:instruction not supported in Thumb16 mode --
`adds r6,r5,r4'
For S&G, I also tried the following to try and generate the 32 bit
(wide) instructions:
"adds.w r6, r5, r4 ;" // R6 = R5 + R4, sets carry
"adds.w r5, r4 ;" // R5 += R4, sets carry
>> (2) Are 4 byte instructions expected when GCC generates Thumb-16 code?
>> The ARM Instruction Reference seems to state otherwise.
>
> GCC will generate code using all the features available in the instruction
> set for the CPU/architecture it is compiling for. Therefore if you are
> compiling for Cortex-A8 (say) and specify -mthumb on the command line it
> will use both 16-bit and 32-bit Thumb instructions (as they will be
> available). There is no way to tell GCC to compile for a CPU supporting
> Thumb-2 but restrict itself to just Thumb-1 instructions.
According to the ARM reference, when operating in Thumb mode, the
condition flags are set. I'm reading that ADD wil set the condition
flag, with no need for ADDS and friends. See 'ARM® Developer Suite,
v1.2', Section 2.2.8, page 2-9:
The conditional branch instruction is the only Thumb
instruction that can be executed conditionally on the
value of the ALU status flags in the CPSR. All data
processing instructions update these flags, except
when one or more high registers are specified as
operands to the MOV or ADD instructions. In these
cases the flags cannot be updated.
Thanks for the help Matt. I'm missing something, but its not jumping out at me.
Jeff
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Question on ARM/Thumb-16 Disassembly
2011-06-21 3:05 ` Jeffrey Walton
@ 2011-06-21 4:53 ` Jeffrey Walton
2011-06-21 5:01 ` Jeffrey Walton
0 siblings, 1 reply; 5+ messages in thread
From: Jeffrey Walton @ 2011-06-21 4:53 UTC (permalink / raw)
To: Matthew Gretton-Dann; +Cc: GDB Users
On Mon, Jun 20, 2011 at 11:04 PM, Jeffrey Walton <noloader@gmail.com> wrote:
> On Mon, Jun 20, 2011 at 12:14 PM, Matthew Gretton-Dann
> <matthew.gretton-dann@arm.com> wrote:
>> On 20/06/11 16:35, Jeffrey Walton wrote:
>>> A couple of questions for ARM/Thumb-2. I'm working on a live iPhone,
>>> so I'm using Apple's GAS.
> My bad: Thumb-16.
>
>> It would be useful if you could give the command line you are using - as I
>> can't give precise answers without that info. Most of the comments I make
>> below are based upon the behaviour of the vanilla FSF tools, Apple may have
>> changed their behaviors in ways I am unaware of.
>
> [SNIP]
>
>>
>> There are two types of assembly language syntax in GAS for ARM:
>>
>> 1. 'divided' syntax - where add instruction has different semantics
>> depending on whether you are in Thumb or ARM state.
>> 2. 'unified' syntax - where the add instruction has the same semantics in
>> ARM and Thumb state.
> Not sure about this - its inline assembly.
>
>> (Look for a .syntax directive in your assembly source).
>>
>> My guess is that you have written something like the following in your
>> assembly code:
>> add r0, r1, r2
> Yes.
>
>> Which would set the flags in Thumb-1 code when using divided syntax but does
>> not when using unified syntax.
>>
>> So the fix is to do the following instead:
>> adds r0, r1, r2
>>
>> [The additional 's' means set the flags].
> OK - got that. Neither of the following will assemble, so I moved to
> the non-condition updating ADD.
>
> "adds r6, r5, r4 ;" // R6 = R5 + R4, sets carry
> "adds r5, r4 ;" // R5 += R4, sets carry
>
> Both result in:
> {standard input}:262:instruction not supported in Thumb16 mode --
> `adds r6,r5,r4'
>
> For S&G, I also tried the following to try and generate the 32 bit
> (wide) instructions:
>
> "adds.w r6, r5, r4 ;" // R6 = R5 + R4, sets carry
> "adds.w r5, r4 ;" // R5 += R4, sets carry
>
I came across an ARM sample with the directive "CODE32", which got me
looking for a similar Apple AS directive. I never found the Apple
directives (and as(1) is useless), but I did find Red Hat's at
http://sources.redhat.com/binutils/docs-2.12/as.info/ARM-Directives.html#ARM%20Directives.
So I added a ".code 32" and got the ADDS to assemble:
__asm__ volatile
(
"ldr r4, %[xa] ;" // R4 = a
"ldr r5, %[xb] ;" // R5 = b
".code 32 ;" // same as ".arm"
"adds r6, r4, r5 ;" // R6 = R4 + R5, set status
".code 16 ;" // same as ".thumb"
"bcc 1f ;" // jump if carry is clear
"mov r5, #0 ;" // set overflow
"str r5, %[xc] ;" // write it to memory
"1: ;" // jump target
"str r6, %[xr] ;" // result = R6
: [xr] "=m" (result), [xc] "=m" (no_carry)
: [xa] "m" (a), [xb] "m" (b)
: "r4", "r5", "r6"
);
Unfortunately, EXC_BAD_ACCESS. When I disassemble, 'bcc 1f" is changed
to a "str r5, [r0, #0]" and then a branch into the damn Application
delegate. I've also tried applying ".code 32" to the entire function
(which makes matters worse).
I know I'm missing something (that much is obvious), but I have no
clue what it might be since I've verified the instructions and their
usage against the ARM manual.
Jeff
(gdb) disass
Dump of assembler code for function add_u32:
0x0000232c <add_u32+0>: push {r4, r5, r6, r7, lr}
0x0000232e <add_u32+2>: add r7, sp, #12
0x00002330 <add_u32+4>: sub sp, #20
0x00002332 <add_u32+6>: str r0, [sp, #8]
0x00002334 <add_u32+8>: str r1, [sp, #4]
0x00002336 <add_u32+10>: str r2, [sp, #0]
0x00002338 <add_u32+12>: mov.w r3, #1 ; 0x1
0x0000233c <add_u32+16>: str r3, [sp, #16]
0x0000233e <add_u32+18>: ldr r4, [sp, #8]
0x00002340 <add_u32+20>: ldr r5, [sp, #4]
0x00002342 <add_u32+22>: str r5, [r0, #0]
0x00002344 <add_u32+24>: b.n 0x2470 <-[iDeviceAppDelegate
applicationWillResignActive:]+8>
0x00002346 <add_u32+26>: bcc.n 0x234e <add_u32+34>
0x00002348 <add_u32+28>: mov.w r5, #0 ; 0x0
0x0000234c <add_u32+32>: str r5, [sp, #16]
0x0000234e <add_u32+34>: str r6, [sp, #12]
0x00002350 <add_u32+36>: ldr r3, [sp, #0]
0x00002352 <add_u32+38>: cmp r3, #0
0x00002354 <add_u32+40>: beq.n 0x235c <add_u32+48>
0x00002356 <add_u32+42>: ldr r2, [sp, #12]
0x00002358 <add_u32+44>: ldr r3, [sp, #0]
0x0000235a <add_u32+46>: str r2, [r3, #0]
0x0000235c <add_u32+48>: ldr r3, [sp, #16]
0x0000235e <add_u32+50>: mov r0, r3
0x00002360 <add_u32+52>: sub.w sp, r7, #12 ; 0xc
0x00002364 <add_u32+56>: pop {r4, r5, r6, r7, pc}
End of assembler dump.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Question on ARM/Thumb-16 Disassembly
2011-06-21 4:53 ` Jeffrey Walton
@ 2011-06-21 5:01 ` Jeffrey Walton
0 siblings, 0 replies; 5+ messages in thread
From: Jeffrey Walton @ 2011-06-21 5:01 UTC (permalink / raw)
To: Matthew Gretton-Dann; +Cc: GDB Users
On Tue, Jun 21, 2011 at 12:53 AM, Jeffrey Walton <noloader@gmail.com> wrote:
> On Mon, Jun 20, 2011 at 11:04 PM, Jeffrey Walton <noloader@gmail.com> wrote:
>> On Mon, Jun 20, 2011 at 12:14 PM, Matthew Gretton-Dann
>> <matthew.gretton-dann@arm.com> wrote:
>>> On 20/06/11 16:35, Jeffrey Walton wrote:
>>>> A couple of questions for ARM/Thumb-2. I'm working on a live iPhone,
>>>> so I'm using Apple's GAS.
>>
>> [SNIP]
>>
>>> [SNIP]
My bad - this thread went from "why are there 4 byte instructions in a
Thumb-16 disassembly" to "how do I compile/assemble ADDS or ADD (with
conditionals) under AS". I'll move it over to GCC users.
Jeff
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-06-21 5:01 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-20 15:35 Question on ARM/Thumb-16 Disassembly Jeffrey Walton
2011-06-20 16:14 ` Matthew Gretton-Dann
2011-06-21 3:05 ` Jeffrey Walton
2011-06-21 4:53 ` Jeffrey Walton
2011-06-21 5:01 ` Jeffrey Walton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox