25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_mips_coproc.c,v 1.17 2005/04/22 16:03:43 debug Exp $ |
* $Id: cpu_mips_coproc.c,v 1.27 2005/08/14 15:47:36 debug Exp $ |
29 |
* |
* |
30 |
* Emulation of MIPS coprocessors. |
* Emulation of MIPS coprocessors. |
31 |
*/ |
*/ |
88 |
#else |
#else |
89 |
const int m16 = 0; |
const int m16 = 0; |
90 |
#endif |
#endif |
91 |
int IB, DB, SB, IC, DC, SC; |
int cpu_type, IB, DB, SB, IC, DC, SC, IA, DA; |
92 |
|
|
93 |
/* Default values: */ |
/* Default values: */ |
94 |
c->reg[COP0_CONFIG] = |
c->reg[COP0_CONFIG] = |
111 |
(TODO) */ |
(TODO) */ |
112 |
; |
; |
113 |
|
|
114 |
switch (cpu->cd.mips.cpu_type.rev) { |
cpu_type = cpu->cd.mips.cpu_type.rev & 0xff; |
115 |
|
|
116 |
|
/* AU1x00 are treated as 4Kc (MIPS32 cores): */ |
117 |
|
if ((cpu->cd.mips.cpu_type.rev & 0xffff) == 0x0301) |
118 |
|
cpu_type = MIPS_4Kc; |
119 |
|
|
120 |
|
switch (cpu_type) { |
121 |
case MIPS_R4000: /* according to the R4000 manual */ |
case MIPS_R4000: /* according to the R4000 manual */ |
122 |
case MIPS_R4600: |
case MIPS_R4600: |
123 |
IB = cpu->machine->cache_picache_linesize - 4; |
IB = cpu->machine->cache_picache_linesize - 4; |
304 |
break; |
break; |
305 |
case MIPS_4Kc: |
case MIPS_4Kc: |
306 |
case MIPS_5Kc: |
case MIPS_5Kc: |
307 |
/* According to the MIPS64 5K User's Manual: */ |
/* According to the MIPS64 (5K) User's Manual: */ |
|
/* TODO: How good does this work with 4K? */ |
|
308 |
c->reg[COP0_CONFIG] = |
c->reg[COP0_CONFIG] = |
309 |
( (uint32_t)1 << 31)/* Config 1 present bit */ |
( (uint32_t)1 << 31)/* Config 1 present bit */ |
310 |
| ( 0 << 20) /* ISD: instruction scheduling |
| ( 0 << 20) /* ISD: instruction scheduling |
311 |
disable (=1) */ |
disable (=1) */ |
312 |
| ( 0 << 17) /* DID: dual issue disable */ |
| ( 0 << 17) /* DID: dual issue disable */ |
313 |
| ( 0 << 16) /* BM: burst mode */ |
| ( 0 << 16) /* BM: burst mode */ |
314 |
| ((cpu->byte_order==EMUL_BIG_ENDIAN? 1 : 0) << 15) |
| ((cpu->byte_order == EMUL_BIG_ENDIAN? 1 : 0) << 15) |
315 |
/* endian mode */ |
/* endian mode */ |
316 |
| ((cpu->cd.mips.cpu_type.rev==MIPS_5Kc?2:1) << 13) |
| ((cpu_type == MIPS_5Kc? 2 : 0) << 13) |
317 |
/* 1=32-bit only, 2=32/64 */ |
/* 0=MIPS32, 1=64S, 2=64 */ |
318 |
| ( 0 << 10) /* Architecture revision */ |
| ( 0 << 10) /* Architecture revision */ |
319 |
| ( 1 << 7) /* MMU type: 1=TLB, 3=FMT */ |
| ( 1 << 7) /* MMU type: 1=TLB, 3=FMT */ |
320 |
| ( 2 << 0) /* kseg0 cache coherency algorithm */ |
| ( 2 << 0) /* kseg0 cache coherency algorithm */ |
321 |
; |
; |
322 |
/* TODO: Config select 1: caches and such */ |
/* Config select 1: caches etc. TODO: Don't use |
323 |
|
cpu->machine for this stuff! */ |
324 |
|
IB = cpu->machine->cache_picache_linesize - 1; |
325 |
|
IB = IB < 0? 0 : (IB > 7? 7 : IB); |
326 |
|
DB = cpu->machine->cache_pdcache_linesize - 1; |
327 |
|
DB = DB < 0? 0 : (DB > 7? 7 : DB); |
328 |
|
IC = cpu->machine->cache_picache - |
329 |
|
cpu->machine->cache_picache_linesize - 7; |
330 |
|
DC = cpu->machine->cache_pdcache - |
331 |
|
cpu->machine->cache_pdcache_linesize - 7; |
332 |
|
IA = cpu->cd.mips.cpu_type.piways - 1; |
333 |
|
DA = cpu->cd.mips.cpu_type.pdways - 1; |
334 |
|
cpu->cd.mips.cop0_config_select1 = |
335 |
|
((cpu->cd.mips.cpu_type.nr_of_tlb_entries - 1) << 25) |
336 |
|
| (IC << 22) /* IS: I-cache sets per way */ |
337 |
|
| (IB << 19) /* IL: I-cache line-size */ |
338 |
|
| (IA << 16) /* IA: I-cache assoc. (ways-1) */ |
339 |
|
| (DC << 13) /* DS: D-cache sets per way */ |
340 |
|
| (DB << 10) /* DL: D-cache line-size */ |
341 |
|
| (DA << 7) /* DA: D-cache assoc. (ways-1) */ |
342 |
|
| (16 * 0) /* Existance of PerformanceCounters */ |
343 |
|
| ( 8 * 0) /* Existance of Watch Registers */ |
344 |
|
| ( 4 * m16) /* Existance of MIPS16 */ |
345 |
|
| ( 2 * 0) /* Existance of EJTAG */ |
346 |
|
| ( 1 * 1) /* Existance of FPU */ |
347 |
|
; |
348 |
break; |
break; |
349 |
default: |
default: |
350 |
; |
; |
541 |
static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
static void old_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
542 |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
543 |
{ |
{ |
544 |
#ifdef BINTRANS |
int a, b, index; |
|
int a, b; |
|
545 |
struct vth32_table *tbl1; |
struct vth32_table *tbl1; |
546 |
void *p; |
void *p_r, *p_w; |
547 |
uint32_t p_paddr; |
uint32_t p_paddr; |
548 |
|
|
549 |
/* This table stuff only works for 32-bit mode: */ |
/* This table stuff only works for 32-bit mode: */ |
557 |
|
|
558 |
a = (vaddr_page >> 22) & 0x3ff; |
a = (vaddr_page >> 22) & 0x3ff; |
559 |
b = (vaddr_page >> 12) & 0x3ff; |
b = (vaddr_page >> 12) & 0x3ff; |
560 |
|
index = (vaddr_page >> 12) & 0xfffff; |
561 |
|
|
562 |
/* printf("vaddr = %08x, a = %03x, b = %03x\n", |
/* printf("vaddr = %08x, a = %03x, b = %03x\n", |
563 |
(int)vaddr_page,a, b); */ |
(int)vaddr_page,a, b); */ |
564 |
|
|
565 |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
566 |
/* printf("tbl1 = %p\n", tbl1); */ |
/* printf("tbl1 = %p\n", tbl1); */ |
567 |
if (tbl1 == cpu->cd.mips.vaddr_to_hostaddr_nulltable) { |
if (tbl1 == cpu->cd.mips.vaddr_to_hostaddr_nulltable) { |
577 |
memset(tbl1, 0, sizeof(struct vth32_table)); |
memset(tbl1, 0, sizeof(struct vth32_table)); |
578 |
} else { |
} else { |
579 |
tbl1 = cpu->cd.mips.next_free_vth_table; |
tbl1 = cpu->cd.mips.next_free_vth_table; |
580 |
cpu->cd.mips.next_free_vth_table = |
cpu->cd.mips.next_free_vth_table = tbl1->next_free; |
|
tbl1->next_free; |
|
581 |
tbl1->next_free = NULL; |
tbl1->next_free = NULL; |
582 |
} |
} |
583 |
cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] = tbl1; |
cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a] = tbl1; |
586 |
exit(1); |
exit(1); |
587 |
} |
} |
588 |
} |
} |
589 |
p = tbl1->haddr_entry[b]; |
p_r = tbl1->haddr_entry[b*2]; |
590 |
|
p_w = tbl1->haddr_entry[b*2+1]; |
591 |
p_paddr = tbl1->paddr_entry[b]; |
p_paddr = tbl1->paddr_entry[b]; |
592 |
/* printf(" p = %p\n", p); */ |
/* printf(" p_r=%p p_w=%p\n", p_r, p_w); */ |
593 |
if (p == NULL && p_paddr == 0 && |
if (p_r == NULL && p_paddr == 0 && |
594 |
(host_page!=NULL || paddr_page!=0)) { |
(host_page != NULL || paddr_page != 0)) { |
595 |
tbl1->refcount ++; |
tbl1->refcount ++; |
596 |
/* printf("ADDING %08x -> %p wf=%i (refcount is " |
/* printf("ADDING %08x -> %p wf=%i (refcount is " |
597 |
"now %i)\n", (int)vaddr_page, host_page, |
"now %i)\n", (int)vaddr_page, host_page, |
599 |
} |
} |
600 |
if (writeflag == -1) { |
if (writeflag == -1) { |
601 |
/* Forced downgrade to read-only: */ |
/* Forced downgrade to read-only: */ |
602 |
tbl1->haddr_entry[b] = (void *) |
tbl1->haddr_entry[b*2 + 1] = NULL; |
603 |
((size_t)tbl1->haddr_entry[b] & ~1); |
if (cpu->cd.mips.host_store == |
604 |
} else if (writeflag==0 && (size_t)p&1 && host_page != NULL) { |
cpu->cd.mips.host_store_orig) |
605 |
|
cpu->cd.mips.host_store[index] = NULL; |
606 |
|
} else if (writeflag==0 && p_w != NULL && host_page != NULL) { |
607 |
/* Don't degrade a page from writable to readonly. */ |
/* Don't degrade a page from writable to readonly. */ |
608 |
} else { |
} else { |
609 |
if (host_page != NULL) |
if (host_page != NULL) { |
610 |
tbl1->haddr_entry[b] = (void *) |
tbl1->haddr_entry[b*2] = host_page; |
611 |
((size_t)host_page + (writeflag?1:0)); |
if (cpu->cd.mips.host_load == |
612 |
else |
cpu->cd.mips.host_load_orig) |
613 |
tbl1->haddr_entry[b] = NULL; |
cpu->cd.mips.host_load[index] = host_page; |
614 |
|
if (writeflag) { |
615 |
|
tbl1->haddr_entry[b*2+1] = host_page; |
616 |
|
if (cpu->cd.mips.host_store == |
617 |
|
cpu->cd.mips.host_store_orig) |
618 |
|
cpu->cd.mips.host_store[index] = |
619 |
|
host_page; |
620 |
|
} else { |
621 |
|
tbl1->haddr_entry[b*2+1] = NULL; |
622 |
|
if (cpu->cd.mips.host_store == |
623 |
|
cpu->cd.mips.host_store_orig) |
624 |
|
cpu->cd.mips.host_store[index] = NULL; |
625 |
|
} |
626 |
|
} else { |
627 |
|
tbl1->haddr_entry[b*2] = NULL; |
628 |
|
tbl1->haddr_entry[b*2+1] = NULL; |
629 |
|
if (cpu->cd.mips.host_store == |
630 |
|
cpu->cd.mips.host_store_orig) { |
631 |
|
cpu->cd.mips.host_load[index] = NULL; |
632 |
|
cpu->cd.mips.host_store[index] = NULL; |
633 |
|
} |
634 |
|
} |
635 |
tbl1->paddr_entry[b] = paddr_page; |
tbl1->paddr_entry[b] = paddr_page; |
636 |
} |
} |
637 |
tbl1->bintrans_chunks[b] = NULL; |
tbl1->bintrans_chunks[b] = NULL; |
|
#endif |
|
638 |
} |
} |
639 |
|
|
640 |
|
|
641 |
/* |
/* |
642 |
* update_translation_table(): |
* mips_update_translation_table(): |
643 |
*/ |
*/ |
644 |
void update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
void mips_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
645 |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
unsigned char *host_page, int writeflag, uint64_t paddr_page) |
646 |
{ |
{ |
|
#ifdef BINTRANS |
|
647 |
if (!cpu->machine->bintrans_enable) |
if (!cpu->machine->bintrans_enable) |
648 |
return; |
return; |
649 |
|
|
658 |
|
|
659 |
/* TODO */ |
/* TODO */ |
660 |
/* printf("update_translation_table(): TODO\n"); */ |
/* printf("update_translation_table(): TODO\n"); */ |
|
#endif |
|
661 |
} |
} |
662 |
|
|
663 |
|
|
|
#ifdef BINTRANS |
|
664 |
/* |
/* |
665 |
* invalidate_table_entry(): |
* invalidate_table_entry(): |
666 |
*/ |
*/ |
667 |
static void invalidate_table_entry(struct cpu *cpu, uint64_t vaddr) |
static void invalidate_table_entry(struct cpu *cpu, uint64_t vaddr) |
668 |
{ |
{ |
669 |
int a, b; |
int a, b, index; |
670 |
struct vth32_table *tbl1; |
struct vth32_table *tbl1; |
671 |
void *p; |
void *p_r, *p_w; |
672 |
uint32_t p_paddr; |
uint32_t p_paddr; |
673 |
|
|
674 |
if (!cpu->machine->old_bintrans_enable) { |
if (!cpu->machine->old_bintrans_enable) { |
693 |
|
|
694 |
a = (vaddr >> 22) & 0x3ff; |
a = (vaddr >> 22) & 0x3ff; |
695 |
b = (vaddr >> 12) & 0x3ff; |
b = (vaddr >> 12) & 0x3ff; |
696 |
|
index = (vaddr >> 12) & 0xfffff; |
697 |
|
|
698 |
/* printf("vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */ |
/* printf("vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */ |
699 |
|
|
700 |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
701 |
/* printf("tbl1 = %p\n", tbl1); */ |
/* printf("tbl1 = %p\n", tbl1); */ |
702 |
p = tbl1->haddr_entry[b]; |
p_r = tbl1->haddr_entry[b*2]; |
703 |
|
p_w = tbl1->haddr_entry[b*2+1]; |
704 |
p_paddr = tbl1->paddr_entry[b]; |
p_paddr = tbl1->paddr_entry[b]; |
705 |
tbl1->bintrans_chunks[b] = NULL; |
tbl1->bintrans_chunks[b] = NULL; |
706 |
/* printf(" p = %p\n", p); */ |
/* printf("B: p_r=%p p_w=%p\n", p_r,p_w); */ |
707 |
if (p != NULL || p_paddr != 0) { |
cpu->cd.mips.host_load_orig[index] = NULL; |
708 |
|
cpu->cd.mips.host_store_orig[index] = NULL; |
709 |
|
if (p_r != NULL || p_paddr != 0) { |
710 |
/* printf("Found a mapping, " |
/* printf("Found a mapping, " |
711 |
"vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */ |
"vaddr = %08x, a = %03x, b = %03x\n", (int)vaddr,a, b); */ |
712 |
tbl1->haddr_entry[b] = NULL; |
tbl1->haddr_entry[b*2] = NULL; |
713 |
|
tbl1->haddr_entry[b*2+1] = NULL; |
714 |
tbl1->paddr_entry[b] = 0; |
tbl1->paddr_entry[b] = 0; |
715 |
tbl1->refcount --; |
tbl1->refcount --; |
716 |
if (tbl1->refcount == 0) { |
if (tbl1->refcount == 0) { |
741 |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
tbl1 = cpu->cd.mips.vaddr_to_hostaddr_table0_kernel[a]; |
742 |
if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) { |
if (tbl1 != cpu->cd.mips.vaddr_to_hostaddr_nulltable) { |
743 |
for (b=0; b<0x400; b++) { |
for (b=0; b<0x400; b++) { |
744 |
tbl1->haddr_entry[b] = NULL; |
int index; |
745 |
|
|
746 |
|
tbl1->haddr_entry[b*2] = NULL; |
747 |
|
tbl1->haddr_entry[b*2+1] = NULL; |
748 |
tbl1->paddr_entry[b] = 0; |
tbl1->paddr_entry[b] = 0; |
749 |
tbl1->bintrans_chunks[b] = NULL; |
tbl1->bintrans_chunks[b] = NULL; |
750 |
|
|
751 |
|
if (cpu->cd.mips.host_store == |
752 |
|
cpu->cd.mips.host_store_orig) { |
753 |
|
index = (a << 10) + b; |
754 |
|
cpu->cd.mips.host_load[index] = NULL; |
755 |
|
cpu->cd.mips.host_store[index] = NULL; |
756 |
|
} |
757 |
} |
} |
758 |
} |
} |
759 |
} |
} |
760 |
} |
} |
|
#endif |
|
761 |
|
|
762 |
|
|
763 |
/* |
/* |
767 |
*/ |
*/ |
768 |
void mips_invalidate_translation_caches_paddr(struct cpu *cpu, uint64_t paddr) |
void mips_invalidate_translation_caches_paddr(struct cpu *cpu, uint64_t paddr) |
769 |
{ |
{ |
|
#ifdef BINTRANS |
|
770 |
paddr &= ~0xfff; |
paddr &= ~0xfff; |
771 |
|
|
772 |
if (cpu->machine->bintrans_enable) { |
if (cpu->machine->bintrans_enable) { |
871 |
cpu->bintrans_data_hostpage[i] = NULL; |
cpu->bintrans_data_hostpage[i] = NULL; |
872 |
} |
} |
873 |
#endif |
#endif |
|
|
|
|
#endif |
|
874 |
} |
} |
875 |
|
|
876 |
|
|
889 |
/* printf("inval(all=%i, kernel=%i, addr=%016llx)\n", |
/* printf("inval(all=%i, kernel=%i, addr=%016llx)\n", |
890 |
all, kernelspace, (long long)vaddr); */ |
all, kernelspace, (long long)vaddr); */ |
891 |
|
|
|
#ifdef BINTRANS |
|
892 |
if (!cpu->machine->bintrans_enable) |
if (!cpu->machine->bintrans_enable) |
893 |
goto nobintrans; |
goto nobintrans; |
894 |
|
|
969 |
/* TODO: Don't invalidate everything. */ |
/* TODO: Don't invalidate everything. */ |
970 |
for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++) |
for (i=0; i<N_BINTRANS_VADDR_TO_HOST; i++) |
971 |
cpu->cd.mips.bintrans_data_hostpage[i] = NULL; |
cpu->cd.mips.bintrans_data_hostpage[i] = NULL; |
|
#endif |
|
972 |
|
|
973 |
if (kernelspace) |
if (kernelspace) |
974 |
all = 1; |
all = 1; |
1000 |
* Read a value from a MIPS coprocessor register. |
* Read a value from a MIPS coprocessor register. |
1001 |
*/ |
*/ |
1002 |
void coproc_register_read(struct cpu *cpu, |
void coproc_register_read(struct cpu *cpu, |
1003 |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr) |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int select) |
1004 |
{ |
{ |
1005 |
int unimpl = 1; |
int unimpl = 1; |
1006 |
|
|
1042 |
if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_CAUSE) unimpl = 0; |
1043 |
if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_EPC) unimpl = 0; |
1044 |
if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_PRID) unimpl = 0; |
1045 |
if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_CONFIG) { |
1046 |
|
if (select > 0) { |
1047 |
|
switch (select) { |
1048 |
|
case 1: *ptr = cpu->cd.mips.cop0_config_select1; |
1049 |
|
break; |
1050 |
|
default:fatal("coproc_register_read(): unimplemented" |
1051 |
|
" config register select %i\n", select); |
1052 |
|
exit(1); |
1053 |
|
} |
1054 |
|
return; |
1055 |
|
} |
1056 |
|
unimpl = 0; |
1057 |
|
} |
1058 |
if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_LLADDR) unimpl = 0; |
1059 |
if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_WATCHLO) unimpl = 0; |
1060 |
if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0; |
if (cp->coproc_nr==0 && reg_nr==COP0_WATCHHI) unimpl = 0; |
1094 |
* Write a value to a MIPS coprocessor register. |
* Write a value to a MIPS coprocessor register. |
1095 |
*/ |
*/ |
1096 |
void coproc_register_write(struct cpu *cpu, |
void coproc_register_write(struct cpu *cpu, |
1097 |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64) |
struct mips_coproc *cp, int reg_nr, uint64_t *ptr, int flag64, |
1098 |
|
int select) |
1099 |
{ |
{ |
1100 |
int unimpl = 1; |
int unimpl = 1; |
1101 |
int readonly = 0; |
int readonly = 0; |
1261 |
readonly = 1; |
readonly = 1; |
1262 |
break; |
break; |
1263 |
case COP0_CONFIG: |
case COP0_CONFIG: |
1264 |
|
if (select > 0) { |
1265 |
|
switch (select) { |
1266 |
|
case 1: cpu->cd.mips.cop0_config_select1 = tmp; |
1267 |
|
break; |
1268 |
|
default:fatal("coproc_register_write(): unimpl" |
1269 |
|
"emented config register select " |
1270 |
|
"%i\n", select); |
1271 |
|
exit(1); |
1272 |
|
} |
1273 |
|
return; |
1274 |
|
} |
1275 |
|
|
1276 |
/* fatal("COP0_CONFIG: modifying K0 bits: " |
/* fatal("COP0_CONFIG: modifying K0 bits: " |
1277 |
"0x%08x => ", cp->reg[reg_nr]); */ |
"0x%08x => ", cp->reg[reg_nr]); */ |
1278 |
tmp = *ptr; |
tmp = *ptr; |
1301 |
} |
} |
1302 |
#endif |
#endif |
1303 |
|
|
|
#ifdef BINTRANS |
|
1304 |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K && |
if (cpu->cd.mips.cpu_type.mmu_model == MMU3K && |
1305 |
(oldmode & MIPS1_ISOL_CACHES) != |
(oldmode & MIPS1_ISOL_CACHES) != |
1306 |
(tmp & MIPS1_ISOL_CACHES)) { |
(tmp & MIPS1_ISOL_CACHES)) { |
1308 |
treated in bintrans mode by changing |
treated in bintrans mode by changing |
1309 |
the vaddr_to_hostaddr_table0 pointer: */ |
the vaddr_to_hostaddr_table0 pointer: */ |
1310 |
if (tmp & MIPS1_ISOL_CACHES) { |
if (tmp & MIPS1_ISOL_CACHES) { |
1311 |
/* cpu->cd.mips. |
/* 2-level table: */ |
|
dont_run_next_bintrans = 1; */ |
|
1312 |
cpu->cd.mips.vaddr_to_hostaddr_table0 = |
cpu->cd.mips.vaddr_to_hostaddr_table0 = |
1313 |
tmp & MIPS1_SWAP_CACHES? |
tmp & MIPS1_SWAP_CACHES? |
1314 |
cpu->cd.mips. |
cpu->cd.mips. |
1315 |
vaddr_to_hostaddr_table0_cacheisol_i |
vaddr_to_hostaddr_table0_cacheisol_i |
1316 |
: cpu->cd.mips. |
: cpu->cd.mips. |
1317 |
vaddr_to_hostaddr_table0_cacheisol_d; |
vaddr_to_hostaddr_table0_cacheisol_d; |
1318 |
|
|
1319 |
|
/* 1M-entry table: */ |
1320 |
|
cpu->cd.mips.host_load = |
1321 |
|
cpu->cd.mips.host_store = |
1322 |
|
cpu->cd.mips.huge_r2k3k_cache_table; |
1323 |
} else { |
} else { |
1324 |
|
/* 2-level table: */ |
1325 |
cpu->cd.mips.vaddr_to_hostaddr_table0 = |
cpu->cd.mips.vaddr_to_hostaddr_table0 = |
1326 |
cpu->cd.mips. |
cpu->cd.mips. |
1327 |
vaddr_to_hostaddr_table0_kernel; |
vaddr_to_hostaddr_table0_kernel; |
1328 |
|
|
1329 |
/* TODO: cpu->cd.mips. |
/* TODO: cpu->cd.mips. |
1330 |
vaddr_to_hostaddr_table0_user; */ |
vaddr_to_hostaddr_table0_user; */ |
1331 |
|
|
1332 |
|
/* 1M-entry table: */ |
1333 |
|
cpu->cd.mips.host_load = |
1334 |
|
cpu->cd.mips.host_load_orig; |
1335 |
|
cpu->cd.mips.host_store = |
1336 |
|
cpu->cd.mips.host_store_orig; |
1337 |
} |
} |
1338 |
} |
} |
|
#endif |
|
1339 |
unimpl = 0; |
unimpl = 0; |
1340 |
break; |
break; |
1341 |
case COP0_CAUSE: |
case COP0_CAUSE: |
2416 |
vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K; |
vaddr2 = cp->tlbs[i].hi & ENTRYHI_VPN2_MASK_R10K; |
2417 |
if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 & |
if (vaddr1 == vaddr2 && ((cp->tlbs[i].lo0 & |
2418 |
ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V))) |
ENTRYLO_V) || (cp->tlbs[i].lo1 & ENTRYLO_V))) |
2419 |
fatal("\n[ WARNING! tlbw%s vaddr=0x%llx is " |
fatal("\n[ WARNING! tlbw%s to index 0x%02x " |
2420 |
"already in the TLB! ]\n\n", randomflag? |
"vaddr=0x%llx (asid 0x%02x) is already in" |
2421 |
"r" : "i", (long long)vaddr1); |
" the TLB (entry 0x%02x) ! ]\n\n", |
2422 |
|
randomflag? "r" : "i", index, |
2423 |
|
(long long)vaddr1, asid, i); |
2424 |
} |
} |
2425 |
} |
} |
2426 |
|
|
2456 |
/* if (vaddr < 0x10000000) */ |
/* if (vaddr < 0x10000000) */ |
2457 |
wf = 0; |
wf = 0; |
2458 |
|
|
2459 |
update_translation_table(cpu, vaddr, memblock, |
cpu->update_translation_table(cpu, vaddr, memblock, |
2460 |
wf, paddr); |
wf, paddr); |
2461 |
} |
} |
2462 |
} else { |
} else { |
2609 |
if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21)) |
if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MFCz << 21)) |
2610 |
|| ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) { |
|| ((function & 0x03e007f8) == (COPz_DMFCz << 21)))) { |
2611 |
if (unassemble_only) { |
if (unassemble_only) { |
2612 |
debug("%s%i\t%s,%s\n", |
debug("%s%i\t%s,%s", |
2613 |
copz==COPz_DMFCz? "dmfc" : "mfc", cpnr, |
copz==COPz_DMFCz? "dmfc" : "mfc", cpnr, |
2614 |
regnames[rt], cop0_names[rd]); |
regnames[rt], cop0_names[rd]); |
2615 |
|
if (function & 7) |
2616 |
|
debug(",%i", (int)(function & 7)); |
2617 |
|
debug("\n"); |
2618 |
return; |
return; |
2619 |
} |
} |
2620 |
coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], |
coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], |
2621 |
rd, &tmpvalue); |
rd, &tmpvalue, function & 7); |
2622 |
cpu->cd.mips.gpr[rt] = tmpvalue; |
cpu->cd.mips.gpr[rt] = tmpvalue; |
2623 |
if (copz == COPz_MFCz) { |
if (copz == COPz_MFCz) { |
2624 |
/* Sign-extend: */ |
/* Sign-extend: */ |
2632 |
if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21)) |
if (cpnr < 2 && (((function & 0x03e007f8) == (COPz_MTCz << 21)) |
2633 |
|| ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) { |
|| ((function & 0x03e007f8) == (COPz_DMTCz << 21)))) { |
2634 |
if (unassemble_only) { |
if (unassemble_only) { |
2635 |
debug("%s%i\t%s,%s\n", |
debug("%s%i\t%s,%s", |
2636 |
copz==COPz_DMTCz? "dmtc" : "mtc", cpnr, |
copz==COPz_DMTCz? "dmtc" : "mtc", cpnr, |
2637 |
regnames[rt], cop0_names[rd]); |
regnames[rt], cop0_names[rd]); |
2638 |
|
if (function & 7) |
2639 |
|
debug(",%i", (int)(function & 7)); |
2640 |
|
debug("\n"); |
2641 |
return; |
return; |
2642 |
} |
} |
2643 |
tmpvalue = cpu->cd.mips.gpr[rt]; |
tmpvalue = cpu->cd.mips.gpr[rt]; |
2648 |
tmpvalue |= 0xffffffff00000000ULL; |
tmpvalue |= 0xffffffff00000000ULL; |
2649 |
} |
} |
2650 |
coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd, |
coproc_register_write(cpu, cpu->cd.mips.coproc[cpnr], rd, |
2651 |
&tmpvalue, copz == COPz_DMTCz); |
&tmpvalue, copz == COPz_DMTCz, function & 7); |
2652 |
return; |
return; |
2653 |
} |
} |
2654 |
|
|