symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/armv7m.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * ARMV7M System emulation.
       
     3  *
       
     4  * Copyright (c) 2006-2007 CodeSourcery.
       
     5  * Written by Paul Brook
       
     6  *
       
     7  * This code is licenced under the GPL.
       
     8  */
       
     9 
       
    10 #include "hw.h"
       
    11 #include "arm-misc.h"
       
    12 #include "sysemu.h"
       
    13 
       
    14 /* Bitbanded IO.  Each word corresponds to a single bit.  */
       
    15 
       
    16 /* Get the byte address of the real memory for a bitband acess.  */
       
    17 static inline uint32_t bitband_addr(void * opaque, uint32_t addr)
       
    18 {
       
    19     uint32_t res;
       
    20 
       
    21     res = *(uint32_t *)opaque;
       
    22     res |= (addr & 0x1ffffff) >> 5;
       
    23     return res;
       
    24 
       
    25 }
       
    26 
       
    27 static uint32_t bitband_readb(void *opaque, target_phys_addr_t offset)
       
    28 {
       
    29     uint8_t v;
       
    30     cpu_physical_memory_read(bitband_addr(opaque, offset), &v, 1);
       
    31     return (v & (1 << ((offset >> 2) & 7))) != 0;
       
    32 }
       
    33 
       
    34 static void bitband_writeb(void *opaque, target_phys_addr_t offset,
       
    35                            uint32_t value)
       
    36 {
       
    37     uint32_t addr;
       
    38     uint8_t mask;
       
    39     uint8_t v;
       
    40     addr = bitband_addr(opaque, offset);
       
    41     mask = (1 << ((offset >> 2) & 7));
       
    42     cpu_physical_memory_read(addr, &v, 1);
       
    43     if (value & 1)
       
    44         v |= mask;
       
    45     else
       
    46         v &= ~mask;
       
    47     cpu_physical_memory_write(addr, &v, 1);
       
    48 }
       
    49 
       
    50 static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset)
       
    51 {
       
    52     uint32_t addr;
       
    53     uint16_t mask;
       
    54     uint16_t v;
       
    55     addr = bitband_addr(opaque, offset) & ~1;
       
    56     mask = (1 << ((offset >> 2) & 15));
       
    57     mask = tswap16(mask);
       
    58     cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
       
    59     return (v & mask) != 0;
       
    60 }
       
    61 
       
    62 static void bitband_writew(void *opaque, target_phys_addr_t offset,
       
    63                            uint32_t value)
       
    64 {
       
    65     uint32_t addr;
       
    66     uint16_t mask;
       
    67     uint16_t v;
       
    68     addr = bitband_addr(opaque, offset) & ~1;
       
    69     mask = (1 << ((offset >> 2) & 15));
       
    70     mask = tswap16(mask);
       
    71     cpu_physical_memory_read(addr, (uint8_t *)&v, 2);
       
    72     if (value & 1)
       
    73         v |= mask;
       
    74     else
       
    75         v &= ~mask;
       
    76     cpu_physical_memory_write(addr, (uint8_t *)&v, 2);
       
    77 }
       
    78 
       
    79 static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset)
       
    80 {
       
    81     uint32_t addr;
       
    82     uint32_t mask;
       
    83     uint32_t v;
       
    84     addr = bitband_addr(opaque, offset) & ~3;
       
    85     mask = (1 << ((offset >> 2) & 31));
       
    86     mask = tswap32(mask);
       
    87     cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
       
    88     return (v & mask) != 0;
       
    89 }
       
    90 
       
    91 static void bitband_writel(void *opaque, target_phys_addr_t offset,
       
    92                            uint32_t value)
       
    93 {
       
    94     uint32_t addr;
       
    95     uint32_t mask;
       
    96     uint32_t v;
       
    97     addr = bitband_addr(opaque, offset) & ~3;
       
    98     mask = (1 << ((offset >> 2) & 31));
       
    99     mask = tswap32(mask);
       
   100     cpu_physical_memory_read(addr, (uint8_t *)&v, 4);
       
   101     if (value & 1)
       
   102         v |= mask;
       
   103     else
       
   104         v &= ~mask;
       
   105     cpu_physical_memory_write(addr, (uint8_t *)&v, 4);
       
   106 }
       
   107 
       
   108 static CPUReadMemoryFunc *bitband_readfn[] = {
       
   109    bitband_readb,
       
   110    bitband_readw,
       
   111    bitband_readl
       
   112 };
       
   113 
       
   114 static CPUWriteMemoryFunc *bitband_writefn[] = {
       
   115    bitband_writeb,
       
   116    bitband_writew,
       
   117    bitband_writel
       
   118 };
       
   119 
       
   120 static void armv7m_bitband_init(void)
       
   121 {
       
   122     int iomemtype;
       
   123     static uint32_t bitband1_offset = 0x20000000;
       
   124     static uint32_t bitband2_offset = 0x40000000;
       
   125 
       
   126     iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn,
       
   127                                        &bitband1_offset);
       
   128     cpu_register_physical_memory(0x22000000, 0x02000000, iomemtype);
       
   129     iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn,
       
   130                                        &bitband2_offset);
       
   131     cpu_register_physical_memory(0x42000000, 0x02000000, iomemtype);
       
   132 }
       
   133 
       
   134 /* Board init.  */
       
   135 /* Init CPU and memory for a v7-M based board.
       
   136    flash_size and sram_size are in kb.
       
   137    Returns the NVIC array.  */
       
   138 
       
   139 qemu_irq *armv7m_init(int flash_size, int sram_size,
       
   140                       const char *kernel_filename, const char *cpu_model)
       
   141 {
       
   142     CPUState *env;
       
   143     qemu_irq *pic;
       
   144     uint32_t pc;
       
   145     int image_size;
       
   146     uint64_t entry;
       
   147     uint64_t lowaddr;
       
   148 
       
   149     flash_size *= 1024;
       
   150     sram_size *= 1024;
       
   151 
       
   152     if (!cpu_model)
       
   153 	cpu_model = "cortex-m3";
       
   154     env = cpu_init(cpu_model);
       
   155     if (!env) {
       
   156         fprintf(stderr, "Unable to find CPU definition\n");
       
   157         exit(1);
       
   158     }
       
   159 
       
   160 #if 0
       
   161     /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
       
   162        We don't have proper commandline options, so allocate half of memory
       
   163        as SRAM, up to a maximum of 32Mb, and the rest as code.  */
       
   164     if (ram_size > (512 + 32) * 1024 * 1024)
       
   165         ram_size = (512 + 32) * 1024 * 1024;
       
   166     sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
       
   167     if (sram_size > 32 * 1024 * 1024)
       
   168         sram_size = 32 * 1024 * 1024;
       
   169     code_size = ram_size - sram_size;
       
   170 #endif
       
   171 
       
   172     /* Flash programming is done via the SCU, so pretend it is ROM.  */
       
   173     cpu_register_physical_memory(0, flash_size, IO_MEM_ROM);
       
   174     cpu_register_physical_memory(0x20000000, sram_size,
       
   175                                  flash_size + IO_MEM_RAM);
       
   176     armv7m_bitband_init();
       
   177 
       
   178     pic = armv7m_nvic_init(env);
       
   179 
       
   180     image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
       
   181     if (image_size < 0) {
       
   182         /* FIXME: This is broken if it spans multiple regions.  */
       
   183         image_size = load_image(kernel_filename, host_ram_addr(0));
       
   184 	lowaddr = 0;
       
   185     }
       
   186     if (image_size < 0) {
       
   187         fprintf(stderr, "qemu: could not load kernel '%s'\n",
       
   188                 kernel_filename);
       
   189         exit(1);
       
   190     }
       
   191 
       
   192     /* If the image was loaded at address zero then assume it is a
       
   193        regular ROM image and perform the normal CPU reset sequence.
       
   194        Otherwise jump directly to the entry point.  */
       
   195     if (lowaddr == 0) {
       
   196 	env->regs[13] = ldl_phys(0);
       
   197 	pc = ldl_phys(4);
       
   198     } else {
       
   199 	pc = entry;
       
   200     }
       
   201     env->thumb = pc & 1;
       
   202     env->regs[15] = pc & ~1;
       
   203 
       
   204     /* Hack to map an additional page of ram at the top of the address
       
   205        space.  This stops qemu complaining about executing code outside RAM
       
   206        when returning from an exception.  */
       
   207     cpu_register_physical_memory(0xfffff000, 0x1000, IO_MEM_RAM + ram_size);
       
   208 
       
   209     return pic;
       
   210 }