2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
12 #define IO_ADDR_MASK (addr_max - 1)
16 // allocate tables here to support multiple instances with different address range
17 if(wr_table == NULL) {
18 wr_table = (wr_bank_t *)calloc(addr_max, sizeof(wr_bank_t));
19 rd_table = (rd_bank_t *)calloc(addr_max, sizeof(rd_bank_t));
21 // vm->dummy must be generated first !
22 for(int i = 0; i < addr_max; i++) {
23 wr_table[i].dev = rd_table[i].dev = vm->dummy;
24 wr_table[i].addr = rd_table[i].addr = i;
35 void IO::write_io8(uint32_t addr, uint32_t data)
37 write_port8(addr, data, false);
40 uint32_t IO::read_io8(uint32_t addr)
42 return read_port8(addr, false);
45 void IO::write_io16(uint32_t addr, uint32_t data)
47 write_port16(addr, data, false);
50 uint32_t IO::read_io16(uint32_t addr)
52 return read_port16(addr, false);
55 void IO::write_io32(uint32_t addr, uint32_t data)
57 write_port32(addr, data, false);
60 uint32_t IO::read_io32(uint32_t addr)
62 return read_port32(addr, false);
65 void IO::write_io8w(uint32_t addr, uint32_t data, int* wait)
67 *wait = wr_table[addr & IO_ADDR_MASK].wait;
68 write_port8(addr, data, false);
71 uint32_t IO::read_io8w(uint32_t addr, int* wait)
73 *wait = rd_table[addr & IO_ADDR_MASK].wait;
74 return read_port8(addr, false);
77 void IO::write_io16w(uint32_t addr, uint32_t data, int* wait)
79 *wait = wr_table[addr & IO_ADDR_MASK].wait;
80 write_port16(addr, data, false);
83 uint32_t IO::read_io16w(uint32_t addr, int* wait)
85 *wait = rd_table[addr & IO_ADDR_MASK].wait;
86 return read_port16(addr, false);
89 void IO::write_io32w(uint32_t addr, uint32_t data, int* wait)
91 *wait = wr_table[addr & IO_ADDR_MASK].wait;
92 write_port32(addr, data, false);
95 uint32_t IO::read_io32w(uint32_t addr, int* wait)
97 *wait = rd_table[addr & IO_ADDR_MASK].wait;
98 return read_port32(addr, false);
101 void IO::write_dma_io8(uint32_t addr, uint32_t data)
103 write_port8(addr, data, true);
106 uint32_t IO::read_dma_io8(uint32_t addr)
108 return read_port8(addr, true);
111 void IO::write_dma_io16(uint32_t addr, uint32_t data)
113 write_port16(addr, data, true);
116 uint32_t IO::read_dma_io16(uint32_t addr)
118 return read_port16(addr, true);
121 void IO::write_dma_io32(uint32_t addr, uint32_t data)
123 write_port32(addr, data, true);
126 uint32_t IO::read_dma_io32(uint32_t addr)
128 return read_port32(addr, true);
131 void IO::write_port8(uint32_t addr, uint32_t data, bool is_dma)
133 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
134 uint32_t addr2 = haddr | wr_table[laddr].addr;
136 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
137 this->out_debug_log(_T("UNKNOWN:\t"));
139 this->out_debug_log(_T("%06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(cpu_index), addr, data);
141 if(wr_table[laddr].is_flipflop) {
142 rd_table[laddr].value = data & 0xff;
144 wr_table[laddr].dev->write_dma_io8(addr2, data & 0xff);
146 wr_table[laddr].dev->write_io8(addr2, data & 0xff);
150 uint32_t IO::read_port8(uint32_t addr, bool is_dma)
152 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
153 uint32_t addr2 = haddr | rd_table[laddr].addr;
154 uint32_t val = rd_table[laddr].value_registered ? rd_table[laddr].value : is_dma ? rd_table[laddr].dev->read_dma_io8(addr2) : rd_table[laddr].dev->read_io8(addr2);
156 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
157 this->out_debug_log(_T("UNKNOWN:\t"));
159 this->out_debug_log(_T("%06x\tIN8\t%04x = %02x\n"), get_cpu_pc(cpu_index), addr, val);
164 void IO::write_port16(uint32_t addr, uint32_t data, bool is_dma)
166 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
167 uint32_t addr2 = haddr | wr_table[laddr].addr;
169 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
170 this->out_debug_log(_T("UNKNOWN:\t"));
172 this->out_debug_log(_T("%06x\tOUT16\t%04x,%04x\n"), get_cpu_pc(cpu_index), addr, data);
174 if(wr_table[laddr].is_flipflop) {
175 rd_table[laddr].value = data & 0xffff;
177 wr_table[laddr].dev->write_dma_io16(addr2, data & 0xffff);
179 wr_table[laddr].dev->write_io16(addr2, data & 0xffff);
183 uint32_t IO::read_port16(uint32_t addr, bool is_dma)
185 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
186 uint32_t addr2 = haddr | rd_table[laddr].addr;
187 uint32_t val = rd_table[laddr].value_registered ? rd_table[laddr].value : is_dma ? rd_table[laddr].dev->read_dma_io16(addr2) : rd_table[laddr].dev->read_io16(addr2);
189 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
190 this->out_debug_log(_T("UNKNOWN:\t"));
192 this->out_debug_log(_T("%06x\tIN16\t%04x = %04x\n"), get_cpu_pc(cpu_index), addr, val);
197 void IO::write_port32(uint32_t addr, uint32_t data, bool is_dma)
199 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
200 uint32_t addr2 = haddr | wr_table[laddr].addr;
202 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
203 this->out_debug_log(_T("UNKNOWN:\t"));
205 this->out_debug_log(_T("%06x\tOUT32\t%04x,%08x\n"), get_cpu_pc(cpu_index), addr, data);
207 if(wr_table[laddr].is_flipflop) {
208 rd_table[laddr].value = data;
210 wr_table[laddr].dev->write_dma_io32(addr2, data);
212 wr_table[laddr].dev->write_io32(addr2, data);
216 uint32_t IO::read_port32(uint32_t addr, bool is_dma)
218 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
219 uint32_t addr2 = haddr | rd_table[laddr].addr;
220 uint32_t val = rd_table[laddr].value_registered ? rd_table[laddr].value : is_dma ? rd_table[laddr].dev->read_dma_io32(addr2) : rd_table[laddr].dev->read_io32(addr2);
222 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
223 this->out_debug_log(_T("UNKNOWN:\t"));
225 this->out_debug_log(_T("%06x\tIN32\t%04x = %08x\n"), get_cpu_pc(cpu_index), laddr | haddr, val);
232 void IO::set_iomap_single_r(uint32_t addr, DEVICE* device)
234 IO::initialize(); // subclass may overload initialize()
236 rd_table[addr & IO_ADDR_MASK].dev = device;
237 rd_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
240 void IO::set_iomap_single_w(uint32_t addr, DEVICE* device)
244 wr_table[addr & IO_ADDR_MASK].dev = device;
245 wr_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
248 void IO::set_iomap_single_rw(uint32_t addr, DEVICE* device)
250 set_iomap_single_r(addr, device);
251 set_iomap_single_w(addr, device);
254 void IO::set_iomap_alias_r(uint32_t addr, DEVICE* device, uint32_t alias)
258 rd_table[addr & IO_ADDR_MASK].dev = device;
259 rd_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
262 void IO::set_iomap_alias_w(uint32_t addr, DEVICE* device, uint32_t alias)
266 wr_table[addr & IO_ADDR_MASK].dev = device;
267 wr_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
270 void IO::set_iomap_alias_rw(uint32_t addr, DEVICE* device, uint32_t alias)
272 set_iomap_alias_r(addr, device, alias);
273 set_iomap_alias_w(addr, device, alias);
276 void IO::set_iomap_range_r(uint32_t s, uint32_t e, DEVICE* device)
280 for(uint32_t i = s; i <= e; i++) {
281 rd_table[i & IO_ADDR_MASK].dev = device;
282 rd_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
286 void IO::set_iomap_range_w(uint32_t s, uint32_t e, DEVICE* device)
290 for(uint32_t i = s; i <= e; i++) {
291 wr_table[i & IO_ADDR_MASK].dev = device;
292 wr_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
296 void IO::set_iomap_range_rw(uint32_t s, uint32_t e, DEVICE* device)
298 set_iomap_range_r(s, e, device);
299 set_iomap_range_w(s, e, device);
302 void IO::set_iovalue_single_r(uint32_t addr, uint32_t value)
306 rd_table[addr & IO_ADDR_MASK].value = value;
307 rd_table[addr & IO_ADDR_MASK].value_registered = true;
310 void IO::set_iovalue_range_r(uint32_t s, uint32_t e, uint32_t value)
314 for(uint32_t i = s; i <= e; i++) {
315 rd_table[i & IO_ADDR_MASK].value = value;
316 rd_table[i & IO_ADDR_MASK].value_registered = true;
320 void IO::set_flipflop_single_rw(uint32_t addr, uint32_t value)
324 wr_table[addr & IO_ADDR_MASK].is_flipflop = true;
325 rd_table[addr & IO_ADDR_MASK].value = value;
326 rd_table[addr & IO_ADDR_MASK].value_registered = true;
329 void IO::set_flipflop_range_rw(uint32_t s, uint32_t e, uint32_t value)
333 for(uint32_t i = s; i <= e; i++) {
334 wr_table[i & IO_ADDR_MASK].is_flipflop = true;
335 rd_table[i & IO_ADDR_MASK].value = value;
336 rd_table[i & IO_ADDR_MASK].value_registered = true;
340 void IO::set_iowait_single_r(uint32_t addr, int wait)
344 rd_table[addr & IO_ADDR_MASK].wait = wait;
347 void IO::set_iowait_single_w(uint32_t addr, int wait)
351 wr_table[addr & IO_ADDR_MASK].wait = wait;
354 void IO::set_iowait_single_rw(uint32_t addr, int wait)
356 set_iowait_single_r(addr, wait);
357 set_iowait_single_w(addr, wait);
360 void IO::set_iowait_range_r(uint32_t s, uint32_t e, int wait)
364 for(uint32_t i = s; i <= e; i++) {
365 rd_table[i & IO_ADDR_MASK].wait = wait;
369 void IO::set_iowait_range_w(uint32_t s, uint32_t e, int wait)
373 for(uint32_t i = s; i <= e; i++) {
374 wr_table[i & IO_ADDR_MASK].wait = wait;
378 void IO::set_iowait_range_rw(uint32_t s, uint32_t e, int wait)
380 set_iowait_range_r(s, e, wait);
381 set_iowait_range_w(s, e, wait);
384 #define STATE_VERSION 1
386 void IO::save_state(FILEIO* state_fio)
388 state_fio->FputUint32(STATE_VERSION);
389 state_fio->FputInt32(this_device_id);
391 for(int i = 0; i < addr_max; i++) {
392 state_fio->FputUint32(rd_table[i].value);
396 bool IO::load_state(FILEIO* state_fio)
398 if(state_fio->FgetUint32() != STATE_VERSION) {
401 if(state_fio->FgetInt32() != this_device_id) {
404 for(int i = 0; i < addr_max; i++) {
405 rd_table[i].value = state_fio->FgetUint32();