Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12599 Discussions

Another Nios GCC Bug with -mflat

Altera_Forum
Honored Contributor II
1,534 Views

I was stepping through my code trying to figure out how a block of data was being overwritten by some of the initialization code on my project. I was rather surprised to find the data changed as soon as I stepped into any one of several simple functions - it was overwritten with the argument for the simple function, even before I had executed any statements in the body of the routine. When I looked at the assembly code generated for the function prolog, it was obvious what the problem was. 

; flat prologue begin ; Expand callers frame 26 words.     mov    %g1, %sp     pfx    %hi(104)     subi    %sp, %lo(104)     sts  , %fp ; save call preserved regs     sts    , %o7     sts    , %l0 ; Set frame pointer     mov  %fp, %g1 ; flat prologue end     pfx    17     st    , %o0     pfx    18     st    , %o1     pfx    19     st    , %o2 

The prolog sets up a stack frame (bounded by %fp at the top and %sp at the bottom), but then when it saves the arguments (%o0, %o1 and %o2), it uses a positive offset from %fp! This means the arguments are saved in the space allocated for saved arguements in the callers stack frame. Most of the time this works by accident, and doesn't cause an obvious problem, since the caller has made the same mistake (and thus isn't using this space). 

 

But it is noticeable when calling a routine that saves arguments on a newly set-up stack: it saves its arguments 17 32-bit words above the top of the stack (in memory that is probably allocated to something else).  

 

Fortunately, as a work around one just has to make sure there 23 32-bit words available above the initial stack pointer when setting up a stack. 

 

I haven't figured out how functions with more than six 32-bit arugments are actually working, I'm planning on avoiding them.
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
790 Views

On reflection, I don't think this is a bug after all (or maybe just a a documentation bug). The description of the Nios stack frame in the "ABI Summary" section of the manual "User's Guide for Altera Nios" v1.0 is not as clear as it might be, and I think I misunderstood it. This became clear when I tried to figure out how things worked when there were more than 6 arguments to be passed to a function. 

 

Stack space for the arguments to a function (including arguments passed in registers %o0 - %o5) is indeed allocated in the frame of the calling function. However, these arguments aren't pushed on to the stack - the space must be allocated by setting the %sp register to point 23 32-bit words below the top of the stack before making any calls (further if the calling a function with more than 6 arguments). Indeed, the startup code from Altera does this. 

 

Thus, although the %fp and %sp registers mark the boundaries of the stack space a routine is responsible for allocating, they do not mark the boundaries of where a routine is allowed to write to. In addition to the stack space a routine has allocated, a routine is free to write to the stack space allocated by its caller for its argument save area. When setting up a new stack, this argument save area has to be provided before calling any routines.
0 Kudos
Reply