qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] qemu on mips patch
@ 2007-06-02  6:37 Jun Peng
  2007-06-03 13:30 ` Thiemo Seufer
  0 siblings, 1 reply; 4+ messages in thread
From: Jun Peng @ 2007-06-02  6:37 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1000 bytes --]

Hello!

Are you are just testing host_mips qemu? I have been doing the same
work two or three month

ago on a mips + linux system. But, it have some bugs however.

It is for qemu 0.6.1 refer to qemu-irix.patch at first. And yesterday,
I made a qemu 0.9.0

patch. It seems working(only target-i386). In order to handle
relocation symbol, I writed a

little tool named op_mips.c. This tool is the key of my patch.

host detail:
cpu: loognson 2E(mips compatible, little endian)
os: debian linux 4.0
kernel: linux 2.6.18
gcc: 3.4.6
glibc: 2.3.6

test:
in full system mode: can run windows 98 or linux(x86)
in user mode: can run some i386 elf programs except wine!

bugs:
In user mode, it catchs a SIGSEGV when launching a windows PE program.
I have been trying to

solve this problem a long time. But unfortunately, I failed.

I wondered if you could give me some help about qemu + wine. And hope
new qemu release

supply host_mips soon.

There is the patch: qemu-0.9.0-loongson.patch


Thanks.
Peng Jun

[-- Attachment #2: qemu-0.9.0-loongson.patch --]
[-- Type: text/plain, Size: 44536 bytes --]

diff -Nurb qemu-0.9.0/cpu-all.h qemu-loongson/cpu-all.h
--- qemu-0.9.0/cpu-all.h	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/cpu-all.h	2007-06-01 23:23:34.000000000 +0800
@@ -20,7 +20,7 @@
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 
-#if defined(__arm__) || defined(__sparc__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
 #define WORDS_ALIGNED
 #endif
 
@@ -1001,6 +1001,21 @@
         return rval.i64;
 #endif
 }
+
+#elif defined(__mips__)
+
+#include <time.h>
+static inline int64_t cpu_get_real_ticks (void)
+{
+    struct timespec t;
+    // linux/time.h
+#ifndef	CLOCK_MONOTONIC
+#define	CLOCK_MONOTONIC	1
+#endif
+    clock_gettime(CLOCK_MONOTONIC, &t);
+    return t.tv_sec*1000000000LL+t.tv_nsec;
+}
+
 #else
 /* The host CPU doesn't have an easily accessible cycle counter.
    Just return a monotonically increasing vlue.  This will be totally wrong,
diff -Nurb qemu-0.9.0/cpu-exec.c qemu-loongson/cpu-exec.c
--- qemu-0.9.0/cpu-exec.c	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/cpu-exec.c	2007-06-01 23:23:34.000000000 +0800
@@ -1478,6 +1478,25 @@
                              &uc->uc_sigmask, puc);
 }
 
+#elif defined(__mips__)
+
+#include <sys/user.h>
+int cpu_signal_handler(int host_signum, void *pinfo, 
+                       void *puc)
+{
+    siginfo_t *info = pinfo;
+    struct ucontext *uc = puc;
+    unsigned long pc;
+    int is_write;
+    
+    pc = uc->uc_mcontext.gregs[EF_REG31];	// ???
+    /* XXX: compute is_write */
+    is_write = 0;
+    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
+                             is_write,
+                             &uc->uc_sigmask, puc);
+}
+
 #else
 
 #error host CPU specific signal handler needed
diff -Nurb qemu-0.9.0/dyngen.c qemu-loongson/dyngen.c
--- qemu-0.9.0/dyngen.c	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/dyngen.c	2007-06-01 23:23:34.000000000 +0800
@@ -117,6 +117,13 @@
 #define elf_check_arch(x) ((x) == EM_68K)
 #define ELF_USES_RELOCA
 
+#elif defined(HOST_MIPS)
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOC
+
 #else
 #error unsupported CPU - please update the code
 #endif
@@ -1641,6 +1648,20 @@
             error("rts expected at the end of %s", name);
         copy_size = p - p_start;
     }
+#elif defined(HOST_MIPS)
+    {
+        uint8_t *p;
+        p = (void *)(p_end - 4);
+        if (p == p_start)
+            error("empty code for %s", name);
+        // remove NOP's, added for alignment
+       	while ((get32((uint32_t *)p) != 0x03e00008) &&
+       	        (p>p_start)) 
+ 	    p -= 4;
+	if (get32((uint32_t *)p) != 0x03e00008)
+             error("jr ra expected at the end of %s", name);
+        copy_size = p - p_start;
+    }
 #else
 #error unsupported CPU
 #endif
@@ -1727,12 +1748,16 @@
 				fprintf(outfile, "    extern char %s;\n",
 					sym_name);
 #else
+#ifndef	HOST_MIPS
                     fprintf(outfile, "extern char %s;\n", sym_name);
 #endif
+#endif
                 }
             }
         }
-
+	// debug
+/*	fprintf(outfile, "	fprintf(stderr, \"%s: [%%08x][%%08x] %d/%d\\n\", (int)gen_code_ptr, (int)%s);\n",
+			name, copy_size/4, copy_size, name);*/
         fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",
 					name, (int)(start_offset - offset), copy_size);
 
@@ -2456,6 +2481,63 @@
                 }
                 }
             }
+#elif defined(HOST_MIPS)
+            {
+                char name[256];
+                int type;
+		Elf32_Sym *sym;
+
+                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
+                if (rel->r_offset >= start_offset &&
+		    rel->r_offset < start_offset + copy_size) {
+		    sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
+                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
+                    if (strstart(sym_name, "__op_jmp", &p)) {
+                        int n;
+			if(ELF32_R_TYPE(rel->r_info)==R_MIPS_LO16)
+			    continue;
+                        n = strtol(p, NULL, 10);
+                        /* __op_jmp relocations are done at
+                           runtime to do translated block
+                           chaining: the offset of the instruction
+                           needs to be stored */
+                        fprintf(outfile, "    jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
+                                    n, rel->r_offset - start_offset);
+                        continue;
+                    }
+                    if (strstart(sym_name, "__op_param", &p)) {
+                        snprintf(name, sizeof(name), "param%s", p);
+		    } else if (strstart(sym_name,
+					    "__op_gen_label", &p)) {
+        		snprintf(name, sizeof(name),
+					"gen_labels[param%s]", p);
+                    } else {
+		continue;
+                    }
+                    type = ELF32_R_TYPE(rel->r_info);
+                    switch(type) {
+		    case R_MIPS_HI16:
+                        fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)((uint32_t)(%s)>>16);\n", 
+                                rel->r_offset - start_offset + 0, name);
+			break;
+		    case R_MIPS_LO16:
+                        fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)((uint32_t)(%s)&0xffff);\n", 
+                                rel->r_offset - start_offset + 0, name);
+			break;
+		    case R_MIPS_GPREL16:
+		    case R_MIPS_GOT_DISP:
+		    case R_MIPS_GOT_PAGE:
+		    case R_MIPS_GOT_OFST:
+		    case R_MIPS_CALL16:
+			/* ignore: these relocations are no parameters;
+			   they will be filled in by the linker */
+			break;
+                    default:
+                        error("unsupported MIPS relocation (%d)", type);
+		    }
+                }
+                }
+            }
 #else
 #error unsupported CPU
 #endif
diff -Nurb qemu-0.9.0/dyngen-exec.h qemu-loongson/dyngen-exec.h
--- qemu-0.9.0/dyngen-exec.h	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/dyngen-exec.h	2007-06-02 08:11:09.000000000 +0800
@@ -227,9 +227,21 @@
 #else
 extern int __op_param1, __op_param2, __op_param3;
 #endif
+#if defined(__mips__)
+/* On MIPS, parameters to a c expression are passed via the global pointer.
+ * We don't want that. */
+#define PARAMN(index) ({ register int _r; \
+		asm("lui %0,%%hi(__op_param" #index ")\n\t" \
+			"ori %0,%0,%%lo(__op_param" #index ")" \
+			: "=r"(_r)); _r; })
+#define PARAM1 PARAMN(1)
+#define PARAM2 PARAMN(2)
+#define PARAM3 PARAMN(3)
+#else
 #define PARAM1 ((long)(&__op_param1))
 #define PARAM2 ((long)(&__op_param2))
 #define PARAM3 ((long)(&__op_param3))
+#endif
 #endif /* !defined(__alpha__) */
 
 extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
@@ -275,5 +287,14 @@
 #ifdef __mc68000
 #define EXIT_TB() asm volatile ("rts")
 #endif
+#ifdef __mips__
+#define EXIT_TB() asm volatile ("j	$31\n\tnop")
+//#define GOTO_LABEL_PARAM(n) asm volatile ("j	" ASM_NAME(__op_gen_label) #n)
+#define	GOTO_LABEL_PARAM(n)	\
+	asm volatile ("lui	$25,%hi(__op_gen_label" #n")\n\
+	ori	$25,$25,%lo(__op_gen_label" #n")\n\
+	j	$25\n\
+	nop")
+#endif
 
 #endif /* !defined(__DYNGEN_EXEC_H__) */
diff -Nurb qemu-0.9.0/dyngen.h qemu-loongson/dyngen.h
--- qemu-0.9.0/dyngen.h	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/dyngen.h	2007-06-01 23:23:34.000000000 +0800
@@ -120,6 +120,14 @@
 }
 #endif
 
+#ifdef __mips__
+#include <sys/cachectl.h>
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+    cacheflush((void*)start,stop-start,BCACHE);
+}
+#endif
+
 #ifdef __alpha__
 
 register int gp asm("$29");
diff -Nurb qemu-0.9.0/exec-all.h qemu-loongson/exec-all.h
--- qemu-0.9.0/exec-all.h	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/exec-all.h	2007-06-01 23:23:34.000000000 +0800
@@ -481,6 +481,25 @@
 }
 #endif
 
+#ifdef __mips__
+static inline int testandset (int *spinlock)
+{
+        int ret;
+        __asm__ __volatile__(".set mips2\n"
+                "ll %0,%1\n"
+                ".set noreorder\n"
+                "bnez %0,1f\n"
+                "li %0,0\n" /* branch delay slot */
+                "li %0,1\n"
+                "sc %0,%1\n"
+                "1:\n"
+                ".set reorder\n"
+                : "=r" (ret), "=m" (*spinlock));
+
+        return !ret;
+}
+#endif
+
 typedef int spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED 0
diff -Nurb qemu-0.9.0/linux-user/mmap.c qemu-loongson/linux-user/mmap.c
--- qemu-0.9.0/linux-user/mmap.c	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/linux-user/mmap.c	2007-06-02 08:22:41.000000000 +0800
@@ -157,7 +157,7 @@
     target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
     long host_start;
 #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
-    defined(__ia64)
+    defined(__ia64) || defined(__mips__)
     static target_ulong last_start = 0x40000000;
 #elif defined(__CYGWIN__)
     /* Cygwin doesn't have a whole lot of address space.  */
@@ -202,7 +202,7 @@
 
     if (!(flags & MAP_FIXED)) {
 #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \
-    defined(__ia64) || defined(__CYGWIN__)
+    defined(__ia64) || defined(__CYGWIN__) || defined(__mips__)
         /* tell the kenel to search at the same place as i386 */
         if (real_start == 0) {
             real_start = last_start;
diff -Nurb qemu-0.9.0/linux-user/syscall.c qemu-loongson/linux-user/syscall.c
--- qemu-0.9.0/linux-user/syscall.c	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/linux-user/syscall.c	2007-06-02 08:47:29.000000000 +0800
@@ -58,7 +58,13 @@
 #define ltchars host_ltchars /* same as target */
 
 #include <linux/termios.h>
+#ifdef	__mips__
+#define	__KERNEL__
 #include <linux/unistd.h>
+#undef	__KERNEL__
+#else
+#include <linux/unistd.h>
+#endif
 #include <linux/utsname.h>
 #include <linux/cdrom.h>
 #include <linux/hdreg.h>
@@ -68,6 +74,10 @@
 
 #include "qemu.h"
 
+// testing!!! only for host-mips target-i386
+#include "x86_sys_errno.c"
+#include "x86_sys_socket.c"
+
 //#define DEBUG
 
 #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
@@ -176,7 +186,8 @@
 static inline long get_errno(long ret)
 {
     if (ret == -1)
-        return -errno;
+//        return -errno;
+	    return -gs_x86_errno(errno);
     else
         return ret;
 }
@@ -445,6 +456,8 @@
         }
 
         cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+	if(cmsg->cmsg_level == X86_SOL_SOCKET)
+		cmsg->cmsg_level = SOL_SOCKET;
         cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
         cmsg->cmsg_len = CMSG_LEN(len);
 
@@ -489,10 +502,13 @@
         }
 
         target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+	if(cmsg->cmsg_level == SOL_SOCKET)
+		cmsg->cmsg_level = X86_SOL_SOCKET;
         target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
         target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
 
-        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
+	if (cmsg->cmsg_level != X86_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
+
             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
             memcpy(target_data, data, len);
         } else {
@@ -752,6 +768,7 @@
 
 static long do_socket(int domain, int type, int protocol)
 {
+	return get_errno(x86_sys_socket(domain, type, protocol));
 #if defined(TARGET_MIPS)
     switch(type) {
     case TARGET_SOCK_DGRAM:
@@ -1086,7 +1103,8 @@
             target_ulong optval = tgetl(vptr + 3 * n);
             socklen_t optlen = tgetl(vptr + 4 * n);
 
-            ret = do_setsockopt(sockfd, level, optname, optval, optlen);
+//            ret = do_setsockopt(sockfd, level, optname, optval, optlen);
+	    ret = get_errno(x86_sys_setsockopt(sockfd, level, optname, (void*)optval, optlen));
         }
         break;
     case SOCKOP_getsockopt:
@@ -1097,7 +1115,8 @@
             target_ulong optval = tgetl(vptr + 3 * n);
             target_ulong poptlen = tgetl(vptr + 4 * n);
 
-            ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
+//            ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
+	    ret = get_errno(x86_sys_getsockopt(sockfd, level, optname, (void*)optval, (void*)poptlen));
         }
         break;
     default:
@@ -3951,7 +3970,7 @@
 #if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_getdomainname)
     unimplemented_nowarn:
 #endif
-        ret = -ENOSYS;
+	ret = -gs_x86_errno(ENOSYS);
         break;
     }
  fail:
diff -Nurb qemu-0.9.0/linux-user/x86_sys_errno.c qemu-loongson/linux-user/x86_sys_errno.c
--- qemu-0.9.0/linux-user/x86_sys_errno.c	1970-01-01 08:00:00.000000000 +0800
+++ qemu-loongson/linux-user/x86_sys_errno.c	2007-06-01 23:25:18.000000000 +0800
@@ -0,0 +1,411 @@
+/*
+ * 	x86_sys_errno.c
+ *
+ * 	_errno
+ *
+ * 	gs_x86_errno
+ *
+ * 		x86run/syscall
+ * 		Peng Jun
+ */
+
+#include <errno.h>
+
+
+#define	X86_EPERM		 1	/* Operation not permitted */
+#define	X86_ENOENT		 2	/* No such file or directory */
+#define	X86_ESRCH		 3	/* No such process */
+#define	X86_EINTR		 4	/* Interrupted system call */
+#define	X86_EIO		 5	/* I/O error */
+#define	X86_ENXIO		 6	/* No such device or address */
+#define	X86_E2BIG		 7	/* Arg list too long */
+#define	X86_ENOEXEC		 8	/* Exec format error */
+#define	X86_EBADF		 9	/* Bad file number */
+#define	X86_ECHILD		10	/* No child processes */
+#define	X86_EAGAIN		11	/* Try again */
+#define	X86_ENOMEM		12	/* Out of memory */
+#define	X86_EACCES		13	/* Permission denied */
+#define	X86_EFAULT		14	/* Bad address */
+#define	X86_ENOTBLK		15	/* Block device required */
+#define	X86_EBUSY		16	/* Device or resource busy */
+#define	X86_EEXIST		17	/* File exists */
+#define	X86_EXDEV		18	/* Cross-device link */
+#define	X86_ENODEV		19	/* No such device */
+#define	X86_ENOTDIR		20	/* Not a directory */
+#define	X86_EISDIR		21	/* Is a directory */
+#define	X86_EINVAL		22	/* Invalid argument */
+#define	X86_ENFILE		23	/* File table overflow */
+#define	X86_EMFILE		24	/* Too many open files */
+#define	X86_ENOTTY		25	/* Not a typewriter */
+#define	X86_ETXTBSY		26	/* Text file busy */
+#define	X86_EFBIG		27	/* File too large */
+#define	X86_ENOSPC		28	/* No space left on device */
+#define	X86_ESPIPE		29	/* Illegal seek */
+#define	X86_EROFS		30	/* Read-only file system */
+#define	X86_EMLINK		31	/* Too many links */
+#define	X86_EPIPE		32	/* Broken pipe */
+#define	X86_EDOM		33	/* Math argument out of domain of func */
+#define	X86_ERANGE		34	/* Math result not representable */
+#define	X86_EDEADLK		35	/* Resource deadlock would occur */
+#define	X86_ENAMETOOLONG	36	/* File name too long */
+#define	X86_ENOLCK		37	/* No record locks available */
+#define	X86_ENOSYS		38	/* Function not implemented */
+#define	X86_ENOTEMPTY	39	/* Directory not empty */
+#define	X86_ELOOP		40	/* Too many symbolic links encountered */
+#define	X86_EWOULDBLOCK	X86_EAGAIN	/* Operation would block */
+#define	X86_ENOMSG		42	/* No message of desired type */
+#define	X86_EIDRM		43	/* Identifier removed */
+#define	X86_ECHRNG		44	/* Channel number out of range */
+#define	X86_EL2NSYNC	45	/* Level 2 not synchronized */
+#define	X86_EL3HLT		46	/* Level 3 halted */
+#define	X86_EL3RST		47	/* Level 3 reset */
+#define	X86_ELNRNG		48	/* Link number out of range */
+#define	X86_EUNATCH		49	/* Protocol driver not attached */
+#define	X86_ENOCSI		50	/* No CSI structure available */
+#define	X86_EL2HLT		51	/* Level 2 halted */
+#define	X86_EBADE		52	/* Invalid exchange */
+#define	X86_EBADR		53	/* Invalid request descriptor */
+#define	X86_EXFULL		54	/* Exchange full */
+#define	X86_ENOANO		55	/* No anode */
+#define	X86_EBADRQC		56	/* Invalid request code */
+#define	X86_EBADSLT		57	/* Invalid slot */
+#define	X86_EDEADLOCK	X86_EDEADLK
+#define	X86_EBFONT		59	/* Bad font file format */
+#define	X86_ENOSTR		60	/* Device not a stream */
+#define	X86_ENODATA		61	/* No data available */
+#define	X86_ETIME		62	/* Timer expired */
+#define	X86_ENOSR		63	/* Out of streams resources */
+#define	X86_ENONET		64	/* Machine is not on the network */
+#define	X86_ENOPKG		65	/* Package not installed */
+#define	X86_EREMOTE		66	/* Object is remote */
+#define	X86_ENOLINK		67	/* Link has been severed */
+#define	X86_EADV		68	/* Advertise error */
+#define	X86_ESRMNT		69	/* Srmount error */
+#define	X86_ECOMM		70	/* Communication error on send */
+#define	X86_EPROTO		71	/* Protocol error */
+#define	X86_EMULTIHOP	72	/* Multihop attempted */
+#define	X86_EDOTDOT		73	/* RFS specific error */
+#define	X86_EBADMSG		74	/* Not a data message */
+#define	X86_EOVERFLOW	75	/* Value too large for defined data type */
+#define	X86_ENOTUNIQ	76	/* Name not unique on network */
+#define	X86_EBADFD		77	/* File descriptor in bad state */
+#define	X86_EREMCHG		78	/* Remote address changed */
+#define	X86_ELIBACC		79	/* Can not access a needed shared library */
+#define	X86_ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	X86_ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	X86_ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	X86_ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	X86_EILSEQ		84	/* Illegal byte sequence */
+#define	X86_ERESTART	85	/* Interrupted system call should be restarted */
+#define	X86_ESTRPIPE	86	/* Streams pipe error */
+#define	X86_EUSERS		87	/* Too many users */
+#define	X86_ENOTSOCK	88	/* Socket operation on non-socket */
+#define	X86_EDESTADDRREQ	89	/* Destination address required */
+#define	X86_EMSGSIZE	90	/* Message too long */
+#define	X86_EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	X86_ENOPROTOOPT	92	/* Protocol not available */
+#define	X86_EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	X86_ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	X86_EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	X86_EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	X86_EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	X86_EADDRINUSE	98	/* Address already in use */
+#define	X86_EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	X86_ENETDOWN	100	/* Network is down */
+#define	X86_ENETUNREACH	101	/* Network is unreachable */
+#define	X86_ENETRESET	102	/* Network dropped connection because of reset */
+#define	X86_ECONNABORTED	103	/* Software caused connection abort */
+#define	X86_ECONNRESET	104	/* Connection reset by peer */
+#define	X86_ENOBUFS		105	/* No buffer space available */
+#define	X86_EISCONN		106	/* Transport endpoint is already connected */
+#define	X86_ENOTCONN	107	/* Transport endpoint is not connected */
+#define	X86_ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	X86_ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	X86_ETIMEDOUT	110	/* Connection timed out */
+#define	X86_ECONNREFUSED	111	/* Connection refused */
+#define	X86_EHOSTDOWN	112	/* Host is down */
+#define	X86_EHOSTUNREACH	113	/* No route to host */
+#define	X86_EALREADY	114	/* Operation already in progress */
+#define	X86_EINPROGRESS	115	/* Operation now in progress */
+#define	X86_ESTALE		116	/* Stale NFS file handle */
+#define	X86_EUCLEAN		117	/* Structure needs cleaning */
+#define	X86_ENOTNAM		118	/* Not a XENIX named type file */
+#define	X86_ENAVAIL		119	/* No XENIX semaphores available */
+#define	X86_EISNAM		120	/* Is a named type file */
+#define	X86_EREMOTEIO	121	/* Remote I/O error */
+#define	X86_EDQUOT		122	/* Quota exceeded */
+#define	X86_ENOMEDIUM	123	/* No medium found */
+#define	X86_EMEDIUMTYPE	124	/* Wrong medium type */
+#define	X86_ECANCELED	125
+
+
+int gs_x86_errno(int gs_errno);
+
+
+/*
+ * public
+ */
+
+
+/*
+ * private
+ */
+int gs_x86_errno(int gs_errno)
+{
+	if(gs_errno < 35)
+		return gs_errno;
+
+	switch(gs_errno) {
+	/*	case EPERM:
+			return X86_EPERM;
+		case ENOENT:
+			return X86_ENOENT;
+		case ESRCH:
+			return X86_ESRCH;
+		case EINTR:
+			return X86_EINTR;
+		case EIO:
+			return X86_EIO;
+		case ENXIO:
+			return X86_ENXIO;
+		case E2BIG:
+			return X86_E2BIG;
+		case ENOEXEC:
+			return X86_ENOEXEC;
+		case EBADF:
+			return X86_EBADF;
+		case ECHILD:
+			return X86_ECHILD;
+		case EAGAIN:
+			return X86_EAGAIN;
+		case ENOMEM:
+			return X86_ENOMEM;
+		case EACCES:
+			return X86_EACCES;
+		case EFAULT:
+			return X86_EFAULT;
+		case ENOTBLK:
+			return X86_ENOTBLK;
+		case EBUSY:
+			return X86_EBUSY;
+		case EEXIST:
+			return X86_EEXIST;
+		case EXDEV:
+			return X86_EXDEV;
+		case ENODEV:
+			return X86_ENODEV;
+		case ENOTDIR:
+			return X86_ENOTDIR;
+		case EISDIR:
+			return X86_EISDIR;
+		case EINVAL:
+			return X86_EINVAL;
+		case ENFILE:
+			return X86_ENFILE;
+		case EMFILE:
+			return X86_EMFILE;
+		case ENOTTY:
+			return X86_ENOTTY;
+		case ETXTBSY:
+			return X86_ETXTBSY;
+		case EFBIG:
+			return X86_EFBIG;
+		case ENOSPC:
+			return X86_ENOSPC;
+		case ESPIPE:
+			return X86_ESPIPE;
+		case EROFS:
+			return X86_EROFS;
+		case EMLINK:
+			return X86_EMLINK;
+		case EPIPE:
+			return X86_EPIPE;
+		case EDOM:
+			return X86_EDOM;
+		case ERANGE:
+			return X86_ERANGE; */
+		case EDEADLK:
+			return X86_EDEADLK;
+		case ENAMETOOLONG:
+			return X86_ENAMETOOLONG;
+		case ENOLCK:
+			return X86_ENOLCK;
+		case ENOSYS:
+			return X86_ENOSYS;
+		case ENOTEMPTY:
+			return X86_ENOTEMPTY;
+		case ELOOP:
+			return X86_ELOOP;
+		case EWOULDBLOCK:
+			return X86_EWOULDBLOCK;
+		case ENOMSG:
+			return X86_ENOMSG;
+		case EIDRM:
+			return X86_EIDRM;
+		case ECHRNG:
+			return X86_ECHRNG;
+		case EL2NSYNC:
+			return X86_EL2NSYNC;
+		case EL3HLT:
+			return X86_EL3HLT;
+		case EL3RST:
+			return X86_EL3RST;
+		case ELNRNG:
+			return X86_ELNRNG;
+		case EUNATCH:
+			return X86_EUNATCH;
+		case ENOCSI:
+			return X86_ENOCSI;
+		case EL2HLT:
+			return X86_EL2HLT;
+		case EBADE:
+			return X86_EBADE;
+		case EBADR:
+			return X86_EBADR;
+		case EXFULL:
+			return X86_EXFULL;
+		case ENOANO:
+			return X86_ENOANO;
+		case EBADRQC:
+			return X86_EBADRQC;
+		case EBADSLT:
+			return X86_EBADSLT;
+		case EDEADLOCK:
+			return X86_EDEADLOCK;
+		case EBFONT:
+			return X86_EBFONT;
+		case ENOSTR:
+			return X86_ENOSTR;
+		case ENODATA:
+			return X86_ENODATA;
+		case ETIME:
+			return X86_ETIME;
+		case ENOSR:
+			return X86_ENOSR;
+		case ENONET:
+			return X86_ENONET;
+		case ENOPKG:
+			return X86_ENOPKG;
+		case EREMOTE:
+			return X86_EREMOTE;
+		case ENOLINK:
+			return X86_ENOLINK;
+		case EADV:
+			return X86_EADV;
+		case ESRMNT:
+			return X86_ESRMNT;
+		case ECOMM:
+			return X86_ECOMM;
+		case EPROTO:
+			return X86_EPROTO;
+		case EMULTIHOP:
+			return X86_EMULTIHOP;
+		case EDOTDOT:
+			return X86_EDOTDOT;
+		case EBADMSG:
+			return X86_EBADMSG;
+		case EOVERFLOW:
+			return X86_EOVERFLOW;
+		case ENOTUNIQ:
+			return X86_ENOTUNIQ;
+		case EBADFD:
+			return X86_EBADFD;
+		case EREMCHG:
+			return X86_EREMCHG;
+		case ELIBACC:
+			return X86_ELIBACC;
+		case ELIBBAD:
+			return X86_ELIBBAD;
+		case ELIBSCN:
+			return X86_ELIBSCN;
+		case ELIBMAX:
+			return X86_ELIBMAX;
+		case ELIBEXEC:
+			return X86_ELIBEXEC;
+		case EILSEQ:
+			return X86_EILSEQ;
+		case ERESTART:
+			return X86_ERESTART;
+		case ESTRPIPE:
+			return X86_ESTRPIPE;
+		case EUSERS:
+			return X86_EUSERS;
+		case ENOTSOCK:
+			return X86_ENOTSOCK;
+		case EDESTADDRREQ:
+			return X86_EDESTADDRREQ;
+		case EMSGSIZE:
+			return X86_EMSGSIZE;
+		case EPROTOTYPE:
+			return X86_EPROTOTYPE;
+		case ENOPROTOOPT:
+			return X86_ENOPROTOOPT;
+		case EPROTONOSUPPORT:
+			return X86_EPROTONOSUPPORT;
+		case ESOCKTNOSUPPORT:
+			return X86_ESOCKTNOSUPPORT;
+		case EOPNOTSUPP:
+			return X86_EOPNOTSUPP;
+		case EPFNOSUPPORT:
+			return X86_EPFNOSUPPORT;
+		case EAFNOSUPPORT:
+			return X86_EAFNOSUPPORT;
+		case EADDRINUSE:
+			return X86_EADDRINUSE;
+		case EADDRNOTAVAIL:
+			return X86_EADDRNOTAVAIL;
+		case ENETDOWN:
+			return X86_ENETDOWN;
+		case ENETUNREACH:
+			return X86_ENETUNREACH;
+		case ENETRESET:
+			return X86_ENETRESET;
+		case ECONNABORTED:
+			return X86_ECONNABORTED;
+		case ECONNRESET:
+			return X86_ECONNRESET;
+		case ENOBUFS:
+			return X86_ENOBUFS;
+		case EISCONN:
+			return X86_EISCONN;
+		case ENOTCONN:
+			return X86_ENOTCONN;
+		case ESHUTDOWN:
+			return X86_ESHUTDOWN;
+		case ETOOMANYREFS:
+			return X86_ETOOMANYREFS;
+		case ETIMEDOUT:
+			return X86_ETIMEDOUT;
+		case ECONNREFUSED:
+			return X86_ECONNREFUSED;
+		case EHOSTDOWN:
+			return X86_EHOSTDOWN;
+		case EHOSTUNREACH:
+			return X86_EHOSTUNREACH;
+		case EALREADY:
+			return X86_EALREADY;
+		case EINPROGRESS:
+			return X86_EINPROGRESS;
+		case ESTALE:
+			return X86_ESTALE;
+		case EUCLEAN:
+			return X86_EUCLEAN;
+		case ENOTNAM:
+			return X86_ENOTNAM;
+		case ENAVAIL:
+			return X86_ENAVAIL;
+		case EISNAM:
+			return X86_EISNAM;
+		case EREMOTEIO:
+			return X86_EREMOTEIO;
+		case EDQUOT:
+			return X86_EDQUOT;
+		case ENOMEDIUM:
+			return X86_ENOMEDIUM;
+		case EMEDIUMTYPE:
+			return X86_EMEDIUMTYPE;
+		case ECANCELED:
+			return X86_ECANCELED;
+	}
+	return ENOSYS;
+}
diff -Nurb qemu-0.9.0/linux-user/x86_sys_socket.c qemu-loongson/linux-user/x86_sys_socket.c
--- qemu-0.9.0/linux-user/x86_sys_socket.c	1970-01-01 08:00:00.000000000 +0800
+++ qemu-loongson/linux-user/x86_sys_socket.c	2007-06-01 23:25:18.000000000 +0800
@@ -0,0 +1,189 @@
+/*
+ * 	x86_sys_socket.c
+ *
+ * 	_socket _connect _bind _listen _accept
+ * 	_send _sendto _recv _recvfrom
+ * 	_getsockopt _setsockopt
+ *
+ * 	x86_gs_sockopt
+ *
+ * 		x86run/syscall
+ * 		Peng Jun
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+
+#define	X86_SOCK_STREAM	1
+#define	X86_SOCK_DGRAM	2
+
+#define	X86_SOL_SOCKET	1
+
+#define X86_SO_DEBUG	1
+#define X86_SO_REUSEADDR	2
+#define X86_SO_TYPE		3
+#define X86_SO_ERROR	4
+#define X86_SO_DONTROUTE	5
+#define X86_SO_BROADCAST	6
+#define X86_SO_SNDBUF	7
+#define X86_SO_RCVBUF	8
+#define X86_SO_KEEPALIVE	9
+#define X86_SO_OOBINLINE	10
+#define X86_SO_NO_CHECK	11
+#define X86_SO_PRIORITY	12
+#define X86_SO_LINGER	13
+#define X86_SO_BSDCOMPAT	14
+#define X86_SO_PASSCRED	16
+#define X86_SO_PEERCRED	17
+#define X86_SO_RCVLOWAT	18
+#define X86_SO_SNDLOWAT	19
+#define X86_SO_RCVTIMEO	20
+#define X86_SO_SNDTIMEO	21
+#define X86_SO_SECURITY_AUTHENTICATION		22
+#define X86_SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define X86_SO_SECURITY_ENCRYPTION_NETWORK		24
+#define X86_SO_BINDTODEVICE	25
+#define X86_SO_ATTACH_FILTER        26
+#define X86_SO_DETACH_FILTER        27
+#define X86_SO_PEERNAME		28
+#define X86_SO_TIMESTAMP		29
+#define X86_SO_ACCEPTCONN		30
+
+
+int x86_gs_sockopt(int x86_so);
+
+
+/*
+ * public
+ */
+int x86_sys_socket(int domain, int type, int protocal)
+{
+	int re;
+	switch(type) {
+		case X86_SOCK_STREAM:
+			type = SOCK_STREAM;
+			break;
+		case X86_SOCK_DGRAM:
+			type = SOCK_DGRAM;
+			break;
+	}
+	re = socket(domain, type, protocal);
+
+	return re;
+}
+
+int x86_sys_getsockopt(int s, int level, int opname, void *optval, int *optlen)
+{
+	int re;
+	switch(level) {
+		case X86_SOL_SOCKET:
+			opname = x86_gs_sockopt(opname);
+			if(opname == -1) {
+				fprintf(stderr,
+					"Unimplemented socket option %d\n",
+						opname);
+				return -1;
+			}
+			re = getsockopt(s, SOL_SOCKET, opname, optval, optlen);
+			break;
+		default:
+			fprintf(stderr, "Unimplemented socket level %d\n",
+					level);
+			return -1;
+	}
+
+	return re;
+}
+
+int x86_sys_setsockopt(int s, int level, int opname, void *optval, int optlen)
+{
+	int re;
+	switch(level) {
+		case X86_SOL_SOCKET:
+			opname = x86_gs_sockopt(opname);
+			if(opname == -1) {
+				fprintf(stderr,
+					"Unimplemented socket option %d\n",
+						opname);
+				return -1;
+			}
+			re = setsockopt(s, SOL_SOCKET, opname, optval, optlen);
+			break;
+		default:
+			fprintf(stderr, "Unimplemented socket level %d\n",
+					level);
+			return -1;
+	}
+
+	return re;
+}
+
+/*
+ * private
+ */
+int x86_gs_sockopt(int x86_so)
+{
+	switch(x86_so) {
+		case X86_SO_DEBUG:
+			return SO_DEBUG;
+		case X86_SO_REUSEADDR:
+			return SO_REUSEADDR;
+		case X86_SO_TYPE:
+			return SO_TYPE;
+		case X86_SO_ERROR:
+			return SO_ERROR;
+		case X86_SO_DONTROUTE:
+			return SO_DONTROUTE;
+		case X86_SO_BROADCAST:
+			return SO_BROADCAST;
+		case X86_SO_SNDBUF:
+			return SO_SNDBUF;
+		case X86_SO_RCVBUF:
+			return SO_RCVBUF;
+		case X86_SO_KEEPALIVE:
+			return SO_KEEPALIVE;
+		case X86_SO_OOBINLINE:
+			return SO_OOBINLINE;
+		case X86_SO_NO_CHECK:
+			return SO_NO_CHECK;
+		case X86_SO_PRIORITY:
+			return SO_PRIORITY;
+		case X86_SO_LINGER:
+			return SO_LINGER;
+		case X86_SO_BSDCOMPAT:
+			return SO_BSDCOMPAT;
+		case X86_SO_PASSCRED:
+			return SO_PASSCRED;
+		case X86_SO_PEERCRED:
+			return SO_PEERCRED;
+		case X86_SO_RCVLOWAT:
+			return SO_RCVLOWAT;
+		case X86_SO_SNDLOWAT:
+			return SO_SNDLOWAT;
+		case X86_SO_RCVTIMEO:
+			return SO_RCVTIMEO;
+		case X86_SO_SNDTIMEO:
+			return SO_SNDTIMEO;
+		case X86_SO_SECURITY_AUTHENTICATION:
+			return SO_SECURITY_AUTHENTICATION;
+		case X86_SO_SECURITY_ENCRYPTION_TRANSPORT:
+			return SO_SECURITY_ENCRYPTION_TRANSPORT;
+		case X86_SO_SECURITY_ENCRYPTION_NETWORK:
+			return SO_SECURITY_ENCRYPTION_NETWORK;
+		case X86_SO_BINDTODEVICE:
+			return SO_BINDTODEVICE;
+		case X86_SO_ATTACH_FILTER:
+			return SO_ATTACH_FILTER;
+		case X86_SO_DETACH_FILTER:
+			return SO_DETACH_FILTER;
+		case X86_SO_PEERNAME:
+			return SO_PEERNAME;
+		case X86_SO_TIMESTAMP:
+			return SO_TIMESTAMP;
+		case X86_SO_ACCEPTCONN:
+			return SO_ACCEPTCONN;		
+	}
+	return -1;
+}
diff -Nurb qemu-0.9.0/Makefile qemu-loongson/Makefile
--- qemu-0.9.0/Makefile	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/Makefile	2007-06-01 23:23:34.000000000 +0800
@@ -34,9 +34,16 @@
 
 all: $(TOOLS) $(DOCS) recurse-all
 
+ifeq ($(ARCH),mips)
+subdir-%: dyngen$(EXESUF) op_mips$(EXESUF)
+	$(MAKE) -C $(subst subdir-,,$@) all
+
+else
 subdir-%: dyngen$(EXESUF)
 	$(MAKE) -C $(subst subdir-,,$@) all
 
+endif
+
 recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
 
 qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
@@ -45,10 +52,16 @@
 dyngen$(EXESUF): dyngen.c
 	$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
 
+ifeq ($(ARCH),mips)
+op_mips$(EXESUF): op_mips.c
+	$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
+
+endif
+
 clean:
 # avoid old build problems by removing potentially incorrect old files
 	rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h 
-	rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
+	rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) op_mips$(EXESUB) TAGS *.pod *~ */*~
 	$(MAKE) -C tests clean
 	for d in $(TARGET_DIRS); do \
 	$(MAKE) -C $$d $@ || exit 1 ; \
diff -Nurb qemu-0.9.0/Makefile.target qemu-loongson/Makefile.target
--- qemu-0.9.0/Makefile.target	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/Makefile.target	2007-06-02 08:19:14.000000000 +0800
@@ -27,6 +27,7 @@
 LIBS=
 HELPER_CFLAGS=$(CFLAGS)
 DYNGEN=../dyngen$(EXESUF)
+OP_MIPS=../op_mips$(EXESUF)
 # user emulator name
 TARGET_ARCH2=$(TARGET_ARCH)
 ifeq ($(TARGET_ARCH),arm)
@@ -160,7 +161,8 @@
 endif
 
 ifeq ($(ARCH),mips)
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+OP_CFLAGS+=-fno-delayed-branch
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -lrt
 endif
 
 ifeq ($(HAVE_GCC3_OPTIONS),yes)
@@ -504,9 +506,22 @@
 gen-op.h: op.o $(DYNGEN)
 	$(DYNGEN) -g -o $@ $<
 
+ifeq ($(ARCH),mips)
+op.o: op2.s
+	$(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ op2.s
+
+op2.s:	op.s
+	$(OP_MIPS) < op.s > op2.s
+
+op.s:	op.c
+	$(CC) $(OP_CFLAGS) $(CPPFLAGS) -S -o op.s $<
+
+else
 op.o: op.c
 	$(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+endif
+
 # HELPER_CFLAGS is used for all the code compiled with static register
 # variables
 ifeq ($(TARGET_BASE_ARCH), i386)
diff -Nurb qemu-0.9.0/mips.ld qemu-loongson/mips.ld
--- qemu-0.9.0/mips.ld	1970-01-01 08:00:00.000000000 +0800
+++ qemu-loongson/mips.ld	2007-06-01 23:23:34.000000000 +0800
@@ -0,0 +1,238 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips",
+	      "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(__start)
+SEARCH_DIR("/usr/mipsel-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .reginfo        : { *(.reginfo) }
+  .dynamic        : { *(.dynamic) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.dyn        :
+    {
+      *(.rel.init)
+      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+      *(.rel.fini)
+      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+      *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
+      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+      *(.rel.ctors)
+      *(.rel.dtors)
+      *(.rel.got)
+      *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*)
+      *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*)
+      *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*)
+      *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*)
+      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+    }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+      *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+      *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+      *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+    }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0
+  .plt            : { *(.plt) }
+  .text           :
+  {
+    _ftext = . ;
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    KEEP (*(.text.*personality*))
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+    *(.mips16.fn.*) *(.mips16.call.*)
+  } =0
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .sdata2         :
+  {
+    *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+  }
+  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (0x40000) - ((0x40000 - .) & (0x40000 - 1)); . = DATA_SEGMENT_ALIGN (0x40000, 0x1000);
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+     PROVIDE_HIDDEN (__init_array_start = .);
+     KEEP (*(SORT(.init_array.*)))
+     KEEP (*(.init_array))
+     PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(.fini_array))
+    KEEP (*(SORT(.fini_array.*)))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin*.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+  . = DATA_SEGMENT_RELRO_END (0, .);
+  .data           :
+  {
+    _fdata = . ;
+    *(.data .data.* .gnu.linkonce.d.*)
+    KEEP (*(.gnu.linkonce.d.*personality*))
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  . = .;
+  _gp = ALIGN(16) + 0x7ff0;
+  .got            : { *(.got.plt) *(.got) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata          :
+  {
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+  }
+  .lit8           : { *(.lit8) }
+  .lit4           : { *(.lit4) }
+  _edata = .; PROVIDE (edata = .);
+  __bss_start = .;
+  _fbss = .;
+  .sbss           :
+  {
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+  }
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 32 / 8 : 1);
+  }
+  . = ALIGN(32 / 8);
+  . = ALIGN(32 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+  .mdebug.abi32 : { KEEP(*(.mdebug.abi32)) }
+  .mdebug.abiN32 : { KEEP(*(.mdebug.abiN32)) }
+  .mdebug.abi64 : { KEEP(*(.mdebug.abi64)) }
+  .mdebug.abiO64 : { KEEP(*(.mdebug.abiO64)) }
+  .mdebug.eabi32 : { KEEP(*(.mdebug.eabi32)) }
+  .mdebug.eabi64 : { KEEP(*(.mdebug.eabi64)) }
+  .gcc_compiled_long32 : { KEEP(*(.gcc_compiled_long32)) }
+  .gcc_compiled_long64 : { KEEP(*(.gcc_compiled_long64)) }
+  /DISCARD/ : { *(.note.GNU-stack) }
+}
diff -Nurb qemu-0.9.0/op_mips.c qemu-loongson/op_mips.c
--- qemu-0.9.0/op_mips.c	1970-01-01 08:00:00.000000000 +0800
+++ qemu-loongson/op_mips.c	2007-06-02 08:13:22.000000000 +0800
@@ -0,0 +1,160 @@
+/*	qemu/op_mips.c
+ *
+ *			Peng Jun <jun7903@163.com>
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//#define	GCC_MNO_ABICALLS
+//#define	QEMU_VERSION_6
+
+#ifdef	QEMU_VERSION_6
+int exit_tb_key = 0;
+char exit_tb_buf[1024];
+char exit_tb_sp[1024];
+
+int line2(char *buf, int num)
+{
+	if(strcmp(buf, "\tj\t$31\n") != 0) {
+		strcat(exit_tb_buf, buf);
+		if(strstr(buf, "$sp"))
+			strcat(exit_tb_sp, buf);
+		strcpy(buf, "");
+		return 0;
+	}
+
+	sprintf(buf, "\
+#EXIT_TB\n\
+%s\
+	j	$31\n\
+	nop\n\
+%s\
+$end_%08X:\n\
+	j	$31\n\
+",
+		exit_tb_sp, exit_tb_buf, num);
+
+	exit_tb_key = 0;
+
+	return 0;
+}
+#endif	/* QEMU_VERSION_6 */
+
+int line(char *buf, int num)
+{
+	char func[256];
+
+#ifdef	QEMU_VERSION_6
+	// exit_tb
+	if(strcmp(buf, "#EXIT_TB\n") == 0) {
+		exit_tb_key = 1;
+		strcpy(buf, "");
+		strcpy(exit_tb_buf, "");
+		strcpy(exit_tb_sp, "");
+		return 0;
+	}
+#endif
+
+	// j $31  --> end_XXX: j $31
+	if(strcmp(buf, "\tj\t$31\n") == 0) {
+		sprintf(buf, "\
+$end_%08X:\n\
+	j	$31\n\
+", num);
+			return 0;
+	}
+
+#ifdef	GCC_MNO_ABICALLS
+
+#ifdef	QEMU_VERSION_6
+	if(strcmp(buf, "\tjal\t$2\n") == 0) {
+		return 0;
+	}
+#else
+	// jal $2  -->  jal $t9  (0.9.0)
+	if(strcmp(buf, "\tjal\t$2\n") == 0) {
+		sprintf(buf, "\
+	move	$25,$2\n\
+	jal	$25\n\
+"
+		);
+		return 0;
+	}
+#endif	/* QEMU_VERSION_6 */
+
+	// jal func  --> lui + addiu
+	if(strncmp(buf, "\tjal\t", 5) == 0) {
+		*(strchr(buf, '\n')) = 0;
+		strcpy(func, buf + 5);
+		sprintf(buf, "\
+	lui	$25,%%hi(%s)\n\
+	addiu	$25,$25,%%lo(%s)\n\
+	jal	$25\n\
+",
+				func, func);
+		return 0;
+	}
+
+#else	/* GCC_MNO_ABICALLS */
+
+	{ char *p, reg[4];
+	// lw $?,%got(var)($28)  -->  lui + addiu
+	if(strstr(buf, "%got")) {
+		if(strncmp(buf, "\tlw\t$", 5))
+			exit(1);
+		p = buf + 4;
+		*strchr(p, ',') = 0;
+		strcpy(reg, p);
+		p = p + strlen(reg) + 1;
+		p = strchr(p, '(') + 1;
+		*strchr(p, ')') = 0;
+		strcpy(func, p);
+		sprintf(buf, "\
+	lui	%s,%%hi(%s)\n\
+	addiu	%s,%s,%%lo(%s)\n\
+",
+				reg, func, reg, reg, func);
+		return 0;
+	}
+
+	// lw $25,%call16(func)($28)  -->  lui + addiu
+	if(strstr(buf, "%call16")) {
+		if(strncmp(buf, "\tlw\t$25,%call16", 15))
+			exit(1);
+		p = strchr(buf, '(') + 1;
+		*strchr(p, ')') = 0;
+		strcpy(func, p);
+		sprintf(buf, "\
+	lui	$25,%%hi(%s)\n\
+	addiu	$25,$25,%%lo(%s)\n\
+",
+				func, func);
+		return 0;
+	}
+	}
+
+#endif	/* GCC_MNO_ABICALLS */
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	char buf[1024];
+	int n = 0;
+
+	while(fgets(buf, 1023, stdin)) {
+#ifdef	QEMU_VERSION_6
+		if(exit_tb_key)
+			line2(buf, n);
+		else
+#endif
+			line(buf, n);
+		printf("%s", buf);
+		n++;
+	}
+	return 0;
+}
diff -Nurb qemu-0.9.0/slirp/mbuf.h qemu-loongson/slirp/mbuf.h
--- qemu-0.9.0/slirp/mbuf.h	2007-02-06 07:01:54.000000000 +0800
+++ qemu-loongson/slirp/mbuf.h	2007-06-01 23:23:34.000000000 +0800
@@ -39,6 +39,12 @@
 
 #define m_freem m_free
 
+#if defined(__mips__)
+#define WORDS_ALIGNED
+#define ATTRIBUTE_ALIGNED __attribute__((aligned (4)))
+#else
+#define ATTRIBUTE_ALIGNED
+#endif
 
 #define MINCSIZE 4096	/* Amount to increase mbuf if too small */
 
@@ -70,7 +76,7 @@
 	int	mh_size;		/* Size of data */
 	struct	socket *mh_so;
 	
-	caddr_t	mh_data;		/* Location of data */
+	caddr_t	mh_data ATTRIBUTE_ALIGNED;		/* Location of data */
 	int	mh_len;			/* Amount of data in this mbuf */
 };
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] qemu on mips patch
@ 2007-06-02 13:58 Jun Peng
  0 siblings, 0 replies; 4+ messages in thread
From: Jun Peng @ 2007-06-02 13:58 UTC (permalink / raw)
  To: qemu-devel

Sorry, sorry, I did send a wrony "cpu_signal_handler()"!

in cpu-exec.c:

#include <sys/user.h>
int cpu_signal_handler(int host_signum, void *pinfo,
                       void *puc)
{
    siginfo_t *info = pinfo;
    struct ucontext *uc = puc;
    unsigned long pc;
    int is_write;

    pc = uc->uc_mcontext.pc;
    /* XXX: compute is_write */
    is_write = 0;
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
                             is_write,
                             &uc->uc_sigmask, puc);
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] qemu on mips patch
  2007-06-02  6:37 [Qemu-devel] qemu on mips patch Jun Peng
@ 2007-06-03 13:30 ` Thiemo Seufer
  0 siblings, 0 replies; 4+ messages in thread
