Here's the context for my question:
In my project, a C function is called from an assembly file before the stack is initialized. Because the stack is not initialized, the function must not use the stack.
Is it possible with some "pragma like" command to force gcc to not use the stack with that particular function?
Additional information : The goal of my work is to convert a project previously compiled with ARMASM to gcc. So in ARMASM, calling this C function before the stack initialization was working. Maybe that the definitive answer will be that it is not possible to do this in gcc...
Below there is an extract of the ELF listing for the C function called in the assembly code (as you can see I tried a always_inline, but when called from assembly this doesn't seem to be enough):
000049d0 <CInit_Init>:
__attribute__((always_inline)) extern void CInit_Init(void) {
49d0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
49d4: e28db000 add fp, sp, #0
__attribute__((always_inline)) void COM1_Init(void);
__attribute__((always_inline)) extern inline void COM1_Init_I(void) {
// Skip if already enabled
if (TEST_BIT_CLR(HwrSysControl1, HwSysControl1UartEnable)) {
49d8: e59f3038 ldr r3, [pc, #56] ; 4a18 <CInit_Init+0x48>
49dc: e5933000 ldr r3, [r3]
49e0: e2033c01 and r3, r3, #256 ; 0x100
49e4: e3530000 cmp r3, #0
49e8: 1a000007 bne 4a0c <CInit_Init+0x3c>
HwrUart1Control = (
49ec: e59f3028 ldr r3, [pc, #40] ; 4a1c <CInit_Init+0x4c>
49f0: e59f2028 ldr r2, [pc, #40] ; 4a20 <CInit_Init+0x50>
49f4: e5832000 str r2, [r3]
HwUartControlDataLength8|
HwUartControlFifoEnable|
HwUartControlRate115200);
BIT_SET(HwrSysControl1, HwSysControl1UartEnable);
49f8: e59f3018 ldr r3, [pc, #24] ; 4a18 <CInit_Init+0x48>
49fc: e59f2014 ldr r2, [pc, #20] ; 4a18 <CInit_Init+0x48>
4a00: e5922000 ldr r2, [r2]
4a04: e3822c01 orr r2, r2, #256 ; 0x100
4a08: e5832000 str r2, [r3]
COM1_Init_I();
}
4a0c: e28bd000 add sp, fp, #0
4a10: e49db004 pop {fp} ; (ldr fp, [sp], #4)
4a14: e12fff1e bx lr
4a18: 80000100 .word 0x80000100
4a1c: 800004c0 .word 0x800004c0
4a20: 00070001 .word 0x00070001
just set up the stack. Otherwise if you dont want a stack have no local variables and have little enough code that you dont run out of registers, dont call any functions from within this function, etc. If you really need variables then use global variables. The compiler CANNOT generate your code without using the stack if you cause the code to run out of registers and globals. No compiler switch will invent storage, and I wouldnt trust a compiler that has some non-stack non-standard trick it might try to use..
Simple, no local variables, doesnt even need an intermediate register:
unsigned int fun ( unsigned int a, unsigned int b )
{
return(a+b);
}
no stack:
00000000 <fun>:
0: e0810000 add r0, r1, r0
4: e12fff1e bx lr
you can always change the stack after you call your initial C code, it takes one to a few instructions to set the stack before your C call, just set the stack pointer. You dont need all the stack pointers, just one. either set the stack pointer or write the function in assembler not C. You should be initializing the stack before a com port anyway. It is one instruction, two word locations and you are calling C so the cost is negligible.
.globl _start
_start:
b reset
reset:
ldr sp,=0x20008000
bl more_fun
b .
.globl fun
fun:
bx lr
.globl fun_out
fun_out:
bx lr
unsigned int fun ( unsigned int , unsigned int );
void fun_out ( unsigned int, unsigned int, unsigned int, unsigned int );
unsigned int more_fun ( unsigned int a, unsigned int b, unsigned int c )
{
unsigned int d;
d = fun(a,b);
fun_out(a,b+c,b,a+c);
}
on instruction, two words and you can call C
4: e59fd00c ldr sp, [pc, #12] ; 18 <fun_out+0x4>
8: eb000003 bl 1c <more_fun>
...
18: 20008000 andcs r8, r0, r0
0000001c <more_fun>:
1c: e92d4070 push {r4, r5, r6, lr}
20: e1a05002 mov r5, r2
24: e1a06000 mov r6, r0
28: e1a04001 mov r4, r1
2c: ebfffff7 bl 10 <fun>
30: e1a00006 mov r0, r6
34: e0853006 add r3, r5, r6
38: e0851004 add r1, r5, r4
3c: e1a02004 mov r2, r4
40: ebfffff3 bl 14 <fun_out>
44: e8bd8070 pop {r4, r5, r6, pc}