| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
|
| 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 assembly code from within a C file that has been compiled for Thumb 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 ..... here is the generated code: 00008194 8194: b580 push {r7, lr} 8196: af02 add r7, sp, #8 8198: 0000 lsls r0, r0, #0 819a: e10f b.n 83bc 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 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 Makefile -------- CC = arm-elf-gcc TARGET_ARCH = -mlittle-endian -mcpu=arm7tdmi -march=armv4t TARGET_ARCH += -mthumb -mno-tpcs-frame -mthumb-interwork all: test arm-elf-objdump -S -D test > test.lst clean: rm -f test test.o function.o C CODE ------ 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; } |
|
#2
|
| >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 assembly code from within a C file that >has been compiled for Thumb 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 ..... > >here is the generated code: >00008194 > 8194: b580 push {r7, lr} > 8196: af02 add r7, sp, #8 > 8198: 0000 lsls r0, r0, #0 > 819a: e10f b.n 83bc > 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 > > >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 > >Makefile >-------- > >CC = arm-elf-gcc >TARGET_ARCH = -mlittle-endian -mcpu=arm7tdmi -march=armv4t >TARGET_ARCH += -mthumb -mno-tpcs-frame -mthumb-interwork > >all: test > arm-elf-objdump -S -D test > test.lst > >clean: > rm -f test test.o function.o > > >C CODE >------ > >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; >} Try this: void function_f( void ) { asm volatile ( ".code 32 \n\t" "mrs r0, cpsr \n\t" "msr cpsr_c, r0 \n\t" ".code 16 \n\t" "pop { r0 }" ); } It generates: function_f: .code 32 mrs r0, cpsr msr cpsr_c, r0 .code 16 pop { r0 } bx lr You need to return to thumb mode after inserting the arm code or the assembles will get confused. BTW, that "pop r0" will crash the program. regards, Giovanni Di Sirio --- ChibiOS/RT http://chibios.sourceforge.net |
|
#3
|
| Op Wed, 27 Aug 2008 11:44:59 +0200 schreef Wilco Dijkstra > "gdisirio" > news:hKidnZFpiODXnCjVnZ2dnUVZ_uadnZ2d-at-giganews.com ... > A. Switch to ARM mode for the whole function - many compilers can switch > between ARM and Thumb on a per function basis. I don't know whether > GCC supports this yet. No attribute or pragma exists for this in the documentation. -- Gemaakt met Opera's revolutionaire e-mailprogramma: http://www.opera.com/mail/ |
|
#4
|
| > ... > The above example was only meant to make it compile correctly, I didn't remove that "pop {r0}" either. If you want to switch to arm mode and back to thumb mode then more instructions are required: 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 This one should be complete. regards, Giovanni --- ChibiOS/RT http://chibios.sourceforge.net |
|
#5
|
| >Op Wed, 27 Aug 2008 11:44:59 +0200 schreef Wilco Dijkstra > >> "gdisirio" >> news:hKidnZFpiODXnCjVnZ2dnUVZ_uadnZ2d-at-giganews.com ... >> A. Switch to ARM mode for the whole function - many compilers can switch >> between ARM and Thumb on a per function basis. I don't know whether >> GCC supports this yet. > >No attribute or pragma exists for this in the documentation. > > > > >-- >Gemaakt met Opera's revolutionaire e-mailprogramma: >http://www.opera.com/mail/ Yes, it is a big limit in the current implementation, they should really add new function attributes for that. That would make writing mixed code less painful. --- ChibiOS/RT http://chibios.sourceforge.net |
|
#6
|
| hello: a few apologies. in this example, i was focussing on the ".arm" directive and thought that the assembler was not recognizing it. that's why the code is not semantically correct. the extra r0 is an error here. i should have written that i have not included the code to move from ARM to Thumb mode and vice versa. that will require a bx r0, which i was planning to use. before using r0, i was planning to save r0 on the stack. that's why there is a pop r0. i have also received a reply from Nick Clifton and will post his reply also. i will also post my complete code that works, and i could not find it anywhere on the Internet. i wanted to simply add ARM mode inline assembly code into a Thumb mode C file for enabling/disabling interrupts without needing to call a function. Aaron |
|
#7
|
| 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 |
|
#8
|
| Nick Clifton said: > 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" > ); >} i tried the above code but it still did not work! here is the code generated. 00008194 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 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 |
|
#9
|
| Nick Clifton said: > 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" > ); >} i tried the above code but it still did not work! here is the code generated. 00008194 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 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 |
|
#10
|
| hello: i should have added a few important points: - i tried Nick Clifton's solution and it did not work - i tried Giovanni's solution and it did not work - the entire C code is compiled to Thumb mode - function function_f() is compiled to Thumb mode - GNUARM gcc4.1.1 is being used - the code is being checked in disassembled code generated from the final .ELF executable file, disassembly being done using arm-elf-objdump. i hope that this information is helpful. Aaron |
![]() |
| Thread Tools | |
| Display Modes | |