hello:
one small question regarding use of ARM inline assembly code in a
C file that has been compiled for Thumb mode.
is it possible to use ARM inline assembly code from within a C file
that has been compiled for Thumb mode and Thumb interworking?
how this is done is described on this page:
http://www.devrs.com/gba/files/asmc.txt
i have a C file that has been compiled for Thumb mode. in it, i am
using ARM inline assembly code. apparently, GCC issues no error
message but forcibly converts the ARM code into Thumb code.
i think that GCC requires an entire file to be in either Thumb mode
or ARM mode, but i am not sure. is that true?
the C code that is compiled into Thumb is:
void function_f( void )
{
asm volatile
(
".align \n\t"
".arm \n\t"
"mrs r0, cpsr \n\t"
"msr cpsr_c, r0 \n\t"
"pop { r0 }"
);
}
the C code is compiled with:
arm-elf-gcc -mlittle-endian -mcpu=arm7tdmi -march=armv4t \
-mthumb-interwork -mthumb -mno-tpcs-frame .....
in the inline assembly code, if i do not use ".arm", i get compiler
errors.
is it possible to use ARM assembly code from within a C file that
has been compiled for Thumb and Thumb interworking?
Aaron
=============================== SOURCE CODE
================================
Makefile
--------
CC = arm-elf-gcc
TARGET_ARCH = -mlittle-endian -mcpu=arm7tdmi -march=armv4t
-mthumb-interwork
TARGET_ARCH += -mthumb -mno-tpcs-frame
all: test
arm-elf-objdump -S -D test > test.lst
clean:
rm -f test test.o function.o
test.c
------
void function_f( void )
{
asm volatile
(
".align \n\t"
".arm \n\t"
"mrs r0, cpsr \n\t"
"msr cpsr_c, r0 \n\t"
"pop { r0 }"
);
}
int main( void )
{
function_f();
return 0;
}
hello folks:
in the last post, i forgot to show the generated code.
here it is. as you can see, ".arm" in inline assembly
generates "0000" in the output.
00008194 <function_f>:
8194: b580 push {r7, lr}
8196: af02 add r7, sp, #8
8198: 0000 lsls r0, r0, #0
819a: e10f b.n 83bc <wrap+0x10>
819c: f000 e121 blx 4083e0 <_stack+0x3883e0>
81a0: 0001 lsls r1, r0, #0
81a2: e8bd 46bd ldmia.w sp!, {r0, r2, r3, r4, r5, r7, r9, sl,
lr}
81a6: b082 sub sp, #8
81a8: bc80 pop {r7}
81aa: bc01 pop {r0}
81ac: 4700 bx r0
Aaron D'souza wrote:
> hello:>> one small question regarding use of ARM inline assembly code in a> C file that has been compiled for Thumb mode.> ...
Hello, I posted an answer on usenet already.
Anyway you just need to put a ".code 16" after the arm code in order to
return to thumb mode or the assembler will get confused.
regards,
Giovanni
---
ChibiOS/RT http://chibios.sourceforge.net
hello Giovanni:
Giovanni Di Sirio wrote:
> Hello, I posted an answer on usenet already.
i saw your quick reply. thank you very much.
> Anyway you just need to put a ".code 16" after the arm code in order to> return to thumb mode or the assembler will get confused.
that's the trick that i did not know about. how do i know that the
assembler is going to get confused?
anyway, as i said on Usenet, i have also received a reply from Nick
Clifton, which i will now post. i will also post the complete working
solution that i use.
Aaron
hello ffolks:
here is a reply from Nick Clifton, which is really illuminating. pls
read it carefully. i will also post the complete working solution, if i
can get permission from my boss.
-------- Original Message --------
Subject : Re: RESEND : QUERY : ARM inline code in Thumb file?
Date : Wed 27 Aug 2008 10:37:23 +0100
From : Nick Clifton @ RedHat
To : Aaron P. D'Souza
Hi Aaron,
> is it possible to use ARM assembly code from within a C file that> has been compiled for Thumb and Thumb interworking?
Yes.
> i have a C file that has been compiled for Thumb mode. in it, i am> using ARM inline assembly code. apparently, GCC issues no error> message but forcibly converts the ARM code into Thumb code.
Highly unlikely. What is more likely is that you need to be careful
about how you insert the ARM code.
> the C code that is compiled into Thumb is:>> void function_f( void )> {> asm volatile> (> ".align \n\t"> ".arm \n\t"> "mrs r0, cpsr \n\t"> "msr cpsr_c, r0 \n\t"> "pop { r0 }"> );> }
There are two problems with the above code:
1. You do not switch back to thumb mode at the end of the ARM code
fragment. Gcc passes the contents of the asm() directory on to the
assembler - it does not try to parse it and discover that you are
sneakily switching into ARM mode...
2. You have the .arm directive without a nearby label to hang it on.
The .arm (and .thumb) directives need a label because the changes
between instruction sets is encoded into attributes of the labels, thus
allowing the linker and disassembler to know when instruction sets have
changed.
ie. please try this:
void function_f( void )
{
asm volatile
(
".align \n"
"__f_into_arm:\n\t"
".arm \n\t"
"mrs r0, cpsr \n\t"
"msr cpsr_c, r0 \n\t"
"pop { r0 } \n"
"__f_from_arm:\n\t"
".thumb"
);
}
Cheers
Nick
hello:
Nick Clifton wrote:
>> void function_f( void )>> {>> asm volatile>> (>> ".align \n\t">> ".arm \n\t">> "mrs r0, cpsr \n\t">> "msr cpsr_c, r0 \n\t">> "pop { r0 }">> );>> }>> There are two problems with the above code:>> 1. You do not switch back to thumb mode at the end of the ARM code> fragment. Gcc passes the contents of the asm() directory on to the> assembler - it does not try to parse it and discover that you are> sneakily switching into ARM mode...>> 2. You have the .arm directive without a nearby label to hang it on.> The .arm (and .thumb) directives need a label because the changes> between instruction sets is encoded into attributes of the labels, thus> allowing the linker and disassembler to know when instruction sets have> changed.>> ie. please try this:>> void function_f( void )> {> asm volatile> (> ".align \n"> "__f_into_arm:\n\t"> ".arm \n\t"> "mrs r0, cpsr \n\t"> "msr cpsr_c, r0 \n\t"> "pop { r0 } \n"> "__f_from_arm:\n\t"> ".thumb"> );> }
actually that does not work also. look at the translated code:
00008194 <function_f>:
8194: b580 push {r7, lr}
8196: af02 add r7, sp, #8
00008198 <__f_into_arm>:
8198: 0000 lsls r0, r0, #0
819a: e10f b.n 83bc <wrap+0x10>
819c: f000 e121 blx 4083e0 <_stack+0x3883e0>
81a0: 0001 lsls r1, r0, #0
81a2: e8bd 46bd ldmia.w sp!, {r0, r2, r3, r4, r5, r7, r9, sl,
lr}
000081a4 <__f_from_arm>:
81a4: b08246bd strlth r4, [r2], sp
81a8: bc01bc80 stclt 12, cr11, [r1], {128}
81ac: 00004700 andeq r4, r0, r0, lsl #14
Aaron D'souza wrote:
> hello Giovanni:>> Giovanni Di Sirio wrote:>> Hello, I posted an answer on usenet already.>> i saw your quick reply. thank you very much.>>> Anyway you just need to put a ".code 16" after the arm code in order to>> return to thumb mode or the assembler will get confused.>> that's the trick that i did not know about. how do i know that the> assembler is going to get confused?>> anyway, as i said on Usenet, i have also received a reply from Nick> Clifton, which i will now post. i will also post the complete working> solution that i use.>> Aaron
Please look at my last reply, that example includes the switch to arm
mode and back to thumb mode.
This is the code I posted there:
void function_f( void )
{
asm volatile
(
".balign 4 \n\t"
"mov r0, pc \n\t"
"bx r0 \n\t"
".code 32 \n\t"
"mrs r0, cpsr \n\t"
"msr cpsr_c, r0 \n\t"
"add r0, pc, #1 \n\t"
"bx r0 \n\t"
".code 16 \n\t"
);
}
which generates:
function_f:
.balign 4
mov r0, pc // jumps into ARM mode
bx r0
.code 32
mrs r0, cpsr // ARM code starting here
msr cpsr_c, r0
add r0, pc, #1 // returns to thumb code
bx r0
.code 16
bx lr // thumb code continues here
regards,
Giovanni
---
ChibiOS/RT http://chibios.sourceforge.net
hello Giovanni:
thank you for being so helpful. i am truly indebted to you.
i tried your code and that also did not work. are you sure you are
compiling the C file into Thumb mode? pls find attached the C file
and the Makefile. pls try those.
also, the version of GNUARM that i am using is 4.1.1.
$ arm-elf-gcc --version
arm-elf-gcc (GCC) 4.1.1
Giovanni Di Sirio wrote:
> Please look at my last reply, that example includes the switch to arm> mode and back to thumb mode.>> This is the code I posted there:>> void function_f( void )> {> asm volatile> (> ".balign 4 \n\t"> "mov r0, pc \n\t"> "bx r0 \n\t"> ".code 32 \n\t"> "mrs r0, cpsr \n\t"> "msr cpsr_c, r0 \n\t"> "add r0, pc, #1 \n\t"> "bx r0 \n\t"> ".code 16 \n\t"> );> }>> which generates:>> function_f:> .balign 4> mov r0, pc // jumps into ARM mode> bx r0> .code 32> mrs r0, cpsr // ARM code starting here> msr cpsr_c, r0> add r0, pc, #1 // returns to thumb code> bx r0> .code 16> bx lr // thumb code continues here
i am looking at the code in the executable .ELF file, which i
disassembled
using arm-elf-objdump. pls take a look at the Makefile attached.
with your code, this is what is disassembled from the .ELF file.
00008194 <function_f>:
8194: b580 push {r7, lr}
8196: af02 add r7, sp, #8
8198: 4678 mov r0, pc
819a: 4700 bx r0
819c: 0000 lsls r0, r0, #0
819e: e10f b.n 83c0 <wrap+0xc>
81a0: f000 e121 blx 4083e4 <_stack+0x3883e4>
81a4: 0001 lsls r1, r0, #0
81a6: e28f b.n 86c8 <_stat+0x1c>
81a8: ff10 e12f undefined
81ac: 46bd mov sp, r7
81ae: b082 sub sp, #8
81b0: bc80 pop {r7}
81b2: bc01 pop {r0}
81b4: 4700 bx r0
> 00008194 <function_f>:> 8194: b580 push {r7, lr}> 8196: af02 add r7, sp, #8> 8198: 4678 mov r0, pc> 819a: 4700 bx r0> 819c: 0000 lsls r0, r0, #0> 819e: e10f b.n 83c0 <wrap+0xc>> 81a0: f000 e121 blx 4083e4 <_stack+0x3883e4>> 81a4: 0001 lsls r1, r0, #0> 81a6: e28f b.n 86c8 <_stat+0x1c>> 81a8: ff10 e12f undefined> 81ac: 46bd mov sp, r7> 81ae: b082 sub sp, #8> 81b0: bc80 pop {r7}> 81b2: bc01 pop {r0}> 81b4: 4700 bx r0
Ok, I understood the problem now. The disassembler is not able to
understand when to disassemble in arm mode and when disassemble in thumb
mode, it always disassemble in thumb mode so when it disassemble the arm
code the resulting text is garbage.
I suggest that you look at the listing files generated by the assembler,
there you can see both the correct mnemonics and the binary code.
The listing of the above code is:
18 function_f:
19 .LFB9:
20 .file 1 "board.c"
21 .loc 1 32 0
22 @ lr needed for prologue
23 .loc 1 33 0
24 .balign 4
25 0000 7846 mov r0, pc
26 0002 0047 bx r0
27 .code 32
28 0004 00000FE1 mrs r0, cpsr
29 0008 00F021E1 msr cpsr_c, r0
30 000c 01008FE2 add r0, pc, #1
31 0010 10FF2FE1 bx r0
32 .code 16
33
34 .loc 1 45 0
35 .code 16
36 @ sp needed for prologue
37 0014 7047 bx lr
Note, it is compiled using -O2 so it is a bit different (no prologue and
epilogue code).