Hello!
Was reading about windowed calling conventions and found that a0, the return address is not accessible from within called function. E.g. if I would like to modify the return address, should I:
1. Manually move window left, change a0, move window right or
2. Provoke window spill, make a few nested dummy function calls, so my a0 can be found on the stack and modified there
I am asking this just for better understanding of how it all works. Xtensa is new for me so I want to learn the basics.
Also, regarding "entry aX, N"
Am I right in the assumption that it is "entry" who actually rotates the window, so register a0 (return address) is accessible from the called function before "entry" call? I.e. if I change function prologue from "entry aX, N" to
mov a13, a0
entry ...
then I can get my return address value in a13 (which becomes a5 after rotation by 8)
Is this correct?
Thank you!
call8 and a0 (access / modify the return address)
Re: call8 and a0 (access / modify the return address)
Espressif documentation:
Then it says "whenever function B returns" (??) did they mean H or I ? When H calls I, then window will be the same as for B, so exception overflow occurs again?
It implies that a8, a9.. of H
are a0, a1.. of A. and then : "B’s stack frame is accessible since a9
is a1 of B, which is B’s stack pointer."
So.... a9 of H is a1 of A or a1 of B? Or it is a mistake in the doc?
Is this correct? It says, that after call to H, register window now is in area of A.With all the necessary points covered, let’s take an example and connect all the dots.
Suppose, each function call is carried out using call8 and we start with WindowBase = 4
Function A calls B, B calls C, C calls D... till I, i.e:
Functions A -> B -> C -> D -> E -> F -> G -> H ->I
WindowBase 4 -> 6 -> 8 -> 10 -> 12 -> 14 -> 0 -> 2 -> 4
On each function call, the WindowBase will be incremented by 2 because call8 is used.
No. of bits in WindowBase register = log2((No. of registers in register file)/4) = log2(64/4) = 4.
Thus the max value of WindowBase is 15.
As we have noticed, on the 9th function call the window wraps around to a point where the frame
contains the data of a parent function, i.e a0, a1.. contains data of A. It implies that a8, a9.. of H
are a0, a1.. of A.
A window overflow exception will be generated when H tries to modify a8, a9.. since it originally
contains the context of A, so these must be saved to accommodate arguments of I. At this point, in
the window overflow exception handler we must rotate the register window to frame A (WindowBase
= 4)
a0 – a3 are stored in the Base Save Area of B’s stack frame. B’s stack frame is accessible since a9
is a1 of B, which is B’s stack pointer. a4 – a7 are stored in the Extra Save Area of A’s stack frame.
Now whenever B returns, window underflow exception will be generated and we need to make sure
that the corresponding exception handler would restore these values back into the registers.
Then it says "whenever function B returns" (??) did they mean H or I ? When H calls I, then window will be the same as for B, so exception overflow occurs again?
It implies that a8, a9.. of H
are a0, a1.. of A. and then : "B’s stack frame is accessible since a9
is a1 of B, which is B’s stack pointer."
So.... a9 of H is a1 of A or a1 of B? Or it is a mistake in the doc?
Thanks!
Slava.
Slava.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: call8 and a0 (access / modify the return address)
https://www.cadence.com/content/dam/cad ... ummary.pdf
The CALL8 instruction does not rotate the window itself, but instead stores the window increment for later use by the ENTRY instruction. The return address and window increment are placed in the caller’s a8 (the callee’s a0), and the processor then branches to the target address.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: call8 and a0 (access / modify the return address)
When the window overflow occurs, the WindowStart is moved (up), so A is pushed out of the window. When B returns (to A), a window underflow occurs and the WindowStart has to be moved down again.Then it says "whenever function B returns" (??) did they mean H or I ?
Last edited by MicroController on Wed Sep 24, 2025 6:38 pm, edited 1 time in total.
Re: call8 and a0 (access / modify the return address)
In this scheme:When the window overflow occurs, the WindowBase is moved (up), so A is pushed out of the window. When B returns (to A), a window underflow occurs and the WindowBase has to be moved down again.Then it says "whenever function B returns" (??) did they mean H or I ?
Functions A -> B -> C -> D -> E -> F -> G -> H ->I
WindowBase 4 -> 6 -> 8 -> 10 -> 12 -> 14 -> 0 -> 2 -> 4
Overflow occurs when H calls I. As a result, window is moved to the A, but registers a0..a7 of A are saved to the stack by the window overflow handler, is it correct?
Suppose function I calls another function K. Window moves to the right, to position of B and? Overflow happens again? If not, then registers of B will be overwritten by K.
Totally lost.
Thanks!
Slava.
Slava.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: call8 and a0 (access / modify the return address)
... and registers a0...a7 of B will be saved to the stack by the overflow exception handler and the WindowStart moved up again, correct.Overflow occurs when H calls I. As a result, window is moved to the A, but registers a0..a7 of A are saved to the stack by the window overflow handler, is it correct?
Suppose function I calls another function K. Window moves to the right, to position of B and? Overflow happens again?
Btw, since the IDF already comes with the window exception handler you don't really need to bother about the workings. You only need to know the ABI, i.e. CALL8, i.e. caller's a8...a15 become callee's a0...a7; caller and callee share only 8 registers.
Who is online
Users browsing this forum: Applebot, Bing [Bot], Qwantbot, YisouSpider and 3 guests