Merge remote-tracking branch 'remotes/rth/tcg-mips' into staging

* remotes/rth/tcg-mips: (24 commits)
  tcg-mips: Enable direct chaining of TBs
  tcg-mips: Simplify movcond
  tcg-mips: Simplify brcond2
  tcg-mips: Improve setcond eq/ne vs zeros
  tcg-mips: Simplify setcond2
  tcg-mips: Simplify brcond
  tcg-mips: Simplify setcond
  tcg-mips: Commonize opcode implementations
  tcg-mips: Improve add2/sub2
  tcg-mips: Hoist args loads
  tcg-mips: Fix subtract immediate range
  tcg-mips: Name the opcode enumeration
  tcg-mips: Use EXT for AND on mips32r2
  tcg-mips: Use T9 for TCG_TMP1
  tcg-mips: Introduce TCG_TMP0, TCG_TMP1
  tcg-mips: Rearrange register allocation
  tcg-mips: Convert to new_ldst
  tcg-mips: Convert to new qemu_l/st helpers
  tcg-mips: Move softmmu slow path out of line
  tcg-mips: Split large ldst offsets
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-05-27 18:31:02 +01:00
commit 27aa948502
5 changed files with 1128 additions and 1005 deletions

7
configure vendored
View File

@ -4029,11 +4029,14 @@ fi
if test "$pie" = "no" ; then if test "$pie" = "no" ; then
textseg_addr= textseg_addr=
case "$cpu" in case "$cpu" in
arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64 | x32) arm | i386 | ppc* | s390* | sparc* | x86_64 | x32)
# ??? Rationale for choosing this address
textseg_addr=0x60000000 textseg_addr=0x60000000
;; ;;
mips) mips)
textseg_addr=0x400000 # A 256M aligned address, high in the address space, with enough
# room for the code_gen_buffer above it before the stack.
textseg_addr=0x60000000
;; ;;
esac esac
if [ -n "$textseg_addr" ]; then if [ -n "$textseg_addr" ]; then

View File

@ -131,7 +131,7 @@ static inline void tlb_flush(CPUState *cpu, int flush_global)
#if defined(__arm__) || defined(_ARCH_PPC) \ #if defined(__arm__) || defined(_ARCH_PPC) \
|| defined(__x86_64__) || defined(__i386__) \ || defined(__x86_64__) || defined(__i386__) \
|| defined(__sparc__) || defined(__aarch64__) \ || defined(__sparc__) || defined(__aarch64__) \
|| defined(__s390x__) \ || defined(__s390x__) || defined(__mips__) \
|| defined(CONFIG_TCG_INTERPRETER) || defined(CONFIG_TCG_INTERPRETER)
#define USE_DIRECT_JUMP #define USE_DIRECT_JUMP
#endif #endif
@ -268,7 +268,7 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
#endif #endif
} }
#elif defined(__sparc__) #elif defined(__sparc__) || defined(__mips__)
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr); void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
#else #else
#error tb_set_jmp_target1 is missing #error tb_set_jmp_target1 is missing

File diff suppressed because it is too large Load Diff

View File

@ -60,16 +60,14 @@ typedef enum {
TCG_REG_K1, TCG_REG_K1,
TCG_REG_GP, TCG_REG_GP,
TCG_REG_SP, TCG_REG_SP,
TCG_REG_FP, TCG_REG_S8,
TCG_REG_RA, TCG_REG_RA,
TCG_REG_CALL_STACK = TCG_REG_SP,
TCG_AREG0 = TCG_REG_S0,
} TCGReg; } TCGReg;
#define TCG_CT_CONST_ZERO 0x100
#define TCG_CT_CONST_U16 0x200
#define TCG_CT_CONST_S16 0x400
/* used for function call generation */ /* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_SP
#define TCG_TARGET_STACK_ALIGN 8 #define TCG_TARGET_STACK_ALIGN 8
#define TCG_TARGET_CALL_STACK_OFFSET 16 #define TCG_TARGET_CALL_STACK_OFFSET 16
#define TCG_TARGET_CALL_ALIGN_ARGS 1 #define TCG_TARGET_CALL_ALIGN_ARGS 1
@ -120,15 +118,13 @@ extern bool use_mips32r2_instructions;
#define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions #define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions
#define TCG_TARGET_HAS_new_ldst 0 #define TCG_TARGET_HAS_new_ldst 1
/* optional instructions automatically implemented */ /* optional instructions automatically implemented */
#define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */ #define TCG_TARGET_HAS_ext8u_i32 0 /* andi rt, rs, 0xff */
#define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */ #define TCG_TARGET_HAS_ext16u_i32 0 /* andi rt, rs, 0xffff */
#define TCG_AREG0 TCG_REG_S0
#ifdef __OpenBSD__ #ifdef __OpenBSD__
#include <machine/sysarch.h> #include <machine/sysarch.h>
#else #else

View File

