Mercurial > mplayer.hg
annotate osdep/lrmi.c @ 11595:95413c6d76a0
keyframe detection support by rgselk <rgselknospam@yahoo.com>
author | alex |
---|---|
date | Mon, 08 Dec 2003 21:57:12 +0000 |
parents | 830c5c1800bc |
children | 7a6d3ca86409 |
rev | line source |
---|---|
2212 | 1 /* |
2 Linux Real Mode Interface - A library of DPMI-like functions for Linux. | |
3 | |
4 Copyright (C) 1998 by Josh Vanderhoof | |
5 | |
6 You are free to distribute and modify this file, as long as you | |
7 do not remove this copyright notice and clearly label modified | |
8 versions as being modified. | |
9 | |
10 This software has NO WARRANTY. Use it at your own risk. | |
11 Original location: http://cvs.debian.org/lrmi/ | |
12 */ | |
13 | |
11455 | 14 #include "../config.h" |
15 #ifdef HAVE_VESA | |
16 | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
17 #include <signal.h> |
2212 | 18 #include <stdio.h> |
19 #include <string.h> | |
20 #include <sys/io.h> | |
21 #include <asm/vm86.h> | |
22 | |
23 #ifdef USE_LIBC_VM86 | |
24 #include <sys/vm86.h> | |
25 #endif | |
26 | |
27 #include <sys/types.h> | |
28 #include <sys/stat.h> | |
29 #include <sys/mman.h> | |
30 #include <unistd.h> | |
31 #include <fcntl.h> | |
32 | |
33 #include "lrmi.h" | |
34 | |
35 #define REAL_MEM_BASE ((void *)0x10000) | |
36 #define REAL_MEM_SIZE 0x10000 | |
37 #define REAL_MEM_BLOCKS 0x100 | |
38 | |
39 struct mem_block | |
40 { | |
41 unsigned int size : 20; | |
42 unsigned int free : 1; | |
43 }; | |
44 | |
45 static struct | |
46 { | |
47 int ready; | |
48 int count; | |
49 struct mem_block blocks[REAL_MEM_BLOCKS]; | |
10857 | 50 } mem_info = { .ready = 0, }; |
2212 | 51 |
52 static int | |
53 real_mem_init(void) | |
54 { | |
55 void *m; | |
56 int fd_zero; | |
57 | |
58 if (mem_info.ready) | |
59 return 1; | |
60 | |
61 fd_zero = open("/dev/zero", O_RDONLY); | |
62 if (fd_zero == -1) | |
63 { | |
64 perror("open /dev/zero"); | |
65 return 0; | |
66 } | |
67 | |
68 m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, | |
69 PROT_READ | PROT_WRITE | PROT_EXEC, | |
70 MAP_FIXED | MAP_PRIVATE, fd_zero, 0); | |
71 | |
72 if (m == (void *)-1) | |
73 { | |
74 perror("mmap /dev/zero"); | |
75 close(fd_zero); | |
76 return 0; | |
77 } | |
78 | |
79 mem_info.ready = 1; | |
80 mem_info.count = 1; | |
81 mem_info.blocks[0].size = REAL_MEM_SIZE; | |
82 mem_info.blocks[0].free = 1; | |
83 | |
84 return 1; | |
85 } | |
86 | |
87 | |
88 static void | |
89 insert_block(int i) | |
90 { | |
91 memmove( | |
92 mem_info.blocks + i + 1, | |
93 mem_info.blocks + i, | |
94 (mem_info.count - i) * sizeof(struct mem_block)); | |
95 | |
96 mem_info.count++; | |
97 } | |
98 | |
99 static void | |
100 delete_block(int i) | |
101 { | |
102 mem_info.count--; | |
103 | |
104 memmove( | |
105 mem_info.blocks + i, | |
106 mem_info.blocks + i + 1, | |
107 (mem_info.count - i) * sizeof(struct mem_block)); | |
108 } | |
109 | |
110 void * | |
111 LRMI_alloc_real(int size) | |
112 { | |
113 int i; | |
114 char *r = (char *)REAL_MEM_BASE; | |
115 | |
116 if (!mem_info.ready) | |
117 return NULL; | |
118 | |
119 if (mem_info.count == REAL_MEM_BLOCKS) | |
120 return NULL; | |
121 | |
122 size = (size + 15) & ~15; | |
123 | |
124 for (i = 0; i < mem_info.count; i++) | |
125 { | |
126 if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) | |
127 { | |
128 insert_block(i); | |
129 | |
130 mem_info.blocks[i].size = size; | |
131 mem_info.blocks[i].free = 0; | |
132 mem_info.blocks[i + 1].size -= size; | |
133 | |
134 return (void *)r; | |
135 } | |
136 | |
137 r += mem_info.blocks[i].size; | |
138 } | |
139 | |
140 return NULL; | |
141 } | |
142 | |
143 | |
144 void | |
145 LRMI_free_real(void *m) | |
146 { | |
147 int i; | |
148 char *r = (char *)REAL_MEM_BASE; | |
149 | |
150 if (!mem_info.ready) | |
151 return; | |
152 | |
153 i = 0; | |
154 while (m != (void *)r) | |
155 { | |
156 r += mem_info.blocks[i].size; | |
157 i++; | |
158 if (i == mem_info.count) | |
159 return; | |
160 } | |
161 | |
162 mem_info.blocks[i].free = 1; | |
163 | |
164 if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) | |
165 { | |
166 mem_info.blocks[i].size += mem_info.blocks[i + 1].size; | |
167 delete_block(i + 1); | |
168 } | |
169 | |
170 if (i - 1 >= 0 && mem_info.blocks[i - 1].free) | |
171 { | |
172 mem_info.blocks[i - 1].size += mem_info.blocks[i].size; | |
173 delete_block(i); | |
174 } | |
175 } | |
176 | |
177 | |
178 #define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK) | |
179 #define DEFAULT_STACK_SIZE 0x1000 | |
180 #define RETURN_TO_32_INT 255 | |
181 | |
182 static struct | |
183 { | |
184 int ready; | |
185 unsigned short ret_seg, ret_off; | |
186 unsigned short stack_seg, stack_off; | |
187 struct vm86_struct vm; | |
10857 | 188 } context = { .ready = 0, }; |
2212 | 189 |
190 | |
191 static inline void | |
192 set_bit(unsigned int bit, void *array) | |
193 { | |
194 unsigned char *a = array; | |
195 | |
196 a[bit / 8] |= (1 << (bit % 8)); | |
197 } | |
198 | |
199 | |
200 static inline unsigned int | |
201 get_int_seg(int i) | |
202 { | |
203 return *(unsigned short *)(i * 4 + 2); | |
204 } | |
205 | |
206 | |
207 static inline unsigned int | |
208 get_int_off(int i) | |
209 { | |
210 return *(unsigned short *)(i * 4); | |
211 } | |
212 | |
213 | |
214 static inline void | |
215 pushw(unsigned short i) | |
216 { | |
217 struct vm86_regs *r = &context.vm.regs; | |
218 r->esp -= 2; | |
219 *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i; | |
220 } | |
221 | |
222 | |
223 int | |
224 LRMI_init(void) | |
225 { | |
226 void *m; | |
227 int fd_mem; | |
228 | |
229 if (context.ready) | |
230 return 1; | |
231 | |
232 if (!real_mem_init()) | |
233 return 0; | |
234 | |
235 /* | |
236 Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) | |
237 and the ROM (0xa0000 - 0x100000) | |
238 */ | |
239 fd_mem = open("/dev/mem", O_RDWR); | |
240 | |
241 if (fd_mem == -1) | |
242 { | |
243 perror("open /dev/mem"); | |
244 return 0; | |
245 } | |
246 | |
247 m = mmap((void *)0, 0x502, | |
248 PROT_READ | PROT_WRITE | PROT_EXEC, | |
249 MAP_FIXED | MAP_PRIVATE, fd_mem, 0); | |
250 | |
251 if (m == (void *)-1) | |
252 { | |
253 perror("mmap /dev/mem"); | |
254 return 0; | |
255 } | |
256 | |
257 m = mmap((void *)0xa0000, 0x100000 - 0xa0000, | |
258 PROT_READ | PROT_WRITE, | |
259 MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); | |
260 | |
261 if (m == (void *)-1) | |
262 { | |
263 perror("mmap /dev/mem"); | |
264 return 0; | |
265 } | |
266 | |
267 | |
268 /* | |
269 Allocate a stack | |
270 */ | |
271 m = LRMI_alloc_real(DEFAULT_STACK_SIZE); | |
272 | |
273 context.stack_seg = (unsigned int)m >> 4; | |
274 context.stack_off = DEFAULT_STACK_SIZE; | |
275 | |
276 /* | |
277 Allocate the return to 32 bit routine | |
278 */ | |
279 m = LRMI_alloc_real(2); | |
280 | |
281 context.ret_seg = (unsigned int)m >> 4; | |
282 context.ret_off = (unsigned int)m & 0xf; | |
283 | |
284 ((unsigned char *)m)[0] = 0xcd; /* int opcode */ | |
285 ((unsigned char *)m)[1] = RETURN_TO_32_INT; | |
286 | |
287 memset(&context.vm, 0, sizeof(context.vm)); | |
288 | |
289 /* | |
290 Enable kernel emulation of all ints except RETURN_TO_32_INT | |
291 */ | |
292 memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored)); | |
293 set_bit(RETURN_TO_32_INT, &context.vm.int_revectored); | |
294 | |
295 context.ready = 1; | |
296 | |
297 return 1; | |
298 } | |
299 | |
300 | |
301 static void | |
302 set_regs(struct LRMI_regs *r) | |
303 { | |
304 context.vm.regs.edi = r->edi; | |
305 context.vm.regs.esi = r->esi; | |
306 context.vm.regs.ebp = r->ebp; | |
307 context.vm.regs.ebx = r->ebx; | |
308 context.vm.regs.edx = r->edx; | |
309 context.vm.regs.ecx = r->ecx; | |
310 context.vm.regs.eax = r->eax; | |
311 context.vm.regs.eflags = DEFAULT_VM86_FLAGS; | |
312 context.vm.regs.es = r->es; | |
313 context.vm.regs.ds = r->ds; | |
314 context.vm.regs.fs = r->fs; | |
315 context.vm.regs.gs = r->gs; | |
316 } | |
317 | |
318 | |
319 static void | |
320 get_regs(struct LRMI_regs *r) | |
321 { | |
322 r->edi = context.vm.regs.edi; | |
323 r->esi = context.vm.regs.esi; | |
324 r->ebp = context.vm.regs.ebp; | |
325 r->ebx = context.vm.regs.ebx; | |
326 r->edx = context.vm.regs.edx; | |
327 r->ecx = context.vm.regs.ecx; | |
328 r->eax = context.vm.regs.eax; | |
329 r->flags = context.vm.regs.eflags; | |
330 r->es = context.vm.regs.es; | |
331 r->ds = context.vm.regs.ds; | |
332 r->fs = context.vm.regs.fs; | |
333 r->gs = context.vm.regs.gs; | |
334 } | |
335 | |
336 #define DIRECTION_FLAG (1 << 10) | |
337 | |
338 static void | |
339 em_ins(int size) | |
340 { | |
341 unsigned int edx, edi; | |
342 | |
343 edx = context.vm.regs.edx & 0xffff; | |
344 edi = context.vm.regs.edi & 0xffff; | |
345 edi += (unsigned int)context.vm.regs.ds << 4; | |
346 | |
347 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
348 { | |
349 if (size == 4) | |
350 asm volatile ("std; insl; cld" | |
351 : "=D" (edi) : "d" (edx), "0" (edi)); | |
352 else if (size == 2) | |
353 asm volatile ("std; insw; cld" | |
354 : "=D" (edi) : "d" (edx), "0" (edi)); | |
355 else | |
356 asm volatile ("std; insb; cld" | |
357 : "=D" (edi) : "d" (edx), "0" (edi)); | |
358 } | |
359 else | |
360 { | |
361 if (size == 4) | |
362 asm volatile ("cld; insl" | |
363 : "=D" (edi) : "d" (edx), "0" (edi)); | |
364 else if (size == 2) | |
365 asm volatile ("cld; insw" | |
366 : "=D" (edi) : "d" (edx), "0" (edi)); | |
367 else | |
368 asm volatile ("cld; insb" | |
369 : "=D" (edi) : "d" (edx), "0" (edi)); | |
370 } | |
371 | |
372 edi -= (unsigned int)context.vm.regs.ds << 4; | |
373 | |
374 context.vm.regs.edi &= 0xffff0000; | |
375 context.vm.regs.edi |= edi & 0xffff; | |
376 } | |
377 | |
378 static void | |
379 em_rep_ins(int size) | |
380 { | |
381 unsigned int ecx, edx, edi; | |
382 | |
383 ecx = context.vm.regs.ecx & 0xffff; | |
384 edx = context.vm.regs.edx & 0xffff; | |
385 edi = context.vm.regs.edi & 0xffff; | |
386 edi += (unsigned int)context.vm.regs.ds << 4; | |
387 | |
388 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
389 { | |
390 if (size == 4) | |
391 asm volatile ("std; rep; insl; cld" | |
392 : "=D" (edi), "=c" (ecx) | |
393 : "d" (edx), "0" (edi), "1" (ecx)); | |
394 else if (size == 2) | |
395 asm volatile ("std; rep; insw; cld" | |
396 : "=D" (edi), "=c" (ecx) | |
397 : "d" (edx), "0" (edi), "1" (ecx)); | |
398 else | |
399 asm volatile ("std; rep; insb; cld" | |
400 : "=D" (edi), "=c" (ecx) | |
401 : "d" (edx), "0" (edi), "1" (ecx)); | |
402 } | |
403 else | |
404 { | |
405 if (size == 4) | |
406 asm volatile ("cld; rep; insl" | |
407 : "=D" (edi), "=c" (ecx) | |
408 : "d" (edx), "0" (edi), "1" (ecx)); | |
409 else if (size == 2) | |
410 asm volatile ("cld; rep; insw" | |
411 : "=D" (edi), "=c" (ecx) | |
412 : "d" (edx), "0" (edi), "1" (ecx)); | |
413 else | |
414 asm volatile ("cld; rep; insb" | |
415 : "=D" (edi), "=c" (ecx) | |
416 : "d" (edx), "0" (edi), "1" (ecx)); | |
417 } | |
418 | |
419 edi -= (unsigned int)context.vm.regs.ds << 4; | |
420 | |
421 context.vm.regs.edi &= 0xffff0000; | |
422 context.vm.regs.edi |= edi & 0xffff; | |
423 | |
424 context.vm.regs.ecx &= 0xffff0000; | |
425 context.vm.regs.ecx |= ecx & 0xffff; | |
426 } | |
427 | |
428 static void | |
429 em_outs(int size) | |
430 { | |
431 unsigned int edx, esi; | |
432 | |
433 edx = context.vm.regs.edx & 0xffff; | |
434 esi = context.vm.regs.esi & 0xffff; | |
435 esi += (unsigned int)context.vm.regs.ds << 4; | |
436 | |
437 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
438 { | |
439 if (size == 4) | |
440 asm volatile ("std; outsl; cld" | |
441 : "=S" (esi) : "d" (edx), "0" (esi)); | |
442 else if (size == 2) | |
443 asm volatile ("std; outsw; cld" | |
444 : "=S" (esi) : "d" (edx), "0" (esi)); | |
445 else | |
446 asm volatile ("std; outsb; cld" | |
447 : "=S" (esi) : "d" (edx), "0" (esi)); | |
448 } | |
449 else | |
450 { | |
451 if (size == 4) | |
452 asm volatile ("cld; outsl" | |
453 : "=S" (esi) : "d" (edx), "0" (esi)); | |
454 else if (size == 2) | |
455 asm volatile ("cld; outsw" | |
456 : "=S" (esi) : "d" (edx), "0" (esi)); | |
457 else | |
458 asm volatile ("cld; outsb" | |
459 : "=S" (esi) : "d" (edx), "0" (esi)); | |
460 } | |
461 | |
462 esi -= (unsigned int)context.vm.regs.ds << 4; | |
463 | |
464 context.vm.regs.esi &= 0xffff0000; | |
465 context.vm.regs.esi |= esi & 0xffff; | |
466 } | |
467 | |
468 static void | |
469 em_rep_outs(int size) | |
470 { | |
471 unsigned int ecx, edx, esi; | |
472 | |
473 ecx = context.vm.regs.ecx & 0xffff; | |
474 edx = context.vm.regs.edx & 0xffff; | |
475 esi = context.vm.regs.esi & 0xffff; | |
476 esi += (unsigned int)context.vm.regs.ds << 4; | |
477 | |
478 if (context.vm.regs.eflags & DIRECTION_FLAG) | |
479 { | |
480 if (size == 4) | |
481 asm volatile ("std; rep; outsl; cld" | |
482 : "=S" (esi), "=c" (ecx) | |
483 : "d" (edx), "0" (esi), "1" (ecx)); | |
484 else if (size == 2) | |
485 asm volatile ("std; rep; outsw; cld" | |
486 : "=S" (esi), "=c" (ecx) | |
487 : "d" (edx), "0" (esi), "1" (ecx)); | |
488 else | |
489 asm volatile ("std; rep; outsb; cld" | |
490 : "=S" (esi), "=c" (ecx) | |
491 : "d" (edx), "0" (esi), "1" (ecx)); | |
492 } | |
493 else | |
494 { | |
495 if (size == 4) | |
496 asm volatile ("cld; rep; outsl" | |
497 : "=S" (esi), "=c" (ecx) | |
498 : "d" (edx), "0" (esi), "1" (ecx)); | |
499 else if (size == 2) | |
500 asm volatile ("cld; rep; outsw" | |
501 : "=S" (esi), "=c" (ecx) | |
502 : "d" (edx), "0" (esi), "1" (ecx)); | |
503 else | |
504 asm volatile ("cld; rep; outsb" | |
505 : "=S" (esi), "=c" (ecx) | |
506 : "d" (edx), "0" (esi), "1" (ecx)); | |
507 } | |
508 | |
509 esi -= (unsigned int)context.vm.regs.ds << 4; | |
510 | |
511 context.vm.regs.esi &= 0xffff0000; | |
512 context.vm.regs.esi |= esi & 0xffff; | |
513 | |
514 context.vm.regs.ecx &= 0xffff0000; | |
515 context.vm.regs.ecx |= ecx & 0xffff; | |
516 } | |
517 | |
518 static void | |
519 em_inbl(unsigned char literal) | |
520 { | |
521 context.vm.regs.eax = inb(literal) & 0xff; | |
522 } | |
523 | |
524 static void | |
525 em_inb(void) | |
526 { | |
527 asm volatile ("inb (%w1), %b0" | |
528 : "=a" (context.vm.regs.eax) | |
529 : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); | |
530 } | |
531 | |
532 static void | |
533 em_inw(void) | |
534 { | |
535 asm volatile ("inw (%w1), %w0" | |
536 : "=a" (context.vm.regs.eax) | |
537 : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax)); | |
538 } | |
539 | |
540 static void | |
541 em_inl(void) | |
542 { | |
543 asm volatile ("inl (%w1), %0" | |
544 : "=a" (context.vm.regs.eax) | |
545 : "d" (context.vm.regs.edx)); | |
546 } | |
547 | |
548 static void | |
549 em_outbl(unsigned char literal) | |
550 { | |
551 outb(context.vm.regs.eax & 0xff, literal); | |
552 } | |
553 | |
554 static void | |
555 em_outb(void) | |
556 { | |
557 asm volatile ("outb %b0, (%w1)" | |
558 : : "a" (context.vm.regs.eax), | |
559 "d" (context.vm.regs.edx)); | |
560 } | |
561 | |
562 static void | |
563 em_outw(void) | |
564 { | |
565 asm volatile ("outw %w0, (%w1)" | |
566 : : "a" (context.vm.regs.eax), | |
567 "d" (context.vm.regs.edx)); | |
568 } | |
569 | |
570 static void | |
571 em_outl(void) | |
572 { | |
573 asm volatile ("outl %0, (%w1)" | |
574 : : "a" (context.vm.regs.eax), | |
575 "d" (context.vm.regs.edx)); | |
576 } | |
577 | |
578 static int | |
579 emulate(void) | |
580 { | |
581 unsigned char *insn; | |
582 struct | |
583 { | |
584 unsigned int size : 1; | |
585 unsigned int rep : 1; | |
586 } prefix = { 0, 0 }; | |
587 int i = 0; | |
588 | |
589 insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4); | |
590 insn += context.vm.regs.eip; | |
591 | |
592 while (1) | |
593 { | |
594 if (insn[i] == 0x66) | |
595 { | |
596 prefix.size = 1 - prefix.size; | |
597 i++; | |
598 } | |
599 else if (insn[i] == 0xf3) | |
600 { | |
601 prefix.rep = 1; | |
602 i++; | |
603 } | |
604 else if (insn[i] == 0xf0 || insn[i] == 0xf2 | |
605 || insn[i] == 0x26 || insn[i] == 0x2e | |
606 || insn[i] == 0x36 || insn[i] == 0x3e | |
607 || insn[i] == 0x64 || insn[i] == 0x65 | |
608 || insn[i] == 0x67) | |
609 { | |
610 /* these prefixes are just ignored */ | |
611 i++; | |
612 } | |
613 else if (insn[i] == 0x6c) | |
614 { | |
615 if (prefix.rep) | |
616 em_rep_ins(1); | |
617 else | |
618 em_ins(1); | |
619 i++; | |
620 break; | |
621 } | |
622 else if (insn[i] == 0x6d) | |
623 { | |
624 if (prefix.rep) | |
625 { | |
626 if (prefix.size) | |
627 em_rep_ins(4); | |
628 else | |
629 em_rep_ins(2); | |
630 } | |
631 else | |
632 { | |
633 if (prefix.size) | |
634 em_ins(4); | |
635 else | |
636 em_ins(2); | |
637 } | |
638 i++; | |
639 break; | |
640 } | |
641 else if (insn[i] == 0x6e) | |
642 { | |
643 if (prefix.rep) | |
644 em_rep_outs(1); | |
645 else | |
646 em_outs(1); | |
647 i++; | |
648 break; | |
649 } | |
650 else if (insn[i] == 0x6f) | |
651 { | |
652 if (prefix.rep) | |
653 { | |
654 if (prefix.size) | |
655 em_rep_outs(4); | |
656 else | |
657 em_rep_outs(2); | |
658 } | |
659 else | |
660 { | |
661 if (prefix.size) | |
662 em_outs(4); | |
663 else | |
664 em_outs(2); | |
665 } | |
666 i++; | |
667 break; | |
668 } | |
669 else if (insn[i] == 0xe4) | |
670 { | |
671 em_inbl(insn[i + 1]); | |
672 i += 2; | |
673 break; | |
674 } | |
675 else if (insn[i] == 0xe6) | |
676 { | |
677 em_outbl(insn[i + 1]); | |
678 i += 2; | |
679 break; | |
680 } | |
681 else if (insn[i] == 0xec) | |
682 { | |
683 em_inb(); | |
684 i++; | |
685 break; | |
686 } | |
687 else if (insn[i] == 0xed) | |
688 { | |
689 if (prefix.size) | |
690 em_inl(); | |
691 else | |
692 em_inw(); | |
693 i++; | |
694 break; | |
695 } | |
696 else if (insn[i] == 0xee) | |
697 { | |
698 em_outb(); | |
699 i++; | |
700 break; | |
701 } | |
702 else if (insn[i] == 0xef) | |
703 { | |
704 if (prefix.size) | |
705 em_outl(); | |
706 else | |
707 em_outw(); | |
708 | |
709 i++; | |
710 break; | |
711 } | |
712 else | |
713 return 0; | |
714 } | |
715 | |
716 context.vm.regs.eip += i; | |
717 return 1; | |
718 } | |
719 | |
720 | |
721 /* | |
722 I don't know how to make sure I get the right vm86() from libc. | |
723 The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) | |
724 which should be declared as "int vm86(struct vm86_struct *);" in | |
725 <sys/vm86.h>. | |
726 | |
727 This just does syscall 113 with inline asm, which should work | |
728 for both libc's (I hope). | |
729 */ | |
730 #if !defined(USE_LIBC_VM86) | |
731 static int | |
732 lrmi_vm86(struct vm86_struct *vm) | |
733 { | |
734 int r; | |
735 #ifdef __PIC__ | |
736 asm volatile ( | |
737 "pushl %%ebx\n\t" | |
738 "movl %2, %%ebx\n\t" | |
739 "int $0x80\n\t" | |
740 "popl %%ebx" | |
741 : "=a" (r) | |
742 : "0" (113), "r" (vm)); | |
743 #else | |
744 asm volatile ( | |
745 "int $0x80" | |
746 : "=a" (r) | |
747 : "0" (113), "b" (vm)); | |
748 #endif | |
749 return r; | |
750 } | |
751 #else | |
752 #define lrmi_vm86 vm86 | |
753 #endif | |
754 | |
755 | |
756 static void | |
757 debug_info(int vret) | |
758 { | |
759 int i; | |
760 unsigned char *p; | |
761 | |
762 fputs("vm86() failed\n", stderr); | |
763 fprintf(stderr, "return = 0x%x\n", vret); | |
764 fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax); | |
765 fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx); | |
766 fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx); | |
767 fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx); | |
768 fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi); | |
769 fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi); | |
770 fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp); | |
771 fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip); | |
772 fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs); | |
773 fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp); | |
774 fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss); | |
775 fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds); | |
776 fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es); | |
777 fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs); | |
778 fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs); | |
779 fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags); | |
780 | |
781 fputs("cs:ip = [ ", stderr); | |
782 | |
783 p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff)); | |
784 | |
785 for (i = 0; i < 16; ++i) | |
786 fprintf(stderr, "%02x ", (unsigned int)p[i]); | |
787 | |
788 fputs("]\n", stderr); | |
789 } | |
790 | |
791 | |
792 static int | |
793 run_vm86(void) | |
794 { | |
795 unsigned int vret; | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
796 sigset_t allsigs, cursigs; |
11519
830c5c1800bc
Save fs before calling vm86, this might eleminate bugs (if there were any) in cooperation of using vesa with win32 dlls. Patch by Peter Kosinar <goober@ksp.sk>
alex
parents:
11455
diff
changeset
|
797 unsigned long oldgs, oldfs; |
2212 | 798 |
799 while (1) | |
800 { | |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
801 sigfillset(&allsigs); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
802 sigprocmask(SIG_SETMASK, &allsigs, &cursigs); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
803 asm volatile ("movl %%gs, %0" : "=g" (oldgs)); |
11519
830c5c1800bc
Save fs before calling vm86, this might eleminate bugs (if there were any) in cooperation of using vesa with win32 dlls. Patch by Peter Kosinar <goober@ksp.sk>
alex
parents:
11455
diff
changeset
|
804 asm volatile ("movl %%fs, %0" : "=g" (oldfs)); |
2212 | 805 vret = lrmi_vm86(&context.vm); |
11519
830c5c1800bc
Save fs before calling vm86, this might eleminate bugs (if there were any) in cooperation of using vesa with win32 dlls. Patch by Peter Kosinar <goober@ksp.sk>
alex
parents:
11455
diff
changeset
|
806 asm volatile ("movl %0, %%fs" :: "g" (oldfs)); |
11434
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
807 asm volatile ("movl %0, %%gs" :: "g" (oldgs)); |
5084f09ba20e
Fix pthread & lrmi segfault issue. ("Oleg I. Vdovikin" <vdovikin@jscc.ru>)
ranma
parents:
10857
diff
changeset
|
808 sigprocmask(SIG_SETMASK, &cursigs, NULL); |
2212 | 809 |
810 if (VM86_TYPE(vret) == VM86_INTx) | |
811 { | |
812 unsigned int v = VM86_ARG(vret); | |
813 | |
814 if (v == RETURN_TO_32_INT) | |
815 return 1; | |
816 | |
817 pushw(context.vm.regs.eflags); | |
818 pushw(context.vm.regs.cs); | |
819 pushw(context.vm.regs.eip); | |
820 | |
821 context.vm.regs.cs = get_int_seg(v); | |
822 context.vm.regs.eip = get_int_off(v); | |
823 context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK); | |
824 | |
825 continue; | |
826 } | |
827 | |
828 if (VM86_TYPE(vret) != VM86_UNKNOWN) | |
829 break; | |
830 | |
831 if (!emulate()) | |
832 break; | |
833 } | |
834 | |
835 #ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT | |
836 debug_info(vret); | |
837 #endif | |
838 return 0; | |
839 } | |
840 | |
841 | |
842 int | |
843 LRMI_call(struct LRMI_regs *r) | |
844 { | |
845 unsigned int vret; | |
846 | |
847 memset(&context.vm.regs, 0, sizeof(context.vm.regs)); | |
848 | |
849 set_regs(r); | |
850 | |
851 context.vm.regs.cs = r->cs; | |
852 context.vm.regs.eip = r->ip; | |
853 | |
854 if (r->ss == 0 && r->sp == 0) | |
855 { | |
856 context.vm.regs.ss = context.stack_seg; | |
857 context.vm.regs.esp = context.stack_off; | |
858 } | |
859 else | |
860 { | |
861 context.vm.regs.ss = r->ss; | |
862 context.vm.regs.esp = r->sp; | |
863 } | |
864 | |
865 pushw(context.ret_seg); | |
866 pushw(context.ret_off); | |
867 | |
868 vret = run_vm86(); | |
869 | |
870 get_regs(r); | |
871 | |
872 return vret; | |
873 } | |
874 | |
875 | |
876 int | |
877 LRMI_int(int i, struct LRMI_regs *r) | |
878 { | |
879 unsigned int vret; | |
880 unsigned int seg, off; | |
881 | |
882 seg = get_int_seg(i); | |
883 off = get_int_off(i); | |
884 | |
885 /* | |
886 If the interrupt is in regular memory, it's probably | |
887 still pointing at a dos TSR (which is now gone). | |
888 */ | |
889 if (seg < 0xa000 || (seg << 4) + off >= 0x100000) | |
890 { | |
891 #ifdef ORIGINAL_LRMI_CODE_THAT_GOT_IFDEFED_OUT | |
892 fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off); | |
893 #endif | |
894 return 0; | |
895 } | |
896 | |
897 memset(&context.vm.regs, 0, sizeof(context.vm.regs)); | |
898 | |
899 set_regs(r); | |
900 | |
901 context.vm.regs.cs = seg; | |
902 context.vm.regs.eip = off; | |
903 | |
904 if (r->ss == 0 && r->sp == 0) | |
905 { | |
906 context.vm.regs.ss = context.stack_seg; | |
907 context.vm.regs.esp = context.stack_off; | |
908 } | |
909 else | |
910 { | |
911 context.vm.regs.ss = r->ss; | |
912 context.vm.regs.esp = r->sp; | |
913 } | |
914 | |
915 pushw(DEFAULT_VM86_FLAGS); | |
916 pushw(context.ret_seg); | |
917 pushw(context.ret_off); | |
918 | |
919 vret = run_vm86(); | |
920 | |
921 get_regs(r); | |
922 | |
923 return vret; | |
924 } | |
925 | |
11455 | 926 #endif |