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