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 | 181 | endif |
182 | 182 | |
183 | 183 | ifeq ($(ARCH),mips) |
184 | +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch | |
184 | 185 | ifeq ($(WORDS_BIGENDIAN),yes) |
185 | 186 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld |
186 | 187 | else |
... | ... | @@ -189,6 +190,7 @@ endif |
189 | 190 | endif |
190 | 191 | |
191 | 192 | ifeq ($(ARCH),mips64) |
193 | +OP_CFLAGS+=-G 0 -fomit-frame-pointer -fno-delayed-branch | |
192 | 194 | ifeq ($(WORDS_BIGENDIAN),yes) |
193 | 195 | BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld |
194 | 196 | else | ... | ... |
cpu-all.h
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | #ifndef CPU_ALL_H |
21 | 21 | #define CPU_ALL_H |
22 | 22 | |
23 | -#if defined(__arm__) || defined(__sparc__) | |
23 | +#if defined(__arm__) || defined(__sparc__) || defined(__mips__) | |
24 | 24 | #define WORDS_ALIGNED |
25 | 25 | #endif |
26 | 26 | |
... | ... | @@ -1022,6 +1022,27 @@ static inline int64_t cpu_get_real_ticks (void) |
1022 | 1022 | return rval.i64; |
1023 | 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 | 1046 | #else |
1026 | 1047 | /* The host CPU doesn't have an easily accessible cycle counter. |
1027 | 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 | 1540 | /* XXX: compute is_write */ |
1541 | 1541 | is_write = 0; |
1542 | 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 | 1561 | #else | ... | ... |
dyngen-exec.h
... | ... | @@ -129,10 +129,15 @@ extern int printf(const char *, ...); |
129 | 129 | #define AREG3 "r6" |
130 | 130 | #endif |
131 | 131 | #ifdef __mips__ |
132 | -#define AREG0 "s3" | |
132 | +#define AREG0 "fp" | |
133 | 133 | #define AREG1 "s0" |
134 | 134 | #define AREG2 "s1" |
135 | 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 | 141 | #endif |
137 | 142 | #ifdef __sparc__ |
138 | 143 | #ifdef HOST_SOLARIS |
... | ... | @@ -280,5 +285,9 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3; |
280 | 285 | #ifdef __mc68000 |
281 | 286 | #define EXIT_TB() asm volatile ("rts") |
282 | 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 | 293 | #endif /* !defined(__DYNGEN_EXEC_H__) */ | ... | ... |
dyngen.c
... | ... | @@ -117,6 +117,13 @@ |
117 | 117 | #define elf_check_arch(x) ((x) == EM_68K) |
118 | 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 | 127 | #else |
121 | 128 | #error unsupported CPU - please update the code |
122 | 129 | #endif |
... | ... | @@ -1641,6 +1648,26 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
1641 | 1648 | error("rts expected at the end of %s", name); |
1642 | 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 | 1671 | #else |
1645 | 1672 | #error unsupported CPU |
1646 | 1673 | #endif |
... | ... | @@ -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 | 2578 | #else |
2487 | 2579 | #error unsupported CPU |
2488 | 2580 | #endif | ... | ... |
dyngen.h
... | ... | @@ -463,3 +463,11 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp, |
463 | 463 | } |
464 | 464 | |
465 | 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 | 481 | } |
482 | 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 | 506 | typedef int spinlock_t; |
485 | 507 | |
486 | 508 | #define SPIN_LOCK_UNLOCKED 0 | ... | ... |