[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?
From: |
Bob Paddock |
Subject: |
Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup? |
Date: |
Fri, 6 Jul 2012 10:57:17 -0400 |
>> Did I miss anything in the documentation that would tell me not to
>> use auto variables in .initX sections after .init2 that sets the
>> stack?
>
> If you declare the function being "naked", you cannot expect the
> compiler to allocate a stack frame.
What one expects and reality are often different. Before I submit a
patch for the documentation, to prevent others from shooting
themselves in the foot, I wanted to make sure I understood how stack
frames are working.
In looking at the .lss file, I see something that I do not understand,
when comping code for the
XMega128A1 using GCC 4.7.1-rc1
Is the timing of the XMega OUT instruction different than a non-XMega
part, in that it would prevent an interrupt between two sequential
OUT instructions? What happens when an interrupt happens between the
instructions that manipulate the stack pointer in the epilogue/prologue?
If there is 256 bytes of stack head-room between the heap/bss maybe nothing
(it would not be noticed as a problem).
Going back to Anatoly original OS_Main/OS_Task patch:
http://www.mail-archive.com/address@hidden/msg03812.html
Using his example code from that email, copied in to the file main.c,
compiling using the Makefile at the end of this message, Non-XMega run:
# Non-XMega the stack manipulation is properly protected.
# The non-XMega parts delay a cycle when enabling interrupts,
# hence it is safe to save stack_hi, enable interrupts, save_lo,
# this code disables interrupts when modifying the stack pointer 0x3E/0x3F:
00000090 <__prologue_saves__>:
[snip pushs]
b4: cd b7 in r28, 0x3d ; 61
b6: de b7 in r29, 0x3e ; 62
b8: ca 1b sub r28, r26
ba: db 0b sbc r29, r27
bc: 0f b6 in r0, 0x3f ; 63
be: f8 94 cli ; Disable Interrupts
c0: de bf out 0x3e, r29 ; 62
c2: 0f be out 0x3f, r0 ; 63 Enable Interrupts are
delayed
till after next instruction
c4: cd bf out 0x3d, r28 ; 61
c6: 09 94 ijmp
000000c8 <__epilogue_restores__>:
[snip pops]
f0: 0f b6 in r0, 0x3f ; 63
f2: f8 94 cli ; Disable Interrupts
f4: de bf out 0x3e, r29 ; 62
f6: 0f be out 0x3f, r0 ; 63 Enable Interrupts are
delayed
till after next instruction
f8: cd bf out 0x3d, r28 ; 61
fa: ca 2f mov r28, r26
fc: db 2f mov r29, r27
fe: 08 95 ret
I'm fine with the above code, however I question this
XMega run:
# This code DOES NOT disable interrupts when modifying the stack
# pointer 0x3D/0x3E:
000002b0 <__prologue_saves__>:
[snip pushs]
2d4: cd b7 in r28, 0x3d ; 61
2d6: de b7 in r29, 0x3e ; 62
2d8: ca 1b sub r28, r26
2da: db 0b sbc r29, r27
2dc: cd bf out 0x3d, r28 ; 61
; [What happens if an interrupt happens between these two out instructions?]
2de: de bf out 0x3e, r29 ; 62
2e0: 19 94 eijmp
000002e2 <__epilogue_restores__>:
[snip ldds]
306: ce 0f add r28, r30
308: d1 1d adc r29, r1
30a: cd bf out 0x3d, r28 ; 61
; [What happens if an interrupt happens between these two out instructions?]
30c: de bf out 0x3e, r29 ; 62
30e: ed 01 movw r28, r26
310: 08 95 ret
For anyone that wants to reproduce:
# -------------- Cut Here main.c --------------
__attribute__ ((noinline))
int fn0(long a1, long a2, long a3, long a4, long a5)
{
return 0;
}
// Note this is commented out, OS_MAIN/OS_TASK are not relevant at this point:
//__attribute__ ((OS_main))
int main(void)
{
volatile long long a; // local var, need function frame
a = 1;
return fn0(1, 2, 3, 4, 5); // use call-saved regs
}
# -------------- Cut Here --------------
And this Makefile of mine:
# -------------- Cut Here Makefile --------------
MCU=atxmega128a1
#
# NOTE, that this is commented out, it is the important point.
# Uncomment to see the Xmega main.lss output and compare.
#
#M_MCU=-mmcu=$(MCU)
SRC=main.c
TARGET=main
OBJDIR = .
CSTANDARD = -std=gnu99
CFLAGS += $(CSTANDARD)
# Functions prologues/epilogues expanded as call to appropriate
# subroutines. Code size will be smaller. Use subroutines for function
# prologue/epilogue. For complex functions that use many registers (that needs
# to be saved/restored on function entry/exit), this saves some space at the
# cost of a slightly increased execution time.
CFLAGS += -mcall-prologues
# -adhlns...: create assembler listing
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
# Be verbose:
CFLAGS += -v
ALL_CFLAGS = -v $(M_MCU) $(CFLAGS)
# Tools:
OBJDUMP = avr-objdump
CC = avr-gcc
SHELL = sh
REMOVE = rm -f
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o)
$(ASRC:%.S=$(OBJDIR)/%.o)
all: build
build: elf lss
elf: $(TARGET).elf
lss: $(TARGET).lss
# Create extended listing file from ELF output file.
%.lss: %.elf
# -h Display section headers
# -S Intermix source code with disassembly
# -z Do not skip blocks of zero when disassembling
$(OBJDUMP) -h -S -z $(OBJDIR)/$< > $(OBJDIR)/$@
%.elf: $(OBJ)
$(info )
$(info ALL_CFLAGS = $(ALL_CFLAGS))
$(info )
$(CC) $(ALL_CFLAGS) $^ --output $(OBJDIR)/$@ $(LDFLAGS)
# Compile: create object files from C source files.
$(OBJDIR)/%.o : %.c
$(CC) -c $(ALL_CFLAGS) $< -o $@
clean:
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).lss
# -------------- Cut Here --------------
Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?, Joerg Wunsch, 2012/07/04
Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?, Joerg Wunsch, 2012/07/04
Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?, Georg-Johann Lay, 2012/07/04