about summary refs log tree commit diff
path: root/src/rt/arch/i386/context.cpp
blob: f5fa3777eec390c9f093106dbc9401858bf374ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "context.h"

#include "../../rust.h"

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

extern "C" uint32_t CDECL swap_registers(registers_t *oregs,
                                         registers_t *regs)
  asm ("swap_registers");

context::context()
{
    assert((void*)&regs == (void*)this);
}

void context::swap(context &out)
{
  swap_registers(&out.regs, &regs);
}

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;
  *--sp = 0xdeadbeef;

  regs.esp = (uint32_t)sp;
  regs.eip = (uint32_t)f;
}

#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)&regs.r - (intptr_t)&regs);

  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