+static CPUWriteMemoryFunc *watch_mem_write[3] = {
+ watch_mem_writeb,
+ watch_mem_writew,
+ watch_mem_writel,
+};
+#endif
+
+static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
+ unsigned int len)
+{
+ CPUReadMemoryFunc **mem_read;
+ uint32_t ret;
+ unsigned int idx;
+
+ idx = SUBPAGE_IDX(addr - mmio->base);
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
+ mmio, len, addr, idx);
+#endif
+ mem_read = mmio->mem_read[idx];
+ ret = (*mem_read[len])(mmio->opaque[idx], addr);
+
+ return ret;
+}
+
+static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
+ uint32_t value, unsigned int len)
+{
+ CPUWriteMemoryFunc **mem_write;
+ unsigned int idx;
+
+ idx = SUBPAGE_IDX(addr - mmio->base);
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
+ mmio, len, addr, idx, value);
+#endif
+ mem_write = mmio->mem_write[idx];
+ (*mem_write[len])(mmio->opaque[idx], addr, value);
+}
+
+static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+ return subpage_readlen(opaque, addr, 0);
+}
+
+static void subpage_writeb (void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
+#endif
+ subpage_writelen(opaque, addr, value, 0);
+}
+
+static uint32_t subpage_readw (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+ return subpage_readlen(opaque, addr, 1);
+}
+
+static void subpage_writew (void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
+#endif
+ subpage_writelen(opaque, addr, value, 1);
+}
+
+static uint32_t subpage_readl (void *opaque, target_phys_addr_t addr)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+#endif
+
+ return subpage_readlen(opaque, addr, 2);
+}
+
+static void subpage_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t value)
+{
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: addr " TARGET_FMT_plx " val %08x\n", __func__, addr, value);
+#endif
+ subpage_writelen(opaque, addr, value, 2);
+}
+
+static CPUReadMemoryFunc *subpage_read[] = {
+ &subpage_readb,
+ &subpage_readw,
+ &subpage_readl,
+};
+
+static CPUWriteMemoryFunc *subpage_write[] = {
+ &subpage_writeb,
+ &subpage_writew,
+ &subpage_writel,
+};
+
+static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
+ int memory)
+{
+ int idx, eidx;
+
+ if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
+ return -1;
+ idx = SUBPAGE_IDX(start);
+ eidx = SUBPAGE_IDX(end);
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %d\n", __func__,
+ mmio, start, end, idx, eidx, memory);
+#endif
+ memory >>= IO_MEM_SHIFT;
+ for (; idx <= eidx; idx++) {
+ mmio->mem_read[idx] = io_mem_read[memory];
+ mmio->mem_write[idx] = io_mem_write[memory];
+ mmio->opaque[idx] = io_mem_opaque[memory];
+ }
+
+ return 0;
+}
+
+static void *subpage_init (target_phys_addr_t base, uint32_t *phys,
+ int orig_memory)
+{
+ subpage_t *mmio;
+ int subpage_memory;
+
+ mmio = qemu_mallocz(sizeof(subpage_t));
+ if (mmio != NULL) {
+ mmio->base = base;
+ subpage_memory = cpu_register_io_memory(0, subpage_read, subpage_write, mmio);
+#if defined(DEBUG_SUBPAGE)
+ printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
+ mmio, base, TARGET_PAGE_SIZE, subpage_memory);
+#endif
+ *phys = subpage_memory | IO_MEM_SUBPAGE;
+ subpage_register(mmio, 0, TARGET_PAGE_SIZE - 1, orig_memory);
+ }
+
+ return mmio;
+}
+