x86emu: add support for the rdtsc opcode
[v86d.git] / v86_x86emu.c
blob146f9c61796130e23b0085d14a1c276c05d76781
1 #include <stdarg.h>
2 #include <string.h>
3 #include <x86emu.h>
4 /*
5 This is header file for x86_64 is broken in current versions
6 of klibc, so we temporarily comment it out.
7 #include <sys/io.h>
8 */
9 #include "v86.h"
10 #include "v86_x86emu.h"
12 u8 *stack;
13 u8 *halt;
15 __BUILDIO(b,b,u8);
16 __BUILDIO(w,w,u16);
17 __BUILDIO(l,,u32);
19 void printk(const char *fmt, ...)
21 va_list argptr;
22 va_start(argptr, fmt);
23 vsyslog(LOG_INFO, fmt, argptr);
24 va_end(argptr);
27 void pushw(u16 val)
29 X86_ESP -= 2;
30 wrw(((u32) X86_SS << 4) + X86_SP, val);
33 static void x86emu_do_int(int num)
35 u32 eflags;
37 eflags = X86_EFLAGS;
38 eflags = eflags | X86_IF_MASK;
40 /* Return address and flags */
41 pushw(eflags);
42 pushw(X86_CS);
43 pushw(X86_IP);
44 X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK);
46 X86_CS = rdw((num << 2) + 2);
47 X86_IP = rdw((num << 2));
50 int v86_init()
52 X86EMU_intrFuncs intFuncs[256];
53 X86EMU_pioFuncs pioFuncs = {
54 .inb = x_inb,
55 .inw = x_inw,
56 .inl = x_inl,
57 .outb = x_outb,
58 .outw = x_outw,
59 .outl = x_outl,
61 int i;
63 v86_mem_init();
65 stack = v86_mem_alloc(DEFAULT_STACK_SIZE);
66 X86_SS = (u32)stack >> 4;
67 X86_ESP = 0xfffe;
69 halt = v86_mem_alloc(0x100);
70 *halt = 0xF4;
72 /* Setup x86emu I/O functions */
73 X86EMU_setupPioFuncs(&pioFuncs);
75 /* Setup interrupt handlers */
76 for (i = 0; i < 256; i++) {
77 intFuncs[i] = x86emu_do_int;
79 X86EMU_setupIntrFuncs(intFuncs);
81 /* Set the default flags */
82 X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
84 /* M is a macro poiting to the global virtual machine state
85 * for x86emu. */
86 M.mem_base = 0x0;
87 M.mem_size = 0x100000;
89 ioperm(0, 1024, 1);
90 iopl(3);
92 return 0;
95 void v86_cleanup()
97 v86_mem_cleanup();
100 void rconv_v86_to_x86emu(struct v86_regs *rs)
102 X86_EAX = rs->eax;
103 X86_EBX = rs->ebx;
104 X86_ECX = rs->ecx;
105 X86_EDX = rs->edx;
106 X86_EDI = rs->edi;
107 X86_ESI = rs->esi;
108 X86_EBP = rs->ebp;
109 X86_ESP = rs->esp;
110 X86_EFLAGS = rs->eflags;
111 X86_EIP = rs->eip;
112 X86_CS = rs->cs;
113 X86_DS = rs->ds;
114 X86_ES = rs->es;
115 X86_FS = rs->fs;
116 X86_GS = rs->gs;
119 void rconv_x86emu_to_v86(struct v86_regs *rd)
121 rd->eax = X86_EAX;
122 rd->ebx = X86_EBX;
123 rd->ecx = X86_ECX;
124 rd->edx = X86_EDX;
125 rd->edi = X86_EDI;
126 rd->esi = X86_ESI;
127 rd->ebp = X86_EBP;
128 rd->esp = X86_ESP;
129 rd->eflags = X86_EFLAGS;
130 rd->eip = X86_EIP;
131 rd->cs = X86_CS;
132 rd->ds = X86_DS;
133 rd->es = X86_ES;
134 rd->fs = X86_FS;
135 rd->gs = X86_GS;
139 * Perform a simulated interrupt call.
141 int v86_int(int num, struct v86_regs *regs)
143 rconv_v86_to_x86emu(regs);
145 X86_DS = 0x0040;
146 X86_CS = get_int_seg(num);
147 X86_EIP = get_int_off(num);
148 X86_SS = (u32)stack >> 4;
149 X86_ESP = 0xffff;
150 X86_EFLAGS = DEFAULT_V86_FLAGS | X86_IF_MASK;
151 X86_EFLAGS &= ~(X86_VIF_MASK | X86_TF_MASK | X86_IF_MASK | X86_NT_MASK);
153 pushw(DEFAULT_V86_FLAGS);
154 pushw(((u32)halt >> 4));
155 pushw(0x0);
157 X86EMU_exec();
159 rconv_x86emu_to_v86(regs);
160 return 0;