1 #include "port.h"
2 #include "cpu.h"
3 #include "schedule.h"
4 #include "debug/debug.h"
5 
6 #define PORT_READ_DELAY  2
7 #define PORT_WRITE_DELAY 4
8 
9 /* Global APB state */
10 eZ80portrange_t port_map[0x10];
11 
12 #define port_range(a) (((a)>>12)&0xF) /* converts an address to a port range 0x0-0xF */
13 
14 static const uint32_t port_mirrors[0x10] = {0xFF,0xFF,0xFF,0x1FF,0xFFF,0xFF,0x1F,0xFF,0x7F,0xFFF,0x7F,0xFFF,0xFF,0x7F,0x7F,0xFFF};
15 
port_read(uint16_t address,uint8_t loc,bool peek)16 static uint8_t port_read(uint16_t address, uint8_t loc, bool peek) {
17     return port_map[loc].read(address & port_mirrors[loc], peek);
18 }
port_peek_byte(uint16_t address)19 uint8_t port_peek_byte(uint16_t address) {
20     return port_read(address, port_range(address), true);
21 }
port_read_byte(uint16_t address)22 uint8_t port_read_byte(uint16_t address) {
23     uint8_t port_loc = port_range(address);
24     uint8_t value;
25     static const uint8_t port_read_cycles[0x10] = {2,2,2,4,3,3,3,3,3,3,3,3,3,3,3,3};
26 
27 #ifdef DEBUG_SUPPORT
28     if (debug.port[address] & DBG_MASK_PORT_READ) {
29         debug_open(DBG_PORT_READ, address);
30     }
31 #endif
32 
33     cpu.cycles += PORT_READ_DELAY;
34     sched_process_pending_events(); /* make io ports consistent with mid-instruction state */
35     value = port_read(address, port_loc, false);
36     cpu.cycles += port_read_cycles[port_loc] - PORT_READ_DELAY;
37     return value;
38 }
39 
port_write(uint16_t address,uint8_t loc,uint8_t value,bool peek)40 static void port_write(uint16_t address, uint8_t loc, uint8_t value, bool peek) {
41     port_map[loc].write(address & port_mirrors[loc], value, peek);
42 }
port_poke_byte(uint16_t address,uint8_t value)43 void port_poke_byte(uint16_t address, uint8_t value) {
44     port_write(address, port_range(address), value, true);
45 }
port_write_byte(uint16_t address,uint8_t value)46 void port_write_byte(uint16_t address, uint8_t value) {
47     uint8_t port_loc = port_range(address);
48     static const uint8_t port_write_cycles[0x10] = {2,2,2,4,2,3,3,3,3,3,3,3,3,3,3,3};
49 
50 #ifdef DEBUG_SUPPORT
51     if (debug.port[address] & (DBG_MASK_PORT_FREEZE | DBG_MASK_PORT_WRITE)) {
52         if (debug.port[address] & DBG_MASK_PORT_WRITE) {
53             debug_open(DBG_PORT_WRITE, address);
54         }
55         if (debug.port[address] & DBG_MASK_PORT_FREEZE) {
56             return;
57         }
58     }
59 #endif
60 
61     cpu.cycles += PORT_WRITE_DELAY;
62     sched_process_pending_events(); /* make io ports consistent with mid-instruction state */
63     port_write(address, port_loc, value, false);
64     cpu.cycles -= PORT_WRITE_DELAY - port_write_cycles[port_loc];
65 }
66