Fix minor bugs, use v86_regs to pass reg values from/to the kernel.
[v86d.git] / v86_x86emu.c
blob3a9750736d57e3ee43a39f3d1d5309508e4b511d
1 #include <stdarg.h>
2 #include <string.h>
3 #include <x86emu.h>
4 #include <sys/io.h>
5 #include "v86.h"
6 #include "v86_x86emu.h"
8 u8 *stack;
9 u8 *halt;
11 __BUILDIO(b,b,u8);
12 __BUILDIO(w,w,u16);
13 __BUILDIO(l,,u32);
15 void printk(const char *fmt, ...)
17 va_list argptr;
18 va_start(argptr, fmt);
19 vsyslog(LOG_INFO, fmt, argptr);
20 va_end(argptr);
23 void pushw(u16 val)
25 X86_ESP -= 2;
26 wrw(((u32) X86_SS << 4) + X86_SP, val);
29 static void x86emu_do_int(int num)
31 u32 eflags;
33 eflags = X86_EFLAGS;
34 eflags = eflags | X86_IF_MASK;
36 /* Return address and flags */
37 pushw(eflags);
38 pushw(X86_CS);
39 pushw(X86_IP);
40 X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK);
42 X86_CS = rdw((num << 2) + 2);
43 X86_IP = rdw((num << 2));
46 int v86_init()
48 X86EMU_intrFuncs intFuncs[256];
49 X86EMU_pioFuncs pioFuncs = {
50 .inb = x_inb,
51 .inw = x_inw,
52 .inl = x_inl,
53 .outb = x_outb,
54 .outw = x_outw,
55 .outl = x_outl,
57 int i;
59 v86_mem_init();
61 stack = v86_mem_alloc(DEFAULT_STACK_SIZE);
62 X86_SS = (u32)stack >> 4;
63 X86_ESP = 0xfffe;
65 halt = v86_mem_alloc(0x100);
66 *halt = 0xF4;
68 /* Setup x86emu I/O functions */
69 X86EMU_setupPioFuncs(&pioFuncs);
71 /* Setup interrupt handlers */
72 for (i = 0; i < 256; i++) {
73 intFuncs[i] = x86emu_do_int;
75 X86EMU_setupIntrFuncs(intFuncs);
77 /* Set the default flags */
78 X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
80 /* M is a macro poiting to the global virtual machine state
81 * for x86emu. */
82 M.mem_base = 0x0;
83 M.mem_size = 0x100000;
85 ioperm(0, 1024, 1);
86 iopl(3);
88 return 0;
91 void v86_cleanup()
93 v86_mem_cleanup();
96 void rconv_v86_to_x86emu(struct v86_regs *rs)
98 X86_EAX = rs->eax;
99 X86_EBX = rs->ebx;
100 X86_ECX = rs->ecx;
101 X86_EDX = rs->edx;
102 X86_EDI = rs->edi;
103 X86_ESI = rs->esi;
104 X86_EBP = rs->ebp;
105 X86_ESP = rs->esp;
106 X86_EFLAGS = rs->eflags;
107 X86_EIP = rs->eip;
108 X86_CS = rs->cs;
109 X86_DS = rs->ds;
110 X86_ES = rs->es;
111 X86_FS = rs->fs;
112 X86_GS = rs->gs;
115 void rconv_x86emu_to_v86(struct v86_regs *rd)
117 rd->eax = X86_EAX;
118 rd->ebx = X86_EBX;
119 rd->ecx = X86_ECX;
120 rd->edx = X86_EDX;
121 rd->edi = X86_EDI;
122 rd->esi = X86_ESI;
123 rd->ebp = X86_EBP;
124 rd->esp = X86_ESP;
125 rd->eflags = X86_EFLAGS;
126 rd->eip = X86_EIP;
127 rd->cs = X86_CS;
128 rd->ds = X86_DS;
129 rd->es = X86_ES;
130 rd->fs = X86_FS;
131 rd->gs = X86_GS;
135 * Perform a simulated interrupt call.
137 int v86_int(int num, struct v86_regs *regs)
139 rconv_v86_to_x86emu(regs);
141 X86_DS = 0x0040;
142 X86_CS = get_int_seg(num);
143 X86_EIP = get_int_off(num);
144 X86_SS = (u32)stack >> 4;
145 X86_ESP = 0xffff;
146 X86_EFLAGS = DEFAULT_V86_FLAGS | X86_IF_MASK;
147 X86_EFLAGS &= ~(X86_VIF_MASK | X86_TF_MASK | X86_IF_MASK | X86_NT_MASK);
149 pushw(DEFAULT_V86_FLAGS);
150 pushw(((u32)halt >> 4));
151 pushw(0x0);
153 X86EMU_exec();
155 rconv_x86emu_to_v86(regs);
156 return 0;