/[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 36 - (show annotations)
Mon Oct 8 16:21:34 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 29218 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1497 2007/03/18 03:41:36 debug Exp $
20070224	Minor update to the initialization of the ns16550 in
		machine_walnut.c, to allow that machine type to boot with the
		new interrupt system (although it is still a dummy machine).
		Adding a wdc at 0x14000000 to machine_landisk.c, and fixing
		the SCIF serial interrupts of the SH4 cpu enough to get
		NetBSD/landisk booting from a disk image :-)  Adding a
		preliminary install instruction skeleton to guestoses.html.
20070306	Adding SH-IPL+G PROM emulation, and also passing the "end"
		symbol in r5 on bootup, for Landisk emulation. This is enough
		to get OpenBSD/landisk to install :)  Adding a preliminary
		install instruction skeleton to the documentation. SuperH
		emulation is still shaky, though :-/
20070307	Fixed a strangeness in memory_sh.c (read/write was never
		returned for any page). (Unknown whether this fixes any actual
		problems, though.)
20070308	dev_ram.c fix: invalidate code translations on writes to
		RAM, emulated as separate devices. Linux/dreamcast gets
		further in the boot process than before, but still bugs out
		in userland.
		Fixing bugs in the "stc.l gbr,@-rN" and "ldc.l @rN+,gbr" SuperH 
		instructions (they should NOT check the MD bit), allowing the
		Linux/dreamcast Live CD to reach userland correctly :-)
20070310	Changing the cpu name "Alpha" in src/useremul.c to "21364" to
		unbreak userland syscall emulation of FreeBSD/Alpha binaries.
20070314	Applying a patch from Michael Yaroslavtsev which fixes the
		previous Linux lib64 patch to the configure script.
20070315	Adding a (dummy) sun4v machine type, and SPARC T1 cpu type.
20070316	Creating a new directory, src/disk, and moving diskimage.c
		to it. Separating out bootblock loading stuff from emul.c into
		new files in src/disk.
		Adding some more SPARC registers.
20070318	Preparing/testing for a minirelease, 0.4.4.1.

==============  RELEASE 0.4.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26