I'm writing a task switcher and want to be able to call my OS's taskSwitch() function using an [R]JMP so the calling location does not get pushed onto stack. I can't use IJMP because I can't clobber any registers.
taskSwitch() is only called from ISRs (for preemtive kernel) or wait(), which tasks call when they have nothing to do, instead of waiting for ISR tick. Therefore when taskSwitch() returns, it jumps straight back into user code and skips the epilog of the ISR or wait() that called it.
The current solution is to take the mangled name of the taskSwitch() function copied out of an assembly call line and use that as rjmp's argument in inline assembly.
And yes, I'm actually using a C++ static function because I want the syntactic sugar (and, if written correctly, there is no overhead to C++)
Becomes this assembly function call:
But I want this:
Which works if I enter that explicitly, but I want the compiler to mangle the names for me. (I guess there is a pattern to the mangled names so they shouldn't change?)
So, does anyone know if this is possible?
If this isn't possible, I have another solution where I can push a register onto stack first (push rX), then call taskSwitch(), then pop the return location to the saved register (pop rX, pop rX), then continue with the context save and rearrange context restore accordingly. This method however has a 2 clock penalty...