From d1d39415422c9fc85cf9174810c77768602987d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Jan 2026 04:03:20 +0100 Subject: [PATCH] NEC Vx0: Swap the two operands in CMPSB/CMPSW, fixes #6764. Also do some refactoring to make thinking back to old 808x instructions easier for debugging purposes. --- src/cpu/808x.c | 3287 ++++++++++++++++++++++----------------------- src/cpu/vx0.c | 133 +- src/cpu/vx0_biu.h | 19 +- 3 files changed, 1701 insertions(+), 1738 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 7908160e8..a1d29e56a 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -40,6 +40,7 @@ #include <86box/gdbstub.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#include "vx0_biu.h" /* Is the CPU 8088 or 8086. */ int is8086 = 0; @@ -54,6 +55,23 @@ static uint8_t pfq[6]; static int biu_cycles = 0; int pfq_pos = 0; +int oldc; +int cpu_alu_op; +int completed = 1; +int in_rep = 0; +int repeating = 0; +int rep_c_flag = 0; +int noint = 0; +int tempc_fpu = 0; +int clear_lock = 0; + +uint32_t cpu_src = 0; +uint32_t cpu_dest = 0; + +uint32_t cpu_data = 0; + +uint32_t * ovr_seg = NULL; + /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; @@ -61,18 +79,11 @@ static uint16_t pfq_ip; static uint32_t *opseg[4]; static x86seg *_opseg[4]; -static int noint = 0; -static int cpu_alu_op, pfq_size; - -static uint32_t cpu_src = 0, cpu_dest = 0; -static uint32_t cpu_data = 0; +static int pfq_size; uint16_t last_addr = 0x0000; -static uint32_t *ovr_seg = NULL; -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 prefetching = 1; static int refresh = 0, cycdiff; static i8080 emulated_processor; @@ -136,8 +147,6 @@ static bool cpu_md_write_disable = 1; typedef int (*OpFn)(uint32_t fetchdat); -static int tempc_fpu = 0; - #ifdef ENABLE_808X_LOG #if 0 void dumpregs(int); @@ -246,8 +255,12 @@ fetch_and_bus(int c, int bus) static void wait_cycs(int c, int bus) { - cycles -= c; - fetch_and_bus(c, bus); + if (is_nec) + wait_vx0(c); + else { + cycles -= c; + fetch_and_bus(c, bus); + } } /* This is for external subtraction of cycles. */ @@ -283,55 +296,63 @@ resub_cycles(int old_cycles) static void cpu_io(int bits, int out, uint16_t port) { - int old_cycles = cycles; + if (is_nec) + cpu_io_vx0(bits, out, port); + else { + int old_cycles = cycles; - if (out) { - wait_cycs(is_mazovia ? 5 : 4, 1); - if (bits == 16) { - if (is8086 && !(port & 1)) { - old_cycles = cycles; - outw(port, AX); + if (out) { + wait_cycs(is_mazovia ? 5 : 4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) { + old_cycles = cycles; + outw(port, AX); + } else { + wait_cycs(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + outb(port++, AL); + outb(port, AH); + } } else { - wait_cycs(is_mazovia ? 5 : 4, 1); old_cycles = cycles; - outb(port++, AL); - outb(port, AH); + outb(port, AL); } } else { - old_cycles = cycles; - outb(port, AL); - } - } else { - wait_cycs(is_mazovia ? 5 : 4, 1); - if (bits == 16) { - if (is8086 && !(port & 1)) { - old_cycles = cycles; - AX = inw(port); + wait_cycs(is_mazovia ? 5 : 4, 1); + if (bits == 16) { + if (is8086 && !(port & 1)) { + old_cycles = cycles; + AX = inw(port); + } else { + wait_cycs(is_mazovia ? 5 : 4, 1); + old_cycles = cycles; + AL = inb(port++); + AH = inb(port); + } } else { - wait_cycs(is_mazovia ? 5 : 4, 1); old_cycles = cycles; - AL = inb(port++); - AH = inb(port); + AL = inb(port); } - } else { - old_cycles = cycles; - AL = inb(port); } + + resub_cycles(old_cycles); } - - resub_cycles(old_cycles); } /* Reads a byte from the memory and advances the BIU. */ static uint8_t -readmemb(uint32_t a) +readmemb(uint32_t s, uint32_t a) { - uint8_t ret; + if (is_nec) + return readmemb_vx0(s, a); + else { + uint8_t ret; - wait_cycs(4, 1); - ret = read_mem_b(a); + wait_cycs(4, 1); + ret = read_mem_b(s + a); - return ret; + return ret; + } } /* Reads a byte from the memory but does not advance the BIU. */ @@ -350,18 +371,22 @@ readmembf(uint32_t a) static uint16_t readmemw(uint32_t s, uint16_t a) { - uint16_t ret; - - wait_cycs(4, 1); - if (is8086 && !(a & 1)) - ret = read_mem_w(s + a); + if (is_nec) + return readmemw_vx0(s, a); else { - wait_cycs(4, 1); - ret = read_mem_b(s + a); - ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8; - } + uint16_t ret; - return ret; + wait_cycs(4, 1); + if (is8086 && !(a & 1)) + ret = read_mem_w(s + a); + else { + wait_cycs(4, 1); + ret = read_mem_b(s + a); + ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8; + } + + return ret; + } } static uint16_t @@ -377,88 +402,120 @@ readmemwf(uint16_t a) static uint16_t readmem(uint32_t s) { - if (opcode & 1) - return readmemw(s, cpu_state.eaaddr); - else - return (uint16_t) readmemb(s + cpu_state.eaaddr); + if (is_nec) + return readmem_vx0(s); + else { + if (opcode & 1) + return readmemw(s, cpu_state.eaaddr); + else + return (uint16_t) readmemb(s, cpu_state.eaaddr); + } } static uint32_t readmeml(uint32_t s, uint16_t a) { - uint32_t temp; + if (is_nec) + return readmeml_vx0(s, a); + else { + uint32_t temp; - temp = (uint32_t) (readmemw(s, a + 2)) << 16; - temp |= readmemw(s, a); + temp = (uint32_t) (readmemw(s, a + 2)) << 16; + temp |= readmemw(s, a); - return temp; + return temp; + } } static uint64_t readmemq(uint32_t s, uint16_t a) { - uint64_t temp; + if (is_nec) + return readmemq_vx0(s, a); + else { + uint64_t temp; - temp = (uint64_t) (readmeml(s, a + 4)) << 32; - temp |= readmeml(s, a); + temp = (uint64_t) (readmeml(s, a + 4)) << 32; + temp |= readmeml(s, a); - return temp; + return temp; + } } /* 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; + if (is_nec) + writememb_vx0(s, a, v); + else { + uint32_t addr = s + a; - wait_cycs(4, 1); - write_mem_b(addr, v); + wait_cycs(4, 1); + write_mem_b(addr, v); - if ((addr >= 0xf0000) && (addr <= 0xfffff)) - last_addr = addr & 0xffff; + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; + } } /* Writes a word to the memory and advances the BIU. */ static void writememw(uint32_t s, uint32_t a, uint16_t v) { - uint32_t addr = s + a; - - wait_cycs(4, 1); - if (is8086 && !(a & 1)) - write_mem_w(addr, v); + if (is_nec) + writememw_vx0(s, a, v); else { - write_mem_b(addr, v & 0xff); - wait_cycs(4, 1); - addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff)); - write_mem_b(addr, v >> 8); - } + uint32_t addr = s + a; - if ((addr >= 0xf0000) && (addr <= 0xfffff)) - last_addr = addr & 0xffff; + wait_cycs(4, 1); + if (is8086 && !(a & 1)) + write_mem_w(addr, v); + else { + write_mem_b(addr, v & 0xff); + wait_cycs(4, 1); + addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff)); + write_mem_b(addr, v >> 8); + } + + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; + } } static void writemem(uint32_t s, uint16_t v) { - if (opcode & 1) - writememw(s, cpu_state.eaaddr, v); - else - writememb(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); + if (is_nec) + writemem_vx0(s, v); + else { + if (opcode & 1) + writememw(s, cpu_state.eaaddr, v); + else + writememb(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); + } } static void writememl(uint32_t s, uint32_t a, uint32_t v) { - writememw(s, a, v & 0xffff); - writememw(s, a + 2, v >> 16); + if (is_nec) + writememl_vx0(s, a, v); + else { + writememw(s, a, v & 0xffff); + writememw(s, a + 2, v >> 16); + } } static void writememq(uint32_t s, uint32_t a, uint64_t v) { - writememl(s, a, v & 0xffffffff); - writememl(s, a + 4, v >> 32); + if (is_nec) + writememl_vx0(s, a, v); + else { + writememl(s, a, v & 0xffffffff); + writememl(s, a + 4, v >> 32); + } } static void @@ -485,13 +542,17 @@ pfq_write(void) static uint8_t pfq_read(void) { - uint8_t temp = pfq[0]; + if (is_nec) + return biu_pfq_read(); + else { + uint8_t temp = pfq[0]; - for (int i = 0; i < (pfq_size - 1); i++) - pfq[i] = pfq[i + 1]; - pfq_pos--; - cpu_state.pc = (cpu_state.pc + 1) & 0xffff; - return temp; + for (int i = 0; i < (pfq_size - 1); i++) + pfq[i] = pfq[i + 1]; + pfq_pos--; + cpu_state.pc = (cpu_state.pc + 1) & 0xffff; + return temp; + } } /* Fetches a byte from the prefetch queue, or from memory if the queue has @@ -499,28 +560,36 @@ pfq_read(void) static uint8_t pfq_fetchb_common(void) { - uint8_t temp; + if (is_nec) + return biu_pfq_fetchb_common(); + else { + uint8_t temp; - if (pfq_pos == 0) { - /* Reset prefetch queue internal position. */ - pfq_ip = cpu_state.pc; - /* Fill the queue. */ - wait_cycs(4 - (biu_cycles & 3), 0); + if (pfq_pos == 0) { + /* Reset prefetch queue internal position. */ + pfq_ip = cpu_state.pc; + /* Fill the queue. */ + wait_cycs(4 - (biu_cycles & 3), 0); + } + + /* Fetch. */ + temp = pfq_read(); + return temp; } - - /* Fetch. */ - temp = pfq_read(); - return temp; } static uint8_t pfq_fetchb(void) { - uint8_t ret; + if (is_nec) + return biu_pfq_fetchb(); + else { + uint8_t ret; - ret = pfq_fetchb_common(); - wait_cycs(1, 0); - return ret; + ret = pfq_fetchb_common(); + wait_cycs(1, 0); + return ret; + } } /* Fetches a word from the prefetch queue, or from memory if the queue has @@ -528,22 +597,30 @@ pfq_fetchb(void) static uint16_t pfq_fetchw(void) { - uint16_t temp; + if (is_nec) + return biu_pfq_fetchw(); + else { + uint16_t temp; - temp = pfq_fetchb_common(); - wait_cycs(1, 0); - temp |= (pfq_fetchb_common() << 8); + temp = pfq_fetchb_common(); + wait_cycs(1, 0); + temp |= (pfq_fetchb_common() << 8); - return temp; + return temp; + } } static uint16_t pfq_fetch(void) { - if (opcode & 1) - return pfq_fetchw(); - else - return (uint16_t) pfq_fetchb(); + if (is_nec) + return biu_pfq_fetch(); + else { + if (opcode & 1) + return pfq_fetchw(); + else + return (uint16_t) pfq_fetchb(); + } } /* Adds bytes to the prefetch queue based on the instruction's cycle count. */ @@ -562,12 +639,26 @@ pfq_add(int c, int add) } } +static void +pfq_clear_pos(void) +{ + if (is_nec) + biu_queue_flush(); + else + pfq_pos = 0; +} + /* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ static void pfq_clear(void) { - pfq_pos = 0; - prefetching = 0; + if (is_nec) { + biu_suspend_fetch(); + biu_queue_flush(); + } else { + pfq_pos = 0; + prefetching = 0; + } } static void @@ -586,12 +677,12 @@ load_seg(uint16_t seg, x86seg *s) uint8_t fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr) { - return readmemb(cs + addr); + return readmemb(cs, addr); } uint8_t fetch_i8080_data(UNUSED(void* priv), uint16_t addr) { - return readmemb(ds + addr); + return readmemb(ds, addr); } void put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val) @@ -659,8 +750,13 @@ reset_808x(int hard) static void set_ip(uint16_t new_ip) { - pfq_ip = cpu_state.pc = new_ip; - prefetching = 1; + if (is_nec) { + cpu_state.pc = new_ip; + biu_queue_flush(); + } else { + pfq_ip = cpu_state.pc = new_ip; + prefetching = 1; + } } /* Memory refresh read - called by reads and writes on DMA channel 0. */ @@ -754,7 +850,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. */ @@ -798,7 +894,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) { @@ -816,7 +912,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. */ @@ -1180,10 +1276,15 @@ jump(uint16_t delta) { uint16_t old_ip; access(67, 8); - pfq_clear(); + if (is_nec) + biu_suspend_fetch(); + else + pfq_clear(); wait_cycs(5, 0); old_ip = cpu_state.pc; set_ip((cpu_state.pc + delta) & 0xffff); + if (is_nec) + biu_queue_flush(); return old_ip; } @@ -1621,7 +1722,7 @@ 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); } @@ -1776,9 +1877,8 @@ cpu_outw(uint16_t port, uint16_t val) resub_cycles(old_cycles); } -/* Executes instructions up to the specified number of cycles. */ void -execx86(int cycs) +execx86_instruction(void) { uint8_t temp = 0, temp2, old_af, nests; uint16_t addr, tempw, new_cs, new_ip, handled = 0; @@ -1787,6 +1887,1378 @@ execx86(int cycs) int bits; uint32_t dest_seg; + if (!repeating) + handled = 0; + + completed = 1; + // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + + if (is186) { + switch (opcode) { + case 0x60: /* PUSHA/PUSH R */ + orig_sp = SP; + wait_cycs(1, 0); + push(&AX); + push(&CX); + push(&DX); + push(&BX); + push(&orig_sp); + push(&BP); + push(&SI); + push(&DI); + handled = 1; + break; + case 0x61: /* POPA/POP R */ + wait_cycs(9, 0); + DI = pop(); + SI = pop(); + BP = pop(); + (void) pop(); /* former orig_sp */ + BX = pop(); + DX = pop(); + CX = pop(); + AX = pop(); + handled = 1; + break; + + case 0x62: /* BOUND r/m */ + lowbound = 0; + highbound = 0; + regval = 0; + do_mod_rm(); + + lowbound = readmemw(easeg, cpu_state.eaaddr); + highbound = readmemw(easeg, cpu_state.eaaddr + 2); + regval = get_reg(cpu_reg); + if (lowbound > regval || highbound < regval) { + cpu_state.pc = cpu_state.oldpc; + interrupt(5); + } + handled = 1; + break; + + case 0x68: + wordtopush = pfq_fetchw(); + wait_cycs(1, 0); + push(&wordtopush); + handled = 1; + break; + + case 0x69: + immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchw(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + handled = 1; + break; + + case 0x6a: + wordtopush = sign_extend(pfq_fetchb()); + push(&wordtopush); + handled = 1; + break; + + case 0x6b: /* IMUL reg16,reg16/mem16,imm8 */ + immediate = 0; + bits = 16; + do_mod_rm(); + read_ea(0, 16); + immediate = pfq_fetchb(); + mul(cpu_data & 0xFFFF, immediate); + set_reg(cpu_reg, cpu_data); + set_co_mul(16, cpu_dest != 0); + handled = 1; + break; + + case 0x6c ... 0x6d: /* INM dst, DW/INS dst, DX */ + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait_cycs(2, 0); + + if (rep_action(bits)) + break; + else if (!repeating) + wait_cycs(7, 0); + + if (bits == 16) { + writememw(es, DI, cpu_inw(DX)); + DI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + writememb(es, DI, cpu_inb(DX)); + DI += (cpu_state.flags & D_FLAG) ? -1 : 1; + } + + if (in_rep == 0) + break; + + repeating = 1; + clock_end(); + break; + + case 0x6e ... 0x6f: /* OUTM DW, src/OUTS DX, src */ + dest_seg = ovr_seg ? *ovr_seg : ds; + bits = 8 << (opcode & 1); + handled = 1; + if (!repeating) + wait_cycs(2, 0); + + if (rep_action(bits)) + break; + else if (!repeating) + wait_cycs(7, 0); + + if (bits == 16) { + cpu_outw(DX, readmemw(dest_seg, SI)); + SI += (cpu_state.flags & D_FLAG) ? -2 : 2; + } else { + cpu_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 */ + tempw_int = 0; + size = pfq_fetchw(); + nests = pfq_fetchb(); + + push(&BP); + tempw_int = SP; + if (nests > 0) { + while (--nests) { + tempbp = 0; + BP -= 2; + tempbp = readmemw(ss, BP); + push(&tempbp); + } + push(&tempw_int); + } + BP = tempw_int; + SP -= size; + handled = 1; + break; + + case 0xc0 ... 0xc1: /* rot imm8 */ + bits = 8 << (opcode & 1); + do_mod_rm(); + if (cpu_mod == 3) + wait_cycs(1, 0); + access(53, bits); + cpu_data = get_ea(); + cpu_src = pfq_fetchb(); + + wait_cycs((cpu_mod != 3) ? 9 : 6, 0); + + cpu_src &= 0x1F; + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + switch (rmdat & 0x38) { + case 0x00: /* ROL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x08: /* ROR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (cpu_state.flags & C_FLAG) + cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); + set_of_rotate(bits); + set_af(0); + break; + case 0x10: /* RCL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x18: /* RCR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (oldc) + cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); + set_cf((cpu_dest & 1) != 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x20: /* SHL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + set_of_rotate(bits); + set_af((cpu_data & 0x10) != 0); + set_pzs(bits); + break; + case 0x28: /* SHR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x30: /* SETMO - undocumented? */ + bitwise(bits, 0xffff); + set_cf(0); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x38: /* SAR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (!(opcode & 1)) + cpu_data |= (cpu_dest & 0x80); + else + cpu_data |= (cpu_dest & 0x8000); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + } + if ((opcode & 2) != 0) + wait_cycs(4, 0); + --cpu_src; + } + access(17, bits); + set_ea(cpu_data); + handled = 1; + break; + + case 0xc9: /* LEAVE/DISPOSE */ + SP = BP; + BP = pop(); + handled = 1; + break; + } + } + if (!handled) { + if (!is186 && !is_nec && (opcode >= 0x60) && (opcode <= 0x6f)) + opcode |= 0x10; + + switch (opcode) { + case 0x06: + case 0x0e: + case 0x16: + case 0x1e: /* PUSH seg */ + access(29, 16); + push(&(_opseg[(opcode >> 3) & 0x03]->seg)); + break; + case 0x07: + case 0x0f: + case 0x17: + case 0x1f: /* POP seg */ + access(22, 16); + if (opcode == 0x0f) { + load_cs(pop()); + pfq_pos = 0; + } else + load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); + wait_cycs(1, 0); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; + break; + + case 0x26: /* ES: */ + case 0x2e: /* CS: */ + case 0x36: /* SS: */ + case 0x3e: /* DS: */ + wait_cycs(1, 0); + ovr_seg = opseg[(opcode >> 3) & 0x03]; + completed = 0; + break; + + case 0x00 ... 0x03: /* alu rm, r / r, rm */ + case 0x08 ... 0x0b: + case 0x10 ... 0x13: + case 0x18 ... 0x1b: + case 0x20 ... 0x23: + case 0x28 ... 0x2b: + case 0x30 ... 0x33: + case 0x38 ... 0x3b: + bits = 8 << (opcode & 1); + do_mod_rm(); + access(46, bits); + tempw = get_ea(); + cpu_alu_op = (opcode >> 3) & 7; + 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_cycs(2, 0); + wait_cycs(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_cycs(1, 0); + } else { + set_reg(cpu_reg, cpu_data); + wait_cycs(1, 0); + } + } else + wait_cycs(1, 0); + break; + + case 0x04 ... 0x05: /* alu A, imm */ + case 0x0c ... 0x0d: + case 0x14 ... 0x15: + case 0x1c ... 0x1d: + case 0x24 ... 0x25: + case 0x2c ... 0x2d: + case 0x34 ... 0x35: + case 0x3c ... 0x3d: + bits = 8 << (opcode & 1); + wait_cycs(1, 0); + cpu_data = pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + cpu_alu_op = (opcode >> 3) & 7; + alu_op(bits); + if (cpu_alu_op != 7) + set_accum(bits, cpu_data); + wait_cycs(1, 0); + break; + + case 0x27: /* DAA */ + cpu_dest = AL; + set_of(0); + old_af = !!(cpu_state.flags & A_FLAG); + if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) { + cpu_src = 6; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + cpu_dest = cpu_data; + set_af(1); + } + if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { + cpu_src = 0x60; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + cpu_dest = cpu_data; + set_cf(1); + } + AL = cpu_dest; + set_pzs(8); + wait_cycs(3, 0); + break; + case 0x2f: /* DAS */ + cpu_dest = AL; + set_of(0); + old_af = !!(cpu_state.flags & A_FLAG); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + cpu_dest = cpu_data; + set_af(1); + } + if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { + cpu_src = 0x60; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + cpu_dest = cpu_data; + set_cf(1); + } + AL = cpu_dest; + set_pzs(8); + wait_cycs(3, 0); + break; + case 0x37: /* AAA */ + wait_cycs(1, 0); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + ++AH; + set_ca(); + } else { + cpu_src = 0; + clear_ca(); + wait_cycs(1, 0); + } + cpu_dest = AL; + cpu_data = cpu_dest + cpu_src; + set_of_add(8); + aa(); + break; + case 0x3f: /* AAS */ + wait_cycs(1, 0); + if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { + cpu_src = 6; + --AH; + set_ca(); + } else { + cpu_src = 0; + clear_ca(); + wait_cycs(1, 0); + } + cpu_dest = AL; + cpu_data = cpu_dest - cpu_src; + set_of_sub(8); + aa(); + break; + + case 0x40 ... 0x4f: /* INCDEC rw */ + wait_cycs(1, 0); + cpu_dest = cpu_state.regs[opcode & 7].w; + cpu_src = 1; + bits = 16; + if ((opcode & 8) == 0) { + cpu_data = cpu_dest + cpu_src; + set_of_add(bits); + } else { + cpu_data = cpu_dest - cpu_src; + set_of_sub(bits); + } + do_af(); + set_pzs(16); + cpu_state.regs[opcode & 7].w = cpu_data; + break; + + case 0x50 ... 0x57: /* PUSH r16 */ + access(30, 16); + push(&(cpu_state.regs[opcode & 0x07].w)); + break; + case 0x58 ... 0x5f: /* POP r16 */ + access(23, 16); + cpu_state.regs[opcode & 0x07].w = pop(); + wait_cycs(1, 0); + break; + + case 0x70 ... 0x71: /* JO, JNO */ + jcc(opcode, cpu_state.flags & V_FLAG); + break; + case 0x72 ... 0x73: /* JB, JNB */ + jcc(opcode, cpu_state.flags & C_FLAG); + break; + case 0x74 ... 0x75: /* JE, JNE */ + jcc(opcode, cpu_state.flags & Z_FLAG); + break; + case 0x76 ... 0x77: /* JBE, JBBE */ + jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); + break; + case 0x78 ... 0x79: /* JS, JNS */ + jcc(opcode, cpu_state.flags & N_FLAG); + break; + case 0x7a ... 0x7b: /* JP, JNP */ + jcc(opcode, cpu_state.flags & P_FLAG); + break; + case 0x7c ... 0x7d: /* JL, JNL */ + temp = (cpu_state.flags & N_FLAG) ? 1 : 0; + temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; + jcc(opcode, temp ^ temp2); + break; + case 0x7e ... 0x7f: /* JLE, JNLE */ + temp = (cpu_state.flags & N_FLAG) ? 1 : 0; + temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; + jcc(opcode, (cpu_state.flags & Z_FLAG) || (temp != temp2)); + break; + + case 0x80 ... 0x83: /* 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_cycs(3, 0); + if (opcode == 0x81) { + if (cpu_mod == 3) + wait_cycs(1, 0); + cpu_src = pfq_fetchw(); + } else { + if (cpu_mod == 3) + wait_cycs(1, 0); + if (opcode == 0x83) + cpu_src = sign_extend(pfq_fetchb()); + else + cpu_src = pfq_fetchb() | 0xff00; + } + wait_cycs(1, 0); + cpu_alu_op = (rmdat & 0x38) >> 3; + alu_op(bits); + if (cpu_alu_op != 7) { + access(11, bits); + set_ea(cpu_data); + } else { + if (cpu_mod != 3) + wait_cycs(1, 0); + } + break; + + case 0x84 ... 0x85: + /* 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_cycs(2, 0); + wait_cycs(2, 0); + break; + case 0x86 ... 0x87: + /* 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_cycs(3, 0); + access(12, bits); + set_ea(cpu_src); + break; + + case 0x88 ... 0x89: + /* MOV rm, reg */ + bits = 8 << (opcode & 1); + do_mod_rm(); + wait_cycs(1, 0); + access(13, bits); + set_ea(get_reg(cpu_reg)); + break; + case 0x8a ... 0x8b: + /* MOV reg, rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + access(50, bits); + set_reg(cpu_reg, get_ea()); + wait_cycs(1, 0); + if (cpu_mod != 3) + wait_cycs(2, 0); + break; + + case 0x8c: /* MOV w,sreg */ + do_mod_rm(); + if (cpu_mod == 3) + wait_cycs(1, 0); + access(14, 16); + seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); + break; + + case 0x8d: /* LEA */ + do_mod_rm(); + cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + wait_cycs(1, 0); + if (cpu_mod != 3) + wait_cycs(2, 0); + break; + + case 0x8e: /* MOV sreg,w */ + do_mod_rm(); + access(51, 16); + tempw = geteaw(); + if ((rmdat & 0x18) == 0x08) { + load_cs(tempw); + pfq_clear_pos(); + } else + load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); + wait_cycs(1, 0); + if (cpu_mod != 3) + wait_cycs(2, 0); + if (((rmdat & 0x18) >> 3) == 2) + noint = 1; + break; + + case 0x8f: /* POPW */ + do_mod_rm(); + wait_cycs(1, 0); + cpu_src = cpu_state.eaaddr; + access(24, 16); + if (cpu_mod != 3) + wait_cycs(2, 0); + cpu_data = pop(); + cpu_state.eaaddr = cpu_src; + wait_cycs(2, 0); + access(15, 16); + seteaw(cpu_data); + break; + + case 0x90 ... 0x97: /* XCHG AX, rw */ + wait_cycs(1, 0); + cpu_data = cpu_state.regs[opcode & 7].w; + cpu_state.regs[opcode & 7].w = AX; + AX = cpu_data; + wait_cycs(1, 0); + break; + + case 0x98: /* CBW */ + wait_cycs(1, 0); + AX = sign_extend(AL); + break; + case 0x99: /* CWD */ + wait_cycs(4, 0); + if (!top_bit(AX, 16)) + DX = 0; + else { + wait_cycs(1, 0); + DX = 0xffff; + } + break; + case 0x9a: /* CALL FAR */ + wait_cycs(1, 0); + new_ip = pfq_fetchw(); + wait_cycs(1, 0); + new_cs = pfq_fetchw(); + pfq_clear(); + access(31, 16); + push(&(CS)); + access(60, 16); + cpu_state.oldpc = cpu_state.pc; + load_cs(new_cs); + set_ip(new_ip); + access(32, 16); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x9b: /* WAIT */ + if (!repeating) + wait_cycs(2, 0); + wait_cycs(5, 0); +#ifdef NO_HACK + if (irq_pending(0)) { + wait_cycs(7, 0); + check_interrupts(0); + } else { + repeating = 1; + completed = 0; + clock_end(); + } +#else + wait_cycs(7, 0); + check_interrupts(); +#endif + break; + case 0x9c: /* PUSHF */ + access(33, 16); + tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + push(&tempw); + break; + case 0x9d: { /* POPF */ + uint16_t old_flags = cpu_state.flags; + access(25, 16); + cpu_state.flags = pop() | 0x0002; + wait_cycs(1, 0); + if ((old_flags ^ cpu_state.flags) & T_FLAG) + noint = 1; + break; + } case 0x9e: /* SAHF */ + wait_cycs(1, 0); + cpu_state.flags = (cpu_state.flags & 0xff02) | AH; + wait_cycs(2, 0); + break; + case 0x9f: /* LAHF */ + wait_cycs(1, 0); + AH = cpu_state.flags & 0xd7; + break; + + case 0xa0 ... 0xa1: /* MOV A, [iw] */ + bits = 8 << (opcode & 1); + wait_cycs(1, 0); + cpu_state.eaaddr = pfq_fetchw(); + access(1, bits); + set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); + wait_cycs(1, 0); + break; + case 0xa2 ... 0xa3: /* MOV [iw], A */ + bits = 8 << (opcode & 1); + wait_cycs(1, 0); + cpu_state.eaaddr = pfq_fetchw(); + access(7, bits); + writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); + break; + + case 0xa4 ... 0xa5: /* MOVS */ + case 0xac ... 0xad: /* LODS */ + bits = 8 << (opcode & 1); + if (!repeating) { + wait_cycs(1, 0); + if ((opcode & 8) == 0 && in_rep != 0) + wait_cycs(1, 0); + } + if (rep_action(bits)) { + wait_cycs(1, 0); + if ((opcode & 8) != 0) + wait_cycs(1, 0); + break; + } + if (in_rep != 0 && (opcode & 8) != 0) + wait_cycs(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_cycs(2, 0); + } + if (in_rep == 0) { + wait_cycs(3, 0); + if ((opcode & 8) != 0) + wait_cycs(1, 0); + break; + } + repeating = 1; + if (!is_nec) + clock_end(); + break; + + case 0xa6 ... 0xa7: /* CMPS */ + case 0xae ... 0xaf: /* SCAS */ + bits = 8 << (opcode & 1); + if (!repeating) + wait_cycs(1, 0); + if (rep_action(bits)) { + wait_cycs(2, 0); + break; + } + if (in_rep != 0) + wait_cycs(1, 0); + wait_cycs(1, 0); + cpu_dest = get_accum(bits); + if ((opcode & 8) == 0) { + access(21, bits); + lods(bits); + wait_cycs(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_cycs(2, 0); + if (in_rep == 0) { + wait_cycs(3, 0); + break; + } + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { + completed = 1; + wait_cycs(4, 0); + break; + } + repeating = 1; + if (!is_nec) + clock_end(); + break; + + case 0xa8 ... 0xa9: /* TEST A, imm */ + bits = 8 << (opcode & 1); + wait_cycs(1, 0); + cpu_data = pfq_fetch(); + test(bits, get_accum(bits), cpu_data); + wait_cycs(1, 0); + break; + + case 0xaa ... 0xab: /* STOS */ + bits = 8 << (opcode & 1); + if (!repeating) { + wait_cycs(1, 0); + if (in_rep != 0) + wait_cycs(1, 0); + } + if (rep_action(bits)) { + wait_cycs(1, 0); + break; + } + cpu_data = AX; + access(28, bits); + stos(bits); + if (in_rep == 0) { + wait_cycs(3, 0); + break; + } + repeating = 1; + if (!is_nec) + clock_end(); + break; + + case 0xb0 ... 0xb7: /* MOV cpu_reg,#8 */ + wait_cycs(1, 0); + if (opcode & 0x04) + cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); + else + cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); + wait_cycs(1, 0); + break; + + case 0xb8 ... 0xbf: /* MOV cpu_reg,#16 */ + wait_cycs(1, 0); + cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); + wait_cycs(1, 0); + break; + + case 0xc0 ... 0xc3: /* RET */ + case 0xc8 ... 0xcb: + bits = 8 + (opcode & 0x08); + if ((opcode & 9) != 1) + wait_cycs(1, 0); + if (!(opcode & 1)) { + cpu_src = pfq_fetchw(); + wait_cycs(1, 0); + } + if ((opcode & 9) == 9) + wait_cycs(1, 0); + pfq_clear(); + access(26, bits); + new_ip = pop(); + wait_cycs(2, 0); + if ((opcode & 8) == 0) + new_cs = CS; + else { + access(42, bits); + new_cs = pop(); + if (opcode & 1) + wait_cycs(1, 0); + } + if (!(opcode & 1)) { + SP += cpu_src; + wait_cycs(1, 0); + } + load_cs(new_cs); + access(72, bits); + set_ip(new_ip); + break; + + case 0xc4 ... 0xc5: /* LsS rw, rmd */ + do_mod_rm(); + bits = 16; + access(52, bits); + read_ea(1, bits); + cpu_state.regs[cpu_reg].w = cpu_data; + access(57, bits); + read_ea2(bits); + load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); + wait_cycs(1, 0); + break; + + case 0xc6 ... 0xc7: /* MOV rm, imm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + wait_cycs(1, 0); + if (cpu_mod != 3) + wait_cycs(2, 0); + cpu_data = pfq_fetch(); + if (cpu_mod == 3) + wait_cycs(1, 0); + access(16, bits); + set_ea(cpu_data); + break; + + case 0xcc: /* INT 3 */ + interrupt(3); + break; + case 0xcd: /* INT */ + wait_cycs(1, 0); + interrupt(pfq_fetchb()); + break; + case 0xce: /* INTO */ + wait_cycs(3, 0); + if (cpu_state.flags & V_FLAG) { + wait_cycs(2, 0); + interrupt(4); + } + break; + case 0xcf: /* IRET */ + access(43, 8); + new_ip = pop(); + wait_cycs(3, 0); + access(44, 8); + new_cs = pop(); + load_cs(new_cs); + access(62, 8); + set_ip(new_ip); + access(45, 8); + cpu_state.flags = pop() | 0x0002; + wait_cycs(5, 0); + noint = 2; + nmi_enable = 1; + break; + + case 0xd0 ... 0xd3: /* rot rm */ + bits = 8 << (opcode & 1); + do_mod_rm(); + if (cpu_mod == 3) + wait_cycs(1, 0); + access(53, bits); + cpu_data = get_ea(); + if ((opcode & 2) == 0) { + cpu_src = 1; + wait_cycs((cpu_mod != 3) ? 4 : 0, 0); + } else { + cpu_src = CL; + wait_cycs((cpu_mod != 3) ? 9 : 6, 0); + } + if (is186) + cpu_src &= 0x1f; + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + switch (rmdat & 0x38) { + case 0x00: /* ROL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x08: /* ROR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (cpu_state.flags & C_FLAG) + cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); + set_of_rotate(bits); + set_af(0); + break; + case 0x10: /* RCL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x18: /* RCR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (oldc) + cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); + set_cf((cpu_dest & 1) != 0); + set_of_rotate(bits); + set_af(0); + break; + case 0x20: /* SHL */ + set_cf(top_bit(cpu_data, bits)); + cpu_data <<= 1; + set_of_rotate(bits); + set_af((cpu_data & 0x10) != 0); + set_pzs(bits); + break; + case 0x28: /* SHR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x30: /* SETMO - undocumented? */ + bitwise(bits, 0xffff); + set_cf(0); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + case 0x38: /* SAR */ + set_cf((cpu_data & 1) != 0); + cpu_data >>= 1; + if (!(opcode & 1)) + cpu_data |= (cpu_dest & 0x80); + else + cpu_data |= (cpu_dest & 0x8000); + set_of_rotate(bits); + set_af(0); + set_pzs(bits); + break; + } + if ((opcode & 2) != 0) + wait_cycs(4, 0); + --cpu_src; + } + access(17, bits); + set_ea(cpu_data); + break; + + case 0xd4: /* AAM */ + wait_cycs(1, 0); + cpu_src = pfq_fetchb(); + if (x86_div(AL, 0)) { + cpu_data = AL; + set_pzs(8); + } + break; + case 0xd5: /* AAD */ + wait_cycs(1, 0); + mul(pfq_fetchb(), AH); + cpu_dest = AL; + cpu_src = cpu_data; + add(8); + AL = cpu_data; + AH = 0x00; + set_pzs(8); + break; + case 0xd6: /* SALC */ + wait_cycs(1, 0); + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; + wait_cycs(1, 0); + break; + case 0xd7: /* XLATB */ + cpu_state.eaaddr = (BX + AL) & 0xffff; + access(4, 8); + AL = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + wait_cycs(1, 0); + break; + + case 0xd8 ... 0xdf: /* esc i, r, rm */ + do_mod_rm(); + access(54, 16); + tempw = cpu_state.pc; + if (!hasfpu) + geteaw(); + else 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; + } + cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on + the 286+ core, but not here. */ + wait_cycs(1, 0); + if (cpu_mod != 3) + wait_cycs(2, 0); + break; + + case 0xe0 ... 0xe3: /* LOOP */ + wait_cycs(3, 0); + cpu_data = pfq_fetchb(); + if (opcode != 0xe2) + wait_cycs(1, 0); + if (opcode != 0xe3) { + --CX; + oldc = (CX != 0); + switch (opcode) { + case 0xe0: + if (cpu_state.flags & Z_FLAG) + oldc = 0; + break; + case 0xe1: + if (!(cpu_state.flags & Z_FLAG)) + oldc = 0; + break; + } + } else + oldc = (CX == 0); + if (oldc) + jump_short(); + break; + + case 0xe4 ... 0xe7: + case 0xec ... 0xef: + bits = 8 << (opcode & 1); + if ((opcode & 0x0e) != 0x0c) + wait_cycs(1, 0); + if ((opcode & 8) == 0) + cpu_data = pfq_fetchb(); + else + cpu_data = DX; + cpu_state.eaaddr = cpu_data; + if ((opcode & 2) == 0) { + access(3, bits); + if (opcode & 1) + cpu_io(16, 0, cpu_data); + else + cpu_io(8, 0, cpu_data); + wait_cycs(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_cycs(1, 0); + cpu_state.oldpc = jump_near(); + access(34, 8); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0xe9: /* JMP rel 16 */ + wait_cycs(1, 0); + jump_near(); + break; + case 0xea: /* JMP far */ + wait_cycs(1, 0); + addr = pfq_fetchw(); + wait_cycs(1, 0); + tempw = pfq_fetchw(); + load_cs(tempw); + access(70, 8); + pfq_clear(); + set_ip(addr); + break; + case 0xeb: /* JMP rel */ + wait_cycs(1, 0); + cpu_data = (int8_t) pfq_fetchb(); + jump_short(); + wait_cycs(1, 0); + break; + + case 0xf0 ... 0xf1: /*LOCK - F1 is alias*/ + in_lock = 1; + wait_cycs(1, 0); + completed = 0; + break; + + case 0xf2 ... 0xf3: /* REPNE, REPE */ + wait_cycs(1, 0); + in_rep = (opcode == 0xf2 ? 1 : 2); + completed = 0; + rep_c_flag = 0; + break; + + case 0xf4: /* HLT */ + if (!repeating) { + wait_cycs(1, 0); + pfq_clear(); + } + wait_cycs(1, 0); + if (irq_pending()) { + wait_cycs(cycles & 1, 0); + check_interrupts(); + } else { + repeating = 1; + completed = 0; + clock_end(); + } + break; + case 0xf5: /* CMC */ + wait_cycs(1, 0); + cpu_state.flags ^= C_FLAG; + break; + + case 0xf6 ... 0xf7: + bits = 8 << (opcode & 1); + do_mod_rm(); + access(55, bits); + cpu_data = get_ea(); + switch (rmdat & 0x38) { + case 0x00: case 0x08: /* TEST */ + wait_cycs(2, 0); + if (cpu_mod != 3) + wait_cycs(1, 0); + cpu_src = pfq_fetch(); + wait_cycs(1, 0); + test(bits, cpu_data, cpu_src); + if (cpu_mod != 3) + wait_cycs(1, 0); + break; + case 0x10: case 0x18: /* NOT, NEG */ + wait_cycs(2, 0); + if ((rmdat & 0x38) == 0x10) + cpu_data = ~cpu_data; + else { + cpu_src = cpu_data; + cpu_dest = 0; + sub(bits); + } + access(18, bits); + set_ea(cpu_data); + break; + case 0x20: case 0x28: /* MUL, IMUL */ + wait_cycs(1, 0); + mul(get_accum(bits), cpu_data); + if (opcode & 1) { + AX = cpu_data; + DX = cpu_dest; + 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)); + cpu_data = AH; + } + set_sf(bits); + set_pf(); + if (cpu_mod != 3) + wait_cycs(1, 0); + break; + case 0x30: case 0x38: /* DIV, IDIV */ + if (cpu_mod != 3) + wait_cycs(1, 0); + cpu_src = cpu_data; + if (x86_div(AL, AH)) + wait_cycs(1, 0); + break; + } + break; + + case 0xf8 ... 0xf9: /* CLCSTC */ + wait_cycs(1, 0); + set_cf(opcode & 1); + break; + case 0xfa ... 0xfb: /* CLISTI */ + wait_cycs(1, 0); + set_if(opcode & 1); + break; + case 0xfc ... 0xfd: /* CLDSTD */ + wait_cycs(1, 0); + set_df(opcode & 1); + break; + + case 0xfe ... 0xff: /* 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: case 0x08: /* INC rm, DEC rm */ + cpu_dest = cpu_data; + cpu_src = 1; + if ((rmdat & 0x38) == 0x00) { + cpu_data = cpu_dest + cpu_src; + set_of_add(bits); + } else { + cpu_data = cpu_dest - cpu_src; + set_of_sub(bits); + } + do_af(); + set_pzs(bits); + wait_cycs(2, 0); + access(19, bits); + set_ea(cpu_data); + break; + case 0x10: /* CALL rm */ + cpu_data_opff_rm(); + access(63, bits); + wait_cycs(1, 0); + pfq_clear(); + wait_cycs(4, 0); + if (cpu_mod != 3) + wait_cycs(1, 0); + wait_cycs(1, 0); /* Wait. */ + cpu_state.oldpc = cpu_state.pc; + set_ip(cpu_data); + wait_cycs(2, 0); + access(35, bits); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x18: /* CALL rmd */ + new_ip = cpu_data; + access(58, bits); + read_ea2(bits); + if (!(opcode & 1)) + cpu_data |= 0xff00; + new_cs = cpu_data; + access(36, bits); + push(&(CS)); + access(64, bits); + wait_cycs(4, 0); + cpu_state.oldpc = cpu_state.pc; + load_cs(new_cs); + set_ip(new_ip); + access(37, bits); + push((uint16_t *) &(cpu_state.oldpc)); + break; + case 0x20: /* JMP rm */ + cpu_data_opff_rm(); + access(65, bits); + set_ip(cpu_data); + break; + case 0x28: /* JMP rmd */ + new_ip = cpu_data; + 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: case 0x38: /* PUSH rm */ + if (cpu_mod != 3) + wait_cycs(1, 0); + access(38, bits); + push((uint16_t *) &(cpu_data)); + break; + } + break; + + default: + x808x_log("Illegal opcode: %02X\n", opcode); + pfq_fetchb(); + wait_cycs(8, 0); + break; + } + } +} + +/* Executes instructions up to the specified number of cycles. */ +void +execx86(int cycs) +{ cycles += cycs; while (cycles > 0) { @@ -1795,7 +3267,6 @@ execx86(int cycs) if (!repeating) { cpu_state.oldpc = cpu_state.pc; opcode = pfq_fetchb(); - handled = 0; oldc = cpu_state.flags & C_FLAG; if (clear_lock) { in_lock = 0; @@ -1804,1551 +3275,7 @@ execx86(int cycs) wait_cycs(1, 0); } - completed = 1; - // pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); - if (is186) { - switch (opcode) { - case 0x60: /*PUSHA/PUSH R*/ - orig_sp = SP; - wait_cycs(1, 0); - push(&AX); - push(&CX); - push(&DX); - push(&BX); - push(&orig_sp); - push(&BP); - push(&SI); - push(&DI); - handled = 1; - break; - case 0x61: /*POPA/POP R*/ - wait_cycs(9, 0); - DI = pop(); - SI = pop(); - BP = pop(); - (void) pop(); /* former orig_sp */ - BX = pop(); - DX = pop(); - CX = pop(); - AX = pop(); - handled = 1; - break; - - case 0x62: /* BOUND r/m */ - lowbound = 0; - highbound = 0; - regval = 0; - do_mod_rm(); - - lowbound = readmemw(easeg, cpu_state.eaaddr); - highbound = readmemw(easeg, cpu_state.eaaddr + 2); - regval = get_reg(cpu_reg); - if (lowbound > regval || highbound < regval) { - cpu_state.pc = cpu_state.oldpc; - interrupt(5); - } - handled = 1; - break; - - case 0x68: - wordtopush = pfq_fetchw(); - wait_cycs(1, 0); - push(&wordtopush); - handled = 1; - break; - - case 0x69: - immediate = 0; - bits = 16; - do_mod_rm(); - read_ea(0, 16); - immediate = pfq_fetchw(); - mul(cpu_data & 0xFFFF, immediate); - set_reg(cpu_reg, cpu_data); - set_co_mul(16, cpu_dest != 0); - handled = 1; - break; - - case 0x6a: - wordtopush = sign_extend(pfq_fetchb()); - push(&wordtopush); - handled = 1; - break; - - case 0x6b: /* IMUL reg16,reg16/mem16,imm8 */ - immediate = 0; - bits = 16; - do_mod_rm(); - read_ea(0, 16); - immediate = pfq_fetchb(); - mul(cpu_data & 0xFFFF, immediate); - set_reg(cpu_reg, cpu_data); - set_co_mul(16, cpu_dest != 0); - handled = 1; - break; - - case 0x6c: - case 0x6d: /* INM dst, DW/INS dst, DX */ - bits = 8 << (opcode & 1); - handled = 1; - if (!repeating) - wait_cycs(2, 0); - - if (rep_action(bits)) - break; - else if (!repeating) - wait_cycs(7, 0); - - if (bits == 16) { - writememw(es, DI, cpu_inw(DX)); - DI += (cpu_state.flags & D_FLAG) ? -2 : 2; - } else { - writememb(es, DI, cpu_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 */ - dest_seg = ovr_seg ? *ovr_seg : ds; - bits = 8 << (opcode & 1); - handled = 1; - if (!repeating) - wait_cycs(2, 0); - - if (rep_action(bits)) - break; - else if (!repeating) - wait_cycs(7, 0); - - if (bits == 16) { - cpu_outw(DX, readmemw(dest_seg, SI)); - SI += (cpu_state.flags & D_FLAG) ? -2 : 2; - } else { - cpu_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 */ - tempw_int = 0; - size = pfq_fetchw(); - nests = pfq_fetchb(); - - push(&BP); - tempw_int = SP; - if (nests > 0) { - while (--nests) { - tempbp = 0; - BP -= 2; - tempbp = readmemw(ss, BP); - push(&tempbp); - } - push(&tempw_int); - } - BP = tempw_int; - SP -= size; - handled = 1; - break; - - case 0xc0: - case 0xc1: /*rot imm8 */ - bits = 8 << (opcode & 1); - do_mod_rm(); - if (cpu_mod == 3) - wait_cycs(1, 0); - access(53, bits); - cpu_data = get_ea(); - cpu_src = pfq_fetchb(); - - wait_cycs((cpu_mod != 3) ? 9 : 6, 0); - - cpu_src &= 0x1F; - while (cpu_src != 0) { - cpu_dest = cpu_data; - oldc = cpu_state.flags & C_FLAG; - switch (rmdat & 0x38) { - case 0x00: /* ROL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x08: /* ROR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (cpu_state.flags & C_FLAG) - cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); - set_of_rotate(bits); - set_af(0); - break; - case 0x10: /* RCL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x18: /* RCR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (oldc) - cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); - set_cf((cpu_dest & 1) != 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x20: /* SHL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - set_of_rotate(bits); - set_af((cpu_data & 0x10) != 0); - set_pzs(bits); - break; - case 0x28: /* SHR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x30: /* SETMO - undocumented? */ - bitwise(bits, 0xffff); - set_cf(0); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x38: /* SAR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (!(opcode & 1)) - cpu_data |= (cpu_dest & 0x80); - else - cpu_data |= (cpu_dest & 0x8000); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - } - if ((opcode & 2) != 0) - wait_cycs(4, 0); - --cpu_src; - } - access(17, bits); - set_ea(cpu_data); - handled = 1; - break; - - case 0xc9: /* LEAVE/DISPOSE */ - SP = BP; - BP = pop(); - handled = 1; - break; - } - } - if (!handled) { - switch (opcode) { - case 0x06: - case 0x0E: - case 0x16: - case 0x1E: /* PUSH seg */ - access(29, 16); - push(&(_opseg[(opcode >> 3) & 0x03]->seg)); - break; - case 0x07: - case 0x0F: - case 0x17: - case 0x1F: /* POP seg */ - access(22, 16); - if (opcode == 0x0F) { - load_cs(pop()); - pfq_pos = 0; - } else - load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); - wait_cycs(1, 0); - /* All POP segment instructions suppress interrupts for one instruction. */ - noint = 1; - break; - - case 0x26: /*ES:*/ - case 0x2E: /*CS:*/ - case 0x36: /*SS:*/ - case 0x3E: /*DS:*/ - wait_cycs(1, 0); - ovr_seg = opseg[(opcode >> 3) & 0x03]; - completed = 0; - break; - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x38: - case 0x39: - case 0x3a: - 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; - 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_cycs(2, 0); - wait_cycs(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_cycs(1, 0); - } else { - set_reg(cpu_reg, cpu_data); - wait_cycs(1, 0); - } - } else - wait_cycs(1, 0); - break; - - 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: - /* alu A, imm */ - bits = 8 << (opcode & 1); - wait_cycs(1, 0); - cpu_data = pfq_fetch(); - cpu_dest = get_accum(bits); /* AX/AL */ - cpu_src = cpu_data; - cpu_alu_op = (opcode >> 3) & 7; - alu_op(bits); - if (cpu_alu_op != 7) - set_accum(bits, cpu_data); - wait_cycs(1, 0); - break; - - case 0x27: /*DAA*/ - cpu_dest = AL; - set_of(0); - old_af = !!(cpu_state.flags & A_FLAG); - if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) { - cpu_src = 6; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - cpu_dest = cpu_data; - set_af(1); - } - if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { - cpu_src = 0x60; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - cpu_dest = cpu_data; - set_cf(1); - } - AL = cpu_dest; - set_pzs(8); - wait_cycs(3, 0); - break; - case 0x2F: /*DAS*/ - cpu_dest = AL; - set_of(0); - old_af = !!(cpu_state.flags & A_FLAG); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - cpu_dest = cpu_data; - set_af(1); - } - if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) { - cpu_src = 0x60; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - cpu_dest = cpu_data; - set_cf(1); - } - AL = cpu_dest; - set_pzs(8); - wait_cycs(3, 0); - break; - case 0x37: /*AAA*/ - wait_cycs(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - ++AH; - set_ca(); - } else { - cpu_src = 0; - clear_ca(); - wait_cycs(1, 0); - } - cpu_dest = AL; - cpu_data = cpu_dest + cpu_src; - set_of_add(8); - aa(); - break; - case 0x3F: /*AAS*/ - wait_cycs(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_src = 6; - --AH; - set_ca(); - } else { - cpu_src = 0; - clear_ca(); - wait_cycs(1, 0); - } - cpu_dest = AL; - cpu_data = cpu_dest - cpu_src; - set_of_sub(8); - aa(); - break; - - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - /* INCDEC rw */ - wait_cycs(1, 0); - cpu_dest = cpu_state.regs[opcode & 7].w; - cpu_src = 1; - bits = 16; - if ((opcode & 8) == 0) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(16); - cpu_state.regs[opcode & 7].w = cpu_data; - break; - - case 0x50: - case 0x51: - case 0x52: - case 0x53: /*PUSH r16*/ - case 0x54: - case 0x55: - case 0x56: - case 0x57: - access(30, 16); - push(&(cpu_state.regs[opcode & 0x07].w)); - break; - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: /*POP r16*/ - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - access(23, 16); - cpu_state.regs[opcode & 0x07].w = pop(); - wait_cycs(1, 0); - break; - - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - jcc(opcode, cpu_state.flags & V_FLAG); - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - jcc(opcode, cpu_state.flags & C_FLAG); - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - jcc(opcode, cpu_state.flags & Z_FLAG); - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - jcc(opcode, cpu_state.flags & N_FLAG); - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - jcc(opcode, cpu_state.flags & P_FLAG); - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, temp ^ temp2); - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, (cpu_state.flags & Z_FLAG) || (temp != temp2)); - break; - - case 0x80: - case 0x81: - case 0x82: - case 0x83: - /* 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_cycs(3, 0); - if (opcode == 0x81) { - if (cpu_mod == 3) - wait_cycs(1, 0); - cpu_src = pfq_fetchw(); - } else { - if (cpu_mod == 3) - wait_cycs(1, 0); - if (opcode == 0x83) - cpu_src = sign_extend(pfq_fetchb()); - else - cpu_src = pfq_fetchb() | 0xff00; - } - wait_cycs(1, 0); - cpu_alu_op = (rmdat & 0x38) >> 3; - alu_op(bits); - if (cpu_alu_op != 7) { - access(11, bits); - set_ea(cpu_data); - } else { - if (cpu_mod != 3) - wait_cycs(1, 0); - } - break; - - case 0x84: - case 0x85: - /* 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_cycs(2, 0); - wait_cycs(2, 0); - break; - case 0x86: - case 0x87: - /* 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_cycs(3, 0); - access(12, bits); - set_ea(cpu_src); - break; - - case 0x88: - case 0x89: - /* MOV rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait_cycs(1, 0); - access(13, bits); - set_ea(get_reg(cpu_reg)); - break; - case 0x8A: - case 0x8B: - /* MOV reg, rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(50, bits); - set_reg(cpu_reg, get_ea()); - wait_cycs(1, 0); - if (cpu_mod != 3) - wait_cycs(2, 0); - break; - - case 0x8C: /*MOV w,sreg*/ - do_mod_rm(); - if (cpu_mod == 3) - wait_cycs(1, 0); - access(14, 16); - seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); - break; - - case 0x8D: /*LEA*/ - do_mod_rm(); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - wait_cycs(1, 0); - if (cpu_mod != 3) - wait_cycs(2, 0); - break; - - case 0x8E: /*MOV sreg,w*/ - do_mod_rm(); - access(51, 16); - tempw = geteaw(); - if ((rmdat & 0x18) == 0x08) { - load_cs(tempw); - pfq_pos = 0; - } else - load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); - wait_cycs(1, 0); - if (cpu_mod != 3) - wait_cycs(2, 0); - if (((rmdat & 0x18) >> 3) == 2) - noint = 1; - break; - - case 0x8F: /*POPW*/ - do_mod_rm(); - wait_cycs(1, 0); - cpu_src = cpu_state.eaaddr; - access(24, 16); - if (cpu_mod != 3) - wait_cycs(2, 0); - cpu_data = pop(); - cpu_state.eaaddr = cpu_src; - wait_cycs(2, 0); - access(15, 16); - seteaw(cpu_data); - break; - - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - /* XCHG AX, rw */ - wait_cycs(1, 0); - cpu_data = cpu_state.regs[opcode & 7].w; - cpu_state.regs[opcode & 7].w = AX; - AX = cpu_data; - wait_cycs(1, 0); - break; - - case 0x98: /*CBW*/ - wait_cycs(1, 0); - AX = sign_extend(AL); - break; - case 0x99: /*CWD*/ - wait_cycs(4, 0); - if (!top_bit(AX, 16)) - DX = 0; - else { - wait_cycs(1, 0); - DX = 0xffff; - } - break; - case 0x9A: /*CALL FAR*/ - wait_cycs(1, 0); - new_ip = pfq_fetchw(); - wait_cycs(1, 0); - new_cs = pfq_fetchw(); - pfq_clear(); - access(31, 16); - push(&(CS)); - access(60, 16); - cpu_state.oldpc = cpu_state.pc; - load_cs(new_cs); - set_ip(new_ip); - access(32, 16); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x9B: /*WAIT*/ - if (!repeating) - wait_cycs(2, 0); - wait_cycs(5, 0); -#ifdef NO_HACK - if (irq_pending(0)) { - wait_cycs(7, 0); - check_interrupts(0); - } else { - repeating = 1; - completed = 0; - clock_end(); - } -#else - wait_cycs(7, 0); - check_interrupts(); -#endif - break; - case 0x9C: /*PUSHF*/ - access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; - push(&tempw); - break; - case 0x9D: { /*POPF*/ - uint16_t old_flags = cpu_state.flags; - access(25, 16); - cpu_state.flags = pop() | 0x0002; - wait_cycs(1, 0); - if ((old_flags ^ cpu_state.flags) & T_FLAG) - noint = 1; - break; - } case 0x9E: /*SAHF*/ - wait_cycs(1, 0); - cpu_state.flags = (cpu_state.flags & 0xff02) | AH; - wait_cycs(2, 0); - break; - case 0x9F: /*LAHF*/ - wait_cycs(1, 0); - AH = cpu_state.flags & 0xd7; - break; - - case 0xA0: - case 0xA1: - /* MOV A, [iw] */ - bits = 8 << (opcode & 1); - wait_cycs(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(1, bits); - set_accum(bits, readmem((ovr_seg ? *ovr_seg : ds))); - wait_cycs(1, 0); - break; - case 0xA2: - case 0xA3: - /* MOV [iw], A */ - bits = 8 << (opcode & 1); - wait_cycs(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(7, bits); - writemem((ovr_seg ? *ovr_seg : ds), get_accum(bits)); - break; - - case 0xA4: - case 0xA5: /* MOVS */ - case 0xAC: - case 0xAD: /* LODS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait_cycs(1, 0); - if ((opcode & 8) == 0 && in_rep != 0) - wait_cycs(1, 0); - } - if (rep_action(bits)) { - wait_cycs(1, 0); - if ((opcode & 8) != 0) - wait_cycs(1, 0); - break; - } - if (in_rep != 0 && (opcode & 8) != 0) - wait_cycs(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_cycs(2, 0); - } - if (in_rep == 0) { - wait_cycs(3, 0); - if ((opcode & 8) != 0) - wait_cycs(1, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xA6: - case 0xA7: /* CMPS */ - case 0xAE: - case 0xAF: /* SCAS */ - bits = 8 << (opcode & 1); - if (!repeating) - wait_cycs(1, 0); - if (rep_action(bits)) { - wait_cycs(2, 0); - break; - } - if (in_rep != 0) - wait_cycs(1, 0); - wait_cycs(1, 0); - cpu_dest = get_accum(bits); - if ((opcode & 8) == 0) { - access(21, bits); - lods(bits); - wait_cycs(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_cycs(2, 0); - if (in_rep == 0) { - wait_cycs(3, 0); - break; - } - if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { - completed = 1; - wait_cycs(4, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xA8: - case 0xA9: - /* TEST A, imm */ - bits = 8 << (opcode & 1); - wait_cycs(1, 0); - cpu_data = pfq_fetch(); - test(bits, get_accum(bits), cpu_data); - wait_cycs(1, 0); - break; - - case 0xAA: - case 0xAB: /* STOS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait_cycs(1, 0); - if (in_rep != 0) - wait_cycs(1, 0); - } - if (rep_action(bits)) { - wait_cycs(1, 0); - break; - } - cpu_data = AX; - access(28, bits); - stos(bits); - if (in_rep == 0) { - wait_cycs(3, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: /*MOV cpu_reg,#8*/ - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - wait_cycs(1, 0); - if (opcode & 0x04) - cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); - else - cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); - wait_cycs(1, 0); - break; - - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - wait_cycs(1, 0); - cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); - wait_cycs(1, 0); - break; - - case 0xC0: - case 0xC1: - case 0xC2: - case 0xC3: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - /* RET */ - bits = 8 + (opcode & 0x08); - if ((opcode & 9) != 1) - wait_cycs(1, 0); - if (!(opcode & 1)) { - cpu_src = pfq_fetchw(); - wait_cycs(1, 0); - } - if ((opcode & 9) == 9) - wait_cycs(1, 0); - pfq_clear(); - access(26, bits); - new_ip = pop(); - wait_cycs(2, 0); - if ((opcode & 8) == 0) - new_cs = CS; - else { - access(42, bits); - new_cs = pop(); - if (opcode & 1) - wait_cycs(1, 0); - } - if (!(opcode & 1)) { - SP += cpu_src; - wait_cycs(1, 0); - } - load_cs(new_cs); - access(72, bits); - set_ip(new_ip); - break; - - case 0xC4: - case 0xC5: - /* LsS rw, rmd */ - do_mod_rm(); - bits = 16; - access(52, bits); - read_ea(1, bits); - cpu_state.regs[cpu_reg].w = cpu_data; - access(57, bits); - read_ea2(bits); - load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); - wait_cycs(1, 0); - break; - - case 0xC6: - case 0xC7: - /* MOV rm, imm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait_cycs(1, 0); - if (cpu_mod != 3) - wait_cycs(2, 0); - cpu_data = pfq_fetch(); - if (cpu_mod == 3) - wait_cycs(1, 0); - access(16, bits); - set_ea(cpu_data); - break; - - case 0xCC: /*INT 3*/ - interrupt(3); - break; - case 0xCD: /*INT*/ - wait_cycs(1, 0); - interrupt(pfq_fetchb()); - break; - case 0xCE: /*INTO*/ - wait_cycs(3, 0); - if (cpu_state.flags & V_FLAG) { - wait_cycs(2, 0); - interrupt(4); - } - break; - - case 0xCF: /*IRET*/ - access(43, 8); - new_ip = pop(); - wait_cycs(3, 0); - access(44, 8); - new_cs = pop(); - load_cs(new_cs); - access(62, 8); - set_ip(new_ip); - access(45, 8); - cpu_state.flags = pop() | 0x0002; - wait_cycs(5, 0); - noint = 2; - nmi_enable = 1; - break; - - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - /* rot rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - if (cpu_mod == 3) - wait_cycs(1, 0); - access(53, bits); - cpu_data = get_ea(); - if ((opcode & 2) == 0) { - cpu_src = 1; - wait_cycs((cpu_mod != 3) ? 4 : 0, 0); - } else { - cpu_src = CL; - wait_cycs((cpu_mod != 3) ? 9 : 6, 0); - } - if (is186) - cpu_src &= 0x1F; - while (cpu_src != 0) { - cpu_dest = cpu_data; - oldc = cpu_state.flags & C_FLAG; - switch (rmdat & 0x38) { - case 0x00: /* ROL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x08: /* ROR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (cpu_state.flags & C_FLAG) - cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); - set_of_rotate(bits); - set_af(0); - break; - case 0x10: /* RCL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x18: /* RCR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (oldc) - cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); - set_cf((cpu_dest & 1) != 0); - set_of_rotate(bits); - set_af(0); - break; - case 0x20: /* SHL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - set_of_rotate(bits); - set_af((cpu_data & 0x10) != 0); - set_pzs(bits); - break; - case 0x28: /* SHR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x30: /* SETMO - undocumented? */ - bitwise(bits, 0xffff); - set_cf(0); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x38: /* SAR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (!(opcode & 1)) - cpu_data |= (cpu_dest & 0x80); - else - cpu_data |= (cpu_dest & 0x8000); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - } - if ((opcode & 2) != 0) - wait_cycs(4, 0); - --cpu_src; - } - access(17, bits); - set_ea(cpu_data); - break; - - case 0xD4: /*AAM*/ - wait_cycs(1, 0); - cpu_src = pfq_fetchb(); - if (x86_div(AL, 0)) { - cpu_data = AL; - set_pzs(8); - } - break; - case 0xD5: /*AAD*/ - wait_cycs(1, 0); - mul(pfq_fetchb(), AH); - cpu_dest = AL; - cpu_src = cpu_data; - add(8); - AL = cpu_data; - AH = 0x00; - set_pzs(8); - break; - case 0xD6: /*SALC*/ - wait_cycs(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait_cycs(1, 0); - break; - case 0xD7: /*XLATB*/ - cpu_state.eaaddr = (BX + AL) & 0xffff; - access(4, 8); - AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); - wait_cycs(1, 0); - break; - - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDD: - case 0xDC: - case 0xDE: - case 0xDF: - /* esc i, r, rm */ - do_mod_rm(); - access(54, 16); - tempw = cpu_state.pc; - if (!hasfpu) - geteaw(); - else - 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; - } - } - cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on - the 286+ core, but not here. */ - wait_cycs(1, 0); - if (cpu_mod != 3) - wait_cycs(2, 0); - break; - - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - /* LOOP */ - wait_cycs(3, 0); - cpu_data = pfq_fetchb(); - if (opcode != 0xe2) - wait_cycs(1, 0); - if (opcode != 0xe3) { - --CX; - oldc = (CX != 0); - switch (opcode) { - case 0xE0: - if (cpu_state.flags & Z_FLAG) - oldc = 0; - break; - case 0xE1: - if (!(cpu_state.flags & Z_FLAG)) - oldc = 0; - break; - } - } else - oldc = (CX == 0); - if (oldc) - jump_short(); - break; - - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - bits = 8 << (opcode & 1); - if ((opcode & 0x0e) != 0x0c) - wait_cycs(1, 0); - if ((opcode & 8) == 0) - cpu_data = pfq_fetchb(); - else - cpu_data = DX; - cpu_state.eaaddr = cpu_data; - if ((opcode & 2) == 0) { - access(3, bits); - if (opcode & 1) - cpu_io(16, 0, cpu_data); - else - cpu_io(8, 0, cpu_data); - wait_cycs(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_cycs(1, 0); - cpu_state.oldpc = jump_near(); - access(34, 8); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0xE9: /*JMP rel 16*/ - wait_cycs(1, 0); - jump_near(); - break; - case 0xEA: /*JMP far*/ - wait_cycs(1, 0); - addr = pfq_fetchw(); - wait_cycs(1, 0); - tempw = pfq_fetchw(); - load_cs(tempw); - access(70, 8); - pfq_clear(); - set_ip(addr); - break; - case 0xEB: /*JMP rel*/ - wait_cycs(1, 0); - cpu_data = (int8_t) pfq_fetchb(); - jump_short(); - wait_cycs(1, 0); - break; - - case 0xF0: - case 0xF1: /*LOCK - F1 is alias*/ - in_lock = 1; - wait_cycs(1, 0); - completed = 0; - break; - - case 0xF2: /*REPNE*/ - case 0xF3: /*REPE*/ - wait_cycs(1, 0); - in_rep = (opcode == 0xf2 ? 1 : 2); - completed = 0; - rep_c_flag = 0; - break; - - case 0xF4: /*HLT*/ - if (!repeating) { - wait_cycs(1, 0); - pfq_clear(); - } - wait_cycs(1, 0); - if (irq_pending()) { - wait_cycs(cycles & 1, 0); - check_interrupts(); - } else { - repeating = 1; - completed = 0; - clock_end(); - } - break; - case 0xF5: /*CMC*/ - wait_cycs(1, 0); - cpu_state.flags ^= C_FLAG; - break; - - case 0xF6: - 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_cycs(2, 0); - if (cpu_mod != 3) - wait_cycs(1, 0); - cpu_src = pfq_fetch(); - wait_cycs(1, 0); - test(bits, cpu_data, cpu_src); - if (cpu_mod != 3) - wait_cycs(1, 0); - break; - case 0x10: /* NOT */ - case 0x18: /* NEG */ - wait_cycs(2, 0); - if ((rmdat & 0x38) == 0x10) - cpu_data = ~cpu_data; - else { - cpu_src = cpu_data; - cpu_dest = 0; - sub(bits); - } - access(18, bits); - set_ea(cpu_data); - break; - case 0x20: /* MUL */ - case 0x28: /* IMUL */ - wait_cycs(1, 0); - mul(get_accum(bits), cpu_data); - if (opcode & 1) { - AX = cpu_data; - DX = cpu_dest; - 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)); - cpu_data = AH; - } - set_sf(bits); - set_pf(); - if (cpu_mod != 3) - wait_cycs(1, 0); - break; - case 0x30: /* DIV */ - case 0x38: /* IDIV */ - if (cpu_mod != 3) - wait_cycs(1, 0); - cpu_src = cpu_data; - if (x86_div(AL, AH)) - wait_cycs(1, 0); - break; - } - break; - - case 0xF8: - case 0xF9: - /* CLCSTC */ - wait_cycs(1, 0); - set_cf(opcode & 1); - break; - case 0xFA: - case 0xFB: - /* CLISTI */ - wait_cycs(1, 0); - set_if(opcode & 1); - break; - case 0xFC: - case 0xFD: - /* CLDSTD */ - wait_cycs(1, 0); - set_df(opcode & 1); - break; - - case 0xFE: - case 0xFF: - /* 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 */ - case 0x08: /* DEC rm */ - cpu_dest = cpu_data; - cpu_src = 1; - if ((rmdat & 0x38) == 0x00) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(bits); - wait_cycs(2, 0); - access(19, bits); - set_ea(cpu_data); - break; - case 0x10: /* CALL rm */ - cpu_data_opff_rm(); - access(63, bits); - wait_cycs(1, 0); - pfq_clear(); - wait_cycs(4, 0); - if (cpu_mod != 3) - wait_cycs(1, 0); - wait_cycs(1, 0); /* Wait. */ - cpu_state.oldpc = cpu_state.pc; - set_ip(cpu_data); - wait_cycs(2, 0); - access(35, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x18: /* CALL rmd */ - new_ip = cpu_data; - access(58, bits); - read_ea2(bits); - if (!(opcode & 1)) - cpu_data |= 0xff00; - new_cs = cpu_data; - access(36, bits); - push(&(CS)); - access(64, bits); - wait_cycs(4, 0); - cpu_state.oldpc = cpu_state.pc; - load_cs(new_cs); - set_ip(new_ip); - access(37, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x20: /* JMP rm */ - cpu_data_opff_rm(); - access(65, bits); - set_ip(cpu_data); - break; - case 0x28: /* JMP rmd */ - new_ip = cpu_data; - 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_cycs(1, 0); - access(38, bits); - push((uint16_t *) &(cpu_data)); - break; - } - break; - - default: - x808x_log("Illegal opcode: %02X\n", opcode); - pfq_fetchb(); - wait_cycs(8, 0); - break; - } - } + execx86_instruction(); if (completed) { repeating = 0; diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index 42bd7cc4b..ab4fc5573 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -224,20 +224,6 @@ const uint8_t opf_0f[256] = { 0, 0, 0, 0, 0, 0, int nx = 0; -static uint32_t cpu_src = 0; -static uint32_t cpu_dest = 0; - -static uint32_t cpu_data = 0; - -static int oldc; -static int cpu_alu_op; -static int completed = 1; -static int in_rep = 0; -static int repeating = 0; -static int rep_c_flag = 0; -static int clear_lock = 0; -static int noint = 0; -static int tempc_fpu = 0; static int started = 0; static int group_delay = 0; static int modrm_loaded = 0; @@ -246,8 +232,6 @@ static int in_hlt = 0; static int retem = 0; static int halted = 0; -static uint32_t * ovr_seg = NULL; - /* Pointer tables needed for segment overrides. */ static uint32_t * opseg[4]; @@ -489,6 +473,8 @@ void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) void reset_vx0(int hard) { + reset_808x(hard); + halted = 0; in_hlt = 0; in_0f = 0; @@ -1854,9 +1840,53 @@ do_mod_rm(void) } static void -decode(void) +decode_modrm(void) { uint8_t op_f; + + modrm_loaded = 0; + + if (is_nec) { + if (in_0f) + op_f = (uint8_t) opf_0f[opcode]; + else + op_f = (uint8_t) opf_nec[opcode]; + } else + op_f = (uint8_t) opf[opcode]; + + if (op_f & OP_GRP) { + do_mod_rm(); + modrm_loaded = 1; + + op_f |= (OP_MRM | OP_EA); + + if (opcode >= 0xf0) { + op_f |= OP_DELAY; + group_delay = 1; + } + } + + if (!modrm_loaded && (op_f & OP_MRM)) { + do_mod_rm(); + modrm_loaded = 1; + } + + if (modrm_loaded && !(op_f & OP_EA)) { + if (is_nec) + do_cycle(); + else { + if (opcode == 0x8f) { + if (cpu_mod == 3) + do_cycles_i(2); + } else + do_cycles_i(2); + } + } +} + +static void +decode(void) +{ uint8_t prefix = 0; if (halted) @@ -1864,8 +1894,6 @@ decode(void) else opcode = biu_pfq_fetchb_common(); - modrm_loaded = 0; - while (1) { prefix = 0; @@ -1913,43 +1941,6 @@ decode(void) opcode = biu_pfq_fetchb_common(); } - - if (is_nec) { - if (in_0f) - op_f = (uint8_t) opf_0f[opcode]; - else - op_f = (uint8_t) opf_nec[opcode]; - } else - op_f = (uint8_t) opf[opcode]; - - if (op_f & OP_GRP) { - do_mod_rm(); - modrm_loaded = 1; - - op_f |= (OP_MRM | OP_EA); - - if (opcode >= 0xf0) { - op_f |= OP_DELAY; - group_delay = 1; - } - } - - if (!modrm_loaded && (op_f & OP_MRM)) { - do_mod_rm(); - modrm_loaded = 1; - } - - if (modrm_loaded && !(op_f & OP_EA)) { - if (is_nec) - do_cycle(); - else { - if (opcode == 0x8f) { - if (cpu_mod == 3) - do_cycles_i(2); - } else - do_cycles_i(2); - } - } } static void @@ -1992,6 +1983,10 @@ string_op(int bits) lods_di(bits); tmpa = cpu_data; lods(bits); + /* Swap them or else the operation goes wrong. */ + uint32_t tmpa2 = tmpa; + tmpa = cpu_data; + cpu_data = tmpa2; } else { lods(bits); tmpa = cpu_data; @@ -4735,7 +4730,16 @@ execvx0(int cycs) startx86(); } +#ifdef DEBUG_INSTRUCTIONS + if (repeating) { + if ((opcode >= 0xa0) && (opcode <= 0xaf) && (opcode != 0x8e)) { + execx86_instruction(); + goto check_completed; + } + } else { +#else if (!repeating) { +#endif cpu_state.oldpc = cpu_state.pc; if (clear_lock) { @@ -4743,9 +4747,21 @@ execvx0(int cycs) clear_lock = 0; } - if (!is_nec || (cpu_state.flags & MD_FLAG)) + if (!is_nec || (cpu_state.flags & MD_FLAG)) { decode(); +#ifdef DEBUG_INSTRUCTIONS + if ((opcode >= 0xa0) && (opcode <= 0xaf) && (opcode != 0x8e)) { + oldc = cpu_state.flags & C_FLAG; + + execx86_instruction(); + goto check_completed; + } +#endif + + decode_modrm(); + } + oldc = cpu_state.flags & C_FLAG; } @@ -4753,6 +4769,9 @@ execvx0(int cycs) execute_instruction(); +#ifdef DEBUG_INSTRUCTIONS +check_completed: +#endif if (completed) { if (opcode != 0xf4) finalize(); diff --git a/src/cpu/vx0_biu.h b/src/cpu/vx0_biu.h index 27d44797c..92eb661af 100644 --- a/src/cpu/vx0_biu.h +++ b/src/cpu/vx0_biu.h @@ -76,7 +76,8 @@ enum { DMA_STATE_OPERATING }; -/* Temporary BIU externs - move to 808x_biu.h. */ +extern void execx86_instruction(void); + extern void biu_resume_on_queue_read(void); extern void wait_vx0(int c); extern void biu_reset(void); @@ -106,6 +107,15 @@ extern void biu_wait_for_read_finish(void); extern uint8_t biu_preload_byte; extern int nx; +extern int oldc; +extern int cpu_alu_op; +extern int completed; +extern int in_rep; +extern int repeating; +extern int rep_c_flag; +extern int noint; +extern int tempc_fpu; +extern int clear_lock; extern int schedule_fetch; extern int in_lock; @@ -113,4 +123,11 @@ extern int bus_request_type; extern int pic_data; extern int biu_queue_preload; +extern uint32_t cpu_src; +extern uint32_t cpu_dest; + +extern uint32_t cpu_data; + +extern uint32_t *ovr_seg; + #endif /*EMU_808X_BIU_H*/