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 +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 +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 +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 +#ifdef __mips__ +#define __KERNEL__ #include +#undef __KERNEL__ +#else +#include +#endif #include #include #include @@ -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 + + +#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 +#include +#include + + +#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 + */ + + +#include +#include +#include + +//#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 */ };