From c4b89d18ba3b494545266970fe8714bc3d7f5917 Mon Sep 17 00:00:00 2001 From: ths Date: Sat, 5 May 2007 19:23:11 +0000 Subject: [PATCH] Some bits of Linux/MIPS host support, still segfaulty. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2771 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile.target | 2 ++ cpu-all.h | 23 +++++++++++++- cpu-exec.c | 18 +++++++++-- dyngen-exec.h | 11 ++++++- dyngen.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dyngen.h | 8 +++++ exec-all.h | 22 +++++++++++++ 7 files changed, 172 insertions(+), 4 deletions(-) diff --git a/Makefile.target b/Makefile.target index 6a5ff90..9bb12c2 100644 --- a/Makefile.target +++ b/Makefile.target @@ -181,6 +181,7 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld endif ifeq ($(ARCH),mips) +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch ifeq ($(WORDS_BIGENDIAN),yes) BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld else @@ -189,6 +190,7 @@ endif endif ifeq ($(ARCH),mips64) +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch ifeq ($(WORDS_BIGENDIAN),yes) BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld else diff --git a/cpu-all.h b/cpu-all.h index 0aa3843..920a0f7 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -20,7 +20,7 @@ #ifndef CPU_ALL_H #define CPU_ALL_H -#if defined(__arm__) || defined(__sparc__) +#if defined(__arm__) || defined(__sparc__) || defined(__mips__) #define WORDS_ALIGNED #endif @@ -1022,6 +1022,27 @@ static inline int64_t cpu_get_real_ticks (void) return rval.i64; #endif } + +#elif defined(__mips__) + +static inline int64_t cpu_get_real_ticks(void) +{ +#if __mips_isa_rev >= 2 + uint32_t count; + static uint32_t cyc_per_count = 0; + + if (!cyc_per_count) + __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count)); + + __asm__ __volatile__("rdhwr %1, $2" : "=r" (count)); + return (int64_t)(count * cyc_per_count); +#else + /* FIXME */ + static int64_t ticks = 0; + return ticks++; +#endif +} + #else /* The host CPU doesn't have an easily accessible cycle counter. Just return a monotonically increasing vlue. This will be totally wrong, diff --git a/cpu-exec.c b/cpu-exec.c index 4777bab..cd74412 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -1540,8 +1540,22 @@ int cpu_signal_handler(int host_signum, void *pinfo, /* XXX: compute is_write */ is_write = 0; return handle_cpu_signal(pc, (unsigned long)info->si_addr, - is_write, - &uc->uc_sigmask, puc); + is_write, &uc->uc_sigmask, puc); +} + +#elif defined(__mips__) + +int cpu_signal_handler(int host_signum, struct siginfo *info, + void *puc) +{ + struct ucontext *uc = puc; + greg_t pc = uc->uc_mcontext.pc; + int is_write; + + /* XXX: compute is_write */ + is_write = 0; + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + is_write, &uc->uc_sigmask, puc); } #else diff --git a/dyngen-exec.h b/dyngen-exec.h index 69c3cd9..8ceb230 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -129,10 +129,15 @@ extern int printf(const char *, ...); #define AREG3 "r6" #endif #ifdef __mips__ -#define AREG0 "s3" +#define AREG0 "fp" #define AREG1 "s0" #define AREG2 "s1" #define AREG3 "s2" +#define AREG4 "s3" +#define AREG5 "s4" +#define AREG6 "s5" +#define AREG7 "s6" +#define AREG8 "s7" #endif #ifdef __sparc__ #ifdef HOST_SOLARIS @@ -280,5 +285,9 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; #ifdef __mc68000 #define EXIT_TB() asm volatile ("rts") #endif +#ifdef __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") +#endif #endif /* !defined(__DYNGEN_EXEC_H__) */ diff --git a/dyngen.c b/dyngen.c index 953b36c..dd46ea0 100644 --- a/dyngen.c +++ b/dyngen.c @@ -117,6 +117,13 @@ #define elf_check_arch(x) ((x) == EM_68K) #define ELF_USES_RELOCA +#elif defined(HOST_MIPS) + +#define ELF_CLASS ELFCLASS32 +#define ELF_ARCH EM_MIPS +#define elf_check_arch(x) ((x) == EM_MIPS) +#define ELF_USES_RELOC + #else #error unsupported CPU - please update the code #endif @@ -1641,6 +1648,26 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, error("rts expected at the end of %s", name); copy_size = p - p_start; } +#elif defined(HOST_MIPS) + { +#define INSN_RETURN 0x03e00008 +#define INSN_NOP 0x00000000 + + uint8_t *p = p_end; + + if (p < (p_start + 0x8)) { + error("empty code for %s", name); + } else { + uint32_t end_insn1, end_insn2; + + 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) + error("jr ra not found at end of %s", name); + } + copy_size = p - p_start; + } #else #error unsupported CPU #endif @@ -2483,6 +2510,71 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, } } } +#elif defined(HOST_MIPS) + { + for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { + if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { + char name[256]; + int type; + int addend; + int reloc_offset; + + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; + /* the compiler leave some unnecessary references to the code */ + if (sym_name[0] == '\0') + continue; + get_reloc_expr(name, sizeof(name), 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_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, name); + 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, 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); + } + } + } + } #else #error unsupported CPU #endif diff --git a/dyngen.h b/dyngen.h index 2a87c44..e8bf72b 100644 --- a/dyngen.h +++ b/dyngen.h @@ -463,3 +463,11 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, } #endif + +#ifdef __mips__ +#include +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ + _flush_cache ((void *)start, stop - start, BCACHE); +} +#endif diff --git a/exec-all.h b/exec-all.h index cb8936a..bc118c8 100644 --- a/exec-all.h +++ b/exec-all.h @@ -481,6 +481,28 @@ static inline int testandset (int *p) } #endif +#ifdef __mips__ +static inline int testandset (int *p) +{ + int ret; + + __asm__ __volatile__ ( + " .set push \n" + " .set noat \n" + " .set mips2 \n" + "1: li $1, 1 \n" + " ll %0, %1 \n" + " sc $1, %1 \n" + " bnez $1, 1b \n" + " .set pop " + : "=r" (ret), "+R" (*p) + : + : "memory"); + + return ret; +} +#endif + typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 -- 1.7.9.5