From: Thiemo Seufer @ 2007-06-03 13:30 UTC (permalink / raw)
  To: Jun Peng; +Cc: qemu-devel

Jun Peng wrote:
> Hello!
> 
> Are you are just testing host_mips qemu? I have been doing the same
> work two or three month
> 
> ago on a mips + linux system. But, it have some bugs however.
> 
> It is for qemu 0.6.1 refer to qemu-irix.patch at first. And yesterday,
> I made a qemu 0.9.0
>
> patch. It seems working(only target-i386). In order to handle
> relocation symbol, I writed a
> 
> little tool named op_mips.c. This tool is the key of my patch.

In the meanwhile the latest CVS qemu has preliminary mips host support,
could you refresh you patch to the latest version? I think the current
CVS version does the right thing without relying on on an equivalent
to your op_mips.c tool.

Also, a patch for the errno handling on mips went just in, please
write your version for x86 in the same style, and split it out in a
separate patch.


Thiemo

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] qemu on mips patch
@ 2007-06-07  8:05 Jun Peng
  0 siblings, 0 replies; 4+ messages in thread
From: Jun Peng @ 2007-06-07  8:05 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1252 bytes --]

2007/6/3, Thiemo Seufer <ths@networkno.de>:
> ... I think the current
> CVS version does the right thing without relying on on an equivalent
> to your op_mips.c tool.
> ...


