/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (hide 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 dpavlin 32 /*
2 dpavlin 34 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 dpavlin 32 *
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 dpavlin 34 * $Id: dev_sh4.c,v 1.29 2007/01/29 18:06:37 debug Exp $
29 dpavlin 32 *
30     * SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).
31 dpavlin 34 *
32     * TODO: Lots and lots of stuff.
33 dpavlin 32 */
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 dpavlin 34 #include "interrupt.h"
44 dpavlin 32 #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 dpavlin 34 #include "sh4_dmacreg.h"
52 dpavlin 32 #include "sh4_exception.h"
53     #include "sh4_intcreg.h"
54     #include "sh4_mmu.h"
55 dpavlin 34 #include "sh4_rtcreg.h"
56 dpavlin 32 #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 dpavlin 34 /* 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 dpavlin 32 /* #define debug fatal */
74 dpavlin 34 #endif
75 dpavlin 32
76     struct sh4_data {
77 dpavlin 34 /* SCIF (Serial controller): */
78     uint16_t scif_smr;
79     uint8_t scif_brr;
80     uint16_t scif_scr;
81     uint16_t scif_fcr;
82 dpavlin 32 int scif_console_handle;
83    
84     /* Bus State Controller: */
85 dpavlin 34 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 dpavlin 32
94 dpavlin 34 /* 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 dpavlin 32 /* Timer Management Unit: */
105     struct timer *sh4_timer;
106 dpavlin 34 struct interrupt timer_irq[4];
107 dpavlin 32 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 dpavlin 34
115     /* RTC: */
116     uint32_t rtc_reg[14]; /* Excluding rcr1 and 2 */
117     uint8_t rtc_rcr1;
118 dpavlin 32 };
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 dpavlin 34 *
131     * Also, RAM Refresh is also faked here.
132 dpavlin 32 */
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 dpavlin 34 /* 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 dpavlin 32 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 dpavlin 34 INTERRUPT_ASSERT(d->timer_irq[i]);
190 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 34 uint32_t old_lo = cpu->cd.sh.itlb_lo[e];
253 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 34 cpu->invalidate_translation_caches(cpu, 0,
382     INVALIDATE_ALL);
383 dpavlin 32 } 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 dpavlin 34 uint32_t old_lo = cpu->cd.sh.utlb_lo[e];
411 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 34 int timer_nr = 0, dma_channel = 0;
446 dpavlin 32
447     if (writeflag == MEM_WRITE)
448     idata = memory_readmax64(cpu, data, len);
449    
450     relative_addr += SH4_REG_BASE;
451    
452 dpavlin 34 /* 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 dpavlin 32 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 dpavlin 34 /*
487     * TODO: Don't invalidate everything,
488     * only those pages that belonged to the
489     * old asid.
490     */
491 dpavlin 32 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 dpavlin 34 int i;
532     for (i = 0; i < SH_N_ITLB_ENTRIES; i++)
533     cpu->cd.sh.itlb_lo[i] &=
534     ~SH4_PTEL_V;
535 dpavlin 32
536 dpavlin 34 for (i = 0; i < SH_N_UTLB_ENTRIES; i++)
537     cpu->cd.sh.utlb_lo[i] &=
538     ~SH4_PTEL_V;
539    
540 dpavlin 32 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 dpavlin 34 INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
708 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 /* BSC: Bus State Controller */
800    
801 dpavlin 34 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 dpavlin 32 break;
810    
811 dpavlin 34 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 dpavlin 32 /*
845 dpavlin 34 * Refresh Time Control/Status Register. Called RTCSR in
846     * NetBSD, but RTSCR in the SH7750 manual?
847 dpavlin 32 */
848     if (writeflag == MEM_WRITE) {
849 dpavlin 34 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 dpavlin 32 } else
856 dpavlin 34 odata = d->bsc_rtcsr;
857 dpavlin 32 break;
858    
859 dpavlin 34 case SH4_RTCOR:
860     /* Refresh Time Constant Register (8 bits): */
861 dpavlin 32 if (writeflag == MEM_WRITE)
862 dpavlin 34 d->bsc_rtcor = idata & 0x00ff;
863     else
864     odata = d->bsc_rtcor & 0x00ff;
865     break;
866 dpavlin 32
867 dpavlin 34 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 dpavlin 32 }
894     break;
895    
896 dpavlin 34 case SH4_PCTRB:
897     if (writeflag == MEM_WRITE)
898     d->pctrb = idata;
899     else
900     odata = d->pctrb;
901     break;
902 dpavlin 32
903 dpavlin 34 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 dpavlin 32 /*********************************/
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 dpavlin 34 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 dpavlin 32
955 dpavlin 34
956 dpavlin 32 /*************************************************/
957     /* SCIF: Serial Controller Interface with FIFO */
958    
959 dpavlin 34 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 dpavlin 32 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 dpavlin 34 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 dpavlin 32 case SH4_SCIF_BASE + SCIF_FDR:
1013     odata = console_charavail(d->scif_console_handle);
1014     break;
1015    
1016 dpavlin 34
1017 dpavlin 32 /*************************************************/
1018    
1019 dpavlin 34 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 dpavlin 32 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 dpavlin 34 #ifdef SH4_DEGUG
1063     // exit(1);
1064     #endif
1065 dpavlin 32 }
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 dpavlin 34 char tmp[200];
1077 dpavlin 32 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 dpavlin 34 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 dpavlin 32 return 1;
1160     }
1161    

  ViewVC Help
Powered by ViewVC 1.1.26