Hi, Is there anyway to control how ARM GCC to emit assembly for the prologue/epilogue? I am using Atmel SAM4LS2A and it seems like the push instruction does not work with the chip (The chip does not save correctly the registers onto the stack). Instead of emitting the push instruction at the prologue, I am wondering if I can control the GCC to emit STMDB instruction which is working (I tested). Thanks
The Cortex-M4F (ARMv7M) does not have an explicit PUSH instruction, but only "STM". Verify that you call the compiler correctly for that core (flags -mcpu=cortex=M4 -mthumb). Paste the disassembly, step through the instructions with a debugger and explain why you believe that the registers are not saved.
Hi, Thanks for the reply. I do use "flags -mcpu=cortex=M4 -mthumb" and the compiler does generate the push instruction: Please see below: arm-none-eabi-gcc.exe" -mthumb -D__SAM4LS2A__ -DARM_MATH_CM4=true -DBOARD=USER_BOARD -Dprintf=iprintf -D__ATSAM4LS2A__ -I"../src" -I"../src/ASF/common/boards" -I"../src/ASF/common/boards/user_board" -I"../src/ASF/common/utils" -I"../src/ASF/sam/utils" -I"../src/ASF/sam/utils/cmsis/sam4l/include" -I"../src/ASF/sam/utils/cmsis/sam4l/source/templates" -I"../src/ASF/sam/utils/header_files" -I"../src/ASF/sam/utils/preprocessor" -I"../src/ASF/thirdparty/CMSIS/Include" -I"../src/ASF/thirdparty/CMSIS/Lib/GCC" -I"../src/config" -I"C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM GCC\Native\4.7.3.1029\arm-gnu-toolchain\bin\..\..\CMSIS_Atmel" -I"C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM GCC\Native\4.7.3.1029\arm-gnu-toolchain\bin\..\..\CMSIS_Atmel\CMSIS\Incl ude" -I"C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM GCC\Native\4.7.3.1029\arm-gnu-toolchain\bin\..\..\CMSIS_Atmel\Device\ATM EL" -I"C:\Program Files (x86)\Atmel\Atmel Toolchain\ARM GCC\Native\4.7.3.1029\arm-gnu-toolchain\bin\..\..\CMSIS_Atmel\Device\ATM EL\sam4l\include" -I"../src/ASF/sam/drivers/bpm" -I"../src/ASF/sam/drivers/flashcalw" -I"../src/ASF/sam/drivers/gpio" -I"../src/ASF/common/services/clock" -I"../src/ASF/common/services/ioport" -O1 -fdata-sections -ffunction-sections -mlong-calls -g3 -Wall -mcpu=cortex-m4 -c -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 -ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef -Wshadow -Wbad-function-cast -Wwrite-strings -Wsign-compare -Waggregate-return -Wmissing-declarations -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs -Wlong-long -Wunreachable-code -Wcast-align --param max-inline-insns-single=500 -D__ATSAM4LS2A__ -MD -MP -MF "src/ASF/common/utils/interrupt/interrupt_sam_nvic.d" -MT"src/ASF/common/utils/interrupt/interrupt_sam_nvic.d" -MT"src/ASF/common/utils/interrupt/interrupt_sam_nvic.o" -o "src/ASF/common/utils/interrupt/interrupt_sam_nvic.o" "../src/ASF/common/utils/interrupt/interrupt_sam_nvic.c" Finished building: ../src/ASF/common/utils/interrupt/interrupt_sam_nvic.c Please see the attached screen capture for the problem (I'm using Atmel studio 6.1) Thanks for your help.
Sorry, i don't have MS Office. Please paste as plain text (the disassembled file). There is no PUSH instruction, the "PUSH" assembler mnemonic is just an alias for STMDB. The GCC disassembler ("objdump") should always print "STMDB", not "PUSH", though.
The following is the source code. I purposely put an asm("STMDB sp!, {r4, r5, lr}"); to test if the STMDB instruction works for the chip, which it does. int main (void) { asm ("b ."); asm("STMDB sp!, {r4, r5, lr}"); //asm("push {r4, r5, r6, lr}"); //asm("push {r4, r5, lr}"); //asm("push {lr}"); //asm("push {lr}"); //asm("push {r5, lr}"); board_init(); OsInit(0); CR_Reg = __get_CONTROL (); MSP_Reg = __get_MSP(); PRIMask_Reg = __get_PRIMASK(); __disable_irq(); //asm("STMDB sp!, {a1-a2, v1-fp, lr}"); //asm ("b OsSchedule"); //OsSchedule1(); TASK_CREATE(&MainTask, main_tsk, (void *)Main_Stk, 2 * 1024, 3, 0, OS_DEFAULT_MODES, "maintask"); OsSchedule(); //asm("LDMIA sp!, {v1-fp, lr}"); //asm("bx lr"); //asm("nop"); // YYY++; // Insert application code here, after the board has been initialized. } The following is the assembly code (by objdump), as you can see the compiler does generate push instruction which is different from the STMDB instruction. 00000b88 <main>: b88: b530 push {r4, r5, lr} b8a: b085 sub sp, #20 b8c: e7fe b.n b8c <main+0x4> b8e: e92d 4030 stmdb sp!, {r4, r5, lr} b92: f640 4325 movw r3, #3109 ; 0xc25 b96: f2c0 0300 movt r3, #0 b9a: 4798 blx r3 b9c: f04f 0000 mov.w r0, #0 ba0: f240 21e5 movw r1, #741 ; 0x2e5 ba4: f2c0 0100 movt r1, #0 ba8: 4788 blx r1 baa: f3ef 8214 mrs r2, CONTROL bae: f640 10b0 movw r0, #2480 ; 0x9b0 bb2: f2c2 0000 movt r0, #8192 ; 0x2000 bb6: 6002 str r2, [r0, #0] bb8: f3ef 8408 mrs r4, MSP bbc: f640 2544 movw r5, #2628 ; 0xa44 bc0: f2c2 0500 movt r5, #8192 ; 0x2000 bc4: 602c str r4, [r5, #0] bc6: f3ef 8110 mrs r1, PRIMASK bca: f640 13b8 movw r3, #2488 ; 0x9b8 bce: f2c2 0300 movt r3, #8192 ; 0x2000 bd2: 6019 str r1, [r3, #0] bd4: b672 cpsid i bd6: f04f 0203 mov.w r2, #3 bda: 9200 str r2, [sp, #0] bdc: f04f 0400 mov.w r4, #0 be0: 9401 str r4, [sp, #4] be2: 9402 str r4, [sp, #8] be4: f640 704c movw r0, #3916 ; 0xf4c be8: f2c0 0000 movt r0, #0 bec: 9003 str r0, [sp, #12] bee: f640 10bc movw r0, #2492 ; 0x9bc bf2: f2c2 0000 movt r0, #8192 ; 0x2000 bf6: f640 3165 movw r1, #2917 ; 0xb65 bfa: f2c0 0100 movt r1, #0 bfe: f640 2248 movw r2, #2632 ; 0xa48 c02: f2c2 0200 movt r2, #8192 ; 0x2000 c06: f44f 6300 mov.w r3, #2048 ; 0x800 c0a: f640 058d movw r5, #2189 ; 0x88d c0e: f2c0 0500 movt r5, #0 c12: 47a8 blx r5 c14: f240 7101 movw r1, #1793 ; 0x701 c18: f2c0 0100 movt r1, #0 c1c: 4788 blx r1 c1e: 4620 mov r0, r4 c20: b005 add sp, #20 c22: bd30 pop {r4, r5, pc}
Please find the attached file for screen captures in PDF format.
Oh you were right, the PUSH instruction has a specific encoding for <=9 registers. Indeed, r5 doesn't seem to be pushed at all, resulting lr ending up in the wrong place. Have you tried this with an other mikrocontroller? Maybe that one is defect... This should definitely work (it does on my STM32F4 which is a Cortex-M4, too - i.e. has exactly the same core). I don't think GCC can be stopped from generating the "PUSH" instruction because it should work.
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.