etrax: Don't keep the passed irq pointer.
[qemu] / hw / armv7m.c
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 "sysbus.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     DeviceState *nvic;
144     /* FIXME: make this local state.  */
145     static qemu_irq pic[64];
146     qemu_irq *cpu_pic;
147     uint32_t pc;
148     int image_size;
149     uint64_t entry;
150     uint64_t lowaddr;
151     int i;
152
153     flash_size *= 1024;
154     sram_size *= 1024;
155
156     if (!cpu_model)
157         cpu_model = "cortex-m3";
158     env = cpu_init(cpu_model);
159     if (!env) {
160         fprintf(stderr, "Unable to find CPU definition\n");
161         exit(1);
162     }
163
164 #if 0
165     /* > 32Mb SRAM gets complicated because it overlaps the bitband area.
166        We don't have proper commandline options, so allocate half of memory
167        as SRAM, up to a maximum of 32Mb, and the rest as code.  */
168     if (ram_size > (512 + 32) * 1024 * 1024)
169         ram_size = (512 + 32) * 1024 * 1024;
170     sram_size = (ram_size / 2) & TARGET_PAGE_MASK;
171     if (sram_size > 32 * 1024 * 1024)
172         sram_size = 32 * 1024 * 1024;
173     code_size = ram_size - sram_size;
174 #endif
175
176     /* Flash programming is done via the SCU, so pretend it is ROM.  */
177     cpu_register_physical_memory(0, flash_size,
178                                  qemu_ram_alloc(flash_size) | IO_MEM_ROM);
179     cpu_register_physical_memory(0x20000000, sram_size,
180                                  qemu_ram_alloc(sram_size) | IO_MEM_RAM);
181     armv7m_bitband_init();
182
183     nvic = qdev_create(NULL, "armv7m_nvic");
184     qdev_set_prop_ptr(nvic, "cpu", env);
185     qdev_init(nvic);
186     cpu_pic = arm_pic_init_cpu(env);
187     sysbus_connect_irq(sysbus_from_qdev(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
188     for (i = 0; i < 64; i++) {
189         pic[i] = qdev_get_irq_sink(nvic, i);
190     }
191
192     image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
193     if (image_size < 0) {
194         image_size = load_image_targphys(kernel_filename, 0, flash_size);
195         lowaddr = 0;
196     }
197     if (image_size < 0) {
198         fprintf(stderr, "qemu: could not load kernel '%s'\n",
199                 kernel_filename);
200         exit(1);
201     }
202
203     /* If the image was loaded at address zero then assume it is a
204        regular ROM image and perform the normal CPU reset sequence.
205        Otherwise jump directly to the entry point.  */
206     if (lowaddr == 0) {
207         env->regs[13] = ldl_phys(0);
208         pc = ldl_phys(4);
209     } else {
210         pc = entry;
211     }
212     env->thumb = pc & 1;
213     env->regs[15] = pc & ~1;
214
215     /* Hack to map an additional page of ram at the top of the address
216        space.  This stops qemu complaining about executing code outside RAM
217        when returning from an exception.  */
218     cpu_register_physical_memory(0xfffff000, 0x1000,
219                                  qemu_ram_alloc(0x1000) | IO_MEM_RAM);
220
221     return pic;
222 }