summary refs log tree commit diff stats
path: root/linux-user
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-22 15:23:14 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-22 15:23:14 +0000
commitdab2ed991a49678fbd4d45ff1b328340a77057df (patch)
tree0c587c5ef62faa0c3bf9b39a7ce9281c0a63e2b2 /linux-user
parente591824733ec698d92d1f09c2ffb9b86b799d6da (diff)
downloadfocaccia-qemu-dab2ed991a49678fbd4d45ff1b328340a77057df.tar.gz
focaccia-qemu-dab2ed991a49678fbd4d45ff1b328340a77057df.zip
better 16 bit code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@38 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c8
-rw-r--r--linux-user/syscall.c37
-rw-r--r--linux-user/syscall_defs.h16
3 files changed, 48 insertions, 13 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 45e81b207c..3222629b27 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -179,7 +179,7 @@ int main(int argc, char **argv)
     env->regs[R_EDI] = regs->edi;
     env->regs[R_EBP] = regs->ebp;
     env->regs[R_ESP] = regs->esp;
-    env->pc = regs->eip;
+    env->eip = regs->eip;
 
     /* linux segment setup */
     env->gdt.base = (void *)gdt_table;
@@ -198,12 +198,12 @@ int main(int argc, char **argv)
         uint8_t *pc;
         
         err = cpu_x86_exec(env);
+        pc = env->seg_cache[R_CS].base + env->eip;
         switch(err) {
         case EXCP0D_GPF:
-            pc = (uint8_t *)env->pc;
             if (pc[0] == 0xcd && pc[1] == 0x80) {
                 /* syscall */
-                env->pc += 2;
+                env->eip += 2;
                 env->regs[R_EAX] = do_syscall(env, 
                                               env->regs[R_EAX], 
                                               env->regs[R_EBX],
@@ -219,7 +219,7 @@ int main(int argc, char **argv)
         default:
         trap_error:
             fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n", 
-                    (long)env->pc, err);
+                    (long)pc, err);
             abort();
         }
     }
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c0bee47f76..afdf189676 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -53,6 +53,7 @@
 #include <linux/cdrom.h>
 #include <linux/hdreg.h>
 #include <linux/soundcard.h>
+#include <linux/dirent.h>
 
 #include "gemu.h"
 
@@ -63,13 +64,6 @@
 #define PAGE_MASK ~(PAGE_SIZE - 1)
 #endif
 
-struct dirent {
-        long            d_ino;
-        long            d_off;
-        unsigned short  d_reclen;
-        char            d_name[256]; /* We must not include limits.h! */
-};
-
 //#include <linux/msdos_fs.h>
 #define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct dirent [2])
 #define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct dirent [2])
@@ -86,6 +80,7 @@ struct dirent {
 #define __NR_sys_statfs __NR_statfs
 #define __NR_sys_fstatfs __NR_fstatfs
 #define __NR_sys_getdents __NR_getdents
+#define __NR_sys_getdents64 __NR_getdents64
 
 #ifdef __NR_gettid
 _syscall0(int, gettid)
@@ -97,6 +92,7 @@ static int gettid(void) {
 _syscall1(int,sys_uname,struct new_utsname *,buf)
 _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
 _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
+_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 _syscall2(int,sys_statfs,const char *,path,struct kernel_statfs *,buf)
@@ -1005,7 +1001,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         ret = get_errno(setsid());
         break;
     case TARGET_NR_sigaction:
-#if 0
+#if 1
         {
             ret = 0;
         }
@@ -1336,6 +1332,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         {
             struct dirent *dirp = (void *)arg2;
             long count = arg3;
+
             ret = get_errno(sys_getdents(arg1, dirp, count));
             if (!is_error(ret)) {
                 struct dirent *de;
@@ -1355,6 +1352,29 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
             }
         }
         break;
+    case TARGET_NR_getdents64:
+        {
+            struct dirent64 *dirp = (void *)arg2;
+            long count = arg3;
+            ret = get_errno(sys_getdents64(arg1, dirp, count));
+            if (!is_error(ret)) {
+                struct dirent64 *de;
+                int len = ret;
+                int reclen;
+                de = dirp;
+                while (len > 0) {
+                    reclen = tswap16(de->d_reclen);
+                    if (reclen > len)
+                        break;
+                    de->d_reclen = reclen;
+                    tswap64s(&de->d_ino);
+                    tswap64s(&de->d_off);
+                    de = (struct dirent64 *)((char *)de + reclen);
+                    len -= reclen;
+                }
+            }
+        }
+        break;
     case TARGET_NR__newselect:
         ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, 
                         (void *)arg5);
@@ -1519,7 +1539,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_pivot_root:
     case TARGET_NR_mincore:
     case TARGET_NR_madvise:
-    case TARGET_NR_getdents64:
         goto unimplemented;
 #if TARGET_LONG_BITS == 32
     case TARGET_NR_fcntl64:
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index dc44272dbb..8b2d6bd756 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -75,6 +75,22 @@ struct kernel_statfs {
 	int f_spare[6];
 };
 
+struct target_dirent {
+	target_long	d_ino;
+	target_long	d_off;
+	unsigned short	d_reclen;
+	char		d_name[256]; /* We must not include limits.h! */
+};
+
+struct target_dirent64 {
+	uint64_t	d_ino;
+	int64_t		d_off;
+	unsigned short	d_reclen;
+	unsigned char	d_type;
+	char		d_name[256];
+};
+
+
 /* mostly generic signal stuff */
 #define TARGET_SIG_DFL	((target_long)0)	/* default signal handling */
 #define TARGET_SIG_IGN	((target_long)1)	/* ignore signal */