summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/m68000/m68kmmu.h
blob: 33aec03565410f612ec71a4add7c441ef5e60daa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
    m68kmmu.h - PMMU implementation for 68851/68030/68040

    By R. Belmont

    Copyright Nicola Salmoria and the MAME Team.
    Visit http://mamedev.org for licensing and usage restrictions.
*/

/*
    pmmu_translate_addr: perform 68851/68030-style PMMU address translation
*/
INLINE UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
{
	UINT32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0;
	UINT32 root_aptr, root_limit, tofs, is, abits, bbits, cbits;
	UINT32 resolved, tptr, shift;

	resolved = 0;
	addr_out = addr_in;

	// if SRP is enabled and we're in supervisor mode, use it
	if ((m68k->mmu_tc & 0x02000000) && (m68ki_get_sr(m68k) & 0x2000))
	{
		root_aptr = m68k->mmu_srp_aptr;
		root_limit = m68k->mmu_srp_limit;
	}
	else	// else use the CRP
	{
		root_aptr = m68k->mmu_crp_aptr;
		root_limit = m68k->mmu_crp_limit;
	}

	// get initial shift (# of top bits to ignore)
	is = (m68k->mmu_tc>>16) & 0xf;
	abits = (m68k->mmu_tc>>12)&0xf;
	bbits = (m68k->mmu_tc>>8)&0xf;
	cbits = (m68k->mmu_tc>>4)&0xf;

//  logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);

	// get table A offset
	tofs = (addr_in<<is)>>(32-abits);

	// find out what format table A is
	switch (root_limit & 3)
	{
		case 0:	// invalid, should cause MMU exception
		case 1:	// page descriptor, should cause direct mapping
			fatalerror("680x0 PMMU: Unhandled root mode\n");
			break;

		case 2:	// valid 4 byte descriptors
			tofs *= 4;
//          logerror("PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc));
			tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc));
			tamode = tbl_entry & 3;
//          logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
			break;

		case 3: // valid 8 byte descriptors
			tofs *= 8;
//          logerror("PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc));
			tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc));
			tbl_entry = memory_read_dword_32be(m68k->program, tofs + (root_aptr & 0xfffffffc)+4);
			tamode = tbl_entry2 & 3;
//          logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
			break;
	}

	// get table B offset and pointer
	tofs = (addr_in<<(is+abits))>>(32-bbits);
	tptr = tbl_entry & 0xfffffff0;

	// find out what format table B is, if any
	switch (tamode)
	{
		case 0: // invalid, should cause MMU exception
			fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in);
			break;

		case 2: // 4-byte table B descriptor
			tofs *= 4;
//          logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
			tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr);
			tbmode = tbl_entry & 3;
//          logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
			break;

		case 3: // 8-byte table B descriptor
			tofs *= 8;
//          logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
			tbl_entry2 = memory_read_dword_32be(m68k->program, tofs + tptr);
			tbl_entry = memory_read_dword_32be(m68k->program, tofs + tptr + 4);
			tbmode = tbl_entry2 & 3;
//          logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
			break;

		case 1:	// early termination descriptor
			tbl_entry &= 0xffffff00;

			shift = is+abits;
			addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
			resolved = 1;
			break;
	}

	// if table A wasn't early-out, continue to process table B
	if (!resolved)
	{
		switch (tbmode)
		{
			case 0:	// invalid, should cause MMU exception
			case 2: // 4-byte table C descriptor
			case 3: // 8-byte table C descriptor
				fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x)\n", tbmode, addr_in);
				break;

			case 1: // early termination descriptor
				tbl_entry &= 0xffffff00;

				shift = is+abits+bbits;
				addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
				resolved = 1;
				break;
		}
	}

//  if ((addr_in < 0x40000000) || (addr_in > 0x4fffffff)) printf("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);

	return addr_out;
}

/*

maincpu at 40804366: called unimplemented instruction f000 (cpgen)
PMMU: tcr 80f05570 limit 7fff0003 aptr 043ffcc0 is 0
PMMU: reading table A entries at 043ffce0
PMMU: addr 4080438a entry 00000000 entry2 7ffffc18 mode 0 aofs 20
680x0 PMMU: Unhandled Table A mode 0

enable, PS = f

tblA @ 043ffcc0:

043ffcc0 0001fc0a 043ffcb0  =>  00000019 04000019
043ffcc8 7ffffc18 00000000
043ffcd0 7ffffc18 00000000
043ffcd8 7ffffc18 00000000
043ffce0 7ffffc18 00000000
043ffce8 7ffffc18 00000000
043ffcf0 7ffffc18 00000000
043ffcf8 7ffffc18 00000000
043ffd00 7ffffc19 40000000
043ffd08 7ffffc19 48000000
043ffd10 7ffffc59 50000000
043ffd18 7ffffc59 58000000
043ffd20 7ffffc59 60000000
043ffd28 7ffffc59 68000000
043ffd30 7ffffc59 70000000
043ffd38 7ffffc59 78000000
043ffd40 7ffffc59 80000000
043ffd48 7ffffc59 88000000
043ffd50 7ffffc59 90000000
043ffd58 7ffffc59 98000000
043ffd60 7ffffc59 a0000000
043ffd68 7ffffc59 a8000000
043ffd70 7ffffc59 b0000000
043ffd78 7ffffc59 b8000000
043ffd80 7ffffc59 c0000000
043ffd88 7ffffc59 c8000000
043ffd90 7ffffc59 d0000000
043ffd98 7ffffc59 d8000000
043ffda0 7ffffc59 e0000000
043ffda8 7ffffc59 e8000000
043ffdb0 7ffffc59 f0000000
043ffdb8 7ffffc59 f8000000

*/