On my computer, I do not think so.

in op.o, -fno-PIC -mno-abicalls
004eb0d4 <op_divb_AL_T0>:
...
  4eb104: afa50010 sw a1,16(sp)
  4eb108: 14600003 bnez v1,4eb118 <op_divb_AL_T0+0x44>
  4eb10c: 00000000 nop
  4eb110: 0c140e12 jal 503848 <raise_exception>
  4eb114: 00000000 nop
  4eb118: 8fa30010 lw v1,16(sp)
  4eb11c: 00002021 move a0,zero

in helper.o, PIC and abicalls
00503848 <raise_exception>:
  503848: 3c1c000c lui gp,0xc
  50384c: 279c0858 addiu gp,gp,2136
  503850: 0399e021 addu gp,gp,t9
  503854: 8f998db8 lw t9,-29256(gp)
  503858: 00002821 move a1,zero
  50385c: 00003021 move a2,zero
  503860: 03200008 jr t9
  503864: 00003821 move a3,zero

When op_divb_AL_T0() calls raise_exception(), $t9 is not address of
raise_exception().

in op.h
case INDEX_op_divb_AL_T0: {
...
    /* R_MIPS_26 RELOC, offset 0x10d0, name raise_exception */
    *(uint32_t *)(gen_code_ptr + 0x3c) = (0xc000000 & ~0x3fffff) |
((0xc000000 + (((long)(&raise_exception) - (*(uint32_t *)(gen_code_ptr +
0x3c))) >> 2))    & 0x3fffff);

jal(R_MIPS_26) is a PC-region branch, not PC-relative.

[-- Attachment #2: Type: text/html, Size: 1692 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-06-07  8:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-02  6:37 [Qemu-devel] qemu on mips patch Jun Peng
2007-06-03 13:30 ` Thiemo Seufer
  -- strict thread matches above, loose matches on Subject: below --
2007-06-02 13:58 Jun Peng
2007-06-07  8:05 Jun Peng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).