/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 35680 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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.39 2007/04/13 16:12:39 debug Exp $
29 *
30 * SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).
31 *
32 * TODO: Among other things:
33 *
34 * x) Interrupt masks (msk register stuff).
35 * x) BSC (Bus state controller).
36 * x) DMA
37 * x) UBC
38 * x) ...
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "console.h"
46 #include "cpu.h"
47 #include "device.h"
48 #include "devices.h"
49 #include "interrupt.h"
50 #include "machine.h"
51 #include "memory.h"
52 #include "misc.h"
53 #include "timer.h"
54
55 #include "sh4_bscreg.h"
56 #include "sh4_cache.h"
57 #include "sh4_dmacreg.h"
58 #include "sh4_exception.h"
59 #include "sh4_intcreg.h"
60 #include "sh4_mmu.h"
61 #include "sh4_rtcreg.h"
62 #include "sh4_scifreg.h"
63 #include "sh4_scireg.h"
64 #include "sh4_tmureg.h"
65
66
67 #define SH4_REG_BASE 0xff000000
68 #define SH4_TICK_SHIFT 14
69 #define N_SH4_TIMERS 3
70
71 #define SCIF_TX_FIFO_SIZE 16
72
73 /* General-purpose I/O stuff: */
74 #define SH4_PCTRA 0xff80002c
75 #define SH4_PDTRA 0xff800030
76 #define SH4_PCTRB 0xff800040
77 #define SH4_PDTRB 0xff800044
78 #define SH4_GPIOIC 0xff800048
79
80 #ifdef UNSTABLE_DEVEL
81 #define SH4_DEGUG
82 /* #define debug fatal */
83 #endif
84
85 struct sh4_data {
86 /* SCIF (Serial controller): */
87 uint16_t scif_smr;
88 uint8_t scif_brr;
89 uint16_t scif_scr;
90 uint16_t scif_ssr;
91 uint16_t scif_fcr;
92 uint16_t scif_lsr;
93 int scif_delayed_tx;
94 int scif_console_handle;
95 uint8_t scif_tx_fifo[SCIF_TX_FIFO_SIZE + 1];
96 int scif_tx_fifo_cursize;
97 struct interrupt scif_tx_irq;
98 struct interrupt scif_rx_irq;
99 int scif_tx_irq_asserted;
100 int scif_rx_irq_asserted;
101
102 /* Bus State Controller: */
103 uint32_t bsc_bcr1;
104 uint16_t bsc_bcr2;
105 uint32_t bsc_wcr1;
106 uint32_t bsc_wcr2;
107 uint32_t bsc_mcr;
108 uint16_t bsc_rtcsr;
109 uint16_t bsc_rtcor;
110 uint16_t bsc_rfcr;
111
112 /* GPIO: */
113 uint32_t pctra; /* Port Control Register A */
114 uint32_t pdtra; /* Port Data Register A */
115 uint32_t pctrb; /* Port Control Register B */
116 uint32_t pdtrb; /* Port Data Register B */
117
118 /* SCI (serial interface): */
119 int sci_bits_outputed;
120 int sci_bits_read;
121 uint8_t sci_scsptr;
122 uint8_t sci_curbyte;
123 uint8_t sci_cur_addr;
124
125 /* SD-RAM: */
126 uint16_t sdmr2;
127 uint16_t sdmr3;
128
129 /* Timer Management Unit: */
130 struct timer *sh4_timer;
131 struct interrupt timer_irq[4];
132 uint32_t tocr;
133 uint32_t tstr;
134 uint32_t tcnt[N_SH4_TIMERS];
135 uint32_t tcor[N_SH4_TIMERS];
136 uint32_t tcr[N_SH4_TIMERS];
137 int timer_interrupts_pending[N_SH4_TIMERS];
138 double timer_hz[N_SH4_TIMERS];
139
140 /* RTC: */
141 uint32_t rtc_reg[14]; /* Excluding rcr1 and 2 */
142 uint8_t rtc_rcr1;
143 };
144
145
146 #define SH4_PSEUDO_TIMER_HZ 110.0
147
148
149 /*
150 * sh4_timer_tick():
151 *
152 * This function is called SH4_PSEUDO_TIMER_HZ times per real-world second.
153 * Its job is to update the SH4 timer counters, and if necessary, increase
154 * the number of pending interrupts.
155 *
156 * Also, RAM Refresh is also faked here.
157 */
158 static void sh4_timer_tick(struct timer *t, void *extra)
159 {
160 struct sh4_data *d = (struct sh4_data *) extra;
161 int i;
162
163 /* Fake RAM refresh: */
164 d->bsc_rfcr ++;
165 if (d->bsc_rtcsr & (RTCSR_CMIE | RTCSR_OVIE)) {
166 fatal("sh4: RTCSR_CMIE | RTCSR_OVIE: TODO\n");
167 /* TODO: Implement refresh interrupts etc. */
168 exit(1);
169 }
170
171 /* Timer interrupts: */
172 for (i=0; i<N_SH4_TIMERS; i++) {
173 int32_t old = d->tcnt[i];
174
175 /* printf("tcnt[%i] = %08x tcor[%i] = %08x\n",
176 i, d->tcnt[i], i, d->tcor[i]); */
177
178 /* Only update timers that are currently started: */
179 if (!(d->tstr & (TSTR_STR0 << i)))
180 continue;
181
182 /* Update the current count: */
183 d->tcnt[i] -= d->timer_hz[i] / SH4_PSEUDO_TIMER_HZ;
184
185 /* Has the timer underflowed? */
186 if ((int32_t)d->tcnt[i] < 0 && old >= 0) {
187 d->tcr[i] |= TCR_UNF;
188
189 if (d->tcr[i] & TCR_UNIE)
190 d->timer_interrupts_pending[i] ++;
191
192 /*
193 * Set tcnt[i] to tcor[i]. Note: Since this function
194 * is only called now and then, adding tcor[i] to
195 * tcnt[i] produces more correct values for long
196 * running timers.
197 */
198 d->tcnt[i] += d->tcor[i];
199
200 /* At least make sure that tcnt is non-negative... */
201 if ((int32_t)d->tcnt[i] < 0)
202 d->tcnt[i] = 0;
203 }
204 }
205 }
206
207
208 static void scif_reassert_interrupts(struct sh4_data *d)
209 {
210 int old_tx_asserted = d->scif_tx_irq_asserted;
211 int old_rx_asserted = d->scif_rx_irq_asserted;
212
213 d->scif_rx_irq_asserted =
214 d->scif_scr & SCSCR2_RIE && d->scif_ssr & SCSSR2_DR;
215
216 if (d->scif_rx_irq_asserted && !old_rx_asserted)
217 INTERRUPT_ASSERT(d->scif_rx_irq);
218 else if (!d->scif_rx_irq_asserted && old_rx_asserted)
219 INTERRUPT_DEASSERT(d->scif_rx_irq);
220
221 d->scif_tx_irq_asserted =
222 d->scif_scr & SCSCR2_TIE &&
223 d->scif_ssr & (SCSSR2_TDFE | SCSSR2_TEND);
224
225 if (d->scif_tx_irq_asserted && !old_tx_asserted)
226 INTERRUPT_ASSERT(d->scif_tx_irq);
227 else if (!d->scif_tx_irq_asserted && old_tx_asserted)
228 INTERRUPT_DEASSERT(d->scif_tx_irq);
229 }
230
231
232 DEVICE_TICK(sh4)
233 {
234 struct sh4_data *d = (struct sh4_data *) extra;
235 int i;
236
237 /*
238 * Serial controller interrupts:
239 *
240 * RX: Cause interrupt if any char is available.
241 * TX: Send entire TX FIFO contents, and interrupt.
242 */
243 if (console_charavail(d->scif_console_handle))
244 d->scif_ssr |= SCSSR2_DR;
245 else
246 d->scif_ssr &= ~SCSSR2_DR;
247
248 if (d->scif_delayed_tx) {
249 if (--d->scif_delayed_tx == 0) {
250 /* Send TX FIFO contents: */
251 for (i=0; i<d->scif_tx_fifo_cursize; i++)
252 console_putchar(d->scif_console_handle,
253 d->scif_tx_fifo[i]);
254
255 /* Clear FIFO: */
256 d->scif_tx_fifo_cursize = 0;
257
258 /* Done sending; cause a transmit end interrupt: */
259 d->scif_ssr |= SCSSR2_TDFE | SCSSR2_TEND;
260 }
261 }
262
263 scif_reassert_interrupts(d);
264
265 /* Timer interrupts: */
266 for (i=0; i<N_SH4_TIMERS; i++)
267 if (d->timer_interrupts_pending[i] > 0) {
268 INTERRUPT_ASSERT(d->timer_irq[i]);
269 d->tcr[i] |= TCR_UNF;
270 }
271 }
272
273
274 /*
275 * sh_sci_cmd():
276 *
277 * Handle a SCI command byte.
278 *
279 * Bit: Meaning:
280 * 7 Ignored (usually 1?)
281 * 6 0=Write, 1=Read
282 * 5 AD: Address transfer
283 * 4 DT: Data transfer
284 * 3..0 Data or address bits
285 */
286 static void sh_sci_cmd(struct sh4_data *d, struct cpu *cpu)
287 {
288 uint8_t cmd = d->sci_curbyte;
289 int writeflag = cmd & 0x40? 0 : 1;
290 int address_transfer;
291
292 /* fatal("[ CMD BYTE %02x ]\n", cmd); */
293
294 if (!(cmd & 0x80)) {
295 fatal("SCI cmd bit 7 not set? TODO\n");
296 exit(1);
297 }
298
299 if ((cmd & 0x30) == 0x20)
300 address_transfer = 1;
301 else if ((cmd & 0x30) == 0x10)
302 address_transfer = 0;
303 else {
304 fatal("SCI: Neither data nor address transfer? TODO\n");
305 exit(1);
306 }
307
308 if (address_transfer)
309 d->sci_cur_addr = cmd & 0x0f;
310
311 if (!writeflag) {
312 /* Read data from the current address: */
313 uint8_t data_byte;
314
315 cpu->memory_rw(cpu, cpu->mem, SCI_DEVICE_BASE + d->sci_cur_addr,
316 &data_byte, 1, MEM_READ, PHYSICAL);
317
318 debug("[ SCI: read addr=%x data=%x ]\n",
319 d->sci_cur_addr, data_byte);
320
321 d->sci_curbyte = data_byte;
322
323 /* Set bit 7 right away: */
324 d->sci_scsptr &= ~SCSPTR_SPB1DT;
325 if (data_byte & 0x80)
326 d->sci_scsptr |= SCSPTR_SPB1DT;
327 }
328
329 if (writeflag && !address_transfer) {
330 /* Write the 4 data bits to the current address: */
331 uint8_t data_byte = cmd & 0x0f;
332
333 debug("[ SCI: write addr=%x data=%x ]\n",
334 d->sci_cur_addr, data_byte);
335
336 cpu->memory_rw(cpu, cpu->mem, SCI_DEVICE_BASE + d->sci_cur_addr,
337 &data_byte, 1, MEM_WRITE, PHYSICAL);
338 }
339 }
340
341
342 /*
343 * sh_sci_access():
344 *
345 * Reads or writes a bit via the SH4's serial interface. If writeflag is
346 * non-zero, input is used. If writeflag is zero, a bit is outputed as
347 * the return value from this function.
348 */
349 static uint8_t sh_sci_access(struct sh4_data *d, struct cpu *cpu,
350 int writeflag, uint8_t input)
351 {
352 if (writeflag) {
353 /* WRITE: */
354 int clockpulse;
355 uint8_t old = d->sci_scsptr;
356 d->sci_scsptr = input;
357
358 /*
359 * Clock pulse (SCSPTR_SPB0DT going from 0 to 1,
360 * when SCSPTR_SPB0IO was already set):
361 */
362 clockpulse = old & SCSPTR_SPB0IO &&
363 d->sci_scsptr & SCSPTR_SPB0DT &&
364 !(old & SCSPTR_SPB0DT);
365
366 if (!clockpulse)
367 return 0;
368
369 /* Are we in output or input mode? */
370 if (d->sci_scsptr & SCSPTR_SPB1IO) {
371 /* Output: */
372 int bit = d->sci_scsptr & SCSPTR_SPB1DT? 1 : 0;
373 d->sci_curbyte <<= 1;
374 d->sci_curbyte |= bit;
375 d->sci_bits_outputed ++;
376 if (d->sci_bits_outputed == 8) {
377 /* 4 control bits and 4 address/data bits have
378 been written. */
379 sh_sci_cmd(d, cpu);
380 d->sci_bits_outputed = 0;
381 }
382 } else {
383 /* Input: */
384 int bit;
385 d->sci_bits_read ++;
386 d->sci_bits_read &= 7;
387
388 bit = d->sci_curbyte & (0x80 >> d->sci_bits_read);
389
390 d->sci_scsptr &= ~SCSPTR_SPB1DT;
391 if (bit)
392 d->sci_scsptr |= SCSPTR_SPB1DT;
393 }
394
395 /* Return (value doesn't matter). */
396 return 0;
397 } else {
398 /* READ: */
399 return d->sci_scsptr;
400 }
401 }
402
403
404 DEVICE_ACCESS(sh4_itlb_aa)
405 {
406 uint64_t idata = 0, odata = 0;
407 int e = (relative_addr & SH4_ITLB_E_MASK) >> SH4_ITLB_E_SHIFT;
408
409 if (writeflag == MEM_WRITE) {
410 int safe_to_invalidate = 0;
411 uint32_t old_hi = cpu->cd.sh.itlb_hi[e];
412 if ((cpu->cd.sh.itlb_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.itlb_hi[e] &=
417 ~(SH4_PTEH_VPN_MASK | SH4_PTEH_ASID_MASK);
418 cpu->cd.sh.itlb_hi[e] |= (idata &
419 (SH4_ITLB_AA_VPN_MASK | SH4_ITLB_AA_ASID_MASK));
420 cpu->cd.sh.itlb_lo[e] &= ~SH4_PTEL_V;
421 if (idata & SH4_ITLB_AA_V)
422 cpu->cd.sh.itlb_lo[e] |= SH4_PTEL_V;
423
424 /* Invalidate if this ITLB entry previously belonged to the
425 currently running process, or if it was shared: */
426 if (cpu->cd.sh.ptel & SH4_PTEL_SH ||
427 (old_hi & SH4_ITLB_AA_ASID_MASK) ==
428 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
429 if (safe_to_invalidate)
430 cpu->invalidate_translation_caches(cpu,
431 old_hi & ~0xfff, INVALIDATE_VADDR);
432 else
433 cpu->invalidate_translation_caches(cpu,
434 0, INVALIDATE_ALL);
435 }
436 } else {
437 odata = cpu->cd.sh.itlb_hi[e] &
438 (SH4_ITLB_AA_VPN_MASK | SH4_ITLB_AA_ASID_MASK);
439 if (cpu->cd.sh.itlb_lo[e] & SH4_PTEL_V)
440 odata |= SH4_ITLB_AA_V;
441 memory_writemax64(cpu, data, len, odata);
442 }
443
444 return 1;
445 }
446
447
448 DEVICE_ACCESS(sh4_itlb_da1)
449 {
450 uint32_t mask = SH4_PTEL_SH | SH4_PTEL_C | SH4_PTEL_SZ_MASK |
451 SH4_PTEL_PR_MASK | SH4_PTEL_V | 0x1ffffc00;
452 uint64_t idata = 0, odata = 0;
453 int e = (relative_addr & SH4_ITLB_E_MASK) >> SH4_ITLB_E_SHIFT;
454
455 if (relative_addr & 0x800000) {
456 fatal("sh4_itlb_da1: TODO: da2 area\n");
457 exit(1);
458 }
459
460 if (writeflag == MEM_WRITE) {
461 uint32_t old_lo = cpu->cd.sh.itlb_lo[e];
462 int safe_to_invalidate = 0;
463 if ((cpu->cd.sh.itlb_lo[e] & SH4_PTEL_SZ_MASK)==SH4_PTEL_SZ_4K)
464 safe_to_invalidate = 1;
465
466 idata = memory_readmax64(cpu, data, len);
467 cpu->cd.sh.itlb_lo[e] &= ~mask;
468 cpu->cd.sh.itlb_lo[e] |= (idata & mask);
469
470 /* Invalidate if this ITLB entry belongs to the
471 currently running process, or if it was shared: */
472 if (old_lo & SH4_PTEL_SH ||
473 (cpu->cd.sh.itlb_hi[e] & SH4_ITLB_AA_ASID_MASK) ==
474 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
475 if (safe_to_invalidate)
476 cpu->invalidate_translation_caches(cpu,
477 cpu->cd.sh.itlb_hi[e] & ~0xfff,
478 INVALIDATE_VADDR);
479 else
480 cpu->invalidate_translation_caches(cpu,
481 0, INVALIDATE_ALL);
482 }
483 } else {
484 odata = cpu->cd.sh.itlb_lo[e] & mask;
485 memory_writemax64(cpu, data, len, odata);
486 }
487
488 return 1;
489 }
490
491
492 DEVICE_ACCESS(sh4_utlb_aa)
493 {
494 uint64_t idata = 0, odata = 0;
495 int i, e = (relative_addr & SH4_UTLB_E_MASK) >> SH4_UTLB_E_SHIFT;
496 int a = relative_addr & SH4_UTLB_A;
497
498 if (writeflag == MEM_WRITE) {
499 int n_hits = 0;
500 int safe_to_invalidate = 0;
501 uint32_t vaddr_to_invalidate = 0;
502
503 idata = memory_readmax64(cpu, data, len);
504 if (a) {
505 for (i=-SH_N_ITLB_ENTRIES; i<SH_N_UTLB_ENTRIES; i++) {
506 uint32_t lo, hi;
507 uint32_t mask = 0xfffff000;
508 int sh;
509
510 if (i < 0) {
511 lo = cpu->cd.sh.itlb_lo[
512 i + SH_N_ITLB_ENTRIES];
513 hi = cpu->cd.sh.itlb_hi[
514 i + SH_N_ITLB_ENTRIES];
515 } else {
516 lo = cpu->cd.sh.utlb_lo[i];
517 hi = cpu->cd.sh.utlb_hi[i];
518 }
519
520 sh = lo & SH4_PTEL_SH;
521 if (!(lo & SH4_PTEL_V))
522 continue;
523
524 switch (lo & SH4_PTEL_SZ_MASK) {
525 case SH4_PTEL_SZ_1K: mask = 0xfffffc00; break;
526 case SH4_PTEL_SZ_64K: mask = 0xffff0000; break;
527 case SH4_PTEL_SZ_1M: mask = 0xfff00000; break;
528 }
529
530 if ((hi & mask) != (idata & mask))
531 continue;
532
533 if ((lo & SH4_PTEL_SZ_MASK) ==
534 SH4_PTEL_SZ_4K) {
535 safe_to_invalidate = 1;
536 vaddr_to_invalidate = hi & mask;
537 }
538
539 if (!sh && (hi & SH4_PTEH_ASID_MASK) !=
540 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK))
541 continue;
542
543 if (i < 0) {
544 cpu->cd.sh.itlb_lo[i +
545 SH_N_ITLB_ENTRIES] &= ~SH4_PTEL_V;
546 if (idata & SH4_UTLB_AA_V)
547 cpu->cd.sh.itlb_lo[
548 i+SH_N_ITLB_ENTRIES] |=
549 SH4_PTEL_V;
550 } else {
551 cpu->cd.sh.utlb_lo[i] &=
552 ~(SH4_PTEL_D | SH4_PTEL_V);
553 if (idata & SH4_UTLB_AA_D)
554 cpu->cd.sh.utlb_lo[i] |=
555 SH4_PTEL_D;
556 if (idata & SH4_UTLB_AA_V)
557 cpu->cd.sh.utlb_lo[i] |=
558 SH4_PTEL_V;
559 }
560
561 if (i >= 0)
562 n_hits ++;
563 }
564
565 if (n_hits > 1)
566 sh_exception(cpu,
567 EXPEVT_RESET_TLB_MULTI_HIT, 0, 0);
568 } else {
569 if ((cpu->cd.sh.utlb_lo[e] & SH4_PTEL_SZ_MASK) ==
570 SH4_PTEL_SZ_4K) {
571 safe_to_invalidate = 1;
572 vaddr_to_invalidate =
573 cpu->cd.sh.utlb_hi[e] & ~0xfff;
574 }
575
576 cpu->cd.sh.utlb_hi[e] &=
577 ~(SH4_PTEH_VPN_MASK | SH4_PTEH_ASID_MASK);
578 cpu->cd.sh.utlb_hi[e] |= (idata &
579 (SH4_UTLB_AA_VPN_MASK | SH4_UTLB_AA_ASID_MASK));
580
581 cpu->cd.sh.utlb_lo[e] &= ~(SH4_PTEL_D | SH4_PTEL_V);
582 if (idata & SH4_UTLB_AA_D)
583 cpu->cd.sh.utlb_lo[e] |= SH4_PTEL_D;
584 if (idata & SH4_UTLB_AA_V)
585 cpu->cd.sh.utlb_lo[e] |= SH4_PTEL_V;
586 }
587
588 if (safe_to_invalidate)
589 cpu->invalidate_translation_caches(cpu,
590 vaddr_to_invalidate, INVALIDATE_VADDR);
591 else
592 cpu->invalidate_translation_caches(cpu, 0,
593 INVALIDATE_ALL);
594 } else {
595 odata = cpu->cd.sh.utlb_hi[e] &
596 (SH4_UTLB_AA_VPN_MASK | SH4_UTLB_AA_ASID_MASK);
597 if (cpu->cd.sh.utlb_lo[e] & SH4_PTEL_D)
598 odata |= SH4_UTLB_AA_D;
599 if (cpu->cd.sh.utlb_lo[e] & SH4_PTEL_V)
600 odata |= SH4_UTLB_AA_V;
601 memory_writemax64(cpu, data, len, odata);
602 }
603
604 return 1;
605 }
606
607
608 DEVICE_ACCESS(sh4_utlb_da1)
609 {
610 uint32_t mask = SH4_PTEL_WT | SH4_PTEL_SH | SH4_PTEL_D | SH4_PTEL_C
611 | SH4_PTEL_SZ_MASK | SH4_PTEL_PR_MASK | SH4_PTEL_V | 0x1ffffc00;
612 uint64_t idata = 0, odata = 0;
613 int e = (relative_addr & SH4_UTLB_E_MASK) >> SH4_UTLB_E_SHIFT;
614
615 if (relative_addr & 0x800000) {
616 fatal("sh4_utlb_da1: TODO: da2 area\n");
617 exit(1);
618 }
619
620 if (writeflag == MEM_WRITE) {
621 uint32_t old_lo = cpu->cd.sh.utlb_lo[e];
622 int safe_to_invalidate = 0;
623 if ((cpu->cd.sh.utlb_lo[e] & SH4_PTEL_SZ_MASK)==SH4_PTEL_SZ_4K)
624 safe_to_invalidate = 1;
625
626 idata = memory_readmax64(cpu, data, len);
627 cpu->cd.sh.utlb_lo[e] &= ~mask;
628 cpu->cd.sh.utlb_lo[e] |= (idata & mask);
629
630 /* Invalidate if this UTLB entry belongs to the
631 currently running process, or if it was shared: */
632 if (old_lo & SH4_PTEL_SH ||
633 (cpu->cd.sh.utlb_hi[e] & SH4_ITLB_AA_ASID_MASK) ==
634 (cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK)) {
635 if (safe_to_invalidate)
636 cpu->invalidate_translation_caches(cpu,
637 cpu->cd.sh.utlb_hi[e] & ~0xfff,
638 INVALIDATE_VADDR);
639 else
640 cpu->invalidate_translation_caches(cpu,
641 0, INVALIDATE_ALL);
642 }
643 } else {
644 odata = cpu->cd.sh.utlb_lo[e] & mask;
645 memory_writemax64(cpu, data, len, odata);
646 }
647
648 return 1;
649 }
650
651
652 DEVICE_ACCESS(sh4)
653 {
654 struct sh4_data *d = (struct sh4_data *) extra;
655 uint64_t idata = 0, odata = 0;
656 int timer_nr = 0, dma_channel = 0;
657
658 if (writeflag == MEM_WRITE)
659 idata = memory_readmax64(cpu, data, len);
660
661 relative_addr += SH4_REG_BASE;
662
663 /* SD-RAM access uses address only: */
664 if (relative_addr >= 0xff900000 && relative_addr <= 0xff97ffff) {
665 /* Possibly not 100% correct... TODO */
666 int v = (relative_addr >> 2) & 0xffff;
667 if (relative_addr & 0x00040000)
668 d->sdmr3 = v;
669 else
670 d->sdmr2 = v;
671 debug("[ sh4: sdmr%i set to 0x%04"PRIx16" ]\n",
672 relative_addr & 0x00040000? 3 : 2, v);
673 return 1;
674 }
675
676
677 switch (relative_addr) {
678
679 /*************************************************/
680
681 case SH4_PVR_ADDR:
682 odata = cpu->cd.sh.cpu_type.pvr;
683 break;
684
685 case SH4_PRR_ADDR:
686 odata = cpu->cd.sh.cpu_type.prr;
687 break;
688
689 case SH4_PTEH:
690 if (writeflag == MEM_READ)
691 odata = cpu->cd.sh.pteh;
692 else {
693 int old_asid = cpu->cd.sh.pteh & SH4_PTEH_ASID_MASK;
694 cpu->cd.sh.pteh = idata;
695
696 if ((idata & SH4_PTEH_ASID_MASK) != old_asid) {
697 /*
698 * TODO: Don't invalidate everything,
699 * only those pages that belonged to the
700 * old asid.
701 */
702 cpu->invalidate_translation_caches(
703 cpu, 0, INVALIDATE_ALL);
704 }
705 }
706 break;
707
708 case SH4_PTEL:
709 if (writeflag == MEM_READ)
710 odata = cpu->cd.sh.ptel;
711 else
712 cpu->cd.sh.ptel = idata;
713 break;
714
715 case SH4_TTB:
716 if (writeflag == MEM_READ)
717 odata = cpu->cd.sh.ttb;
718 else
719 cpu->cd.sh.ttb = idata;
720 break;
721
722 case SH4_TEA:
723 if (writeflag == MEM_READ)
724 odata = cpu->cd.sh.tea;
725 else
726 cpu->cd.sh.tea = idata;
727 break;
728
729 case SH4_PTEA:
730 if (writeflag == MEM_READ)
731 odata = cpu->cd.sh.ptea;
732 else
733 cpu->cd.sh.ptea = idata;
734 break;
735
736 case SH4_MMUCR:
737 if (writeflag == MEM_READ) {
738 odata = cpu->cd.sh.mmucr;
739 } else {
740 if (idata & SH4_MMUCR_TI) {
741 /* TLB invalidate. */
742 int i;
743 for (i = 0; i < SH_N_ITLB_ENTRIES; i++)
744 cpu->cd.sh.itlb_lo[i] &=
745 ~SH4_PTEL_V;
746
747 for (i = 0; i < SH_N_UTLB_ENTRIES; i++)
748 cpu->cd.sh.utlb_lo[i] &=
749 ~SH4_PTEL_V;
750
751 cpu->invalidate_translation_caches(cpu,
752 0, INVALIDATE_ALL);
753
754 /* Should always read back as 0. */
755 idata &= ~SH4_MMUCR_TI;
756 }
757
758 cpu->cd.sh.mmucr = idata;
759 }
760 break;
761
762 case SH4_CCR:
763 if (writeflag == MEM_READ) {
764 odata = cpu->cd.sh.ccr;
765 } else {
766 cpu->cd.sh.ccr = idata;
767 }
768 break;
769
770 case SH4_QACR0:
771 if (writeflag == MEM_READ) {
772 odata = cpu->cd.sh.qacr0;
773 } else {
774 cpu->cd.sh.qacr0 = idata;
775 }
776 break;
777
778 case SH4_QACR1:
779 if (writeflag == MEM_READ) {
780 odata = cpu->cd.sh.qacr1;
781 } else {
782 cpu->cd.sh.qacr1 = idata;
783 }
784 break;
785
786 case SH4_TRA:
787 if (writeflag == MEM_READ)
788 odata = cpu->cd.sh.tra;
789 else
790 cpu->cd.sh.tra = idata;
791 break;
792
793 case SH4_EXPEVT:
794 if (writeflag == MEM_READ)
795 odata = cpu->cd.sh.expevt;
796 else
797 cpu->cd.sh.expevt = idata;
798 break;
799
800 case SH4_INTEVT:
801 if (writeflag == MEM_READ)
802 odata = cpu->cd.sh.intevt;
803 else
804 cpu->cd.sh.intevt = idata;
805 break;
806
807
808 /********************************/
809 /* UBC: User Break Controller */
810
811 case 0xff200008: /* SH4_BBRA */
812 /* TODO */
813 break;
814
815
816 /********************************/
817 /* TMU: Timer Management Unit */
818
819 case SH4_TOCR:
820 /* Timer Output Control Register */
821 if (writeflag == MEM_WRITE) {
822 d->tocr = idata;
823 if (idata & TOCR_TCOE)
824 fatal("[ sh4 timer: TCOE not yet "
825 "implemented ]\n");
826 } else {
827 odata = d->tocr;
828 }
829 break;
830
831 case SH4_TSTR:
832 /* Timer Start Register */
833 if (writeflag == MEM_READ) {
834 odata = d->tstr;
835 } else {
836 if (idata & 1 && !(d->tstr & 1))
837 debug("[ sh4 timer: starting timer 0 ]\n");
838 if (idata & 2 && !(d->tstr & 2))
839 debug("[ sh4 timer: starting timer 1 ]\n");
840 if (idata & 4 && !(d->tstr & 4))
841 debug("[ sh4 timer: starting timer 2 ]\n");
842 if (!(idata & 1) && d->tstr & 1)
843 debug("[ sh4 timer: stopping timer 0 ]\n");
844 if (!(idata & 2) && d->tstr & 2)
845 debug("[ sh4 timer: stopping timer 1 ]\n");
846 if (!(idata & 4) && d->tstr & 4)
847 debug("[ sh4 timer: stopping timer 2 ]\n");
848 d->tstr = idata;
849 }
850 break;
851
852 case SH4_TCOR2:
853 timer_nr ++;
854 case SH4_TCOR1:
855 timer_nr ++;
856 case SH4_TCOR0:
857 /* Timer Constant Register */
858 if (writeflag == MEM_READ)
859 odata = d->tcor[timer_nr];
860 else
861 d->tcor[timer_nr] = idata;
862 break;
863
864 case SH4_TCNT2:
865 timer_nr ++;
866 case SH4_TCNT1:
867 timer_nr ++;
868 case SH4_TCNT0:
869 /* Timer Counter Register */
870 if (writeflag == MEM_READ)
871 odata = d->tcnt[timer_nr];
872 else
873 d->tcnt[timer_nr] = idata;
874 break;
875
876 case SH4_TCR2:
877 timer_nr ++;
878 case SH4_TCR1:
879 timer_nr ++;
880 case SH4_TCR0:
881 /* Timer Control Register */
882 if (writeflag == MEM_READ) {
883 odata = d->tcr[timer_nr];
884 } else {
885 if (cpu->cd.sh.pclock == 0) {
886 fatal("INTERNAL ERROR: pclock must be set"
887 " for this machine. Aborting.\n");
888 exit(1);
889 }
890
891 switch (idata & 3) {
892 case TCR_TPSC_P4:
893 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/4.0;
894 break;
895 case TCR_TPSC_P16:
896 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/16.0;
897 break;
898 case TCR_TPSC_P64:
899 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/64.0;
900 break;
901 case TCR_TPSC_P256:
902 d->timer_hz[timer_nr] = cpu->cd.sh.pclock/256.0;
903 break;
904 }
905
906 debug("[ sh4 timer %i clock set to %f Hz ]\n",
907 timer_nr, d->timer_hz[timer_nr]);
908
909 if (idata & (TCR_ICPF | TCR_ICPE1 | TCR_ICPE0 |
910 TCR_CKEG1 | TCR_CKEG0 | TCR_TPSC2)) {
911 fatal("Unimplemented SH4 timer control"
912 " bits: 0x%08"PRIx32". Aborting.\n",
913 (int) idata);
914 exit(1);
915 }
916
917 INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
918
919 if (d->tcr[timer_nr] & TCR_UNF && !(idata & TCR_UNF)) {
920 if (d->timer_interrupts_pending[timer_nr] > 0)
921 d->timer_interrupts_pending[timer_nr]--;
922 }
923
924 d->tcr[timer_nr] = idata;
925 }
926 break;
927
928
929 /*************************************************/
930 /* DMAC: DMA Controller */
931
932 case SH4_SAR3:
933 dma_channel ++;
934 case SH4_SAR2:
935 dma_channel ++;
936 case SH4_SAR1:
937 dma_channel ++;
938 case SH4_SAR0:
939 dma_channel ++;
940 if (writeflag == MEM_READ)
941 odata = cpu->cd.sh.dmac_sar[dma_channel];
942 else
943 cpu->cd.sh.dmac_sar[dma_channel] = idata;
944 break;
945
946 case SH4_DAR3:
947 dma_channel ++;
948 case SH4_DAR2:
949 dma_channel ++;
950 case SH4_DAR1:
951 dma_channel ++;
952 case SH4_DAR0:
953 dma_channel ++;
954 if (writeflag == MEM_READ)
955 odata = cpu->cd.sh.dmac_dar[dma_channel];
956 else
957 cpu->cd.sh.dmac_dar[dma_channel] = idata;
958 break;
959
960 case SH4_DMATCR3:
961 dma_channel ++;
962 case SH4_DMATCR2:
963 dma_channel ++;
964 case SH4_DMATCR1:
965 dma_channel ++;
966 case SH4_DMATCR0:
967 dma_channel ++;
968 if (writeflag == MEM_READ)
969 odata = cpu->cd.sh.dmac_tcr[dma_channel] & 0x00ffffff;
970 else {
971 if (idata & ~0x00ffffff) {
972 fatal("[ SH4 DMA: Attempt to set top 8 "
973 "bits of the count register? 0x%08"
974 PRIx32" ]\n", (uint32_t) idata);
975 exit(1);
976 }
977
978 /* Special case: writing 0 to the count register
979 means 16777216: */
980 if (idata == 0)
981 idata = 0x01000000;
982 cpu->cd.sh.dmac_tcr[dma_channel] = idata;
983 }
984 break;
985
986 case SH4_CHCR3:
987 dma_channel ++;
988 case SH4_CHCR2:
989 dma_channel ++;
990 case SH4_CHCR1:
991 dma_channel ++;
992 case SH4_CHCR0:
993 dma_channel ++;
994 if (writeflag == MEM_READ)
995 odata = cpu->cd.sh.dmac_chcr[dma_channel];
996 else {
997 /* IP.BIN sets this to 0x12c0, and I want to know if
998 some other guest OS uses other values. */
999 if (idata != 0x12c0) {
1000 fatal("[ SH4 DMA: Attempt to set chcr "
1001 "to 0x%08"PRIx32" ]\n", (uint32_t) idata);
1002 exit(1);
1003 }
1004
1005 cpu->cd.sh.dmac_chcr[dma_channel] = idata;
1006 }
1007 break;
1008
1009
1010 /*************************************************/
1011 /* BSC: Bus State Controller */
1012
1013 case SH4_BCR1:
1014 if (writeflag == MEM_WRITE)
1015 d->bsc_bcr1 = idata & 0x033efffd;
1016 else {
1017 odata = d->bsc_bcr1;
1018 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1019 odata |= BCR1_LITTLE_ENDIAN;
1020 }
1021 break;
1022
1023 case SH4_BCR2:
1024 if (len != sizeof(uint16_t)) {
1025 fatal("Non-16-bit SH4_BCR2 access?\n");
1026 exit(1);
1027 }
1028 if (writeflag == MEM_WRITE)
1029 d->bsc_bcr2 = idata & 0x3ffd;
1030 else
1031 odata = d->bsc_bcr2;
1032 break;
1033
1034 case SH4_WCR1:
1035 if (writeflag == MEM_WRITE)
1036 d->bsc_wcr1 = idata & 0x77777777;
1037 else
1038 odata = d->bsc_wcr1;
1039 break;
1040
1041 case SH4_WCR2:
1042 if (writeflag == MEM_WRITE)
1043 d->bsc_wcr2 = idata & 0xfffeefff;
1044 else
1045 odata = d->bsc_wcr2;
1046 break;
1047
1048 case SH4_MCR:
1049 if (writeflag == MEM_WRITE)
1050 d->bsc_mcr = idata & 0xf8bbffff;
1051 else
1052 odata = d->bsc_mcr;
1053 break;
1054
1055 case SH4_RTCSR:
1056 /*
1057 * Refresh Time Control/Status Register. Called RTCSR in
1058 * NetBSD, but RTSCR in the SH7750 manual?
1059 */
1060 if (writeflag == MEM_WRITE) {
1061 idata &= 0x00ff;
1062 if (idata & RTCSR_CMF) {
1063 idata = (idata & ~RTCSR_CMF)
1064 | (d->bsc_rtcsr & RTCSR_CMF);
1065 }
1066 d->bsc_rtcsr = idata & 0x00ff;
1067 } else
1068 odata = d->bsc_rtcsr;
1069 break;
1070
1071 case SH4_RTCOR:
1072 /* Refresh Time Constant Register (8 bits): */
1073 if (writeflag == MEM_WRITE)
1074 d->bsc_rtcor = idata & 0x00ff;
1075 else
1076 odata = d->bsc_rtcor & 0x00ff;
1077 break;
1078
1079 case SH4_RFCR:
1080 /* Refresh Count Register (10 bits): */
1081 if (writeflag == MEM_WRITE)
1082 d->bsc_rfcr = idata & 0x03ff;
1083 else
1084 odata = d->bsc_rfcr & 0x03ff;
1085 break;
1086
1087
1088 /*******************************************/
1089 /* GPIO: General-purpose I/O controller */
1090
1091 case SH4_PCTRA:
1092 if (writeflag == MEM_WRITE)
1093 d->pctra = idata;
1094 else
1095 odata = d->pctra;
1096 break;
1097
1098 case SH4_PDTRA:
1099 if (writeflag == MEM_WRITE) {
1100 debug("[ sh4: pdtra: write: TODO ]\n");
1101 d->pdtra = idata;
1102 } else {
1103 debug("[ sh4: pdtra: read: TODO ]\n");
1104 odata = d->pdtra;
1105 }
1106 break;
1107
1108 case SH4_PCTRB:
1109 if (writeflag == MEM_WRITE)
1110 d->pctrb = idata;
1111 else
1112 odata = d->pctrb;
1113 break;
1114
1115 case SH4_PDTRB:
1116 if (writeflag == MEM_WRITE) {
1117 debug("[ sh4: pdtrb: write: TODO ]\n");
1118 d->pdtrb = idata;
1119 } else {
1120 debug("[ sh4: pdtrb: read: TODO ]\n");
1121 odata = d->pdtrb;
1122 }
1123 break;
1124
1125
1126 /****************************/
1127 /* SCI: Serial Interface */
1128
1129 case SHREG_SCSPTR:
1130 odata = sh_sci_access(d, cpu,
1131 writeflag == MEM_WRITE? 1 : 0, idata);
1132 break;
1133
1134
1135 /*********************************/
1136 /* INTC: Interrupt Controller */
1137
1138 case SH4_ICR:
1139 if (writeflag == MEM_WRITE) {
1140 if (idata & 0x80) {
1141 fatal("SH4 INTC: IRLM not yet "
1142 "supported. TODO\n");
1143 exit(1);
1144 }
1145 }
1146 break;
1147
1148 case SH4_IPRA:
1149 if (writeflag == MEM_READ)
1150 odata = cpu->cd.sh.intc_ipra;
1151 else {
1152 cpu->cd.sh.intc_ipra = idata;
1153 sh_update_interrupt_priorities(cpu);
1154 }
1155 break;
1156
1157 case SH4_IPRB:
1158 if (writeflag == MEM_READ)
1159 odata = cpu->cd.sh.intc_iprb;
1160 else {
1161 cpu->cd.sh.intc_iprb = idata;
1162 sh_update_interrupt_priorities(cpu);
1163 }
1164 break;
1165
1166 case SH4_IPRC:
1167 if (writeflag == MEM_READ)
1168 odata = cpu->cd.sh.intc_iprc;
1169 else {
1170 cpu->cd.sh.intc_iprc = idata;
1171 sh_update_interrupt_priorities(cpu);
1172 }
1173 break;
1174
1175 case SH4_IPRD:
1176 if (writeflag == MEM_READ)
1177 odata = cpu->cd.sh.intc_iprd;
1178 else {
1179 cpu->cd.sh.intc_iprd = idata;
1180 sh_update_interrupt_priorities(cpu);
1181 }
1182 break;
1183
1184 case SH4_INTPRI00:
1185 if (writeflag == MEM_READ)
1186 odata = cpu->cd.sh.intc_intpri00;
1187 else {
1188 cpu->cd.sh.intc_intpri00 = idata;
1189 sh_update_interrupt_priorities(cpu);
1190 }
1191 break;
1192
1193 case SH4_INTPRI00 + 4:
1194 if (writeflag == MEM_READ)
1195 odata = cpu->cd.sh.intc_intpri04;
1196 else {
1197 cpu->cd.sh.intc_intpri04 = idata;
1198 sh_update_interrupt_priorities(cpu);
1199 }
1200 break;
1201
1202 case SH4_INTPRI00 + 8:
1203 if (writeflag == MEM_READ)
1204 odata = cpu->cd.sh.intc_intpri08;
1205 else {
1206 cpu->cd.sh.intc_intpri08 = idata;
1207 sh_update_interrupt_priorities(cpu);
1208 }
1209 break;
1210
1211 case SH4_INTPRI00 + 0xc:
1212 if (writeflag == MEM_READ)
1213 odata = cpu->cd.sh.intc_intpri0c;
1214 else {
1215 cpu->cd.sh.intc_intpri0c = idata;
1216 sh_update_interrupt_priorities(cpu);
1217 }
1218 break;
1219
1220 case SH4_INTMSK00:
1221 /* Note: Writes can only set bits, not clear them. */
1222 if (writeflag == MEM_READ)
1223 odata = cpu->cd.sh.intc_intmsk00;
1224 else
1225 cpu->cd.sh.intc_intmsk00 |= idata;
1226 break;
1227
1228 case SH4_INTMSK00 + 4:
1229 /* Note: Writes can only set bits, not clear them. */
1230 if (writeflag == MEM_READ)
1231 odata = cpu->cd.sh.intc_intmsk04;
1232 else
1233 cpu->cd.sh.intc_intmsk04 |= idata;
1234 break;
1235
1236 case SH4_INTMSKCLR00:
1237 /* Note: Writes can only clear bits, not set them. */
1238 if (writeflag == MEM_WRITE)
1239 cpu->cd.sh.intc_intmsk00 &= ~idata;
1240 break;
1241
1242 case SH4_INTMSKCLR00 + 4:
1243 /* Note: Writes can only clear bits, not set them. */
1244 if (writeflag == MEM_WRITE)
1245 cpu->cd.sh.intc_intmsk04 &= ~idata;
1246 break;
1247
1248
1249 /*************************************************/
1250 /* SCIF: Serial Controller Interface with FIFO */
1251
1252 case SH4_SCIF_BASE + SCIF_SMR:
1253 if (writeflag == MEM_WRITE) {
1254 d->scif_smr = idata;
1255 } else {
1256 odata = d->scif_smr;
1257 }
1258 break;
1259
1260 case SH4_SCIF_BASE + SCIF_BRR:
1261 if (writeflag == MEM_WRITE) {
1262 d->scif_brr = idata;
1263 } else {
1264 odata = d->scif_brr;
1265 }
1266 break;
1267
1268 case SH4_SCIF_BASE + SCIF_SCR:
1269 if (writeflag == MEM_WRITE) {
1270 d->scif_scr = idata;
1271 scif_reassert_interrupts(d);
1272 } else {
1273 odata = d->scif_scr;
1274 }
1275 break;
1276
1277 case SH4_SCIF_BASE + SCIF_FTDR:
1278 if (writeflag == MEM_WRITE) {
1279 /* Add to TX fifo: */
1280 if (d->scif_tx_fifo_cursize >= sizeof(
1281 d->scif_tx_fifo)) {
1282 fatal("[ SCIF TX fifo overrun! ]\n");
1283 d->scif_tx_fifo_cursize = 0;
1284 }
1285
1286 d->scif_tx_fifo[d->scif_tx_fifo_cursize++] = idata;
1287 d->scif_delayed_tx = 2;
1288 }
1289 break;
1290
1291 case SH4_SCIF_BASE + SCIF_SSR:
1292 if (writeflag == MEM_READ) {
1293 odata = d->scif_ssr;
1294 } else {
1295 d->scif_ssr = idata;
1296 scif_reassert_interrupts(d);
1297 }
1298 break;
1299
1300 case SH4_SCIF_BASE + SCIF_FRDR:
1301 {
1302 int x = console_readchar(d->scif_console_handle);
1303 if (x == 13)
1304 x = 10;
1305 odata = x < 0? 0 : x;
1306 if (console_charavail(d->scif_console_handle))
1307 d->scif_ssr |= SCSSR2_DR;
1308 else
1309 d->scif_ssr &= ~SCSSR2_DR;
1310 scif_reassert_interrupts(d);
1311 }
1312 break;
1313
1314 case SH4_SCIF_BASE + SCIF_FCR:
1315 if (writeflag == MEM_WRITE) {
1316 d->scif_fcr = idata;
1317 } else {
1318 odata = d->scif_fcr;
1319 }
1320 break;
1321
1322 case SH4_SCIF_BASE + SCIF_LSR:
1323 /* TODO: Implement all bits. */
1324 odata = 0;
1325 break;
1326
1327 case SH4_SCIF_BASE + SCIF_FDR:
1328 odata = (console_charavail(d->scif_console_handle)? 1 : 0)
1329 + (d->scif_tx_fifo_cursize << 8);
1330 break;
1331
1332
1333 /*************************************************/
1334
1335 case SH4_RSECCNT:
1336 case SH4_RMINCNT:
1337 case SH4_RHRCNT:
1338 case SH4_RWKCNT:
1339 case SH4_RDAYCNT:
1340 case SH4_RMONCNT:
1341 case SH4_RYRCNT:
1342 case SH4_RSECAR:
1343 case SH4_RMINAR:
1344 case SH4_RHRAR:
1345 case SH4_RWKAR:
1346 case SH4_RDAYAR:
1347 case SH4_RMONAR:
1348 if (writeflag == MEM_WRITE) {
1349 d->rtc_reg[(relative_addr - 0xffc80000) / 4] = idata;
1350 } else {
1351 /* TODO: Update rtc_reg based on host's date/time. */
1352 odata = d->rtc_reg[(relative_addr - 0xffc80000) / 4];
1353 }
1354 break;
1355
1356 case SH4_RCR1:
1357 if (writeflag == MEM_READ)
1358 odata = d->rtc_rcr1;
1359 else {
1360 d->rtc_rcr1 = idata;
1361 if (idata & 0x18) {
1362 fatal("SH4: TODO: RTC interrupt enable\n");
1363 exit(1);
1364 }
1365 }
1366 break;
1367
1368
1369 /*************************************************/
1370
1371 default:if (writeflag == MEM_READ) {
1372 fatal("[ sh4: read from addr 0x%x ]\n",
1373 (int)relative_addr);
1374 } else {
1375 fatal("[ sh4: write to addr 0x%x: 0x%x ]\n",
1376 (int)relative_addr, (int)idata);
1377 }
1378 #ifdef SH4_DEGUG
1379 // exit(1);
1380 #endif
1381 }
1382
1383 if (writeflag == MEM_READ)
1384 memory_writemax64(cpu, data, len, odata);
1385
1386 return 1;
1387 }
1388
1389
1390 DEVINIT(sh4)
1391 {
1392 char tmp[200];
1393 struct machine *machine = devinit->machine;
1394 struct sh4_data *d = malloc(sizeof(struct sh4_data));
1395 if (d == NULL) {
1396 fprintf(stderr, "out of memory\n");
1397 exit(1);
1398 }
1399 memset(d, 0, sizeof(struct sh4_data));
1400
1401 d->scif_console_handle = console_start_slave(devinit->machine,
1402 "SH4 SCIF", 1);
1403
1404 snprintf(tmp, sizeof(tmp), "%s.irq[0x%x]",
1405 devinit->interrupt_path, SH4_INTEVT_SCIF_RXI);
1406 INTERRUPT_CONNECT(tmp, d->scif_rx_irq);
1407 snprintf(tmp, sizeof(tmp), "%s.irq[0x%x]",
1408 devinit->interrupt_path, SH4_INTEVT_SCIF_TXI);
1409 INTERRUPT_CONNECT(tmp, d->scif_tx_irq);
1410
1411 memory_device_register(machine->memory, devinit->name,
1412 SH4_REG_BASE, 0x01000000, dev_sh4_access, d, DM_DEFAULT, NULL);
1413
1414 /* On-chip RAM/cache: */
1415 dev_ram_init(machine, 0x1e000000, 0x8000, DEV_RAM_RAM, 0x0);
1416
1417 /* 0xe0000000: Store queues: */
1418 dev_ram_init(machine, 0xe0000000, 32 * 2, DEV_RAM_RAM, 0x0);
1419
1420 /*
1421 * 0xf0000000 SH4_CCIA I-Cache address array
1422 * 0xf1000000 SH4_CCID I-Cache data array
1423 * 0xf4000000 SH4_CCDA D-Cache address array
1424 * 0xf5000000 SH4_CCDD D-Cache data array
1425 *
1426 * TODO: Implement more correct cache behaviour?
1427 */
1428 dev_ram_init(machine, SH4_CCIA, SH4_ICACHE_SIZE * 2, DEV_RAM_RAM, 0x0);
1429 dev_ram_init(machine, SH4_CCID, SH4_ICACHE_SIZE, DEV_RAM_RAM, 0x0);
1430 dev_ram_init(machine, SH4_CCDA, SH4_DCACHE_SIZE * 2, DEV_RAM_RAM, 0x0);
1431 dev_ram_init(machine, SH4_CCDD, SH4_DCACHE_SIZE, DEV_RAM_RAM, 0x0);
1432
1433 /* 0xf2000000 SH4_ITLB_AA */
1434 memory_device_register(machine->memory, devinit->name, SH4_ITLB_AA,
1435 0x01000000, dev_sh4_itlb_aa_access, d, DM_DEFAULT, NULL);
1436
1437 /* 0xf3000000 SH4_ITLB_DA1 */
1438 memory_device_register(machine->memory, devinit->name, SH4_ITLB_DA1,
1439 0x01000000, dev_sh4_itlb_da1_access, d, DM_DEFAULT, NULL);
1440
1441 /* 0xf6000000 SH4_UTLB_AA */
1442 memory_device_register(machine->memory, devinit->name, SH4_UTLB_AA,
1443 0x01000000, dev_sh4_utlb_aa_access, d, DM_DEFAULT, NULL);
1444
1445 /* 0xf7000000 SH4_UTLB_DA1 */
1446 memory_device_register(machine->memory, devinit->name, SH4_UTLB_DA1,
1447 0x01000000, dev_sh4_utlb_da1_access, d, DM_DEFAULT, NULL);
1448
1449 d->sh4_timer = timer_add(SH4_PSEUDO_TIMER_HZ, sh4_timer_tick, d);
1450 machine_add_tickfunction(devinit->machine, dev_sh4_tick, d,
1451 SH4_TICK_SHIFT, 0.0);
1452
1453 /* Initial Timer values, according to the SH7750 manual: */
1454 d->tcor[0] = 0xffffffff; d->tcnt[0] = 0xffffffff;
1455 d->tcor[1] = 0xffffffff; d->tcnt[1] = 0xffffffff;
1456 d->tcor[2] = 0xffffffff; d->tcnt[2] = 0xffffffff;
1457
1458 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1459 SH_INTEVT_TMU0_TUNI0);
1460 if (!interrupt_handler_lookup(tmp, &d->timer_irq[0])) {
1461 fatal("Could not find interrupt '%s'.\n", tmp);
1462 exit(1);
1463 }
1464 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1465 SH_INTEVT_TMU1_TUNI1);
1466 if (!interrupt_handler_lookup(tmp, &d->timer_irq[1])) {
1467 fatal("Could not find interrupt '%s'.\n", tmp);
1468 exit(1);
1469 }
1470 snprintf(tmp, sizeof(tmp), "emul[0].machine[0].cpu[0].irq[0x%x]",
1471 SH_INTEVT_TMU2_TUNI2);
1472 if (!interrupt_handler_lookup(tmp, &d->timer_irq[2])) {
1473 fatal("Could not find interrupt '%s'.\n", tmp);
1474 exit(1);
1475 }
1476
1477 /*
1478 * Bus State Controller initial values, according to the
1479 * SH7760 manual:
1480 */
1481 d->bsc_bcr2 = 0x3ffc;
1482 d->bsc_wcr1 = 0x77777777;
1483 d->bsc_wcr2 = 0xfffeefff;
1484
1485 return 1;
1486 }
1487

  ViewVC Help
Powered by ViewVC 1.1.26