1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood, Joakim Larsson Edstrom
3 /* 68340 SIM module */
4 
5 #include "emu.h"
6 #include "68340.h"
7 
8 //**************************************************************************
9 //  MACROS / CONSTANTS
10 //**************************************************************************
11 
12 //#define LOG_GENERAL (1U <<  0) // Already defined in logmacro.h
13 #define LOG_SETUP   (1U <<  1)
14 #define LOG_READ    (1U <<  2)
15 #define LOG_PORTS   (1U <<  3)
16 #define LOG_SIM     (1U <<  4)
17 #define LOG_CLOCK   (1U <<  5)
18 #define LOG_DATA    (1U <<  6)
19 #define LOG_INT     (1U <<  7)
20 #define LOG_PIT     (1U <<  8)
21 #define LOG_CS      (1U <<  9)
22 
23 #define VERBOSE  (LOG_PIT)
24 #define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
25 
26 #include "logmacro.h"
27 
28 //#define LOG(...) LOGMASKED(LOG_GENERAL,   __VA_ARGS__) // Already defined in logmacro.h
29 #define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
30 #define LOGR(...)     LOGMASKED(LOG_READ,  __VA_ARGS__)
31 #define LOGPORTS(...) LOGMASKED(LOG_PORTS, __VA_ARGS__)
32 #define LOGSIM(...)   LOGMASKED(LOG_SIM,   __VA_ARGS__)
33 #define LOGCLOCK(...) LOGMASKED(LOG_CLOCK, __VA_ARGS__)
34 #define LOGDATA(...)  LOGMASKED(LOG_DATA,  __VA_ARGS__)
35 #define LOGINT(...)   LOGMASKED(LOG_INT,   __VA_ARGS__)
36 #define LOGPIT(...)   LOGMASKED(LOG_PIT,   __VA_ARGS__)
37 #define LOGCS(...)    LOGMASKED(LOG_CS,    __VA_ARGS__)
38 
39 #ifdef _MSC_VER
40 #define FUNCNAME __func__
41 #else
42 #define FUNCNAME __PRETTY_FUNCTION__
43 #endif
44 
m68340_internal_sim_r(offs_t offset,uint16_t mem_mask)45 uint16_t m68340_cpu_device::m68340_internal_sim_r(offs_t offset, uint16_t mem_mask)
46 {
47 	LOGR("%s\n", FUNCNAME);
48 	assert(m_m68340SIM);
49 	m68340_sim &sim = *m_m68340SIM;
50 	int val = 0;
51 
52 	switch (offset * 2)
53 	{
54 		case m68340_sim::REG_MCR:
55 			LOGSIM("- %08x %s %04x, (%04x) (MCR - Module Configuration Register) - not implemented\n", m_ppc, FUNCNAME, offset * 2, mem_mask);
56 			val = sim.m_mcr;
57 			break;
58 
59 		case m68340_sim::REG_SYNCR:
60 			LOGSIM("- %08x %s %04x, (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
61 			val = sim.m_syncr;
62 			break;
63 
64 		case m68340_sim::REG_AVR_RSR: // Manual seems to say that AVR only autovectors externally triggered interrupts (INT1-INT7)
65 			LOGSIM("- %08x %s %04x, (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
66 			val = sim.m_avr_rsr;
67 			break;
68 
69 		case m68340_sim::REG_SWIV_SYPCR:
70 			LOGSIM("- %08x %s %04x, (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
71 			val = sim.m_swiv_sypcr;
72 			break;
73 
74 		case m68340_sim::REG_PICR:
75 			LOGPIT("- %08x %s %04x, (%04x) (PICR - Periodic Interrupt Control Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
76 			val = sim.m_picr;
77 			break;
78 
79 		case m68340_sim::REG_PITR:
80 			LOGPIT("- %08x %s %04x, (%04x) (PITR - Periodic Interrupt Timer Register) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
81 			val = sim.m_pitr;
82 			break;
83 
84 		case m68340_sim::REG_SWSR:
85 			LOGSIM("- %08x %s %04x, (%04x) (SWSR - Software Service) - not implemented\n", m_ppc, FUNCNAME, offset*2,mem_mask);
86 			val = sim.m_swsr;
87 			break;
88 
89 		default:
90 			logerror("- %08x %s %04x, (%04x) (unsupported register)\n", m_ppc, FUNCNAME, offset * 2, mem_mask);
91 			LOGSIM("- %08x %s %04x, (%04x) (unsupported register)\n", m_ppc, FUNCNAME, offset * 2, mem_mask);
92 	}
93 
94 	LOGR(" * Reg %02x -> %02x - %s\n", offset * 2, val,
95 		 ((offset * 2) >= 0x10 && (offset * 2) < 0x20) || (offset * 2) >= 0x60 ? "Error - should not happen" :
96 		 std::array<char const *, 8> {{"MCR", "reserved", "SYNCR", "AVR/RSR", "SWIV/SYPCR", "PICR", "PITR", "SWSR"}}[(offset * 2) <= m68340_sim::REG_AVR_RSR ? offset : offset - 0x10 + 0x04]);
97 
98 	return val;
99 }
100 
m68340_internal_sim_w(offs_t offset,uint16_t data,uint16_t mem_mask)101 void m68340_cpu_device::m68340_internal_sim_w(offs_t offset, uint16_t data, uint16_t mem_mask)
102 {
103 	LOG("\n%s\n", FUNCNAME);
104 	LOGSETUP(" * Reg %02x <- %02x - %s\n", offset * 2, data,
105 		 ((offset * 2) >= 0x10 && (offset * 2) < 0x20) || (offset * 2) >= 0x60 ? "Error - should not happen" :
106 		 std::array<char const *, 8> {{"MCR", "reserved", "SYNCR", "AVR/RSR", "SWIV/SYPCR", "PICR", "PITR", "SWSR"}}[(offset * 2) <= m68340_sim::REG_AVR_RSR ? offset : offset - 0x10 + 0x04]);
107 
108 	assert(m_m68340SIM);
109 	m68340_sim &sim = *m_m68340SIM;
110 
111 	switch (offset<<1)
112 	{
113 		case m68340_sim::REG_MCR:
114 			COMBINE_DATA(&sim.m_mcr);
115 			LOGSIM("PC: %08x %s %04x, %04x (%04x) (MCR - Module Configuration Register)\n", m_ppc, FUNCNAME, offset * 2, data, mem_mask);
116 			LOGPIT("- FRZ1: Watchdog and PIT timer are %s\n", (data & m68340_sim::REG_MCR_FRZ1) == 0 ? "enabled" : "disabled");
117 			LOGSIM("- FRZ0: The BUS monitor is %s\n", (data & m68340_sim::REG_MCR_FRZ0) == 0 ? "enabled" : "disabled");
118 			LOGSIM("- FIRQ: Full Interrupt Request Mode %s\n", data & m68340_sim::REG_MCR_FIRQ ? "used on port B" : "supressed, adding 4 chip select lines on Port B");
119 			LOGSIM("- SHEN0-SHEN1: Show Cycle Enable %02x - not implemented\n", ((data & m68340_sim::REG_MCR_SHEN) >> 8));
120 			LOGSIM("- Supervisor registers %s - not implemented\n", data & m68340_sim::REG_MCR_SVREG ? "requries supervisor privileges" : "can be accessed by user privileged software");
121 			LOGSIM("- Interrupt Arbitration level: %02x\n", data & m68340_sim::REG_MCR_ARBLV);
122 			break;
123 
124 		case m68340_sim::REG_SYNCR:
125 			LOGSIM("PC: %08x %s %04x, %04x (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", m_ppc, FUNCNAME, offset * 2, data, mem_mask);
126 			COMBINE_DATA(&sim.m_syncr);
127 			LOGSIM("- W    : VCO x %d\n", data & m68340_sim::REG_SYNCR_W ? 4 : 1);
128 			LOGSIM("- X    : System clock / %d\n", data & m68340_sim::REG_SYNCR_X ? 1 : 2);
129 			LOGSIM("- Y5-Y0: Divider: %d\n", (data & m68340_sim::REG_SYNCR_Y_MSK) >> 8);
130 			LOGSIM("- SLIMP: Loss of VCO input reference: %s\n", data & m68340_sim::REG_SYNCR_SLIMP ? "yes" : "no");
131 			LOGSIM("- SLOCK: Synthesizer lock: %s\n", data & m68340_sim::REG_SYNCR_SLOCK ? "yes" : "no");
132 			LOGSIM("- RSTEN: Loss of signal causes %s\n", data & m68340_sim::REG_SYNCR_RSTEN ? "system reset" : "limp mode (no external reference)");
133 			LOGSIM("- STSIM: LPSTOP makes SIM40 to use %s\n", data & m68340_sim::REG_SYNCR_STSIM ? "VCO" : "external clock/oscillator");
134 			LOGSIM("- STEXT: LPSTOP makes CLKOUT %s\n", data & m68340_sim::REG_SYNCR_STEXT ? "driven by SIM40 clock" : "low");
135 
136 			// Adjust VCO
137 			if (m_clock_mode == m68340_sim::CLOCK_MODE_CRYSTAL)
138 			{
139 				set_unscaled_clock(m_crystal *
140 								   (4 << (((sim.m_syncr & m68340_sim::REG_SYNCR_W) != 0 ? 2 : 0) + ((sim.m_syncr & m68340_sim::REG_SYNCR_X) != 0 ? 1 : 0))) *
141 								   (((sim.m_syncr & m68340_sim::REG_SYNCR_Y_MSK) >> 8) & 0x3f));
142 				LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
143 			}
144 			break;
145 
146 		case m68340_sim::REG_AVR_RSR:
147 			LOGSIM("PC: %08x %s %04x, %04x (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register)\n", m_ppc, FUNCNAME, offset * 2, data, mem_mask);
148 			COMBINE_DATA(&sim.m_avr_rsr);
149 			LOGSIM("- AVR: AV7-AV1 autovector bits:  %02x\n", ((data & m68340_sim::REG_AVR_VEC) >> 8) & 0xff);
150 			LOGSIM("- RSR: Last reset type:  %02x - not implemented\n", (data & m68340_sim::REG_RSR_RESBITS) & 0xff);
151 			break;
152 
153 		case m68340_sim::REG_SWIV_SYPCR:
154 			LOGSIM("PC: %08x %s %04x, %04x (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", m_ppc, FUNCNAME, offset * 2, data, mem_mask);
155 			COMBINE_DATA(&sim.m_swiv_sypcr);
156 			LOGSIM("- SWIV: Software watchdog Interrupt Vector: %02x\n", ((data & m68340_sim::REG_SWIV_VEC) >> 8) & 0xff);
157 			LOGSIM("- SWE : Software watchdog %s\n", (data & m68340_sim::REG_SYPCR_SWE) ? "enabled" : "disabled");
158 			LOGSIM("- SWRI: Software watchdog causes %s\n", (data & m68340_sim::REG_SYPCR_SWRI) ? "system reset" : "level 7 IRQ (NMI)");
159 			LOGSIM("- SWT : Software watchdog timing 2^%s/EXTAL Input Frequency\n",
160 				   std::array<char const *, 8> {{"9", "11", "13", "15", "18", "20", "22", "24"}}[((data & m68340_sim::REG_SYPCR_SWT) >> 4) | ((sim.m_pitr & m68340_sim::REG_PITR_SWP) >> 7)]);
161 			break;
162 
163 		case m68340_sim::REG_PICR:
164 			LOGPIT("PC: %08x %s %04x, %04x (%04x) (PICR - Periodic Interrupt Control Register)\n", m_ppc, FUNCNAME, offset*2,data,mem_mask);
165 			COMBINE_DATA(&sim.m_picr);
166 			LOGPIT("- PIRQL: Periodic Interrupt Level  %d%s\n", (data & m68340_sim::REG_PICR_PIRQL) >> 8, (data & m68340_sim::REG_PICR_PIRQL) == 0 ? " (disabled)" : "");
167 			LOGPIT("- PIV  : Periodic Interrupt Vector %02x\n", (data & m68340_sim::REG_PICR_PIVEC));
168 			update_ipl();
169 			break;
170 
171 		case m68340_sim::REG_PITR:
172 			LOGPIT("PC: %08x %s %04x, %04x (%04x) (PITR - Periodic Interrupt Timer Register)\n", m_ppc, FUNCNAME, offset*2,data,mem_mask);
173 			COMBINE_DATA(&sim.m_pitr);
174 			LOGSIM("- SWP  : Software watchdog prescale factor is %d\n", (data & m68340_sim::REG_PITR_SWP) ? 512 : 1);
175 			LOGPIT("- PTP  : Periodic timer prescale factor is %d\n", (data & m68340_sim::REG_PITR_PTP) ? 512 : 1);
176 			LOGPIT("- COUNT: is %d%s\n", (data & m68340_sim::REG_PITR_COUNT), (data & m68340_sim::REG_PITR_COUNT) == 0 ? " (off)" : "d");
177 			if ( (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) == 0 && (sim.m_pitr & m68340_sim::REG_PITR_COUNT) != 0)
178 			{
179 				LOGPIT("Starting PIT timer\n");
180 				sim.m_pit_counter = sim.m_pitr & m68340_sim::REG_PITR_COUNT;
181 				m_irq_timer->adjust(cycles_to_attotime((m_crystal / 4) / ((sim.m_pitr & m68340_sim::REG_PITR_PTP) != 0 ? 512 : 1)));
182 			}
183 
184 			break;
185 
186 		case m68340_sim::REG_SWSR:
187 			// basically watchdog, you must write an alternating pattern of 0x55 / 0xaa to keep the watchdog from resetting the system
188 			//LOGSIM("- %08x %s %04x, %04x (%04x) (SWSR - Software Service)\n", m_ppc, FUNCNAME, offset*2,data,mem_mask);
189 			break;
190 
191 		default:
192 			LOGSIM("- %08x %s %04x, %04x (%04x) - not implemented\n", m_ppc, FUNCNAME, offset*2,data,mem_mask);
193 
194 	}
195 }
196 
m68340_internal_sim_ports_r(offs_t offset)197 uint8_t m68340_cpu_device::m68340_internal_sim_ports_r(offs_t offset)
198 {
199 	LOGR("%s\n", FUNCNAME);
200 	offset += 0x10;
201 	assert(m_m68340SIM);
202 	m68340_sim &sim = *m_m68340SIM;
203 
204 	int val =  machine().rand();
205 
206 	switch (offset)
207 	{
208 		case m68340_sim::REG_PORTA:
209 			LOGR("- %08x %s %04x (PORTA - Port A Data)\n", m_ppc, FUNCNAME, offset);
210 			sim.m_porta &= sim.m_ddra;
211 			// TODO: call callback
212 
213 			if (!m_pa_in_cb.isnull())
214 			{
215 				sim.m_porta |= (m_pa_in_cb() & ~sim.m_ddra);
216 			}
217 #if 0
218 			else
219 			{
220 				sim.m_porta |= (sim.m_pail & ~sim.m_ddra);
221 			}
222 #endif
223 			val = sim.m_porta;
224 			break;
225 
226 		case m68340_sim::REG_DDRA:
227 			LOGR("- %08x %s %04x (DDRA - Port A Data Direction)\n", m_ppc, FUNCNAME, offset);
228 			val = sim.m_ddra;
229 			break;
230 
231 		case m68340_sim::REG_PPARA1:
232 			LOGR("- %08x %s %04x (PPRA1 - Port A Pin Assignment 1)\n", m_ppc, FUNCNAME, offset);
233 			val = sim.m_ppara1;
234 			break;
235 
236 		case m68340_sim::REG_PPARA2:
237 			LOGR("- %08x %s %04x (PPRA2 - Port A Pin Assignment 2) - not implemented\n", m_ppc, FUNCNAME, offset);
238 			val = sim.m_ppara2;
239 			break;
240 
241 		case m68340_sim::REG_PORTB1:
242 			LOGR("- %08x %s %04x (PORTB1 - Port B Data 1)\n", m_ppc, FUNCNAME, offset);
243 			// Fallthrough to mirror register
244 		case m68340_sim::REG_PORTB:
245 			LOGR("- %08x %s %04x (PORTB - Port B Data 0)\n", m_ppc, FUNCNAME, offset);
246 			sim.m_portb &= sim.m_ddrb;
247 			// TODO: call callback
248 
249 			if (!m_pb_in_cb.isnull())
250 			{
251 				sim.m_portb |= (m_pb_in_cb() & ~sim.m_ddrb);
252 			}
253 #if 0
254 			else
255 			{
256 				sim.m_portb |= (sim.m_pbil & ~sim.m_ddrb);
257 			}
258 #endif
259 			val = sim.m_portb;
260 			break;
261 
262 		case m68340_sim::REG_DDRB:
263 			LOGR("- %08x %s %04x (DDR - Port B Data Direction)\n", m_ppc, FUNCNAME, offset);
264 			val = sim.m_ddrb;
265 			break;
266 
267 		case m68340_sim::REG_PPARB:
268 			LOGR("- %08x %s %04x (PPARB - Port B Pin Assignment)\n", m_ppc, FUNCNAME, offset);
269 			val = sim.m_pparb;
270 			break;
271 
272 		default:
273 			LOGR("- %08x %s %04x (ILLEGAL?)\n", m_ppc, FUNCNAME, offset);
274 			logerror("%08x m68340_internal_sim_r %04x (ILLEGAL?)\n", m_ppc, FUNCNAME, offset);
275 			break;
276 	}
277 	LOGR(" * Reg %02x -> %02x - %s\n", offset, val, std::array<char const *, 16>
278 		 {{"", "PORTA", "", "DDRA", "", "PPARA1", "", "PPARA2", "", "PORTB","", "PORTB1", "", "DDRB", "", "PPARB"}}[offset - 0x10]);
279 
280 	return val;
281 }
282 
m68340_internal_sim_ports_w(offs_t offset,uint8_t data)283 void m68340_cpu_device::m68340_internal_sim_ports_w(offs_t offset, uint8_t data)
284 {
285 	LOG("%s", FUNCNAME);
286 	offset += 0x10;
287 	assert(m_m68340SIM);
288 	m68340_sim &sim = *m_m68340SIM;
289 
290 	LOGSETUP(" * Reg %02x <- %02x - %s\n", offset, data, std::array<char const *, 8>
291 			 {{"PORTA", "DDRA", "PPRA1", "PPRA2", "PORTB", "PORTB1", "DDRB", "PPARB"}}[(offset - 0x10) / 2]);
292 	switch (offset)
293 	{
294 		case m68340_sim::REG_PORTA:
295 			LOGDATA("- %08x %04x, %02x (PORTA - Port A Data)\n", m_ppc, offset,data);
296 			sim.m_porta = (data & sim.m_ddra & sim.m_ppara1);
297 
298 			// callback
299 			m_pa_out_cb ((offs_t)0, sim.m_porta);
300 			break;
301 
302 		case m68340_sim::REG_DDRA:
303 			LOGPORTS("- %08x %04x, %02x (DDRA - Port A Data Direction)\n", m_ppc, offset,data);
304 			sim.m_ddra = data;
305 			break;
306 
307 		case m68340_sim::REG_PPARA1:
308 			LOGPORTS("- %08x %04x, %02x (PPARA1 - Port A Pin Assignment 1)\n", m_ppc, offset,data);
309 			sim.m_ppara1 = data;
310 			break;
311 
312 		case m68340_sim::REG_PPARA2:
313 			LOGPORTS("- %08x %04x, %02x (PPARA2 - Port A Pin Assignment 2)\n", m_ppc, offset,data);
314 			sim.m_ppara2 = data;
315 			break;
316 
317 		case m68340_sim::REG_PORTB1:
318 			LOGDATA("- %08x %04x, %02x (PORTB1 - Port B Data - mirror)\n", m_ppc, offset,data);
319 			// Falling through to mirrored register portb
320 		case m68340_sim::REG_PORTB:
321 			LOGDATA("- %08x %04x, %02x (PORTB - Port B Data)\n", m_ppc, offset,data);
322 			sim.m_portb = (data & sim.m_ddrb & sim.m_pparb);
323 
324 			// callback
325 			m_pb_out_cb ((offs_t)0, sim.m_portb);
326 			break;
327 
328 		case m68340_sim::REG_DDRB:
329 			LOGPORTS("- %08x %04x, %02x (DDR - Port B Data Direction)\n", m_ppc, offset,data);
330 			sim.m_ddrb = data;
331 			break;
332 
333 		case m68340_sim::REG_PPARB:
334 			LOGPORTS("- %08x %04x, %02x (PPARB - Port B Pin Assignment)\n", m_ppc, offset,data);
335 			sim.m_pparb = data;
336 			break;
337 
338 		default:
339 			LOGPORTS("- %08x %s %04x, %02x (ILLEGAL?) - not implemented\n", m_ppc, FUNCNAME, offset,data);
340 			logerror("%08x m68340_internal_sim_ports_w %04x, %02x (ILLEGAL?)\n", m_ppc, offset,data);
341 			break;
342 	}
343 }
344 
m68340_internal_sim_cs_r(offs_t offset,uint32_t mem_mask)345 uint32_t m68340_cpu_device::m68340_internal_sim_cs_r(offs_t offset, uint32_t mem_mask)
346 {
347 	LOGR("%s\n", FUNCNAME);
348 	offset += m68340_sim::REG_AM_CS0>>2;
349 
350 	assert(m_m68340SIM);
351 	m68340_sim &sim = *m_m68340SIM;
352 
353 	switch (offset<<2)
354 	{
355 		case m68340_sim::REG_AM_CS0:  return sim.m_am[0];
356 		case m68340_sim::REG_BA_CS0:  return sim.m_ba[0];
357 		case m68340_sim::REG_AM_CS1:  return sim.m_am[1];
358 		case m68340_sim::REG_BA_CS1:  return sim.m_ba[1];
359 		case m68340_sim::REG_AM_CS2:  return sim.m_am[2];
360 		case m68340_sim::REG_BA_CS2:  return sim.m_ba[2];
361 		case m68340_sim::REG_AM_CS3:  return sim.m_am[3];
362 		case m68340_sim::REG_BA_CS3:  return sim.m_ba[3];
363 
364 		default:
365 			logerror("%08x m68340_internal_sim_r %08x, (%08x)\n", m_ppc, offset*4,mem_mask);
366 	}
367 
368 	return 0x00000000;
369 }
370 
m68340_internal_sim_cs_w(offs_t offset,uint32_t data,uint32_t mem_mask)371 void m68340_cpu_device::m68340_internal_sim_cs_w(offs_t offset, uint32_t data, uint32_t mem_mask)
372 {
373 	LOG("%s\n", FUNCNAME);
374 	offset += m68340_sim::REG_AM_CS0>>2;
375 
376 	if (offset & 1)
377 	{
378 	  LOGCS("%08x Base address CS%d %08x, %08x (%08x) ", m_ppc, (offset - 0x10) / 2, offset * 4, data, mem_mask);
379 	  LOGCS("- Base: %08x BFC:%02x WP:%d FTE:%d NCS:%d Valid: %s\n", data & 0xffffff00, (data & 0xf0) >> 4, data & 0x08 ? 1 : 0, data & 0x04 ? 1 : 0, data & 0x02 ? 1 : 0, data & 0x01 ? "Yes" : "No");
380 	}
381 	else
382 	{
383 	  LOGCS("%08x Address mask CS%d %08x, %08x (%08x) ", m_ppc, (offset - 0x10) / 2, offset * 4, data, mem_mask);
384 	  LOGCS("- Mask: %08x FCM:%02x DD:%d PS: %s\n", data & 0xffffff00, (data & 0xf0) >> 4, (data >> 2) & 0x03, std::array<char const *, 4>{{"Reserved", "16-Bit", "8-bit", "External DSACK response"}}[data & 0x03]);
385 	}
386 
387 	assert(m_m68340SIM);
388 	m68340_sim &sim = *m_m68340SIM;
389 
390 	switch (offset << 2)
391 	{
392 		case m68340_sim::REG_AM_CS0:
393 			COMBINE_DATA(&sim.m_am[0]);
394 			break;
395 
396 		case m68340_sim::REG_BA_CS0:
397 			COMBINE_DATA(&sim.m_ba[0]);
398 			break;
399 
400 		case m68340_sim::REG_AM_CS1:
401 			COMBINE_DATA(&sim.m_am[1]);
402 			break;
403 
404 		case m68340_sim::REG_BA_CS1:
405 			COMBINE_DATA(&sim.m_ba[1]);
406 			break;
407 
408 		case m68340_sim::REG_AM_CS2:
409 			COMBINE_DATA(&sim.m_am[2]);
410 			break;
411 
412 		case m68340_sim::REG_BA_CS2:
413 			COMBINE_DATA(&sim.m_ba[2]);
414 			break;
415 
416 		case m68340_sim::REG_AM_CS3:
417 			COMBINE_DATA(&sim.m_am[3]);
418 			break;
419 
420 		case m68340_sim::REG_BA_CS3:
421 			COMBINE_DATA(&sim.m_ba[3]);
422 			break;
423 
424 		default:
425 			logerror("%08x m68340_internal_sim_cs_w %08x, %08x (%08x)\n", m_ppc, offset*4,data,mem_mask);
426 			break;
427 	}
428 }
429 
TIMER_CALLBACK_MEMBER(m68340_cpu_device::periodic_interrupt_timer_callback)430 TIMER_CALLBACK_MEMBER(m68340_cpu_device::periodic_interrupt_timer_callback)
431 {
432 	do_tick_pit();
433 }
434 
start_68340_sim()435 void m68340_cpu_device::start_68340_sim()
436 {
437 	LOG("%s\n", FUNCNAME);
438 	LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
439 	m_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68340_cpu_device::periodic_interrupt_timer_callback),this));
440 
441 	// resolve callbacks Port A
442 	m_pa_out_cb.resolve_safe();
443 	m_pa_in_cb.resolve();
444 
445 	// resolve callbacks Port B
446 	m_pb_out_cb.resolve_safe();
447 	m_pb_in_cb.resolve();
448 
449 	// Setup correct VCO/clock speed based on reset values and crystal
450 	assert(m_m68340SIM);
451 	m68340_sim &sim = *m_m68340SIM;
452 	switch (m_clock_mode)
453 	{
454 	case m68340_sim::CLOCK_MODE_EXT:
455 		LOGCLOCK("External Clock Mode\n");
456 		break;
457 	case m68340_sim::CLOCK_MODE_EXT_PLL:
458 		LOGCLOCK("External Clock Mode with PLL - not implemented\n");
459 		logerror("External Clock Mode with PLL - not implemented\n");
460 		break;
461 	case m68340_sim::CLOCK_MODE_CRYSTAL:
462 		LOGCLOCK("Crystal Mode with VCO and PLL\n");
463 		set_unscaled_clock(m_crystal *
464 						   (4 << (((sim.m_syncr & m68340_sim::REG_SYNCR_W) != 0 ? 2 : 0) + ((sim.m_syncr & m68340_sim::REG_SYNCR_X) != 0 ? 1 : 0))) *
465 						   (((sim.m_syncr & m68340_sim::REG_SYNCR_Y_MSK) >> 8) & 0x3f));
466 		LOGCLOCK("SYNCR: %04x\n", sim.m_syncr);
467 		break;
468 	default:
469 		logerror("Unknown Clock mode, check schematics and/or the source code\n");
470 	}
471 	LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
472 }
473 
reset()474 void m68340_sim::reset()
475 {
476 	LOG("%s\n", FUNCNAME);
477 
478 	// Ports - only setup those that are affected by reset
479 	m_ddra   = 0x00;
480 	m_ppara1 = 0xff;
481 	m_ppara2 = 0x00;
482 	m_ddrb   = 0x00;
483 	m_pparb  = 0xff;
484 
485 	// SIM
486 	m_mcr   = 0x608f;
487 	m_syncr = 0x3f00;
488 	m_avr_rsr = 0x0000;
489 	m_swiv_sypcr = 0x0f00;
490 	m_picr= 0x000f;
491 	m_pitr= 0x0000; // TODO: read MODCK pin to set the clock modes for watch dog and periodic timer
492 	m_swsr= 0x0000;
493 	m_pit_irq = false;
494 }
495 
module_reset()496 void m68340_sim::module_reset()
497 {
498 	// SYS set in RSR, nothing else happens
499 	m_avr_rsr = (m_avr_rsr & 0xff00) | 0x02;
500 }
501 
502 /* do_tick_pit works on whole clock cycles, no flank support */
do_tick_pit()503 void m68340_cpu_device::do_tick_pit()
504 {
505 	assert(m_m68340SIM);
506 	m68340_sim &sim = *m_m68340SIM;
507 
508 	sim.m_pit_counter--;
509 	if ( ( (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) == 0) &&
510 		 ( (sim.m_pit_counter != 0 || (sim.m_pitr & m68340_sim::REG_PITR_COUNT) != 0)))
511 	{
512 		LOGPIT("Re-arming PIT timer\n");
513 		sim.m_pit_counter = sim.m_pitr & m68340_sim::REG_PITR_COUNT;
514 		m_irq_timer->adjust(cycles_to_attotime((m_crystal / 4) / ((sim.m_pitr & m68340_sim::REG_PITR_PTP) != 0 ? 512 : 1)));
515 	}
516 	else
517 	{
518 		LOGPIT("Stopping PIT timer dues to %s\n", (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) != 0 ? "Freeze" : "Counter disabled");
519 		m_irq_timer->adjust(attotime::never);
520 	}
521 
522 	if (sim.m_pit_counter == 0) // Zero detect
523 	{
524 		LOGPIT("PIT timer reached zero!\n");
525 		sim.m_pit_irq = true;
526 		update_ipl();
527 	}
528 }
529 
WRITE_LINE_MEMBER(m68340_cpu_device::extal_w)530 WRITE_LINE_MEMBER( m68340_cpu_device::extal_w )
531 {
532 	LOGPIT("%s H1 set to %d\n", FUNCNAME, state);
533 	m_extal = state;
534 	if (m_extal == ASSERT_LINE)
535 	{
536 		do_tick_pit();
537 	}
538 }
539 
pit_irq_level() const540 uint8_t m68340_cpu_device::pit_irq_level() const
541 {
542 	return m_m68340SIM->m_pit_irq ? (m_m68340SIM->m_picr & m68340_sim::REG_PICR_PIRQL) >> 8 : 0;
543 }
544 
pit_arbitrate(uint8_t level) const545 uint8_t m68340_cpu_device::pit_arbitrate(uint8_t level) const
546 {
547 	if (pit_irq_level() == level)
548 		return m_m68340SIM->m_mcr & m68340_sim::REG_MCR_ARBLV;
549 	else
550 		return 0;
551 }
552 
pit_iack()553 uint8_t m68340_cpu_device::pit_iack()
554 {
555 	m_m68340SIM->m_pit_irq = false;
556 	update_ipl();
557 	return m_m68340SIM->m_picr & m68340_sim::REG_PICR_PIVEC;
558 }
559