@ -475,6 +475,10 @@ static inline PageDesc *page_find(tb_page_addr_t index)
#elif defined(__s390x__) #elif defined(__s390x__)
/* We have a +- 4GB range on the branches; leave some slop. */ /* We have a +- 4GB range on the branches; leave some slop. */
# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024) # define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024)
#elif defined(__mips__)
/* We have a 256MB branch region, but leave room to make sure the
main executable is also within that region. */
# define MAX_CODE_GEN_BUFFER_SIZE (128ul * 1024 * 1024)
#else #else
# define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) # define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
#endif #endif
@ -509,14 +513,47 @@ static inline size_t size_code_gen_buffer(size_t tb_size)
return tb_size; return tb_size;
} }
#ifdef __mips__
/* In order to use J and JAL within the code_gen_buffer, we require
that the buffer not cross a 256MB boundary. */
static inline bool cross_256mb(void *addr, size_t size)
{
return ((uintptr_t)addr ^ ((uintptr_t)addr + size)) & 0xf0000000;
}
/* We weren't able to allocate a buffer without crossing that boundary,
so make do with the larger portion of the buffer that doesn't cross.
Returns the new base of the buffer, and adjusts code_gen_buffer_size. */
static inline void *split_cross_256mb(void *buf1, size_t size1)
{
void *buf2 = (void *)(((uintptr_t)buf1 + size1) & 0xf0000000);
size_t size2 = buf1 + size1 - buf2;
size1 = buf2 - buf1;
if (size1 < size2) {
size1 = size2;
buf1 = buf2;
}
tcg_ctx.code_gen_buffer_size = size1;
return buf1;
}
#endif
#ifdef USE_STATIC_CODE_GEN_BUFFER #ifdef USE_STATIC_CODE_GEN_BUFFER
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
__attribute__((aligned(CODE_GEN_ALIGN))); __attribute__((aligned(CODE_GEN_ALIGN)));
static inline void *alloc_code_gen_buffer(void) static inline void *alloc_code_gen_buffer(void)
{ {
map_exec(static_code_gen_buffer, tcg_ctx.code_gen_buffer_size); void *buf = static_code_gen_buffer;
return static_code_gen_buffer; #ifdef __mips__
if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
}
#endif
map_exec(buf, tcg_ctx.code_gen_buffer_size);
return buf;
} }
#elif defined(USE_MMAP) #elif defined(USE_MMAP)
static inline void *alloc_code_gen_buffer(void) static inline void *alloc_code_gen_buffer(void)
@ -545,20 +582,76 @@ static inline void *alloc_code_gen_buffer(void)
start = 0x40000000ul; start = 0x40000000ul;
# elif defined(__s390x__) # elif defined(__s390x__)
start = 0x90000000ul; start = 0x90000000ul;
# elif defined(__mips__)
/* ??? We ought to more explicitly manage layout for softmmu too. */
# ifdef CONFIG_USER_ONLY
start = 0x68000000ul;
# elif _MIPS_SIM == _ABI64
start = 0x128000000ul;
# else
start = 0x08000000ul;
# endif
# endif # endif
buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size, buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size,
PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0);
return buf == MAP_FAILED ? NULL : buf; if (buf == MAP_FAILED) {
return NULL;
}
#ifdef __mips__
if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
/* Try again, with the original still mapped, to avoid re-aquiring
that 256mb crossing. This time don't specify an address. */
size_t size2, size1 = tcg_ctx.code_gen_buffer_size;
void *buf2 = mmap(NULL, size1, PROT_WRITE | PROT_READ | PROT_EXEC,
flags, -1, 0);
if (buf2 != MAP_FAILED) {
if (!cross_256mb(buf2, size1)) {
/* Success! Use the new buffer. */
munmap(buf, size1);
return buf2;
}
/* Failure. Work with what we had. */
munmap(buf2, size1);
}
/* Split the original buffer. Free the smaller half. */
buf2 = split_cross_256mb(buf, size1);
size2 = tcg_ctx.code_gen_buffer_size;
munmap(buf + (buf == buf2 ? size2 : 0), size1 - size2);
return buf2;
}
#endif
return buf;
} }
#else #else
static inline void *alloc_code_gen_buffer(void) static inline void *alloc_code_gen_buffer(void)
{ {
void *buf = g_malloc(tcg_ctx.code_gen_buffer_size); void *buf = g_malloc(tcg_ctx.code_gen_buffer_size);
if (buf) { if (buf == NULL) {
map_exec(buf, tcg_ctx.code_gen_buffer_size); return NULL;
} }
#ifdef __mips__
if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
void *buf2 = g_malloc(tcg_ctx.code_gen_buffer_size);
if (buf2 != NULL && !cross_256mb(buf2, size1)) {
/* Success! Use the new buffer. */
free(buf);
buf = buf2;
} else {
/* Failure. Work with what we had. Since this is malloc
and not mmap, we can't free the other half. */
free(buf2);
buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
}
}
#endif
map_exec(buf, tcg_ctx.code_gen_buffer_size);
return buf; return buf;
} }
#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */ #endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */