/[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 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 8 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 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 38 * $Id: dev_sh4.c,v 1.39 2007/04/13 16:12:39 debug Exp $
29 dpavlin 32 *
30     * SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).
31 dpavlin 34 *
32 dpavlin 38 * 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 dpavlin 32 */
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 dpavlin 34 #include "interrupt.h"
50 dpavlin 32 #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 dpavlin 34 #include "sh4_dmacreg.h"
58 dpavlin 32 #include "sh4_exception.h"
59     #include "sh4_intcreg.h"
60     #include "sh4_mmu.h"
61 dpavlin 34 #include "sh4_rtcreg.h"
62 dpavlin 32 #include "sh4_scifreg.h"
63 dpavlin 38 #include "sh4_scireg.h"
64 dpavlin 32 #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 dpavlin 38 #define SCIF_TX_FIFO_SIZE 16
72    
73 dpavlin 34 /* 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 dpavlin 32 /* #define debug fatal */
83 dpavlin 34 #endif
84 dpavlin 32
85     struct sh4_data {
86 dpavlin 34 /* SCIF (Serial controller): */
87     uint16_t scif_smr;
88     uint8_t scif_brr;
89     uint16_t scif_scr;
90 dpavlin 36 uint16_t scif_ssr;
91 dpavlin 34 uint16_t scif_fcr;
92 dpavlin 38 uint16_t scif_lsr;
93 dpavlin 36 int scif_delayed_tx;
94 dpavlin 32 int scif_console_handle;
95 dpavlin 38 uint8_t scif_tx_fifo[SCIF_TX_FIFO_SIZE + 1];
96     int scif_tx_fifo_cursize;
97 dpavlin 36 struct interrupt scif_tx_irq;
98     struct interrupt scif_rx_irq;
99 dpavlin 38 int scif_tx_irq_asserted;
100     int scif_rx_irq_asserted;
101 dpavlin 32
102     /* Bus State Controller: */
103 dpavlin 34 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 dpavlin 32
112 dpavlin 34 /* 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 dpavlin 38 /* 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 dpavlin 34 /* SD-RAM: */
126     uint16_t sdmr2;
127     uint16_t sdmr3;
128    
129 dpavlin 32 /* Timer Management Unit: */
130     struct timer *sh4_timer;
131 dpavlin 34 struct interrupt timer_irq[4];
132 dpavlin 32 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 dpavlin 34
140     /* RTC: */
141     uint32_t rtc_reg[14]; /* Excluding rcr1 and 2 */
142     uint8_t rtc_rcr1;
143 dpavlin 32 };
144    
145    
146 dpavlin 38 #define SH4_PSEUDO_TIMER_HZ 110.0
147 dpavlin 32
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 dpavlin 34 *
156     * Also, RAM Refresh is also faked here.
157 dpavlin 32 */
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 dpavlin 34 /* 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 dpavlin 36 /* Timer interrupts: */
172 dpavlin 32 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 dpavlin 36 static void scif_reassert_interrupts(struct sh4_data *d)
209     {
210 dpavlin 38 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 dpavlin 36 INTERRUPT_DEASSERT(d->scif_rx_irq);
220 dpavlin 38
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 dpavlin 36 INTERRUPT_DEASSERT(d->scif_tx_irq);
229     }
230    
231    
232 dpavlin 32 DEVICE_TICK(sh4)
233     {
234     struct sh4_data *d = (struct sh4_data *) extra;
235     int i;
236    
237 dpavlin 38 /*
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 dpavlin 36 if (console_charavail(d->scif_console_handle))
244     d->scif_ssr |= SCSSR2_DR;
245     else
246 dpavlin 38 d->scif_ssr &= ~SCSSR2_DR;
247    
248 dpavlin 36 if (d->scif_delayed_tx) {
249 dpavlin 38 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 dpavlin 36 d->scif_ssr |= SCSSR2_TDFE | SCSSR2_TEND;
260 dpavlin 38 }
261 dpavlin 36 }
262    
263     scif_reassert_interrupts(d);
264    
265     /* Timer interrupts: */
266 dpavlin 32 for (i=0; i<N_SH4_TIMERS; i++)
267     if (d->timer_interrupts_pending[i] > 0) {
268 dpavlin 34 INTERRUPT_ASSERT(d->timer_irq[i]);
269 dpavlin 32 d->tcr[i] |= TCR_UNF;
270     }
271     }
272    
273    
274 dpavlin 38 /*
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 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 34 uint32_t old_lo = cpu->cd.sh.itlb_lo[e];
462 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 38 cpu->cd.sh.itlb_lo[i +
545     SH_N_ITLB_ENTRIES] &= ~SH4_PTEL_V;
546 dpavlin 32 if (idata & SH4_UTLB_AA_V)
547 dpavlin 38 cpu->cd.sh.itlb_lo[
548     i+SH_N_ITLB_ENTRIES] |=
549 dpavlin 32 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 dpavlin 34 cpu->invalidate_translation_caches(cpu, 0,
593     INVALIDATE_ALL);
594 dpavlin 32 } 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 dpavlin 34 uint32_t old_lo = cpu->cd.sh.utlb_lo[e];
622 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 } 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 dpavlin 34 int timer_nr = 0, dma_channel = 0;
657 dpavlin 32
658     if (writeflag == MEM_WRITE)
659     idata = memory_readmax64(cpu, data, len);
660    
661     relative_addr += SH4_REG_BASE;
662    
663 dpavlin 34 /* 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 dpavlin 32 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 dpavlin 34 /*
698     * TODO: Don't invalidate everything,
699     * only those pages that belonged to the
700     * old asid.
701     */
702 dpavlin 32 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 dpavlin 34 int i;
743     for (i = 0; i < SH_N_ITLB_ENTRIES; i++)
744     cpu->cd.sh.itlb_lo[i] &=
745     ~SH4_PTEL_V;
746 dpavlin 32
747 dpavlin 34 for (i = 0; i < SH_N_UTLB_ENTRIES; i++)
748     cpu->cd.sh.utlb_lo[i] &=
749     ~SH4_PTEL_V;
750    
751 dpavlin 32 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 dpavlin 38 INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
918    
919 dpavlin 32 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 dpavlin 34 /* 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 dpavlin 32 /* BSC: Bus State Controller */
1012    
1013 dpavlin 34 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 dpavlin 32 break;
1022    
1023 dpavlin 34 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 dpavlin 32 /*
1057 dpavlin 34 * Refresh Time Control/Status Register. Called RTCSR in
1058     * NetBSD, but RTSCR in the SH7750 manual?
1059 dpavlin 32 */
1060     if (writeflag == MEM_WRITE) {
1061 dpavlin 34 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 dpavlin 32 } else
1068 dpavlin 34 odata = d->bsc_rtcsr;
1069 dpavlin 32 break;
1070    
1071 dpavlin 34 case SH4_RTCOR:
1072     /* Refresh Time Constant Register (8 bits): */
1073 dpavlin 32 if (writeflag == MEM_WRITE)
1074 dpavlin 34 d->bsc_rtcor = idata & 0x00ff;
1075     else
1076     odata = d->bsc_rtcor & 0x00ff;
1077     break;
1078 dpavlin 32
1079 dpavlin 34 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 dpavlin 32 }
1106     break;
1107    
1108 dpavlin 34 case SH4_PCTRB:
1109     if (writeflag == MEM_WRITE)
1110     d->pctrb = idata;
1111     else
1112     odata = d->pctrb;
1113     break;
1114 dpavlin 32
1115 dpavlin 34 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 dpavlin 38 /****************************/
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 dpavlin 32 /*********************************/
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 dpavlin 38 else {
1152 dpavlin 32 cpu->cd.sh.intc_ipra = idata;
1153 dpavlin 38 sh_update_interrupt_priorities(cpu);
1154     }
1155 dpavlin 32 break;
1156    
1157     case SH4_IPRB:
1158     if (writeflag == MEM_READ)
1159     odata = cpu->cd.sh.intc_iprb;
1160 dpavlin 38 else {
1161 dpavlin 32 cpu->cd.sh.intc_iprb = idata;
1162 dpavlin 38 sh_update_interrupt_priorities(cpu);
1163     }
1164 dpavlin 32 break;
1165    
1166     case SH4_IPRC:
1167     if (writeflag == MEM_READ)
1168     odata = cpu->cd.sh.intc_iprc;
1169 dpavlin 38 else {
1170 dpavlin 32 cpu->cd.sh.intc_iprc = idata;
1171 dpavlin 38 sh_update_interrupt_priorities(cpu);
1172     }
1173 dpavlin 32 break;
1174    
1175 dpavlin 34 case SH4_IPRD:
1176     if (writeflag == MEM_READ)
1177     odata = cpu->cd.sh.intc_iprd;
1178 dpavlin 38 else {
1179 dpavlin 34 cpu->cd.sh.intc_iprd = idata;
1180 dpavlin 38 sh_update_interrupt_priorities(cpu);
1181     }
1182 dpavlin 34 break;
1183 dpavlin 32
1184 dpavlin 38 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 dpavlin 34
1193 dpavlin 38 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 dpavlin 32 /*************************************************/
1250     /* SCIF: Serial Controller Interface with FIFO */
1251    
1252 dpavlin 34 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 dpavlin 36 scif_reassert_interrupts(d);
1272 dpavlin 34 } else {
1273     odata = d->scif_scr;
1274     }
1275     break;
1276    
1277 dpavlin 32 case SH4_SCIF_BASE + SCIF_FTDR:
1278 dpavlin 36 if (writeflag == MEM_WRITE) {
1279 dpavlin 38 /* 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 dpavlin 36 }
1289 dpavlin 32 break;
1290    
1291     case SH4_SCIF_BASE + SCIF_SSR:
1292 dpavlin 36 if (writeflag == MEM_READ) {
1293     odata = d->scif_ssr;
1294     } else {
1295 dpavlin 38 d->scif_ssr = idata;
1296 dpavlin 36 scif_reassert_interrupts(d);
1297     }
1298 dpavlin 32 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 dpavlin 38 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 dpavlin 32 }
1312     break;
1313    
1314 dpavlin 34 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 dpavlin 38 case SH4_SCIF_BASE + SCIF_LSR:
1323     /* TODO: Implement all bits. */
1324     odata = 0;
1325     break;
1326    
1327 dpavlin 32 case SH4_SCIF_BASE + SCIF_FDR:
1328 dpavlin 38 odata = (console_charavail(d->scif_console_handle)? 1 : 0)
1329     + (d->scif_tx_fifo_cursize << 8);
1330 dpavlin 32 break;
1331    
1332 dpavlin 34
1333 dpavlin 32 /*************************************************/
1334    
1335 dpavlin 34 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 dpavlin 32 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 dpavlin 34 #ifdef SH4_DEGUG
1379     // exit(1);
1380     #endif
1381 dpavlin 32 }
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 dpavlin 34 char tmp[200];
1393 dpavlin 32 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 dpavlin 36 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 dpavlin 32 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 dpavlin 36 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 dpavlin 32
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 dpavlin 34 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 dpavlin 38 /*
1478     * Bus State Controller initial values, according to the
1479     * SH7760 manual:
1480     */
1481 dpavlin 34 d->bsc_bcr2 = 0x3ffc;
1482     d->bsc_wcr1 = 0x77777777;
1483     d->bsc_wcr2 = 0xfffeefff;
1484    
1485 dpavlin 32 return 1;
1486     }
1487    

  ViewVC Help
Powered by ViewVC 1.1.26