qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] HOST_MIPS: handle relocation of op.o (op_mips.c, patch)
@ 2007-06-12 14:57 Jun Peng
  0 siblings, 0 replies; only message in thread
From: Jun Peng @ 2007-06-12 14:57 UTC (permalink / raw)
  To: qemu-devel

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

Hello,

Let us see "jal R_MIPS_26":
in current CVS version, 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

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 calling PIC/abicalls functions, $25 must contain the address of
the called function. But, At 0x503850, I guess $25 is not
&raise_exception, but &gen_func.

Therefore, before call raise_exception, we must seved the address of
raise_exception into $25. In other words, we must use R_MIPS_HI16 /
R_MIPS_LO16 instead of R_MIPS_26. op_mips.c can take care of this. I
tested it with qemu-0.6.1 and qemu-0.9.0 on loongson + linux.

[-- Attachment #2: qemu-op_mips.patch --]
[-- Type: text/plain, Size: 7365 bytes --]

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 <jun7903cn@gmail.com>
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-06-12 14:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-12 14:57 [Qemu-devel] HOST_MIPS: handle relocation of op.o (op_mips.c, patch) 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).