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).
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.