Commit c4b89d18ba3b494545266970fe8714bc3d7f5917
1 parent
26ea0918
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
Showing
7 changed files
with
172 additions
and
4 deletions
Makefile.target
| @@ -181,6 +181,7 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld | @@ -181,6 +181,7 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld | ||
| 181 | endif | 181 | endif |
| 182 | 182 | ||
| 183 | ifeq ($(ARCH),mips) | 183 | ifeq ($(ARCH),mips) |
| 184 | +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch | ||
| 184 | ifeq ($(WORDS_BIGENDIAN),yes) | 185 | ifeq ($(WORDS_BIGENDIAN),yes) |
| 185 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld | 186 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld |
| 186 | else | 187 | else |
| @@ -189,6 +190,7 @@ endif | @@ -189,6 +190,7 @@ endif | ||
| 189 | endif | 190 | endif |
| 190 | 191 | ||
| 191 | ifeq ($(ARCH),mips64) | 192 | ifeq ($(ARCH),mips64) |
| 193 | +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch | ||
| 192 | ifeq ($(WORDS_BIGENDIAN),yes) | 194 | ifeq ($(WORDS_BIGENDIAN),yes) |
| 193 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld | 195 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld |
| 194 | else | 196 | else |
cpu-all.h
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | #ifndef CPU_ALL_H | 20 | #ifndef CPU_ALL_H |
| 21 | #define CPU_ALL_H | 21 | #define CPU_ALL_H |
| 22 | 22 | ||
| 23 | -#if defined(__arm__) || defined(__sparc__) | 23 | +#if defined(__arm__) || defined(__sparc__) || defined(__mips__) |
| 24 | #define WORDS_ALIGNED | 24 | #define WORDS_ALIGNED |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| @@ -1022,6 +1022,27 @@ static inline int64_t cpu_get_real_ticks (void) | @@ -1022,6 +1022,27 @@ static inline int64_t cpu_get_real_ticks (void) | ||
| 1022 | return rval.i64; | 1022 | return rval.i64; |
| 1023 | #endif | 1023 | #endif |
| 1024 | } | 1024 | } |
| 1025 | + | ||
| 1026 | +#elif defined(__mips__) | ||
| 1027 | + | ||
| 1028 | +static inline int64_t cpu_get_real_ticks(void) | ||
| 1029 | +{ | ||
| 1030 | +#if __mips_isa_rev >= 2 | ||
| 1031 | + uint32_t count; | ||
| 1032 | + static uint32_t cyc_per_count = 0; | ||
| 1033 | + | ||
| 1034 | + if (!cyc_per_count) | ||
| 1035 | + __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count)); | ||
| 1036 | + | ||
| 1037 | + __asm__ __volatile__("rdhwr %1, $2" : "=r" (count)); | ||
| 1038 | + return (int64_t)(count * cyc_per_count); | ||
| 1039 | +#else | ||
| 1040 | + /* FIXME */ | ||
| 1041 | + static int64_t ticks = 0; | ||
| 1042 | + return ticks++; | ||
| 1043 | +#endif | ||
| 1044 | +} | ||
| 1045 | + | ||
| 1025 | #else | 1046 | #else |
| 1026 | /* The host CPU doesn't have an easily accessible cycle counter. | 1047 | /* The host CPU doesn't have an easily accessible cycle counter. |
| 1027 | Just return a monotonically increasing vlue. This will be totally wrong, | 1048 | Just return a monotonically increasing vlue. This will be totally wrong, |
cpu-exec.c
| @@ -1540,8 +1540,22 @@ int cpu_signal_handler(int host_signum, void *pinfo, | @@ -1540,8 +1540,22 @@ int cpu_signal_handler(int host_signum, void *pinfo, | ||
| 1540 | /* XXX: compute is_write */ | 1540 | /* XXX: compute is_write */ |
| 1541 | is_write = 0; | 1541 | is_write = 0; |
| 1542 | return handle_cpu_signal(pc, (unsigned long)info->si_addr, | 1542 | return handle_cpu_signal(pc, (unsigned long)info->si_addr, |
| 1543 | - is_write, | ||
| 1544 | - &uc->uc_sigmask, puc); | 1543 | + is_write, &uc->uc_sigmask, puc); |
| 1544 | +} | ||
| 1545 | + | ||
| 1546 | +#elif defined(__mips__) | ||
| 1547 | + | ||
| 1548 | +int cpu_signal_handler(int host_signum, struct siginfo *info, | ||
| 1549 | + void *puc) | ||
| 1550 | +{ | ||
| 1551 | + struct ucontext *uc = puc; | ||
| 1552 | + greg_t pc = uc->uc_mcontext.pc; | ||
| 1553 | + int is_write; | ||
| 1554 | + | ||
| 1555 | + /* XXX: compute is_write */ | ||
| 1556 | + is_write = 0; | ||
| 1557 | + return handle_cpu_signal(pc, (unsigned long)info->si_addr, | ||
| 1558 | + is_write, &uc->uc_sigmask, puc); | ||
| 1545 | } | 1559 | } |
| 1546 | 1560 | ||
| 1547 | #else | 1561 | #else |
dyngen-exec.h
| @@ -129,10 +129,15 @@ extern int printf(const char *, ...); | @@ -129,10 +129,15 @@ extern int printf(const char *, ...); | ||
| 129 | #define AREG3 "r6" | 129 | #define AREG3 "r6" |
| 130 | #endif | 130 | #endif |
| 131 | #ifdef __mips__ | 131 | #ifdef __mips__ |
| 132 | -#define AREG0 "s3" | 132 | +#define AREG0 "fp" |
| 133 | #define AREG1 "s0" | 133 | #define AREG1 "s0" |
| 134 | #define AREG2 "s1" | 134 | #define AREG2 "s1" |
| 135 | #define AREG3 "s2" | 135 | #define AREG3 "s2" |
| 136 | +#define AREG4 "s3" | ||
| 137 | +#define AREG5 "s4" | ||
| 138 | +#define AREG6 "s5" | ||
| 139 | +#define AREG7 "s6" | ||
| 140 | +#define AREG8 "s7" | ||
| 136 | #endif | 141 | #endif |
| 137 | #ifdef __sparc__ | 142 | #ifdef __sparc__ |
| 138 | #ifdef HOST_SOLARIS | 143 | #ifdef HOST_SOLARIS |
| @@ -280,5 +285,9 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | @@ -280,5 +285,9 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; | ||
| 280 | #ifdef __mc68000 | 285 | #ifdef __mc68000 |
| 281 | #define EXIT_TB() asm volatile ("rts") | 286 | #define EXIT_TB() asm volatile ("rts") |
| 282 | #endif | 287 | #endif |
| 288 | +#ifdef __mips__ | ||
| 289 | +#define EXIT_TB() asm volatile ("jr $ra") | ||
| 290 | +#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at") | ||
| 291 | +#endif | ||
| 283 | 292 | ||
| 284 | #endif /* !defined(__DYNGEN_EXEC_H__) */ | 293 | #endif /* !defined(__DYNGEN_EXEC_H__) */ |
dyngen.c
| @@ -117,6 +117,13 @@ | @@ -117,6 +117,13 @@ | ||
| 117 | #define elf_check_arch(x) ((x) == EM_68K) | 117 | #define elf_check_arch(x) ((x) == EM_68K) |
| 118 | #define ELF_USES_RELOCA | 118 | #define ELF_USES_RELOCA |
| 119 | 119 | ||
| 120 | +#elif defined(HOST_MIPS) | ||
| 121 | + | ||
| 122 | +#define ELF_CLASS ELFCLASS32 | ||
| 123 | +#define ELF_ARCH EM_MIPS | ||
| 124 | +#define elf_check_arch(x) ((x) == EM_MIPS) | ||
| 125 | +#define ELF_USES_RELOC | ||
| 126 | + | ||
| 120 | #else | 127 | #else |
| 121 | #error unsupported CPU - please update the code | 128 | #error unsupported CPU - please update the code |
| 122 | #endif | 129 | #endif |
| @@ -1641,6 +1648,26 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1641,6 +1648,26 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 1641 | error("rts expected at the end of %s", name); | 1648 | error("rts expected at the end of %s", name); |
| 1642 | copy_size = p - p_start; | 1649 | copy_size = p - p_start; |
| 1643 | } | 1650 | } |
| 1651 | +#elif defined(HOST_MIPS) | ||
| 1652 | + { | ||
| 1653 | +#define INSN_RETURN 0x03e00008 | ||
| 1654 | +#define INSN_NOP 0x00000000 | ||
| 1655 | + | ||
| 1656 | + uint8_t *p = p_end; | ||
| 1657 | + | ||
| 1658 | + if (p < (p_start + 0x8)) { | ||
| 1659 | + error("empty code for %s", name); | ||
| 1660 | + } else { | ||
| 1661 | + uint32_t end_insn1, end_insn2; | ||
| 1662 | + | ||
| 1663 | + p -= 0x8; | ||
| 1664 | + end_insn1 = get32((uint32_t *)(p + 0x0)); | ||
| 1665 | + end_insn2 = get32((uint32_t *)(p + 0x4)); | ||
| 1666 | + if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP) | ||
| 1667 | + error("jr ra not found at end of %s", name); | ||
| 1668 | + } | ||
| 1669 | + copy_size = p - p_start; | ||
| 1670 | + } | ||
| 1644 | #else | 1671 | #else |
| 1645 | #error unsupported CPU | 1672 | #error unsupported CPU |
| 1646 | #endif | 1673 | #endif |
| @@ -2483,6 +2510,71 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -2483,6 +2510,71 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 2483 | } | 2510 | } |
| 2484 | } | 2511 | } |
| 2485 | } | 2512 | } |
| 2513 | +#elif defined(HOST_MIPS) | ||
| 2514 | + { | ||
| 2515 | + for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { | ||
| 2516 | + if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { | ||
| 2517 | + char name[256]; | ||
| 2518 | + int type; | ||
| 2519 | + int addend; | ||
| 2520 | + int reloc_offset; | ||
| 2521 | + | ||
| 2522 | + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | ||
| 2523 | + /* the compiler leave some unnecessary references to the code */ | ||
| 2524 | + if (sym_name[0] == '\0') | ||
| 2525 | + continue; | ||
| 2526 | + get_reloc_expr(name, sizeof(name), sym_name); | ||
| 2527 | + type = ELF32_R_TYPE(rel->r_info); | ||
| 2528 | + addend = get32((uint32_t *)(text + rel->r_offset)); | ||
| 2529 | + reloc_offset = rel->r_offset - start_offset; | ||
| 2530 | + switch (type) { | ||
| 2531 | + case R_MIPS_HI16: | ||
| 2532 | + fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n", | ||
| 2533 | + rel->r_offset, sym_name); | ||
| 2534 | + fprintf(outfile, | ||
| 2535 | + " *(uint32_t *)(gen_code_ptr + 0x%x) = " | ||
| 2536 | + "((*(uint32_t *)(gen_code_ptr + 0x%x)) " | ||
| 2537 | + " & ~0xffff) " | ||
| 2538 | + " | (((%s - 0x8000) >> 16) & 0xffff);\n", | ||
| 2539 | + reloc_offset, reloc_offset, name); | ||
| 2540 | + break; | ||
| 2541 | + case R_MIPS_LO16: | ||
| 2542 | + fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n", | ||
| 2543 | + rel->r_offset, sym_name); | ||
| 2544 | + fprintf(outfile, | ||
| 2545 | + " *(uint32_t *)(gen_code_ptr + 0x%x) = " | ||
| 2546 | + "((*(uint32_t *)(gen_code_ptr + 0x%x)) " | ||
| 2547 | + " & ~0xffff) " | ||
| 2548 | + " | (%s & 0xffff);\n", | ||
| 2549 | + reloc_offset, reloc_offset, name); | ||
| 2550 | + break; | ||
| 2551 | + case R_MIPS_PC16: | ||
| 2552 | + fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n", | ||
| 2553 | + rel->r_offset, sym_name); | ||
| 2554 | + fprintf(outfile, | ||
| 2555 | + " *(uint32_t *)(gen_code_ptr + 0x%x) = " | ||
| 2556 | + "(0x%x & ~0xffff) " | ||
| 2557 | + "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) " | ||
| 2558 | + " & 0xffff);\n", | ||
| 2559 | + reloc_offset, addend, addend, name, reloc_offset); | ||
| 2560 | + break; | ||
| 2561 | + case R_MIPS_GOT16: | ||
| 2562 | + case R_MIPS_CALL16: | ||
| 2563 | + fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n", | ||
| 2564 | + rel->r_offset, sym_name); | ||
| 2565 | + fprintf(outfile, | ||
| 2566 | + " *(uint32_t *)(gen_code_ptr + 0x%x) = " | ||
| 2567 | + "((*(uint32_t *)(gen_code_ptr + 0x%x)) " | ||
| 2568 | + " & ~0xffff) " | ||
| 2569 | + " | (((%s - 0x8000) >> 16) & 0xffff);\n", | ||
| 2570 | + reloc_offset, reloc_offset, name); | ||
| 2571 | + break; | ||
| 2572 | + default: | ||
| 2573 | + error("unsupported MIPS relocation (%d)", type); | ||
| 2574 | + } | ||
| 2575 | + } | ||
| 2576 | + } | ||
| 2577 | + } | ||
| 2486 | #else | 2578 | #else |
| 2487 | #error unsupported CPU | 2579 | #error unsupported CPU |
| 2488 | #endif | 2580 | #endif |
dyngen.h
| @@ -463,3 +463,11 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, | @@ -463,3 +463,11 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, | ||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | #endif | 465 | #endif |
| 466 | + | ||
| 467 | +#ifdef __mips__ | ||
| 468 | +#include <sys/cachectl.h> | ||
| 469 | +static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
| 470 | +{ | ||
| 471 | + _flush_cache ((void *)start, stop - start, BCACHE); | ||
| 472 | +} | ||
| 473 | +#endif |
exec-all.h
| @@ -481,6 +481,28 @@ static inline int testandset (int *p) | @@ -481,6 +481,28 @@ static inline int testandset (int *p) | ||
| 481 | } | 481 | } |
| 482 | #endif | 482 | #endif |
| 483 | 483 | ||
| 484 | +#ifdef __mips__ | ||
| 485 | +static inline int testandset (int *p) | ||
| 486 | +{ | ||
| 487 | + int ret; | ||
| 488 | + | ||
| 489 | + __asm__ __volatile__ ( | ||
| 490 | + " .set push \n" | ||
| 491 | + " .set noat \n" | ||
| 492 | + " .set mips2 \n" | ||
| 493 | + "1: li $1, 1 \n" | ||
| 494 | + " ll %0, %1 \n" | ||
| 495 | + " sc $1, %1 \n" | ||
| 496 | + " bnez $1, 1b \n" | ||
| 497 | + " .set pop " | ||
| 498 | + : "=r" (ret), "+R" (*p) | ||
| 499 | + : | ||
| 500 | + : "memory"); | ||
| 501 | + | ||
| 502 | + return ret; | ||
| 503 | +} | ||
| 504 | +#endif | ||
| 505 | + | ||
| 484 | typedef int spinlock_t; | 506 | typedef int spinlock_t; |
| 485 | 507 | ||
| 486 | #define SPIN_LOCK_UNLOCKED 0 | 508 | #define SPIN_LOCK_UNLOCKED 0 |