X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=target-mips%2Fop_helper.c;h=cb4789cfa58278b5a51dda2358f0af97fddeddca;hb=c960bde13c2f9c807beb1c4e8c16cfde769e136a;hp=dc1040786e4a41908907be5305b393fa38f37ac3;hpb=6af0bf9c7c3ab9ddbf74a3bf34e067761eb43c3d;p=qemu diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index dc10407..cb4789c 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -29,7 +29,6 @@ void cpu_loop_exit(void) longjmp(env->jmp_env, 1); } -__attribute__ (( regparm(2) )) void do_raise_exception_err (uint32_t exception, int error_code) { #if 1 @@ -42,7 +41,6 @@ void do_raise_exception_err (uint32_t exception, int error_code) cpu_loop_exit(); } -__attribute__ (( regparm(1) )) void do_raise_exception (uint32_t exception) { do_raise_exception_err(exception, 0); @@ -116,8 +114,38 @@ void do_msubu (void) } #endif +#if defined(CONFIG_USER_ONLY) +void do_mfc0 (int reg, int sel) +{ + cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel); +} +void do_mtc0 (int reg, int sel) +{ + cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel); +} + +void do_tlbwi (void) +{ + cpu_abort(env, "tlbwi\n"); +} + +void do_tlbwr (void) +{ + cpu_abort(env, "tlbwr\n"); +} + +void do_tlbp (void) +{ + cpu_abort(env, "tlbp\n"); +} + +void do_tlbr (void) +{ + cpu_abort(env, "tlbr\n"); +} +#else + /* CP0 helpers */ -__attribute__ (( regparm(2) )) void do_mfc0 (int reg, int sel) { const unsigned char *rn; @@ -174,11 +202,11 @@ void do_mfc0 (int reg, int sel) case 12: T0 = env->CP0_Status; if (env->hflags & MIPS_HFLAG_UM) - T0 |= CP0St_UM; + T0 |= (1 << CP0St_UM); if (env->hflags & MIPS_HFLAG_ERL) - T0 |= CP0St_ERL; + T0 |= (1 << CP0St_ERL); if (env->hflags & MIPS_HFLAG_EXL) - T0 |= CP0St_EXL; + T0 |= (1 << CP0St_EXL); rn = "Status"; break; case 13: @@ -267,12 +295,10 @@ void do_mfc0 (int reg, int sel) return; } -__attribute__ (( regparm(2) )) void do_mtc0 (int reg, int sel) { const unsigned char *rn; uint32_t val, old, mask; - int i, raise; if (sel != 0 && reg != 16 && reg != 28) { val = -1; @@ -352,7 +378,7 @@ void do_mtc0 (int reg, int sel) old = env->CP0_Status; env->CP0_Status = val; /* If we unmasked an asserted IRQ, raise it */ - mask = 0x0000FC00; + mask = 0x0000FF00; if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", old, val, env->CP0_Cause, old & mask, val & mask, @@ -363,7 +389,7 @@ void do_mtc0 (int reg, int sel) !(env->hflags & MIPS_HFLAG_EXL) && !(env->hflags & MIPS_HFLAG_ERL) && !(env->hflags & MIPS_HFLAG_DM) && - (env->CP0_Cause & mask)) { + (env->CP0_Status & env->CP0_Cause & mask)) { if (logfile) fprintf(logfile, "Raise pending IRQs\n"); env->interrupt_request |= CPU_INTERRUPT_HARD; @@ -379,11 +405,14 @@ void do_mtc0 (int reg, int sel) old = env->CP0_Cause; env->CP0_Cause = val; #if 0 - /* Check if we ever asserted a software IRQ */ - for (i = 0; i < 2; i++) { - mask = 0x100 << i; - if ((val & mask) & !(old & mask)) - mips_set_irq(i); + { + int i; + /* Check if we ever asserted a software IRQ */ + for (i = 0; i < 2; i++) { + mask = 0x100 << i; + if ((val & mask) & !(old & mask)) + mips_set_irq(i); + } } #endif rn = "Cause"; @@ -486,7 +515,6 @@ void do_mtc0 (int reg, int sel) /* TLB management */ #if defined(MIPS_USES_R4K_TLB) -__attribute__ (( regparm(1) )) static void invalidate_tb (int idx) { tlb_t *tlb; @@ -505,7 +533,6 @@ static void invalidate_tb (int idx) } } -__attribute__ (( regparm(1) )) static void fill_tb (int idx) { tlb_t *tlb; @@ -531,8 +558,10 @@ static void fill_tb (int idx) void do_tlbwi (void) { - invalidate_tb(env->CP0_index & 0xF); - fill_tb(env->CP0_index & 0xF); + /* Wildly undefined effects for CP0_index containing a too high value and + MIPS_TLB_NB not being a power of two. But so does real silicon. */ + invalidate_tb(env->CP0_index & (MIPS_TLB_NB - 1)); + fill_tb(env->CP0_index & (MIPS_TLB_NB - 1)); } void do_tlbwr (void) @@ -552,7 +581,7 @@ void do_tlbp (void) tag = (env->CP0_EntryHi & 0xFFFFE000); ASID = env->CP0_EntryHi & 0x000000FF; - for (i = 0; i < 16; i++) { + for (i = 0; i < MIPS_TLB_NB; i++) { tlb = &env->tlb[i]; /* Check ASID, virtual page number & size */ if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { @@ -561,7 +590,7 @@ void do_tlbp (void) break; } } - if (i == 16) { + if (i == MIPS_TLB_NB) { env->CP0_index |= 0x80000000; } } @@ -571,7 +600,7 @@ void do_tlbr (void) tlb_t *tlb; int size; - tlb = &env->tlb[env->CP0_index & 0xF]; + tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; env->CP0_EntryHi = tlb->VPN | tlb->ASID; size = (tlb->end - tlb->VPN) >> 12; env->CP0_PageMask = (size - 1) << 13; @@ -582,7 +611,8 @@ void do_tlbr (void) } #endif -__attribute__ (( regparm(1) )) +#endif /* !CONFIG_USER_ONLY */ + void op_dump_ldst (const unsigned char *func) { if (loglevel) @@ -606,7 +636,6 @@ void debug_eret (void) } } -__attribute__ (( regparm(1) )) void do_pmon (int function) { function /= 2; @@ -632,3 +661,50 @@ void do_pmon (int function) break; } } + +#if !defined(CONFIG_USER_ONLY) + +#define MMUSUFFIX _mmu +#define GETPC() (__builtin_return_address(0)) + +#define SHIFT 0 +#include "softmmu_template.h" + +#define SHIFT 1 +#include "softmmu_template.h" + +#define SHIFT 2 +#include "softmmu_template.h" + +#define SHIFT 3 +#include "softmmu_template.h" + +void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) +{ + TranslationBlock *tb; + CPUState *saved_env; + unsigned long pc; + int ret; + + /* XXX: hack to restore env in all cases, even if not called from + generated code */ + saved_env = env; + env = cpu_single_env; + ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1); + if (ret) { + if (retaddr) { + /* now we have a real cpu fault */ + pc = (unsigned long)retaddr; + tb = tb_find_pc(pc); + if (tb) { + /* the PC is inside the translated code. It means that we have + a virtual CPU fault */ + cpu_restore_state(tb, env, pc, NULL); + } + } + do_raise_exception_err(env->exception_index, env->error_code); + } + env = saved_env; +} + +#endif