diff -Nurb qemu-cvs/Makefile qemu-loongson/Makefile --- qemu-cvs/Makefile 2007-05-20 18:54:50.000000000 +0800 +++ qemu-loongson/Makefile 2007-06-12 22:24:06.000000000 +0800 @@ -25,8 +25,15 @@ LIBS+=$(AIOLIBS) +ifeq ($(ARCH),mips) +subdir-%: dyngen$(EXESUF) op_mips$(EXESUF) + $(MAKE) -C $(subst subdir-,,$@) all + +else all: $(TOOLS) $(DOCS) recurse-all +endif + subdir-%: dyngen$(EXESUF) $(MAKE) -C $(subst subdir-,,$@) all @@ -38,10 +45,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$(EXESUF) TAGS *.pod *~ */*~ $(MAKE) -C tests clean for d in $(TARGET_DIRS); do \ $(MAKE) -C $$d $@ || exit 1 ; \ diff -Nurb qemu-cvs/Makefile.target qemu-loongson/Makefile.target --- qemu-cvs/Makefile.target 2007-06-12 22:20:44.000000000 +0800 +++ qemu-loongson/Makefile.target 2007-06-12 22:27:54.000000000 +0800 @@ -33,6 +33,7 @@ LIBS= HELPER_CFLAGS=$(CFLAGS) DYNGEN=../dyngen$(EXESUF) +OP_MIPS=../op_mips$(EXESUF) # user emulator name TARGET_ARCH2=$(TARGET_ARCH) ifeq ($(TARGET_ARCH),arm) @@ -571,9 +572,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: op.s $(OP_MIPS) + $(OP_MIPS) < $< > $@ + +op.s: op.c + $(CC) $(OP_CFLAGS) $(CPPFLAGS) -S -o $@ $< + +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-cvs/dyngen.c qemu-loongson/dyngen.c --- qemu-cvs/dyngen.c 2007-05-09 06:51:41.000000000 +0800 +++ qemu-loongson/dyngen.c 2007-06-12 22:24:06.000000000 +0800 @@ -2537,16 +2537,6 @@ 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", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "(0x%x & ~0x3fffff) " - "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) " - " & 0x3fffff);\n", - reloc_offset, addend, addend, name, reloc_offset); - break; case R_MIPS_HI16: fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n", rel->r_offset, sym_name); @@ -2554,7 +2544,7 @@ " *(uint32_t *)(gen_code_ptr + 0x%x) = " "((*(uint32_t *)(gen_code_ptr + 0x%x)) " " & ~0xffff) " - " | (((%s - 0x8000) >> 16) & 0xffff);\n", + " | (((%s + 0x8000) >> 16) & 0xffff);\n", reloc_offset, reloc_offset, name); break; case R_MIPS_LO16: @@ -2567,27 +2557,6 @@ " | (%s & 0xffff);\n", reloc_offset, reloc_offset, name); break; - case R_MIPS_PC16: - fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n", - rel->r_offset, sym_name); - fprintf(outfile, - " *(uint32_t *)(gen_code_ptr + 0x%x) = " - "(0x%x & ~0xffff) " - "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) " - " & 0xffff);\n", - reloc_offset, addend, addend, name, reloc_offset); - break; - case R_MIPS_GOT16: - case R_MIPS_CALL16: - fprintf(outfile, " /* 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, name); - break; default: error("unsupported MIPS relocation (%d)", type); } diff -Nurb qemu-cvs/op_mips.c qemu-loongson/op_mips.c --- qemu-cvs/op_mips.c 1970-01-01 08:00:00.000000000 +0800 +++ qemu-loongson/op_mips.c 2007-06-12 22:24:06.000000000 +0800 @@ -0,0 +1,160 @@ +/* qemu/op_mips.c + * + * Peng Jun + */ + + +#include +#include +#include + +#define GCC_MNO_ABICALLS // faster +//#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; +}