18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARMV7M System emulation.
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2006-2007 CodeSourcery.
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Written by Paul Brook
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This code is licenced under the GPL.
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1026b47fe632cf0de7962e79a1113d8a5d93459262David 'Digit' Turner#include "hw/sysbus.h"
1162fba4882dbb1bea4f69e0b543cb90acee84742fDavid 'Digit' Turner#include "hw/arm/arm.h"
1234c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitbanded IO.  Each word corresponds to a single bit.  */
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Get the byte address of the real memory for a bitband acess.  */
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline uint32_t bitband_addr(void * opaque, uint32_t addr)
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    res = *(uint32_t *)opaque;
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res |= (addr & 0x1ffffff) >> 5;
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t bitband_readb(void *opaque, hwaddr offset)
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t v;
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (v & (1 << ((offset >> 2) & 7))) != 0;
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void bitband_writeb(void *opaque, hwaddr offset,
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           uint32_t value)
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t mask;
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t v;
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = bitband_addr(opaque, offset);
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1 << ((offset >> 2) & 7));
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, &v, 1);
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (value & 1)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v |= mask;
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v &= ~mask;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_write(addr, &v, 1);
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
50bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t bitband_readw(void *opaque, hwaddr offset)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t mask;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t v;
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = bitband_addr(opaque, offset) & ~1;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1 << ((offset >> 2) & 15));
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = tswap16(mask);
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (v & mask) != 0;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void bitband_writew(void *opaque, hwaddr offset,
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           uint32_t value)
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t mask;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t v;
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = bitband_addr(opaque, offset) & ~1;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1 << ((offset >> 2) & 15));
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = tswap16(mask);
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (value & 1)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v |= mask;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v &= ~mask;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic uint32_t bitband_readl(void *opaque, hwaddr offset)
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t v;
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = bitband_addr(opaque, offset) & ~3;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1 << ((offset >> 2) & 31));
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = tswap32(mask);
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (v & mask) != 0;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91bcde1092aca184dbd7860078af020de7d1e4e22fDavid 'Digit' Turnerstatic void bitband_writel(void *opaque, hwaddr offset,
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           uint32_t value)
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t addr;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t v;
975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr = bitband_addr(opaque, offset) & ~3;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1 << ((offset >> 2) & 31));
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = tswap32(mask);
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (value & 1)
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v |= mask;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        v &= ~mask;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
108280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerstatic CPUReadMemoryFunc * const bitband_readfn[] = {
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_readb,
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_readw,
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_readl
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
114280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turnerstatic CPUWriteMemoryFunc * const bitband_writefn[] = {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_writeb,
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_writew,
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bitband_writel
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct {
1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SysBusDevice busdev;
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t base;
1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} BitBandState;
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bitband_init(SysBusDevice *dev)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BitBandState *s = FROM_SYSBUS(BitBandState, dev);
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int iomemtype;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->base = qdev_get_prop_int(&dev->qdev, "base", 0);
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    iomemtype = cpu_register_io_memory(bitband_readfn, bitband_writefn,
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                       &s->base);
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sysbus_init_mmio(dev, 0x02000000, iomemtype);
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void armv7m_bitband_init(void)
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DeviceState *dev;
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dev = qdev_create(NULL, "ARM,bitband-memory");
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qdev_set_prop_int(dev, "base", 0x20000000);
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qdev_init(dev);
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x22000000);
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    dev = qdev_create(NULL, "ARM,bitband-memory");
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qdev_set_prop_int(dev, "base", 0x40000000);
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qdev_init(dev);
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0x42000000);
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Board init.  */
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Init CPU and memory for a v7-M based board.
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   flash_size and sram_size are in kb.
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Returns the NVIC array.  */
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectqemu_irq *armv7m_init(int flash_size, int sram_size,
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      const char *kernel_filename, const char *cpu_model)
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
159e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    CPUOldState *env;
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DeviceState *nvic;
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* FIXME: make this local state.  */
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    static qemu_irq pic[64];
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_irq *cpu_pic;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t pc;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int image_size;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t entry;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t lowaddr;
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    flash_size *= 1024;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sram_size *= 1024;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!cpu_model)
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	cpu_model = "cortex-m3";
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = cpu_init(cpu_model);
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!env) {
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "Unable to find CPU definition\n");
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        exit(1);
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       We don't have proper commandline options, so allocate half of memory
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       as SRAM, up to a maximum of 32Mb, and the rest as code.  */
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ram_size > (512 + 32) * 1024 * 1024)
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ram_size = (512 + 32) * 1024 * 1024;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sram_size > 32 * 1024 * 1024)
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sram_size = 32 * 1024 * 1024;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    code_size = ram_size - sram_size;
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Flash programming is done via the SCU, so pretend it is ROM.  */
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_register_physical_memory(0, flash_size,
195280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                 qemu_ram_alloc(NULL, "armv7m.flash",
196280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                                flash_size) | IO_MEM_ROM);
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_register_physical_memory(0x20000000, sram_size,
198280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                 qemu_ram_alloc(NULL, "armv7m.sram",
199280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                                sram_size) | IO_MEM_RAM);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    armv7m_bitband_init();
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nvic = qdev_create(NULL, "armv7m_nvic");
2035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    env->nvic = nvic;
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qdev_init(nvic);
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_pic = arm_pic_init_cpu(env);
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < 64; i++) {
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        pic[i] = qdev_get_gpio_in(nvic, i);
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (image_size < 0) {
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        image_size = load_image_targphys(kernel_filename, 0, flash_size);
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	lowaddr = 0;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (image_size < 0) {
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "qemu: could not load kernel '%s'\n",
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                kernel_filename);
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        exit(1);
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* If the image was loaded at address zero then assume it is a
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       regular ROM image and perform the normal CPU reset sequence.
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       Otherwise jump directly to the entry point.  */
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (lowaddr == 0) {
2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	env->regs[13] = ldl_phys(0);
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	pc = ldl_phys(4);
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	pc = entry;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->thumb = pc & 1;
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[15] = pc & ~1;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Hack to map an additional page of ram at the top of the address
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       space.  This stops qemu complaining about executing code outside RAM
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       when returning from an exception.  */
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_register_physical_memory(0xfffff000, 0x1000,
238c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner                                 qemu_ram_alloc(NULL, "armv7m.hack",
239280afa072a7b829e581d884c2b3276530a6014b7David 'Digit' Turner                                                0x1000) | IO_MEM_RAM);
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return pic;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void armv7m_register_devices(void)
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sysbus_register_dev("ARM,bitband-memory", sizeof(BitBandState),
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        bitband_init);
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdevice_init(armv7m_register_devices)
250