2 m68kmmu.h - PMMU implementation for 68851/68030/68040
6 Copyright Nicola Salmoria and the MAME Team.
7 Visit http://mamedev.org for licensing and usage restrictions.
11 pmmu_translate_addr: perform 68851/68030-style PMMU address translation
13 uint pmmu_translate_addr(uint addr_in)
15 uint32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0;
16 uint root_aptr, root_limit, tofs, is, abits, bbits, cbits;
17 uint resolved, tptr, shift;
22 // if SRP is enabled and we're in supervisor mode, use it
23 if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000))
25 root_aptr = m68ki_cpu.mmu_srp_aptr;
26 root_limit = m68ki_cpu.mmu_srp_limit;
28 else // else use the CRP
30 root_aptr = m68ki_cpu.mmu_crp_aptr;
31 root_limit = m68ki_cpu.mmu_crp_limit;
34 // get initial shift (# of top bits to ignore)
35 is = (m68ki_cpu.mmu_tc>>16) & 0xf;
36 abits = (m68ki_cpu.mmu_tc>>12)&0xf;
37 bbits = (m68ki_cpu.mmu_tc>>8)&0xf;
38 cbits = (m68ki_cpu.mmu_tc>>4)&0xf;
40 // fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
43 tofs = (addr_in<<is)>>(32-abits);
45 // find out what format table A is
46 switch (root_limit & 3)
48 case 0: // invalid, should cause MMU exception
49 case 1: // page descriptor, should cause direct mapping
50 fatalerror("680x0 PMMU: Unhandled root mode\n");
53 case 2: // valid 4 byte descriptors
55 // fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
56 tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc));
57 tamode = tbl_entry & 3;
58 // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
61 case 3: // valid 8 byte descriptors
63 // fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
64 tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc));
65 tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4);
66 tamode = tbl_entry2 & 3;
67 // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
71 // get table B offset and pointer
72 tofs = (addr_in<<(is+abits))>>(32-bbits);
73 tptr = tbl_entry & 0xfffffff0;
75 // find out what format table B is, if any
78 case 0: // invalid, should cause MMU exception
79 fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in);
82 case 2: // 4-byte table B descriptor
84 // fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr);
85 tbl_entry = m68k_read_memory_32( tofs + tptr);
86 tbmode = tbl_entry & 3;
87 // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
90 case 3: // 8-byte table B descriptor
92 // fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr);
93 tbl_entry2 = m68k_read_memory_32( tofs + tptr);
94 tbl_entry = m68k_read_memory_32( tofs + tptr + 4);
95 tbmode = tbl_entry2 & 3;
96 // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
99 case 1: // early termination descriptor
100 tbl_entry &= 0xffffff00;
103 addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
108 // if table A wasn't early-out, continue to process table B
111 // get table C offset and pointer
112 tofs = (addr_in<<(is+abits+bbits))>>(32-cbits);
113 tptr = tbl_entry & 0xfffffff0;
117 case 0: // invalid, should cause MMU exception
118 fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC);
121 case 2: // 4-byte table C descriptor
123 // fprintf(stderr,"PMMU: reading table C entry at %08x\n", tofs + tptr);
124 tbl_entry = m68k_read_memory_32(tofs + tptr);
125 tcmode = tbl_entry & 3;
126 // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
129 case 3: // 8-byte table C descriptor
131 // fprintf(stderr,"PMMU: reading table C entries at %08x\n", tofs + tptr);
132 tbl_entry2 = m68k_read_memory_32(tofs + tptr);
133 tbl_entry = m68k_read_memory_32(tofs + tptr + 4);
134 tcmode = tbl_entry2 & 3;
135 // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
138 case 1: // termination descriptor
139 tbl_entry &= 0xffffff00;
141 shift = is+abits+bbits;
142 addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
152 case 0: // invalid, should cause MMU exception
153 case 2: // 4-byte ??? descriptor
154 case 3: // 8-byte ??? descriptor
155 fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC);
158 case 1: // termination descriptor
159 tbl_entry &= 0xffffff00;
161 shift = is+abits+bbits+cbits;
162 addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
169 // fprintf(stderr,"PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
176 m68881_mmu_ops: COP 0 MMU opcode handling
180 void m68881_mmu_ops()
183 uint32 ea = m68ki_cpu.ir & 0x3f;
186 // catch the 2 "weird" encodings up front (PBcc)
187 if ((m68ki_cpu.ir & 0xffc0) == 0xf0c0)
189 fprintf(stderr,"680x0: unhandled PBcc\n");
192 else if ((m68ki_cpu.ir & 0xffc0) == 0xf080)
194 fprintf(stderr,"680x0: unhandled PBcc\n");
197 else // the rest are 1111000xxxXXXXXX where xxx is the instruction family
199 switch ((m68ki_cpu.ir>>9) & 0x7)
204 if ((modes & 0xfde0) == 0x2000) // PLOAD
206 fprintf(stderr,"680x0: unhandled PLOAD\n");
209 else if ((modes & 0xe200) == 0x2000) // PFLUSH
211 fprintf(stderr,"680x0: unhandled PFLUSH PC=%x\n", REG_PC);
214 else if (modes == 0xa000) // PFLUSHR
216 fprintf(stderr,"680x0: unhandled PFLUSHR\n");
219 else if (modes == 0x2800) // PVALID (FORMAT 1)
221 fprintf(stderr,"680x0: unhandled PVALID1\n");
224 else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
226 fprintf(stderr,"680x0: unhandled PVALID2\n");
229 else if ((modes & 0xe000) == 0x8000) // PTEST
231 fprintf(stderr,"680x0: unhandled PTEST\n");
236 switch ((modes>>13) & 0x7)
238 case 0: // MC68030/040 form with FD bit
239 case 2: // MC68881 form, FD never set
242 switch ((modes>>10) & 7)
244 case 0: // translation control register
245 WRITE_EA_32(ea, m68ki_cpu.mmu_tc);
248 case 2: // supervisor root pointer
249 WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_srp_limit<<32 | (uint64)m68ki_cpu.mmu_srp_aptr);
252 case 3: // CPU root pointer
253 WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_crp_limit<<32 | (uint64)m68ki_cpu.mmu_crp_aptr);
257 fprintf(stderr,"680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC);
263 switch ((modes>>10) & 7)
265 case 0: // translation control register
266 m68ki_cpu.mmu_tc = READ_EA_32(ea);
268 if (m68ki_cpu.mmu_tc & 0x80000000)
270 m68ki_cpu.pmmu_enabled = 1;
274 m68ki_cpu.pmmu_enabled = 0;
278 case 2: // supervisor root pointer
279 temp64 = READ_EA_64(ea);
280 m68ki_cpu.mmu_srp_limit = (temp64>>32) & 0xffffffff;
281 m68ki_cpu.mmu_srp_aptr = temp64 & 0xffffffff;
284 case 3: // CPU root pointer
285 temp64 = READ_EA_64(ea);
286 m68ki_cpu.mmu_crp_limit = (temp64>>32) & 0xffffffff;
287 m68ki_cpu.mmu_crp_aptr = temp64 & 0xffffffff;
291 fprintf(stderr,"680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC);
297 case 3: // MC68030 to/from status reg
300 WRITE_EA_32(ea, m68ki_cpu.mmu_sr);
304 m68ki_cpu.mmu_sr = READ_EA_32(ea);
309 fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC);
316 fprintf(stderr,"680x0: unknown PMMU instruction group %d\n", (m68ki_cpu.ir>>9) & 0x7);