From: "Jun Peng" <jun7903cn@gmail.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] HOST_MIPS: handle relocation of op.o (op_mips.c, patch)
Date: Tue, 12 Jun 2007 22:57:04 +0800 [thread overview]
Message-ID: <ab4614040706120757q717fd36bkcc9e40811edeea2@mail.gmail.com> (raw)
[-- 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;
+}
reply other threads:[~2007-06-12 14:57 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ab4614040706120757q717fd36bkcc9e40811edeea2@mail.gmail.com \
--to=jun7903cn@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).