openMSX
R800.hh
Go to the documentation of this file.
1#ifndef R800_HH
2#define R800_HH
3
4#include "CPUClock.hh"
5#include "CPURegs.hh"
6#include "Clock.hh"
7
8#include "inline.hh"
9#include "narrow.hh"
10#include "one_of.hh"
11#include "xrange.hh"
12
13#include <array>
14
15namespace openmsx {
16
17class R800TYPE : public CPUClock
18{
19public:
20 void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
21 {
22 extraMemoryDelay[page] =
23 extraMemoryDelays[page][primarySlot][secondarySlot];
24 }
25 void setDRAMmode(bool dram)
26 {
27 // TODO currently hardcoded, move to config file?
28 unsigned val = dram ? 0 : 1;
29 extraMemoryDelays[0][0][0] = val; // BIOS
30 extraMemoryDelays[1][0][0] = val; // BASIC
31 extraMemoryDelays[0][3][1] = val; // SUB-ROM
32 extraMemoryDelays[1][3][1] = val; // KANJI-DRIVER
33 }
34
35protected:
36 template<bool B> struct Normalize { static constexpr bool value = B; };
37
38 static constexpr int CLOCK_FREQ = 7159090;
39 static constexpr unsigned HALT_STATES = 1; // TODO check this
40 static constexpr bool IS_R800 = true;
41
42 R800TYPE(EmuTime::param time, Scheduler& scheduler_)
43 : CPUClock(time, scheduler_)
44 , lastRefreshTime(time)
45 {
47
48 // TODO currently hardcoded, move to config file?
49 for (auto page : xrange(4)) {
50 for (auto prim : xrange(4)) {
51 for (auto sec : xrange(4)) {
52 extraMemoryDelays[page][prim][sec] = [&] {
53 if (prim == one_of(1, 2)) {
54 // external slot
55 return 2;
56 } else if ((prim == 3) && (sec == 0)) {
57 // internal RAM
58 return 0;
59 } else {
60 // internal ROM
61 return 1;
62 }
63 }();
64 }
65 }
66 }
67 for (auto page : xrange(4)) {
68 extraMemoryDelay[page] = extraMemoryDelays[page][0][0];
69 }
70 }
71
73 {
74 lastPage = -1;
75 }
76
77 template<bool PRE_PB, bool POST_PB>
78 ALWAYS_INLINE void PRE_MEM(unsigned address)
79 {
80 int newPage = narrow<int>(address >> 8);
81 if constexpr (PRE_PB) {
82 // there is a statically predictable page break at this
83 // point -> 'add(1)' moved to static cost table
84 } else {
85 if ((newPage != lastPage) ||
86 (extraMemoryDelay[address >> 14])) [[unlikely]] {
87 add(1);
88 }
89 }
90 if constexpr (!POST_PB) {
91 lastPage = newPage;
92 }
93 }
94 template<bool POST_PB>
95 ALWAYS_INLINE void POST_MEM(unsigned address)
96 {
97 add(extraMemoryDelay[address >> 14]);
98 if constexpr (POST_PB) {
100 }
101 }
102 template<bool PRE_PB, bool POST_PB>
103 ALWAYS_INLINE void PRE_WORD(unsigned address)
104 {
105 int newPage = narrow<int>(address >> 8);
106 if constexpr (PRE_PB) {
107 // there is a statically predictable page break at this
108 // point -> 'add(1)' moved to static cost table
109 if (extraMemoryDelay[address >> 14]) [[unlikely]] {
110 add(1);
111 }
112 } else {
113 if (extraMemoryDelay[address >> 14]) [[unlikely]] {
114 add(2);
115 } else if (newPage != lastPage) [[unlikely]] {
116 add(1);
117 }
118 }
119 if constexpr (!POST_PB) {
120 lastPage = newPage;
121 }
122 }
123 template<bool POST_PB>
124 ALWAYS_INLINE void POST_WORD(unsigned address)
125 {
126 add(2 * extraMemoryDelay[address >> 14]);
127 if constexpr (POST_PB) {
129 }
130 }
131
133 {
134 // atoc documentation says refresh every 222 clocks
135 // duration: 256/1024KB 13.5 clocks
136 // 512KB 21.5 clocks
137 // But 26/210 matches measurements much better
138 // (loosely based on old measurements by Jon on his analogue scope)
139 EmuTime time = getTimeFast();
140 if (lastRefreshTime.getTicksTill_fast(time) >= 210) [[unlikely]] {
141 R800RefreshSlow(time, R); // slow-path not inline
142 }
143 }
144 NEVER_INLINE void R800RefreshSlow(EmuTime::param time, CPURegs& R)
145 {
146 do {
147 lastRefreshTime += 210;
148 } while (lastRefreshTime.getTicksTill_fast(time) >= 210); [[unlikely]]
150 add(25);
151 R800ForcePageBreak(); // TODO check this
152 R.incR(1);
153 }
154
155 void setTime(EmuTime::param time)
156 {
157 // Base class implementation.
158 CPUClock::setTime(time);
159
160 // Otherwise advance_fast() in R800Refresh() above, gets a too
161 // large time interval.
162 lastRefreshTime.reset(time);
163 }
164
165 ALWAYS_INLINE void setMemPtr(unsigned /*x*/) const { /* nothing*/ }
166 [[nodiscard]] ALWAYS_INLINE unsigned getMemPtr() const { return 0; } // dummy value
167
168 static constexpr int I = 6; // cycles for an I/O operation
169 static constexpr int O = 1; // wait for one cycle and wait for next even
170 // clock cycle (to sync with slower IO bus)
171 // the latter part must be implemented
172 // dynamically (not here in static tables)
173 static constexpr int P = 1; // cycles for a (statically known) page-break
174
175 static constexpr int
193
197 CC_CP_XIX = 3+P+1, CC_CP_XIX_1 = 1, CC_CP_XIX_2 = 3+P, // +1
199 CC_INC_XHL = 1+P+2+P+1, CC_INC_XHL_1 = 1, CC_INC_XHL_2 = 1+P+2+P,
200 CC_INC_XIX = 3+P+2+P+1, CC_INC_XIX_1 = 1, EE_INC_XIX = 2, // +1
204
205 CC_LDI = 2+P+1+P+1, CC_LDI_1 = 2+P, CC_LDI_2 = 2+P+1+P,
206 CC_LDIR = 2+P+1+P+1,
207 CC_CPI = 2+P+2, CC_CPI_1 = 2+P,
208 CC_CPIR = 2+P+3, // TODO check
209
210 CC_PUSH = 2+P+2, CC_PUSH_1 = 2+P,
211 CC_POP = 1+P+2, CC_POP_1 = 1+P,
212 CC_CALL = 3+P+2, CC_CALL_1 = 1, EE_CALL = 1,
214 CC_RST = 2+P+2, // TODO check
215 CC_RET_A = 1+P+2, CC_RET_B = 1, EE_RET_C = 0,
216 CC_RETN = 2+P+2, EE_RETN = 1, // TODO check
217 CC_JP_A = 4, CC_JP_B = 3, CC_JP_1 = 1,
219 CC_JR_A = 3, CC_JR_B = 2, CC_JR_1 = 1,
220 CC_DJNZ = 3, EE_DJNZ = 0,
221
223
226 CC_BIT_XIX = 3+P+1, CC_BIT_XIX_1 = 3+P, // +1
228 CC_SET_XHL = 2+P+2+P+1, CC_SET_XHL_1 = 2+P, CC_SET_XHL_2 = 2+P+2+P,
229 CC_SET_XIX = 3+P+2+P+1, EE_SET_XIX = 1, // +1
230
232 CC_RLD = 2+P+2+P+1, CC_RLD_1 = 2+P, CC_RLD_2 = 2+P+2+P,
233
236 CC_INI = 2+O+I+P+1, CC_INI_1 = 2+O, CC_INI_2 = 2+O+I+P,
237 CC_INIR = 2+O+I+P+1, // TODO check
240 CC_OUTI = 2+P+1+O+I, CC_OUTI_1 = 2+P, CC_OUTI_2 = 2+P+1+O,
241 CC_OTIR = 2+P+1+O+I, // TODO check
242
243 CC_EX = 1,
250 CC_DI = 2,
251 CC_EI = 1,
252 CC_HALT = 1, // TODO check
253 CC_IM = 3,
254
257
258 CC_NMI = 1+P+2, EE_NMI_1 = -1, // TODO check
259 CC_IRQ0 = 1+P+2, EE_IRQ0_1 = -1, // TODO check
260 CC_IRQ1 = 1+P+2, EE_IRQ1_1 = -1, // TODO check
261 CC_IRQ2 = 1+P+2+P+2, EE_IRQ2_1 = -1, CC_IRQ2_2 = 1+P+2+P, // TODO check
262
264 CC_DD = 1,
266 CC_DD_CB = 1, // +1
267 EE_ED = 1,
270
271 template<typename Archive>
272 void serialize(Archive& ar, unsigned version)
273 {
274 CPUClock::serialize(ar, version);
275 ar.serialize("lastRefreshTime", lastRefreshTime,
276 "lastPage", lastPage,
277 "extraMemoryDelay", extraMemoryDelay);
278
279 // don't serialize 'extraMemoryDelays', is initialized in
280 // constructor and setDRAMmode()
281 }
282
283private:
284 Clock<CLOCK_FREQ> lastRefreshTime;
285 int lastPage;
286
287 std::array<std::array<std::array<unsigned, 4>, 4>, 4> extraMemoryDelays;
288 std::array<unsigned, 4> extraMemoryDelay;
289};
290
291} // namespace openmsx
292
293#endif
void add(unsigned ticks)
Definition CPUClock.hh:28
void serialize(Archive &ar, unsigned version)
Definition CPUClock.cc:20
EmuTime getTimeFast() const
Definition CPUClock.hh:37
void setTime(EmuTime::param time)
Definition CPUClock.hh:41
void waitForEvenCycle(int cc)
R800 runs at 7MHz, but I/O is done over a slower 3.5MHz bus.
Definition CPUClock.hh:65
Represents a clock with a fixed frequency.
Definition Clock.hh:19
constexpr void reset(EmuTime::param e)
Reset the clock to start ticking at the given time.
Definition Clock.hh:103
constexpr unsigned getTicksTill_fast(EmuTime::param e) const
Same as above, only faster, Though the time interval may not be too large.
Definition Clock.hh:70
static constexpr int CC_MULUB
Definition R800.hh:255
static constexpr int CC_CPI
Definition R800.hh:207
static constexpr int CC_LD_R_R
Definition R800.hh:179
static constexpr int CC_NEG
Definition R800.hh:248
static constexpr int CC_LD_HL_N_2
Definition R800.hh:184
ALWAYS_INLINE void PRE_MEM(unsigned address)
Definition R800.hh:78
static constexpr int CC_RETN
Definition R800.hh:216
static constexpr int CC_CALL
Definition R800.hh:212
static constexpr int CC_LD_HL_XX_2
Definition R800.hh:189
static constexpr int CC_LD_XX_HL_1
Definition R800.hh:192
static constexpr int CC_IM
Definition R800.hh:253
static constexpr int CC_LD_R_HL_1
Definition R800.hh:181
static constexpr int CC_JR_1
Definition R800.hh:219
static constexpr int CC_LDI_2
Definition R800.hh:205
static constexpr int CC_CPI_1
Definition R800.hh:207
static constexpr int CC_LD_NN_A
Definition R800.hh:186
static constexpr int CC_LD_HL_N_1
Definition R800.hh:184
static constexpr int CC_PUSH_1
Definition R800.hh:210
static constexpr int CC_BIT_XIX
Definition R800.hh:226
static constexpr int CC_INC_XIX_1
Definition R800.hh:200
static constexpr int CC_JP_A
Definition R800.hh:217
void serialize(Archive &ar, unsigned version)
Definition R800.hh:272
static constexpr int CC_BIT_XHL
Definition R800.hh:225
static constexpr int CC_LD_NN_A_2
Definition R800.hh:186
static constexpr int CC_LD_HL_XX_1
Definition R800.hh:189
static constexpr int CC_BIT_XHL_1
Definition R800.hh:225
static constexpr int CC_LD_XIX_N
Definition R800.hh:188
static constexpr int CC_WRMEM
Definition R800.hh:269
static constexpr int CC_NOP
Definition R800.hh:244
static constexpr int CC_RST
Definition R800.hh:214
static constexpr int CC_JR_B
Definition R800.hh:219
ALWAYS_INLINE void PRE_WORD(unsigned address)
Definition R800.hh:103
static constexpr int CC_LD_SS_NN
Definition R800.hh:191
static constexpr int CC_LD_NN_A_1
Definition R800.hh:186
static constexpr int CC_CP_XHL_1
Definition R800.hh:196
static constexpr int EE_ED
Definition R800.hh:267
static constexpr int CC_JP_HL
Definition R800.hh:218
static constexpr int CC_CALL_A
Definition R800.hh:213
static constexpr int CC_LD_SP_HL
Definition R800.hh:190
static constexpr int CC_DI
Definition R800.hh:250
ALWAYS_INLINE unsigned getMemPtr() const
Definition R800.hh:166
static constexpr int CC_LD_A_NN_1
Definition R800.hh:177
static constexpr int CC_INC_XIX
Definition R800.hh:200
static constexpr int EE_IRQ1_1
Definition R800.hh:260
static constexpr int CC_RLD
Definition R800.hh:232
static constexpr int CC_LD_XIX_N_1
Definition R800.hh:188
static constexpr int CC_NMI
Definition R800.hh:258
static constexpr int CLOCK_FREQ
Definition R800.hh:38
static constexpr bool IS_R800
Definition R800.hh:40
static constexpr int CC_CP_XIX_1
Definition R800.hh:197
static constexpr int CC_INC_SS
Definition R800.hh:201
void setTime(EmuTime::param time)
Definition R800.hh:155
static constexpr int CC_LD_A_SS_1
Definition R800.hh:176
static constexpr int CC_RET_A
Definition R800.hh:215
static constexpr int CC_IRQ1
Definition R800.hh:260
static constexpr int CC_LD_HL_XX
Definition R800.hh:189
static constexpr int EE_RET_C
Definition R800.hh:215
ALWAYS_INLINE void R800ForcePageBreak()
Definition R800.hh:72
static constexpr int CC_LD_SS_NN_1
Definition R800.hh:191
static constexpr int CC_CALL_B
Definition R800.hh:213
static constexpr int CC_LD_XIX_N_2
Definition R800.hh:188
static constexpr int CC_RDMEM
Definition R800.hh:268
static constexpr int CC_SET_XHL_1
Definition R800.hh:228
static constexpr int CC_ADD_HL_SS
Definition R800.hh:202
static constexpr int CC_BIT_R
Definition R800.hh:224
static constexpr int CC_CP_XHL
Definition R800.hh:196
static constexpr int CC_MULUW
Definition R800.hh:256
static constexpr int CC_DAA
Definition R800.hh:247
static constexpr int CC_MAIN
Definition R800.hh:263
static constexpr int CC_LD_R_N
Definition R800.hh:180
static constexpr int CC_BIT_XIX_1
Definition R800.hh:226
static constexpr int P
Definition R800.hh:173
static constexpr int CC_EI
Definition R800.hh:251
static constexpr int CC_JP_B
Definition R800.hh:217
static constexpr int CC_CCF
Definition R800.hh:245
static constexpr int CC_LD_HL_N
Definition R800.hh:184
static constexpr int CC_INC_XHL
Definition R800.hh:199
static constexpr int CC_EX_SP_HL
Definition R800.hh:222
static constexpr int CC_OUT_C_R
Definition R800.hh:239
static constexpr int CC_EX
Definition R800.hh:243
static constexpr int CC_PUSH
Definition R800.hh:210
void updateVisiblePage(byte page, byte primarySlot, byte secondarySlot)
Definition R800.hh:20
ALWAYS_INLINE void R800Refresh(CPURegs &R)
Definition R800.hh:132
static constexpr int CC_RET_B
Definition R800.hh:215
static constexpr int CC_SET_XHL
Definition R800.hh:228
ALWAYS_INLINE void POST_WORD(unsigned address)
Definition R800.hh:124
R800TYPE(EmuTime::param time, Scheduler &scheduler_)
Definition R800.hh:42
static constexpr int CC_LD_HL_R
Definition R800.hh:183
static constexpr int CC_LD_A_NN
Definition R800.hh:177
static constexpr int CC_LD_R_XIX_1
Definition R800.hh:182
static constexpr int CC_HALT
Definition R800.hh:252
static constexpr int CC_EX_SP_HL_1
Definition R800.hh:222
static constexpr int CC_SCF
Definition R800.hh:246
static constexpr int CC_LD_XIX_R_2
Definition R800.hh:187
static constexpr int CC_CP_N_1
Definition R800.hh:195
static constexpr int CC_LD_R_HL
Definition R800.hh:181
static constexpr int CC_LD_A_NN_2
Definition R800.hh:177
static constexpr int CC_LD_SS_A
Definition R800.hh:185
static constexpr int CC_EX_SP_HL_2
Definition R800.hh:222
ALWAYS_INLINE void POST_MEM(unsigned address)
Definition R800.hh:95
static constexpr int CC_CP_R
Definition R800.hh:194
static constexpr int O
Definition R800.hh:169
static constexpr int CC_LD_HL_R_1
Definition R800.hh:183
static constexpr int CC_LD_XX_HL_2
Definition R800.hh:192
static constexpr int CC_INI
Definition R800.hh:236
static constexpr int CC_OUT_N_A_2
Definition R800.hh:238
static constexpr unsigned HALT_STATES
Definition R800.hh:39
static constexpr int EE_CALL
Definition R800.hh:212
static constexpr int CC_LD_XIX_R
Definition R800.hh:187
NEVER_INLINE void R800RefreshSlow(EmuTime::param time, CPURegs &R)
Definition R800.hh:144
static constexpr int CC_CALL_1
Definition R800.hh:212
static constexpr int CC_IRQ2
Definition R800.hh:261
void setDRAMmode(bool dram)
Definition R800.hh:25
static constexpr int CC_DJNZ
Definition R800.hh:220
static constexpr int CC_OUT_C_R_1
Definition R800.hh:239
static constexpr int CC_OTIR
Definition R800.hh:241
static constexpr int CC_RLD_1
Definition R800.hh:232
static constexpr int CC_LD_SS_A_1
Definition R800.hh:185
static constexpr int CC_POP_1
Definition R800.hh:211
static constexpr int EE_RETN
Definition R800.hh:216
static constexpr int CC_LD_XX_HL
Definition R800.hh:192
static constexpr int CC_SET_XIX
Definition R800.hh:229
static constexpr int CC_IN_R_C
Definition R800.hh:235
static constexpr int CC_IRQ0
Definition R800.hh:259
static constexpr int CC_INC_R
Definition R800.hh:198
static constexpr int CC_LDI
Definition R800.hh:205
static constexpr int CC_LD_XIX_R_1
Definition R800.hh:187
static constexpr int CC_CP_XIX
Definition R800.hh:197
static constexpr int CC_DD
Definition R800.hh:264
static constexpr int CC_OUT_N_A_1
Definition R800.hh:238
static constexpr int CC_OUTI_1
Definition R800.hh:240
static constexpr int CC_IN_A_N_1
Definition R800.hh:234
ALWAYS_INLINE void setMemPtr(unsigned) const
Definition R800.hh:165
static constexpr int CC_INC_XHL_1
Definition R800.hh:199
static constexpr int CC_LDIR
Definition R800.hh:206
static constexpr int CC_RLD_2
Definition R800.hh:232
static constexpr int CC_IN_A_N
Definition R800.hh:234
static constexpr int EE_NMI_1
Definition R800.hh:258
static constexpr int CC_CPIR
Definition R800.hh:208
static constexpr int CC_JR_A
Definition R800.hh:219
static constexpr int CC_LD_R_XIX_2
Definition R800.hh:182
static constexpr int EE_IRQ0_1
Definition R800.hh:259
static constexpr int CC_LD_A_SS
Definition R800.hh:176
static constexpr int CC_CPL
Definition R800.hh:249
static constexpr int CC_IN_R_C_1
Definition R800.hh:235
static constexpr int I
Definition R800.hh:168
static constexpr int CC_SET_XHL_2
Definition R800.hh:228
static constexpr int CC_INIR
Definition R800.hh:237
static constexpr int CC_SET_R
Definition R800.hh:227
static constexpr int CC_CP_XIX_2
Definition R800.hh:197
static constexpr int EE_INC_XIX
Definition R800.hh:200
static constexpr int CC_JP_1
Definition R800.hh:217
static constexpr int EE_IRQ2_1
Definition R800.hh:261
static constexpr int CC_OUTI
Definition R800.hh:240
static constexpr int CC_LD_R_N_1
Definition R800.hh:180
static constexpr int EE_DJNZ
Definition R800.hh:220
static constexpr int CC_ADC_HL_SS
Definition R800.hh:203
static constexpr int CC_LD_A_I
Definition R800.hh:178
static constexpr int CC_OUTI_2
Definition R800.hh:240
static constexpr int CC_CP_N
Definition R800.hh:195
static constexpr int CC_LD_R_XIX
Definition R800.hh:182
static constexpr int CC_DD_CB
Definition R800.hh:266
static constexpr int CC_PREFIX
Definition R800.hh:265
static constexpr int CC_POP
Definition R800.hh:211
static constexpr int CC_INI_2
Definition R800.hh:236
static constexpr int EE_SET_XIX
Definition R800.hh:229
static constexpr int CC_IRQ2_2
Definition R800.hh:261
static constexpr int CC_RLA
Definition R800.hh:231
static constexpr int CC_INC_XHL_2
Definition R800.hh:199
static constexpr int CC_OUT_N_A
Definition R800.hh:238
static constexpr int CC_LDI_1
Definition R800.hh:205
static constexpr int CC_INI_1
Definition R800.hh:236
static constexpr int CC_IN_A_N_2
Definition R800.hh:234
#define NEVER_INLINE
Definition inline.hh:17
#define ALWAYS_INLINE
Definition inline.hh:16
This file implemented 3 utility functions:
Definition Autofire.cc:11
static constexpr bool value
Definition R800.hh:36
constexpr auto xrange(T e)
Definition xrange.hh:132