summaryrefslogtreecommitdiffstats
path: root/osdep
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-02-09 20:18:23 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-02-09 20:18:23 +0000
commit7ff83a71810233276517bc497e93ac15267bc830 (patch)
tree23e697fbbe48eae893b8c28c383199bc6ca000ad /osdep
parentc98692a0bf56e79781ae7ca2a1e358f518838dac (diff)
downloadmpv-7ff83a71810233276517bc497e93ac15267bc830.tar.bz2
mpv-7ff83a71810233276517bc497e93ac15267bc830.tar.xz
linux->osdep
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9381 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'osdep')
-rw-r--r--osdep/.cvsignore1
-rw-r--r--osdep/Makefile46
-rw-r--r--osdep/getch2.c256
-rw-r--r--osdep/getch2.h20
-rw-r--r--osdep/keycodes.h36
-rw-r--r--osdep/lrmi.c912
-rw-r--r--osdep/lrmi.h86
-rw-r--r--osdep/scandir.c134
-rw-r--r--osdep/shmem.c107
-rw-r--r--osdep/shmem.h4
-rw-r--r--osdep/strsep.c42
-rw-r--r--osdep/timer-lx.c67
-rw-r--r--osdep/timer.h17
-rw-r--r--osdep/vbelib.c730
-rw-r--r--osdep/vbelib.h227
-rw-r--r--osdep/vsscanf.c20
16 files changed, 2705 insertions, 0 deletions
diff --git a/osdep/.cvsignore b/osdep/.cvsignore
new file mode 100644
index 0000000000..4671378aef
--- /dev/null
+++ b/osdep/.cvsignore
@@ -0,0 +1 @@
+.depend
diff --git a/osdep/Makefile b/osdep/Makefile
new file mode 100644
index 0000000000..f42b913d07
--- /dev/null
+++ b/osdep/Makefile
@@ -0,0 +1,46 @@
+
+include ../config.mak
+
+LIBNAME = libosdep.a
+
+SRCS=getch2.c timer-lx.c shmem.c strsep.c vsscanf.c scandir.c # timer.c
+OBJS=$(SRCS:.c=.o)
+
+ifeq ($(TARGET_ARCH_X86),yes)
+ifeq ($(TARGET_OS),Linux)
+SRCS += lrmi.c vbelib.c
+endif
+endif
+
+CFLAGS = $(OPTFLAGS) -I. -I.. $(EXTRA_INC)
+# -I/usr/X11R6/include/
+
+.SUFFIXES: .c .o
+
+# .PHONY: all clean
+
+.c.o:
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(LIBNAME): $(OBJS)
+ $(AR) r $(LIBNAME) $(OBJS)
+
+all: $(LIBNAME)
+
+clean:
+ rm -f *.o *.a *~
+
+distclean:
+ rm -f Makefile.bak *.o *.a *~ .depend
+
+dep: depend
+
+depend:
+ $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend
+
+#
+# include dependency files if they exist
+#
+ifneq ($(wildcard .depend),)
+include .depend
+endif
diff --git a/osdep/getch2.c b/osdep/getch2.c
new file mode 100644
index 0000000000..dec9b91a0f
--- /dev/null
+++ b/osdep/getch2.c
@@ -0,0 +1,256 @@
+/* GyS-TermIO v2.0 (for GySmail v3) (C) 1999 A'rpi/ESP-team */
+
+#include "../config.h"
+
+//#define USE_TERMCAP
+#ifndef __OS2__
+#define USE_IOCTL
+#endif
+
+#define MAX_KEYS 64
+#define BUF_LEN 256
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef USE_IOCTL
+#include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_SYS_TERMIOS_H
+#include <sys/termios.h>
+#endif
+#endif
+
+#include <unistd.h>
+
+#include "keycodes.h"
+
+#ifdef HAVE_TERMIOS
+static struct termios tio_orig;
+#endif
+static int getch2_len=0;
+static char getch2_buf[BUF_LEN];
+
+int screen_width=80;
+int screen_height=24;
+
+typedef struct {
+ int len;
+ int code;
+ char chars[8];
+} keycode_st;
+static keycode_st getch2_keys[MAX_KEYS];
+static int getch2_key_db=0;
+
+#ifdef USE_TERMCAP
+
+#if 0
+#include <termcap.h>
+#else
+ extern int tgetent (char *BUFFER, char *TERMTYPE);
+ extern int tgetnum (char *NAME);
+ extern int tgetflag (char *NAME);
+ extern char *tgetstr (char *NAME, char **AREA);
+#endif
+
+static char term_buffer[4096];
+static char term_buffer2[4096];
+static char *term_p=term_buffer2;
+
+static void termcap_add(char *id,int code){
+char *p=tgetstr(id,&term_p);
+ if(!p) return;
+ if(getch2_key_db>=MAX_KEYS) return;
+ getch2_keys[getch2_key_db].len=strlen(p);
+ strncpy(getch2_keys[getch2_key_db].chars,p,8);
+ getch2_keys[getch2_key_db].code=code;
+ ++getch2_key_db;
+/* printf("%s=%s\n",id,p); */
+}
+
+static int success=0;
+
+int load_termcap(char *termtype){
+ if(!termtype) termtype=getenv("TERM");
+ if(!termtype) termtype="unknown";
+ success=tgetent(term_buffer, termtype);
+ if(success<0){ printf("Could not access the 'termcap' data base.\n"); return 0; }
+ if(success==0){ printf("Terminal type `%s' is not defined.\n", termtype);return 0;}
+
+ screen_width=tgetnum("co");
+ screen_height=tgetnum("li");
+ if(screen_width<1 || screen_width>255) screen_width=80;
+ if(screen_height<1 || screen_height>255) screen_height=24;
+
+ termcap_add("kP",KEY_PGUP);
+ termcap_add("kN",KEY_PGDWN);
+ termcap_add("kh",KEY_HOME);
+ termcap_add("kH",KEY_END);
+ termcap_add("kI",KEY_INS);
+ termcap_add("kD",KEY_DEL);
+ termcap_add("kb",KEY_BS);
+ termcap_add("kl",KEY_LEFT);
+ termcap_add("kd",KEY_DOWN);
+ termcap_add("ku",KEY_UP);
+ termcap_add("kr",KEY_RIGHT);
+ termcap_add("k0",KEY_F+0);
+ termcap_add("k1",KEY_F+1);
+ termcap_add("k2",KEY_F+2);
+ termcap_add("k3",KEY_F+3);
+ termcap_add("k4",KEY_F+4);
+ termcap_add("k5",KEY_F+5);
+ termcap_add("k6",KEY_F+6);
+ termcap_add("k7",KEY_F+7);
+ termcap_add("k8",KEY_F+8);
+ termcap_add("k9",KEY_F+9);
+ termcap_add("k;",KEY_F+10);
+ return getch2_key_db;
+}
+
+#endif
+
+void get_screen_size(){
+#ifdef USE_IOCTL
+ struct winsize ws;
+ if (ioctl(0, TIOCGWINSZ, &ws) < 0 || !ws.ws_row || !ws.ws_col) return;
+/* printf("Using IOCTL\n"); */
+ screen_width=ws.ws_col;
+ screen_height=ws.ws_row;
+#endif
+}
+
+int getch2(int time){
+ int len=0;
+ int code=0;
+ int i=0;
+
+ while(!getch2_len || (getch2_len==1 && getch2_buf[0]==27)){
+ fd_set rfds;
+ struct timeval tv;
+ int retval;
+ /* Watch stdin (fd 0) to see when it has input. */
+ FD_ZERO(&rfds); FD_SET(0,&rfds);
+ /* Wait up to 'time' microseconds. */
+ tv.tv_sec=time/1000; tv.tv_usec = (time%1000)*1000;
+ retval=select(1, &rfds, NULL, NULL, &tv);
+ if(retval<=0) return -1;
+ /* Data is available now. */
+ retval=read(0,&getch2_buf[getch2_len],BUF_LEN-getch2_len);
+ if(retval<1) return -1;
+ getch2_len+=retval;
+ }
+
+ /* First find in the TERMCAP database: */
+ for(i=0;i<getch2_key_db;i++){
+ if((len=getch2_keys[i].len)<=getch2_len)
+ if(memcmp(getch2_keys[i].chars,getch2_buf,len)==0){
+ code=getch2_keys[i].code; goto found;
+ }
+ }
+ len=1;code=getch2_buf[0];
+ /* Check the well-known codes... */
+ if(code!=27){
+ if(code=='A'-64){ code=KEY_HOME; goto found;}
+ if(code=='E'-64){ code=KEY_END; goto found;}
+ if(code=='D'-64){ code=KEY_DEL; goto found;}
+ if(code=='H'-64){ code=KEY_BS; goto found;}
+ if(code=='U'-64){ code=KEY_PGUP; goto found;}
+ if(code=='V'-64){ code=KEY_PGDWN; goto found;}
+ if(code==8 || code==127){ code=KEY_BS; goto found;}
+ if(code==10 || code==13){
+ if(getch2_len>1){
+ int c=getch2_buf[1];
+ if(c==10 || c==13) if(c!=code) len=2;
+ }
+ code=KEY_ENTER;
+ goto found;
+ }
+ } else if(getch2_len>1){
+ int c=getch2_buf[1];
+ if(c==27){ code=KEY_ESC; len=2; goto found;}
+ if(c>='0' && c<='9'){ code=c-'0'+KEY_F; len=2; goto found;}
+ if(getch2_len>=4 && c=='[' && getch2_buf[2]=='['){
+ int c=getch2_buf[3];
+ if(c>='A' && c<'A'+12){ code=KEY_F+1+c-'A';len=4;goto found;}
+ }
+ if(c=='[' || c=='O') if(getch2_len>=3){
+ int c=getch2_buf[2];
+ static short int ctable[]={ KEY_UP,KEY_DOWN,KEY_RIGHT,KEY_LEFT,0,
+ KEY_END,KEY_PGDWN,KEY_HOME,KEY_PGUP,0,0,KEY_INS,0,0,0,
+ KEY_F+1,KEY_F+2,KEY_F+3,KEY_F+4};
+ if(c>='A' && c<='S')
+ if(ctable[c-'A']){ code=ctable[c-'A']; len=3; goto found;}
+ }
+ if(getch2_len>=4 && c=='[' && getch2_buf[3]=='~'){
+ int c=getch2_buf[2];
+ int ctable[8]={KEY_HOME,KEY_INS,KEY_DEL,KEY_END,KEY_PGUP,KEY_PGDWN,KEY_HOME,KEY_END};
+ if(c>='1' && c<='8'){ code=ctable[c-'1']; len=4; goto found;}
+ }
+ if(getch2_len>=5 && c=='[' && getch2_buf[4]=='~'){
+ int i=getch2_buf[2]-'0';
+ int j=getch2_buf[3]-'0';
+ if(i>=0 && i<=9 && j>=0 && j<=9){
+ static short int ftable[20]={
+ 11,12,13,14,15, 17,18,19,20,21,
+ 23,24,25,26,28, 29,31,32,33,34 };
+ int a=i*10+j;
+ for(i=0;i<20;i++) if(ftable[i]==a){ code=KEY_F+1+i;len=5;goto found;}
+ }
+ }
+ }
+found:
+ if((getch2_len-=len)>0){
+ int i;
+ for(i=0;i<getch2_len;i++) getch2_buf[i]=getch2_buf[len+i];
+ }
+ return code;
+}
+
+static int getch2_status=0;
+
+void getch2_enable(){
+#ifdef HAVE_TERMIOS
+struct termios tio_new;
+#if defined(__NetBSD__) || defined(__svr4__) || defined(__CYGWIN__) || defined(__OS2__) || defined(__GNU__)
+ tcgetattr(0,&tio_orig);
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)
+ ioctl(0,TIOCGETA,&tio_orig);
+#else
+ ioctl(0,TCGETS,&tio_orig);
+#endif
+ tio_new=tio_orig;
+ tio_new.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
+ tio_new.c_cc[VMIN] = 1;
+ tio_new.c_cc[VTIME] = 0;
+#if defined(__NetBSD__) || defined(__svr4__) || defined(__CYGWIN__) || defined(__OS2__) || defined(__GNU__)
+ tcsetattr(0,TCSANOW,&tio_new);
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)
+ ioctl(0,TIOCSETA,&tio_new);
+#else
+ ioctl(0,TCSETS,&tio_new);
+#endif
+#endif
+ getch2_status=1;
+}
+
+void getch2_disable(){
+ if(!getch2_status) return; // already disabled / never enabled
+#ifdef HAVE_TERMIOS
+#if defined(__NetBSD__) || defined(__svr4__) || defined(__CYGWIN__) || defined(__OS2__) || defined(__GNU__)
+ tcsetattr(0,TCSANOW,&tio_orig);
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)
+ ioctl(0,TIOCSETA,&tio_orig);
+#else
+ ioctl(0,TCSETS,&tio_orig);
+#endif
+#endif
+ getch2_status=0;
+}
+
diff --git a/osdep/getch2.h b/osdep/getch2.h
new file mode 100644
index 0000000000..016de5ae9e
--- /dev/null
+++ b/osdep/getch2.h
@@ -0,0 +1,20 @@
+/* GyS-TermIO v2.0 (for GySmail v3) (C) 1999 A'rpi/ESP-team */
+/* a very small replacement of ncurses library */
+
+/* Screen size. Initialized by load_termcap() and get_screen_size() */
+extern int screen_width;
+extern int screen_height;
+
+/* Get screen-size using IOCTL call. */
+extern void get_screen_size();
+
+/* Load key definitions from the TERMCAP database. 'termtype' can be NULL */
+extern int load_termcap(char *termtype);
+
+/* Enable and disable STDIN line-buffering */
+extern void getch2_enable();
+extern void getch2_disable();
+
+/* Read a character or a special key code (see keycodes.h) */
+extern int getch2(int halfdelay_time);
+
diff --git a/osdep/keycodes.h b/osdep/keycodes.h
new file mode 100644
index 0000000000..e0b963535c
--- /dev/null
+++ b/osdep/keycodes.h
@@ -0,0 +1,36 @@
+/* KEY code definitions for GyS-TermIO v2.0 (C) 1999 A'rpi/ESP-team */
+
+#define KEY_ENTER 13
+#define KEY_TAB 9
+
+#define KEY_BASE 0x100
+
+/* Function keys */
+#define KEY_F (KEY_BASE+64)
+
+/* Control keys */
+#define KEY_CTRL (KEY_BASE)
+#define KEY_BACKSPACE (KEY_CTRL+0)
+#define KEY_DELETE (KEY_CTRL+1)
+#define KEY_INSERT (KEY_CTRL+2)
+#define KEY_HOME (KEY_CTRL+3)
+#define KEY_END (KEY_CTRL+4)
+#define KEY_PAGE_UP (KEY_CTRL+5)
+#define KEY_PAGE_DOWN (KEY_CTRL+6)
+#define KEY_ESC (KEY_CTRL+7)
+
+/* Control keys short name */
+#define KEY_BS KEY_BACKSPACE
+#define KEY_DEL KEY_DELETE
+#define KEY_INS KEY_INSERT
+#define KEY_PGUP KEY_PAGE_UP
+#define KEY_PGDOWN KEY_PAGE_DOWN
+#define KEY_PGDWN KEY_PAGE_DOWN
+
+/* Cursor movement */
+#define KEY_CRSR (KEY_BASE+16)
+#define KEY_RIGHT (KEY_CRSR+0)
+#define KEY_LEFT (KEY_CRSR+1)
+#define KEY_DOWN (KEY_CRSR+2)
+#define KEY_UP (KEY_CRSR+3)
+
diff --git a/osdep/lrmi.c b/osdep/lrmi.c
new file mode 100644
index 0000000000..ce77a6767a
--- /dev/null
+++ b/osdep/lrmi.c
@@ -0,0 +1,912 @@
+/*
+Linux Real Mode Interface - A library of DPMI-like functions for Linux.
+
+Copyright (C) 1998 by Josh Vanderhoof
+
+You are free to distribute and modify this file, as long as you
+do not remove this copyright notice and clearly label modified
+versions as being modified.
+
+This software has NO WARRANTY. Use it at your own risk.
+Original location: http://cvs.debian.org/lrmi/
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/io.h>
+#include <asm/vm86.h>
+
+#ifdef USE_LIBC_VM86
+#include <sys/vm86.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "lrmi.h"
+
+#define REAL_MEM_BASE ((void *)0x10000)
+#define REAL_MEM_SIZE 0x10000
+#define REAL_MEM_BLOCKS 0x100
+
+struct mem_block
+ {
+ unsigned int size : 20;
+ unsigned int free : 1;
+ };
+
+static struct
+ {
+ int ready;
+ int count;
+ struct mem_block blocks[REAL_MEM_BLOCKS];
+ } mem_info = { 0 };
+
+static int
+real_mem_init(void)
+ {
+ void *m;
+ int fd_zero;
+
+ if (mem_info.ready)
+ return 1;
+
+ fd_zero = open("/dev/zero", O_RDONLY);
+ if (fd_zero == -1)
+ {
+ perror("open /dev/zero");
+ return 0;
+ }
+
+ m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
+
+ if (m == (void *)-1)
+ {
+ perror("mmap /dev/zero");
+ close(fd_zero);
+ return 0;
+ }
+
+ mem_info.ready = 1;
+ mem_info.count = 1;
+ mem_info.blocks[0].size = REAL_MEM_SIZE;
+ mem_info.blocks[0].free = 1;
+
+ return 1;
+ }
+
+
+static void
+insert_block(int i)
+ {
+ memmove(
+ mem_info.blocks + i + 1,
+ mem_info.blocks + i,
+ (mem_info.count - i) * sizeof(struct mem_block));
+
+ mem_info.count++;
+ }
+
+static void
+delete_block(int i)
+ {
+ mem_info.count--;
+
+ memmove(
+ mem_info.blocks + i,
+ mem_info.blocks + i + 1,
+ (mem_info.count - i) * sizeof(struct mem_block));
+ }
+
+void *
+LRMI_alloc_real(int size)
+ {
+ int i;
+ char *r = (char *)REAL_MEM_BASE;
+
+ if (!mem_info.ready)
+ return NULL;
+
+ if (mem_info.count == REAL_MEM_BLOCKS)
+ return NULL;
+
+ size = (size + 15) & ~15;
+
+ for (i = 0; i < mem_info.count; i++)
+ {
+ if (mem_info.blocks[i].free && size < mem_info.blocks[i].size)
+ {
+ insert_block(i);
+
+ mem_info.blocks[i].size = size;
+ mem_info.blocks[i].free = 0;
+ mem_info.blocks[i + 1].size -= size;
+
+ return (void *)r;
+ }
+
+ r += mem_info.blocks[i].size;
+ }
+
+ return NULL;
+ }
+
+
+void
+LRMI_free_real(void *m)
+ {
+ int i;
+ char *r = (char *)REAL_MEM_BASE;
+
+ if (!mem_info.ready)
+ return;
+
+ i = 0;
+ while (m != (void *)r)
+ {
+ r += mem_info.blocks[i].size;
+ i++;
+ if (i == mem_info.count)
+ return;
+ }
+
+ mem_info.blocks[i].free = 1;
+
+ if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free)
+ {
+ mem_info.blocks[i].size += mem_info.blocks[i + 1].size;
+ delete_block(i + 1);
+ }
+
+ if (i - 1 >= 0 && mem_info.blocks[i - 1].free)
+ {
+ mem_info.blocks[i - 1].size += mem_info.blocks[i].size;
+ delete_block(i);
+ }
+ }
+
+
+#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
+#define DEFAULT_STACK_SIZE 0x1000
+#define RETURN_TO_32_INT 255
+
+static struct
+ {
+ int ready;
+ unsigned short ret_seg, ret_off;
+ unsigned short stack_seg, stack_off;
+ struct vm86_struct vm;
+ } context = { 0 };
+
+
+static inline void
+set_bit(unsigned int bit, void *array)
+ {
+ unsigned char *a = array;
+
+ a[bit / 8] |= (1 << (bit % 8));
+ }
+
+
+static inline unsigned int
+get_int_seg(int i)
+ {
+ return *(unsigned short *)(i * 4 + 2);
+ }
+
+
+static inline unsigned int
+get_int_off(int i)
+ {
+ return *(unsigned short *)(i * 4);
+ }
+
+
+static inline void
+pushw(unsigned short i)
+ {
+ struct vm86_regs *r = &context.vm.regs;
+ r->esp -= 2;
+ *(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i;
+ }
+
+
+int
+LRMI_init(void)
+ {
+ void *m;
+ int fd_mem;
+
+ if (context.ready)
+ return 1;
+
+ if (!real_mem_init())
+ return 0;
+
+ /*
+ Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502)
+ and the ROM (0xa0000 - 0x100000)
+ */
+ fd_mem = open("/dev/mem", O_RDWR);
+
+ if (fd_mem == -1)
+ {
+ perror("open /dev/mem");
+ return 0;
+ }
+
+ m = mmap((void *)0, 0x502,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, fd_mem, 0);
+
+ if (m == (void *)-1)
+ {
+ perror("mmap /dev/mem");
+ return 0;
+ }
+
+ m = mmap((void *)0xa0000, 0x100000 - 0xa0000,
+ PROT_READ | PROT_WRITE,
+ MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000);
+
+ if (m == (void *)-1)
+ {
+ perror("mmap /dev/mem");
+ return 0;
+ }
+
+
+ /*
+ Allocate a stack
+ */
+ m = LRMI_alloc_real(DEFAULT_STACK_SIZE);
+
+ context.stack_seg = (unsigned int)m >> 4;
+ context.stack_off = DEFAULT_STACK_SIZE;
+
+ /*
+ Allocate the return to 32 bit routine
+ */
+ m = LRMI_alloc_real(2);
+
+ context.ret_seg = (unsigned int)m >> 4;
+ context.ret_off = (unsigned int)m & 0xf;
+
+ ((unsigned char *)m)[0] = 0xcd; /* int opcode */
+ ((unsigned char *)m)[1] = RETURN_TO_32_INT;
+
+ memset(&context.vm, 0, sizeof(context.vm));
+
+ /*
+ Enable kernel emulation of all ints except RETURN_TO_32_INT
+ */
+ memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored));
+ set_bit(RETURN_TO_32_INT, &context.vm.int_revectored);
+
+ context.ready = 1;
+
+ return 1;
+ }
+
+
+static void
+set_regs(struct LRMI_regs *r)
+ {
+ context.vm.regs.edi = r->edi;
+ context.vm.regs.esi = r->esi;
+ context.vm.regs.ebp = r->ebp;
+ context.vm.regs.ebx = r->ebx;
+ context.vm.regs.edx = r->edx;
+ context.vm.regs.ecx = r->ecx;
+ context.vm.regs.eax = r->eax;
+ context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
+ context.vm.regs.es = r->es;
+ context.vm.regs.ds = r->ds;
+ context.vm.regs.fs = r->fs;
+ context.vm.regs.gs = r->gs;
+ }
+
+
+static void
+get_regs(struct LRMI_regs *r)
+ {
+ r->edi = context.vm.regs.edi;
+ r->esi = context.vm.regs.esi;
+ r->ebp = context.vm.regs.ebp;
+ r->ebx = context.vm.regs.ebx;
+ r->edx = context.vm.regs.edx;
+ r->ecx = context.vm.regs.ecx;
+ r->eax = context.vm.regs.eax;
+ r->flags = context.vm.regs.eflags;
+ r->es = context.vm.regs.es;
+ r->ds = context.vm.regs.ds;
+ r->fs = context.vm.regs.fs;
+ r->gs = context.vm.regs.gs;
+ }
+
+#define DIRECTION_FLAG (1 << 10)
+
+static void
+em_ins(int size)
+ {
+ unsigned int edx, edi;
+
+ edx = context.vm.regs.edx & 0xffff;
+ edi = context.vm.regs.edi & 0xffff;
+ edi += (unsigned int)context.vm.regs.ds << 4;
+
+ if (context.vm.regs.eflags & DIRECTION_FLAG)
+ {
+ if (size == 4)
+ asm volatile ("std; insl; cld"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ else if (size == 2)
+ asm volatile ("std; insw; cld"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ else
+ asm volatile ("std; insb; cld"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ }
+ else
+ {
+ if (size == 4)
+ asm volatile ("cld; insl"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ else if (size == 2)
+ asm volatile ("cld; insw"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ else
+ asm volatile ("cld; insb"
+ : "=D" (edi) : "d" (edx), "0" (edi));
+ }
+
+ edi -= (unsigned int)context.vm.regs.ds << 4;
+
+ context.vm.regs.edi &= 0xffff0000;
+ context.vm.regs.edi |= edi & 0xffff;
+ }
+
+static void
+em_rep_ins(int size)
+ {
+ unsigned int ecx, edx, edi;
+
+ ecx = context.vm.regs.ecx & 0xffff;
+ edx = context.vm.regs.edx & 0xffff;
+ edi = context.vm.regs.edi & 0xffff;
+ edi += (unsigned int)context.vm.regs.ds << 4;
+
+ if (context.vm.regs.eflags & DIRECTION_FLAG)
+ {
+ if (size == 4)
+ asm volatile ("std; rep; insl; cld"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ else if (size == 2)
+ asm volatile ("std; rep; insw; cld"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ else
+ asm volatile ("std; rep; insb; cld"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ }
+ else
+ {
+ if (size == 4)
+ asm volatile ("cld; rep; insl"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ else if (size == 2)
+ asm volatile ("cld; rep; insw"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ else
+ asm volatile ("cld; rep; insb"
+ : "=D" (edi), "=c" (ecx)
+ : "d" (edx), "0" (edi), "1" (ecx));
+ }
+
+ edi -= (unsigned int)context.vm.regs.ds << 4;
+
+ context.vm.regs.edi &= 0xffff0000;
+ context.vm.regs.edi |= edi & 0xffff;
+
+ context.vm.regs.ecx &= 0xffff0000;
+ context.vm.regs.ecx |= ecx & 0xffff;
+ }
+
+static void
+em_outs(int size)
+ {
+ unsigned int edx, esi;
+
+ edx = context.vm.regs.edx & 0xffff;
+ esi = context.vm.regs.esi & 0xffff;
+ esi += (unsigned int)context.vm.regs.ds << 4;
+
+ if (context.vm.regs.eflags & DIRECTION_FLAG)
+ {
+ if (size == 4)
+ asm volatile ("std; outsl; cld"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ else if (size == 2)
+ asm volatile ("std; outsw; cld"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ else
+ asm volatile ("std; outsb; cld"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ }
+ else
+ {
+ if (size == 4)
+ asm volatile ("cld; outsl"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ else if (size == 2)
+ asm volatile ("cld; outsw"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ else
+ asm volatile ("cld; outsb"
+ : "=S" (esi) : "d" (edx), "0" (esi));
+ }
+
+ esi -= (unsigned int)context.vm.regs.ds << 4;
+
+ context.vm.regs.esi &= 0xffff0000;
+ context.vm.regs.esi |= esi & 0xffff;
+ }
+
+static void
+em_rep_outs(int size)
+ {
+ unsigned int ecx, edx, esi;
+
+ ecx = context.vm.regs.ecx & 0xffff;
+ edx = context.vm.regs.edx & 0xffff;
+ esi = context.vm.regs.esi & 0xffff;
+ esi += (unsigned int)context.vm.regs.ds << 4;
+
+ if (context.vm.regs.eflags & DIRECTION_FLAG)
+ {
+ if (size == 4)
+ asm volatile ("std; rep; outsl; cld"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ else if (size == 2)
+ asm volatile ("std; rep; outsw; cld"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ else
+ asm volatile ("std; rep; outsb; cld"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ }
+ else
+ {
+ if (size == 4)
+ asm volatile ("cld; rep; outsl"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ else if (size == 2)
+ asm volatile ("cld; rep; outsw"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ else
+ asm volatile ("cld; rep; outsb"
+ : "=S" (esi), "=c" (ecx)
+ : "d" (edx), "0" (esi), "1" (ecx));
+ }
+
+ esi -= (unsigned int)context.vm.regs.ds << 4;
+
+ context.vm.regs.esi &= 0xffff0000;
+ context.vm.regs.esi |= esi & 0xffff;
+
+ context.vm.regs.ecx &= 0xffff0000;
+ context.vm.regs.ecx |= ecx & 0xffff;
+ }
+
+static void
+em_inbl(unsigned char literal)
+ {
+ context.vm.regs.eax = inb(literal) & 0xff;
+ }
+
+static void
+em_inb(void)
+ {
+ asm volatile ("inb (%w1), %b0"
+ : "=a" (context.vm.regs.eax)
+ : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
+ }
+
+static void
+em_inw(void)
+ {
+ asm volatile ("inw (%w1), %w0"
+ : "=a" (context.vm.regs.eax)
+ : "d" (context.vm.regs.edx), "0" (context.vm.regs.eax));
+ }
+
+static void
+em_inl(void)
+ {
+ asm volatile ("inl (%w1), %0"
+ : "=a" (context.vm.regs.eax)
+ : "d" (context.vm.regs.edx));
+ }
+
+static void
+em_outbl(unsigned char literal)
+ {
+ outb(context.vm.regs.eax & 0xff, literal);
+ }
+
+static void
+em_outb(void)
+ {
+ asm volatile ("outb %b0, (%w1)"
+ : : "a" (context.vm.regs.eax),
+ "d" (context.vm.regs.edx));
+ }
+
+static void
+em_outw(void)
+ {
+ asm volatile ("outw %w0, (%w1)"
+ : : "a" (context.vm.regs.eax),
+ "d" (context.vm.regs.edx));
+ }
+
+static void
+em_outl(void)
+ {
+ asm volatile ("outl %0, (%w1)"
+ : : "a" (context.vm.regs.eax),
+ "d" (context.vm.regs.edx));
+ }
+
+static int
+emulate(void)
+ {
+ unsigned char *insn;
+ struct
+ {
+ unsigned int size : 1;
+ unsigned int rep : 1;
+ } prefix = { 0, 0 };
+ int i = 0;
+
+ insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4);
+ insn += context.vm.regs.eip;
+
+ while (1)
+ {
+ if (insn[i] == 0x66)
+ {
+ prefix.size = 1 - prefix.size;
+ i++;
+ }
+ else if (insn[i] == 0xf3)
+ {
+ prefix.rep = 1;
+ i++;
+ }
+ else if (insn[i] == 0xf0 || insn[i] == 0xf2
+ || insn[i] == 0x26 || insn[i] == 0x2e
+ || insn[i] == 0x36 || insn[i] == 0x3e
+ || insn[i] == 0x64 || insn[i] == 0x65
+ || insn[i] == 0x67)
+ {
+ /* these prefixes are just ignored */
+ i++;
+ }
+ else if (insn[i] == 0x6c)
+ {
+ if (prefix.rep)
+ em_rep_ins(1);
+ else
+ em_ins(1);
+ i++;
+ break;
+ }
+ else if (insn[i] == 0x6d)
+ {
+ if (prefix.rep)
+ {
+ if (prefix.size)
+ em_rep_ins(4);
+ else
+ em_rep_ins(2);
+ }
+ else
+ {
+ if (prefix.size)
+ em_ins(4);
+ else
+ em_ins(2);
+ }
+ i++;
+ break;
+ }
+ else if (insn[i] == 0x6e)
+ {
+ if (prefix.rep)
+ em_rep_outs(1);
+ else
+ em_outs(1);
+ i++;
+ break;
+ }
+ else if (insn[i] == 0x6f)
+ {
+ if (prefix.rep)
+ {
+ if (prefix.size)
+ em_rep_outs(4);
+ else
+ em_rep_outs(2);
+ }
+ else
+ {
+ if (prefix.size)
+ em_outs(4);
+ else
+ em_outs(2);
+ }
+ i++;
+ break;
+ }
+ else if (insn[i] == 0xe4)
+ {
+ em_inbl(insn[i + 1]);
+ i += 2;
+ break;
+ }
+ else if (insn[i] == 0xe6)
+ {
+ em_outbl(insn[i + 1]);
+ i += 2;
+ break;
+ }
+ else if (insn[i] == 0xec)
+ {
+ em_inb();
+ i++;
+ break;
+ }
+ else if (insn[i] == 0xed)
+ {
+ if (prefix.size)
+ em_inl();
+ else
+ em_inw();
+ i++;
+ break;
+ }
+ else if (insn[i] == 0xee)
+ {
+ em_outb();
+ i++;
+ break;
+ }
+ else if (insn[i] == 0xef)
+ {
+ if (prefix.size)
+ em_outl();
+ else
+ em_outw();
+
+ i++;
+ break;
+ }
+ else
+ return 0;
+ }
+
+ context.vm.regs.eip += i;
+ return 1;
+ }
+
+
+/*
+ I don't know how to make sure I get the right vm86() from libc.
+ The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc)
+ which should be declared as "int vm86(struct vm86_struct *);" in
+ <sys/vm86.h>.
+
+ This just does syscall 113 with inline asm, which should work
+ for both libc's (I hope).
+*/
+#if !defined(USE_LIBC_VM86)
+static int
+lrmi_vm86(struct vm86_struct *vm)
+ {
+ int r;
+#ifdef __PIC__
+ asm volatile (
+ "pushl %%ebx\n\t"
+ "movl %2, %%ebx\n\t"
+ "int $0x80\n\t"
+ "popl %%ebx"
+ : "=a" (r)
+ : "0" (113), "r" (vm));
+#else
+ asm volatile (
+ "int $0x80"
+ : "=a" (r)
+ : "0" (113), "b" (vm));
+#endif
+ return r;
+ }
+#else
+#define lrmi_vm86 vm86
+#endif
+
+
+static void
+debug_info(int vret)
+ {
+ int i;