Search
lxdream.org :: lxdream :: r826:69f2c9f1e608
lxdream 0.9.1
released Jun 29
Download Now
changeset826:69f2c9f1e608
parent825:2ac7ceccd775
child827:d333f4248727
authornkeynes
dateSun Aug 24 02:43:28 2008 +0000 (12 years ago)
Fix mask correctness of MMU/general IO registers, add unknown/undoced
register at FF00002C
src/sh4/mmu.c
src/sh4/sh4mmio.h
test/testregs.c
1.1 --- a/src/sh4/mmu.c Sun Aug 24 01:58:09 2008 +0000
1.2 +++ b/src/sh4/mmu.c Sun Aug 24 02:43:28 2008 +0000
1.3 @@ -1,6 +1,6 @@
1.4 /**
1.5 * $Id$
1.6 - *
1.7 + *
1.8 * MMU implementation
1.9 *
1.10 * Copyright (c) 2005 Nathan Keynes.
1.11 @@ -153,6 +153,13 @@
1.12 case PTEA:
1.13 val &= 0x0000000F;
1.14 break;
1.15 + case TRA:
1.16 + val &= 0x000003FC;
1.17 + break;
1.18 + case EXPEVT:
1.19 + case INTEVT:
1.20 + val &= 0x00000FFF;
1.21 + break;
1.22 case MMUCR:
1.23 if( val & MMUCR_TI ) {
1.24 mmu_invalidate_tlb();
1.25 @@ -174,6 +181,16 @@
1.26 mmu_set_cache_mode( val & (CCR_OIX|CCR_ORA|CCR_OCE) );
1.27 val &= 0x81A7;
1.28 break;
1.29 + case MMUUNK1:
1.30 + /* Note that if the high bit is set, this appears to reset the machine.
1.31 + * Not emulating this behaviour yet until we know why...
1.32 + */
1.33 + val &= 0x00010007;
1.34 + break;
1.35 + case QACR0:
1.36 + case QACR1:
1.37 + val &= 0x0000001C;
1.38 + break;
1.39 case PMCR1:
1.40 case PMCR2:
1.41 if( val != 0 ) {
1.42 @@ -187,7 +204,7 @@
1.43 }
1.44
1.45
1.46 -void MMU_init()
1.47 +void MMU_init()
1.48 {
1.49 cache = mem_alloc_pages(2);
1.50 }
1.51 @@ -344,7 +361,7 @@
1.52 unsigned int i;
1.53 for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.54 if( (mmu_utlb[i].flags & TLB_VALID) &&
1.55 - ((mmu_utlb[i].flags & TLB_SHARE) || asid == mmu_utlb[i].asid) &&
1.56 + ((mmu_utlb[i].flags & TLB_SHARE) || asid == mmu_utlb[i].asid) &&
1.57 ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.58 if( result != -1 ) {
1.59 fprintf( stderr, "TLB Multi hit: %d %d\n", result, i );
1.60 @@ -366,7 +383,7 @@
1.61 unsigned int i;
1.62 for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.63 if( (mmu_itlb[i].flags & TLB_VALID) &&
1.64 - ((mmu_itlb[i].flags & TLB_SHARE) || asid == mmu_itlb[i].asid) &&
1.65 + ((mmu_itlb[i].flags & TLB_SHARE) || asid == mmu_itlb[i].asid) &&
1.66 ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.67 if( result != -1 ) {
1.68 return -2;
1.69 @@ -460,7 +477,7 @@
1.70 /******************************************************************************/
1.71
1.72 /**
1.73 - * The translations are excessively complicated, but unfortunately it's a
1.74 + * The translations are excessively complicated, but unfortunately it's a
1.75 * complicated system. TODO: make this not be painfully slow.
1.76 */
1.77
1.78 @@ -485,7 +502,7 @@
1.79
1.80 for( i = 0; i < UTLB_ENTRY_COUNT; i++ ) {
1.81 if( (mmu_utlb[i].flags & TLB_VALID) &&
1.82 - ((mmu_utlb[i].flags & TLB_SHARE) || mmu_asid == mmu_utlb[i].asid) &&
1.83 + ((mmu_utlb[i].flags & TLB_SHARE) || mmu_asid == mmu_utlb[i].asid) &&
1.84 ((mmu_utlb[i].vpn ^ vpn) & mmu_utlb[i].mask) == 0 ) {
1.85 if( result != -1 ) {
1.86 return -2;
1.87 @@ -548,7 +565,7 @@
1.88 } else { // Note - gets invalid entries too
1.89 replace = 3;
1.90 mmu_lrui = (mmu_lrui | 0x0B);
1.91 - }
1.92 + }
1.93
1.94 mmu_itlb[replace].vpn = mmu_utlb[entryNo].vpn;
1.95 mmu_itlb[replace].mask = mmu_utlb[entryNo].mask;
1.96 @@ -574,7 +591,7 @@
1.97
1.98 for( i = 0; i < ITLB_ENTRY_COUNT; i++ ) {
1.99 if( (mmu_itlb[i].flags & TLB_VALID) &&
1.100 - ((mmu_itlb[i].flags & TLB_SHARE) || mmu_asid == mmu_itlb[i].asid) &&
1.101 + ((mmu_itlb[i].flags & TLB_SHARE) || mmu_asid == mmu_itlb[i].asid) &&
1.102 ((mmu_itlb[i].vpn ^ vpn) & mmu_itlb[i].mask) == 0 ) {
1.103 if( result != -1 ) {
1.104 return -2;
1.105 @@ -695,9 +712,9 @@
1.106 }
1.107
1.108 /* finally generate the target address */
1.109 - sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.110 + sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.111 (addr & (~mmu_utlb[entryNo].mask));
1.112 - if( pma > 0x1C000000 ) // Remap 1Cxx .. 1Fxx region to P4
1.113 + if( pma > 0x1C000000 ) // Remap 1Cxx .. 1Fxx region to P4
1.114 pma |= 0xE0000000;
1.115 return pma;
1.116 }
1.117 @@ -758,9 +775,9 @@
1.118 }
1.119
1.120 /* finally generate the target address */
1.121 - sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.122 + sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.123 (addr & (~mmu_utlb[entryNo].mask));
1.124 - if( pma > 0x1C000000 ) // Remap 1Cxx .. 1Fxx region to P4
1.125 + if( pma > 0x1C000000 ) // Remap 1Cxx .. 1Fxx region to P4
1.126 pma |= 0xE0000000;
1.127 return pma;
1.128 }
1.129 @@ -822,7 +839,7 @@
1.130 return TRUE;
1.131 }
1.132
1.133 - if( (mmucr & MMUCR_SV) == 0 )
1.134 + if( (mmucr & MMUCR_SV) == 0 )
1.135 entryNo = mmu_itlb_lookup_vpn_asid( addr );
1.136 else
1.137 entryNo = mmu_itlb_lookup_vpn( addr );
1.138 @@ -867,10 +884,10 @@
1.139 }
1.140
1.141 /**
1.142 - * Translate address for disassembly purposes (ie performs an instruction
1.143 + * Translate address for disassembly purposes (ie performs an instruction
1.144 * lookup) - does not raise exceptions or modify any state, and ignores
1.145 * protection bits. Returns the translated address, or MMU_VMA_ERROR
1.146 - * on translation failure.
1.147 + * on translation failure.
1.148 */
1.149 sh4addr_t mmu_vma_to_phys_disasm( sh4vma_t vma )
1.150 {
1.151 @@ -896,8 +913,8 @@
1.152 if( entryNo < 0 ) {
1.153 return MMU_VMA_ERROR;
1.154 } else {
1.155 - return (mmu_itlb[entryNo].ppn & mmu_itlb[entryNo].mask) |
1.156 - (vma & (~mmu_itlb[entryNo].mask));
1.157 + return (mmu_itlb[entryNo].ppn & mmu_itlb[entryNo].mask) |
1.158 + (vma & (~mmu_itlb[entryNo].mask));
1.159 }
1.160 }
1.161
1.162 @@ -936,7 +953,7 @@
1.163 }
1.164
1.165 /* finally generate the target address */
1.166 - target = ((mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.167 + target = ((mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
1.168 (addr & (~mmu_utlb[entryNo].mask))) & 0xFFFFFFE0;
1.169 }
1.170 } else {
2.1 --- a/src/sh4/sh4mmio.h Sun Aug 24 01:58:09 2008 +0000
2.2 +++ b/src/sh4/sh4mmio.h Sun Aug 24 02:43:28 2008 +0000
2.3 @@ -1,6 +1,6 @@
2.4 /**
2.5 * $Id$
2.6 - *
2.7 + *
2.8 * MMIO region and supporting function declarations. Private to the sh4
2.9 * module.
2.10 *
2.11 @@ -46,6 +46,7 @@
2.12 LONG_PORT( 0x020, TRA, PORT_MRW, UNDEFINED, "TRAPA exception register" )
2.13 LONG_PORT( 0x024, EXPEVT,PORT_MRW, 0, "Exception event register" )
2.14 LONG_PORT( 0x028, INTEVT,PORT_MRW, UNDEFINED, "Interrupt event register" )
2.15 + LONG_PORT( 0x02C, MMUUNK1, PORT_MRW, 0, "Unknown MMU/general register" )
2.16 LONG_PORT( 0x030, SH4VER, PORT_MRW, 0x040205C1, "SH4 version register (PVR)" ) /* Renamed to avoid naming conflict */
2.17 LONG_PORT( 0x034, PTEA, PORT_MRW, UNDEFINED, "Page table entry assistance" )
2.18 LONG_PORT( 0x038, QACR0,PORT_MRW, UNDEFINED, "Queue address control 0" )
2.19 @@ -56,10 +57,10 @@
2.20
2.21 /* Performance counter values (undocumented) */
2.22 MMIO_REGION_BEGIN( 0xFF100000, PMM, "Performance monitoring" )
2.23 - LONG_PORT (0x004, PMCTR1H, PORT_MR, 0, "Performance counter 1 High" )
2.24 - LONG_PORT (0x008, PMCTR1L, PORT_MR, 0, "Performance counter 1 Low" )
2.25 - LONG_PORT (0x00C, PMCTR2H, PORT_MR, 0, "Performance counter 2 High" )
2.26 - LONG_PORT (0x010, PMCTR2L, PORT_MR, 0, "Performance counter 2 Low" )
2.27 + LONG_PORT( 0x004, PMCTR1H, PORT_MR, 0, "Performance counter 1 High" )
2.28 + LONG_PORT( 0x008, PMCTR1L, PORT_MR, 0, "Performance counter 1 Low" )
2.29 + LONG_PORT( 0x00C, PMCTR2H, PORT_MR, 0, "Performance counter 2 High" )
2.30 + LONG_PORT( 0x010, PMCTR2L, PORT_MR, 0, "Performance counter 2 Low" )
2.31 MMIO_REGION_END
2.32
2.33 /* User Break Controller (Page 717 [757] of sh7750h manual) */
2.34 @@ -173,7 +174,7 @@
2.35 BYTE_PORT( 0x004, SCBRR2, PORT_MRW, 0xFF, "Bit rate register (FIFO)" )
2.36 WORD_PORT( 0x008, SCSCR2, PORT_MRW, 0x0000, "Serial control register" )
2.37 BYTE_PORT( 0x00C, SCFTDR2, PORT_W, UNDEFINED, "Transmit FIFO data register" )
2.38 - WORD_PORT( 0x010, SCFSR2, PORT_MRW, 0x0060, "Serial status register (FIFO)")
2.39 + WORD_PORT( 0x010, SCFSR2, PORT_MRW, 0x0060, "Serial status register (FIFO)" )
2.40 BYTE_PORT( 0x014, SCFRDR2, PORT_R, UNDEFINED, "Receive FIFO data register" )
2.41 WORD_PORT( 0x018, SCFCR2, PORT_MRW, 0x0000, "FIFO control register" )
2.42 WORD_PORT( 0x01C, SCFDR2, PORT_MR, 0x0000, "FIFO data count register" )
3.1 --- a/test/testregs.c Sun Aug 24 01:58:09 2008 +0000
3.2 +++ b/test/testregs.c Sun Aug 24 02:43:28 2008 +0000
3.3 @@ -192,9 +192,23 @@
3.4 { 0xA05F81F4, 0xFFFFFFFF, 0 },
3.5 { 0xA05F81F8, 0xFFFFFFFF, 0 },
3.6 { 0xA05F81FC, 0xFFFFFFFF, 0 },
3.7 + /* SH4 control regs */
3.8 + { 0xFF000000, 0xFFFFFFFF, 0xFFFFFCFF },
3.9 + { 0xFF000004, 0xFFFFFFFF, 0x1FFFFDFF },
3.10 + { 0xFF000008, 0xFFFFFFFF, 0xFFFFFFFF },
3.11 + { 0xFF00000C, 0xFFFFFFFF, 0xFFFFFFFF },
3.12 + { 0xFF000010, 0xFFFFFFFF, 0xFCFCFF01 },
3.13 + { 0xFF000010, 0, 0 },
3.14 { 0xFF00001C, 0xFFFFFFFF, 0x000081A7 },
3.15 + { 0xFF000020, 0xFFFFFFFF, 0x000003FC },
3.16 + { 0xFF000024, 0xFFFFFFFF, 0x00000FFF },
3.17 + { 0xFF000028, 0xFFFFFFFF, 0x00000FFF },
3.18 + { 0xFF00002C, 0x7FFFFFFF, 0x00010007 },
3.19 { 0xFF000030, 0xFFFFFFFF, 0x040205C1 },
3.20 { 0xFF000030, 0, 0x040205C1 },
3.21 + { 0xFF000034, 0xFFFFFFFF, 0x0000000F },
3.22 + { 0xFF000038, 0xFFFFFFFF, 0x0000001C },
3.23 + { 0xFF00003C, 0xFFFFFFFF, 0x0000001C },
3.24 { 0, 0, 0 } };
3.25
3.26 int main( int argc, char *argv[] )
.