diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 7b961961b..fd418abfb 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -98,8 +98,7 @@ static uint32_t *ovr_seg = NULL; static int prefetching = 1, completed = 1; static int in_rep = 0, repeating = 0; static int oldc, clear_lock = 0; -static int refresh = 0, takeint = 0; -static int cycdiff; +static int refresh = 0, cycdiff; /* Various things needed for 8087. */ @@ -254,7 +253,6 @@ static void wait(int c, int bus) { cycles -= c; - fetch_and_bus(c, bus); } @@ -279,17 +277,37 @@ sub_cycles(int c) #undef readmemq -/* Common read function. */ -static uint8_t -readmemb_common(uint32_t a) +static void +cpu_io(int bits, int out, uint16_t port) { - uint8_t ret; - - ret = read_mem_b(a); - - return ret; + if (out) { + wait(4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) + outw(port, AX); + else { + wait(4, 1); + outb(port++, AL); + outb(port, AH); + } + } else + outb(port, AL); + } else { + wait(4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) + AX = inw(port); + else { + wait(4, 1); + AL = inb(port++); + AH = inb(port); + } + } else + AL = inb(port); + } } + /* Reads a byte from the memory and advances the BIU. */ static uint8_t readmemb(uint32_t a) @@ -297,7 +315,7 @@ readmemb(uint32_t a) uint8_t ret; wait(4, 1); - ret = readmemb_common(a); + ret = read_mem_b(a); return ret; } @@ -310,35 +328,26 @@ readmembf(uint32_t a) uint8_t ret; a = cs + (a & 0xffff); - ret = readmemb_common(a); + ret = read_mem_b(a); return ret; } /* Reads a word from the memory and advances the BIU. */ -static uint16_t -readmemw_common(uint32_t s, uint16_t a) -{ - uint16_t ret; - - ret = readmemb_common(s + a); - ret |= readmemb_common(s + ((a + 1) & 0xffff)) << 8; - - return ret; -} - - static uint16_t readmemw(uint32_t s, uint16_t a) { uint16_t ret; + wait(4, 1); if (is8086 && !(a & 1)) + ret = read_mem_w(s + a); + else { wait(4, 1); - else - wait(8, 1); - ret = readmemw_common(s, a); + ret = read_mem_b(s + a); + ret |= read_mem_b(s + ((a + 1) & 0xffff)) << 8; + } return ret; } @@ -349,7 +358,7 @@ readmemwf(uint16_t a) { uint16_t ret; - ret = readmemw_common(cs, a & 0xffff); + ret = read_mem_w(cs + (a & 0xffff)); return ret; } @@ -389,22 +398,17 @@ readmemq(uint32_t s, uint16_t a) } -static void -writememb_common(uint32_t a, uint8_t v) -{ - write_mem_b(a, v); - - if ((a >= 0xf0000) && (a <= 0xfffff)) - last_addr = a & 0xffff; -} - - /* Writes a byte to the memory and advances the BIU. */ static void writememb(uint32_t s, uint32_t a, uint8_t v) { + uint32_t addr = s + a; + wait(4, 1); - writememb_common(s + a, v); + write_mem_b(addr, v); + + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; } @@ -412,12 +416,20 @@ writememb(uint32_t s, uint32_t a, uint8_t v) static void writememw(uint32_t s, uint32_t a, uint16_t v) { + uint32_t addr = s + a; + + wait(4, 1); if (is8086 && !(a & 1)) + write_mem_w(addr, v); + else { + write_mem_b(addr, v & 0xff); wait(4, 1); - else - wait(8, 1); - writememb_common(s + a, v & 0xff); - writememb_common(s + ((a + 1) & 0xffff), v >> 8); + addr = s + ((a + 1) & 0xffff); + write_mem_b(addr, v >> 8); + } + + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; } @@ -947,7 +959,6 @@ reset_common(int hard) cpu_alt_reset = 0; prefetching = 1; - takeint = 0; cpu_ven_reset(); @@ -1132,12 +1143,8 @@ irq_pending(void) { uint8_t temp; - if (takeint && !noint) - temp = 1; - else - temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint); - - takeint = (cpu_state.flags & I_FLAG) && pic.int_pending; + temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || + ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint); return temp; } @@ -1806,6 +1813,7 @@ execx86(int cycs) if (!repeating) { cpu_state.oldpc = cpu_state.pc; opcode = pfq_fetchb(); + if ((CS == 0xf000) && (cpu_state.oldpc == 0x49d)) oldc = cpu_state.flags & C_FLAG; if (clear_lock) { in_lock = 0; @@ -2686,30 +2694,20 @@ execx86(int cycs) cpu_state.eaaddr = cpu_data; if ((opcode & 2) == 0) { access(3, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { - AX = inw(cpu_data); - wait(4, 1); /* I/O access and wait state. */ - } else { - AL = inb(cpu_data); - if (opcode & 1) - AH = inb(cpu_data + 1); - wait(bits >> 1, 1); /* I/O access. */ - } + if (opcode & 1) + cpu_io(16, 0, cpu_data); + else + cpu_io(8, 0, cpu_data); wait(1, 0); } else { if ((opcode & 8) == 0) access(8, bits); else access(9, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { - outw(cpu_data, AX); - wait(4, 1); - } else { - outb(cpu_data, AL); - if (opcode & 1) - outb(cpu_data + 1, AH); - wait(bits >> 1, 1); /* I/O access. */ - } + if (opcode & 1) + cpu_io(16, 1, cpu_data); + else + cpu_io(8, 1, cpu_data); } break; diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 9ece6b698..a5bae6f89 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -232,7 +232,9 @@ extern int mem_a20_state, extern uint8_t read_mem_b(uint32_t addr); +extern uint16_t read_mem_w(uint32_t addr); extern void write_mem_b(uint32_t addr, uint8_t val); +extern void write_mem_w(uint32_t addr, uint16_t val); #ifndef USE_NEW_DYNAREC #define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a))) diff --git a/src/mem/mem.c b/src/mem/mem.c index 6641bbc08..61dece43e 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -674,6 +674,27 @@ read_mem_b(uint32_t addr) } +uint16_t +read_mem_w(uint32_t addr) +{ + mem_mapping_t *map; + mem_logical_addr = addr; + + if (addr & 1) + return read_mem_b(addr) | (read_mem_b(addr + 1) << 8); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + + return 0xffff; +} + + void write_mem_b(uint32_t addr, uint8_t val) { @@ -686,6 +707,30 @@ write_mem_b(uint32_t addr, uint8_t val) } +void +write_mem_w(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map; + mem_logical_addr = addr; + + if (addr & 1) { + write_mem_b(addr, val); + write_mem_b(addr + 1, val >> 8); + return; + } + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_w) + map->write_w(addr, val, map->p); + else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + } + } +} + + uint8_t readmembl(uint32_t addr) { diff --git a/src/pic.c b/src/pic.c index 01c595f0d..80b274ee7 100644 --- a/src/pic.c +++ b/src/pic.c @@ -45,7 +45,10 @@ enum pic_t pic, pic2; -static int shadow = 0, elcr_enabled = 0; +static pc_timer_t pic_timer; + +static int shadow = 0, elcr_enabled = 0, + tmr_inited = 0, latched = 0; #ifdef ENABLE_PIC_LOG @@ -184,9 +187,7 @@ find_best_interrupt(pic_t *dev) void pic_update_pending(void) { - int is_at; - - is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA)); + int is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA)); if (is_at) { pic2.int_pending = (find_best_interrupt(&pic2) != -1); @@ -197,24 +198,47 @@ pic_update_pending(void) pic.irr &= ~(1 << pic2.icw3); } - pic.int_pending = (find_best_interrupt(&pic) != -1); + if (find_best_interrupt(&pic) != -1) { + latched++; + if (latched == 1) + timer_on_auto(&pic_timer, is_at ? 0.3 : 0.35); + /* 300 ms on AT+, 350 ns on PC/PCjr/XT */ + } else if (latched == 0) + pic.int_pending = 0; +} + + +static void +pic_callback(void *priv) +{ + pic_t *dev = (pic_t *) priv; + + dev->int_pending = 1; + + latched--; + if (latched > 0) + timer_on_auto(&pic_timer, 0.35); } void pic_reset() { - int is_at; + int is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA)); memset(&pic, 0, sizeof(pic_t)); memset(&pic2, 0, sizeof(pic_t)); pic.is_master = 1; - is_at = IS_ARCH(machine, (MACHINE_BUS_ISA16 | MACHINE_BUS_MCA | MACHINE_BUS_PCMCIA)); - if (is_at) pic.slaves[2] = &pic2; + + if (tmr_inited) + timer_on_auto(&pic_timer, 0.0); + memset(&pic_timer, 0x00, sizeof(pc_timer_t)); + timer_add(&pic_timer, pic_callback, &pic, 0); + tmr_inited = 1; }