| |
| #include "context.h" |
| #include "../../rust_globals.h" |
| |
| extern "C" uint32_t CDECL swap_registers(registers_t *oregs, |
| registers_t *regs) |
| asm ("swap_registers"); |
| |
| context::context() |
| { |
| assert((void*)®s == (void*)this); |
| } |
| |
| void context::swap(context &out) |
| { |
| swap_registers(&out.regs, ®s); |
| } |
| |
| void context::call(void *f, void *arg, void *stack) { |
| // Get the current context, which we will then modify to call the |
| // given function. |
| swap(*this); |
| |
| // set up the trampoline frame |
| uint32_t *sp = (uint32_t *)stack; |
| |
| // Shift the stack pointer so the alignment works out right. |
| sp = align_down(sp) - 3; |
| *--sp = (uint32_t)arg; |
| // The final return address. 0 indicates the bottom of the stack |
| *--sp = 0; |
| |
| regs.esp = (uint32_t)sp; |
| regs.eip = (uint32_t)f; |
| |
| // Last base pointer on the stack should be 0 |
| regs.ebp = 0; |
| } |
| |
| #if 0 |
| // This is some useful code to check how the registers struct got |
| // layed out in memory. |
| int main() { |
| registers_t regs; |
| |
| printf("Register offsets\n"); |
| |
| #define REG(r) \ |
| printf(" %6s: +%ld\n", #r, (intptr_t)®s.r - (intptr_t)®s); |
| |
| REG(eax); |
| REG(ebx); |
| REG(ecx); |
| REG(edx); |
| REG(ebp); |
| REG(esi); |
| REG(edi); |
| REG(esp); |
| |
| REG(cs); |
| REG(ds); |
| REG(ss); |
| REG(es); |
| REG(fs); |
| REG(gs); |
| |
| REG(eflags); |
| |
| REG(eip); |
| |
| return 0; |
| } |
| #endif |