Content of Q-registers across context switches

vvb333007
Posts: 79
Joined: Wed Jul 31, 2024 5:53 am
Location: Thailand
Contact:

Content of Q-registers across context switches

Postby vvb333007 » Fri Jun 27, 2025 11:37 am

Hello!

Question regarding ESP32-S3's PIEs : can I assume that Q registers (q0,q1 ...) are preserved across task switches? Across FreeRTOS and ESP-IDF API calls?
I.e.
```
...
ee.vld.l.64.ip q0, a2, 8 # load Q0 register
....
vPortYield();
...
Q0 = ?
```

Thanks!
Thanks!
Slava.

MicroController
Posts: 2705
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Content of Q-registers across context switches

Postby MicroController » Fri Jun 27, 2025 11:51 am

Officially, you cannot assume PIE registers to be preserved across any function call. (Any function could potentially be using the PIE, and lacking a specified ABI, there are no callee-saved PIE registers.)

In practice, as of now, the IDF FreeRTOS variant does not distinguish between "solicited" and "unsolicited" context switches so PIE (and FPU) context is preserved in both cases. (I would advocate for this to be changed in the future though.)

When in doubt, notice that 'manually' stashing a few Q registers on the stack before and restoring them after a function call takes almost no time, especially compared to the time needed for a context switch.
Last edited by MicroController on Mon Jun 30, 2025 11:04 pm, edited 1 time in total.

Sprite
Espressif staff
Espressif staff
Posts: 10650
Joined: Thu Nov 26, 2015 4:08 am

Re: Content of Q-registers across context switches

Postby Sprite » Mon Jun 30, 2025 2:09 am

Officially, you cannot assume PIE registers to be preserved across any function call. (Any function could poentially be using the PIE, and lacking a specified ABI, there are no callee-saved PIE registers.)
To be fair, the compiler doesn't know about the Q registers (afaik) so should never use them. Assembly functions don't have to have a general ABI, so look into the docs of the function to see if it saves anything.
In practice, as of now, the IDF FreeRTOS variant does not distinguish between "solicited" and "unsolicited" context switches so PIE (and FPU) context is preserved in both cases. (I would advocate for this to be changed in the future though.)
@MicroController You are correct, but out of interest: can you tell me why you would like to distinguish between solicited and unsolicited context switches?

MicroController
Posts: 2705
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Content of Q-registers across context switches

Postby MicroController » Mon Jun 30, 2025 6:07 am

@MicroController You are correct, but out of interest: can you tell me why you would like to distinguish between solicited and unsolicited context switches?
Sure :)
Two reasons:
1. minor performance gain - since any function call could potentially clobber PIE registers anyway, a solicited context switch could do without saving+restoring the context.
2. currently, tasks are implicitly+permanently pinned to one core as soon as they use PIE or FPU 'coprocessors' for the first time, with no way to 'unpin' them ever again. A solicited context switch could be used to, also implicitly, relinquish a task's 'ownership' of the coprocs and restore its original, potentially 'unpinned', affinity, without having to migrate the coproc context to another core.
Of course, ideally, the coproc context would automatically migrate from core to core with an unpinned task, i.e. no implicit task pinning in the fist place, but that doesn't easily go together with the lazy context saving.
Then again, using the S3's PIE instructions, saving+restoring the full PIE or FPU context can be extremely fast, so, at least on the S3, the whole lazy context saving really doesn't provide much of a benefit, if any, especially when considering the management overhead in the coproc exception handler. (IIRC, I managed to save or restore the full PIE context in 40-50 clock cycles, but could 'only' optimize the corresponding coproc exception handler code down to some 210 clock cycles. So lazy-saving + restoring saves ~100 clock cycles when it doesn't do anything, but 'costs' at least ~400 when it does (more like 600+ out of the box). - And now we're very officially off-topic ;-))

MicroController
Posts: 2705
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Content of Q-registers across context switches

Postby MicroController » Mon Jun 30, 2025 11:36 pm

Officially, you cannot assume PIE registers to be preserved across any function call. (Any function could poentially be using the PIE, and lacking a specified ABI, there are no callee-saved PIE registers.)
To be fair, the compiler doesn't know about the Q registers (afaik) so should never use them. Assembly functions don't have to have a general ABI, so look into the docs of the function to see if it saves anything.
You're right, of course. The compiler won't sneak in any PIE instructions or the like. What I mean is that when you call a function which calls a function which ... which calls a function in some 3rd party library, you may not know if any of those functions might happen to be using the PIE, and the compiler won't protect you in any way from that function clobbering 'your' PIE context, nor is there a convention on which regsters a function should not clobber (=callee-saved), so effectively all PIE registers need to be caller-saved to be safe.

Who is online

Users browsing this forum: ChatGPT-User, PerplexityBot and 2 guests