Implemented PIC IRQ latch and delay (per the datasheet), IBM PCjr now works without a workaround delay in cpu/808x.c which was therefore removed; also redid memory and I/O accesses in cpu/808x.c to fix word writes on 8086.
This commit is contained in:
136
src/cpu/808x.c
136
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;
|
||||
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
40
src/pic.c
40
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user