add linux_emul base, reorganize docs
[openbsd_emul.git] / linux_emul_base / linuxcall.c
CommitLineData
cae36a52 1#include <u.h>
2#include <libc.h>
3#include <ureg.h>
4#include "dat.h"
5#include "fns.h"
6#include "linux.h"
7
8typedef struct Linuxcall Linuxcall;
9
10struct Linuxcall
11{
12 char *name;
13 void *func;
14 int (*stub)(Ureg *, void *);
15};
16
17static int fcall0(Ureg *, void *func){return ((int (*)(void))func)();}
18static int fcall1(Ureg *u, void *func){return ((int (*)(int))func)(u->bx);}
19static int fcall2(Ureg *u, void *func){return ((int (*)(int, int))func)(u->bx, u->cx);}
20static int fcall3(Ureg *u, void *func){return ((int (*)(int, int, int))func)(u->bx, u->cx, u->dx);}
21static int fcall4(Ureg *u, void *func){return ((int (*)(int, int, int, int))func)(u->bx, u->cx, u->dx, u->si);}
22static int fcall5(Ureg *u, void *func){return ((int (*)(int, int, int, int, int))func)(u->bx, u->cx, u->dx, u->si, u->di);}
23static int fcall6(Ureg *u, void *func){return ((int (*)(int, int, int, int, int, int))func)(u->bx, u->cx, u->dx, u->si, u->di, u->bp);}
24
25#include "linuxcalltab.out"
26
27static Linuxcall nocall = {
28 .name = "nosys",
29 .func = sys_nosys,
30 .stub = fcall0,
31};
32
33static void
34linuxret(int errno)
35{
36 Uproc *p;
37 Ureg *u;
38
39 p = current;
40 u = p->ureg;
41 trace("linuxret(%lux: %s, %lux: %E)", u->pc, p->syscall, (ulong)errno, errno);
42 if(errno == -ERESTART){
43 p->restart->syscall = p->syscall;
44 return;
45 }
46 u->ax = (ulong)errno;
47 u->pc += 2;
48 p->restart->syscall = nil;
49 p->syscall = nil;
50}
51
52
53int
54linuxcall(void)
55{
56 Uproc *p;
57 Ureg *u;
58 Linuxcall *c;
59 uchar *pc;
60
61 p = current;
62 u = p->ureg;
63
64 /* CD 80 = INT 0x80 */
65 pc = (uchar*)u->pc;
66 if(pc[0] != 0xcd || pc[1] != 0x80){
67 trace("linuxcall(): not a syscall pc=%lux sp=%lux", u->pc, u->sp);
68 return -1;
69 }
70 c = &linuxcalltab[u->ax];
71 if(c > &linuxcalltab[nelem(linuxcalltab)-1])
72 c = &nocall;
73 p->syscall = c->name;
74 p->sysret = linuxret;
75 if(p->restart->syscall)
76 trace("linuxcall(): restarting %s", p->syscall);
77 linuxret(c->stub(u, c->func));
78 return 0;
79}