From 6d2e5185aea9c07004e1e5afff6f41add8083c9d Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 6 Nov 2023 23:21:58 +0100 Subject: [PATCH] Reverted back to known-good 808x code from 3.11.4311, fixes PC/XT V20 (the full 808x rewrite based on MartyPC is still coming in 4.1). --- src/cpu/808x.c | 2135 +++++++++++++++++------------------------------- 1 file changed, 771 insertions(+), 1364 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index a24d1f07f..3572f2c9f 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -35,8 +35,6 @@ #include <86box/ppi.h> #include <86box/timer.h> #include <86box/gdbstub.h> -#include <86box/plat_fallthrough.h> -#include <86box/plat_unused.h> /* Is the CPU 8088 or 8086. */ int is8086 = 0; @@ -48,8 +46,7 @@ uint32_t custom_nmi_vector = 0x00000000; static uint8_t pfq[6]; /* Variables to aid with the prefetch queue operation. */ -static int biu_cycles = 0; -static int pfq_pos = 0; +static int biu_cycles = 0, pfq_pos = 0; /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; @@ -60,57 +57,18 @@ static x86seg *_opseg[4]; static int noint = 0; static int in_lock = 0; -static int cpu_alu_op; -static int pfq_size; +static int cpu_alu_op, pfq_size; -static uint32_t cpu_src = 0; -static uint32_t cpu_dest = 0; +static uint32_t cpu_src = 0, cpu_dest = 0; static uint32_t cpu_data = 0; static uint16_t last_addr = 0x0000; static uint32_t *ovr_seg = NULL; -static int prefetching = 1; -static int completed = 1; -static int in_rep = 0; -static int repeating = 0; -static int rep_c_flag = 0; -static int oldc; -static int clear_lock = 0; -static int refresh = 0; -static int cycdiff; - -static int access_code = 0; -static int hlda = 0; -static int not_ready = 0; -static int bus_request_type = 0; -static int pic_data = -1; -static int last_was_code = 0; -static uint16_t mem_data = 0; -static uint32_t mem_seg = 0; -static uint16_t mem_addr = 0; -static int schedule_fetch = 1; -static int pasv = 0; - -#define BUS_OUT 1 -#define BUS_HIGH 2 -#define BUS_WIDE 4 -#define BUS_CODE 8 -#define BUS_IO 16 -#define BUS_MEM 32 -#define BUS_PIC 64 -#define BUS_ACCESS_TYPE (BUS_CODE | BUS_IO | BUS_MEM | BUS_PIC) - -#define BUS_CYCLE (biu_cycles & 3) -#define BUS_CYCLE_T1 biu_cycles = 0 -#define BUS_CYCLE_NEXT biu_cycles = (biu_cycles + 1) & 3 - -enum { - BUS_T1 = 0, - BUS_T2, - BUS_T3, - BUS_T4 -}; +static int prefetching = 1, completed = 1; +static int in_rep = 0, repeating = 0, rep_c_flag = 0; +static int oldc, clear_lock = 0; +static int refresh = 0, cycdiff; /* Various things needed for 8087. */ #define OP_TABLE(name) ops_##name @@ -135,6 +93,7 @@ enum { wait(val, 0); \ } +#if 0 # define CLOCK_CYCLES_FPU(val) \ { \ wait(val, 0); \ @@ -153,6 +112,19 @@ enum { } # define CONCURRENCY_CYCLES(c) fpu_cycles = (c) +#else +# define CLOCK_CYCLES(val) \ + { \ + wait(val, 0); \ + } + +# define CLOCK_CYCLES_FPU(val) \ + { \ + wait(val, 0); \ + } + +# define CONCURRENCY_CYCLES(c) +#endif typedef int (*OpFn)(uint32_t fetchdat); @@ -179,7 +151,7 @@ x808x_log(const char *fmt, ...) # define x808x_log(fmt, ...) #endif -static void pfq_add(void); +static void pfq_add(int c, int add); static void set_pzs(int bits); uint16_t @@ -200,344 +172,50 @@ clock_end(void) int diff = cycdiff - cycles; /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += ((uint64_t) diff * (xt_cpu_multi >> 32ULL)); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ + tsc += (uint64_t) diff * ((uint64_t) xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) timer_process(); } static void -process_timers(void) +fetch_and_bus(int c, int bus) { - clock_end(); - clock_start(); -} + if (refresh > 0) { + /* Finish the current fetch, if any. */ + cycles -= ((4 - (biu_cycles & 3)) & 3); + pfq_add((4 - (biu_cycles & 3)) & 3, 1); + /* Add 4 memory access cycles. */ + cycles -= 4; + pfq_add(4, 0); -static void -cycles_forward(int c) -{ - cycles -= c; - - if (!is286) - process_timers(); -} - -static void -bus_outb(uint16_t port, uint8_t val) -{ - int old_cycles = cycles; - - cycles--; - outb(port, val); - resub_cycles(old_cycles); -} - -static void -bus_outw(uint16_t port, uint16_t val) -{ - int old_cycles = cycles; - - cycles--; - outw(port, val); - resub_cycles(old_cycles); -} - -static uint8_t -bus_inb(uint16_t port) -{ - int old_cycles = cycles; - uint8_t ret; - - cycles--; - ret = inb(port); - resub_cycles(old_cycles); - - return ret; -} - -static uint16_t -bus_inw(uint16_t port) -{ - int old_cycles = cycles; - uint16_t ret; - - cycles--; - ret = inw(port); - resub_cycles(old_cycles); - - return ret; -} - -static void -bus_do_io(int io_type) -{ - last_was_code = 0; - - x808x_log("(%02X) bus_do_io(%02X): %04X\n", opcode, io_type, cpu_state.eaaddr); - - if (io_type & BUS_OUT) { - if (io_type & BUS_WIDE) - bus_outw((uint16_t) cpu_state.eaaddr, AX); - else if (io_type & BUS_HIGH) - bus_outb(((uint16_t) cpu_state.eaaddr + 1) & 0xffff, AH); - else - bus_outb((uint16_t) cpu_state.eaaddr, AL); - } else { - if (io_type & BUS_WIDE) - AX = bus_inw((uint16_t) cpu_state.eaaddr); - else if (io_type & BUS_HIGH) - AH = bus_inb(((uint16_t) cpu_state.eaaddr + 1) & 0xffff); - else - AL = bus_inb((uint16_t) cpu_state.eaaddr); - } - - process_timers(); -} - -static void -bus_writeb(uint32_t seg, uint32_t addr, uint8_t val) -{ - write_mem_b(seg + addr, val); -} - -static void -bus_writew(uint32_t seg, uint32_t addr, uint16_t val) -{ - write_mem_w(seg + addr, val); -} - -static uint8_t -bus_readb(uint32_t seg, uint32_t addr) -{ - uint8_t ret = read_mem_b(seg + addr); - - return ret; -} - -static uint16_t -bus_readw(uint32_t seg, uint32_t addr) -{ - uint16_t ret = read_mem_w(seg + addr); - - return ret; -} - -static void -bus_do_mem(int io_type) -{ - last_was_code = 0; - - if (io_type & BUS_OUT) { - if (io_type & BUS_WIDE) - bus_writew(mem_seg, (uint32_t) mem_addr, mem_data); - else if (io_type & BUS_HIGH) { - if (is186 && !is_nec) - bus_writeb(mem_seg, ((uint32_t) mem_addr) + 1, mem_data >> 8); - else - bus_writeb(mem_seg, (uint32_t) ((mem_addr + 1) & 0xffff), mem_data >> 8); - } else - bus_writeb(mem_seg, (uint32_t) mem_addr, mem_data & 0xff); - } else { - if (io_type & BUS_WIDE) - mem_data = bus_readw(mem_seg, (uint32_t) mem_addr); - else if (io_type & BUS_HIGH) { - if (is186 && !is_nec) - mem_data = (mem_data & 0x00ff) | (((uint16_t) bus_readb(mem_seg, ((uint32_t) mem_addr) + 1)) << 8); - else - mem_data = (mem_data & 0x00ff) | (((uint16_t) bus_readb(mem_seg, (uint32_t) ((mem_addr + 1) & 0xffff))) << 8); - } else - mem_data = (mem_data & 0xff00) | ((uint16_t) bus_readb(mem_seg, (uint32_t) mem_addr)); - } -} - -static void -run_bus_cycle(int io_type) -{ - int do_bus_access = (io_type != 0) && (!(io_type & BUS_CODE) || schedule_fetch); - - x808x_log("[%04X:%04X] %02X bus access %02X (%i)\n", CS, cpu_state.pc, opcode, io_type, do_bus_access); - - if (do_bus_access) { - if (not_ready > 0) { - x808x_log("[%04X:%04X] %02X TW x%i\n", CS, cpu_state.pc, opcode, not_ready); - cycles_forward(not_ready); - not_ready = 0; - } - - switch (BUS_CYCLE) { - case BUS_T1: - access_code = !!(io_type & BUS_CODE); - break; - case BUS_T2: - switch (io_type & BUS_ACCESS_TYPE) { - case BUS_IO: - if (io_type & BUS_OUT) - bus_do_io(io_type); - break; - case BUS_MEM: - if (io_type & BUS_OUT) - bus_do_mem(io_type); - break; - default: - break; - } - break; - case BUS_T3: - switch (io_type & BUS_ACCESS_TYPE) { - case BUS_CODE: - pfq_add(); - last_was_code = 1; - break; - case BUS_IO: - if (!(io_type & BUS_OUT)) - bus_do_io(io_type); - break; - case BUS_MEM: - if (!(io_type & BUS_OUT)) - bus_do_mem(io_type); - break; - case BUS_PIC: - pic_data = pic_irq_ack(); - last_was_code = 0; - break; - default: - break; - } - break; - default: - break; - } - } -} - -static void -run_dma_cycle(int idle) -{ - if (not_ready > 0) { - /* Subtract one not ready cycle. */ - not_ready--; - } else if (hlda > 0) { - hlda--; - /* DMAWAIT is two cycles in, the actual wait states - are inserted with one cycle of delay. */ - if (hlda == 0) { - /* Deassert READY. */ - not_ready = 6; - } - } else if ((refresh > 0) && (in_lock == 0) && (idle || (BUS_CYCLE >= BUS_T3))) { - /* Refresh pending and it's either non-bus cycle or T3-T4, - raise HLDA. */ - hlda = 2; - /* Decrease the refresh count. */ refresh--; } -} -static void -cycles_idle(int c) -{ - for (int d = 0; d < c; d++) { - x808x_log("[%04X:%04X] %02X TI\n", CS, cpu_state.pc, opcode); - - cycles_forward(1); - run_dma_cycle(1); + pfq_add(c, !bus); + if (bus < 2) { + clock_end(); + clock_start(); } } -static void -pfq_schedule(int on) -{ - schedule_fetch = on && prefetching && (pfq_pos < pfq_size); -} - -static void -cycles_biu(int bus, int init) -{ - /* T1, T2 = Nothing, T3 = Start and schedule, T4 = Nothing */ - pasv = (bus || ((BUS_CYCLE == BUS_T1) && schedule_fetch)) ? 0 : 1; - - x808x_log("cycles_biu(%i, %i): %i, %i, %i, %i\n", bus, init, prefetching, pfq_pos, pfq_size, BUS_CYCLE); - if (bus) { - /* CPU wants non-code bus access. */ - if (init) { - if (schedule_fetch) { - switch (BUS_CYCLE) { - case BUS_T1: - case BUS_T2: - BUS_CYCLE_T1; /* Simply abort the prefetch before actual scheduling, no penalty. */ - break; - case BUS_T3: - case BUS_T4: - cycles_idle(5 - BUS_CYCLE); /* Leftover BIU cycles + 2 idle cycles. */ - BUS_CYCLE_T1; /* Abort the prefetch. */ - break; - - default: - break; - } - - pfq_schedule(0); - access_code = 0; - } - } - - run_bus_cycle(bus_request_type); - } else { - /* CPU wants idle or code bus access. */ - if (schedule_fetch) - run_bus_cycle(BUS_CODE); - } - - if (BUS_CYCLE == BUS_T2) - pfq_schedule(1); - - run_dma_cycle(pasv); - - BUS_CYCLE_NEXT; -} - -static void -cycles_pasv(void) -{ - pfq_schedule(1); - - run_dma_cycle(1); -} - -/* Bus: - 0 CPU cycles without bus access. - 1 CPU cycle T1-T4, bus access. - 2 CPU cycle Tw (wait state). - 3 CPU cycle Ti (idle). - */ static void wait(int c, int bus) { - if (c < 0) - pclog("Negative cycles: %i!\n", c); - - x808x_log("[%04X:%04X] %02X %i cycles (%i)\n", CS, cpu_state.pc, opcode, c, bus); - - for (int d = 0; d < c; d++) { - x808x_log("[%04X:%04X] %02X cycle %i BIU\n", CS, cpu_state.pc, opcode, d); - if (!bus && !schedule_fetch && (BUS_CYCLE == BUS_T1)) - cycles_pasv(); - else - cycles_biu(bus, !d); - x808x_log("[%04X:%04X] %02X cycle %i EU\n", CS, cpu_state.pc, opcode, d); - cycles_forward(1); - } + cycles -= c; + fetch_and_bus(c, bus); } -/* This is for external subtraction of cycles, ie. wait states. */ +/* This is for external subtraction of cycles. */ void sub_cycles(int c) { - if (is286) - cycles -= c; - else { - if (c > 0) - cycles_idle(c); - } + if (c <= 0) + return; + + cycles -= c; + + if (!is286) + fetch_and_bus(c, 2); } void @@ -547,14 +225,9 @@ resub_cycles(int old_cycles) if (old_cycles > cycles) { cyc_diff = old_cycles - cycles; - - for (int i = 0; i < cyc_diff; i++) { - if (not_ready > 0) - not_ready--; - } + cycles = old_cycles; + sub_cycles(cyc_diff); } - - process_timers(); } #undef readmemb @@ -565,55 +238,53 @@ resub_cycles(int old_cycles) static void cpu_io(int bits, int out, uint16_t port) { + int old_cycles = cycles; + if (out) { + wait(4, 1); if (bits == 16) { if (is8086 && !(port & 1)) { - bus_request_type = BUS_IO | BUS_OUT | BUS_WIDE; - wait(4, 1); + old_cycles = cycles; + outw(port, AX); } else { - bus_request_type = BUS_IO | BUS_OUT; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_IO | BUS_OUT | BUS_HIGH; wait(4, 1); + old_cycles = cycles; + outb(port++, AL); + outb(port, AH); } } else { - bus_request_type = BUS_IO | BUS_OUT; - wait(4, 1); + old_cycles = cycles; + outb(port, AL); } } else { + wait(4, 1); if (bits == 16) { if (is8086 && !(port & 1)) { - bus_request_type = BUS_IO | BUS_WIDE; - wait(4, 1); + old_cycles = cycles; + AX = inw(port); } else { - bus_request_type = BUS_IO; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_IO | BUS_HIGH; wait(4, 1); + old_cycles = cycles; + AL = inb(port++); + AH = inb(port); } } else { - bus_request_type = BUS_IO; - wait(4, 1); + old_cycles = cycles; + AL = inb(port); } } - bus_request_type = 0; + resub_cycles(old_cycles); } /* Reads a byte from the memory and advances the BIU. */ static uint8_t -readmemb(uint32_t s, uint16_t a) +readmemb(uint32_t a) { uint8_t ret; - mem_seg = s; - mem_addr = a; - bus_request_type = BUS_MEM; wait(4, 1); - ret = mem_data & 0xff; - bus_request_type = 0; + ret = read_mem_b(a); return ret; } @@ -627,8 +298,6 @@ readmembf(uint32_t a) a = cs + (a & 0xffff); ret = read_mem_b(a); - last_was_code = 1; - return ret; } @@ -638,20 +307,14 @@ readmemw(uint32_t s, uint16_t a) { uint16_t ret; - mem_seg = s; - mem_addr = a; - if (is8086 && !(a & 1)) { - bus_request_type = BUS_MEM | BUS_WIDE; - wait(4, 1); - } else { - bus_request_type = BUS_MEM | BUS_HIGH; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_MEM; + wait(4, 1); + if (is8086 && !(a & 1)) + ret = read_mem_w(s + a); + else { wait(4, 1); + ret = read_mem_b(s + a); + ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8; } - ret = mem_data; - bus_request_type = 0; return ret; } @@ -663,8 +326,6 @@ readmemwf(uint16_t a) ret = read_mem_w(cs + (a & 0xffff)); - last_was_code = 1; - return ret; } @@ -674,7 +335,7 @@ readmem(uint32_t s) if (opcode & 1) return readmemw(s, cpu_state.eaaddr); else - return (uint16_t) readmemb(s, cpu_state.eaaddr); + return (uint16_t) readmemb(s + cpu_state.eaaddr); } static uint32_t @@ -696,8 +357,6 @@ readmemq(uint32_t s, uint16_t a) temp = (uint64_t) (readmeml(s, a + 4)) << 32; temp |= readmeml(s, a); - last_was_code = 0; - return temp; } @@ -707,15 +366,8 @@ writememb(uint32_t s, uint32_t a, uint8_t v) { uint32_t addr = s + a; - // if (CS == DEBUG_SEG) - // fatal("writememb(%08X, %08X, %02X)\n", s, a, v); - - mem_seg = s; - mem_addr = a; - mem_data = v; - bus_request_type = BUS_MEM | BUS_OUT; wait(4, 1); - bus_request_type = 0; + write_mem_b(addr, v); if ((addr >= 0xf0000) && (addr <= 0xfffff)) last_addr = addr & 0xffff; @@ -727,20 +379,15 @@ writememw(uint32_t s, uint32_t a, uint16_t v) { uint32_t addr = s + a; - mem_seg = s; - mem_addr = a; - mem_data = v; - if (is8086 && !(a & 1)) { - bus_request_type = BUS_MEM | BUS_OUT | BUS_WIDE; - wait(4, 1); - } else { - bus_request_type = BUS_MEM | BUS_OUT | BUS_HIGH; - wait(4, 1); - pfq_schedule(0); - bus_request_type = BUS_MEM | BUS_OUT; + wait(4, 1); + if (is8086 && !(a & 1)) + write_mem_w(addr, v); + else { + write_mem_b(addr, v & 0xff); wait(4, 1); + addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff)); + write_mem_b(addr, v >> 8); } - bus_request_type = 0; if ((addr >= 0xf0000) && (addr <= 0xfffff)) last_addr = addr & 0xffff; @@ -773,55 +420,38 @@ static void pfq_write(void) { uint16_t tempw; - /* Byte fetch on odd addres on 8086 to simulate the HL toggle. */ - int fetch_word = is8086 && !(pfq_ip & 1); - if (fetch_word && (pfq_pos < (pfq_size - 1))) { + if (is8086 && (pfq_pos < (pfq_size - 1))) { /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes free in the queue. */ tempw = readmemwf(pfq_ip); *(uint16_t *) &(pfq[pfq_pos]) = tempw; - pfq_ip = (pfq_ip + 2) & 0xffff; + pfq_ip += 2; pfq_pos += 2; - - if (pfq_pos >= (pfq_size - 1)) - pfq_schedule(0); - } else if (!fetch_word && (pfq_pos < pfq_size)) { + } else if (!is8086 && (pfq_pos < pfq_size)) { /* The 8088 fetches 1 byte at a time, and only if there's at least 1 byte free in the queue. */ pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip = (pfq_ip + 1) & 0xffff; + pfq_ip++; pfq_pos++; - - if (pfq_pos >= pfq_size) - pfq_schedule(0); } - - if (pfq_pos >= pfq_size) - pfq_pos = pfq_size; } static uint8_t pfq_read(void) { - uint8_t temp; + uint8_t temp, i; temp = pfq[0]; - for (int i = 0; i < (pfq_size - 1); i++) + for (i = 0; i < (pfq_size - 1); i++) pfq[i] = pfq[i + 1]; pfq_pos--; - if (pfq_pos < 0) - pfq_pos = 0; cpu_state.pc = (cpu_state.pc + 1) & 0xffff; return temp; } /* Fetches a byte from the prefetch queue, or from memory if the queue has - been drained. - - Cycles: 1 If fetching from the queue; - (4 - (biu_cycles & 3)) If fetching from the bus - fetch into the queue; - 1 If fetching from the bus - delay. */ + been drained. */ static uint8_t pfq_fetchb_common(void) { @@ -831,8 +461,7 @@ pfq_fetchb_common(void) /* Reset prefetch queue internal position. */ pfq_ip = cpu_state.pc; /* Fill the queue. */ - while (pfq_pos == 0) - wait(1, 0); + wait(4 - (biu_cycles & 3), 0); } /* Fetch. */ @@ -840,7 +469,6 @@ pfq_fetchb_common(void) return temp; } -/* The timings are above. */ static uint8_t pfq_fetchb(void) { @@ -876,36 +504,26 @@ pfq_fetch(void) /* Adds bytes to the prefetch queue based on the instruction's cycle count. */ static void -pfq_add(void) +pfq_add(int c, int add) { - if (prefetching && (pfq_pos < pfq_size)) - pfq_write(); + int d; + + if ((c <= 0) || (pfq_pos >= pfq_size)) + return; + + for (d = 0; d < c; d++) { + biu_cycles = (biu_cycles + 1) & 0x03; + if (prefetching && add && (biu_cycles == 0x00)) + pfq_write(); + } } /* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ static void pfq_clear(void) { - pfq_pos = 0; - - BUS_CYCLE_T1; -} - -static void -pfq_do_suspend(void) -{ - while (BUS_CYCLE != BUS_T1) - wait(1, 0); - wait(1, 0); - pfq_schedule(0); - prefetching = 0; -} - -static void -pfq_suspend(void) -{ - pfq_do_suspend(); - pfq_clear(); + pfq_pos = 0; + prefetching = 0; } static void @@ -925,7 +543,7 @@ load_seg(uint16_t seg, x86seg *s) void reset_808x(int hard) { - BUS_CYCLE_T1; + biu_cycles = 0; in_rep = 0; in_lock = 0; completed = 1; @@ -944,7 +562,7 @@ reset_808x(int hard) _opseg[2] = &cpu_state.seg_ss; _opseg[3] = &cpu_state.seg_ds; - pfq_size = is8086 ? 6 : 4; + pfq_size = (is8086) ? 6 : 4; pfq_clear(); } @@ -954,25 +572,11 @@ reset_808x(int hard) cpu_state.flags |= MD_FLAG; rammask = 0xfffff; - pasv = 0; - - cpu_alu_op = 0; + prefetching = 1; + cpu_alu_op = 0; use_custom_nmi_vector = 0x00; custom_nmi_vector = 0x00000000; - - access_code = 0; - hlda = 0; - not_ready = 0; - bus_request_type = 0; - pic_data = -1; - last_was_code = 0; - mem_data = 0; - mem_seg = 0; - mem_addr = 0; - - prefetching = 1; - pfq_schedule(1); } static void @@ -980,7 +584,6 @@ set_ip(uint16_t new_ip) { pfq_ip = cpu_state.pc = new_ip; prefetching = 1; - pfq_schedule(1); } /* Memory refresh read - called by reads and writes on DMA channel 0. */ @@ -1023,11 +626,12 @@ do_mod_rm(void) if (cpu_mod == 3) return; - wait(2, 0); + wait(1, 0); if ((rmdat & 0xc7) == 0x06) { + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); easeg = ovr_seg ? *ovr_seg : ds; - wait(2, 0); + wait(1, 0); return; } else switch (cpu_rm) { @@ -1039,24 +643,17 @@ do_mod_rm(void) case 2: wait(3, 0); break; - - default: - break; } cpu_state.eaaddr = (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; switch (rmdat & 0xc0) { case 0x40: - wait(2, 0); + wait(3, 0); cpu_state.eaaddr += sign_extend(pfq_fetchb()); - wait(1, 0); break; case 0x80: - wait(2, 0); + wait(3, 0); cpu_state.eaaddr += pfq_fetchw(); - wait(1, 0); - break; - default: break; } cpu_state.eaaddr &= 0xffff; @@ -1080,7 +677,7 @@ geteab(void) if (cpu_mod == 3) return (getr8(cpu_rm)); - return readmemb(easeg, cpu_state.eaaddr); + return readmemb(easeg + cpu_state.eaaddr); } /* Reads a word from the effective address. */ @@ -1124,7 +721,7 @@ read_ea(int memory_only, int bits) if (bits == 16) cpu_data = readmemw(easeg, cpu_state.eaaddr); else - cpu_data = readmemb(easeg, cpu_state.eaaddr); + cpu_data = readmemb(easeg + cpu_state.eaaddr); return; } if (!memory_only) { @@ -1142,7 +739,7 @@ read_ea2(int bits) if (bits == 16) cpu_data = readmemw(easeg, cpu_state.eaaddr); else - cpu_data = readmemb(easeg, cpu_state.eaaddr); + cpu_data = readmemb(easeg + cpu_state.eaaddr); } /* Writes a byte to the effective address. */ @@ -1151,10 +748,8 @@ seteab(uint8_t val) { if (cpu_mod == 3) { setr8(cpu_rm, val); - } else { - wait(1, 0); + } else writememb(easeg, cpu_state.eaaddr, val); - } } /* Writes a word to the effective address. */ @@ -1163,10 +758,8 @@ seteaw(uint16_t val) { if (cpu_mod == 3) cpu_state.regs[cpu_rm].w = val; - else { - wait(1, 0); + else writememw(easeg, cpu_state.eaaddr, val); - } } static void @@ -1222,129 +815,206 @@ pop(void) } static void -nearcall(uint16_t new_ip) +access(int num, int bits) { - uint16_t ret_ip = cpu_state.pc & 0xffff; - - wait(1, 0); - set_ip(new_ip); - pfq_clear(); - wait(3, 0); - push(&ret_ip); -} - -static void -farcall2(uint16_t new_cs, uint16_t new_ip) -{ - wait(3, 0); - push(&CS); - load_cs(new_cs); - wait(2, 0); - nearcall(new_ip); + switch (num) { + case 0: + case 61: + case 63: + case 64: + case 67: + case 69: + case 71: + case 72: + default: + break; + case 1: + case 6: + case 7: + case 8: + case 9: + case 17: + case 20: + case 21: + case 24: + case 28: + case 47: + case 48: + case 49: + case 50: + case 51: + case 55: + case 56: + case 62: + case 66: + case 68: + wait(1, 0); + break; + case 3: + case 11: + case 15: + case 22: + case 23: + case 25: + case 26: + case 35: + case 44: + case 45: + case 46: + case 52: + case 53: + case 54: + wait(2, 0); + break; + case 16: + case 18: + case 19: + case 27: + case 32: + case 37: + case 42: + wait(3, 0); + break; + case 10: + case 12: + case 13: + case 14: + case 29: + case 30: + case 33: + case 34: + case 39: + case 41: + case 60: + wait(4, 0); + break; + case 4: + case 70: + wait(5, 0); + break; + case 31: + case 38: + case 40: + wait(6, 0); + break; + case 5: + if (opcode == 0xcc) + wait(7, 0); + else + wait(4, 0); + break; + case 36: + wait(1, 0); + pfq_clear(); + wait(1, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 43: + wait(2, 0); + pfq_clear(); + wait(1, 0); + break; + case 57: + if (cpu_mod != 3) + wait(2, 0); + wait(4, 0); + break; + case 58: + if (cpu_mod != 3) + wait(1, 0); + wait(4, 0); + break; + case 59: + wait(2, 0); + pfq_clear(); + if (cpu_mod != 3) + wait(1, 0); + wait(3, 0); + break; + case 65: + wait(1, 0); + pfq_clear(); + wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); + break; + } } /* Calls an interrupt. */ -/* The INTR microcode routine. */ static void -intr_routine(uint16_t intr, int skip_first) +interrupt(uint16_t addr) { - uint16_t vector = intr * 4; - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; - if (!skip_first) - wait(1, 0); - wait(2, 0); - - cpu_state.eaaddr = vector & 0xffff; - new_ip = readmemw(0, cpu_state.eaaddr); + addr <<= 2; + cpu_state.eaaddr = addr; + old_cs = CS; + access(5, 16); + new_ip = readmemw(0, cpu_state.eaaddr); wait(1, 0); cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - new_cs = readmemw(0, cpu_state.eaaddr); - - pfq_do_suspend(); - wait(2, 0); - push(&tempf); - cpu_state.flags &= ~(I_FLAG | T_FLAG); - wait(1, 0); - - farcall2(new_cs, new_ip); -} - -static void -sw_int(uint16_t intr) -{ - uint16_t vector = intr * 4; - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; - uint16_t old_ip; - - wait(3, 0); - cpu_state.eaaddr = vector & 0xffff; - new_ip = readmemw(0, cpu_state.eaaddr); - wait(1, 0); - cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - new_cs = readmemw(0, cpu_state.eaaddr); - pfq_do_suspend(); - wait(2, 0); - push(&tempf); - cpu_state.flags &= ~(I_FLAG | T_FLAG); - - /* FARCALL2 */ - wait(4, 0); - push(&CS); - load_cs(new_cs); - wait(1, 0); - - /* NEARCALL */ - old_ip = cpu_state.pc & 0xffff; - wait(2, 0); - set_ip(new_ip); + access(6, 16); + new_cs = readmemw(0, cpu_state.eaaddr); + prefetching = 0; pfq_clear(); - wait(3, 0); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); push(&old_ip); } -static void -int3(void) -{ - wait(4, 0); - intr_routine(3, 0); -} - void interrupt_808x(uint16_t addr) { - intr_routine(addr, 0); + interrupt(addr); } static void custom_nmi(void) { - uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - uint16_t new_cs; - uint16_t new_ip; - - wait(1, 0); - wait(2, 0); + uint16_t old_cs, old_ip; + uint16_t new_cs, new_ip; + uint16_t tempf; cpu_state.eaaddr = 0x0002; + old_cs = CS; + access(5, 16); (void) readmemw(0, cpu_state.eaaddr); new_ip = custom_nmi_vector & 0xffff; wait(1, 0); cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + access(6, 16); (void) readmemw(0, cpu_state.eaaddr); - new_cs = custom_nmi_vector >> 16; - - pfq_do_suspend(); - wait(2, 0); + new_cs = custom_nmi_vector >> 16; + prefetching = 0; + pfq_clear(); + ovr_seg = NULL; + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); - wait(1, 0); - - farcall2(new_cs, new_ip); + access(40, 16); + push(&old_cs); + old_ip = cpu_state.pc; + load_cs(new_cs); + access(68, 16); + set_ip(new_ip); + access(41, 16); + push(&old_ip); } static int @@ -1357,18 +1027,6 @@ irq_pending(void) return temp; } -static int -bus_pic_ack(void) -{ - int old_in_lock = in_lock; - - in_lock = 1; - bus_request_type = BUS_PIC; - wait(4, 1); - in_lock = old_in_lock; - return pic_data; -} - static void check_interrupts(void) { @@ -1376,17 +1034,15 @@ check_interrupts(void) if (irq_pending()) { if ((cpu_state.flags & T_FLAG) && !noint) { - wait(2, 0); - intr_routine(1, 0); + interrupt(1); return; } if (nmi && nmi_enable && nmi_mask) { nmi_enable = 0; - wait(2, 0); if (use_custom_nmi_vector) custom_nmi(); else - intr_routine(2, 0); + interrupt(2); #ifndef OLD_NMI_BEHAVIOR nmi = 0; #endif @@ -1396,75 +1052,65 @@ check_interrupts(void) repeating = 0; completed = 1; ovr_seg = NULL; - wait(4, 0); + wait(3, 0); /* ACK to PIC */ - temp = bus_pic_ack(); + temp = pic_irq_ack(); + wait(4, 1); wait(1, 0); /* ACK to PIC */ - temp = bus_pic_ack(); + temp = pic_irq_ack(); + wait(4, 1); wait(1, 0); in_lock = 0; clear_lock = 0; - if (BUS_CYCLE != BUS_T3) - wait(1, 0); - wait(5, 0); + wait(1, 0); /* Here is where temp should be filled, but we cheat. */ + wait(3, 0); opcode = 0x00; - intr_routine(temp, 0); + interrupt(temp); } } } -static void -rep_end(void) -{ - repeating = 0; - in_rep = 0; - completed = 1; -} - static int -rep_start(void) +rep_action(int bits) { - if (!repeating) { - wait(2, 0); + uint16_t t; - if (in_rep != 0) { - if (CX == 0) { - wait(4, 0); - rep_end(); - return 0; - } else - wait(7, 0); - } + if (in_rep == 0) + return 0; + wait(2, 0); + t = CX; + if (irq_pending() && (repeating != 0)) { + access(71, bits); + pfq_clear(); + if (is_nec && (ovr_seg != NULL)) + set_ip(cpu_state.pc - 3); + else + set_ip(cpu_state.pc - 2); + t = 0; } - - completed = 1; - return 1; -} - -static void -rep_interrupt(void) -{ - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); - - if (is_nec && (ovr_seg != NULL)) - set_ip((cpu_state.pc - 3) & 0xffff); - else - set_ip((cpu_state.pc - 2) & 0xffff); - - rep_end(); + if (t == 0) { + wait(1, 0); + completed = 1; + repeating = 0; + return 1; + } + --CX; + completed = 0; + wait(2, 0); + if (!repeating) + wait(2, 0); + return 0; } static uint16_t jump(uint16_t delta) { uint16_t old_ip; - wait(1, 0); - pfq_suspend(); - cycles_idle(1); + access(67, 8); + pfq_clear(); + wait(5, 0); old_ip = cpu_state.pc; set_ip((cpu_state.pc + delta) & 0xffff); return old_ip; @@ -1486,6 +1132,8 @@ jump_near(void) static void jcc(uint8_t opcode, int cond) { + /* int8_t offset; */ + wait(1, 0); cpu_data = pfq_fetchb(); wait(1, 0); @@ -1614,14 +1262,14 @@ alu_op(int bits) case 2: if (cpu_state.flags & C_FLAG) cpu_src++; - fallthrough; + /* Fall through. */ case 0: add(bits); break; case 3: if (cpu_state.flags & C_FLAG) cpu_src++; - fallthrough; + /* Fall through. */ case 5: case 7: sub(bits); @@ -1632,9 +1280,6 @@ alu_op(int bits) case 6: bitwise(bits, (cpu_dest ^ cpu_src)); break; - - default: - break; } } @@ -1655,11 +1300,10 @@ mul(uint16_t a, uint16_t b) { int negate = 0; int bit_count = 8; - int carry; + int carry, i; uint16_t high_bit = 0x80; uint16_t size_mask; - uint16_t c; - uint16_t r; + uint16_t c, r; size_mask = (1 << bit_count) - 1; @@ -1700,7 +1344,7 @@ mul(uint16_t a, uint16_t b) a &= size_mask; carry = (a & 1) != 0; a >>= 1; - for (int i = 0; i < bit_count; ++i) { + for (i = 0; i < bit_count; ++i) { wait(7, 0); if (carry) { cpu_src = c; @@ -1761,7 +1405,7 @@ set_pzs(int bits) } static void -set_co_mul(UNUSED(int bits), int carry) +set_co_mul(int bits, int carry) { set_cf(carry); set_of(carry); @@ -1774,11 +1418,10 @@ set_co_mul(UNUSED(int bits), int carry) static int x86_div(uint16_t l, uint16_t h) { - int bit_count = 8; + int b, bit_count = 8; int negative = 0; int dividend_negative = 0; - int size_mask; - int carry; + int size_mask, carry; uint16_t r; if (opcode & 1) { @@ -1815,14 +1458,14 @@ x86_div(uint16_t l, uint16_t h) if (h >= cpu_src) { if (opcode != 0xd4) wait(1, 0); - intr_routine(0, 0); + interrupt(0); return 0; } if (opcode != 0xd4) wait(1, 0); wait(2, 0); carry = 1; - for (int b = 0; b < bit_count; ++b) { + for (b = 0; b < bit_count; ++b) { r = (l << 1) + (carry ? 1 : 0); carry = top_bit(l, bit_count); l = r; @@ -1851,7 +1494,7 @@ x86_div(uint16_t l, uint16_t h) if (top_bit(l, bit_count)) { if (cpu_mod == 3) wait(1, 0); - intr_routine(0, 0); + interrupt(0); return 0; } wait(7, 0); @@ -1893,21 +1536,10 @@ lods(int bits) if (bits == 16) cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); else - cpu_data = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + cpu_data = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); SI = string_increment(bits); } -static void -lods_di(int bits) -{ - cpu_state.eaaddr = DI; - if (bits == 16) - cpu_data = readmemw(es, cpu_state.eaaddr); - else - cpu_data = readmemb(es, cpu_state.eaaddr); - DI = string_increment(bits); -} - static void stos(int bits) { @@ -1919,22 +1551,6 @@ stos(int bits) DI = string_increment(bits); } -static void -ins(int bits) -{ - cpu_state.eaaddr = DX; - cpu_io(bits, 0, cpu_state.eaaddr); - stos(bits); -} - -static void -outs(int bits) -{ - lods(bits); - cpu_state.eaaddr = DX; - cpu_io(bits, 1, cpu_state.eaaddr); -} - static void aa(void) { @@ -2028,82 +1644,23 @@ cpu_outw(uint16_t port, uint16_t val) return outw(port, val); } -/* The FARRET microcode routine. */ -static void -farret(int far) -{ - uint8_t far2 = !!(opcode & 0x08); - uint16_t new_cs; - uint16_t new_ip; - - wait(1, 0); - new_ip = pop(); - pfq_do_suspend(); - wait(2, 0); - - if ((!!far) != far2) - fatal("Far call distance mismatch (%i = %i)\n", !!far, far2); - - if (far) { - wait(1, 0); - new_cs = pop(); - - pfq_clear(); - wait(2, 0); - } else { - pfq_clear(); - wait(2, 0); - } - - wait(2, 0); - if (far) - load_cs(new_cs); - set_ip(new_ip); -} - /* Executes instructions up to the specified number of cycles. */ void -execx86(int32_t cycs) +execx86(int cycs) { - uint8_t temp = 0; - uint8_t temp2; - uint8_t old_af; - uint8_t nests; - uint8_t temp_val; - uint8_t temp_al; - uint8_t bit; - uint8_t handled = 0; - uint8_t odd; - uint8_t zero; - uint8_t nibbles_count; - uint8_t destcmp; - uint8_t destbyte; - uint8_t srcbyte; - uint8_t nibble_result; - uint8_t bit_length; + uint8_t temp = 0, temp2, old_af, nests; + uint8_t temp_val, temp_al, bit, handled = 0; + uint8_t odd, zero, nibbles_count, destcmp; + uint8_t destbyte, srcbyte, nibble_result, bit_length; uint8_t bit_offset; int8_t nibble_result_s; - uint16_t addr; - uint16_t tempw; - uint16_t new_cs; - uint16_t new_ip; - uint16_t tempw_int; - uint16_t size; - uint16_t tempbp; - uint16_t lowbound; - uint16_t highbound; - uint16_t regval; - uint16_t orig_sp; - uint16_t wordtopush; - uint16_t immediate; - uint16_t old_flags; - uint16_t tmpa; + uint16_t addr, tempw, new_cs, new_ip; + uint16_t tempw_int, size, tempbp, lowbound; + uint16_t highbound, regval, orig_sp, wordtopush; + uint16_t immediate, old_flags; int bits; - uint32_t i; - uint32_t carry; - uint32_t nibble; - uint32_t srcseg; - uint32_t byteaddr; + uint32_t dest_seg, i, carry, nibble; + uint32_t srcseg, byteaddr; cycles += cycs; @@ -2112,9 +1669,9 @@ execx86(int32_t cycs) if (!repeating) { cpu_state.oldpc = cpu_state.pc; - opcode = pfq_fetchb_common(); - handled = 0; - oldc = cpu_state.flags & C_FLAG; + opcode = pfq_fetchb(); + handled = 0; + oldc = cpu_state.flags & C_FLAG; if (clear_lock) { in_lock = 0; clear_lock = 0; @@ -2123,7 +1680,7 @@ execx86(int32_t cycs) } completed = 1; - x808x_log("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); if (is186) { switch (opcode) { case 0x60: /*PUSHA/PUSH R*/ @@ -2163,7 +1720,7 @@ execx86(int32_t cycs) regval = get_reg(cpu_reg); if (lowbound > regval || highbound < regval) { cpu_state.pc = cpu_state.oldpc; - intr_routine(5, 0); + interrupt(5); } handled = 1; break; @@ -2219,60 +1776,58 @@ execx86(int32_t cycs) case 0x6c: case 0x6d: /* INM dst, DW/INS dst, DX */ + bits = 8 << (opcode & 1); handled = 1; - bits = 8 << (opcode & 1); - if (rep_start()) { - ins(bits); - wait(3, 0); + if (!repeating) + wait(2, 0); - if (in_rep != 0) { - completed = 0; - repeating = 1; + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - wait(1, 0); - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + writememb(es, DI, inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; } + + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); break; case 0x6e: case 0x6f: /* OUTM DW, src/OUTS DX, src */ - handled = 1; - bits = 8 << (opcode & 1); - if (rep_start()) { - wait(1, 0); - outs(bits); - if (in_rep != 0) { - completed = 0; - repeating = 1; + dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait(2, 0); - wait(1, 0); - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } + if (rep_action(bits)) + break; + else if (!repeating) + wait(7, 0); - wait(1, 0); - CX--; - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else - wait(1, 0); + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + wait(4, 0); + outb(DX, readmemb(dest_seg + SI)); + SI += (cpu_state.flags & D_FLAG) ? -1 : 1; } + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); break; case 0xc8: /* ENTER/PREPARE */ @@ -2303,6 +1858,7 @@ execx86(int32_t cycs) do_mod_rm(); if (cpu_mod == 3) wait(1, 0); + access(53, bits); cpu_data = get_ea(); cpu_src = pfq_fetchb(); @@ -2376,14 +1932,12 @@ execx86(int32_t cycs) set_af(0); set_pzs(bits); break; - - default: - break; } if ((opcode & 2) != 0) wait(4, 0); --cpu_src; } + access(17, bits); set_ea(cpu_data); handled = 1; break; @@ -2393,9 +1947,6 @@ execx86(int32_t cycs) BP = pop(); handled = 1; break; - - default: - break; } } if (!handled) { @@ -2404,7 +1955,7 @@ execx86(int32_t cycs) case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ - wait(3, 0); + access(29, 16); push(&(_opseg[(opcode >> 3) & 0x03]->seg)); break; case 0x07: @@ -2647,7 +2198,7 @@ execx86(int32_t cycs) } for (i = 0; i < bit_length; i++) { byteaddr = (es) + DI; - writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << bit_offset)) | ((!!(AX & (1 << i))) << bit_offset)); + writememb(es, DI, (read_mem_b(byteaddr) & ~(1 << (bit_offset))) | ((!!(AX & (1 << i))) << bit_offset)); bit_offset++; if (bit_offset == 8) { DI++; @@ -2678,7 +2229,7 @@ execx86(int32_t cycs) AX = 0; for (i = 0; i < bit_length; i++) { byteaddr = (ds) + SI; - AX |= (!!(readmemb((ds), SI) & (1 << bit_offset))) << i; + AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; bit_offset++; if (bit_offset == 8) { SI++; @@ -2696,20 +2247,23 @@ execx86(int32_t cycs) break; default: - opcode = orig_opcode; - cpu_state.pc = (cpu_state.pc - 1) & 0xffff; + opcode = orig_opcode; + cpu_state.pc--; break; } - } else { - wait(1, 0); - if (opcode == 0x0F) { - load_cs(pop()); - pfq_pos = 0; - } else - load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); - /* All POP segment instructions suppress interrupts for one instruction. */ - noint = 1; - } + } else + handled = 0; + if (handled) + break; + access(22, 16); + if (opcode == 0x0F) { + load_cs(pop()); + pfq_pos = 0; + } else + load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); + wait(1, 0); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; break; case 0x26: /*ES:*/ @@ -2721,164 +2275,96 @@ execx86(int32_t cycs) completed = 0; break; - case 0x00: /* ADD r/m8, r8; r8, r/m8; al, imm8 */ + case 0x00: + case 0x01: case 0x02: - case 0x04: - case 0x08: /* OR r/m8, r8; r8, r/m8; al, imm8 */ - case 0x0a: - case 0x0c: - case 0x10: /* ADC r/m8, r8; r8, r/m8; al, imm8 */ - case 0x12: - case 0x14: - case 0x18: /* SBB r/m8, r8; r8, r/m8; al, imm8 */ - case 0x1a: - case 0x1c: - case 0x20: /* AND r/m8, r8; r8, r/m8; al, imm8 */ - case 0x22: - case 0x24: - case 0x28: /* SUB r/m8, r8; r8, r/m8; al, imm8 */ - case 0x2a: - case 0x2c: - case 0x30: /* XOR r/m8, r8; r8, r/m8; al, imm8 */ - case 0x32: - case 0x34: - bits = 8; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } - cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - if (cpu_mod == 3) - wait(2, 0); - - alu_op(bits); - if (opcode & 0x04) - set_accum(bits, cpu_data); - else { - if (opcode & 2) - set_reg(cpu_reg, cpu_data); - else - set_ea(cpu_data); - } - break; - - case 0x01: /* ADD r/m16, r16; r16, r/m16; ax, imm16 */ case 0x03: - case 0x05: - case 0x09: /* OR r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x08: + case 0x09: + case 0x0a: case 0x0b: - case 0x0d: - case 0x11: /* ADC r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x10: + case 0x11: + case 0x12: case 0x13: - case 0x15: - case 0x19: /* SBB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x18: + case 0x19: + case 0x1a: case 0x1b: - case 0x1d: - case 0x21: /* AND r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x20: + case 0x21: + case 0x22: case 0x23: - case 0x25: - case 0x29: /* SUB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x28: + case 0x29: + case 0x2a: case 0x2b: - case 0x2d: - case 0x31: /* XOR r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x30: + case 0x31: + case 0x32: case 0x33: - case 0x35: - bits = 16; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } - cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - if (cpu_mod == 3) - wait(2, 0); - - alu_op(bits); - if (opcode & 0x04) - set_accum(bits, cpu_data); - else { - if (opcode & 2) - set_reg(cpu_reg, cpu_data); - else - set_ea(cpu_data); - } - break; - - case 0x38: /* CMP r/m8, r8; r8, r/m8; al, imm8 */ + case 0x38: + case 0x39: case 0x3a: - case 0x3c: - bits = 8; - wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } + case 0x3b: + /* alu rm, r / r, rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(46, bits); + tempw = get_ea(); cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - + if ((opcode & 2) == 0) { + cpu_dest = tempw; + cpu_src = get_reg(cpu_reg); + } else { + cpu_dest = get_reg(cpu_reg); + cpu_src = tempw; + } + if (cpu_mod != 3) + wait(2, 0); + wait(1, 0); alu_op(bits); + if (cpu_alu_op != 7) { + if ((opcode & 2) == 0) { + access(10, bits); + set_ea(cpu_data); + if (cpu_mod == 3) + wait(1, 0); + } else { + set_reg(cpu_reg, cpu_data); + wait(1, 0); + } + } else + wait(1, 0); break; - case 0x39: /* CMP r/m16, r16; r16, r/m16; ax, imm16 */ - case 0x3b: + case 0x04: + case 0x05: + case 0x0c: + case 0x0d: + case 0x14: + case 0x15: + case 0x1c: + case 0x1d: + case 0x24: + case 0x25: + case 0x2c: + case 0x2d: + case 0x34: + case 0x35: + case 0x3c: case 0x3d: - bits = 16; + /* alu A, imm */ + bits = 8 << (opcode & 1); wait(1, 0); - if (opcode & 0x04) { - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - } else { - do_mod_rm(); - tempw = get_ea(); - if (opcode & 2) { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } else { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } - } + cpu_data = pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; cpu_alu_op = (opcode >> 3) & 7; - wait(2, 0); - alu_op(bits); + if (cpu_alu_op != 7) + set_accum(bits, cpu_data); + wait(1, 0); break; case 0x27: /*DAA*/ @@ -2999,7 +2485,7 @@ execx86(int32_t cycs) case 0x55: case 0x56: case 0x57: - wait(3, 0); + access(30, 16); push(&(cpu_state.regs[opcode & 0x07].w)); break; case 0x58: @@ -3010,8 +2496,9 @@ execx86(int32_t cycs) case 0x5D: case 0x5E: case 0x5F: - wait(1, 0); + access(23, 16); cpu_state.regs[opcode & 0x07].w = pop(); + wait(1, 0); break; case 0x60: /*JO alias*/ @@ -3074,14 +2561,18 @@ execx86(int32_t cycs) /* alu rm, imm */ bits = 8 << (opcode & 1); do_mod_rm(); + access(47, bits); cpu_data = get_ea(); cpu_dest = cpu_data; if (cpu_mod != 3) - wait(1, 0); - wait(1, 0); - if (opcode == 0x81) + wait(3, 0); + if (opcode == 0x81) { + if (cpu_mod == 3) + wait(1, 0); cpu_src = pfq_fetchw(); - else { + } else { + if (cpu_mod == 3) + wait(1, 0); if (opcode == 0x83) cpu_src = sign_extend(pfq_fetchb()); else @@ -3091,8 +2582,7 @@ execx86(int32_t cycs) cpu_alu_op = (rmdat & 0x38) >> 3; alu_op(bits); if (cpu_alu_op != 7) { - if (cpu_mod != 3) - wait(1, 0); + access(11, bits); set_ea(cpu_data); } else { if (cpu_mod != 3) @@ -3105,10 +2595,11 @@ execx86(int32_t cycs) /* TEST rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); + access(48, bits); cpu_data = get_ea(); test(bits, cpu_data, get_reg(cpu_reg)); - if (cpu_mod != 3) - wait(1, 0); + if (cpu_mod == 3) + wait(2, 0); wait(2, 0); break; case 0x86: @@ -3116,12 +2607,12 @@ execx86(int32_t cycs) /* XCHG rm, reg */ bits = 8 << (opcode & 1); do_mod_rm(); + access(49, bits); cpu_data = get_ea(); cpu_src = get_reg(cpu_reg); set_reg(cpu_reg, cpu_data); wait(3, 0); - if (cpu_mod != 3) - wait(3, 0); + access(12, bits); set_ea(cpu_src); break; @@ -3131,8 +2622,7 @@ execx86(int32_t cycs) bits = 8 << (opcode & 1); do_mod_rm(); wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); + access(13, bits); set_ea(get_reg(cpu_reg)); break; case 0x8A: @@ -3140,17 +2630,18 @@ execx86(int32_t cycs) /* MOV reg, rm */ bits = 8 << (opcode & 1); do_mod_rm(); + access(50, bits); set_reg(cpu_reg, get_ea()); wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); break; case 0x8C: /*MOV w,sreg*/ do_mod_rm(); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); + if (cpu_mod == 3) + wait(1, 0); + access(14, 16); seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); break; @@ -3159,34 +2650,36 @@ execx86(int32_t cycs) cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); break; case 0x8E: /*MOV sreg,w*/ do_mod_rm(); + access(51, 16); tempw = geteaw(); - if ((rmdat & 0x18) == 0x08) + if ((rmdat & 0x18) == 0x08) { load_cs(tempw); - else + pfq_pos = 0; + } else load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); wait(1, 0); if (cpu_mod != 3) - wait(1, 0); + wait(2, 0); if (((rmdat & 0x18) >> 3) == 2) noint = 1; break; case 0x8F: /*POPW*/ do_mod_rm(); - wait(2, 0); - cpu_src = cpu_state.eaaddr; - if (cpu_mod != 3) - wait(1, 0); wait(1, 0); + cpu_src = cpu_state.eaaddr; + access(24, 16); if (cpu_mod != 3) wait(2, 0); cpu_data = pop(); cpu_state.eaaddr = cpu_src; + wait(2, 0); + access(15, 16); seteaw(cpu_data); break; @@ -3224,14 +2717,14 @@ execx86(int32_t cycs) new_ip = pfq_fetchw(); wait(1, 0); new_cs = pfq_fetchw(); - wait(1, 0); - pfq_suspend(); + pfq_clear(); + access(31, 16); push(&(CS)); - wait(4, 0); + access(60, 16); cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); set_ip(new_ip); - wait(1, 0); + access(32, 16); push((uint16_t *) &(cpu_state.oldpc)); break; case 0x9B: /*WAIT*/ @@ -3253,7 +2746,7 @@ execx86(int32_t cycs) #endif break; case 0x9C: /*PUSHF*/ - wait(4, 0); + access(33, 16); if (is_nec) tempw = (cpu_state.flags & 0x8fd7) | 0x7000; else @@ -3261,11 +2754,12 @@ execx86(int32_t cycs) push(&tempw); break; case 0x9D: /*POPF*/ - wait(1, 0); + access(25, 16); if (is_nec) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; + wait(1, 0); break; case 0x9E: /*SAHF*/ wait(1, 0); @@ -3281,49 +2775,58 @@ execx86(int32_t cycs) case 0xA1: /* MOV A, [iw] */ bits = 8 << (opcode & 1); - wait(2, 0); + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); - set_accum(bits, readmem(ovr_seg ? *ovr_seg : ds)); + access(1, bits); + set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); + wait(1, 0); break; case 0xA2: case 0xA3: /* MOV [iw], A */ bits = 8 << (opcode & 1); - wait(2, 0); + wait(1, 0); cpu_state.eaaddr = pfq_fetchw(); + access(7, bits); writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); - wait(2, 0); break; case 0xA4: case 0xA5: /* MOVS */ + case 0xAC: + case 0xAD: /* LODS */ bits = 8 << (opcode & 1); - if (rep_start()) { - lods(bits); + if (!repeating) { wait(1, 0); - stos(bits); - wait(1, 0); - - if (in_rep != 0) { - completed = 0; - repeating = 1; - - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } else + if ((opcode & 8) == 0 && in_rep != 0) wait(1, 0); } + if (rep_action(bits)) { + wait(1, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + if (in_rep != 0 && (opcode & 8) != 0) + wait(1, 0); + access(20, bits); + lods(bits); + if ((opcode & 8) == 0) { + access(27, bits); + stos(bits); + } else { + set_accum(bits, cpu_data); + if (in_rep != 0) + wait(2, 0); + } + if (in_rep == 0) { + wait(3, 0); + if ((opcode & 8) != 0) + wait(1, 0); + break; + } + repeating = 1; + clock_end(); break; case 0xA6: @@ -3331,53 +2834,40 @@ execx86(int32_t cycs) case 0xAE: case 0xAF: /* SCAS */ bits = 8 << (opcode & 1); - if (rep_start()) { - if ((opcode & 8) == 0) { - wait(1, 0); - lods(bits); - tmpa = cpu_data; - } else - tmpa = AX; + if (!repeating) + wait(1, 0); + if (rep_action(bits)) { wait(2, 0); - lods_di(bits); - cpu_src = cpu_data; - cpu_dest = tmpa; - wait(3, 0); - sub(bits); - - if (in_rep) { - uint8_t end = 0; - - completed = 0; - repeating = 1; - - wait(1, 0); - - CX--; - - if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { - completed = 1; - wait(1, 0); - end = 1; - } - - if (!end) { - wait(1, 0); - - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } - - wait(1, 0); - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else - wait(1, 0); - } + break; } + if (in_rep != 0) + wait(1, 0); + wait(1, 0); + cpu_dest = get_accum(bits); + if ((opcode & 8) == 0) { + access(21, bits); + lods(bits); + wait(1, 0); + cpu_dest = cpu_data; + } + access(2, bits); + cpu_state.eaaddr = DI; + cpu_data = readmem(es); + DI = string_increment(bits); + cpu_src = cpu_data; + sub(bits); + wait(2, 0); + if (in_rep == 0) { + wait(3, 0); + break; + } + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { + completed = 1; + wait(4, 0); + break; + } + repeating = 1; + clock_end(); break; case 0xA8: @@ -3393,59 +2883,24 @@ execx86(int32_t cycs) case 0xAA: case 0xAB: /* STOS */ bits = 8 << (opcode & 1); - if (rep_start()) { - cpu_data = AX; + if (!repeating) { wait(1, 0); - stos(bits); - if (in_rep != 0) { - completed = 0; - repeating = 1; - - wait(1, 0); - if (irq_pending()) { - wait(1, 0); - rep_interrupt(); - } - - wait(1, 0); - CX--; - if (CX == 0) - rep_end(); - else - wait(1, 0); - } else + if (in_rep != 0) wait(1, 0); } - break; - - case 0xAC: - case 0xAD: /* LODS */ - bits = 8 << (opcode & 1); - if (rep_start()) { - lods(bits); - set_accum(bits, cpu_data); + if (rep_action(bits)) { + wait(1, 0); + break; + } + cpu_data = AX; + access(28, bits); + stos(bits); + if (in_rep == 0) { wait(3, 0); - - if (in_rep != 0) { - completed = 0; - repeating = 1; - - wait(1, 0); - CX--; - - if (irq_pending()) { - wait(2, 0); - rep_interrupt(); - } else { - wait(2, 0); - - if (CX == 0) - rep_end(); - else - wait(1, 0); - } - } + break; } + repeating = 1; + clock_end(); break; case 0xB0: @@ -3478,53 +2933,42 @@ execx86(int32_t cycs) break; case 0xC0: - case 0xC2: - /* RETN imm16 */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - wait(1, 0); - new_ip = pop(); - pfq_do_suspend(); - wait(2, 0); - pfq_clear(); - wait(3, 0); - SP += cpu_src; - set_ip(new_ip); - break; - case 0xC1: + case 0xC2: case 0xC3: - /* RETN */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - new_ip = pop(); - pfq_do_suspend(); - wait(1, 0); - pfq_clear(); - wait(2, 0); - set_ip(new_ip); - break; - case 0xC8: - case 0xCA: - /* RETF imm16 */ - bits = 8 + (opcode & 0x08); - wait(1, 0); - cpu_src = pfq_fetchw(); - farret(1); - SP += cpu_src; - wait(1, 0); - break; - case 0xC9: + case 0xCA: case 0xCB: - /* RETF */ + /* RET */ bits = 8 + (opcode & 0x08); - wait(1, 0); - wait(1, 0); - farret(1); + if ((opcode & 9) != 1) + wait(1, 0); + if (!(opcode & 1)) { + cpu_src = pfq_fetchw(); + wait(1, 0); + } + if ((opcode & 9) == 9) + wait(1, 0); + pfq_clear(); + access(26, bits); + new_ip = pop(); + wait(2, 0); + if ((opcode & 8) == 0) + new_cs = CS; + else { + access(42, bits); + new_cs = pop(); + if (opcode & 1) + wait(1, 0); + } + if (!(opcode & 1)) { + SP += cpu_src; + wait(1, 0); + } + load_cs(new_cs); + access(72, bits); + set_ip(new_ip); break; case 0xC4: @@ -3532,12 +2976,13 @@ execx86(int32_t cycs) /* LsS rw, rmd */ do_mod_rm(); bits = 16; + access(52, bits); read_ea(1, bits); cpu_state.regs[cpu_reg].w = cpu_data; - if (cpu_mod != 3) - wait(2, 0); + access(57, bits); read_ea2(bits); load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); + wait(1, 0); break; case 0xC6: @@ -3546,37 +2991,45 @@ execx86(int32_t cycs) bits = 8 << (opcode & 1); do_mod_rm(); wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); cpu_data = pfq_fetch(); - wait((opcode == 0xc6) ? 2 : 1, 0); + if (cpu_mod == 3) + wait(1, 0); + access(16, bits); set_ea(cpu_data); break; case 0xCC: /*INT 3*/ - wait(1, 0); - wait(4, 0); - int3(); + interrupt(3); break; case 0xCD: /*INT*/ wait(1, 0); - temp = pfq_fetchb(); - wait(1, 0); - sw_int(temp); + interrupt(pfq_fetchb()); break; case 0xCE: /*INTO*/ - wait(1, 0); - if (cpu_state.flags & V_FLAG) - sw_int(4); + wait(3, 0); + if (cpu_state.flags & V_FLAG) { + wait(2, 0); + interrupt(4); + } break; case 0xCF: /*IRET*/ - wait(1, 0); - wait(1, 0); - farret(1); + access(43, 8); + new_ip = pop(); + wait(3, 0); + access(44, 8); + new_cs = pop(); + load_cs(new_cs); + access(62, 8); + set_ip(new_ip); + access(45, 8); if (is_nec) cpu_state.flags = pop() | 0x8002; else cpu_state.flags = pop() | 0x0002; - wait(1, 0); + wait(5, 0); noint = 1; nmi_enable = 1; break; @@ -3588,9 +3041,10 @@ execx86(int32_t cycs) /* rot rm */ bits = 8 << (opcode & 1); do_mod_rm(); - cpu_data = get_ea(); if (cpu_mod == 3) wait(1, 0); + access(53, bits); + cpu_data = get_ea(); if ((opcode & 2) == 0) { cpu_src = 1; wait((cpu_mod != 3) ? 4 : 0, 0); @@ -3666,14 +3120,12 @@ execx86(int32_t cycs) set_af(0); set_pzs(bits); break; - - default: - break; } if ((opcode & 2) != 0) wait(4, 0); --cpu_src; } + access(17, bits); set_ea(cpu_data); break; @@ -3711,8 +3163,9 @@ execx86(int32_t cycs) break; case 0xD7: /*XLATB*/ cpu_state.eaaddr = (BX + AL) & 0xffff; - wait(4, 0); - AL = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + access(4, 8); + AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); + wait(1, 0); break; case 0xD8: @@ -3725,76 +3178,42 @@ execx86(int32_t cycs) case 0xDF: /* esc i, r, rm */ do_mod_rm(); + access(54, 16); tempw = cpu_state.pc; - geteaw(); - wait(1, 0); - if (cpu_mod != 3) - wait(1, 0); - if (hasfpu) { - if (fpu_softfloat) { - switch (opcode) { - case 0xD8: - ops_sf_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xD9: - ops_sf_fpu_8087_d9[rmdat & 0xff](rmdat); - break; - case 0xDA: - ops_sf_fpu_8087_da[rmdat & 0xff](rmdat); - break; - case 0xDB: - ops_sf_fpu_8087_db[rmdat & 0xff](rmdat); - break; - case 0xDC: - ops_sf_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xDD: - ops_sf_fpu_8087_dd[rmdat & 0xff](rmdat); - break; - case 0xDE: - ops_sf_fpu_8087_de[rmdat & 0xff](rmdat); - break; - case 0xDF: - ops_sf_fpu_8087_df[rmdat & 0xff](rmdat); - break; - - default: - break; - } - } else { - switch (opcode) { - case 0xD8: - ops_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xD9: - ops_fpu_8087_d9[rmdat & 0xff](rmdat); - break; - case 0xDA: - ops_fpu_8087_da[rmdat & 0xff](rmdat); - break; - case 0xDB: - ops_fpu_8087_db[rmdat & 0xff](rmdat); - break; - case 0xDC: - ops_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat); - break; - case 0xDD: - ops_fpu_8087_dd[rmdat & 0xff](rmdat); - break; - case 0xDE: - ops_fpu_8087_de[rmdat & 0xff](rmdat); - break; - case 0xDF: - ops_fpu_8087_df[rmdat & 0xff](rmdat); - break; - - default: - break; - } + if (!hasfpu) + geteaw(); + else + switch (opcode) { + case 0xD8: + ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xD9: + ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDA: + ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDB: + ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDC: + ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); + break; + case 0xDD: + ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDE: + ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat); + break; + case 0xDF: + ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat); + break; } - } cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on the 286+ core, but not here. */ + wait(1, 0); + if (cpu_mod != 3) + wait(2, 0); break; case 0xE0: @@ -3818,9 +3237,6 @@ execx86(int32_t cycs) if (!(cpu_state.flags & Z_FLAG)) oldc = 0; break; - - default: - break; } } else oldc = (CX == 0); @@ -3830,46 +3246,43 @@ execx86(int32_t cycs) case 0xE4: case 0xE5: - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetchb(); - cpu_state.eaaddr = cpu_data; - wait(1, 0); - cpu_io(bits, 0, cpu_state.eaaddr); - break; case 0xE6: case 0xE7: - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetchb(); - cpu_state.eaaddr = cpu_data; - cpu_data = (bits == 16) ? AX : AL; - wait(2, 0); - cpu_io(bits, 1, cpu_state.eaaddr); - break; case 0xEC: case 0xED: - bits = 8 << (opcode & 1); - cpu_data = DX; - cpu_state.eaaddr = cpu_data; - wait(1, 0); - cpu_io(bits, 0, cpu_state.eaaddr); - break; case 0xEE: case 0xEF: bits = 8 << (opcode & 1); - wait(2, 0); - cpu_data = DX; + if ((opcode & 0x0e) != 0x0c) + wait(1, 0); + if ((opcode & 8) == 0) + cpu_data = pfq_fetchb(); + else + cpu_data = DX; cpu_state.eaaddr = cpu_data; - cpu_data = (bits == 16) ? AX : AL; - cpu_io(bits, 1, cpu_state.eaaddr); - wait(1, 0); + if ((opcode & 2) == 0) { + access(3, bits); + 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) + cpu_io(16, 1, cpu_data); + else + cpu_io(8, 1, cpu_data); + } break; case 0xE8: /*CALL rel 16*/ wait(1, 0); cpu_state.oldpc = jump_near(); - wait(2, 0); + access(34, 8); push((uint16_t *) &(cpu_state.oldpc)); break; case 0xE9: /*JMP rel 16*/ @@ -3879,13 +3292,12 @@ execx86(int32_t cycs) case 0xEA: /*JMP far*/ wait(1, 0); addr = pfq_fetchw(); + wait(1, 0); tempw = pfq_fetchw(); load_cs(tempw); - pfq_do_suspend(); - set_ip(addr); - wait(2, 0); + access(70, 8); pfq_clear(); - wait(1, 0); + set_ip(addr); break; case 0xEB: /*JMP rel*/ wait(1, 0); @@ -3910,23 +3322,18 @@ execx86(int32_t cycs) break; case 0xF4: /*HLT*/ - if (repeating) { + if (!repeating) { wait(1, 0); - wait(1, 0); - wait(1, 0); - if (irq_pending()) { - check_interrupts(); - wait(7, 0); - } else { - repeating = 1; - completed = 0; - } + pfq_clear(); + } + wait(1, 0); + if (irq_pending()) { + wait(cycles & 1, 0); + check_interrupts(); } else { - wait(1, 0); - pfq_do_suspend(); - wait(2, 0); repeating = 1; completed = 0; + clock_end(); } break; case 0xF5: /*CMC*/ @@ -3938,12 +3345,15 @@ execx86(int32_t cycs) case 0xF7: bits = 8 << (opcode & 1); do_mod_rm(); + access(55, bits); cpu_data = get_ea(); switch (rmdat & 0x38) { case 0x00: case 0x08: /* TEST */ wait(2, 0); + if (cpu_mod != 3) + wait(1, 0); cpu_src = pfq_fetch(); wait(1, 0); test(bits, cpu_data, cpu_src); @@ -3960,8 +3370,7 @@ execx86(int32_t cycs) cpu_dest = 0; sub(bits); } - if (cpu_mod != 3) - wait(2, 0); + access(18, bits); set_ea(cpu_data); break; case 0x20: /* MUL */ @@ -3972,19 +3381,19 @@ execx86(int32_t cycs) if (opcode & 1) { AX = cpu_data; DX = cpu_dest; - set_co_mul(bits, DX != ((AX & 0x8000) == 0 || - (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); + set_co_mul(bits, DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); cpu_data = DX; } else { AL = (uint8_t) cpu_data; AH = (uint8_t) cpu_dest; - set_co_mul(bits, AH != ((AL & 0x80) == 0 || - (rmdat & 0x38) == 0x20 ? 0 : 0xff)); + set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); if (!is_nec) cpu_data = AH; } set_sf(bits); set_pf(); + if (cpu_mod != 3) + wait(1, 0); /* NOTE: When implementing the V20, care should be taken to not change the zero flag. */ if (is_nec) @@ -3992,13 +3401,12 @@ execx86(int32_t cycs) break; case 0x30: /* DIV */ case 0x38: /* IDIV */ + if (cpu_mod != 3) + wait(1, 0); cpu_src = cpu_data; if (x86_div(AL, AH)) wait(1, 0); break; - - default: - break; } break; @@ -4026,6 +3434,7 @@ execx86(int32_t cycs) /* misc */ bits = 8 << (opcode & 1); do_mod_rm(); + access(56, bits); read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); switch (rmdat & 0x38) { case 0x00: /* INC rm */ @@ -4042,65 +3451,63 @@ execx86(int32_t cycs) do_af(); set_pzs(bits); wait(2, 0); + access(19, bits); set_ea(cpu_data); break; case 0x10: /* CALL rm */ cpu_data_opff_rm(); - wait(2, 0); - pfq_do_suspend(); - wait(4, 0); + access(63, bits); + wait(1, 0); pfq_clear(); + wait(4, 0); + if (cpu_mod != 3) + wait(1, 0); + wait(1, 0); /* Wait. */ cpu_state.oldpc = cpu_state.pc; set_ip(cpu_data); wait(2, 0); + access(35, bits); push((uint16_t *) &(cpu_state.oldpc)); break; case 0x18: /* CALL rmd */ new_ip = cpu_data; - wait(3, 0); + access(58, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; - wait(1, 0); - pfq_do_suspend(); - wait(3, 0); + access(36, bits); push(&(CS)); + access(64, bits); + wait(4, 0); + cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); - wait(3, 0); - pfq_clear(); - wait(3, 0); - push((uint16_t *) &(cpu_state.pc)); set_ip(new_ip); + access(37, bits); + push((uint16_t *) &(cpu_state.oldpc)); break; case 0x20: /* JMP rm */ cpu_data_opff_rm(); - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); + access(65, bits); set_ip(cpu_data); break; case 0x28: /* JMP rmd */ new_ip = cpu_data; - pfq_do_suspend(); - wait(4, 0); - pfq_clear(); + access(59, bits); read_ea2(bits); if (!(opcode & 1)) cpu_data |= 0xff00; new_cs = cpu_data; load_cs(new_cs); + access(66, bits); set_ip(new_ip); break; case 0x30: /* PUSH rm */ case 0x38: if (cpu_mod != 3) wait(1, 0); - wait(4, 0); - push((uint16_t *) &cpu_data); - break; - - default: + access(38, bits); + push((uint16_t *) &(cpu_data)); break; } break;