Support for registering address space only for some access widths

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3879 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
blueswir1 2008-01-01 16:57:19 +00:00
parent 0b09be2b2f
commit 4254fab8f9
2 changed files with 22 additions and 18 deletions

View file

@ -821,6 +821,7 @@ extern uint8_t *phys_ram_dirty;
the physical address */ the physical address */
#define IO_MEM_ROMD (1) #define IO_MEM_ROMD (1)
#define IO_MEM_SUBPAGE (2) #define IO_MEM_SUBPAGE (2)
#define IO_MEM_SUBWIDTH (4)
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);

39
exec.c
View file

@ -163,8 +163,8 @@ static int tb_phys_invalidate_count;
#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK) #define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
typedef struct subpage_t { typedef struct subpage_t {
target_phys_addr_t base; target_phys_addr_t base;
CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE]; CPUReadMemoryFunc *mem_read[TARGET_PAGE_SIZE][4];
CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE]; CPUWriteMemoryFunc *mem_write[TARGET_PAGE_SIZE][4];
void *opaque[TARGET_PAGE_SIZE]; void *opaque[TARGET_PAGE_SIZE];
} subpage_t; } subpage_t;
@ -2025,7 +2025,7 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2, CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, end_addr2,
need_subpage); need_subpage);
if (need_subpage) { if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
if (!(orig_memory & IO_MEM_SUBPAGE)) { if (!(orig_memory & IO_MEM_SUBPAGE)) {
subpage = subpage_init((addr & TARGET_PAGE_MASK), subpage = subpage_init((addr & TARGET_PAGE_MASK),
&p->phys_offset, orig_memory); &p->phys_offset, orig_memory);
@ -2053,7 +2053,7 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr, CHECK_SUBPAGE(addr, start_addr, start_addr2, end_addr,
end_addr2, need_subpage); end_addr2, need_subpage);
if (need_subpage) { if (need_subpage || phys_offset & IO_MEM_SUBWIDTH) {
subpage = subpage_init((addr & TARGET_PAGE_MASK), subpage = subpage_init((addr & TARGET_PAGE_MASK),
&p->phys_offset, IO_MEM_UNASSIGNED); &p->phys_offset, IO_MEM_UNASSIGNED);
subpage_register(subpage, start_addr2, end_addr2, subpage_register(subpage, start_addr2, end_addr2,
@ -2308,7 +2308,6 @@ static CPUWriteMemoryFunc *watch_mem_write[3] = {
static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr, static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr,
unsigned int len) unsigned int len)
{ {
CPUReadMemoryFunc **mem_read;
uint32_t ret; uint32_t ret;
unsigned int idx; unsigned int idx;
@ -2317,8 +2316,7 @@ static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr
printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__, printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d\n", __func__,
mmio, len, addr, idx); mmio, len, addr, idx);
#endif #endif
mem_read = mmio->mem_read[idx]; ret = (*mmio->mem_read[idx][len])(mmio->opaque[idx], addr);
ret = (*mem_read[len])(mmio->opaque[idx], addr);
return ret; return ret;
} }
@ -2326,7 +2324,6 @@ static inline uint32_t subpage_readlen (subpage_t *mmio, target_phys_addr_t addr
static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr, static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
uint32_t value, unsigned int len) uint32_t value, unsigned int len)
{ {
CPUWriteMemoryFunc **mem_write;
unsigned int idx; unsigned int idx;
idx = SUBPAGE_IDX(addr - mmio->base); idx = SUBPAGE_IDX(addr - mmio->base);
@ -2334,8 +2331,7 @@ static inline void subpage_writelen (subpage_t *mmio, target_phys_addr_t addr,
printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__, printf("%s: subpage %p len %d addr " TARGET_FMT_plx " idx %d value %08x\n", __func__,
mmio, len, addr, idx, value); mmio, len, addr, idx, value);
#endif #endif
mem_write = mmio->mem_write[idx]; (*mmio->mem_write[idx][len])(mmio->opaque[idx], addr, value);
(*mem_write[len])(mmio->opaque[idx], addr, value);
} }
static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr) static uint32_t subpage_readb (void *opaque, target_phys_addr_t addr)
@ -2408,6 +2404,7 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
int memory) int memory)
{ {
int idx, eidx; int idx, eidx;
unsigned int i;
if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE) if (start >= TARGET_PAGE_SIZE || end >= TARGET_PAGE_SIZE)
return -1; return -1;
@ -2419,8 +2416,12 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
#endif #endif
memory >>= IO_MEM_SHIFT; memory >>= IO_MEM_SHIFT;
for (; idx <= eidx; idx++) { for (; idx <= eidx; idx++) {
mmio->mem_read[idx] = io_mem_read[memory]; for (i = 0; i < 4; i++) {
mmio->mem_write[idx] = io_mem_write[memory]; if (io_mem_read[memory][i])
mmio->mem_read[idx][i] = io_mem_read[memory][i];
if (io_mem_write[memory][i])
mmio->mem_write[idx][i] = io_mem_write[memory][i];
}
mmio->opaque[idx] = io_mem_opaque[memory]; mmio->opaque[idx] = io_mem_opaque[memory];
} }
@ -2466,16 +2467,16 @@ static void io_mem_init(void)
/* mem_read and mem_write are arrays of functions containing the /* mem_read and mem_write are arrays of functions containing the
function to access byte (index 0), word (index 1) and dword (index function to access byte (index 0), word (index 1) and dword (index
2). All functions must be supplied. If io_index is non zero, the 2). If io_index is non zero, the corresponding io zone is
corresponding io zone is modified. If it is zero, a new io zone is modified. If it is zero, a new io zone is allocated. The return
allocated. The return value can be used with value can be used with cpu_register_physical_memory(). (-1) is
cpu_register_physical_memory(). (-1) is returned if error. */ returned if error. */
int cpu_register_io_memory(int io_index, int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read, CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write, CPUWriteMemoryFunc **mem_write,
void *opaque) void *opaque)
{ {
int i; int i, subwidth = 0;
if (io_index <= 0) { if (io_index <= 0) {
if (io_mem_nb >= IO_MEM_NB_ENTRIES) if (io_mem_nb >= IO_MEM_NB_ENTRIES)
@ -2487,11 +2488,13 @@ int cpu_register_io_memory(int io_index,
} }
for(i = 0;i < 3; i++) { for(i = 0;i < 3; i++) {
if (!mem_read[i] || !mem_write[i])
subwidth = IO_MEM_SUBWIDTH;
io_mem_read[io_index][i] = mem_read[i]; io_mem_read[io_index][i] = mem_read[i];
io_mem_write[io_index][i] = mem_write[i]; io_mem_write[io_index][i] = mem_write[i];
} }
io_mem_opaque[io_index] = opaque; io_mem_opaque[io_index] = opaque;
return io_index << IO_MEM_SHIFT; return (io_index << IO_MEM_SHIFT) | subwidth;
} }
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index) CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)