* [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).