cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

sh7750.c (24792B)


      1/*
      2 * SH7750 device
      3 *
      4 * Copyright (c) 2007 Magnus Damm
      5 * Copyright (c) 2005 Samuel Tardieu
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a copy
      8 * of this software and associated documentation files (the "Software"), to deal
      9 * in the Software without restriction, including without limitation the rights
     10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11 * copies of the Software, and to permit persons to whom the Software is
     12 * furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice shall be included in
     15 * all copies or substantial portions of the Software.
     16 *
     17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23 * THE SOFTWARE.
     24 */
     25
     26#include "qemu/osdep.h"
     27#include "hw/irq.h"
     28#include "hw/sh4/sh.h"
     29#include "sysemu/sysemu.h"
     30#include "sh7750_regs.h"
     31#include "sh7750_regnames.h"
     32#include "hw/sh4/sh_intc.h"
     33#include "hw/timer/tmu012.h"
     34#include "exec/exec-all.h"
     35
     36#define NB_DEVICES 4
     37
     38typedef struct SH7750State {
     39    MemoryRegion iomem;
     40    MemoryRegion iomem_1f0;
     41    MemoryRegion iomem_ff0;
     42    MemoryRegion iomem_1f8;
     43    MemoryRegion iomem_ff8;
     44    MemoryRegion iomem_1fc;
     45    MemoryRegion iomem_ffc;
     46    MemoryRegion mmct_iomem;
     47    /* CPU */
     48    SuperHCPU *cpu;
     49    /* Peripheral frequency in Hz */
     50    uint32_t periph_freq;
     51    /* SDRAM controller */
     52    uint32_t bcr1;
     53    uint16_t bcr2;
     54    uint16_t bcr3;
     55    uint32_t bcr4;
     56    uint16_t rfcr;
     57    /* PCMCIA controller */
     58    uint16_t pcr;
     59    /* IO ports */
     60    uint16_t gpioic;
     61    uint32_t pctra;
     62    uint32_t pctrb;
     63    uint16_t portdira;		/* Cached */
     64    uint16_t portpullupa;	/* Cached */
     65    uint16_t portdirb;		/* Cached */
     66    uint16_t portpullupb;	/* Cached */
     67    uint16_t pdtra;
     68    uint16_t pdtrb;
     69    uint16_t periph_pdtra;	/* Imposed by the peripherals */
     70    uint16_t periph_portdira;	/* Direction seen from the peripherals */
     71    uint16_t periph_pdtrb;	/* Imposed by the peripherals */
     72    uint16_t periph_portdirb;	/* Direction seen from the peripherals */
     73    sh7750_io_device *devices[NB_DEVICES];	/* External peripherals */
     74
     75    /* Cache */
     76    uint32_t ccr;
     77
     78    struct intc_desc intc;
     79} SH7750State;
     80
     81static inline int has_bcr3_and_bcr4(SH7750State * s)
     82{
     83    return s->cpu->env.features & SH_FEATURE_BCR3_AND_BCR4;
     84}
     85/**********************************************************************
     86 I/O ports
     87**********************************************************************/
     88
     89int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
     90{
     91    int i;
     92
     93    for (i = 0; i < NB_DEVICES; i++) {
     94	if (s->devices[i] == NULL) {
     95	    s->devices[i] = device;
     96	    return 0;
     97	}
     98    }
     99    return -1;
    100}
    101
    102static uint16_t portdir(uint32_t v)
    103{
    104#define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
    105    return
    106	EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
    107	EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
    108	EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
    109	EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
    110	EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
    111	EVENPORTMASK(0);
    112}
    113
    114static uint16_t portpullup(uint32_t v)
    115{
    116#define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
    117    return
    118	ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
    119	ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
    120	ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
    121	ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
    122	ODDPORTMASK(1) | ODDPORTMASK(0);
    123}
    124
    125static uint16_t porta_lines(SH7750State * s)
    126{
    127    return (s->portdira & s->pdtra) |	/* CPU */
    128	(s->periph_portdira & s->periph_pdtra) |	/* Peripherals */
    129	(~(s->portdira | s->periph_portdira) & s->portpullupa);	/* Pullups */
    130}
    131
    132static uint16_t portb_lines(SH7750State * s)
    133{
    134    return (s->portdirb & s->pdtrb) |	/* CPU */
    135	(s->periph_portdirb & s->periph_pdtrb) |	/* Peripherals */
    136	(~(s->portdirb | s->periph_portdirb) & s->portpullupb);	/* Pullups */
    137}
    138
    139static void gen_port_interrupts(SH7750State * s)
    140{
    141    /* XXXXX interrupts not generated */
    142}
    143
    144static void porta_changed(SH7750State * s, uint16_t prev)
    145{
    146    uint16_t currenta, changes;
    147    int i, r = 0;
    148
    149#if 0
    150    fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
    151	    prev, porta_lines(s));
    152    fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
    153#endif
    154    currenta = porta_lines(s);
    155    if (currenta == prev)
    156	return;
    157    changes = currenta ^ prev;
    158
    159    for (i = 0; i < NB_DEVICES; i++) {
    160	if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
    161	    r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
    162					       &s->periph_pdtra,
    163					       &s->periph_portdira,
    164					       &s->periph_pdtrb,
    165					       &s->periph_portdirb);
    166	}
    167    }
    168
    169    if (r)
    170	gen_port_interrupts(s);
    171}
    172
    173static void portb_changed(SH7750State * s, uint16_t prev)
    174{
    175    uint16_t currentb, changes;
    176    int i, r = 0;
    177
    178    currentb = portb_lines(s);
    179    if (currentb == prev)
    180	return;
    181    changes = currentb ^ prev;
    182
    183    for (i = 0; i < NB_DEVICES; i++) {
    184	if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
    185	    r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
    186					       &s->periph_pdtra,
    187					       &s->periph_portdira,
    188					       &s->periph_pdtrb,
    189					       &s->periph_portdirb);
    190	}
    191    }
    192
    193    if (r)
    194	gen_port_interrupts(s);
    195}
    196
    197/**********************************************************************
    198 Memory
    199**********************************************************************/
    200
    201static void error_access(const char *kind, hwaddr addr)
    202{
    203    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") not supported\n",
    204	    kind, regname(addr), addr);
    205}
    206
    207static void ignore_access(const char *kind, hwaddr addr)
    208{
    209    fprintf(stderr, "%s to %s (0x" TARGET_FMT_plx ") ignored\n",
    210	    kind, regname(addr), addr);
    211}
    212
    213static uint32_t sh7750_mem_readb(void *opaque, hwaddr addr)
    214{
    215    switch (addr) {
    216    default:
    217	error_access("byte read", addr);
    218        abort();
    219    }
    220}
    221
    222static uint32_t sh7750_mem_readw(void *opaque, hwaddr addr)
    223{
    224    SH7750State *s = opaque;
    225
    226    switch (addr) {
    227    case SH7750_BCR2_A7:
    228	return s->bcr2;
    229    case SH7750_BCR3_A7:
    230	if(!has_bcr3_and_bcr4(s))
    231	    error_access("word read", addr);
    232	return s->bcr3;
    233    case SH7750_FRQCR_A7:
    234	return 0;
    235    case SH7750_PCR_A7:
    236	return s->pcr;
    237    case SH7750_RFCR_A7:
    238	fprintf(stderr,
    239		"Read access to refresh count register, incrementing\n");
    240	return s->rfcr++;
    241    case SH7750_PDTRA_A7:
    242	return porta_lines(s);
    243    case SH7750_PDTRB_A7:
    244	return portb_lines(s);
    245    case SH7750_RTCOR_A7:
    246    case SH7750_RTCNT_A7:
    247    case SH7750_RTCSR_A7:
    248	ignore_access("word read", addr);
    249	return 0;
    250    default:
    251	error_access("word read", addr);
    252        abort();
    253    }
    254}
    255
    256static uint32_t sh7750_mem_readl(void *opaque, hwaddr addr)
    257{
    258    SH7750State *s = opaque;
    259    SuperHCPUClass *scc;
    260
    261    switch (addr) {
    262    case SH7750_BCR1_A7:
    263	return s->bcr1;
    264    case SH7750_BCR4_A7:
    265	if(!has_bcr3_and_bcr4(s))
    266	    error_access("long read", addr);
    267	return s->bcr4;
    268    case SH7750_WCR1_A7:
    269    case SH7750_WCR2_A7:
    270    case SH7750_WCR3_A7:
    271    case SH7750_MCR_A7:
    272        ignore_access("long read", addr);
    273        return 0;
    274    case SH7750_MMUCR_A7:
    275        return s->cpu->env.mmucr;
    276    case SH7750_PTEH_A7:
    277        return s->cpu->env.pteh;
    278    case SH7750_PTEL_A7:
    279        return s->cpu->env.ptel;
    280    case SH7750_TTB_A7:
    281        return s->cpu->env.ttb;
    282    case SH7750_TEA_A7:
    283        return s->cpu->env.tea;
    284    case SH7750_TRA_A7:
    285        return s->cpu->env.tra;
    286    case SH7750_EXPEVT_A7:
    287        return s->cpu->env.expevt;
    288    case SH7750_INTEVT_A7:
    289        return s->cpu->env.intevt;
    290    case SH7750_CCR_A7:
    291	return s->ccr;
    292    case 0x1f000030:		/* Processor version */
    293        scc = SUPERH_CPU_GET_CLASS(s->cpu);
    294        return scc->pvr;
    295    case 0x1f000040:		/* Cache version */
    296        scc = SUPERH_CPU_GET_CLASS(s->cpu);
    297        return scc->cvr;
    298    case 0x1f000044:		/* Processor revision */
    299        scc = SUPERH_CPU_GET_CLASS(s->cpu);
    300        return scc->prr;
    301    default:
    302	error_access("long read", addr);
    303        abort();
    304    }
    305}
    306
    307#define is_in_sdrmx(a, x) (a >= SH7750_SDMR ## x ## _A7 \
    308			&& a <= (SH7750_SDMR ## x ## _A7 + SH7750_SDMR ## x ## _REGNB))
    309static void sh7750_mem_writeb(void *opaque, hwaddr addr,
    310			      uint32_t mem_value)
    311{
    312
    313    if (is_in_sdrmx(addr, 2) || is_in_sdrmx(addr, 3)) {
    314	ignore_access("byte write", addr);
    315	return;
    316    }
    317
    318    error_access("byte write", addr);
    319    abort();
    320}
    321
    322static void sh7750_mem_writew(void *opaque, hwaddr addr,
    323			      uint32_t mem_value)
    324{
    325    SH7750State *s = opaque;
    326    uint16_t temp;
    327
    328    switch (addr) {
    329	/* SDRAM controller */
    330    case SH7750_BCR2_A7:
    331        s->bcr2 = mem_value;
    332        return;
    333    case SH7750_BCR3_A7:
    334	if(!has_bcr3_and_bcr4(s))
    335	    error_access("word write", addr);
    336	s->bcr3 = mem_value;
    337	return;
    338    case SH7750_PCR_A7:
    339	s->pcr = mem_value;
    340	return;
    341    case SH7750_RTCNT_A7:
    342    case SH7750_RTCOR_A7:
    343    case SH7750_RTCSR_A7:
    344	ignore_access("word write", addr);
    345	return;
    346	/* IO ports */
    347    case SH7750_PDTRA_A7:
    348	temp = porta_lines(s);
    349	s->pdtra = mem_value;
    350	porta_changed(s, temp);
    351	return;
    352    case SH7750_PDTRB_A7:
    353	temp = portb_lines(s);
    354	s->pdtrb = mem_value;
    355	portb_changed(s, temp);
    356	return;
    357    case SH7750_RFCR_A7:
    358	fprintf(stderr, "Write access to refresh count register\n");
    359	s->rfcr = mem_value;
    360	return;
    361    case SH7750_GPIOIC_A7:
    362	s->gpioic = mem_value;
    363	if (mem_value != 0) {
    364	    fprintf(stderr, "I/O interrupts not implemented\n");
    365            abort();
    366	}
    367	return;
    368    default:
    369	error_access("word write", addr);
    370        abort();
    371    }
    372}
    373
    374static void sh7750_mem_writel(void *opaque, hwaddr addr,
    375			      uint32_t mem_value)
    376{
    377    SH7750State *s = opaque;
    378    uint16_t temp;
    379
    380    switch (addr) {
    381	/* SDRAM controller */
    382    case SH7750_BCR1_A7:
    383        s->bcr1 = mem_value;
    384        return;
    385    case SH7750_BCR4_A7:
    386	if(!has_bcr3_and_bcr4(s))
    387	    error_access("long write", addr);
    388	s->bcr4 = mem_value;
    389	return;
    390    case SH7750_WCR1_A7:
    391    case SH7750_WCR2_A7:
    392    case SH7750_WCR3_A7:
    393    case SH7750_MCR_A7:
    394	ignore_access("long write", addr);
    395	return;
    396	/* IO ports */
    397    case SH7750_PCTRA_A7:
    398	temp = porta_lines(s);
    399	s->pctra = mem_value;
    400	s->portdira = portdir(mem_value);
    401	s->portpullupa = portpullup(mem_value);
    402	porta_changed(s, temp);
    403	return;
    404    case SH7750_PCTRB_A7:
    405	temp = portb_lines(s);
    406	s->pctrb = mem_value;
    407	s->portdirb = portdir(mem_value);
    408	s->portpullupb = portpullup(mem_value);
    409	portb_changed(s, temp);
    410	return;
    411    case SH7750_MMUCR_A7:
    412        if (mem_value & MMUCR_TI) {
    413            cpu_sh4_invalidate_tlb(&s->cpu->env);
    414        }
    415        s->cpu->env.mmucr = mem_value & ~MMUCR_TI;
    416        return;
    417    case SH7750_PTEH_A7:
    418        /* If asid changes, clear all registered tlb entries. */
    419        if ((s->cpu->env.pteh & 0xff) != (mem_value & 0xff)) {
    420            tlb_flush(CPU(s->cpu));
    421        }
    422        s->cpu->env.pteh = mem_value;
    423        return;
    424    case SH7750_PTEL_A7:
    425        s->cpu->env.ptel = mem_value;
    426        return;
    427    case SH7750_PTEA_A7:
    428        s->cpu->env.ptea = mem_value & 0x0000000f;
    429        return;
    430    case SH7750_TTB_A7:
    431        s->cpu->env.ttb = mem_value;
    432        return;
    433    case SH7750_TEA_A7:
    434        s->cpu->env.tea = mem_value;
    435        return;
    436    case SH7750_TRA_A7:
    437        s->cpu->env.tra = mem_value & 0x000007ff;
    438        return;
    439    case SH7750_EXPEVT_A7:
    440        s->cpu->env.expevt = mem_value & 0x000007ff;
    441        return;
    442    case SH7750_INTEVT_A7:
    443        s->cpu->env.intevt = mem_value & 0x000007ff;
    444        return;
    445    case SH7750_CCR_A7:
    446	s->ccr = mem_value;
    447	return;
    448    default:
    449	error_access("long write", addr);
    450        abort();
    451    }
    452}
    453
    454static uint64_t sh7750_mem_readfn(void *opaque, hwaddr addr, unsigned size)
    455{
    456    switch (size) {
    457    case 1:
    458        return sh7750_mem_readb(opaque, addr);
    459    case 2:
    460        return sh7750_mem_readw(opaque, addr);
    461    case 4:
    462        return sh7750_mem_readl(opaque, addr);
    463    default:
    464        g_assert_not_reached();
    465    }
    466}
    467
    468static void sh7750_mem_writefn(void *opaque, hwaddr addr,
    469                               uint64_t value, unsigned size)
    470{
    471    switch (size) {
    472    case 1:
    473        sh7750_mem_writeb(opaque, addr, value);
    474        break;
    475    case 2:
    476        sh7750_mem_writew(opaque, addr, value);
    477        break;
    478    case 4:
    479        sh7750_mem_writel(opaque, addr, value);
    480        break;
    481    default:
    482        g_assert_not_reached();
    483    }
    484}
    485
    486static const MemoryRegionOps sh7750_mem_ops = {
    487    .read = sh7750_mem_readfn,
    488    .write = sh7750_mem_writefn,
    489    .valid.min_access_size = 1,
    490    .valid.max_access_size = 4,
    491    .endianness = DEVICE_NATIVE_ENDIAN,
    492};
    493
    494/* sh775x interrupt controller tables for sh_intc.c
    495 * stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c
    496 */
    497
    498enum {
    499	UNUSED = 0,
    500
    501	/* interrupt sources */
    502	IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6, IRL_7,
    503	IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E,
    504	IRL0, IRL1, IRL2, IRL3,
    505	HUDI, GPIOI,
    506	DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
    507	DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
    508	DMAC_DMAE,
    509	PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    510	PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
    511	TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
    512	RTC_ATI, RTC_PRI, RTC_CUI,
    513	SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
    514	SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
    515	WDT,
    516	REF_RCMI, REF_ROVI,
    517
    518	/* interrupt groups */
    519	DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
    520	/* irl bundle */
    521	IRL,
    522
    523	NR_SOURCES,
    524};
    525
    526static struct intc_vect vectors[] = {
    527	INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
    528	INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
    529	INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
    530	INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
    531	INTC_VECT(RTC_CUI, 0x4c0),
    532	INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
    533	INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
    534	INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
    535	INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
    536	INTC_VECT(WDT, 0x560),
    537	INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
    538};
    539
    540static struct intc_group groups[] = {
    541	INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
    542	INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
    543	INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
    544	INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
    545	INTC_GROUP(REF, REF_RCMI, REF_ROVI),
    546};
    547
    548static struct intc_prio_reg prio_registers[] = {
    549	{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
    550	{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } },
    551	{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } },
    552	{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
    553	{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0,
    554						 TMU4, TMU3,
    555						 PCIC1, PCIC0_PCISERR } },
    556};
    557
    558/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
    559
    560static struct intc_vect vectors_dma4[] = {
    561	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
    562	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
    563	INTC_VECT(DMAC_DMAE, 0x6c0),
    564};
    565
    566static struct intc_group groups_dma4[] = {
    567	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
    568		   DMAC_DMTE3, DMAC_DMAE),
    569};
    570
    571/* SH7750R and SH7751R both have 8-channel DMA controllers */
    572
    573static struct intc_vect vectors_dma8[] = {
    574	INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
    575	INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
    576	INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
    577	INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
    578	INTC_VECT(DMAC_DMAE, 0x6c0),
    579};
    580
    581static struct intc_group groups_dma8[] = {
    582	INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
    583		   DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
    584		   DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
    585};
    586
    587/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
    588
    589static struct intc_vect vectors_tmu34[] = {
    590	INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80),
    591};
    592
    593static struct intc_mask_reg mask_registers[] = {
    594	{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */
    595	  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    596	    0, 0, 0, 0, 0, 0, TMU4, TMU3,
    597	    PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    598	    PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2,
    599	    PCIC1_PCIDMA3, PCIC0_PCISERR } },
    600};
    601
    602/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */
    603
    604static struct intc_vect vectors_irlm[] = {
    605	INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
    606	INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
    607};
    608
    609/* SH7751 and SH7751R both have PCI */
    610
    611static struct intc_vect vectors_pci[] = {
    612	INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0),
    613	INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0),
    614	INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60),
    615	INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20),
    616};
    617
    618static struct intc_group groups_pci[] = {
    619	INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
    620		   PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
    621};
    622
    623static struct intc_vect vectors_irl[] = {
    624	INTC_VECT(IRL_0, 0x200),
    625	INTC_VECT(IRL_1, 0x220),
    626	INTC_VECT(IRL_2, 0x240),
    627	INTC_VECT(IRL_3, 0x260),
    628	INTC_VECT(IRL_4, 0x280),
    629	INTC_VECT(IRL_5, 0x2a0),
    630	INTC_VECT(IRL_6, 0x2c0),
    631	INTC_VECT(IRL_7, 0x2e0),
    632	INTC_VECT(IRL_8, 0x300),
    633	INTC_VECT(IRL_9, 0x320),
    634	INTC_VECT(IRL_A, 0x340),
    635	INTC_VECT(IRL_B, 0x360),
    636	INTC_VECT(IRL_C, 0x380),
    637	INTC_VECT(IRL_D, 0x3a0),
    638	INTC_VECT(IRL_E, 0x3c0),
    639};
    640
    641static struct intc_group groups_irl[] = {
    642	INTC_GROUP(IRL, IRL_0, IRL_1, IRL_2, IRL_3, IRL_4, IRL_5, IRL_6,
    643		IRL_7, IRL_8, IRL_9, IRL_A, IRL_B, IRL_C, IRL_D, IRL_E),
    644};
    645
    646/**********************************************************************
    647 Memory mapped cache and TLB
    648**********************************************************************/
    649
    650#define MM_REGION_MASK   0x07000000
    651#define MM_ICACHE_ADDR   (0)
    652#define MM_ICACHE_DATA   (1)
    653#define MM_ITLB_ADDR     (2)
    654#define MM_ITLB_DATA     (3)
    655#define MM_OCACHE_ADDR   (4)
    656#define MM_OCACHE_DATA   (5)
    657#define MM_UTLB_ADDR     (6)
    658#define MM_UTLB_DATA     (7)
    659#define MM_REGION_TYPE(addr)  ((addr & MM_REGION_MASK) >> 24)
    660
    661static uint64_t invalid_read(void *opaque, hwaddr addr)
    662{
    663    abort();
    664
    665    return 0;
    666}
    667
    668static uint64_t sh7750_mmct_read(void *opaque, hwaddr addr,
    669                                 unsigned size)
    670{
    671    SH7750State *s = opaque;
    672    uint32_t ret = 0;
    673
    674    if (size != 4) {
    675        return invalid_read(opaque, addr);
    676    }
    677
    678    switch (MM_REGION_TYPE(addr)) {
    679    case MM_ICACHE_ADDR:
    680    case MM_ICACHE_DATA:
    681        /* do nothing */
    682	break;
    683    case MM_ITLB_ADDR:
    684        ret = cpu_sh4_read_mmaped_itlb_addr(&s->cpu->env, addr);
    685        break;
    686    case MM_ITLB_DATA:
    687        ret = cpu_sh4_read_mmaped_itlb_data(&s->cpu->env, addr);
    688        break;
    689    case MM_OCACHE_ADDR:
    690    case MM_OCACHE_DATA:
    691        /* do nothing */
    692	break;
    693    case MM_UTLB_ADDR:
    694        ret = cpu_sh4_read_mmaped_utlb_addr(&s->cpu->env, addr);
    695        break;
    696    case MM_UTLB_DATA:
    697        ret = cpu_sh4_read_mmaped_utlb_data(&s->cpu->env, addr);
    698        break;
    699    default:
    700        abort();
    701    }
    702
    703    return ret;
    704}
    705
    706static void invalid_write(void *opaque, hwaddr addr,
    707                          uint64_t mem_value)
    708{
    709    abort();
    710}
    711
    712static void sh7750_mmct_write(void *opaque, hwaddr addr,
    713                              uint64_t mem_value, unsigned size)
    714{
    715    SH7750State *s = opaque;
    716
    717    if (size != 4) {
    718        invalid_write(opaque, addr, mem_value);
    719    }
    720
    721    switch (MM_REGION_TYPE(addr)) {
    722    case MM_ICACHE_ADDR:
    723    case MM_ICACHE_DATA:
    724        /* do nothing */
    725	break;
    726    case MM_ITLB_ADDR:
    727        cpu_sh4_write_mmaped_itlb_addr(&s->cpu->env, addr, mem_value);
    728        break;
    729    case MM_ITLB_DATA:
    730        cpu_sh4_write_mmaped_itlb_data(&s->cpu->env, addr, mem_value);
    731        abort();
    732	break;
    733    case MM_OCACHE_ADDR:
    734    case MM_OCACHE_DATA:
    735        /* do nothing */
    736	break;
    737    case MM_UTLB_ADDR:
    738        cpu_sh4_write_mmaped_utlb_addr(&s->cpu->env, addr, mem_value);
    739	break;
    740    case MM_UTLB_DATA:
    741        cpu_sh4_write_mmaped_utlb_data(&s->cpu->env, addr, mem_value);
    742	break;
    743    default:
    744        abort();
    745	break;
    746    }
    747}
    748
    749static const MemoryRegionOps sh7750_mmct_ops = {
    750    .read = sh7750_mmct_read,
    751    .write = sh7750_mmct_write,
    752    .endianness = DEVICE_NATIVE_ENDIAN,
    753};
    754
    755SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem)
    756{
    757    SH7750State *s;
    758
    759    s = g_malloc0(sizeof(SH7750State));
    760    s->cpu = cpu;
    761    s->periph_freq = 60000000;	/* 60MHz */
    762    memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s,
    763                          "memory", 0x1fc01000);
    764
    765    memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0",
    766                             &s->iomem, 0x1f000000, 0x1000);
    767    memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0);
    768
    769    memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0",
    770                             &s->iomem, 0x1f000000, 0x1000);
    771    memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0);
    772
    773    memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8",
    774                             &s->iomem, 0x1f800000, 0x1000);
    775    memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8);
    776
    777    memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8",
    778                             &s->iomem, 0x1f800000, 0x1000);
    779    memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8);
    780
    781    memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc",
    782                             &s->iomem, 0x1fc00000, 0x1000);
    783    memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc);
    784
    785    memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc",
    786                             &s->iomem, 0x1fc00000, 0x1000);
    787    memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc);
    788
    789    memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s,
    790                          "cache-and-tlb", 0x08000000);
    791    memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem);
    792
    793    sh_intc_init(sysmem, &s->intc, NR_SOURCES,
    794		 _INTC_ARRAY(mask_registers),
    795		 _INTC_ARRAY(prio_registers));
    796
    797    sh_intc_register_sources(&s->intc,
    798			     _INTC_ARRAY(vectors),
    799			     _INTC_ARRAY(groups));
    800
    801    cpu->env.intc_handle = &s->intc;
    802
    803    sh_serial_init(sysmem, 0x1fe00000,
    804                   0, s->periph_freq, serial_hd(0),
    805                   s->intc.irqs[SCI1_ERI],
    806                   s->intc.irqs[SCI1_RXI],
    807                   s->intc.irqs[SCI1_TXI],
    808                   s->intc.irqs[SCI1_TEI],
    809                   NULL);
    810    sh_serial_init(sysmem, 0x1fe80000,
    811                   SH_SERIAL_FEAT_SCIF,
    812                   s->periph_freq, serial_hd(1),
    813                   s->intc.irqs[SCIF_ERI],
    814                   s->intc.irqs[SCIF_RXI],
    815                   s->intc.irqs[SCIF_TXI],
    816                   NULL,
    817                   s->intc.irqs[SCIF_BRI]);
    818
    819    tmu012_init(sysmem, 0x1fd80000,
    820		TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK,
    821		s->periph_freq,
    822		s->intc.irqs[TMU0],
    823		s->intc.irqs[TMU1],
    824		s->intc.irqs[TMU2_TUNI],
    825		s->intc.irqs[TMU2_TICPI]);
    826
    827    if (cpu->env.id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
    828        sh_intc_register_sources(&s->intc,
    829				 _INTC_ARRAY(vectors_dma4),
    830				 _INTC_ARRAY(groups_dma4));
    831    }
    832
    833    if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
    834        sh_intc_register_sources(&s->intc,
    835				 _INTC_ARRAY(vectors_dma8),
    836				 _INTC_ARRAY(groups_dma8));
    837    }
    838
    839    if (cpu->env.id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
    840        sh_intc_register_sources(&s->intc,
    841				 _INTC_ARRAY(vectors_tmu34),
    842				 NULL, 0);
    843        tmu012_init(sysmem, 0x1e100000, 0, s->periph_freq,
    844		    s->intc.irqs[TMU3],
    845		    s->intc.irqs[TMU4],
    846		    NULL, NULL);
    847    }
    848
    849    if (cpu->env.id & (SH_CPU_SH7751_ALL)) {
    850        sh_intc_register_sources(&s->intc,
    851				 _INTC_ARRAY(vectors_pci),
    852				 _INTC_ARRAY(groups_pci));
    853    }
    854
    855    if (cpu->env.id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
    856        sh_intc_register_sources(&s->intc,
    857				 _INTC_ARRAY(vectors_irlm),
    858				 NULL, 0);
    859    }
    860
    861    sh_intc_register_sources(&s->intc,
    862				_INTC_ARRAY(vectors_irl),
    863				_INTC_ARRAY(groups_irl));
    864    return s;
    865}
    866
    867qemu_irq sh7750_irl(SH7750State *s)
    868{
    869    sh_intc_toggle_source(sh_intc_source(&s->intc, IRL), 1, 0); /* enable */
    870    return qemu_allocate_irq(sh_intc_set_irl, sh_intc_source(&s->intc, IRL), 0);
    871}