Index: Makefile.target =================================================================== RCS file: /sources/qemu/qemu/Makefile.target,v retrieving revision 1.189 diff -u -b -B -r1.189 Makefile.target --- Makefile.target 31 Jul 2007 01:45:35 -0000 1.189 +++ Makefile.target 31 Jul 2007 20:03:22 -0000 @@ -181,7 +185,7 @@ endif ifeq ($(ARCH),mips) -OP_CFLAGS+=-mabi=32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0 +OP_CFLAGS += -G 0 -fomit-frame-pointer -fno-delayed-branch ifeq ($(WORDS_BIGENDIAN),yes) BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld else Index: dyngen-exec.h =================================================================== RCS file: /sources/qemu/qemu/dyngen-exec.h,v retrieving revision 1.36 diff -u -b -B -r1.36 dyngen-exec.h --- dyngen-exec.h 8 May 2007 23:30:44 -0000 1.36 +++ dyngen-exec.h 31 Jul 2007 20:03:23 -0000 @@ -224,6 +224,16 @@ #define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; }) #define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; }) #define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; }) +#elif 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 #if defined(__APPLE__) static int __op_param1, __op_param2, __op_param3; @@ -271,7 +281,10 @@ #define EXIT_TB() asm volatile ("rts") #elif defined(__mips__) #define EXIT_TB() asm volatile ("jr $ra") -#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at") +#define GOTO_LABEL_PARAM(n) asm volatile (\ + "lui $2,%hi(" ASM_NAME(__op_gen_label) #n ")\n\t" \ + "ori $2,$2,%lo(" ASM_NAME(__op_gen_label)#n ")\n\t" \ + "jr $2") #else #error unsupported CPU #endif Index: dyngen.c =================================================================== RCS file: /sources/qemu/qemu/dyngen.c,v retrieving revision 1.54 diff -u -b -B -r1.54 dyngen.c --- dyngen.c 15 Jul 2007 16:56:08 -0000 1.54 +++ dyngen.c 31 Jul 2007 20:03:26 -0000 @@ -1661,6 +1661,30 @@ #define INSN_RETURN 0x03e00008 #define INSN_NOP 0x00000000 + uint8_t *p = (void *)(p_end - 8); + if (p == p_start) { + error("empty code for %s", name); + } else if (get32((uint32_t *)(p)) != INSN_RETURN) { + error("jr ra expected near the end of %s", name); + } else if (get32((uint32_t *)(p + 4)) != INSN_NOP) { + error("nop expected at the end of %s", name); + } else if ((get32((uint32_t *)(p_start)) >> 16) == 0x3c1c && + (get32((uint32_t *)(p_start + 4)) >> 16) == 0x279c && + get32((uint32_t *)(p_start + 8)) == 0x0399e021) { + /* Skip prologue + lui gp,nn + addiu gp,gp,nn + addu gp,gp,t9 */ + p_start += 12; + start_offset += 12; + } + copy_size = p - p_start; + } +#elif (defined(HOST_MIPS) || defined(HOST_MIPS64)) && 0 + { +#define INSN_RETURN 0x03e00008 +#define INSN_NOP 0x00000000 + uint8_t *p = p_end; if (p < (p_start + 0x8)) { @@ -1671,7 +1695,7 @@ p -= 0x8; end_insn1 = get32((uint32_t *)(p + 0x0)); end_insn2 = get32((uint32_t *)(p + 0x4)); - if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP) + if (end_insn1 != INSN_RETURN || end_insn2 != INSN_NOP) error("jr ra not found at end of %s", name); } copy_size = p - p_start; @@ -2521,11 +2545,17 @@ #elif defined(HOST_MIPS) || defined(HOST_MIPS64) { for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { - if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { + host_ulong r_offset = rel->r_offset; + if (r_offset >= start_offset && r_offset < start_offset + copy_size) { char relname[256]; int type; int addend; - int reloc_offset; + int reloc_offset = r_offset - start_offset; +#if defined(WORDS_BIGENDIAN) + int reloc_offset_lsb = reloc_offset + 2; +#else + int reloc_offset_lsb = reloc_offset; +#endif sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; /* the compiler leave some unnecessary references to the code */ @@ -2534,7 +2564,6 @@ get_reloc_expr(relname, sizeof(relname), sym_name); type = ELF32_R_TYPE(rel->r_info); addend = get32((uint32_t *)(text + rel->r_offset)); - reloc_offset = rel->r_offset - start_offset; switch (type) { case R_MIPS_26: fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n", @@ -2547,24 +2576,12 @@ reloc_offset, addend, addend, relname, reloc_offset); break; case R_MIPS_HI16: - fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (((%s - 0x8000) >> 16) & 0xffff);\n", - reloc_offset, reloc_offset, relname); + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)((uint32_t)(%s) >> 16); // R_MIPS_HI16\n", + reloc_offset_lsb, relname); break; case R_MIPS_LO16: - fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (%s & 0xffff);\n", - reloc_offset, reloc_offset, relname); + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (uint16_t)(%s); // R_MIPS_LO16\n", + reloc_offset_lsb, relname); break; case R_MIPS_PC16: fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n", @@ -2578,14 +2595,10 @@ break; case R_MIPS_GOT16: case R_MIPS_CALL16: - fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n", + /* No need to relocate. */ + fprintf(outfile, " /* R_MIPS_CALL16 / R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n", rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "((*(uint32_t *)(gen_code_ptr + 0x%x)) " - " & ~0xffff) " - " | (((%s - 0x8000) >> 16) & 0xffff);\n", - reloc_offset, reloc_offset, relname); + fprintf(outfile, " (void)%s;\n", relname); break; default: error("unsupported MIPS relocation (%d)", type); Index: dyngen.h =================================================================== RCS file: /sources/qemu/qemu/dyngen.h,v retrieving revision 1.15 diff -u -b -B -r1.15 dyngen.h --- dyngen.h 2 Jul 2007 14:06:26 -0000 1.15 +++ dyngen.h 31 Jul 2007 20:03:26 -0000 @@ -19,7 +19,7 @@ */ int __op_param1, __op_param2, __op_param3; -#if defined(__sparc__) || defined(__arm__) +#if defined(__sparc__) || defined(__arm__) || defined(__mips__) void __op_gen_label1(){} void __op_gen_label2(){} void __op_gen_label3(){} Index: exec-all.h =================================================================== RCS file: /sources/qemu/qemu/exec-all.h,v retrieving revision 1.58 diff -u -b -B -r1.58 exec-all.h --- exec-all.h 2 Jul 2007 14:06:26 -0000 1.58 +++ exec-all.h 31 Jul 2007 20:03:27 -0000 @@ -472,6 +472,20 @@ { int ret; +#if 1 + __asm__ __volatile__( + ".set push\n" + ".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 pop\n" + : "=r" (ret), "=m" (*p)); +#else __asm__ __volatile__ ( " .set push \n" " .set noat \n" @@ -484,6 +498,7 @@ : "=r" (ret), "+R" (*p) : : "memory"); +#endif return ret; }