25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_coproc.c,v 1.62 2007/02/03 16:18:56 debug Exp $ |
* $Id: cpu_mips_coproc.c,v 1.69 2007/06/15 18:07:08 debug Exp $ |
29 |
* |
* |
30 |
* Emulation of MIPS coprocessors. |
* Emulation of MIPS coprocessors. |
31 |
*/ |
*/ |
48 |
#include "timer.h" |
#include "timer.h" |
49 |
|
|
50 |
|
|
|
#ifndef ENABLE_MIPS |
|
|
|
|
|
|
|
|
struct mips_coproc *mips_coproc_new(struct cpu *cpu, int coproc_nr) |
|
|
{ return NULL; } |
|
|
|
|
|
void mips_coproc_tlb_set_entry(struct cpu *cpu, int entrynr, int size, |
|
|
uint64_t vaddr, uint64_t paddr0, uint64_t paddr1, |
|
|
int valid0, int valid1, int dirty0, int dirty1, int global, int asid, |
|
|
int cachealgo0, int cachealgo1) { } |
|
|
|
|
|
|
|
|
#else /* ENABLE_MIPS */ |
|
|
|
|
|
|
|
51 |
extern volatile int single_step; |
extern volatile int single_step; |
52 |
|
|
53 |
static char *cop0_names[] = COP0_NAMES; |
static char *cop0_names[] = COP0_NAMES; |
84 |
; |
; |
85 |
/* Config select 1: caches etc. TODO: Don't use |
/* Config select 1: caches etc. TODO: Don't use |
86 |
cpu->machine for this stuff! */ |
cpu->machine for this stuff! */ |
87 |
IB = cpu->machine->cache_picache_linesize - 1; |
IB = cpu->cd.mips.cache_picache_linesize - 1; |
88 |
IB = IB < 0? 0 : (IB > 7? 7 : IB); |
IB = IB < 0? 0 : (IB > 7? 7 : IB); |
89 |
DB = cpu->machine->cache_pdcache_linesize - 1; |
DB = cpu->cd.mips.cache_pdcache_linesize - 1; |
90 |
DB = DB < 0? 0 : (DB > 7? 7 : DB); |
DB = DB < 0? 0 : (DB > 7? 7 : DB); |
91 |
IC = cpu->machine->cache_picache - |
IC = cpu->cd.mips.cache_picache - |
92 |
cpu->machine->cache_picache_linesize - 7; |
cpu->cd.mips.cache_picache_linesize - 7; |
93 |
DC = cpu->machine->cache_pdcache - |
DC = cpu->cd.mips.cache_pdcache - |
94 |
cpu->machine->cache_pdcache_linesize - 7; |
cpu->cd.mips.cache_pdcache_linesize - 7; |
95 |
IA = cpu->cd.mips.cpu_type.piways - 1; |
IA = cpu->cd.mips.cpu_type.piways - 1; |
96 |
DA = cpu->cd.mips.cpu_type.pdways - 1; |
DA = cpu->cd.mips.cpu_type.pdways - 1; |
97 |
cpu->cd.mips.cop0_config_select1 = |
cpu->cd.mips.cop0_config_select1 = |
119 |
break; |
break; |
120 |
case MIPS_R4000: /* according to the R4000 manual */ |
case MIPS_R4000: /* according to the R4000 manual */ |
121 |
case MIPS_R4600: |
case MIPS_R4600: |
122 |
IB = cpu->machine->cache_picache_linesize - 4; |
IB = cpu->cd.mips.cache_picache_linesize - 4; |
123 |
IB = IB < 0? 0 : (IB > 1? 1 : IB); |
IB = IB < 0? 0 : (IB > 1? 1 : IB); |
124 |
DB = cpu->machine->cache_pdcache_linesize - 4; |
DB = cpu->cd.mips.cache_pdcache_linesize - 4; |
125 |
DB = DB < 0? 0 : (DB > 1? 1 : DB); |
DB = DB < 0? 0 : (DB > 1? 1 : DB); |
126 |
SB = cpu->machine->cache_secondary_linesize - 4; |
SB = cpu->cd.mips.cache_secondary_linesize - 4; |
127 |
SB = SB < 0? 0 : (SB > 3? 3 : SB); |
SB = SB < 0? 0 : (SB > 3? 3 : SB); |
128 |
IC = cpu->machine->cache_picache - 12; |
IC = cpu->cd.mips.cache_picache - 12; |
129 |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
130 |
DC = cpu->machine->cache_pdcache - 12; |
DC = cpu->cd.mips.cache_pdcache - 12; |
131 |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
132 |
SC = cpu->machine->cache_secondary? 0 : 1; |
SC = cpu->cd.mips.cache_secondary? 0 : 1; |
133 |
c->reg[COP0_CONFIG] = |
c->reg[COP0_CONFIG] = |
134 |
( 0 << 31) /* Master/Checker present bit */ |
( 0 << 31) /* Master/Checker present bit */ |
135 |
| (0x00 << 28) /* EC: system clock divisor, |
| (0x00 << 28) /* EC: system clock divisor, |
161 |
; |
; |
162 |
break; |
break; |
163 |
case MIPS_R4100: /* According to the VR4131 manual: */ |
case MIPS_R4100: /* According to the VR4131 manual: */ |
164 |
IB = cpu->machine->cache_picache_linesize - 4; |
IB = cpu->cd.mips.cache_picache_linesize - 4; |
165 |
IB = IB < 0? 0 : (IB > 1? 1 : IB); |
IB = IB < 0? 0 : (IB > 1? 1 : IB); |
166 |
DB = cpu->machine->cache_pdcache_linesize - 4; |
DB = cpu->cd.mips.cache_pdcache_linesize - 4; |
167 |
DB = DB < 0? 0 : (DB > 1? 1 : DB); |
DB = DB < 0? 0 : (DB > 1? 1 : DB); |
168 |
IC = cpu->machine->cache_picache - 10; |
IC = cpu->cd.mips.cache_picache - 10; |
169 |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
170 |
DC = cpu->machine->cache_pdcache - 10; |
DC = cpu->cd.mips.cache_pdcache - 10; |
171 |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
172 |
c->reg[COP0_CONFIG] = |
c->reg[COP0_CONFIG] = |
173 |
( 0 << 31) /* IS: Instruction Streaming bit */ |
( 0 << 31) /* IS: Instruction Streaming bit */ |
232 |
case MIPS_R10000: |
case MIPS_R10000: |
233 |
case MIPS_R12000: |
case MIPS_R12000: |
234 |
case MIPS_R14000: |
case MIPS_R14000: |
235 |
IC = cpu->machine->cache_picache - 12; |
IC = cpu->cd.mips.cache_picache - 12; |
236 |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
IC = IC < 0? 0 : (IC > 7? 7 : IC); |
237 |
DC = cpu->machine->cache_pdcache - 12; |
DC = cpu->cd.mips.cache_pdcache - 12; |
238 |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
DC = DC < 0? 0 : (DC > 7? 7 : DC); |
239 |
SC = cpu->machine->cache_secondary - 19; |
SC = cpu->cd.mips.cache_secondary - 19; |
240 |
SC = SC < 0? 0 : (SC > 7? 7 : SC); |
SC = SC < 0? 0 : (SC > 7? 7 : SC); |
241 |
/* According to the R10000 User's Manual: */ |
/* According to the R10000 User's Manual: */ |
242 |
c->reg[COP0_CONFIG] = |
c->reg[COP0_CONFIG] = |
359 |
{ |
{ |
360 |
struct mips_coproc *c; |
struct mips_coproc *c; |
361 |
|
|
362 |
c = malloc(sizeof(struct mips_coproc)); |
CHECK_ALLOCATION(c = malloc(sizeof(struct mips_coproc))); |
|
if (c == NULL) { |
|
|
fprintf(stderr, "out of memory\n"); |
|
|
exit(1); |
|
|
} |
|
|
|
|
363 |
memset(c, 0, sizeof(struct mips_coproc)); |
memset(c, 0, sizeof(struct mips_coproc)); |
364 |
|
|
365 |
c->coproc_nr = coproc_nr; |
c->coproc_nr = coproc_nr; |
366 |
|
|
367 |
if (coproc_nr == 0) { |
if (coproc_nr == 0) { |
516 |
* |
* |
517 |
* Note: In the R3000 case, the asid argument is shifted 6 bits. |
* Note: In the R3000 case, the asid argument is shifted 6 bits. |
518 |
*/ |
*/ |
519 |
static void invalidate_asid(struct cpu *cpu, int asid) |
static void invalidate_asid(struct cpu *cpu, unsigned int asid) |
520 |
{ |
{ |
521 |
struct mips_coproc *cp = cpu->cd.mips.coproc[0]; |
struct mips_coproc *cp = cpu->cd.mips.coproc[0]; |
522 |
int i, ntlbs = cp->nr_of_tlbs; |
unsigned int i, ntlbs = cp->nr_of_tlbs; |
523 |
struct mips_tlb *tlb = cp->tlbs; |
struct mips_tlb *tlb = cp->tlbs; |
524 |
|
|
525 |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) { |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K) { |
664 |
int readonly = 0; |
int readonly = 0; |
665 |
uint64_t tmp = *ptr; |
uint64_t tmp = *ptr; |
666 |
uint64_t tmp2 = 0, old; |
uint64_t tmp2 = 0, old; |
667 |
int inval = 0, old_asid, oldmode; |
int inval = 0; |
668 |
|
unsigned int old_asid; |
669 |
|
uint64_t oldmode; |
670 |
|
|
671 |
switch (cp->coproc_nr) { |
switch (cp->coproc_nr) { |
672 |
case 0: |
case 0: |
960 |
cp->coproc_nr, reg_nr, cp->coproc_nr==0? |
cp->coproc_nr, reg_nr, cp->coproc_nr==0? |
961 |
cop0_names[reg_nr] : "?", (long long)tmp); |
cop0_names[reg_nr] : "?", (long long)tmp); |
962 |
|
|
963 |
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, |
/* mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, |
964 |
cp->coproc_nr, 0, 0, 0); |
cp->coproc_nr, 0, 0, 0); |
965 |
return; |
return; */ |
966 |
} |
} |
967 |
|
|
968 |
if (readonly) { |
if (readonly) { |
1783 |
int pfn_shift = 12, vpn_shift = 12; |
int pfn_shift = 12, vpn_shift = 12; |
1784 |
int wf0, wf1, mask; |
int wf0, wf1, mask; |
1785 |
uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp; |
uint64_t vaddr0, vaddr1, paddr0, paddr1, ptmp; |
1786 |
|
uint64_t psize; |
1787 |
|
|
1788 |
cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK]; |
cp->tlbs[index].mask = cp->reg[COP0_PAGEMASK]; |
1789 |
cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI]; |
cp->tlbs[index].hi = cp->reg[COP0_ENTRYHI]; |
1822 |
} |
} |
1823 |
|
|
1824 |
paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK) |
paddr0 = ((cp->tlbs[index].lo0 & ENTRYLO_PFN_MASK) |
1825 |
>> ENTRYLO_PFN_SHIFT) << pfn_shift; |
>> ENTRYLO_PFN_SHIFT) << pfn_shift |
1826 |
|
>> vpn_shift << vpn_shift; |
1827 |
paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK) |
paddr1 = ((cp->tlbs[index].lo1 & ENTRYLO_PFN_MASK) |
1828 |
>> ENTRYLO_PFN_SHIFT) << pfn_shift; |
>> ENTRYLO_PFN_SHIFT) << pfn_shift |
1829 |
|
>> vpn_shift << vpn_shift; |
1830 |
|
|
1831 |
if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { |
if (cpu->cd.mips.cpu_type.mmu_model == MMU10K) { |
1832 |
vaddr0 = cp->tlbs[index].hi & |
vaddr0 = cp->tlbs[index].hi & |
1869 |
* Invalidate any code translations, if we are writing Dirty |
* Invalidate any code translations, if we are writing Dirty |
1870 |
* pages to the TLB: (TODO: 4KB hardcoded... ugly) |
* pages to the TLB: (TODO: 4KB hardcoded... ugly) |
1871 |
*/ |
*/ |
1872 |
for (ptmp = 0; ptmp < (1 << pfn_shift); ptmp += 0x1000) { |
psize = 1 << pfn_shift; |
1873 |
|
for (ptmp = 0; ptmp < psize; ptmp += 0x1000) { |
1874 |
if (wf0) |
if (wf0) |
1875 |
cpu->invalidate_code_translation(cpu, |
cpu->invalidate_code_translation(cpu, |
1876 |
paddr0 + ptmp, INVALIDATE_PADDR); |
paddr0 + ptmp, INVALIDATE_PADDR); |
2128 |
exit(1); |
exit(1); |
2129 |
} |
} |
2130 |
|
|
|
op = (function) & 0xff; |
|
2131 |
switch (co_bit) { |
switch (co_bit) { |
2132 |
|
case 0: |
2133 |
|
if ((function & 0x03e0ffdf) == 0x01606000) { |
2134 |
|
debug("%ci", function & 0x20? 'e' : 'd'); |
2135 |
|
if (rt != MIPS_GPR_ZERO) |
2136 |
|
debug("\t%s", regnames[rt]); |
2137 |
|
debug("\n"); |
2138 |
|
return; |
2139 |
|
} |
2140 |
|
break; |
2141 |
case 1: |
case 1: |
2142 |
|
op = (function) & 0xff; |
2143 |
switch (op) { |
switch (op) { |
2144 |
case COP0_TLBR: /* Read indexed TLB entry */ |
case COP0_TLBR: /* Read indexed TLB entry */ |
2145 |
debug("tlbr\n"); |
debug("tlbr\n"); |
2202 |
default: |
default: |
2203 |
; |
; |
2204 |
} |
} |
2205 |
default: |
break; |
|
; |
|
2206 |
} |
} |
2207 |
} |
} |
2208 |
|
|
2228 |
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0); |
mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cp->coproc_nr, 0, 0, 0); |
2229 |
} |
} |
2230 |
|
|
|
#endif /* ENABLE_MIPS */ |
|