qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 5/5] tcg/mips: use direct jumps


From: Aurelien Jarno
Subject: [Qemu-devel] [PATCH 5/5] tcg/mips: use direct jumps
Date: Thu, 22 Oct 2009 21:31:12 +0200

Use direct jumps on MIPS hosts. The jump address has to be written
atomically, so a R_MIPS_26 needs to be used. It means the code
generation buffer should not be bigger than 256MB, and has to be
aligned on a 256MB boundary.

Signed-off-by: Aurelien Jarno <address@hidden>
---
 exec-all.h            |   13 ++++++++++++-
 exec.c                |    7 +++++++
 tcg/mips/tcg-target.c |    3 ++-
 tcg/mips/tcg-target.h |    5 -----
 4 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 820b59e..21d6c91 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -114,7 +114,7 @@ static inline int tlb_set_page(CPUState *env1, target_ulong 
vaddr,
 #define CODE_GEN_AVG_BLOCK_SIZE 64
 #endif
 
-#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || 
defined(__i386__)
+#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || 
defined(__i386__) || defined(__mips__)
 #define USE_DIRECT_JUMP
 #endif
 
@@ -222,6 +222,17 @@ static inline void tb_set_jmp_target1(unsigned long 
jmp_addr, unsigned long addr
     __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
 #endif
 }
+#elif defined(__mips__)
+static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long 
addr)
+{
+    *(uint32_t *)jmp_addr = 0x08000000 | ((addr >> 2) & 0x03ffffff);
+#if QEMU_GNUC_PREREQ(4, 1)
+    void __clear_cache(char *beg, char *end);
+    __clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
+#else
+# error __clear_cache not available
+#endif
+}
 #endif
 
 static inline void tb_set_jmp_target(TranslationBlock *tb,
diff --git a/exec.c b/exec.c
index 076d26b..1d3f48c 100644
--- a/exec.c
+++ b/exec.c
@@ -454,6 +454,13 @@ static void code_gen_alloc(unsigned long tb_size)
         start = (void *) 0x01000000UL;
         if (code_gen_buffer_size > 16 * 1024 * 1024)
             code_gen_buffer_size = 16 * 1024 * 1024;
+#elif defined(__mips__)
+        /* Map the buffer aligned on a 256M boundary, so we can use direct
+           calls and branches (R_MIPS_26 relocation) */
+        flags |= MAP_FIXED;
+        start = (void *) 0x30000000UL;
+        if (code_gen_buffer_size > 256 * 1024 * 1024)
+            code_gen_buffer_size = 256 * 1024 * 1024;
 #endif
         code_gen_buffer = mmap(start, code_gen_buffer_size,
                                PROT_WRITE | PROT_READ | PROT_EXEC,
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 03fdcbf..d445169 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1042,7 +1042,8 @@ static inline void tcg_out_op(TCGContext *s, int opc,
     case INDEX_op_goto_tb:
         if (s->tb_jmp_offset) {
             /* direct jump method */
-            tcg_abort();
+            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
+            s->code_ptr += 4;
         } else {
             /* indirect jump method */
             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, 
(tcg_target_long)(s->tb_next + args[0]));
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index ba91623..3d36100 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -98,10 +98,5 @@ enum {
 
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-#if QEMU_GNUC_PREREQ(4, 1)
-    void __clear_cache(char *beg, char *end);
     __clear_cache((char *) start, (char *) stop);
-#else
-# error __clear_cache not available
-#endif
 }
-- 
1.6.1.3





reply via email to

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