/[gxemul]/trunk/src/devices/dev_sh4.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/devices/dev_sh4.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 27971 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: dev_sh4.c,v 1.29 2007/01/29 18:06:37 debug Exp $
29 *
30 * SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).
31 *
32 * TODO: Lots and lots of stuff.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "console.h"
40 #include "cpu.h"
41 #include "device.h"
42 #include "devices.h"
43 #include "interrupt.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47 #include "timer.h"
48
49 #include "sh4_bscreg.h"
50 #include "sh4_cache.h"
51 #include "sh4_dmacreg.h"
52 #include "sh4_exception.h"
53 #include "sh4_intcreg.h"
54 #include "sh4_mmu.h"
55 #include "sh4_rtcreg.h"
56 #include "sh4_scifreg.h"
57 #include "sh4_tmureg.h"
58
59
60 #define SH4_REG_BASE 0xff000000
61 #define SH4_TICK_SHIFT 14
62 #define N_SH4_TIMERS 3
63
64 /* General-purpose I/O stuff: */
65 #define SH4_PCTRA 0xff80002c
66 #define SH4_PDTRA 0xff800030
67 #define SH4_PCTRB 0xff800040
68 #define SH4_PDTRB 0xff800044
69 #define SH4_GPIOIC 0xff800048
70
71 #ifdef UNSTABLE_DEVEL
72 #define SH4_DEGUG
73 /* #define debug fatal */
74 #endif
75
76 struct sh4_data {
77 /* SCIF (Serial controller): */
78 uint16_t scif_smr;
79 uint8_t scif_brr;
80 uint16_t scif_scr;
81 uint16_t scif_fcr;
82 int scif_console_handle;
83
84 /* Bus State Controller: */
85 uint32_t bsc_bcr1;
86 uint16_t bsc_bcr2;
87 uint32_t bsc_wcr1;
88 uint32_t bsc_wcr2;
89 uint32_t bsc_mcr;
90 uint16_t bsc_rtcsr;
91 uint16_t bsc_rtcor;
92 uint16_t bsc_rfcr;
93
94 /* GPIO: */
95 uint32_t pctra; /* Port Control Register A */
96 uint32_t pdtra; /* Port Data Register A */
97 uint32_t pctrb; /* Port Control Register B */
98 uint32_t pdtrb; /* Port Data Register B */
99
100 /* SD-RAM: */
101 uint16_t sdmr2;
102 uint16_t sdmr3;
103
104 /* Timer Management Unit: */
105 struct timer *sh4_timer;
106 struct interrupt timer_irq[4];
107 uint32_t tocr;
108 uint32_t tstr;
109 uint32_t tcnt[N_SH4_TIMERS];
110 uint32_t tcor[N_SH4_TIMERS];
111 uint32_t tcr[N_SH4_TIMERS];
112 int timer_interrupts_pending[N_SH4_TIMERS];
113 double timer_hz[N_SH4_TIMERS];
114
115 /* RTC: */
116 uint32_t rtc_reg[14]; /* Excluding rcr1 and 2 */
117 uint8_t rtc_rcr1;
118 };
119
120
121 #define SH4_PSEUDO_TIMER_HZ 100.0
122
123
124 /*
125 * sh4_timer_tick():
126 *
127 * This function is called SH4_PSEUDO_TIMER_HZ times per real-world second.
128 * Its job is to update the SH4 timer counters, and if necessary, increase
129 * the number of pending interrupts.
130 *
131 * Also, RAM Refresh is also faked here.
132 */
133 static void sh4_timer_tick(struct timer *t, void *extra)
134 {
135 struct sh4_data *d = (struct sh4_data *) extra;
136 int i;
137
138 /* Fake RAM refresh: */
139 d->bsc_rfcr ++;
140 if (d->bsc_rtcsr & (RTCSR_CMIE | RTCSR_OVIE)) {
141 fatal("sh4: RTCSR_CMIE | RTCSR_OVIE: TODO\n");
142 /* TODO: Implement refresh interrupts etc. */
143 exit(1);
144 }
145
146 for (i=0; i<N_SH4_TIMERS; i++) {
147 int32_t old = d->tcnt[i];
148
149 /* printf("tcnt[%i] = %08x tcor[%i] = %08x\n",
150 i, d->tcnt[i], i, d->tcor[i]); */
151
152 /* Only update timers that are currently started: */
153 if (!(d->tstr & (TSTR_STR0 << i)))
154 continue;
155
156 /* Update the current count: */
157 d->tcnt[i] -= d->timer_hz[i] / SH4_PSEUDO_TIMER_HZ;
158
159 /* Has the timer underflowed? */
160 if ((int32_t)d->tcnt[i] < 0 && old >= 0) {
161 d->tcr[i] |= TCR_UNF;
162
163 if (d->tcr[i] & TCR_UNIE)
164 d->timer_interrupts_pending[i] ++;
165
166 /*
167 * Set tcnt[i] to tcor[i]. Note: Since this function
168 * is only called now and then, adding tcor[i] to
169 * tcnt[i] produces more correct values for long
170 * running timers.
171 */
172 d->tcnt[i] += d->tcor[i];
173
174 /* At least make sure that tcnt is non-negative... */
175 if ((int32_t)d->tcnt[i] < 0)
176 d->tcnt[i] = 0;
177 }
178 }
179 }
180
181
182 DEVICE_TICK(sh4)
183 {
184 struct sh4_data *d = (struct sh4_data *) extra;
185 int i;
186
187 for (i=0; i<N_SH4_TIMERS; i++)
188 if (d->timer_interrupts_pending[i] > 0) {
189 INTERRUPT_ASSERT(d->timer_irq[i]);
190 d->tcr[i] |= TCR_UNF;
191 }
192 }
193
194
195 DEVICE_ACCESS(sh4_itlb_aa)
196 {
197 uint64_t idata = 0, odata = 0;
198 int e = (relative_addr & SH4_ITLB_E_MASK) >> SH4_ITLB_E_SHIFT;
199
200 if (writeflag == MEM_WRITE) {
201 int safe_to_invalidate = 0;
202 uint32_t old_hi = cpu->cd.sh.itlb_hi[e];
203 if ((cpu->cd.sh.itlb_lo[e] & SH4_PTEL_SZ_MASK)==SH4_PTEL_SZ_4K)
204 safe_to_invalidate = 1;
205
206 idata = memory_readmax64(cpu, data, len);
207 cpu->cd.sh.itlb_hi[e] &=
208 ~(SH4_PTEH_VPN_MASK | SH4_PTEH_ASID_MASK);
209 cpu->cd.sh.itlb_hi[e] |= (idata &
210 (SH4_ITLB_AA_VPN_MASK | SH4_ITLB_AA_ASID_MASK));
211 cpu->cd.sh.itlb_lo[e] &= ~SH4_PTEL_V;
212 if (idata & SH4_ITLB_AA_V)
213 cpu->cd.sh.itlb_lo[e] |= SH4_PTEL_V;
214
215 /* Invalidate if this ITLB entry previously belonged to the
216 currently running process, or if it was shared: */
217 if (cpu->cd.sh.ptel & SH4_PTEL_SH ||
218 (old_hi & SH4_ITLB_AA_ASID_MASK) ==
219 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
220 if (safe_to_invalidate)
221 cpu->invalidate_translation_caches(cpu,
222 old_hi & ~0xfff, INVALIDATE_VADDR);
223 else
224 cpu->invalidate_translation_caches(cpu,
225 0, INVALIDATE_ALL);
226 }
227 } else {
228 odata = cpu->cd.sh.itlb_hi[e] &
229 (SH4_ITLB_AA_VPN_MASK | SH4_ITLB_AA_ASID_MASK);
230 if (cpu->cd.sh.itlb_lo[e] & SH4_PTEL_V)
231 odata |= SH4_ITLB_AA_V;
232 memory_writemax64(cpu, data, len, odata);
233 }
234
235 return 1;
236 }
237
238
239 DEVICE_ACCESS(sh4_itlb_da1)
240 {
241 uint32_t mask = SH4_PTEL_SH | SH4_PTEL_C | SH4_PTEL_SZ_MASK |
242 SH4_PTEL_PR_MASK | SH4_PTEL_V | 0x1ffffc00;
243 uint64_t idata = 0, odata = 0;
244 int e = (relative_addr & SH4_ITLB_E_MASK) >> SH4_ITLB_E_SHIFT;
245
246 if (relative_addr & 0x800000) {
247 fatal("sh4_itlb_da1: TODO: da2 area\n");
248 exit(1);
249 }
250
251 if (writeflag == MEM_WRITE) {
252 uint32_t old_lo = cpu->cd.sh.itlb_lo[e];
253 int safe_to_invalidate = 0;
254 if ((cpu->cd.sh.itlb_lo[e] & SH4_PTEL_SZ_MASK)==SH4_PTEL_SZ_4K)
255 safe_to_invalidate = 1;
256
257 idata = memory_readmax64(cpu, data, len);
258 cpu->cd.sh.itlb_lo[e] &= ~mask;
259 cpu->cd.sh.itlb_lo[e] |= (idata & mask);
260
261 /* Invalidate if this ITLB entry belongs to the
262 currently running process, or if it was shared: */
263 if (old_lo & SH4_PTEL_SH ||
264 (cpu->cd.sh.itlb_hi[e] & SH4_ITLB_AA_ASID_MASK) ==
265 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
266 if (safe_to_invalidate)
267 cpu->invalidate_translation_caches(cpu,
268 cpu->cd.sh.itlb_hi[e] & ~0xfff,
269 INVALIDATE_VADDR);
270 else
271 cpu->invalidate_translation_caches(cpu,
272 0, INVALIDATE_ALL);
273 }
274 } else {
275 odata = cpu->cd.sh.itlb_lo[e] & mask;
276 memory_writemax64(cpu, data, len, odata);
277 }
278
279 return 1;
280 }
281
282
283 DEVICE_ACCESS(sh4_utlb_aa)
284 {
285 uint64_t idata = 0, odata = 0;
286 int i, e = (relative_addr & SH4_UTLB_E_MASK) >> SH4_UTLB_E_SHIFT;
287 int a = relative_addr & SH4_UTLB_A;
288
289 if (writeflag == MEM_WRITE) {
290 int n_hits = 0;
291 int safe_to_invalidate = 0;
292 uint32_t vaddr_to_invalidate = 0;
293
294 idata = memory_readmax64(cpu, data, len);
295 if (a) {
296 for (i=-SH_N_ITLB_ENTRIES; i<SH_N_UTLB_ENTRIES; i++) {
297 uint32_t lo, hi;
298 uint32_t mask = 0xfffff000;
299 int sh;
300
301 if (i < 0) {
302 lo = cpu->cd.sh.itlb_lo[
303 i + SH_N_ITLB_ENTRIES];
304 hi = cpu->cd.sh.itlb_hi[
305 i + SH_N_ITLB_ENTRIES];
306 } else {
307 lo = cpu->cd.sh.utlb_lo[i];
308 hi = cpu->cd.sh.utlb_hi[i];
309 }
310
311 sh = lo & SH4_PTEL_SH;
312 if (!(lo & SH4_PTEL_V))
313 continue;
314
315 switch (lo & SH4_PTEL_SZ_MASK) {
316 case SH4_PTEL_SZ_1K: mask = 0xfffffc00; break;
317 case SH4_PTEL_SZ_64K: mask = 0xffff0000; break;
318 case SH4_PTEL_SZ_1M: mask = 0xfff00000; break;
319 }
320
321 if ((hi & mask) != (idata & mask))
322 continue;
323
324 if ((lo & SH4_PTEL_SZ_MASK) ==
325 SH4_PTEL_SZ_4K) {
326 safe_to_invalidate = 1;
327 vaddr_to_invalidate = hi & mask;
328 }
329
330 if (!sh && (hi & SH4_PTEH_ASID_MASK) !=
331 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK))
332 continue;
333
334 if (i < 0) {
335 cpu->cd.sh.itlb_lo[i] &= ~SH4_PTEL_V;
336 if (idata & SH4_UTLB_AA_V)
337 cpu->cd.sh.itlb_lo[i] |=
338 SH4_PTEL_V;
339 } else {
340 cpu->cd.sh.utlb_lo[i] &=
341 ~(SH4_PTEL_D | SH4_PTEL_V);
342 if (idata & SH4_UTLB_AA_D)
343 cpu->cd.sh.utlb_lo[i] |=
344 SH4_PTEL_D;
345 if (idata & SH4_UTLB_AA_V)
346 cpu->cd.sh.utlb_lo[i] |=
347 SH4_PTEL_V;
348 }
349
350 if (i >= 0)
351 n_hits ++;
352 }
353
354 if (n_hits > 1)
355 sh_exception(cpu,
356 EXPEVT_RESET_TLB_MULTI_HIT, 0, 0);
357 } else {
358 if ((cpu->cd.sh.utlb_lo[e] & SH4_PTEL_SZ_MASK) ==
359 SH4_PTEL_SZ_4K) {
360 safe_to_invalidate = 1;
361 vaddr_to_invalidate =
362 cpu->cd.sh.utlb_hi[e] & ~0xfff;
363 }
364
365 cpu->cd.sh.utlb_hi[e] &=
366 ~(SH4_PTEH_VPN_MASK | SH4_PTEH_ASID_MASK);
367 cpu->cd.sh.utlb_hi[e] |= (idata &
368 (SH4_UTLB_AA_VPN_MASK | SH4_UTLB_AA_ASID_MASK));
369
370 cpu->cd.sh.utlb_lo[e] &= ~(SH4_PTEL_D | SH4_PTEL_V);
371 if (idata & SH4_UTLB_AA_D)
372 cpu->cd.sh.utlb_lo[e] |= SH4_PTEL_D;
373 if (idata & SH4_UTLB_AA_V)
374 cpu->cd.sh.utlb_lo[e] |= SH4_PTEL_V;
375 }
376
377 if (safe_to_invalidate)
378 cpu->invalidate_translation_caches(cpu,
379 vaddr_to_invalidate, INVALIDATE_VADDR);
380 else
381 cpu->invalidate_translation_caches(cpu, 0,
382 INVALIDATE_ALL);
383 } else {
384 odata = cpu->cd.sh.utlb_hi[e] &
385 (SH4_UTLB_AA_VPN_MASK | SH4_UTLB_AA_ASID_MASK);
386 if (cpu->cd.sh.utlb_lo[e] & SH4_PTEL_D)
387 odata |= SH4_UTLB_AA_D;
388 if (cpu->cd.sh.utlb_lo[e] & SH4_PTEL_V)
389 odata |= SH4_UTLB_AA_V;
390 memory_writemax64(cpu, data, len, odata);
391 }
392
393 return 1;
394 }
395
396
397 DEVICE_ACCESS(sh4_utlb_da1)
398 {
399 uint32_t mask = SH4_PTEL_WT | SH4_PTEL_SH | SH4_PTEL_D | SH4_PTEL_C
400 | SH4_PTEL_SZ_MASK | SH4_PTEL_PR_MASK | SH4_PTEL_V | 0x1ffffc00;
401 uint64_t idata = 0, odata = 0;
402 int e = (relative_addr & SH4_UTLB_E_MASK) >> SH4_UTLB_E_SHIFT;
403
404 if (relative_addr & 0x800000) {
405 fatal("sh4_utlb_da1: TODO: da2 area\n");
406 exit(1);
407 }
408
409 if (writeflag == MEM_WRITE) {
410 uint32_t old_lo = cpu->cd.sh.utlb_lo[e];
411 int safe_to_invalidate = 0;
412 if ((cpu->cd.sh.utlb_lo[e] & SH4_PTEL_SZ_MASK)==SH4_PTEL_SZ_4K)
413 safe_to_invalidate = 1;
414
415 idata = memory_readmax64(cpu, data, len);
416 cpu->cd.sh.utlb_lo[e] &= ~mask;
417 cpu->cd.sh.utlb_lo[e] |= (idata & mask);
418
419 /* Invalidate if this UTLB entry belongs to the
420 currently running process, or if it was shared: */
421 if (old_lo & SH4_PTEL_SH ||
422 (cpu->cd.sh.utlb_hi[e] & SH4_ITLB_AA_ASID_MASK) ==
423 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
424 if (safe_to_invalidate)
425 cpu->invalidate_translation_caches(cpu,
426 cpu->cd.sh.utlb_hi[e] & ~0xfff,
427 INVALIDATE_VADDR);
428 else
429 cpu->invalidate_translation_caches(cpu,
430 0, INVALIDATE_ALL);
431 }
432 } else {
433 odata = cpu->cd.sh.utlb_lo[e] & mask;
434 memory_writemax64(cpu, data, len, odata);
435 }
436
437 return 1;
438 }
439
440
441 DEVICE_ACCESS(sh4)
442 {
443 struct sh4_data *d = (struct sh4_data *) extra;
444 uint64_t idata = 0, odata = 0;
445 int timer_nr = 0, dma_channel = 0;
446
447 if (writeflag == MEM_WRITE)
448 idata = memory_readmax64(cpu, data, len);
449
450 relative_addr += SH4_REG_BASE;
451
452 /* SD-RAM access uses address only: */
453 if (relative_addr >= 0xff900000 && relative_addr <= 0xff97ffff) {
454 /* Possibly not 100% correct... TODO */
455 int v = (relative_addr >> 2) & 0xffff;
456 if (relative_addr & 0x00040000)
457 d->sdmr3 = v;
458 else
459 d->sdmr2 = v;
460 debug("[ sh4: sdmr%i set to 0x%04"PRIx16" ]\n",
461 relative_addr & 0x00040000? 3 : 2, v);
462 return 1;
463 }
464
465
466 switch (relative_addr) {
467
468 /*************************************************/
469
470 case SH4_PVR_ADDR:
471 odata = cpu->cd.sh.cpu_type.pvr;
472 break;
473
474 case SH4_PRR_ADDR:
475 odata = cpu->cd.sh.cpu_type.prr;
476 break;
477
478 case SH4_PTEH:
479 if (writeflag == MEM_READ)
480 odata = cpu->cd.sh.pteh;
481 else {
482 int old_asid = cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK;
483 cpu->cd.sh.pteh = idata;
484
485 if ((idata & SH4_PTEH_ASID_MASK) != old_asid) {
486 /*
487 * TODO: Don't invalidate everything,
488 * only those pages that belonged to the
489 * old asid.
490 */
491 cpu->invalidate_translation_caches(
492 cpu, 0, INVALIDATE_ALL);
493 }
494 }
495 break;
496
497 case SH4_PTEL:
498 if (writeflag == MEM_READ)
499 odata = cpu->cd.sh.ptel;
500 else
501 cpu->cd.sh.ptel = idata;
502 break;
503
504 case SH4_TTB:
505 if (writeflag == MEM_READ)
506 odata = cpu->cd.sh.ttb;
507 else
508 cpu->cd.sh.ttb = idata;
509 break;
510
511 case SH4_TEA:
512 if (writeflag == MEM_READ)
513 odata = cpu->cd.sh.tea;
514 else
515 cpu->cd.sh.tea = idata;
516 break;
517
518 case SH4_PTEA:
519 if (writeflag == MEM_READ)
520 odata = cpu->cd.sh.ptea;
521 else
522 cpu->cd.sh.ptea = idata;
523 break;
524
525 case SH4_MMUCR:
526 if (writeflag == MEM_READ) {
527 odata = cpu->cd.sh.mmucr;
528 } else {
529 if (idata & SH4_MMUCR_TI) {
530 /* TLB invalidate. */
531 int i;
532 for (i = 0; i < SH_N_ITLB_ENTRIES; i++)
533 cpu->cd.sh.itlb_lo[i] &=
534 ~SH4_PTEL_V;
535
536 for (i = 0; i < SH_N_UTLB_ENTRIES; i++)
537 cpu->cd.sh.utlb_lo[i] &=
538 ~SH4_PTEL_V;
539
540 cpu->invalidate_translation_caches(cpu,
541 0, INVALIDATE_ALL);
542
543 /* Should always read back as 0. */
544 idata &= ~SH4_MMUCR_TI;
545 }
546
547 cpu->cd.sh.mmucr = idata;
548 }
549 break;
550
551 case SH4_CCR:
552 if (writeflag == MEM_READ) {
553 odata = cpu->cd.sh.ccr;
554 } else {
555 cpu->cd.sh.ccr = idata;
556 }
557 break;
558
559 case SH4_QACR0:
560 if (writeflag == MEM_READ) {
561 odata = cpu->cd.sh.qacr0;
562 } else {
563 cpu->cd.sh.qacr0 = idata;
564 }
565 break;
566
567 case SH4_QACR1:
568 if (writeflag == MEM_READ) {
569 odata = cpu->cd.sh.qacr1;
570 } else {
571 cpu->cd.sh.qacr1 = idata;
572 }
573 break;
574
575 case SH4_TRA:
576 if (writeflag == MEM_READ)
577 odata = cpu->cd.sh.tra;
578 else
579 cpu->cd.sh.tra = idata;
580 break;
581
582 case SH4_EXPEVT:
583 if (writeflag == MEM_READ)
584 odata = cpu->cd.sh.expevt;
585 else
586 cpu->cd.sh.expevt = idata;
587 break;
588
589 case SH4_INTEVT:
590 if (writeflag == MEM_READ)
591 odata = cpu->cd.sh.intevt;
592 else
593 cpu->cd.sh.intevt = idata;
594 break;
595
596
597 /********************************/
598 /* UBC: User Break Controller */
599
600 case 0xff200008: /* SH4_BBRA */
601 /* TODO */
602 break;
603
604
605 /********************************/
606 /* TMU: Timer Management Unit */
607
608 case SH4_TOCR:
609 /* Timer Output Control Register */
610 if (writeflag == MEM_WRITE) {
611 d->tocr = idata;
612 if (idata & TOCR_TCOE)
613 fatal("[ sh4 timer: TCOE not yet "
614 "implemented ]\n");
615 } else {
616 odata = d->tocr;
617 }
618 break;
619
620 case SH4_TSTR:
621 /* Timer Start Register */
622 if (writeflag == MEM_READ) {
623 odata = d->tstr;
624 } else {
625 if (idata & 1 && !(d->tstr & 1))
626 debug("[ sh4 timer: starting timer 0 ]\n");
627 if (idata & 2 && !(d->tstr & 2))
628 debug("[ sh4 timer: starting timer 1 ]\n");
629 if (idata & 4 && !(d->tstr & 4))
630 debug("[ sh4 timer: starting timer 2 ]\n");
631 if (!(idata & 1) && d->tstr & 1)
632 debug("[ sh4 timer: stopping timer 0 ]\n");
633 if (!(idata & 2) && d->tstr & 2)
634 debug("[ sh4 timer: stopping timer 1 ]\n");
635 if (!(idata & 4) && d->tstr & 4)
636 debug("[ sh4 timer: stopping timer 2 ]\n");
637 d->tstr = idata;
638 }
639 break;
640
641 case SH4_TCOR2:
642 timer_nr ++;
643 case SH4_TCOR1:
644 timer_nr ++;
645 case SH4_TCOR0:
646 /* Timer Constant Register */
647 if (writeflag == MEM_READ)
648 odata = d->tcor[timer_nr];
649 else
650 d->tcor[timer_nr] = idata;
651 break;
652
653 case SH4_TCNT2:
654 timer_nr ++;
655 case SH4_TCNT1:
656 timer_nr ++;
657 case SH4_TCNT0:
658 /* Timer Counter Register */
659 if (writeflag == MEM_READ)
660 odata = d->tcnt[timer_nr];
661 else
662 d->tcnt[timer_nr] = idata;
663 break;
664
665 case SH4_TCR2:
666 timer_nr ++;
667 case SH4_TCR1:
668 timer_nr ++;
669 case SH4_TCR0:
670 /* Timer Control Register */
671 if (writeflag == MEM_READ) {
672 odata = d->tcr[timer_nr];
673 } else {
674 if (cpu->cd.sh.pclock == 0) {
675 fatal("INTERNAL ERROR: pclock must be set"
676 " for this machine. Aborting.\n");
677 exit(1);
678 }
679
680 switch (idata & 3) {
681 case TCR_TPSC_P4:
682 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/4.0;
683 break;
684 case TCR_TPSC_P16:
685 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/16.0;
686 break;
687 case TCR_TPSC_P64:
688 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/64.0;
689 break;
690 case TCR_TPSC_P256:
691 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/256.0;
692 break;
693 }
694
695 debug("[ sh4 timer %i clock set to %f Hz ]\n",
696 timer_nr, d->timer_hz[timer_nr]);
697
698 if (idata & (TCR_ICPF | TCR_ICPE1 | TCR_ICPE0 |
699 TCR_CKEG1 | TCR_CKEG0 | TCR_TPSC2)) {
700 fatal("Unimplemented SH4 timer control"
701 " bits: 0x%08"PRIx32". Aborting.\n",
702 (int) idata);
703 exit(1);
704 }
705
706 if (d->tcr[timer_nr] & TCR_UNF && !(idata & TCR_UNF)) {
707 INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
708 if (d->timer_interrupts_pending[timer_nr] > 0)
709 d->timer_interrupts_pending[timer_nr]--;
710 }
711
712 d->tcr[timer_nr] = idata;
713 }
714 break;
715
716
717 /*************************************************/
718 /* DMAC: DMA Controller */
719
720 case SH4_SAR3:
721 dma_channel ++;
722 case SH4_SAR2:
723 dma_channel ++;
724 case SH4_SAR1:
725 dma_channel ++;
726 case SH4_SAR0:
727 dma_channel ++;
728 if (writeflag == MEM_READ)
729 odata = cpu->cd.sh.dmac_sar[dma_channel];
730 else
731 cpu->cd.sh.dmac_sar[dma_channel] = idata;
732 break;
733
734 case SH4_DAR3:
735 dma_channel ++;
736 case SH4_DAR2:
737 dma_channel ++;
738 case SH4_DAR1:
739 dma_channel ++;
740 case SH4_DAR0:
741 dma_channel ++;
742 if (writeflag == MEM_READ)
743 odata = cpu->cd.sh.dmac_dar[dma_channel];
744 else
745 cpu->cd.sh.dmac_dar[dma_channel] = idata;
746 break;
747
748 case SH4_DMATCR3:
749 dma_channel ++;
750 case SH4_DMATCR2:
751 dma_channel ++;
752 case SH4_DMATCR1:
753 dma_channel ++;
754 case SH4_DMATCR0:
755 dma_channel ++;
756 if (writeflag == MEM_READ)
757 odata = cpu->cd.sh.dmac_tcr[dma_channel] & 0x00ffffff;
758 else {
759 if (idata & ~0x00ffffff) {
760 fatal("[ SH4 DMA: Attempt to set top 8 "
761 "bits of the count register? 0x%08"
762 PRIx32" ]\n", (uint32_t) idata);
763 exit(1);
764 }
765
766 /* Special case: writing 0 to the count register
767 means 16777216: */
768 if (idata == 0)
769 idata = 0x01000000;
770 cpu->cd.sh.dmac_tcr[dma_channel] = idata;
771 }
772 break;
773
774 case SH4_CHCR3:
775 dma_channel ++;
776 case SH4_CHCR2:
777 dma_channel ++;
778 case SH4_CHCR1:
779 dma_channel ++;
780 case SH4_CHCR0:
781 dma_channel ++;
782 if (writeflag == MEM_READ)
783 odata = cpu->cd.sh.dmac_chcr[dma_channel];
784 else {
785 /* IP.BIN sets this to 0x12c0, and I want to know if
786 some other guest OS uses other values. */
787 if (idata != 0x12c0) {
788 fatal("[ SH4 DMA: Attempt to set chcr "
789 "to 0x%08"PRIx32" ]\n", (uint32_t) idata);
790 exit(1);
791 }
792
793 cpu->cd.sh.dmac_chcr[dma_channel] = idata;
794 }
795 break;
796
797
798 /*************************************************/
799 /* BSC: Bus State Controller */
800
801 case SH4_BCR1:
802 if (writeflag == MEM_WRITE)
803 d->bsc_bcr1 = idata & 0x033efffd;
804 else {
805 odata = d->bsc_bcr1;
806 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
807 odata |= BCR1_LITTLE_ENDIAN;
808 }
809 break;
810
811 case SH4_BCR2:
812 if (len != sizeof(uint16_t)) {
813 fatal("Non-16-bit SH4_BCR2 access?\n");
814 exit(1);
815 }
816 if (writeflag == MEM_WRITE)
817 d->bsc_bcr2 = idata & 0x3ffd;
818 else
819 odata = d->bsc_bcr2;
820 break;
821
822 case SH4_WCR1:
823 if (writeflag == MEM_WRITE)
824 d->bsc_wcr1 = idata & 0x77777777;
825 else
826 odata = d->bsc_wcr1;
827 break;
828
829 case SH4_WCR2:
830 if (writeflag == MEM_WRITE)
831 d->bsc_wcr2 = idata & 0xfffeefff;
832 else
833 odata = d->bsc_wcr2;
834 break;
835
836 case SH4_MCR:
837 if (writeflag == MEM_WRITE)
838 d->bsc_mcr = idata & 0xf8bbffff;
839 else
840 odata = d->bsc_mcr;
841 break;
842
843 case SH4_RTCSR:
844 /*
845 * Refresh Time Control/Status Register. Called RTCSR in
846 * NetBSD, but RTSCR in the SH7750 manual?
847 */
848 if (writeflag == MEM_WRITE) {
849 idata &= 0x00ff;
850 if (idata & RTCSR_CMF) {
851 idata = (idata & ~RTCSR_CMF)
852 | (d->bsc_rtcsr & RTCSR_CMF);
853 }
854 d->bsc_rtcsr = idata & 0x00ff;
855 } else
856 odata = d->bsc_rtcsr;
857 break;
858
859 case SH4_RTCOR:
860 /* Refresh Time Constant Register (8 bits): */
861 if (writeflag == MEM_WRITE)
862 d->bsc_rtcor = idata & 0x00ff;
863 else
864 odata = d->bsc_rtcor & 0x00ff;
865 break;
866
867 case SH4_RFCR:
868 /* Refresh Count Register (10 bits): */
869 if (writeflag == MEM_WRITE)
870 d->bsc_rfcr = idata & 0x03ff;
871 else
872 odata = d->bsc_rfcr & 0x03ff;
873 break;
874
875
876 /*******************************************/
877 /* GPIO: General-purpose I/O controller */
878
879 case SH4_PCTRA:
880 if (writeflag == MEM_WRITE)
881 d->pctra = idata;
882 else
883 odata = d->pctra;
884 break;
885
886 case SH4_PDTRA:
887 if (writeflag == MEM_WRITE) {
888 debug("[ sh4: pdtra: write: TODO ]\n");
889 d->pdtra = idata;
890 } else {
891 debug("[ sh4: pdtra: read: TODO ]\n");
892 odata = d->pdtra;
893 }
894 break;
895
896 case SH4_PCTRB:
897 if (writeflag == MEM_WRITE)
898 d->pctrb = idata;
899 else
900 odata = d->pctrb;
901 break;
902
903 case SH4_PDTRB:
904 if (writeflag == MEM_WRITE) {
905 debug("[ sh4: pdtrb: write: TODO ]\n");
906 d->pdtrb = idata;
907 } else {
908 debug("[ sh4: pdtrb: read: TODO ]\n");
909 odata = d->pdtrb;
910 }
911 break;
912
913
914 /*********************************/
915 /* INTC: Interrupt Controller */
916
917 case SH4_ICR:
918 if (writeflag == MEM_WRITE) {
919 if (idata & 0x80) {
920 fatal("SH4 INTC: IRLM not yet "
921 "supported. TODO\n");
922 exit(1);
923 }
924 }
925 break;
926
927 case SH4_IPRA:
928 if (writeflag == MEM_READ)
929 odata = cpu->cd.sh.intc_ipra;
930 else
931 cpu->cd.sh.intc_ipra = idata;
932 break;
933
934 case SH4_IPRB:
935 if (writeflag == MEM_READ)
936 odata = cpu->cd.sh.intc_iprb;
937 else
938 cpu->cd.sh.intc_iprb = idata;
939 break;
940
941 case SH4_IPRC:
942 if (writeflag == MEM_READ)
943 odata = cpu->cd.sh.intc_iprc;
944 else
945 cpu->cd.sh.intc_iprc = idata;
946 break;
947
948 case SH4_IPRD:
949 if (writeflag == MEM_READ)
950 odata = cpu->cd.sh.intc_iprd;
951 else
952 cpu->cd.sh.intc_iprd = idata;
953 break;
954
955
956 /*************************************************/
957 /* SCIF: Serial Controller Interface with FIFO */
958
959 case SH4_SCIF_BASE + SCIF_SMR:
960 if (writeflag == MEM_WRITE) {
961 d->scif_smr = idata;
962 } else {
963 odata = d->scif_smr;
964 }
965 break;
966
967 case SH4_SCIF_BASE + SCIF_BRR:
968 if (writeflag == MEM_WRITE) {
969 d->scif_brr = idata;
970 } else {
971 odata = d->scif_brr;
972 }
973 break;
974
975 case SH4_SCIF_BASE + SCIF_SCR:
976 if (writeflag == MEM_WRITE) {
977 d->scif_scr = idata;
978 } else {
979 odata = d->scif_scr;
980 }
981 break;
982
983 case SH4_SCIF_BASE + SCIF_FTDR:
984 if (writeflag == MEM_WRITE)
985 console_putchar(d->scif_console_handle, idata);
986 break;
987
988 case SH4_SCIF_BASE + SCIF_SSR:
989 /* TODO: Implement more of this. */
990 odata = SCSSR2_TDFE | SCSSR2_TEND;
991 if (console_charavail(d->scif_console_handle))
992 odata |= SCSSR2_DR;
993 break;
994
995 case SH4_SCIF_BASE + SCIF_FRDR:
996 {
997 int x = console_readchar(d->scif_console_handle);
998 if (x == 13)
999 x = 10;
1000 odata = x < 0? 0 : x;
1001 }
1002 break;
1003
1004 case SH4_SCIF_BASE + SCIF_FCR:
1005 if (writeflag == MEM_WRITE) {
1006 d->scif_fcr = idata;
1007 } else {
1008 odata = d->scif_fcr;
1009 }
1010 break;
1011
1012 case SH4_SCIF_BASE + SCIF_FDR:
1013 odata = console_charavail(d->scif_console_handle);
1014 break;
1015
1016
1017 /*************************************************/
1018
1019 case SH4_RSECCNT:
1020 case SH4_RMINCNT:
1021 case SH4_RHRCNT:
1022 case SH4_RWKCNT:
1023 case SH4_RDAYCNT:
1024 case SH4_RMONCNT:
1025 case SH4_RYRCNT:
1026 case SH4_RSECAR:
1027 case SH4_RMINAR:
1028 case SH4_RHRAR:
1029 case SH4_RWKAR:
1030 case SH4_RDAYAR:
1031 case SH4_RMONAR:
1032 if (writeflag == MEM_WRITE) {
1033 d->rtc_reg[(relative_addr - 0xffc80000) / 4] = idata;
1034 } else {
1035 /* TODO: Update rtc_reg based on host's date/time. */
1036 odata = d->rtc_reg[(relative_addr - 0xffc80000) / 4];
1037 }
1038 break;
1039
1040 case SH4_RCR1:
1041 if (writeflag == MEM_READ)
1042 odata = d->rtc_rcr1;
1043 else {
1044 d->rtc_rcr1 = idata;
1045 if (idata & 0x18) {
1046 fatal("SH4: TODO: RTC interrupt enable\n");
1047 exit(1);
1048 }
1049 }
1050 break;
1051
1052
1053 /*************************************************/
1054
1055 default:if (writeflag == MEM_READ) {
1056 fatal("[ sh4: read from addr 0x%x ]\n",
1057 (int)relative_addr);
1058 } else {
1059 fatal("[ sh4: write to addr 0x%x: 0x%x ]\n",
1060 (int)relative_addr, (int)idata);
1061 }
1062 #ifdef SH4_DEGUG
1063 // exit(1);
1064 #endif
1065 }
1066
1067 if (writeflag == MEM_READ)
1068 memory_writemax64(cpu, data, len, odata);
1069
1070 return 1;
1071 }
1072
1073
1074 DEVINIT(sh4)
1075 {
1076 char tmp[200];
1077 struct machine *machine = devinit->machine;
1078 struct sh4_data *d = malloc(sizeof(struct sh4_data));
1079 if (d == NULL) {
1080 fprintf(stderr, "out of memory\n");
1081 exit(1);
1082 }
1083 memset(d, 0, sizeof(struct sh4_data));
1084
1085 d->scif_console_handle = console_start_slave(devinit->machine,
1086 "SH4 SCIF", 1);
1087
1088 memory_device_register(machine->memory, devinit->name,
1089 SH4_REG_BASE, 0x01000000, dev_sh4_access, d, DM_DEFAULT, NULL);
1090
1091 /* On-chip RAM/cache: */
1092 dev_ram_init(machine, 0x1e000000, 0x8000, DEV_RAM_RAM, 0x0);
1093
1094 /* 0xe0000000: Store queues: */
1095 dev_ram_init(machine, 0xe0000000, 32 * 2, DEV_RAM_RAM, 0x0);
1096
1097 /*
1098 * 0xf0000000 SH4_CCIA I-Cache address array
1099 * 0xf1000000 SH4_CCID I-Cache data array
1100 * 0xf4000000 SH4_CCDA D-Cache address array
1101 * 0xf5000000 SH4_CCDD D-Cache data array
1102 *
1103 * TODO: Implement more correct cache behaviour?
1104 */
1105 dev_ram_init(machine, SH4_CCIA, SH4_ICACHE_SIZE, DEV_RAM_RAM, 0x0);
1106 dev_ram_init(machine, SH4_CCID, SH4_ICACHE_SIZE, DEV_RAM_RAM, 0x0);
1107 dev_ram_init(machine, SH4_CCDA, SH4_DCACHE_SIZE, DEV_RAM_RAM, 0x0);
1108 dev_ram_init(machine, SH4_CCDD, SH4_DCACHE_SIZE, DEV_RAM_RAM, 0x0);
1109
1110 /* 0xf2000000 SH4_ITLB_AA */
1111 memory_device_register(machine->memory, devinit->name, SH4_ITLB_AA,
1112 0x01000000, dev_sh4_itlb_aa_access, d, DM_DEFAULT, NULL);
1113
1114 /* 0xf3000000 SH4_ITLB_DA1 */
1115 memory_device_register(machine->memory, devinit->name, SH4_ITLB_DA1,
1116 0x01000000, dev_sh4_itlb_da1_access, d, DM_DEFAULT, NULL);
1117
1118 /* 0xf6000000 SH4_UTLB_AA */
1119 memory_device_register(machine->memory, devinit->name, SH4_UTLB_AA,
1120 0x01000000, dev_sh4_utlb_aa_access, d, DM_DEFAULT, NULL);
1121
1122 /* 0xf7000000 SH4_UTLB_DA1 */
1123 memory_device_register(machine->memory, devinit->name, SH4_UTLB_DA1,
1124 0x01000000, dev_sh4_utlb_da1_access, d, DM_DEFAULT, NULL);
1125
1126 d->sh4_timer = timer_add(SH4_PSEUDO_TIMER_HZ, sh4_timer_tick, d);
1127 machine_add_tickfunction(devinit->machine, dev_sh4_tick, d,
1128 SH4_TICK_SHIFT, 0.0);
1129
1130 /* Initial Timer values, according to the SH7750 manual: */
1131 d->tcor[0] = 0xffffffff; d->tcnt[0] = 0xffffffff;
1132 d->tcor[1] = 0xffffffff; d->tcnt[1] = 0xffffffff;
1133 d->tcor[2] = 0xffffffff; d->tcnt[2] = 0xffffffff;
1134
1135 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1136 SH_INTEVT_TMU0_TUNI0);
1137 if (!interrupt_handler_lookup(tmp, &d->timer_irq[0])) {
1138 fatal("Could not find interrupt '%s'.\n", tmp);
1139 exit(1);
1140 }
1141 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1142 SH_INTEVT_TMU1_TUNI1);
1143 if (!interrupt_handler_lookup(tmp, &d->timer_irq[1])) {
1144 fatal("Could not find interrupt '%s'.\n", tmp);
1145 exit(1);
1146 }
1147 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1148 SH_INTEVT_TMU2_TUNI2);
1149 if (!interrupt_handler_lookup(tmp, &d->timer_irq[2])) {
1150 fatal("Could not find interrupt '%s'.\n", tmp);
1151 exit(1);
1152 }
1153
1154 /* Bus State Controller initial values: */
1155 d->bsc_bcr2 = 0x3ffc;
1156 d->bsc_wcr1 = 0x77777777;
1157 d->bsc_wcr2 = 0xfffeefff;
1158
1159 return 1;
1160 }
1161

  ViewVC Help
Powered by ViewVC 1.1.26