22 |
|
|
23 |
#define MIPS_DEBUG_DISAS |
#define MIPS_DEBUG_DISAS |
24 |
|
|
25 |
|
#define GETPC() (__builtin_return_address(0)) |
26 |
|
|
27 |
/*****************************************************************************/ |
/*****************************************************************************/ |
28 |
/* Exceptions processing helpers */ |
/* Exceptions processing helpers */ |
29 |
void cpu_loop_exit(void) |
void cpu_loop_exit(void) |
48 |
do_raise_exception_err(exception, 0); |
do_raise_exception_err(exception, 0); |
49 |
} |
} |
50 |
|
|
51 |
|
void do_restore_state (void *pc_ptr) |
52 |
|
{ |
53 |
|
TranslationBlock *tb; |
54 |
|
unsigned long pc = (unsigned long) pc_ptr; |
55 |
|
|
56 |
|
tb = tb_find_pc (pc); |
57 |
|
cpu_restore_state (tb, env, pc, NULL); |
58 |
|
} |
59 |
|
|
60 |
|
void do_raise_exception_direct (uint32_t exception) |
61 |
|
{ |
62 |
|
do_restore_state (GETPC ()); |
63 |
|
do_raise_exception_err (exception, 0); |
64 |
|
} |
65 |
|
|
66 |
#define MEMSUFFIX _raw |
#define MEMSUFFIX _raw |
67 |
#include "op_helper_mem.c" |
#include "op_helper_mem.c" |
68 |
#undef MEMSUFFIX |
#undef MEMSUFFIX |
90 |
|
|
91 |
void do_mult (void) |
void do_mult (void) |
92 |
{ |
{ |
93 |
set_HILO((int64_t)T0 * (int64_t)T1); |
set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
94 |
} |
} |
95 |
|
|
96 |
void do_multu (void) |
void do_multu (void) |
102 |
{ |
{ |
103 |
int64_t tmp; |
int64_t tmp; |
104 |
|
|
105 |
tmp = ((int64_t)T0 * (int64_t)T1); |
tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
106 |
set_HILO((int64_t)get_HILO() + tmp); |
set_HILO((int64_t)get_HILO() + tmp); |
107 |
} |
} |
108 |
|
|
118 |
{ |
{ |
119 |
int64_t tmp; |
int64_t tmp; |
120 |
|
|
121 |
tmp = ((int64_t)T0 * (int64_t)T1); |
tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1); |
122 |
set_HILO((int64_t)get_HILO() - tmp); |
set_HILO((int64_t)get_HILO() - tmp); |
123 |
} |
} |
124 |
|
|
370 |
val = T0 & 0xFFFFF0FF; |
val = T0 & 0xFFFFF0FF; |
371 |
old = env->CP0_EntryHi; |
old = env->CP0_EntryHi; |
372 |
env->CP0_EntryHi = val; |
env->CP0_EntryHi = val; |
373 |
|
/* If the ASID changes, flush qemu's TLB. */ |
374 |
|
if ((old & 0xFF) != (val & 0xFF)) |
375 |
|
tlb_flush (env, 1); |
376 |
rn = "EntryHi"; |
rn = "EntryHi"; |
377 |
break; |
break; |
378 |
case 11: |
case 11: |
545 |
addr = tlb->PFN[0]; |
addr = tlb->PFN[0]; |
546 |
end = addr + (tlb->end - tlb->VPN); |
end = addr + (tlb->end - tlb->VPN); |
547 |
tb_invalidate_page_range(addr, end); |
tb_invalidate_page_range(addr, end); |
548 |
|
/* FIXME: Might be faster to just invalidate the whole "tlb" here |
549 |
|
and refill it on demand from our simulated TLB. */ |
550 |
|
addr = tlb->VPN; |
551 |
|
while (addr < tlb->end) { |
552 |
|
tlb_flush_page (env, addr); |
553 |
|
addr += TARGET_PAGE_SIZE; |
554 |
|
} |
555 |
} |
} |
556 |
if (tlb->V[1]) { |
if (tlb->V[1]) { |
557 |
addr = tlb->PFN[1]; |
addr = tlb->PFN[1]; |
558 |
end = addr + (tlb->end - tlb->VPN); |
end = addr + (tlb->end - tlb->VPN); |
559 |
tb_invalidate_page_range(addr, end); |
tb_invalidate_page_range(addr, end); |
560 |
|
/* FIXME: Might be faster to just invalidate the whole "tlb" here |
561 |
|
and refill it on demand from our simulated TLB. */ |
562 |
|
addr = tlb->end; |
563 |
|
while (addr < tlb->end2) { |
564 |
|
tlb_flush_page (env, addr); |
565 |
|
addr += TARGET_PAGE_SIZE; |
566 |
|
} |
567 |
} |
} |
568 |
} |
} |
569 |
|
|
579 |
size = env->CP0_PageMask >> 13; |
size = env->CP0_PageMask >> 13; |
580 |
size = 4 * (size + 1); |
size = 4 * (size + 1); |
581 |
tlb->end = tlb->VPN + (1 << (8 + size)); |
tlb->end = tlb->VPN + (1 << (8 + size)); |
582 |
|
tlb->end2 = tlb->end + (1 << (8 + size)); |
583 |
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; |
584 |
tlb->V[0] = env->CP0_EntryLo0 & 2; |
tlb->V[0] = env->CP0_EntryLo0 & 2; |
585 |
tlb->D[0] = env->CP0_EntryLo0 & 4; |
tlb->D[0] = env->CP0_EntryLo0 & 4; |
636 |
int size; |
int size; |
637 |
|
|
638 |
tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; |
tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; |
639 |
|
|
640 |
|
/* If this will change the current ASID, flush qemu's TLB. */ |
641 |
|
/* FIXME: Could avoid flushing things which match global entries... */ |
642 |
|
if ((env->CP0_EntryHi & 0xFF) != tlb->ASID) |
643 |
|
tlb_flush (env, 1); |
644 |
|
|
645 |
env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
646 |
size = (tlb->end - tlb->VPN) >> 12; |
size = (tlb->end - tlb->VPN) >> 12; |
647 |
env->CP0_PageMask = (size - 1) << 13; |
env->CP0_PageMask = (size - 1) << 13; |
705 |
|
|
706 |
#if !defined(CONFIG_USER_ONLY) |
#if !defined(CONFIG_USER_ONLY) |
707 |
|
|
708 |
|
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr); |
709 |
|
|
710 |
#define MMUSUFFIX _mmu |
#define MMUSUFFIX _mmu |
711 |
#define GETPC() (__builtin_return_address(0)) |
#define ALIGNED_ONLY |
712 |
|
|
713 |
#define SHIFT 0 |
#define SHIFT 0 |
714 |
#include "softmmu_template.h" |
#include "softmmu_template.h" |
722 |
#define SHIFT 3 |
#define SHIFT 3 |
723 |
#include "softmmu_template.h" |
#include "softmmu_template.h" |
724 |
|
|
725 |
|
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr) |
726 |
|
{ |
727 |
|
env->CP0_BadVAddr = addr; |
728 |
|
do_restore_state (retaddr); |
729 |
|
do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL); |
730 |
|
} |
731 |
|
|
732 |
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) |
void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) |
733 |
{ |
{ |
734 |
TranslationBlock *tb; |
TranslationBlock *tb; |