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.