qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] QEMU Mips Host


From: Stefan Weil
Subject: [Qemu-devel] [PATCH] QEMU Mips Host
Date: Tue, 31 Jul 2007 22:49:23 +0200
User-agent: IceDove 1.5.0.12 (X11/20070607)

Some parts for a working mips host are still missing
in QEMU CVS HEAD.

Here is a new patch which makes mips host work for
system emulation.

I tested it with i386-softmmu/qemu, mips-softmmu/qemu-system-mips
and mipsel-softmmu/qemu-system-mipsel running on
an emulated malta (big and little endian, 32 bit) machine.

I could not test it with 64 bit mips host.

User mode emulation does not work (it does not work with
i386 host, too).

These parts of my patch are essential to get a working emulation:

Makefile.target:
       compiler flags for mips op.o

dyngen-exec.h:
       declarations for PARAM1, PARAM2 and PARAM3
       declaration for GOTO_LABEL_PARAM

dyngen.c:
       fixes for gen_code() and relocation code

dyngen.h:
exec-all.h:
       I'm not sure whether these changes are needed.
       At least it works with the changes...

Stefan

Thiemo Seufer schrieb:
> Stefan Weil wrote:
> [snip]
>
> I cherrypicked the easy bits, and will look at the rest when I have
> more time.
>> When I started to write MIPS host, I found it difficult to
>> get all locations which needed new code. To make it easier for
>> new ports, I changed sequences of #if ... #endif, #if ... #endif
>> into #if ... #elif ... #elif ... #else #error #endif.
>
> Some of those folded unrelated things together, I committed a different
> patch based on yours.
>> Most important was Johannes code for testandset and PARAMn.
> AFAICS that testandset implementation is broken, and I think
> mine is correct, maybe except for the +R vs. +m bit in the asm
> constraints.
>
> Did my implementation fail for you?
>> The patch still includes your relocation code, but it is disabled
>> and uses my own code. I had no time to check or try the differences.
>
> Then I gather there's no particular reason why my _PC16 reloc code
> is deleted in the patch.
>
> Thiemo
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;
 }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]