/
mam.go
116 lines (98 loc) · 2.87 KB
/
mam.go
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
// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package arm
import (
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/architecture"
"github.com/jetsetilly/gopher2600/hardware/preferences"
"github.com/jetsetilly/gopher2600/logger"
)
// MAM implements the memory addressing module as found in the LPC20000. Not
// fully implemented but good enough for most Harmony games
type mam struct {
prefs *preferences.ARMPreferences
mmap architecture.Map
// valid values for mamcr are 0, 1 or 2 are valid. we can think of these
// respectively, as "disable", "partial" and "full"
mamcr architecture.MAMCR
// NOTE: not used yet
mamtim uint32
// the preference value
pref int
// the address of the last prefetch and data read
prefectchLatch uint32
dataLatch uint32
// the address of the last branch. implements the branch trail buffer.
// if an unexpected PC value is the same as lastBranchAddress then there is
// no need to fetch from flash
branchLatch uint32
// if the previous cycle was a data read any pending MAM prefetch will be
// aborted causing a MAM miss
prefectchAborted bool
}
func newMam(prefs *preferences.ARMPreferences, mmap architecture.Map) mam {
return mam{
prefs: prefs,
mmap: mmap,
}
}
func (m *mam) Reset() {
}
func (m *mam) updatePrefs() {
m.pref = m.prefs.MAM.Get().(int)
if m.pref == preferences.MAMDriver {
m.mamcr = m.mmap.PreferredMAMCR
m.mamtim = 4.0
} else {
m.setMAMCR(architecture.MAMCR(m.pref))
m.mamtim = 4.0
}
}
func (m *mam) Write(addr uint32, val uint32) bool {
switch addr {
case m.mmap.MAMCR:
if m.pref == preferences.MAMDriver {
m.setMAMCR(architecture.MAMCR(val))
}
case m.mmap.MAMTIM:
if m.pref == preferences.MAMDriver {
if m.mamcr == 0 {
m.mamtim = val
} else {
logger.Logf("ARM7", "trying to write to MAMTIM while MAMCR is active")
}
}
default:
return false
}
return true
}
func (m *mam) Read(addr uint32) (uint32, bool) {
var val uint32
switch addr {
case m.mmap.MAMCR:
val = uint32(m.mamcr)
case m.mmap.MAMTIM:
val = m.mamtim
default:
return 0, false
}
return val, true
}
func (m *mam) setMAMCR(val architecture.MAMCR) {
m.mamcr = val
if m.mamcr > 2 {
logger.Logf("ARM7", "setting MAMCR to a value greater than 2 (%#08x)", m.mamcr)
}
}