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;
36 void IO::write_io8(uint32_t addr, uint32_t data)
38 write_port8(addr, data, false);
41 uint32_t IO::read_io8(uint32_t addr)
43 return read_port8(addr, false);
46 void IO::write_io16(uint32_t addr, uint32_t data)
48 write_port16(addr, data, false);
51 uint32_t IO::read_io16(uint32_t addr)
53 return read_port16(addr, false);
56 void IO::write_io32(uint32_t addr, uint32_t data)
58 write_port32(addr, data, false);
61 uint32_t IO::read_io32(uint32_t addr)
63 return read_port32(addr, false);
66 void IO::write_io8w(uint32_t addr, uint32_t data, int* wait)
68 *wait = wr_table[addr & IO_ADDR_MASK].wait;
69 write_port8(addr, data, false);
72 uint32_t IO::read_io8w(uint32_t addr, int* wait)
74 *wait = rd_table[addr & IO_ADDR_MASK].wait;
75 return read_port8(addr, false);
78 void IO::write_io16w(uint32_t addr, uint32_t data, int* wait)
80 *wait = wr_table[addr & IO_ADDR_MASK].wait;
81 write_port16(addr, data, false);
84 uint32_t IO::read_io16w(uint32_t addr, int* wait)
86 *wait = rd_table[addr & IO_ADDR_MASK].wait;
87 return read_port16(addr, false);
90 void IO::write_io32w(uint32_t addr, uint32_t data, int* wait)
92 *wait = wr_table[addr & IO_ADDR_MASK].wait;
93 write_port32(addr, data, false);
96 uint32_t IO::read_io32w(uint32_t addr, int* wait)
98 *wait = rd_table[addr & IO_ADDR_MASK].wait;
99 return read_port32(addr, false);
102 void IO::write_dma_io8(uint32_t addr, uint32_t data)
104 write_port8(addr, data, true);
107 uint32_t IO::read_dma_io8(uint32_t addr)
109 return read_port8(addr, true);
112 void IO::write_dma_io16(uint32_t addr, uint32_t data)
114 write_port16(addr, data, true);
117 uint32_t IO::read_dma_io16(uint32_t addr)
119 return read_port16(addr, true);
122 void IO::write_dma_io32(uint32_t addr, uint32_t data)
124 write_port32(addr, data, true);
127 uint32_t IO::read_dma_io32(uint32_t addr)
129 return read_port32(addr, true);
132 void IO::write_port8(uint32_t addr, uint32_t data, bool is_dma)
134 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
135 uint32_t addr2 = haddr | wr_table[laddr].addr;
137 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
138 this->out_debug_log(_T("UNKNOWN:\t"));
140 this->out_debug_log(_T("%06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(cpu_index), addr, data & 0xff);
142 if(wr_table[laddr].is_flipflop) {
143 rd_table[laddr].value = data & 0xff;
145 wr_table[laddr].dev->write_dma_io8(addr2, data & 0xff);
147 wr_table[laddr].dev->write_io8(addr2, data & 0xff);
151 uint32_t IO::read_port8(uint32_t addr, bool is_dma)
153 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
154 uint32_t addr2 = haddr | rd_table[laddr].addr;
155 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);
157 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
158 this->out_debug_log(_T("UNKNOWN:\t"));
160 this->out_debug_log(_T("%06x\tIN8\t%04x = %02x\n"), get_cpu_pc(cpu_index), addr, val & 0xff);
165 void IO::write_port16(uint32_t addr, uint32_t data, bool is_dma)
167 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
168 uint32_t addr2 = haddr | wr_table[laddr].addr;
170 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
171 this->out_debug_log(_T("UNKNOWN:\t"));
173 this->out_debug_log(_T("%06x\tOUT16\t%04x,%04x\n"), get_cpu_pc(cpu_index), addr, data & 0xffff);
175 if(wr_table[laddr].is_flipflop) {
176 rd_table[laddr].value = data & 0xffff;
178 wr_table[laddr].dev->write_dma_io16(addr2, data & 0xffff);
180 wr_table[laddr].dev->write_io16(addr2, data & 0xffff);
184 uint32_t IO::read_port16(uint32_t addr, bool is_dma)
186 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
187 uint32_t addr2 = haddr | rd_table[laddr].addr;
188 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);
190 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
191 this->out_debug_log(_T("UNKNOWN:\t"));
193 this->out_debug_log(_T("%06x\tIN16\t%04x = %04x\n"), get_cpu_pc(cpu_index), addr, val & 0xffff);
198 void IO::write_port32(uint32_t addr, uint32_t data, bool is_dma)
200 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
201 uint32_t addr2 = haddr | wr_table[laddr].addr;
203 if(!wr_table[laddr].dev->this_device_id && !wr_table[laddr].is_flipflop) {
204 this->out_debug_log(_T("UNKNOWN:\t"));
206 this->out_debug_log(_T("%06x\tOUT32\t%04x,%08x\n"), get_cpu_pc(cpu_index), addr, data);
208 if(wr_table[laddr].is_flipflop) {
209 rd_table[laddr].value = data;
211 wr_table[laddr].dev->write_dma_io32(addr2, data);
213 wr_table[laddr].dev->write_io32(addr2, data);
217 uint32_t IO::read_port32(uint32_t addr, bool is_dma)
219 uint32_t laddr = addr & IO_ADDR_MASK, haddr = addr & ~IO_ADDR_MASK;
220 uint32_t addr2 = haddr | rd_table[laddr].addr;
221 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);
223 if(!rd_table[laddr].dev->this_device_id && !rd_table[laddr].value_registered) {
224 this->out_debug_log(_T("UNKNOWN:\t"));
226 this->out_debug_log(_T("%06x\tIN32\t%04x = %08x\n"), get_cpu_pc(cpu_index), laddr | haddr, val);
233 void IO::set_iomap_single_r(uint32_t addr, DEVICE* device)
235 IO::initialize(); // subclass may overload initialize()
237 rd_table[addr & IO_ADDR_MASK].dev = device;
238 rd_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
241 void IO::set_iomap_single_w(uint32_t addr, DEVICE* device)
245 wr_table[addr & IO_ADDR_MASK].dev = device;
246 wr_table[addr & IO_ADDR_MASK].addr = addr & IO_ADDR_MASK;
249 void IO::set_iomap_single_rw(uint32_t addr, DEVICE* device)
251 set_iomap_single_r(addr, device);
252 set_iomap_single_w(addr, device);
255 void IO::set_iomap_alias_r(uint32_t addr, DEVICE* device, uint32_t alias)
259 rd_table[addr & IO_ADDR_MASK].dev = device;
260 rd_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
263 void IO::set_iomap_alias_w(uint32_t addr, DEVICE* device, uint32_t alias)
267 wr_table[addr & IO_ADDR_MASK].dev = device;
268 wr_table[addr & IO_ADDR_MASK].addr = alias & IO_ADDR_MASK;
271 void IO::set_iomap_alias_rw(uint32_t addr, DEVICE* device, uint32_t alias)
273 set_iomap_alias_r(addr, device, alias);
274 set_iomap_alias_w(addr, device, alias);
277 void IO::set_iomap_range_r(uint32_t s, uint32_t e, DEVICE* device)
281 for(uint32_t i = s; i <= e; i++) {
282 rd_table[i & IO_ADDR_MASK].dev = device;
283 rd_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
287 void IO::set_iomap_range_w(uint32_t s, uint32_t e, DEVICE* device)
291 for(uint32_t i = s; i <= e; i++) {
292 wr_table[i & IO_ADDR_MASK].dev = device;
293 wr_table[i & IO_ADDR_MASK].addr = i & IO_ADDR_MASK;
297 void IO::set_iomap_range_rw(uint32_t s, uint32_t e, DEVICE* device)
299 set_iomap_range_r(s, e, device);
300 set_iomap_range_w(s, e, device);
303 void IO::set_iovalue_single_r(uint32_t addr, uint32_t value)
307 rd_table[addr & IO_ADDR_MASK].value = value;
308 rd_table[addr & IO_ADDR_MASK].value_registered = true;
311 void IO::set_iovalue_range_r(uint32_t s, uint32_t e, uint32_t value)
315 for(uint32_t i = s; i <= e; i++) {
316 rd_table[i & IO_ADDR_MASK].value = value;
317 rd_table[i & IO_ADDR_MASK].value_registered = true;
321 void IO::set_flipflop_single_rw(uint32_t addr, uint32_t value)
325 wr_table[addr & IO_ADDR_MASK].is_flipflop = true;
326 rd_table[addr & IO_ADDR_MASK].value = value;
327 rd_table[addr & IO_ADDR_MASK].value_registered = true;
330 void IO::set_flipflop_range_rw(uint32_t s, uint32_t e, uint32_t value)
334 for(uint32_t i = s; i <= e; i++) {
335 wr_table[i & IO_ADDR_MASK].is_flipflop = true;
336 rd_table[i & IO_ADDR_MASK].value = value;
337 rd_table[i & IO_ADDR_MASK].value_registered = true;
341 void IO::set_iowait_single_r(uint32_t addr, int wait)
345 rd_table[addr & IO_ADDR_MASK].wait = wait;
348 void IO::set_iowait_single_w(uint32_t addr, int wait)
352 wr_table[addr & IO_ADDR_MASK].wait = wait;
355 void IO::set_iowait_single_rw(uint32_t addr, int wait)
357 set_iowait_single_r(addr, wait);
358 set_iowait_single_w(addr, wait);
361 void IO::set_iowait_range_r(uint32_t s, uint32_t e, int wait)
365 for(uint32_t i = s; i <= e; i++) {
366 rd_table[i & IO_ADDR_MASK].wait = wait;
370 void IO::set_iowait_range_w(uint32_t s, uint32_t e, int wait)
374 for(uint32_t i = s; i <= e; i++) {
375 wr_table[i & IO_ADDR_MASK].wait = wait;
379 void IO::set_iowait_range_rw(uint32_t s, uint32_t e, int wait)
381 set_iowait_range_r(s, e, wait);
382 set_iowait_range_w(s, e, wait);
385 #define STATE_VERSION 3
387 #include "../statesub.h"
389 void IO::decl_state()
391 enter_decl_state(STATE_VERSION);
393 // for(int i = 0; i < addr_max; i++) {
394 // Is comment outing right? (^_^; 20180630 K.O
396 // DECL_STATE_ENTRY_UINT32_MEMBER((rd_table[i].addr), i);
397 // DECL_STATE_ENTRY_INT32_MEMBER((rd_table[i].wait), i);
398 // DECL_STATE_ENTRY_BOOL_MEMBER((rd_table[i].value_registered), i);
399 // DECL_STATE_ENTRY_UINT32_MEMBER((rd_table[i].value), i);
401 // DECL_STATE_ENTRY_UINT32_MEMBER((wr_table[i].addr), i);
402 // DECL_STATE_ENTRY_INT32_MEMBER((wr_table[i].wait), i);
403 // DECL_STATE_ENTRY_BOOL_MEMBER((wr_table[i].is_flipflop), i);
405 DECL_STATE_ENTRY_UINT32_STRIDE((rd_table[0].value), addr_max, sizeof(rd_bank_t));
408 void IO::save_state(FILEIO* state_fio)
410 if(state_entry != NULL) {
411 state_entry->save_state(state_fio);
413 //state_fio->FputUint32(STATE_VERSION);
414 //state_fio->FputInt32(this_device_id);
416 //for(int i = 0; i < addr_max; i++) {
417 // state_fio->FputUint32(rd_table[i].value);
421 bool IO::load_state(FILEIO* state_fio)
424 if(state_entry != NULL) {
425 mb = state_entry->load_state(state_fio);
427 if(!mb) return false;
428 //if(state_fio->FgetUint32() != STATE_VERSION) {
431 //if(state_fio->FgetInt32() != this_device_id) {
434 //for(int i = 0; i < addr_max; i++) {
435 // rd_table[i].value = state_fio->FgetUint32();