From a3fbb33e1078baf31ec9f79d601f4bab4ee78237 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 26 Jan 2026 09:40:24 +0100 Subject: [PATCH 01/31] Generic PCL Printer: Set language version to PCL 5C (PCL 5E is still supported as PCL 5C is a superset of it) and apply a few fixes, including no longer incorrectly processing the 1B 0E escape (it appears that's actually used as part of PCL 5C), fixes the HP Color LaserJet drivers when outputting to PDF. --- src/printer/prt_ps.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index adf57a523..bb153723c 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -156,7 +156,7 @@ convert_to_pdf(ps_t *dev) gsargv[arg++] = "-sDEVICE=pdfwrite"; if (dev->pcl) { gsargv[arg++] = "-LPCL"; - gsargv[arg++] = "-lPCL5E"; + gsargv[arg++] = "-lPCL5C"; } gsargv[arg++] = "-q"; gsargv[arg++] = "-o"; @@ -299,11 +299,14 @@ process_data(ps_t *dev) dev->pjl = false; else if (!memcmp(&(dev->buffer[dev->pjl_command_start]), "@PJL ENTER LANGUAGE=POSTSCRIPT", 0x1e)) fatal("Printing PostScript using the PCL printer is not (yet) supported!\n"); + dev->buffer[dev->buffer_pos] = 0x00; dev->buffer_pos = dev->pjl_command_start; } else if (!dev->pjl_command && (dev->buffer_pos >= 0x05) && !memcmp(&(dev->buffer[dev->buffer_pos - 0x5]), "@PJL ", 0x05)) { dev->pjl_command = true; dev->pjl_command_start = dev->buffer_pos - 0x05; - } + } else if (!dev->pjl_command && (dev->data == 0x1b)) + /* The universal exit code is also valid in PJL. */ + dev->pcl_escape = 1; dev->buffer[dev->buffer_pos] = 0; return; @@ -312,15 +315,6 @@ process_data(ps_t *dev) else switch (dev->pcl_escape) { case 1: dev->pcl_escape = (dev->data == 0x25) ? 2 : 0; - if (dev->data == 0x0e) { - dev->buffer[dev->buffer_pos++] = dev->data; - dev->buffer[dev->buffer_pos] = 0; - - if (dev->buffer_pos > 2) - write_buffer(dev, true); - - return; - } break; case 2: dev->pcl_escape = (dev->data == 0x2d) ? 3 : 0; @@ -342,8 +336,19 @@ process_data(ps_t *dev) break; case 8: dev->pcl_escape = 0; - if (dev->data == 0x58) + if (dev->data == 0x58) { dev->pjl = true; + + dev->buffer[dev->buffer_pos++] = dev->data; + dev->buffer[dev->buffer_pos] = 0; + + if (dev->pjl) + /* Wipe the slate clean so that there won't be a bogus empty page output to PDF. */ + dev->pending = false; + else if (dev->buffer_pos > 9) + write_buffer(dev, true); + return; + } break; } } else if ((dev->data < 0x20) || (dev->data == 0x7f)) { From 9c27adeef5593183524f435244cdf8f058e452b5 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 26 Jan 2026 18:02:23 +0100 Subject: [PATCH 02/31] Some clean up on 8514/A 1. Remove more hacks usually placed for stuff to make them work, now stuff works per manual. 2. Pixtrans reads are no longer written in the accelerator function per manual. Warning: I still don't know how to properly fix the 8514/A bug on win2.x paint/pbrush, the commands are fine as well as the rop/mixes and the coordinates as well, I need help for this. --- src/video/vid_8514a.c | 942 +++++++++++++++++++++--------------------- 1 file changed, 461 insertions(+), 481 deletions(-) diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index ca7e182b0..872743b72 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -261,8 +261,8 @@ void ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint8_t nibble = 0; - uint32_t pixelxfer = 0; + uint8_t nibble = 0x0000; + uint32_t pixelxfer = 0x00000000; uint32_t monoxfer = 0xffffffff; int pixcnt = 0; int pixcntl = (dev->accel.multifunc[0x0a] >> 6) & 3; @@ -289,8 +289,23 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in val = (val >> 8) | (val << 8); } if ((cmd <= 2) || (cmd == 4) || (cmd == 6)) { - if ((dev->accel.cmd & 0x08) && (cmd >= 1)) { - monoxfer = val; + if (dev->accel.cmd & 0x08) { + if (val & 0x02) + nibble |= 0x08; + if (val & 0x04) + nibble |= 0x04; + if (val & 0x08) + nibble |= 0x02; + if (val & 0x10) + nibble |= 0x01; + if (val & 0x200) + nibble |= 0x80; + if (val & 0x400) + nibble |= 0x40; + if (val & 0x800) + nibble |= 0x20; + if (val & 0x1000) + nibble |= 0x10; } else { if (val & 0x02) nibble |= 0x80; @@ -308,9 +323,8 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in nibble |= 0x02; if (val & 0x1000) nibble |= 0x01; - - monoxfer = nibble; } + monoxfer = nibble; } else monoxfer = val; } else @@ -545,7 +559,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; - ibm8514_log("8514/A CMD=%04x, frgd color=%04x, frgdmix=%02x, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.frgd_color, dev->accel.frgd_mix, dev->accel.multifunc[0x0a]); + ibm8514_log("8514A CMDflags=%04x, frgd color=%04x, frgdmix=%02x, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.frgd_color, dev->accel.frgd_mix, dev->accel.multifunc[0x0a]); ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; @@ -894,9 +908,6 @@ ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) } ibm8514_accel_out_pixtrans(svga, port, (temp >> 8) & 0xff, len); } else { - if (dev->accel.input3) - temp = 0xffff; - ibm8514_accel_out_pixtrans(svga, port, temp, len); } } @@ -981,6 +992,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) dev->data_available2 = 0; temp |= INT_FIFO_EMP; } + if (!dev->fifo_idx) { + if (dev->accel.cmd_back) + temp |= 0x800; + } temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); temp |= 0x20; } @@ -1070,6 +1085,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat uint16_t bkgd_color = dev->accel.bkgd_color; uint32_t old_mix_dat; int and3 = dev->accel.cur_x & 3; + int and3_blt = dev->accel.destx & 3; int poly_src; if (!dev->bpp) { @@ -1229,7 +1245,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if (dev->accel.ssv_draw) { if ((dev->accel.cmd & 0x04) && dev->accel.ssv_len) { WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); @@ -1300,42 +1315,44 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; + if (ibm8514_cpu_src(svga) || !cpu_input) { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; - default: - break; - } + default: + break; + } - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & mix_mask, dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if (dev->accel.ssv_draw) { - if ((dev->accel.cmd & 0x04) && dev->accel.ssv_len) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + if (dev->accel.ssv_draw) { + if ((dev->accel.cmd & 0x04) && dev->accel.ssv_len) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } } } } @@ -1397,12 +1414,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat case 1: /*Draw line*/ if (!cpu_input) { - dev->accel.init_cx = 0; - dev->accel.input3 = 0; dev->accel.output = 0; - dev->accel.output3 = 0; dev->accel.x_count = 0; - dev->accel.xx_count = 0; dev->accel.cx = dev->accel.cur_x; if (dev->accel.cur_x >= 0x600) @@ -1414,19 +1427,41 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy = dev->accel.maj_axis_pcnt; - ibm8514_log("CMD=%d, full=%04x, curx=%d, cury=%d, pixcntl=%x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, bkgdmix=%02x, and3=%d, sy=%d.\n", - cmd, dev->accel.cmd, dev->accel.cx, dev->accel.cy, pixcntl, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.bkgd_mix, and3, dev->accel.sy); + ibm8514_log("CMD=%d, full=%04x, curx=%d, cury=%d, pixcntl=%x, frgdsel=%d, bkgdsel=%d, frgdmix=%02x, bkgdmix=%02x, and3=%d, sy=%d, polygon=%02x.\n", + cmd, dev->accel.cmd, dev->accel.cx, dev->accel.cy, pixcntl, frgd_mix, bkgd_mix, dev->accel.frgd_mix, dev->accel.bkgd_mix, and3, dev->accel.sy, dev->accel.multifunc[0x0a] & 0x06); ibm8514_log("Line Draw 8514/A CMD=%04x, frgdmix=%d, bkgdmix=%d, c(%d,%d), pixcntl=%d, sy=%d, polyfill=%x, selfrmix=%02x, selbkmix=%02x, bkgdcol=%02x, frgdcol=%02x, clipt=%d, clipb=%d.\n", dev->accel.cmd, frgd_mix, bkgd_mix, dev->accel.cx, dev->accel.cy, pixcntl, dev->accel.sy, dev->accel.multifunc[0x0a] & 6, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, bkgd_color, frgd_color, dev->accel.clip_top, clip_b); if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 0x02) { if (!(dev->accel.cmd & 0x1000)) { if (dev->accel.cmd & 0x08) { - if (dev->accel.cmd == 0x211b) { - dev->accel.x_count = dev->accel.cx - (and3 + 3); - dev->accel.sy += (and3 + 3); - } else + if (and3) { + dev->accel.sy += and3; dev->accel.output = 1; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx -= and3; + break; + case 0x20: + dev->accel.cx -= and3; + break; + case 0x60: + dev->accel.cx += and3; + break; + case 0x80: + dev->accel.cx += and3; + break; + case 0xa0: + dev->accel.cx += and3; + break; + case 0xe0: + dev->accel.cx -= and3; + break; + + default: + break; + } + } } } } @@ -1436,15 +1471,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->data_available2 = 0; return; /*Wait for data from CPU*/ } else if (ibm8514_cpu_dest(svga)) { - if (dev->accel.cmd & 0x02) { - if (!(dev->accel.cmd & 0x1000)) { - if (dev->accel.cmd & 0x08) { - if ((frgd_mix == 3) && (bkgd_mix == 3) && (pixcntl == 0) && - ((dev->accel.multifunc[0x0a] & 0x06) == 0x04) && (dev->accel.frgd_mix != 0x07)) /*Kinda of a workaround for fill brushes on 8514/A using Windows 2.x*/ - dev->accel.input3 = 1; - } - } - } dev->force_busy = 1; dev->force_busy2 = 1; dev->data_available = 1; @@ -1454,239 +1480,253 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } if (dev->accel.cmd & 0x08) { /*Vector Line*/ - if (ibm8514_cpu_dest(svga) && cpu_input && (dev->accel.cmd & 0x02)) - count >>= 1; + if (ibm8514_cpu_dest(svga)) { + if (dev->accel.cmd & 0x02) + count >>= 1; - if (dev->accel.cmd == 0x211b) { - if (and3 >= 2) { - if (dev->accel.sy < (count << 1)) - count <<= 1; - } - } - if (dev->accel.cmd & 0x1000) - ibm8514_log("Vector Line %d: full=%04x, odd=%d, c(%d,%d), frgdmix=%d, bkgdmix=%d, xcount=%d, and3=%d, len(%d,%d), CURX=%d, Width=%d, pixcntl=%d, mix_dat=%08x, count=%d, cpu_data=%08x, cpu_input=%d.\n", cmd, dev->accel.cmd, dev->accel.input, dev->accel.cx, dev->accel.cy, frgd_mix, bkgd_mix, dev->accel.x_count, and3, dev->accel.sx, dev->accel.sy, dev->accel.cur_x, dev->accel.maj_axis_pcnt, pixcntl, mix_dat, count, cpu_dat, cpu_input); + if ((dev->accel.multifunc[0x0a] & 0x06) == 0x04) { + ibm8514_log("Destination Vector Line CNT=%d.\n", count); + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= INT_GE_BSY; + } else + ibm8514_log("Scissor out of bounds.\n"); - while (count-- && (dev->accel.sy >= 0)) { - ibm8514_log("CurrentX=%d, CurrentY=%d, Count=%d.\n", dev->accel.cx, dev->accel.cy, count); - if ((dev->accel.cx >= clip_l) && - (dev->accel.cx <= clip_r) && - (dev->accel.cy >= clip_t) && - (dev->accel.cy <= clip_b)) { - dev->subsys_stat |= INT_GE_BSY; - if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; + if (!dev->accel.sy) { + dev->force_busy = 0; + dev->force_busy2 = 0; + dev->fifo_idx = 0; + dev->accel.cmd_back = 1; + break; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.cy++; + break; + + default: + break; + } + + dev->accel.sy--; } + } else { + while (count-- && (dev->accel.sy >= 0)) { + if ((dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= INT_GE_BSY; + } - if (ibm8514_cpu_dest(svga)) { - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else { - if (dev->accel.cmd == 0x211b) { - if (dev->accel.x_count != dev->accel.cx) { - dev->accel.output3 = 1; + if (!dev->accel.sy) { + dev->force_busy = 0; + dev->force_busy2 = 0; + dev->fifo_idx = 0; + dev->accel.cmd_back = 1; + break; + } + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.cy++; + break; + + default: + break; + } + + dev->accel.sy--; + } + } + } else { + if (ibm8514_cpu_src(svga)) { + if ((dev->accel.cmd & 0x02) && (pixcntl != 2)) + count >>= 1; + } + + while (count-- && (dev->accel.sy >= 0)) { + ibm8514_log("CurrentX=%d, CurrentY=%d, Count=%d.\n", dev->accel.cx, dev->accel.cy, count); + if ((dev->accel.cx >= clip_l) && + (dev->accel.cx <= clip_r) && + (dev->accel.cy >= clip_t) && + (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= INT_GE_BSY; + switch ((mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask)) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; + + default: + break; + } + + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask), dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); + if ((dev->accel.cmd & 0x02) && ibm8514_cpu_src(svga)) { + if (!(dev->accel.cmd & 0x1000)) { + if (dev->accel.x_count >= and3) { + if ((dev->accel.cmd & 0x04) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } + } + } else { + if ((dev->accel.cmd & 0x04) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } + } } else { - dev->accel.output3 = 0; - } - - if (dev->accel.output3 == 1) - goto skip_vector_line_write; - } - - if (dev->accel.output) { - switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; - - default: - break; - } - } else { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; - - default: - break; - } - } - } - - READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - if (dev->accel.output) { - MIX(mix_dat & 0x01, dest_dat, src_dat); - } else { - MIX(mix_dat & mix_mask, dest_dat, src_dat); - } - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 0x02) && ibm8514_cpu_src(svga)) { - if ((dev->accel.cmd & 0x04) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } - } else { - if (ibm8514_cpu_src(svga) || !cpu_input) { - if ((dev->accel.cmd & 0x04) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } - } else if (dev->accel.input3) { - if ((dev->accel.cmd & 0x04) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat ? dest_dat : 0xff); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat ? dest_dat : 0xff); + if (ibm8514_cpu_src(svga) || !cpu_input) { + if ((dev->accel.cmd & 0x04) && dev->accel.sy) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); + } } } } } - } - if (!dev->accel.sy) { - if (cpu_input) { - dev->force_busy = 0; - dev->force_busy2 = 0; + if (!dev->accel.sy) { + if (cpu_input) { + dev->force_busy = 0; + dev->force_busy2 = 0; + } + dev->fifo_idx = 0; + dev->accel.cmd_back = 1; + if (!cpu_input) { + dev->accel.cur_x = dev->accel.cx; + dev->accel.cur_y = dev->accel.cy; + } + break; } - dev->fifo_idx = 0; - dev->accel.cmd_back = 1; - if (!cpu_input) { - dev->accel.cur_x = dev->accel.cx; - dev->accel.cur_y = dev->accel.cy; + + if (dev->bpp) + cpu_dat >>= 16; + else + cpu_dat >>= 8; + + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx++; + break; + case 0x20: + dev->accel.cx++; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cy--; + break; + case 0x60: + dev->accel.cx--; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx--; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cy++; + break; + case 0xe0: + dev->accel.cx++; + dev->accel.cy++; + break; + + default: + break; } - break; + + if (dev->accel.cmd & 0x02) + mix_dat >>= 1; + else { + mix_dat <<= 1; + mix_dat |= 1; + } + dev->accel.sy--; + dev->accel.x_count++; } - - if (dev->bpp) - cpu_dat >>= 16; - else - cpu_dat >>= 8; - - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.cx++; - break; - case 0x20: - dev->accel.cx++; - if (!dev->accel.output3) - dev->accel.cy--; - break; - case 0x40: - if (!dev->accel.output3) - dev->accel.cy--; - break; - case 0x60: - dev->accel.cx--; - if (!dev->accel.output3) - dev->accel.cy--; - break; - case 0x80: - dev->accel.cx--; - break; - case 0xa0: - dev->accel.cx--; - if (!dev->accel.output3) - dev->accel.cy++; - break; - case 0xc0: - if (!dev->accel.output3) - dev->accel.cy++; - break; - case 0xe0: - dev->accel.cx++; - if (!dev->accel.output3) - dev->accel.cy++; - break; - - default: - break; - } - -skip_vector_line_write: - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.x_count++; - break; - case 0x20: - dev->accel.x_count++; - if (dev->accel.output3) - dev->accel.cy--; - break; - case 0x40: - if (dev->accel.output3) - dev->accel.cy--; - break; - case 0x60: - dev->accel.x_count--; - if (dev->accel.output3) - dev->accel.cy--; - break; - case 0x80: - dev->accel.x_count--; - break; - case 0xa0: - dev->accel.x_count--; - if (dev->accel.output3) - dev->accel.cy++; - break; - case 0xc0: - if (dev->accel.output3) - dev->accel.cy++; - break; - case 0xe0: - dev->accel.x_count++; - if (dev->accel.output3) - dev->accel.cy++; - break; - - default: - break; - } - - if (dev->accel.output) - mix_dat >>= 1; - else { - mix_dat <<= 1; - mix_dat |= 1; - } - - dev->accel.sy--; } - dev->accel.output = 0; } else { /*Bresenham Line*/ if (pixcntl == 1) { dev->accel.temp_cnt = 8; @@ -1912,9 +1952,9 @@ skip_vector_line_write: if (!cpu_input) { dev->accel.x_count = 0; dev->accel.output = 0; + dev->accel.output2 = 0; dev->accel.input = 0; dev->accel.input2 = 0; - dev->accel.input3 = 0; dev->accel.odd_in = 0; dev->accel.cx = dev->accel.cur_x; @@ -1941,19 +1981,43 @@ skip_vector_line_write: if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 0x02) { if (!(dev->accel.cmd & 0x1000)) { - if (dev->accel.cmd & 0x08) { - dev->accel.x_count = dev->accel.cx - (and3 + 3); - dev->accel.sx += (and3 + 3); - } else { - dev->accel.x_count = dev->accel.cx; + if (!(dev->accel.cmd & 0x08)) { if (and3) { if (dev->accel.cmd & 0x20) - dev->accel.x_count -= and3; + dev->accel.cx -= and3; else - dev->accel.x_count += and3; + dev->accel.cx += and3; dev->accel.sx += 8; } + } else { + if (and3) { + dev->accel.sx += and3; + dev->accel.output2 = 1; + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx -= and3; + break; + case 0x20: + dev->accel.cx -= and3; + break; + case 0x60: + dev->accel.cx += and3; + break; + case 0x80: + dev->accel.cx += and3; + break; + case 0xa0: + dev->accel.cx += and3; + break; + case 0xe0: + dev->accel.cx -= and3; + break; + + default: + break; + } + } } } } else { @@ -1982,10 +2046,6 @@ skip_vector_line_write: dev->accel.sx -= 2; } } - } else { - if ((dev->accel.cmd == 0x41f0) && (frgd_mix == 3) && (bkgd_mix == 3) && - (pixcntl == 0)) - dev->accel.input3 = 1; } } ibm8514_log("INPUT1=%d, INPUT2=%d.\n", dev->accel.input, dev->accel.input2); @@ -2008,7 +2068,8 @@ skip_vector_line_write: (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { + ibm8514_log("RectRadial: MIXDATA=%08x, mask=%04x, frgdcol=%02x, bkgdcol=%02x, cpudat=%08x.\n", mix_dat, mix_mask, frgd_color, bkgd_color, cpu_dat); + switch ((mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask)) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; break; @@ -2036,15 +2097,15 @@ skip_vector_line_write: ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; - MIX(mix_dat & mix_mask, dest_dat, src_dat); + MIX(mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask), dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 0x02) && (dev->accel.x_count != dev->accel.cx)) - goto skip_vector_rect_write; - - if ((dev->accel.cmd & 0x04) && dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + if (dev->accel.x_count >= and3) { + if ((dev->accel.cmd & 0x04) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + ibm8514_log("RectFill Radial CX=%d, CY=%d, dstdat=%02x, olddst=%02x, srcdat=%02x.\n", dev->accel.cx, dev->accel.cy, dest_dat, old_dest_dat, src_dat); + } } } } @@ -2073,42 +2134,24 @@ skip_vector_line_write: break; } -skip_vector_rect_write: - switch (dev->accel.cmd & 0xe0) { - case 0x00: - dev->accel.x_count++; - break; - case 0x20: - dev->accel.x_count++; - break; - case 0x60: - dev->accel.x_count--; - break; - case 0x80: - dev->accel.x_count--; - break; - case 0xa0: - dev->accel.x_count--; - break; - case 0xe0: - dev->accel.x_count++; - break; - - default: - break; - } - if (dev->bpp) cpu_dat >>= 16; else cpu_dat >>= 8; - mix_dat <<= 1; - mix_dat |= 1; - + if (dev->accel.cmd & 0x02) + mix_dat >>= 1; + else { + mix_dat <<= 1; + mix_dat |= 1; + } dev->accel.sx--; + dev->accel.x_count++; if (dev->accel.sx < 0) { dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.x_count = 0; + if (dev->accel.output2) + dev->accel.sx += and3; if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx + 1); @@ -2142,7 +2185,6 @@ skip_vector_rect_write: dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; - dev->accel.x_count = 0; if (dev->accel.sy < 0) { dev->force_busy = 0; @@ -2166,93 +2208,59 @@ skip_vector_rect_write: (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { dev->subsys_stat |= INT_GE_BSY; - if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { - mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { - /* Mix data = current video memory value. */ - READ(dev->accel.dest + dev->accel.cx, mix_dat); - mix_dat = ((mix_dat & rd_mask) == rd_mask); - mix_dat = mix_dat ? mix_mask : 0; - } + if (ibm8514_cpu_src(svga) || !cpu_input) { + switch ((mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask)) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + src_dat = 0; + break; - if (ibm8514_cpu_dest(svga)) { - READ(dev->accel.dest + dev->accel.cx, src_dat); - if (pixcntl == 3) - src_dat = ((src_dat & rd_mask) == rd_mask); - } else { - if (dev->accel.cmd & 0x02) { - switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; - - default: - break; - } - } else { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - src_dat = 0; - break; - - default: - break; - } + default: + break; } - } - READ(dev->accel.dest + dev->accel.cx, dest_dat); - - if ((compare_mode == 0) || - ((compare_mode == 0x10) && (dest_dat >= compare)) || - ((compare_mode == 0x18) && (dest_dat < compare)) || - ((compare_mode == 0x20) && (dest_dat != compare)) || - ((compare_mode == 0x28) && (dest_dat == compare)) || - ((compare_mode == 0x30) && (dest_dat <= compare)) || - ((compare_mode == 0x38) && (dest_dat > compare))) { - old_dest_dat = dest_dat; - if (dev->accel.cmd & 0x02) { - MIX(mix_dat & 0x01, dest_dat, src_dat); - if ((dev->accel.x_count != dev->accel.cx) && !(dev->accel.cmd & 0x1000) && and3) - goto skip_nibble_rect_write; + READ(dev->accel.dest + dev->accel.cx, dest_dat); + if ((compare_mode == 0) || + ((compare_mode == 0x10) && (dest_dat >= compare)) || + ((compare_mode == 0x18) && (dest_dat < compare)) || + ((compare_mode == 0x20) && (dest_dat != compare)) || + ((compare_mode == 0x28) && (dest_dat == compare)) || + ((compare_mode == 0x30) && (dest_dat <= compare)) || + ((compare_mode == 0x38) && (dest_dat > compare))) { + old_dest_dat = dest_dat; + MIX(mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask), dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 0x04) && dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); - } - } else { - if (ibm8514_cpu_dest(svga) && (cmd == 2)) { - if (pixcntl == 3) { - MIX(mix_dat & mix_mask, dest_dat, src_dat); + if (dev->accel.cmd & 0x02) { + if (dev->accel.cmd & 0x1000) { + if ((dev->accel.cmd & 0x04) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } else { + if (dev->accel.x_count >= and3) { + if ((dev->accel.cmd & 0x04) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } + } } } else { - MIX(mix_dat & mix_mask, dest_dat, src_dat); - } - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 0x04) && dev->accel.sx) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); - } else if (!(dev->accel.cmd & 0x04)) { - WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + if ((dev->accel.cmd & 0x04) && dev->accel.sx) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } else if (!(dev->accel.cmd & 0x04)) { + WRITE(dev->accel.dest + dev->accel.cx, dest_dat); + } } } } @@ -2262,12 +2270,6 @@ skip_vector_rect_write: else dev->accel.cx--; -skip_nibble_rect_write: - if (dev->accel.cmd & 0x20) - dev->accel.x_count++; - else - dev->accel.x_count--; - if (dev->accel.cmd & 0x02) mix_dat >>= 1; else { @@ -2281,10 +2283,13 @@ skip_nibble_rect_write: cpu_dat >>= 8; dev->accel.sx--; + dev->accel.x_count++; if (dev->accel.sx < 0) { dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; + dev->accel.x_count = 0; if (dev->accel.input) dev->accel.odd_in = 1; + if (dev->accel.output || dev->accel.input2) dev->accel.sx -= 2; @@ -2301,7 +2306,6 @@ skip_nibble_rect_write: dev->accel.dest = dev->accel.ge_offset + (dev->accel.cy * dev->pitch); dev->accel.sy--; - dev->accel.x_count = 0; if (dev->accel.sy < 0) { dev->fifo_idx = 0; @@ -2957,12 +2961,11 @@ skip_nibble_rect_write: if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 0x02) { if (!(dev->accel.cmd & 0x1000)) { - dev->accel.x_count = dev->accel.cx; - if (and3) { + if (and3_blt) { if (dev->accel.cmd & 0x20) - dev->accel.x_count -= and3; + dev->accel.dx -= and3_blt; else - dev->accel.x_count += and3; + dev->accel.dx += and3_blt; dev->accel.sx += 8; } @@ -3006,50 +3009,27 @@ skip_nibble_rect_write: mix_dat = mix_dat ? mix_mask : 0x00; } } - if (dev->accel.cmd & 0x02) { - switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - READ(dev->accel.src + dev->accel.cx, src_dat); - if (pixcntl == 3) { - if (dev->accel.cmd & 0x10) - src_dat = ((src_dat & rd_mask) == rd_mask); - } - break; - default: - break; - } - } else { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { - case 0: - src_dat = bkgd_color; - break; - case 1: - src_dat = frgd_color; - break; - case 2: - src_dat = cpu_dat; - break; - case 3: - READ(dev->accel.src + dev->accel.cx, src_dat); - if (pixcntl == 3) { - if (dev->accel.cmd & 0x10) - src_dat = ((src_dat & rd_mask) == rd_mask); - } - break; + switch (((mix_dat & (dev->accel.cmd & 0x02) ? 0x01 : mix_mask)) ? frgd_mix : bkgd_mix) { + case 0: + src_dat = bkgd_color; + break; + case 1: + src_dat = frgd_color; + break; + case 2: + src_dat = cpu_dat; + break; + case 3: + READ(dev->accel.src + dev->accel.cx, src_dat); + if (pixcntl == 3) { + if (dev->accel.cmd & 0x10) + src_dat = ((src_dat & rd_mask) == rd_mask); + } + break; - default: - break; - } + default: + break; } READ(dev->accel.dest + dev->accel.dx, dest_dat); @@ -3062,16 +3042,17 @@ skip_nibble_rect_write: ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; + MIX(mix_dat & ((dev->accel.cmd & 0x02) ? 0x01 : mix_mask), dest_dat, src_dat); + dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); if (dev->accel.cmd & 0x02) { - MIX(mix_dat & 0x01, dest_dat, src_dat); - if ((dev->accel.x_count != dev->accel.cx) && !(dev->accel.cmd & 0x1000) && and3) - goto skip_nibble_bitblt_write; - - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + if (dev->accel.cmd & 0x1000) { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } else { + if (dev->accel.x_count >= and3_blt) { + WRITE(dev->accel.dest + dev->accel.dx, dest_dat); + } + } } else { - MIX(mix_dat & mix_mask, dest_dat, src_dat); - dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } @@ -3085,12 +3066,6 @@ skip_nibble_rect_write: dev->accel.cx--; } -skip_nibble_bitblt_write: - if (dev->accel.cmd & 0x20) - dev->accel.x_count++; - else - dev->accel.x_count--; - if (dev->accel.cmd & 0x02) mix_dat >>= 1; else { @@ -3104,7 +3079,9 @@ skip_nibble_bitblt_write: cpu_dat >>= 8; dev->accel.sx--; + dev->accel.x_count++; if (dev->accel.sx < 0) { + dev->accel.x_count = 0; dev->accel.sx = dev->accel.maj_axis_pcnt & 0x7ff; if (dev->accel.cmd & 0x20) { @@ -3127,7 +3104,6 @@ skip_nibble_bitblt_write: dev->accel.dest = dev->accel.ge_offset + (dev->accel.dy * dev->pitch); dev->accel.sy--; - dev->accel.x_count = 0; if (dev->accel.sy < 0) { dev->accel.cmd_back = 1; @@ -3358,7 +3334,10 @@ skip_nibble_bitblt_write: } } } else { - while (count-- && dev->accel.sy >= 0) { + if ((dev->accel.cmd == 0xc073) && (dev->accel.frgd_mix == 0x05) && (frgd_mix == 3)) + ibm8514_log("BitBLT PBRUSH: DX=%d, DY=%d, cl=%d, cr=%d, ct=%d, cb=%d.\n", dev->accel.dx, dev->accel.dy, clip_l, clip_r, clip_t, clip_b); + + while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.dx >= clip_l) && (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && @@ -3409,7 +3388,8 @@ skip_nibble_bitblt_write: MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); WRITE(dev->accel.dest + dev->accel.dx, dest_dat); - ibm8514_log("BitBLT DX=%d, DY=%d, data=%02x, old=%02x, src=%02x, frmix=%02x, bkmix=%02x, pixcntl=%d.\n", dev->accel.dx, dev->accel.dy, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); + if ((dev->accel.cmd == 0xc073) && (dev->accel.frgd_mix == 0x05) && (frgd_mix == 3)) + ibm8514_log("BitBLT CX=%d, CY=%d, DX=%d, DY=%d, data=%02x, old=%02x, src=%02x, frmix=%02x, bkmix=%02x, pixcntl=%d.\n", dev->accel.cx, dev->accel.cy, dev->accel.dx, dev->accel.dy, dest_dat, old_dest_dat, src_dat, dev->accel.frgd_mix & 0x1f, dev->accel.bkgd_mix & 0x1f, pixcntl); } } From 1d854ee2b02ea060cf2aab9fbd3af06c0dfb6662 Mon Sep 17 00:00:00 2001 From: DimMan88 Date: Sun, 25 Jan 2026 16:59:01 +0000 Subject: [PATCH 03/31] Translated using Weblate (Greek) Currently translated at 100.0% (1004 of 1004 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/el/ --- src/qt/languages/el-GR.po | 68 +++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/qt/languages/el-GR.po b/src/qt/languages/el-GR.po index 9243c24fb..5cb45bded 100644 --- a/src/qt/languages/el-GR.po +++ b/src/qt/languages/el-GR.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2026-01-10 12:56+0000\n" +"PO-Revision-Date: 2026-01-26 17:57+0000\n" "Last-Translator: DimMan88 \n" "Language-Team: Greek \n" "Language: el-GR\n" @@ -2919,24 +2919,26 @@ msgstr "Επιτυχής διαγραφή των περιεχομένων NVRAM msgid "An error occurred trying to wipe the NVRAM contents of the virtual machine \"%1\"" msgstr "" +"Ένα σφάλμα προέκυψε κατά την εκκαθάριση των περιεχομένων της NVRAM της " +"εικονικής μηχανής \"%1\"" msgid "%1 VM Manager" -msgstr "" +msgstr "%1 VM Manager" msgid "%n disk(s)" -msgstr "" +msgstr "%n δίσκος(οι)" msgid "Unknown Status" -msgstr "" +msgstr "Άγνωστη Κατάσταση" msgid "No Machines Found!" -msgstr "" +msgstr "Δεν βρέθηκαν μηχανές!" msgid "Check for updates on startup" msgstr "Έλεγχος για ενημερώσεις κατα την εκκίνηση" msgid "Unable to determine release information" -msgstr "" +msgstr "Αδυναμία προσδιορισμού πληροφοριών έκδοσης" msgid "There was an error checking for updates:\n\n%1\n\nPlease try again later." msgstr "" @@ -2947,82 +2949,84 @@ msgstr "" "Παρακαλώ προσπαθήστε ξανά αργότερα." msgid "Update check complete" -msgstr "" +msgstr "Ο έλεγχος ενημερώσεων ολοκληρώθηκε" msgid "stable" -msgstr "" +msgstr "σταθερή" msgid "beta" -msgstr "" +msgstr "δοκιμαστική" msgid "You are running the latest %1 version of 86Box: %2" -msgstr "" +msgstr "Τρέχετε την τελευταία %1 έκδοση του 86Box: %2" msgid "version" -msgstr "" +msgstr "έκδοση" msgid "build" -msgstr "" +msgstr "build" msgid "You are currently running version %1." -msgstr "" +msgstr "Τρέχετε την έκδοση %1." msgid "Version %1 is now available." -msgstr "" +msgstr "Έκδοση %1 είναι διαθέσιμη." msgid "You are currently running build %1." -msgstr "" +msgstr "Τρέχετε το build %1." msgid "Build %1 is now available." -msgstr "" +msgstr "Build %1 είναι τώρα διαθέσιμο." msgid "Would you like to visit the download page?" -msgstr "" +msgstr "Επιθυμείτε να επισκεφθείτε την σελίδα λήψεων;" msgid "Visit download page" -msgstr "" +msgstr "Επίσκεψη σελίδας λήψεων" msgid "Update check" -msgstr "" +msgstr "Έλεγχος ενημερώσεων" msgid "Checking for updates…" msgstr "Έλεγχος για ενημερώσεις…" msgid "86Box Update" -msgstr "" +msgstr "Ενημέρωση 86Box" msgid "Release notes:" -msgstr "" +msgstr "Σημειώσεις έκδοσης:" msgid "%1 Hz" -msgstr "" +msgstr "%1 Hz" msgid "Virtual machine crash" -msgstr "" +msgstr "Σφάλμα εικονικής μηχανής" msgid "The virtual machine \"%1\"'s process has unexpectedly terminated with exit code %2." msgstr "" +"Η διεργασία της εικονικής μηχανής \"%1\" τερματίστηκε απροσδόκητα με κωδικό " +"εξόδου %2." msgid "The system will not be added." -msgstr "" +msgstr "Το σύστημα δεν θα προστεθεί." msgid "&Update mouse every CPU frame" msgstr "&Ανανέωση ποντικιού ανα καρέ CPU" msgid "Hue" -msgstr "" +msgstr "Απόχρωση" msgid "Saturation" -msgstr "" +msgstr "Κορεσμός" msgid "Contrast" -msgstr "" +msgstr "Αντίθεση" msgid "Brightness" -msgstr "" +msgstr "Φωτεινότητα" msgid "Sharpness" -msgstr "" +msgstr "Οξύτητα" msgid "&CGA composite settings…" msgstr "Ρυθμίσεις &CGA composite…" @@ -3073,10 +3077,12 @@ msgid "&Allow recompilation" msgstr "&Να επιτρέπεται ανασύνταξη" msgid "&Fast forward" -msgstr "" +msgstr "&Γρήγορα μπροστά" msgid "Fast forward" -msgstr "" +msgstr "Γρήγορα μπροστά" msgid "To change the system directory, stop all running machines." msgstr "" +"Για να αλλάξετε τον κατάλογο συστήματος, σταματήστε πρώτα όλες τις μηχανές " +"σε λειτουργία." From 9b7b92622bc055d8b4089af8971bb25273531797 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 06:47:08 +0100 Subject: [PATCH 04/31] Restructure LPT devices so that lpt_device_t is now only used internally while the exposed LPT devices are now regular device_t's. --- src/86box.c | 2 + src/device/hasp.c | 32 +++++----- src/device/lpt.c | 110 ++++++++++++++++++++--------------- src/include/86box/lpt.h | 59 +++++++++---------- src/include/86box/network.h | 6 +- src/include/86box/prt_devs.h | 12 ++-- src/network/net_plip.c | 33 +++++------ src/printer/prt_escp.c | 28 ++------- src/printer/prt_ps.c | 62 ++++++++++---------- src/printer/prt_text.c | 27 ++------- src/sound/snd_lpt_dac.c | 60 +++++++++---------- src/sound/snd_lpt_dss.c | 30 +++++----- 12 files changed, 214 insertions(+), 247 deletions(-) diff --git a/src/86box.c b/src/86box.c index 80244dc8b..24e8be26a 100644 --- a/src/86box.c +++ b/src/86box.c @@ -1704,6 +1704,8 @@ pc_reset_hard_init(void) ide_hard_reset(); + lpt_ports_reset(); + /* Initialize the actual machine and its basic modules. */ machine_init(); diff --git a/src/device/hasp.c b/src/device/hasp.c index ea8b9b413..920f48257 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -302,13 +302,13 @@ hasp_read_status(void *priv) } static void * -hasp_init(void *lpt, int type) +hasp_init(const device_t *info, int type) { hasp_t *dev = calloc(1, sizeof(hasp_t)); hasp_log("HASP: init(%d)\n", type); - dev->lpt = lpt; + dev->lpt = lpt_attach(info->local & 0xf, hasp_write_data, NULL, NULL, hasp_read_status, NULL, NULL, NULL, dev); dev->type = &hasp_types[type]; dev->status = 0x80; @@ -317,9 +317,9 @@ hasp_init(void *lpt, int type) } static void * -hasp_init_savquest(void *lpt) +hasp_init_savquest(const device_t *info) { - return hasp_init(lpt, HASP_TYPE_SAVQUEST); + return hasp_init(info, HASP_TYPE_SAVQUEST); } static void @@ -332,16 +332,16 @@ hasp_close(void *priv) free(dev); } -const lpt_device_t lpt_hasp_savquest_device = { - .name = "Protection Dongle for Savage Quest", - .internal_name = "dongle_savquest", - .init = hasp_init_savquest, - .close = hasp_close, - .write_data = hasp_write_data, - .write_ctrl = NULL, - .strobe = NULL, - .read_status = hasp_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL +const device_t lpt_hasp_savquest_device = { + .name = "Protection Dongle for Savage Quest", + .internal_name = "dongle_savquest", + .flags = DEVICE_LPT, + .local = 0, + .init = hasp_init_savquest, + .close = hasp_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/device/lpt.c b/src/device/lpt.c index f7cc6eda0..b6ec9f031 100644 --- a/src/device/lpt.c +++ b/src/device/lpt.c @@ -34,19 +34,22 @@ lpt_port_t lpt_ports[PARALLEL_MAX]; lpt_device_t lpt_devs[PARALLEL_MAX]; -const lpt_device_t lpt_none_device = { +const device_t lpt_none_device = { .name = "None", .internal_name = "none", + .flags = DEVICE_LPT, + .local = 0, .init = NULL, .close = NULL, - .write_data = NULL, - .write_ctrl = NULL, - .read_status = NULL, - .read_ctrl = NULL + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; static const struct { - const lpt_device_t *device; + const device_t *device; } lpt_devices[] = { // clang-format off { &lpt_none_device }, @@ -83,50 +86,41 @@ lpt_log(const char *fmt, ...) # define lpt_log(fmt, ...) #endif +int +lpt_device_available(int id) +{ + if (lpt_devices[id].device) + return device_available(lpt_devices[id].device); + + return 1; +} + const device_t * lpt_device_getdevice(const int id) { - return (device_t *) lpt_devices[id].device->cfgdevice; + return lpt_devices[id].device; } int lpt_device_has_config(const int id) { - int c = 0; - const device_t *dev = (device_t *) lpt_devices[id].device->cfgdevice; - const device_config_t *config; - if (dev == NULL) + if (lpt_devices[id].device == NULL) return 0; - - if (dev->config == NULL) - return 0; - - config = dev->config; - - while (config->type != CONFIG_END) { - c++; - config++; - } - - return (c > 0) ? 1 : 0; + return device_has_config(lpt_devices[id].device); } const char * lpt_device_get_name(const int id) { if (lpt_devices[id].device == NULL) - return NULL; - + return 0; return lpt_devices[id].device->name; } const char * lpt_device_get_internal_name(const int id) { - if (lpt_devices[id].device == NULL) - return NULL; - - return lpt_devices[id].device->internal_name; + return device_get_internal_name(lpt_devices[id].device); } int @@ -147,29 +141,42 @@ void lpt_devices_init(void) { for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - lpt_t *dev = lpt_devs[i].lpt; + memset(&(lpt_devs[i]), 0x00, sizeof(lpt_device_t)); - if (lpt_devices[lpt_ports[i].device].device != NULL) { - memcpy(&(lpt_devs[i]), (lpt_device_t *) lpt_devices[lpt_ports[i].device].device, sizeof(lpt_device_t)); - - if (lpt_devs[i].init) - lpt_devs[i].priv = lpt_devs[i].init(dev); - } else - memset(&(lpt_devs[i]), 0x00, sizeof(lpt_device_t)); - - lpt_devs[i].lpt = dev; + if ((lpt_devices[lpt_ports[i].device].device != NULL) && + (lpt_devices[lpt_ports[i].device].device != &lpt_none_device)) + device_add_params((device_t *) lpt_devices[lpt_ports[i].device].device, (void *) (uintptr_t) i); } } +void * +lpt_attach(int port, + void (*write_data)(uint8_t val, void *priv), + void (*write_ctrl)(uint8_t val, void *priv), + void (*strobe)(uint8_t old, uint8_t val,void *priv), + uint8_t (*read_status)(void *priv), + uint8_t (*read_ctrl)(void *priv), + void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv), + void (*epp_request_read)(uint8_t is_addr, void *priv), + void *priv) +{ + lpt_devs[port].write_data = write_data; + lpt_devs[port].write_ctrl = write_ctrl; + lpt_devs[port].strobe = strobe; + lpt_devs[port].read_status = read_status; + lpt_devs[port].read_ctrl = read_ctrl; + lpt_devs[port].epp_write_data = epp_write_data; + lpt_devs[port].epp_request_read = epp_request_read; + lpt_devs[port].priv = priv; + + return lpt_ports[port].lpt; +} + void lpt_devices_close(void) { - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - if (lpt_devs[i].close) - lpt_devs[i].close(lpt_devs[i].priv); - + for (uint8_t i = 0; i < PARALLEL_MAX; i++) memset(&(lpt_devs[i]), 0x00, sizeof(lpt_device_t)); - } } static uint8_t @@ -954,10 +961,10 @@ lpt_init(const device_t *info) if (lpt_ports[next_inst].enabled || (info->local & 0xFFF00000)) { lpt_log("Adding parallel port %i...\n", next_inst); - dev->dt = &(lpt_devs[next_inst]); - dev->dt->lpt = dev; + dev->dt = &(lpt_devs[next_inst]); + lpt_ports[next_inst].lpt = dev; - dev->fifo = NULL; + dev->fifo = NULL; memset(&dev->fifo_out_timer, 0x00, sizeof(pc_timer_t)); lpt_port_zero(dev); @@ -1033,7 +1040,14 @@ lpt_standalone_init(void) { while (next_inst < (PARALLEL_MAX - 1)) device_add_inst(&lpt_port_device, next_inst + 1); -}; +} + +void +lpt_ports_reset(void) +{ + for (int i = 0; i < PARALLEL_MAX; i++) + lpt_ports[i].lpt = NULL; +} const device_t lpt_port_device = { .name = "Parallel Port", diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 61c95094f..89f7cb5d1 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -18,11 +18,6 @@ #endif typedef struct lpt_device_s { - const char *name; - const char *internal_name; - - void *(*init)(void *lpt); - void (*close)(void *priv); void (*write_data)(uint8_t val, void *priv); void (*write_ctrl)(uint8_t val, void *priv); void (*strobe)(uint8_t old, uint8_t val,void *priv); @@ -31,13 +26,7 @@ typedef struct lpt_device_s { void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv); void (*epp_request_read)(uint8_t is_addr, void *priv); - void *priv; - struct lpt_t *lpt; -//#ifdef EMU_DEVICE_H -// struct device_t *cfgdevice; -//#else - void *cfgdevice; -//#endif + void * priv; } lpt_device_t; #ifdef _TIMER_H_ @@ -86,6 +75,8 @@ typedef struct lpt_port_s { uint8_t enabled; int device; + + lpt_t *lpt; } lpt_port_t; extern lpt_port_t lpt_ports[PARALLEL_MAX]; @@ -96,6 +87,22 @@ typedef enum { LPT_STATE_WRITE_FIFO } lpt_state_t; +extern const device_t lpt_dac_device; +extern const device_t lpt_dac_stereo_device; + +extern const device_t dss_device; + +extern const device_t lpt_hasp_savquest_device; + +extern int lpt_device_available(int id); +#ifdef EMU_DEVICE_H +extern const device_t *lpt_device_getdevice(const int id); +#endif +extern int lpt_device_has_config(const int id); +extern const char *lpt_device_get_name(int id); +extern const char *lpt_device_get_internal_name(int id); +extern int lpt_device_get_from_internal_name(const char *str); + extern void lpt_write(uint16_t port, uint8_t val, void *priv); extern void lpt_write_to_fifo(void *priv, uint8_t val); @@ -109,24 +116,6 @@ extern uint8_t lpt_read_ecp_mode(lpt_t *dev); extern void lpt_irq(void *priv, int raise); -extern int lpt_device_get_from_internal_name(const char *str); - -extern const char *lpt_device_get_name(int id); -extern const char *lpt_device_get_internal_name(int id); - -#ifdef EMU_DEVICE_H -extern const device_t *lpt_device_getdevice(const int id); -#endif - -extern int lpt_device_has_config(const int id); - -extern const lpt_device_t lpt_dac_device; -extern const lpt_device_t lpt_dac_stereo_device; - -extern const lpt_device_t dss_device; - -extern const lpt_device_t lpt_hasp_savquest_device; - extern void lpt_set_ext(lpt_t *dev, uint8_t ext); extern void lpt_set_ecp(lpt_t *dev, uint8_t ecp); extern void lpt_set_epp(lpt_t *dev, uint8_t epp); @@ -143,12 +132,22 @@ extern void lpt_port_remove(lpt_t *dev); extern void lpt1_remove_ams(lpt_t *dev); extern void lpt_devices_init(void); +extern void * lpt_attach(int port, + void (*write_data)(uint8_t val, void *priv), + void (*write_ctrl)(uint8_t val, void *priv), + void (*strobe)(uint8_t old, uint8_t val,void *priv), + uint8_t (*read_status)(void *priv), + uint8_t (*read_ctrl)(void *priv), + void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv), + void (*epp_request_read)(uint8_t is_addr, void *priv), + void *priv); extern void lpt_devices_close(void); extern void lpt_set_next_inst(int ni); extern void lpt_set_3bc_used(int is_3bc_used); extern void lpt_standalone_init(void); +extern void lpt_ports_reset(void); extern const device_t lpt_port_device; diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 0642c3f53..2c91a6d9f 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -244,10 +244,8 @@ extern const device_t pcnet_am79c973_onboard_device; extern const device_t modem_device; /* PLIP */ -#ifdef EMU_LPT_H -extern const lpt_device_t lpt_plip_device; -#endif -extern const device_t plip_device; +extern const device_t lpt_plip_device; +extern const device_t plip_device; /* Realtek RTL8139C+ */ extern const device_t rtl8139c_plus_device; diff --git a/src/include/86box/prt_devs.h b/src/include/86box/prt_devs.h index d136d9d93..05b5a7d94 100644 --- a/src/include/86box/prt_devs.h +++ b/src/include/86box/prt_devs.h @@ -1,15 +1,11 @@ #ifndef EMU_PRT_DEVS_H #define EMU_PRT_DEVS_H -extern const lpt_device_t lpt_prt_text_device; -extern const device_t prt_text_device; -extern const lpt_device_t lpt_prt_escp_device; -extern const device_t prt_escp_device; -extern const lpt_device_t lpt_prt_ps_device; -extern const device_t prt_ps_device; +extern const device_t lpt_prt_text_device; +extern const device_t lpt_prt_escp_device; +extern const device_t lpt_prt_ps_device; #ifdef USE_PCL -extern const lpt_device_t lpt_prt_pcl_device; -extern const device_t prt_pcl_device; +extern const device_t lpt_prt_pcl_device; #endif #endif /*EMU_PRT_DEVS_H*/ diff --git a/src/network/net_plip.c b/src/network/net_plip.c index 36df49153..e472ea6c3 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -441,13 +441,14 @@ plip_rx(void *priv, uint8_t *buf, int io_len) } static void * -plip_lpt_init(void *lpt) +plip_lpt_init(const device_t *info) { plip_t *dev = (plip_t *) calloc(1, sizeof(plip_t)); plip_log(1, "PLIP: lpt_init()\n"); - dev->lpt = lpt; + dev->lpt = lpt_attach(info->local & 0xf, plip_write_data, plip_write_ctrl, NULL, plip_read_status, NULL, NULL, NULL, dev); + memset(dev->mac, 0xfc, 6); /* static MAC used by Linux; just a placeholder */ dev->status = 0x80; @@ -485,24 +486,22 @@ plip_close(void *priv) free(priv); } -const lpt_device_t lpt_plip_device = { - .name = "Parallel Line Internet Protocol", - .internal_name = "plip", - .init = plip_lpt_init, - .close = plip_close, - .write_data = plip_write_data, - .write_ctrl = plip_write_ctrl, - .strobe = NULL, - .read_status = plip_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t lpt_plip_device = { + .name = "Parallel Line Internet Protocol (LPT)", + .internal_name = "plip", + .flags = DEVICE_LPT, + .local = 0, + .init = plip_lpt_init, + .close = plip_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; const device_t plip_device = { - .name = "Parallel Line Internet Protocol", + .name = "Parallel Line Internet Protocol (Network)", .internal_name = "plip", .flags = DEVICE_LPT, .local = 0, diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index a24072971..42702dce3 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1979,7 +1979,7 @@ read_status(void *priv) } static void * -escp_init(void *lpt) +escp_init(const device_t *info) { escp_t *dev = NULL; @@ -1995,7 +1995,8 @@ escp_init(void *lpt) /* Initialize a device instance. */ dev = (escp_t *) calloc(1, sizeof(escp_t)); dev->ctrl = 0x04; - dev->lpt = lpt; + + dev->lpt = lpt_attach(info->local & 0xf, write_data, write_ctrl, strobe, read_status, read_ctrl, NULL, NULL, dev); rom_get_full_path(dev->fontpath, "roms/printer/fonts/"); @@ -2109,13 +2110,13 @@ static const device_config_t lpt_prt_escp_config[] = { #endif // clang-format on -const device_t prt_escp_device = { +const device_t lpt_prt_escp_device = { .name = "Generic ESC/P 2 Dot-Matrix Printer", .internal_name = "dot_matrix", .flags = DEVICE_LPT, .local = 0, - .init = NULL, - .close = NULL, + .init = escp_init, + .close = escp_close, .reset = NULL, .available = NULL, .speed_changed = NULL, @@ -2126,20 +2127,3 @@ const device_t prt_escp_device = { .config = NULL #endif }; - -const lpt_device_t lpt_prt_escp_device = { - .name = "Generic ESC/P 2 Dot-Matrix Printer", - .internal_name = "dot_matrix", - .init = escp_init, - .close = escp_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .strobe = strobe, - .read_status = read_status, - .read_ctrl = read_ctrl, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL, - .cfgdevice = (device_t *) &prt_escp_device -}; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index bb153723c..60e87e15e 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -465,15 +465,16 @@ ps_read_status(void *priv) } static void * -ps_init(void *lpt) +ps_init(const device_t *info) { ps_t *dev = (ps_t *) calloc(1, sizeof(ps_t)); gsapi_revision_t rev; dev->ctrl = 0x04; - dev->lpt = lpt; dev->pcl = false; + dev->lpt = lpt_attach(info->local & 0xf, ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); #ifdef PATH_GHOSTSCRIPT_DLL_ALT1 @@ -513,15 +514,16 @@ ps_init(void *lpt) #ifdef USE_PCL static void * -pcl_init(void *lpt) +pcl_init(const device_t *info) { ps_t *dev = (ps_t *) calloc(1, sizeof(ps_t)); gsapi_revision_t rev; dev->ctrl = 0x04; - dev->lpt = lpt; dev->pcl = true; + dev->lpt = lpt_attach(info->local & 0xf, ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); #ifdef PATH_GHOSTPCL_DLL_ALT1 @@ -579,36 +581,32 @@ ps_close(void *priv) free(dev); } -const lpt_device_t lpt_prt_ps_device = { - .name = "Generic PostScript Printer", - .internal_name = "postscript", - .init = ps_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .strobe = ps_strobe, - .read_status = ps_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t lpt_prt_ps_device = { + .name = "Generic PostScript Printer", + .internal_name = "postscript", + .flags = DEVICE_LPT, + .local = 0, + .init = ps_init, + .close = ps_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; #ifdef USE_PCL -const lpt_device_t lpt_prt_pcl_device = { - .name = "Generic PCL5e Printer", - .internal_name = "pcl", - .init = pcl_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .strobe = ps_strobe, - .read_status = ps_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t lpt_prt_pcl_device = { + .name = "Generic PCL5e Printer", + .internal_name = "pcl", + .flags = DEVICE_LPT, + .local = 0, + .init = pcl_init, + .close = ps_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; #endif diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index af601af75..0e27bf1af 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -455,13 +455,13 @@ read_status(void *priv) } static void * -prnt_init(void *lpt) +prnt_init(const device_t *info) { /* Initialize a device instance. */ prnt_t *dev = (prnt_t *) calloc(1, sizeof(prnt_t)); dev->ctrl = 0x04; - dev->lpt = lpt; + dev->lpt = lpt_attach(info->local & 0xf, write_data, write_ctrl, strobe, read_status, NULL, NULL, NULL, dev); /* Initialize parameters. */ reset_printer(dev); @@ -523,13 +523,13 @@ static const device_config_t lpt_prt_text_config[] = { #endif // clang-format on -const device_t prt_text_device = { +const device_t lpt_prt_text_device = { .name = "Generic Text Printer", .internal_name = "text_prt", .flags = DEVICE_LPT, .local = 0, - .init = NULL, - .close = NULL, + .init = prnt_init, + .close = prnt_close, .reset = NULL, .available = NULL, .speed_changed = NULL, @@ -540,20 +540,3 @@ const device_t prt_text_device = { .config = NULL #endif }; - -const lpt_device_t lpt_prt_text_device = { - .name = "Generic Text Printer", - .internal_name = "text_prt", - .init = prnt_init, - .close = prnt_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .strobe = strobe, - .read_status = read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL, - .cfgdevice = (device_t *) &prt_text_device -}; diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 33b197230..f2268cd0f 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -89,11 +89,11 @@ dac_get_buffer(int32_t *buffer, int len, void *priv) } static void * -dac_init(void *lpt) +dac_init(UNUSED(const device_t *info)) { lpt_dac_t *lpt_dac = calloc(1, sizeof(lpt_dac_t)); - lpt_dac->lpt = lpt; + lpt_dac->lpt = lpt_attach(info->local & 0xf, dac_write_data, dac_write_ctrl, dac_strobe, dac_read_status, NULL, NULL, NULL, lpt_dac); sound_add_handler(dac_get_buffer, lpt_dac); @@ -101,9 +101,9 @@ dac_init(void *lpt) } static void * -dac_stereo_init(void *lpt) +dac_stereo_init(const device_t *info) { - lpt_dac_t *lpt_dac = dac_init(lpt); + lpt_dac_t *lpt_dac = dac_init(info); lpt_dac->is_stereo = 1; @@ -117,34 +117,30 @@ dac_close(void *priv) free(lpt_dac); } -const lpt_device_t lpt_dac_device = { - .name = "LPT DAC / Covox Speech Thing", - .internal_name = "lpt_dac", - .init = dac_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .strobe = dac_strobe, - .read_status = dac_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t lpt_dac_device = { + .name = "LPT DAC / Covox Speech Thing", + .internal_name = "lpt_dac", + .flags = DEVICE_LPT, + .local = 0, + .init = dac_init, + .close = dac_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; -const lpt_device_t lpt_dac_stereo_device = { - .name = "Stereo LPT DAC", - .internal_name = "lpt_dac_stereo", - .init = dac_stereo_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .strobe = dac_strobe, - .read_status = dac_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t lpt_dac_stereo_device = { + .name = "Stereo LPT DAC", + .internal_name = "lpt_dac_stereo", + .flags = DEVICE_LPT, + .local = 0, + .init = dac_stereo_init, + .close = dac_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 5ea0048f4..2581d7873 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -114,11 +114,11 @@ dss_callback(void *priv) } static void * -dss_init(void *lpt) +dss_init(UNUSED(const device_t *info)) { dss_t *dss = calloc(1, sizeof(dss_t)); - dss->lpt = lpt; + dss->lpt = lpt_attach(info->local & 0xf, dss_write_data, dss_write_ctrl, NULL, dss_read_status, NULL, NULL, NULL, dss); sound_add_handler(dss_get_buffer, dss); timer_add(&dss->timer, dss_callback, dss, 1); @@ -133,18 +133,16 @@ dss_close(void *priv) free(dss); } -const lpt_device_t dss_device = { - .name = "Disney Sound Source", - .internal_name = "dss", - .init = dss_init, - .close = dss_close, - .write_data = dss_write_data, - .strobe = NULL, - .write_ctrl = dss_write_ctrl, - .read_status = dss_read_status, - .read_ctrl = NULL, - .epp_write_data = NULL, - .epp_request_read = NULL, - .priv = NULL, - .lpt = NULL +const device_t dss_device = { + .name = "Disney Sound Source", + .internal_name = "dss", + .flags = DEVICE_LPT, + .local = 0, + .init = dss_init, + .close = dss_close, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL }; From 51e0e8832948f050beef4b4093a221df658af04e Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 09:40:53 +0100 Subject: [PATCH 05/31] More LPT device sanitization, un-dev-branch the Generic PCL printer, add language selection to it and the PostScript printer (including a Raw option), and translate the missing strings. --- CMakeLists.txt | 1 - src/device/hasp.c | 2 +- src/device/lpt.c | 9 +- src/include/86box/lpt.h | 3 +- src/include/86box/prt_devs.h | 2 - src/network/net_plip.c | 2 +- src/printer/CMakeLists.txt | 4 - src/printer/prt_escp.c | 2 +- src/printer/prt_ps.c | 337 ++++++++++++++++++++++------------- src/printer/prt_text.c | 2 +- src/qt/languages/86box.pot | 3 + src/qt/languages/ca-ES.po | 9 +- src/qt/languages/cs-CZ.po | 6 +- src/qt/languages/de-DE.po | 9 +- src/qt/languages/el-GR.po | 7 +- src/qt/languages/es-ES.po | 9 +- src/qt/languages/fi-FI.po | 9 +- src/qt/languages/fr-FR.po | 9 +- src/qt/languages/hr-HR.po | 9 +- src/qt/languages/it-IT.po | 9 +- src/qt/languages/ja-JP.po | 9 +- src/qt/languages/ko-KR.po | 9 +- src/qt/languages/nb-NO.po | 9 +- src/qt/languages/nl-NL.po | 9 +- src/qt/languages/pl-PL.po | 9 +- src/qt/languages/pt-BR.po | 9 +- src/qt/languages/pt-PT.po | 9 +- src/qt/languages/ru-RU.po | 3 + src/qt/languages/sk-SK.po | 9 +- src/qt/languages/sl-SI.po | 9 +- src/qt/languages/sv-SE.po | 9 +- src/qt/languages/tr-TR.po | 3 + src/qt/languages/uk-UA.po | 9 +- src/qt/languages/vi-VN.po | 9 +- src/qt/languages/zh-CN.po | 3 + src/qt/languages/zh-TW.po | 3 + src/sound/snd_lpt_dac.c | 2 +- src/sound/snd_lpt_dss.c | 2 +- 38 files changed, 365 insertions(+), 202 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 667df5221..b64902c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,7 +180,6 @@ cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) -cmake_dependent_option(PCL "Generic PCL5e Printer" ON "DEV_BRANCH" OFF) cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) cmake_dependent_option(WACOM "Wacom Input Devices" ON "DEV_BRANCH" OFF) cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) diff --git a/src/device/hasp.c b/src/device/hasp.c index 920f48257..f4b6bc0ad 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -308,7 +308,7 @@ hasp_init(const device_t *info, int type) hasp_log("HASP: init(%d)\n", type); - dev->lpt = lpt_attach(info->local & 0xf, hasp_write_data, NULL, NULL, hasp_read_status, NULL, NULL, NULL, dev); + dev->lpt = lpt_attach(hasp_write_data, NULL, NULL, hasp_read_status, NULL, NULL, NULL, dev); dev->type = &hasp_types[type]; dev->status = 0x80; diff --git a/src/device/lpt.c b/src/device/lpt.c index b6ec9f031..a7fb5ac2d 100644 --- a/src/device/lpt.c +++ b/src/device/lpt.c @@ -59,9 +59,7 @@ static const struct { { &lpt_prt_text_device }, { &lpt_prt_escp_device }, { &lpt_prt_ps_device }, -#ifdef USE_PCL { &lpt_prt_pcl_device }, -#endif { &lpt_plip_device }, { &lpt_hasp_savquest_device }, { NULL } @@ -145,13 +143,12 @@ lpt_devices_init(void) if ((lpt_devices[lpt_ports[i].device].device != NULL) && (lpt_devices[lpt_ports[i].device].device != &lpt_none_device)) - device_add_params((device_t *) lpt_devices[lpt_ports[i].device].device, (void *) (uintptr_t) i); + device_add_inst((device_t *) lpt_devices[lpt_ports[i].device].device, i + 1); } } void * -lpt_attach(int port, - void (*write_data)(uint8_t val, void *priv), +lpt_attach(void (*write_data)(uint8_t val, void *priv), void (*write_ctrl)(uint8_t val, void *priv), void (*strobe)(uint8_t old, uint8_t val,void *priv), uint8_t (*read_status)(void *priv), @@ -160,6 +157,8 @@ lpt_attach(int port, void (*epp_request_read)(uint8_t is_addr, void *priv), void *priv) { + int port = device_get_instance() - 1; + lpt_devs[port].write_data = write_data; lpt_devs[port].write_ctrl = write_ctrl; lpt_devs[port].strobe = strobe; diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 89f7cb5d1..fe5442379 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -132,8 +132,7 @@ extern void lpt_port_remove(lpt_t *dev); extern void lpt1_remove_ams(lpt_t *dev); extern void lpt_devices_init(void); -extern void * lpt_attach(int port, - void (*write_data)(uint8_t val, void *priv), +extern void * lpt_attach(void (*write_data)(uint8_t val, void *priv), void (*write_ctrl)(uint8_t val, void *priv), void (*strobe)(uint8_t old, uint8_t val,void *priv), uint8_t (*read_status)(void *priv), diff --git a/src/include/86box/prt_devs.h b/src/include/86box/prt_devs.h index 05b5a7d94..343182946 100644 --- a/src/include/86box/prt_devs.h +++ b/src/include/86box/prt_devs.h @@ -4,8 +4,6 @@ extern const device_t lpt_prt_text_device; extern const device_t lpt_prt_escp_device; extern const device_t lpt_prt_ps_device; -#ifdef USE_PCL extern const device_t lpt_prt_pcl_device; -#endif #endif /*EMU_PRT_DEVS_H*/ diff --git a/src/network/net_plip.c b/src/network/net_plip.c index e472ea6c3..f61c04646 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -447,7 +447,7 @@ plip_lpt_init(const device_t *info) plip_log(1, "PLIP: lpt_init()\n"); - dev->lpt = lpt_attach(info->local & 0xf, plip_write_data, plip_write_ctrl, NULL, plip_read_status, NULL, NULL, NULL, dev); + dev->lpt = lpt_attach(plip_write_data, plip_write_ctrl, NULL, plip_read_status, NULL, NULL, NULL, dev); memset(dev->mac, 0xfc, 6); /* static MAC used by Linux; just a placeholder */ diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index 0efb2aec2..1b4d9c0c5 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -23,10 +23,6 @@ add_library(print OBJECT prt_ps.c ) -if(PCL) - target_compile_definitions(print PRIVATE USE_PCL) -endif() - if(APPLE) find_library(GHOSTSCRIPT_LIB gs) if (NOT GHOSTSCRIPT_LIB) diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 42702dce3..2a50ae54f 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1996,7 +1996,7 @@ escp_init(const device_t *info) dev = (escp_t *) calloc(1, sizeof(escp_t)); dev->ctrl = 0x04; - dev->lpt = lpt_attach(info->local & 0xf, write_data, write_ctrl, strobe, read_status, read_ctrl, NULL, NULL, dev); + dev->lpt = lpt_attach(write_data, write_ctrl, strobe, read_status, read_ctrl, NULL, NULL, dev); rom_get_full_path(dev->fontpath, "roms/printer/fonts/"); diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 60e87e15e..77ecf0a5f 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -61,40 +61,55 @@ #define POSTSCRIPT_BUFFER_LENGTH 65536 +enum { + LANG_RAW = 0, + LANG_PS, + LANG_PCL_5E, + LANG_PCL_5C, + LANG_HP_RTL, + LANG_PCL_6 +}; + typedef struct ps_t { const char *name; - void *lpt; + void * lpt; - pc_timer_t pulse_timer; - pc_timer_t timeout_timer; + pc_timer_t pulse_timer; + pc_timer_t timeout_timer; - char data; - bool ack; - bool select; - bool busy; - bool int_pending; - bool error; - bool autofeed; - bool pcl; - bool pending; - bool pjl; - bool pjl_command; - uint8_t ctrl; - uint8_t pcl_escape; - uint16_t pjl_command_start; + bool ack; + bool select; + bool busy; + bool int_pending; + bool error; + bool autofeed; + bool pcl; + bool pending; + bool pjl; + bool pjl_command; - char printer_path[260]; + char data; - char filename[260]; + char printer_path[260]; + char filename[260]; - char buffer[POSTSCRIPT_BUFFER_LENGTH]; - size_t buffer_pos; + char buffer[POSTSCRIPT_BUFFER_LENGTH]; + + uint8_t ctrl; + uint8_t pcl_escape; + + uint16_t pjl_command_start; + + int lang; + + size_t buffer_pos; } ps_t; typedef struct gsapi_revision_s { const char *product; const char *copyright; + long revision; long revisiondate; } gsapi_revision_t; @@ -155,8 +170,23 @@ convert_to_pdf(ps_t *dev) gsargv[arg++] = "-dSAFER"; gsargv[arg++] = "-sDEVICE=pdfwrite"; if (dev->pcl) { - gsargv[arg++] = "-LPCL"; - gsargv[arg++] = "-lPCL5C"; + if (dev->lang == LANG_PCL_6) + gsargv[arg++] = "-LPCLXL"; + else { + gsargv[arg++] = "-LPCL"; + switch (dev->lang) { + default: + case LANG_PCL_5E: + gsargv[arg++] = "-lPCL5E"; + break; + case LANG_PCL_5C: + gsargv[arg++] = "-lPCL5C"; + break; + case LANG_HP_RTL: + gsargv[arg++] = "-lRTL"; + break; + } + } } gsargv[arg++] = "-q"; gsargv[arg++] = "-o"; @@ -196,7 +226,7 @@ reset_ps(ps_t *dev) dev->ack = false; if (dev->pending) { - if (ghostscript_handle != NULL) + if ((dev->lang != LANG_RAW) && (ghostscript_handle != NULL)) convert_to_pdf(dev); dev->filename[0] = 0; @@ -220,8 +250,14 @@ write_buffer(ps_t *dev, bool finish) if (dev->buffer_pos == 0) return; - if (dev->filename[0] == 0) - plat_tempfile(dev->filename, NULL, dev->pcl ? ".pcl" : ".ps"); + if (dev->filename[0] == 0) { + if (dev->lang == LANG_RAW) + plat_tempfile(dev->filename, NULL, ".raw"); + else if (dev->pcl) + plat_tempfile(dev->filename, NULL, (dev->lang == LANG_PCL_6) ? ".pxl" : ".pcl"); + else + plat_tempfile(dev->filename, NULL, ".ps"); + } strcpy(path, dev->printer_path); path_slash(path); @@ -244,7 +280,7 @@ write_buffer(ps_t *dev, bool finish) dev->buffer_pos = 0; if (finish) { - if (ghostscript_handle != NULL) + if ((dev->lang != LANG_RAW) && (ghostscript_handle != NULL)) convert_to_pdf(dev); dev->filename[0] = 0; @@ -262,7 +298,7 @@ timeout_timer(void *priv) if (dev->buffer_pos != 0) write_buffer(dev, true); else if (dev->pending) { - if (ghostscript_handle != NULL) + if ((dev->lang != LANG_RAW) && (ghostscript_handle != NULL)) convert_to_pdf(dev); dev->filename[0] = 0; @@ -284,97 +320,115 @@ ps_write_data(uint8_t val, void *priv) dev->data = (char) val; } +static int +process_escape(ps_t *dev, int do_pjl) +{ + int ret = 0; + + if (dev->data == 0x1b) + dev->pcl_escape = 1; + else switch (dev->pcl_escape) { + case 1: + dev->pcl_escape = (dev->data == 0x25) ? 2 : 0; + break; + case 2: + dev->pcl_escape = (dev->data == 0x2d) ? 3 : 0; + break; + case 3: + dev->pcl_escape = (dev->data == 0x31) ? 4 : 0; + break; + case 4: + dev->pcl_escape = (dev->data == 0x32) ? 5 : 0; + break; + case 5: + dev->pcl_escape = (dev->data == 0x33) ? 6 : 0; + break; + case 6: + dev->pcl_escape = (dev->data == 0x34) ? 7 : 0; + break; + case 7: + dev->pcl_escape = (dev->data == 0x35) ? 8 : 0; + break; + case 8: + dev->pcl_escape = 0; + if (dev->data == 0x58) { + if (do_pjl) + dev->pjl = true; + + dev->buffer[dev->buffer_pos++] = dev->data; + dev->buffer[dev->buffer_pos] = 0; + + /* Wipe the slate clean so that there won't be a bogus empty page output to PDF. */ + dev->pending = false; + ret = 1; + } + break; + } + + return ret; +} + static void process_data(ps_t *dev) { - /* On PCL, check for escape sequences. */ - if (dev->pcl) { - if (dev->pjl) { - dev->buffer[dev->buffer_pos++] = dev->data; - - /* Filter out any PJL commands. */ - if (dev->pjl_command && (dev->data == '\n')) { - dev->pjl_command = false; - if (!memcmp(&(dev->buffer[dev->pjl_command_start]), "@PJL ENTER LANGUAGE=PCL", 0x17)) - dev->pjl = false; - else if (!memcmp(&(dev->buffer[dev->pjl_command_start]), "@PJL ENTER LANGUAGE=POSTSCRIPT", 0x1e)) - fatal("Printing PostScript using the PCL printer is not (yet) supported!\n"); - dev->buffer[dev->buffer_pos] = 0x00; - dev->buffer_pos = dev->pjl_command_start; - } else if (!dev->pjl_command && (dev->buffer_pos >= 0x05) && !memcmp(&(dev->buffer[dev->buffer_pos - 0x5]), "@PJL ", 0x05)) { - dev->pjl_command = true; - dev->pjl_command_start = dev->buffer_pos - 0x05; - } else if (!dev->pjl_command && (dev->data == 0x1b)) - /* The universal exit code is also valid in PJL. */ - dev->pcl_escape = 1; - - dev->buffer[dev->buffer_pos] = 0; - return; - } else if (dev->data == 0x1b) - dev->pcl_escape = 1; - else switch (dev->pcl_escape) { - case 1: - dev->pcl_escape = (dev->data == 0x25) ? 2 : 0; - break; - case 2: - dev->pcl_escape = (dev->data == 0x2d) ? 3 : 0; - break; - case 3: - dev->pcl_escape = (dev->data == 0x31) ? 4 : 0; - break; - case 4: - dev->pcl_escape = (dev->data == 0x32) ? 5 : 0; - break; - case 5: - dev->pcl_escape = (dev->data == 0x33) ? 6 : 0; - break; - case 6: - dev->pcl_escape = (dev->data == 0x34) ? 7 : 0; - break; - case 7: - dev->pcl_escape = (dev->data == 0x35) ? 8 : 0; - break; - case 8: - dev->pcl_escape = 0; - if (dev->data == 0x58) { - dev->pjl = true; - - dev->buffer[dev->buffer_pos++] = dev->data; - dev->buffer[dev->buffer_pos] = 0; - - if (dev->pjl) - /* Wipe the slate clean so that there won't be a bogus empty page output to PDF. */ - dev->pending = false; - else if (dev->buffer_pos > 9) - write_buffer(dev, true); - return; - } - break; + if (dev->lang == LANG_RAW) { + if ((dev->data == 0x1b) || (dev->pcl_escape > 0)) { + if (process_escape(dev, 0)) + return; } - } else if ((dev->data < 0x20) || (dev->data == 0x7f)) { - /* On PostScript, check for non-printable characters. */ - switch (dev->data) { - /* The following characters are considered white-space - by the PostScript specification */ - case '\t': - case '\n': - case '\f': - case '\r': - break; + } else { + /* On PCL, check for escape sequences. */ + if (dev->pcl) { + if (dev->pjl) { + dev->buffer[dev->buffer_pos++] = dev->data; - /* Same with NUL, except we better change it to a space first */ - case '\0': - dev->data = ' '; - break; + /* Filter out any PJL commands. */ + if (dev->pjl_command && (dev->data == '\n')) { + dev->pjl_command = false; + if (!memcmp(&(dev->buffer[dev->pjl_command_start]), "@PJL ENTER LANGUAGE=PCL", 0x17)) + dev->pjl = false; + else if (!memcmp(&(dev->buffer[dev->pjl_command_start]), "@PJL ENTER LANGUAGE=POSTSCRIPT", 0x1e)) + fatal("Printing PostScript using the PCL printer is not (yet) supported!\n"); + dev->buffer[dev->buffer_pos] = 0x00; + dev->buffer_pos = dev->pjl_command_start; + } else if (!dev->pjl_command && (dev->buffer_pos >= 0x05) && !memcmp(&(dev->buffer[dev->buffer_pos - 0x5]), "@PJL ", 0x05)) { + dev->pjl_command = true; + dev->pjl_command_start = dev->buffer_pos - 0x05; + } else if (!dev->pjl_command && (dev->data == 0x1b)) + /* The universal exit code is also valid in PJL. */ + dev->pcl_escape = 1; - /* Ctrl+D (0x04) marks the end of the document */ - case '\4': - write_buffer(dev, true); + dev->buffer[dev->buffer_pos] = 0; return; + } else if ((dev->data == 0x1b) || (dev->pcl_escape > 0)) { + if (process_escape(dev, 1)) + return; + } + } else if ((dev->data < 0x20) || (dev->data == 0x7f)) { + /* On PostScript, check for non-printable characters. */ + switch (dev->data) { + /* The following characters are considered white-space + by the PostScript specification */ + case '\t': + case '\n': + case '\f': + case '\r': + break; - /* Don't bother with the others */ - default: - return; + /* Same with NUL, except we better change it to a space first */ + case '\0': + dev->data = ' '; + break; + + /* Ctrl+D (0x04) marks the end of the document */ + case '\4': + write_buffer(dev, true); + return; + + /* Don't bother with the others */ + default: + return; + } } } @@ -473,7 +527,8 @@ ps_init(const device_t *info) dev->ctrl = 0x04; dev->pcl = false; - dev->lpt = lpt_attach(info->local & 0xf, ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + dev->lpt = lpt_attach(ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + dev->lang = device_get_config_int("language"); /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); @@ -512,7 +567,6 @@ ps_init(const device_t *info) return dev; } -#ifdef USE_PCL static void * pcl_init(const device_t *info) { @@ -522,7 +576,8 @@ pcl_init(const device_t *info) dev->ctrl = 0x04; dev->pcl = true; - dev->lpt = lpt_attach(info->local & 0xf, ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + dev->lpt = lpt_attach(ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); + dev->lang = device_get_config_int("language"); /* Try loading the DLL. */ ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); @@ -560,7 +615,6 @@ pcl_init(const device_t *info) return dev; } -#endif static void ps_close(void *priv) @@ -581,6 +635,51 @@ ps_close(void *priv) free(dev); } +// clang-format off +static const device_config_t lpt_prt_ps_config[] = { + { + .name = "language", + .description = "Language", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = LANG_PS, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Raw", .value = LANG_RAW }, + { .description = "PDF (PostScript)", .value = LANG_PS }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + +// clang-format off +static const device_config_t lpt_prt_pcl_config[] = { + { + .name = "language", + .description = "Language", + .type = CONFIG_SELECTION, + .default_string = NULL, + .default_int = LANG_PCL_5E, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "Raw", .value = LANG_RAW }, + { .description = "PDF (PCL 5e)", .value = LANG_PCL_5E }, + { .description = "PDF (PCL 5c)", .value = LANG_PCL_5C }, + { .description = "PDF (HP-RTL)", .value = LANG_HP_RTL }, + { .description = "PDF (PCL 6)", .value = LANG_PCL_6 }, + { .description = "" } + }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } +}; +// clang-format on + const device_t lpt_prt_ps_device = { .name = "Generic PostScript Printer", .internal_name = "postscript", @@ -592,12 +691,11 @@ const device_t lpt_prt_ps_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = lpt_prt_ps_config }; -#ifdef USE_PCL const device_t lpt_prt_pcl_device = { - .name = "Generic PCL5e Printer", + .name = "Generic PCL Printer", .internal_name = "pcl", .flags = DEVICE_LPT, .local = 0, @@ -607,6 +705,5 @@ const device_t lpt_prt_pcl_device = { .available = NULL, .speed_changed = NULL, .force_redraw = NULL, - .config = NULL + .config = lpt_prt_pcl_config }; -#endif diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index 0e27bf1af..ad49bc56f 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -461,7 +461,7 @@ prnt_init(const device_t *info) prnt_t *dev = (prnt_t *) calloc(1, sizeof(prnt_t)); dev->ctrl = 0x04; - dev->lpt = lpt_attach(info->local & 0xf, write_data, write_ctrl, strobe, read_status, NULL, NULL, NULL, dev); + dev->lpt = lpt_attach(write_data, write_ctrl, strobe, read_status, NULL, NULL, NULL, dev); /* Initialize parameters. */ reset_printer(dev); diff --git a/src/qt/languages/86box.pot b/src/qt/languages/86box.pot index c5d1d2514..c62c18ea8 100644 --- a/src/qt/languages/86box.pot +++ b/src/qt/languages/86box.pot @@ -3017,3 +3017,6 @@ msgstr "" msgid "To change the system directory, stop all running machines." msgstr "" + +msgid "Raw" +msgstr "" diff --git a/src/qt/languages/ca-ES.po b/src/qt/languages/ca-ES.po index ad9dd6eb1..0c1c8ac89 100644 --- a/src/qt/languages/ca-ES.po +++ b/src/qt/languages/ca-ES.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Permetre recompilació" msgid "&Fast forward" -msgstr "" +msgstr "&Avançar ràpidament" msgid "Fast forward" -msgstr "" +msgstr "Avançar ràpidament" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Per canviar el directori del sistema, atureu totes les màquines en funcionament." + +msgid "Raw" +msgstr "En brut" diff --git a/src/qt/languages/cs-CZ.po b/src/qt/languages/cs-CZ.po index 5e89f736a..1df82475f 100644 --- a/src/qt/languages/cs-CZ.po +++ b/src/qt/languages/cs-CZ.po @@ -3022,5 +3022,7 @@ msgid "Fast forward" msgstr "Zrychlit" msgid "To change the system directory, stop all running machines." -msgstr "" -"Před změnou systémového adresáře nejprve zastavte všechny běžící počítače." +msgstr "Před změnou systémového adresáře nejprve zastavte všechny běžící počítače." + +msgid "Raw" +msgstr "Surový" diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index 38e829861..f377fcad0 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "Recompilierung &zulassen" msgid "&Fast forward" -msgstr "" +msgstr "&Schnellvorlauf" msgid "Fast forward" -msgstr "" +msgstr "Schnellvorlauf" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Um das Systemverzeichnis zu ändern, stoppen Sie alle laufenden Maschinen." + +msgid "Raw" +msgstr "Roh" diff --git a/src/qt/languages/el-GR.po b/src/qt/languages/el-GR.po index 5cb45bded..6933075a5 100644 --- a/src/qt/languages/el-GR.po +++ b/src/qt/languages/el-GR.po @@ -3083,6 +3083,7 @@ msgid "Fast forward" msgstr "Γρήγορα μπροστά" msgid "To change the system directory, stop all running machines." -msgstr "" -"Για να αλλάξετε τον κατάλογο συστήματος, σταματήστε πρώτα όλες τις μηχανές " -"σε λειτουργία." +msgstr "Για να αλλάξετε τον κατάλογο συστήματος, σταματήστε πρώτα όλες τις μηχανές σε λειτουργία." + +msgid "Raw" +msgstr "Αρχικος" diff --git a/src/qt/languages/es-ES.po b/src/qt/languages/es-ES.po index 3d339efd0..4f34c34f5 100644 --- a/src/qt/languages/es-ES.po +++ b/src/qt/languages/es-ES.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Permitir recompilación" msgid "&Fast forward" -msgstr "" +msgstr "&Avance rápido" msgid "Fast forward" -msgstr "" +msgstr "Avance rápido" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Para cambiar el directorio del sistema, detenga todas las máquinas en funcionamiento." + +msgid "Raw" +msgstr "Plano" diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index fd6add696..a5f36d2d4 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Salli uudelleenkääntäminen" msgid "&Fast forward" -msgstr "" +msgstr "&Nopea eteneminen" msgid "Fast forward" -msgstr "" +msgstr "Nopea eteneminen" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Järjestelmähakemiston muuttamiseksi pysäytä kaikki käynnissä olevat koneet." + +msgid "Raw" +msgstr "Raaka" diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index 2e1422a08..42f1a8f40 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Permettre la recompilation" msgid "&Fast forward" -msgstr "" +msgstr "&Avance rapide" msgid "Fast forward" -msgstr "" +msgstr "Avance rapide" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Pour modifier le répertoire système, arrêtez toutes les machines en cours d'exécution." + +msgid "Raw" +msgstr "Brut" diff --git a/src/qt/languages/hr-HR.po b/src/qt/languages/hr-HR.po index b3d9a68f1..32aaf1cf7 100644 --- a/src/qt/languages/hr-HR.po +++ b/src/qt/languages/hr-HR.po @@ -3018,10 +3018,13 @@ msgid "&Allow recompilation" msgstr "&Omogući rekompilaciju" msgid "&Fast forward" -msgstr "" +msgstr "&Brzo naprijed" msgid "Fast forward" -msgstr "" +msgstr "Brzo naprijed" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Za promjenu sustavskog direktorija zaustavite sve pokrenute strojeve." + +msgid "Raw" +msgstr "Neobrađeni podaci" diff --git a/src/qt/languages/it-IT.po b/src/qt/languages/it-IT.po index f4d16bf86..f46d09159 100644 --- a/src/qt/languages/it-IT.po +++ b/src/qt/languages/it-IT.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Permetti ricompilazione" msgid "&Fast forward" -msgstr "" +msgstr "&Avanti veloce" msgid "Fast forward" -msgstr "" +msgstr "Avanti veloce" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Per modificare la directory di sistema, arrestare tutte le macchine in funzione." + +msgid "Raw" +msgstr "Grezzo" diff --git a/src/qt/languages/ja-JP.po b/src/qt/languages/ja-JP.po index 2a7809a47..027b05204 100644 --- a/src/qt/languages/ja-JP.po +++ b/src/qt/languages/ja-JP.po @@ -3017,10 +3017,13 @@ msgid "&Allow recompilation" msgstr "再コンパイルを許可する(&A)" msgid "&Fast forward" -msgstr "" +msgstr "早送り(&F)" msgid "Fast forward" -msgstr "" +msgstr "早送り" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "システムディレクトリを変更するには、稼働中のマシンをすべて停止してください。" + +msgid "Raw" +msgstr "生" diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index 0318e85f3..cd186260b 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "재컴파일 허용(&A)" msgid "&Fast forward" -msgstr "" +msgstr "빠른 전진(&F)" msgid "Fast forward" -msgstr "" +msgstr "빠른 전진" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "시스템 디렉터리를 변경하려면 실행 중인 모든 머신을 중지하십시오." + +msgid "Raw" +msgstr "원본" diff --git a/src/qt/languages/nb-NO.po b/src/qt/languages/nb-NO.po index e31768305..88679fdd3 100644 --- a/src/qt/languages/nb-NO.po +++ b/src/qt/languages/nb-NO.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "&Tillat rekompilering" msgid "&Fast forward" -msgstr "" +msgstr "&Spol fremover" msgid "Fast forward" -msgstr "" +msgstr "Spol fremover" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "For å endre systemkatalogen, stopp alle maskiner som er kjører." + +msgid "Raw" +msgstr "Rå" diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 3d056a2ea..63dcd239b 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "Recompilatie &toestaan" msgid "&Fast forward" -msgstr "" +msgstr "&Snel vooruitspoelen" msgid "Fast forward" -msgstr "" +msgstr "Snel vooruitspoelen" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Om de systeemmap te wijzigen, moet u alle actieve machines stoppen." + +msgid "Raw" +msgstr "Ruw" diff --git a/src/qt/languages/pl-PL.po b/src/qt/languages/pl-PL.po index 20317c9ec..e67ada685 100644 --- a/src/qt/languages/pl-PL.po +++ b/src/qt/languages/pl-PL.po @@ -3017,10 +3017,13 @@ msgid "&Allow recompilation" msgstr "&Zezwól na rekompilację" msgid "&Fast forward" -msgstr "" +msgstr "&Przewiń do przodu" msgid "Fast forward" -msgstr "" +msgstr "Przewiń do przodu" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Aby zmienić katalog systemowy, zatrzymaj wszystkie działające maszyny." + +msgid "Raw" +msgstr "Surowy" diff --git a/src/qt/languages/pt-BR.po b/src/qt/languages/pt-BR.po index 31875d7ba..5ffbc2c72 100644 --- a/src/qt/languages/pt-BR.po +++ b/src/qt/languages/pt-BR.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "&Permitir recompilação" msgid "&Fast forward" -msgstr "" +msgstr "&Avançar rapidamente" msgid "Fast forward" -msgstr "" +msgstr "Avançar rapidamente" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Para alterar o diretório do sistema, pare todas as máquinas em funcionamento." + +msgid "Raw" +msgstr "Bruto" diff --git a/src/qt/languages/pt-PT.po b/src/qt/languages/pt-PT.po index f18eb8f1a..8f0f55caf 100644 --- a/src/qt/languages/pt-PT.po +++ b/src/qt/languages/pt-PT.po @@ -3017,10 +3017,13 @@ msgid "&Allow recompilation" msgstr "&Permitir recompilação" msgid "&Fast forward" -msgstr "" +msgstr "&Avançar rapidamente" msgid "Fast forward" -msgstr "" +msgstr "Avançar rapidamente" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Para alterar o diretório do sistema, pare todas as máquinas em funcionamento." + +msgid "Raw" +msgstr "Bruto" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index 6102dceed..9ca679356 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -3036,3 +3036,6 @@ msgstr "Перемотка вперёд" msgid "To change the system directory, stop all running machines." msgstr "Чтобы изменить системную папку, остановите все запущенные машины." + +msgid "Raw" +msgstr "Сырой" diff --git a/src/qt/languages/sk-SK.po b/src/qt/languages/sk-SK.po index a112005da..a5570faeb 100644 --- a/src/qt/languages/sk-SK.po +++ b/src/qt/languages/sk-SK.po @@ -3016,10 +3016,13 @@ msgid "&Allow recompilation" msgstr "&Povoliť rekompiláciu" msgid "&Fast forward" -msgstr "" +msgstr "&Rýchly posun dopredu" msgid "Fast forward" -msgstr "" +msgstr "Rýchly posun dopredu" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Ak chcete zmeniť systémový adresár, zastavte všetky bežiace stroje." + +msgid "Raw" +msgstr "Surový" diff --git a/src/qt/languages/sl-SI.po b/src/qt/languages/sl-SI.po index 64cc6e7eb..dfe0acbcd 100644 --- a/src/qt/languages/sl-SI.po +++ b/src/qt/languages/sl-SI.po @@ -3018,10 +3018,13 @@ msgid "&Allow recompilation" msgstr "&Dovoli prevajanje" msgid "&Fast forward" -msgstr "" +msgstr "&Hitro previj" msgid "Fast forward" -msgstr "" +msgstr "Hitro previj" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Da bi spremenili sistemski imenik, ustavite vse naprave, ki se izvajajo." + +msgid "Raw" +msgstr "Neobdelan" diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index f49235919..eb7633168 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "&Tillåt omkompilering" msgid "&Fast forward" -msgstr "" +msgstr "&Spola fram" msgid "Fast forward" -msgstr "" +msgstr "Spola fram" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "ör att ändra systemkatalogen, stoppa alla maskiner som är körs." + +msgid "Raw" +msgstr "Rå" diff --git a/src/qt/languages/tr-TR.po b/src/qt/languages/tr-TR.po index a40e07e4b..510fd82f3 100644 --- a/src/qt/languages/tr-TR.po +++ b/src/qt/languages/tr-TR.po @@ -3023,3 +3023,6 @@ msgstr "İleri sar" msgid "To change the system directory, stop all running machines." msgstr "Sistem dizinini değiştirmek için tüm çalışan makineleri durdurun." + +msgid "Raw" +msgstr "Ham" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 7fd0d0b33..d1964e647 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -3018,10 +3018,13 @@ msgid "&Allow recompilation" msgstr "&Дозволити рекомпіляцію" msgid "&Fast forward" -msgstr "" +msgstr "&Перемотай вперед" msgid "Fast forward" -msgstr "" +msgstr "Перемотай вперед" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Щоб змінити системний каталог, зупиніть усі машини, що працюють." + +msgid "Raw" +msgstr "Сирий" diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index b2c7491a1..64d00e210 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -3010,10 +3010,13 @@ msgid "&Allow recompilation" msgstr "&Cho phép biên dịch lại" msgid "&Fast forward" -msgstr "" +msgstr "&Chuyển nhanh băng" msgid "Fast forward" -msgstr "" +msgstr "Chuyển nhanh băng" msgid "To change the system directory, stop all running machines." -msgstr "" +msgstr "Để thay đổi thư mục hệ thống, hãy tắt tất cả các máy đang chạy." + +msgid "Raw" +msgstr "Thô" diff --git a/src/qt/languages/zh-CN.po b/src/qt/languages/zh-CN.po index c922e207b..7e98480cd 100644 --- a/src/qt/languages/zh-CN.po +++ b/src/qt/languages/zh-CN.po @@ -3024,3 +3024,6 @@ msgstr "快进" msgid "To change the system directory, stop all running machines." msgstr "请在变更系统目录前关闭所有正在运行的虚拟机。" + +msgid "Raw" +msgstr "原始" diff --git a/src/qt/languages/zh-TW.po b/src/qt/languages/zh-TW.po index 0bdcd215a..78365a911 100644 --- a/src/qt/languages/zh-TW.po +++ b/src/qt/languages/zh-TW.po @@ -3024,3 +3024,6 @@ msgstr "快轉" msgid "To change the system directory, stop all running machines." msgstr "欲變更系統目錄,請先停止全部運行中的機器。" + +msgid "Raw" +msgstr "原始" diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index f2268cd0f..77271ed8d 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -93,7 +93,7 @@ dac_init(UNUSED(const device_t *info)) { lpt_dac_t *lpt_dac = calloc(1, sizeof(lpt_dac_t)); - lpt_dac->lpt = lpt_attach(info->local & 0xf, dac_write_data, dac_write_ctrl, dac_strobe, dac_read_status, NULL, NULL, NULL, lpt_dac); + lpt_dac->lpt = lpt_attach(dac_write_data, dac_write_ctrl, dac_strobe, dac_read_status, NULL, NULL, NULL, lpt_dac); sound_add_handler(dac_get_buffer, lpt_dac); diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 2581d7873..6fac66b6e 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -118,7 +118,7 @@ dss_init(UNUSED(const device_t *info)) { dss_t *dss = calloc(1, sizeof(dss_t)); - dss->lpt = lpt_attach(info->local & 0xf, dss_write_data, dss_write_ctrl, NULL, dss_read_status, NULL, NULL, NULL, dss); + dss->lpt = lpt_attach(dss_write_data, dss_write_ctrl, NULL, dss_read_status, NULL, NULL, NULL, dss); sound_add_handler(dss_get_buffer, dss); timer_add(&dss->timer, dss_callback, dss, 1); From 7bbbf489135c6ec5d79f534beb79a6cb2040dcda Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 18:58:39 +0100 Subject: [PATCH 06/31] PostScript and PCL printers: Do not attempt to load the library if the language is set to raw. --- src/printer/prt_ps.c | 64 ++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 77ecf0a5f..29ae78feb 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -530,25 +530,28 @@ ps_init(const device_t *info) dev->lpt = lpt_attach(ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); dev->lang = device_get_config_int("language"); - /* Try loading the DLL. */ - ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); + if (dev->lang != LANG_RAW) { + /* Try loading the DLL. */ + ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL, ghostscript_imports); #ifdef PATH_GHOSTSCRIPT_DLL_ALT1 - if (ghostscript_handle == NULL) { - ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT1, ghostscript_imports); + if (ghostscript_handle == NULL) { + ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT1, ghostscript_imports); # ifdef PATH_GHOSTSCRIPT_DLL_ALT2 - if (ghostscript_handle == NULL) - ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT2, ghostscript_imports); + if (ghostscript_handle == NULL) + ghostscript_handle = dynld_module(PATH_GHOSTSCRIPT_DLL_ALT2, ghostscript_imports); # endif - } + } #endif - if (ghostscript_handle == NULL) { - ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTSCRIPT_ERROR_TITLE), plat_get_string(STRING_GHOSTSCRIPT_ERROR_DESC)); - } else { - if (gsapi_revision(&rev, sizeof(rev)) == 0) { - pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); - } else { - dynld_close(ghostscript_handle); - ghostscript_handle = NULL; + + if (ghostscript_handle == NULL) { + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTSCRIPT_ERROR_TITLE), plat_get_string(STRING_GHOSTSCRIPT_ERROR_DESC)); + } else { + if (gsapi_revision(&rev, sizeof(rev)) == 0) { + pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); + } else { + dynld_close(ghostscript_handle); + ghostscript_handle = NULL; + } } } @@ -579,25 +582,28 @@ pcl_init(const device_t *info) dev->lpt = lpt_attach(ps_write_data, ps_write_ctrl, ps_strobe, ps_read_status, NULL, NULL, NULL, dev); dev->lang = device_get_config_int("language"); - /* Try loading the DLL. */ - ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); + if (dev->lang != LANG_RAW) { + /* Try loading the DLL. */ + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); #ifdef PATH_GHOSTPCL_DLL_ALT1 - if (ghostscript_handle == NULL) { - ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT1, ghostscript_imports); + if (ghostscript_handle == NULL) { + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT1, ghostscript_imports); # ifdef PATH_GHOSTPCL_DLL_ALT2 - if (ghostscript_handle == NULL) - ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT2, ghostscript_imports); + if (ghostscript_handle == NULL) + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT2, ghostscript_imports); # endif - } + } #endif - if (ghostscript_handle == NULL) { - ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTPCL_ERROR_TITLE), plat_get_string(STRING_GHOSTPCL_ERROR_DESC)); - } else { - if (gsapi_revision(&rev, sizeof(rev)) == 0) { - pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); + + if (ghostscript_handle == NULL) { + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTPCL_ERROR_TITLE), plat_get_string(STRING_GHOSTPCL_ERROR_DESC)); } else { - dynld_close(ghostscript_handle); - ghostscript_handle = NULL; + if (gsapi_revision(&rev, sizeof(rev)) == 0) { + pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); + } else { + dynld_close(ghostscript_handle); + ghostscript_handle = NULL; + } } } From 2a00f72a6fd0e53ecb0192cb876c258d65e39a75 Mon Sep 17 00:00:00 2001 From: Bozo Scum Date: Wed, 28 Jan 2026 13:38:26 +0800 Subject: [PATCH 07/31] VTech Laser Turbo XT: add older BIOS 1.08 --- src/chipset/laserxt.c | 31 +++++++++++++++++++++++++++++++ src/include/86box/machine.h | 3 +++ src/machine/m_xt.c | 13 ++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/chipset/laserxt.c b/src/chipset/laserxt.c index a5308e2f0..bf2636b91 100644 --- a/src/chipset/laserxt.c +++ b/src/chipset/laserxt.c @@ -296,6 +296,37 @@ lxt_init(const device_t *info) } static const device_config_t laserxt_config[] = { + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "laserxt_126", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "1.08", + .internal_name = "laserxt_108", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { "roms/machines/ltxt/ltxt-v1.08.bin", "" } + }, + { + .name = "1.26", + .internal_name = "laserxt_126", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 0, + .size = 8192, + .files = { "roms/machines/ltxt/27c64.bin", "" } + }, + { .files_no = 0 } + } + }, { .name = "ems_1_base", .description = "EMS 1 Address", diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 6ab3883c8..793aee6fe 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1479,6 +1479,9 @@ extern int machine_xt_to16_init(const machine_t *); extern const device_t vendex_device; #endif extern int machine_xt_vendex_init(const machine_t *); +#ifdef EMU_DEVICE_H +extern const device_t laserxt_device; +#endif extern int machine_xt_laserxt_init(const machine_t *); extern int machine_xt_znic_init(const machine_t *); extern int machine_xt_z151_init(const machine_t *); diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 81c9eba72..6da39d997 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -1884,10 +1884,17 @@ machine_xt_laserxt_common_init(const machine_t *model, int is_lxt3) int machine_xt_laserxt_init(const machine_t *model) { - int ret; + int ret = 0; + const char *fn; - ret = bios_load_linear("roms/machines/ltxt/27c64.bin", - 0x000fe000, 8192, 0); + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; + + device_context(model->device); + fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + ret = bios_load_linear(fn, 0x000fe000, 8192, 0); + device_context_restore(); if (bios_only || !ret) return ret; From 715a6cf4cda69eabeeae42813863ebe79df4204e Mon Sep 17 00:00:00 2001 From: Bozo Scum Date: Wed, 28 Jan 2026 13:45:15 +0800 Subject: [PATCH 08/31] makes Victor V86P BIOS versions selectable --- src/include/86box/machine.h | 3 ++ src/machine/m_v86p.c | 104 +++++++++++++++++++++++++++++------- src/machine/machine_table.c | 2 +- 3 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index 793aee6fe..caf929c19 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -1408,6 +1408,9 @@ extern const device_t tandy_1000sl_video_device; extern int machine_tandy1000sl2_init(const machine_t *); /* m_v86p.c */ +#ifdef EMU_DEVICE_H +extern const device_t v86p_device; +#endif extern int machine_v86p_init(const machine_t *); /* m_xt.c */ diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c index 126517345..d30d9c8a6 100644 --- a/src/machine/m_v86p.c +++ b/src/machine/m_v86p.c @@ -48,35 +48,101 @@ #include <86box/sio.h> #include <86box/video.h> +static const device_config_t v86p_config[] = { + // clang-format off + { + .name = "bios", + .description = "BIOS Version", + .type = CONFIG_BIOS, + .default_string = "v86p_122089", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { + { + .name = "12/20/89", + .internal_name = "v86p_122089", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", + "" } + }, + { + .name = "09/04/89", + .internal_name = "v86p_090489", + .bios_type = BIOS_NORMAL, + .files_no = 2, + .local = 0, + .size = 65536, + .files = { "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", + "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", + "" } + }, + { + .name = "09/04/89 (Alt)", + .internal_name = "v86p_jvernet", + .bios_type = BIOS_NORMAL, + .files_no = 1, + .local = 1, + .size = 65536, + .files = { "roms/machines/v86p/V86P.ROM", + "" } + }, + { .files_no = 0 } + } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t v86p_device = { + .name = "Victor V86P", + .internal_name = "v86p_device", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + .available = NULL, + .speed_changed = NULL, + .force_redraw = NULL, + .config = v86p_config +}; + int machine_v86p_init(const machine_t *model) { - int ret; - int rom_id = 0; + int ret = 0; + int files_no = 0; + int local = 0; + const char *fn1, *fn2; - ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Even.rom", - "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_122089_Odd.rom", - 0x000f8000, 65536, 0); + /* No ROMs available. */ + if (!device_available(model->device)) + return ret; - if (!ret) { - /* Try an older version of the BIOS. */ - rom_id = 1; - ret = bios_load_interleavedr("roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Even.rom", - "roms/machines/v86p/INTEL8086AWD_BIOS_S3.1_V86P_090489_Odd.rom", - 0x000f8000, 65536, 0); - } - - if (!ret) { - /* Try JVERNET's BIOS. */ - rom_id = 2; - ret = bios_load_linear("roms/machines/v86p/V86P.ROM", - 0x000f0000, 65536, 0); + device_context(model->device); + files_no = device_get_bios_num_files(model->device, device_get_config_bios("bios")); + local = device_get_bios_local(model->device, device_get_config_bios("bios")); + fn1 = device_get_bios_file(model->device, device_get_config_bios("bios"), 0); + + if (files_no > 1) + { + fn2 = device_get_bios_file(model->device, device_get_config_bios("bios"), 1); + ret = bios_load_interleavedr(fn1, fn2, 0x000f8000, 65536, 0); } + else + ret = bios_load_linear(fn1, 0x000f0000, 65536, 0); + device_context_restore(); if (bios_only || !ret) return ret; - if (rom_id == 2) + if (local > 0) video_load_font("roms/machines/v86p/V86P.FON", FONT_FORMAT_PC1512_T1000, LOAD_FONT_NO_OFFSET); else video_load_font("roms/machines/v86p/v86pfont.rom", FONT_FORMAT_PC1512_T1000, LOAD_FONT_NO_OFFSET); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index e113f3fe0..762c4410e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -2982,7 +2982,7 @@ const machine_t machines[] = { .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, - .device = NULL, + .device = &v86p_device, .kbd_device = NULL, .fdc_device = NULL, .sio_device = NULL, From 85599deeb18a2410fc06d766fba12fafe282e5dc Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 07:44:12 +0100 Subject: [PATCH 09/31] Ports Settings: Add lpt_device_available() check. --- src/qt/qt_settingsports.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index b1155629d..232822201 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -138,13 +138,15 @@ SettingsPorts::onCurrentMachineChanged(int machineId) if (lptName == nullptr) break; - const QString name = tr(lptName); + if (lpt_device_available(c)) { + const QString name = tr(lptName); - for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { - int row = Models::AddEntry(models[i], name, c); + for (uint8_t i = 0; i < PARALLEL_MAX; ++i) { + int row = Models::AddEntry(models[i], name, c); - if (c == lpt_ports[i].device) - selectedRows[i] = row - removeRows_[i]; + if (c == lpt_ports[i].device) + selectedRows[i] = row - removeRows_[i]; + } } c++; From 72ea51332deefc227e5912540329fa7815a588cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 08:45:05 +0100 Subject: [PATCH 10/31] Use the 808x rewrite from the 808x_rewrite branch as the NEC Vx0 rewrite, as it's good enough for that (it even approximates the NEC Vx0 timings unlike what was there before which did not even remotely attempt to). --- src/cpu/808x.c | 566 +---- src/cpu/CMakeLists.txt | 2 + src/cpu/cpu.c | 2 + src/cpu/cpu.h | 3 + src/cpu/vx0.c | 4783 ++++++++++++++++++++++++++++++++++++++++ src/cpu/vx0_biu.c | 1152 ++++++++++ src/cpu/vx0_biu.h | 116 + src/cpu/x86.c | 8 +- src/cpu/x86.h | 2 + src/cpu/x87_ops.h | 4 + src/cpu/x87_ops_misc.h | 4 + src/cpu/x87_ops_sf.h | 4 + 12 files changed, 6114 insertions(+), 532 deletions(-) create mode 100644 src/cpu/vx0.c create mode 100644 src/cpu/vx0_biu.c create mode 100644 src/cpu/vx0_biu.h diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 4e2e830d0..7908160e8 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -51,7 +51,8 @@ uint32_t custom_nmi_vector = 0x00000000; static uint8_t pfq[6]; /* Variables to aid with the prefetch queue operation. */ -static int biu_cycles = 0, pfq_pos = 0; +static int biu_cycles = 0; +int pfq_pos = 0; /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; @@ -66,7 +67,7 @@ static int cpu_alu_op, pfq_size; static uint32_t cpu_src = 0, cpu_dest = 0; static uint32_t cpu_data = 0; -static uint16_t last_addr = 0x0000; +uint16_t last_addr = 0x0000; static uint32_t *ovr_seg = NULL; static int prefetching = 1, completed = 1; @@ -204,67 +205,12 @@ prefetch_queue_get_size(void) } static void set_if(int cond); -void -sync_from_i8080(void) -{ - AL = emulated_processor.a; - BH = emulated_processor.h; - BL = emulated_processor.l; - CH = emulated_processor.b; - CL = emulated_processor.c; - DH = emulated_processor.d; - DL = emulated_processor.e; - BP = emulated_processor.sp; - - cpu_state.pc = emulated_processor.pc; - cpu_state.flags &= 0xFF00; - cpu_state.flags |= emulated_processor.sf << 7; - cpu_state.flags |= emulated_processor.zf << 6; - cpu_state.flags |= emulated_processor.hf << 4; - cpu_state.flags |= emulated_processor.pf << 2; - cpu_state.flags |= 1 << 1; - cpu_state.flags |= emulated_processor.cf << 0; - set_if(emulated_processor.iff); -} - -void -sync_to_i8080(void) -{ - if (!is_nec) - return; - emulated_processor.a = AL; - emulated_processor.h = BH; - emulated_processor.l = BL; - emulated_processor.b = CH; - emulated_processor.c = CL; - emulated_processor.d = DH; - emulated_processor.e = DL; - emulated_processor.sp = BP; - emulated_processor.pc = cpu_state.pc; - emulated_processor.iff = !!(cpu_state.flags & I_FLAG); - - emulated_processor.sf = (cpu_state.flags >> 7) & 1; - emulated_processor.zf = (cpu_state.flags >> 6) & 1; - emulated_processor.hf = (cpu_state.flags >> 4) & 1; - emulated_processor.pf = (cpu_state.flags >> 2) & 1; - emulated_processor.cf = (cpu_state.flags >> 0) & 1; - - emulated_processor.interrupt_delay = noint; -} - - uint16_t get_last_addr(void) { return last_addr; } -static void -clock_start(void) -{ - cycdiff = cycles; -} - static void clock_end(void) { @@ -293,7 +239,7 @@ fetch_and_bus(int c, int bus) pfq_add(c, !bus); if (bus < 2) { clock_end(); - clock_start(); + cycdiff = cycles; } } @@ -412,7 +358,7 @@ readmemw(uint32_t s, uint16_t a) else { wait_cycs(4, 1); ret = read_mem_b(s + a); - ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8; + ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8; } return ret; @@ -484,7 +430,7 @@ writememw(uint32_t s, uint32_t a, uint16_t v) else { write_mem_b(addr, v & 0xff); wait_cycs(4, 1); - addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff)); + addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff)); write_mem_b(addr, v >> 8); } @@ -693,8 +639,6 @@ reset_808x(int hard) load_cs(0xFFFF); cpu_state.pc = 0; - if (is_nec) - cpu_state.flags |= MD_FLAG; rammask = 0xfffff; prefetching = 1; @@ -929,7 +873,7 @@ seteaq(uint64_t val) static void push(uint16_t *val) { - if ((is186 && !is_nec) && (SP == 1)) { + if (is186 && (SP == 1)) { writememw(ss - 1, 0, *val); SP = cpu_state.eaaddr = 0xFFFF; return; @@ -1085,11 +1029,6 @@ interrupt(uint16_t addr) uint16_t new_cs, new_ip; uint16_t tempf; - if (!(cpu_state.flags & MD_FLAG) && is_nec) { - sync_from_i8080(); - x808x_log("CALLN/INT#/NMI#\n"); - } - addr <<= 2; cpu_state.eaaddr = addr; old_cs = CS; @@ -1103,11 +1042,9 @@ interrupt(uint16_t addr) pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + tempf = cpu_state.flags & 0x0fd7; push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); - if (is_nec) - cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; @@ -1118,71 +1055,6 @@ interrupt(uint16_t addr) push(&old_ip); } -/* Ditto, but for breaking into emulation mode. */ -static void -interrupt_brkem(uint16_t addr) -{ - uint16_t old_cs, old_ip; - uint16_t new_cs, new_ip; - uint16_t tempf; - - addr <<= 2; - cpu_state.eaaddr = addr; - old_cs = CS; - access(5, 16); - new_ip = readmemw(0, cpu_state.eaaddr); - wait_cycs(1, 0); - cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - access(6, 16); - new_cs = readmemw(0, cpu_state.eaaddr); - prefetching = 0; - pfq_clear(); - ovr_seg = NULL; - access(39, 16); - tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); - push(&tempf); - cpu_state.flags &= ~(MD_FLAG); - cpu_md_write_disable = 0; - 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); - sync_to_i8080(); - x808x_log("BRKEM mode\n"); -} - -void -retem_i8080(void) -{ - sync_from_i8080(); - - prefetching = 0; - pfq_clear(); - - set_ip(pop()); - load_cs(pop()); - cpu_state.flags = pop(); - - emulated_processor.iff = !!(cpu_state.flags & I_FLAG); - - cpu_md_write_disable = 1; - - noint = 1; - nmi_enable = 1; - - x808x_log("RETEM mode\n"); -} - -void -interrupt_808x(uint16_t addr) -{ - interrupt(addr); -} - static void custom_nmi(void) { @@ -1190,11 +1062,6 @@ custom_nmi(void) uint16_t new_cs, new_ip; uint16_t tempf; - if (!(cpu_state.flags & MD_FLAG) && is_nec) { - sync_from_i8080(); - pclog("NMI# (CUTSOM)\n"); - } - cpu_state.eaaddr = 0x0002; old_cs = CS; access(5, 16); @@ -1209,11 +1076,9 @@ custom_nmi(void) pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + tempf = cpu_state.flags & 0x0fd7; push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); - if (is_nec) - cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; @@ -1225,10 +1090,10 @@ custom_nmi(void) } static int -irq_pending(int nec_hlt) +irq_pending(void) { uint8_t temp; - int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; + int i_flag = (cpu_state.flags & I_FLAG); temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || (i_flag && pic.int_pending && !noint); @@ -1236,12 +1101,12 @@ irq_pending(int nec_hlt) } static void -check_interrupts(int nec_hlt) +check_interrupts(void) { int temp; - int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; + int i_flag = (cpu_state.flags & I_FLAG); - if (irq_pending(nec_hlt)) { + if (irq_pending()) { if ((cpu_state.flags & T_FLAG) && !(noint & 1)) { interrupt(1); return; @@ -1290,13 +1155,10 @@ rep_action(int bits) return 0; wait_cycs(2, 0); t = CX; - if (irq_pending(0) && (repeating != 0)) { + 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); + set_ip(cpu_state.pc - 2); t = 0; } if (t == 0) { @@ -1919,32 +1781,16 @@ void execx86(int cycs) { 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, tempw, new_cs, new_ip; + uint16_t addr, tempw, new_cs, new_ip, handled = 0; uint16_t tempw_int, size, tempbp, lowbound; - uint16_t highbound, regval, orig_sp, wordtopush; - uint16_t immediate, old_flags; + uint16_t highbound, regval, orig_sp, wordtopush, immediate; int bits; - uint32_t dest_seg, i, carry, nibble; - uint32_t srcseg, byteaddr; + uint32_t dest_seg; cycles += cycs; while (cycles > 0) { - clock_start(); - - if (is_nec && !(cpu_state.flags & MD_FLAG)) { - i8080_step(&emulated_processor); - set_if(emulated_processor.iff); - cycles -= emulated_processor.cyc; - emulated_processor.cyc = 0; - completed = 1; - goto exec_completed; - } + cycdiff = cycles; if (!repeating) { cpu_state.oldpc = cpu_state.pc; @@ -2004,18 +1850,6 @@ execx86(int cycs) handled = 1; break; - case 0x64: - case 0x65: - if (is_nec) { - /* REPC/REPNC */ - wait_cycs(1, 0); - in_rep = (opcode == 0x64 ? 1 : 2); - rep_c_flag = 1; - completed = 0; - handled = 1; - } - break; - case 0x68: wordtopush = pfq_fetchw(); wait_cycs(1, 0); @@ -2111,7 +1945,6 @@ execx86(int cycs) tempw_int = 0; size = pfq_fetchw(); nests = pfq_fetchb(); - i = 0; push(&BP); tempw_int = SP; @@ -2141,8 +1974,7 @@ execx86(int cycs) wait_cycs((cpu_mod != 3) ? 9 : 6, 0); - if (!is_nec) - cpu_src &= 0x1F; + cpu_src &= 0x1F; while (cpu_src != 0) { cpu_dest = cpu_data; oldc = cpu_state.flags & C_FLAG; @@ -2239,299 +2071,6 @@ execx86(int cycs) case 0x0F: case 0x17: case 0x1F: /* POP seg */ - if (is_nec && (opcode == 0x0F)) { - uint8_t orig_opcode = opcode; - opcode = pfq_fetchb(); - switch (opcode) { - case 0x28: /* ROL4 r/m */ - do_mod_rm(); - wait_cycs(21, 0); - - temp_val = geteab(); - temp_al = AL; - - temp_al &= 0xF; - temp_al |= (temp_val & 0xF0); - temp_val = (temp_al & 0xF) | ((temp_val & 0xF) << 4); - temp_al >>= 4; - temp_al &= 0xF; - seteab(temp_val); - AL = temp_al; - - handled = 1; - break; - - case 0x2a: /* ROR4 r/m */ - do_mod_rm(); - wait_cycs(21, 0); - - temp_val = geteab(); - temp_al = AL; - - AL = temp_val & 0xF; - temp_val = (temp_val >> 4) | ((temp_al & 0xF) << 4); - - seteab(temp_val); - - handled = 1; - break; - - case 0x10: /* TEST1 r8/m8, CL*/ - case 0x11: /* TEST1 r16/m16, CL*/ - case 0x18: /* TEST1 r8/m8, imm3 */ - case 0x19: /* TEST1 r16/m16, imm4 */ - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait_cycs(3, 0); - - bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); - - set_zf_ex(!(cpu_data & (1 << bit))); - cpu_state.flags &= ~(V_FLAG | C_FLAG); - - handled = 1; - break; - - case 0x16: /* NOT1 r8/m8, CL*/ - case 0x17: /* NOT1 r16/m16, CL*/ - case 0x1e: /* NOT1 r8/m8, imm3 */ - case 0x1f: /* NOT1 r16/m16, imm4 */ - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait_cycs(3, 0); - - bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); - - if (bits == 8) - seteab((cpu_data & 0xFF) ^ (1 << bit)); - else - seteaw((cpu_data & 0xFFFF) ^ (1 << bit)); - - handled = 1; - break; - - case 0x14: /* SET1 r8/m8, CL*/ - case 0x15: /* SET1 r16/m16, CL*/ - case 0x1c: /* SET1 r8/m8, imm3 */ - case 0x1d: /* SET1 r16/m16, imm4 */ - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait_cycs(3, 0); - - bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); - - if (bits == 8) - seteab((cpu_data & 0xFF) | (1 << bit)); - else - seteaw((cpu_data & 0xFFFF) | (1 << bit)); - - handled = 1; - break; - - case 0x12: /* CLR1 r8/m8, CL*/ - case 0x13: /* CLR1 r16/m16, CL*/ - case 0x1a: /* CLR1 r8/m8, imm3 */ - case 0x1b: /* CLR1 r16/m16, imm4 */ - bits = 8 << (opcode & 0x1); - do_mod_rm(); - wait_cycs(3, 0); - - bit = (opcode & 0x8) ? (pfq_fetchb()) : (CL); - bit &= ((1 << (3 + (opcode & 0x1))) - 1); - read_ea(0, bits); - - if (bits == 8) - seteab((cpu_data & 0xFF) & ~(1 << bit)); - else - seteaw((cpu_data & 0xFFFF) & ~(1 << bit)); - - handled = 1; - break; - - case 0x20: /* ADD4S */ - odd = !!(CL % 2); - zero = 1; - nibbles_count = CL - odd; - i = 0; - carry = 0; - nibble = 0; - srcseg = ovr_seg ? *ovr_seg : ds; - - wait_cycs(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait_cycs(19, 0); - destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - destbyte = destcmp >> (nibble ? 4 : 0); - srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : ((uint8_t) (destbyte)) + ((uint8_t) (srcbyte)) + ((uint32_t) carry); - carry = 0; - while (nibble_result >= 10) { - nibble_result -= 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); - } - write_mem_b(es + DI + i, destcmp); - } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; - - case 0x22: /* SUB4S */ - odd = !!(CL % 2); - zero = 1; - nibbles_count = CL - odd; - i = 0; - carry = 0; - nibble = 0; - srcseg = ovr_seg ? *ovr_seg : ds; - - wait_cycs(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait_cycs(19, 0); - destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - destbyte = destcmp >> (nibble ? 4 : 0); - srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - nibble_result_s = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t) destbyte - (int8_t) carry) : ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); - carry = 0; - while (nibble_result_s < 0) { - nibble_result_s += 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result_s == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); - } - write_mem_b(es + DI + i, destcmp); - } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; - - case 0x26: /* CMP4S */ - odd = !!(CL % 2); - zero = 1; - nibbles_count = CL - odd; - i = 0; - carry = 0; - nibble = 0; - srcseg = ovr_seg ? *ovr_seg : ds; - - wait_cycs(5, 0); - for (i = 0; i < ((nibbles_count / 2) + odd); i++) { - wait_cycs(19, 0); - destcmp = read_mem_b((es) + DI + i); - for (nibble = 0; nibble < 2; nibble++) { - destbyte = destcmp >> (nibble ? 4 : 0); - srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); - destbyte &= 0xF; - srcbyte &= 0xF; - nibble_result_s = ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); - carry = 0; - while (nibble_result_s < 0) { - nibble_result_s += 10; - carry++; - } - if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) - zero = (nibble_result_s == 0); - destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); - } - } - set_cf(!!carry); - set_zf(!!zero); - handled = 1; - break; - - case 0x31: /* INS reg1, reg2 */ - case 0x39: /* INS reg8, imm4 */ - do_mod_rm(); - wait_cycs(1, 0); - - bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; - bit_offset = getr8(cpu_rm) & 0xF; - byteaddr = (es) + DI; - i = 0; - - if (bit_offset >= 8) { - DI++; - byteaddr++; - bit_offset -= 8; - } - 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)); - bit_offset++; - if (bit_offset == 8) { - DI++; - bit_offset = 0; - } - } - setr8(cpu_rm, bit_offset); - - handled = 1; - break; - - case 0x33: /* EXT reg1, reg2 */ - case 0x3b: /* EXT reg8, imm4 */ - do_mod_rm(); - wait_cycs(1, 0); - - bit_length = ((opcode & 0x8) ? (pfq_fetchb() & 0xF) : (getr8(cpu_reg) & 0xF)) + 1; - bit_offset = getr8(cpu_rm) & 0xF; - byteaddr = (ds) + SI; - i = 0; - - if (bit_offset >= 8) { - SI++; - byteaddr++; - bit_offset -= 8; - } - - AX = 0; - for (i = 0; i < bit_length; i++) { - byteaddr = (ds) + SI; - AX |= (!!(readmemb(byteaddr) & (1 << bit_offset))) << i; - bit_offset++; - if (bit_offset == 8) { - SI++; - bit_offset = 0; - } - } - setr8(cpu_rm, bit_offset); - - handled = 1; - break; - - case 0xFF: /* BRKEM */ - interrupt_brkem(pfq_fetchb()); - handled = 1; - break; - - default: - opcode = orig_opcode; - cpu_state.pc--; - break; - } - } else - handled = 0; - if (handled) - break; access(22, 16); if (opcode == 0x0F) { load_cs(pop()); @@ -3019,28 +2558,21 @@ execx86(int cycs) } #else wait_cycs(7, 0); - check_interrupts(0); + check_interrupts(); #endif break; case 0x9C: /*PUSHF*/ access(33, 16); - if (is_nec) - tempw = (cpu_state.flags & 0x8fd7) | 0x7000; - else - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + tempw = (cpu_state.flags & 0x0fd7) | 0xf000; push(&tempw); break; case 0x9D: { /*POPF*/ uint16_t old_flags = cpu_state.flags; access(25, 16); - if (is_nec && cpu_md_write_disable) - cpu_state.flags = pop() | 0x8002; - else - cpu_state.flags = pop() | 0x0002; + cpu_state.flags = pop() | 0x0002; wait_cycs(1, 0); if ((old_flags ^ cpu_state.flags) & T_FLAG) noint = 1; - sync_to_i8080(); break; } case 0x9E: /*SAHF*/ wait_cycs(1, 0); @@ -3306,15 +2838,10 @@ execx86(int cycs) access(62, 8); set_ip(new_ip); access(45, 8); - if (is_nec && cpu_md_write_disable) - cpu_state.flags = pop() | 0x8002; - else - cpu_state.flags = pop() | 0x0002; + cpu_state.flags = pop() | 0x0002; wait_cycs(5, 0); noint = 2; nmi_enable = 1; - if (is_nec && !(cpu_state.flags & MD_FLAG)) - sync_to_i8080(); break; case 0xD0: @@ -3335,7 +2862,7 @@ execx86(int cycs) cpu_src = CL; wait_cycs((cpu_mod != 3) ? 9 : 6, 0); } - if (is186 && !is_nec) + if (is186) cpu_src &= 0x1F; while (cpu_src != 0) { cpu_dest = cpu_data; @@ -3414,15 +2941,7 @@ execx86(int cycs) case 0xD4: /*AAM*/ wait_cycs(1, 0); -#ifdef NO_VARIANT_ON_NEC - if (is_nec) { - (void) pfq_fetchb(); - cpu_src = 10; - } else - cpu_src = pfq_fetchb(); -#else cpu_src = pfq_fetchb(); -#endif if (x86_div(AL, 0)) { cpu_data = AL; set_pzs(8); @@ -3430,11 +2949,7 @@ execx86(int cycs) break; case 0xD5: /*AAD*/ wait_cycs(1, 0); - if (is_nec) { - (void) pfq_fetchb(); - mul(10, AH); - } else - mul(pfq_fetchb(), AH); + mul(pfq_fetchb(), AH); cpu_dest = AL; cpu_src = cpu_data; add(8); @@ -3443,13 +2958,10 @@ execx86(int cycs) set_pzs(8); break; case 0xD6: /*SALC*/ - if (!is_nec) { - wait_cycs(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait_cycs(1, 0); - break; - } - fallthrough; + 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); @@ -3651,9 +3163,9 @@ execx86(int cycs) pfq_clear(); } wait_cycs(1, 0); - if (irq_pending(is_nec)) { + if (irq_pending()) { wait_cycs(cycles & 1, 0); - check_interrupts(is_nec); + check_interrupts(); } else { repeating = 1; completed = 0; @@ -3699,7 +3211,6 @@ execx86(int cycs) break; case 0x20: /* MUL */ case 0x28: /* IMUL */ - old_flags = cpu_state.flags; wait_cycs(1, 0); mul(get_accum(bits), cpu_data); if (opcode & 1) { @@ -3711,17 +3222,12 @@ execx86(int cycs) AL = (uint8_t) cpu_data; AH = (uint8_t) cpu_dest; set_co_mul(bits, AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff)); - if (!is_nec) - cpu_data = AH; + cpu_data = AH; } set_sf(bits); set_pf(); if (cpu_mod != 3) wait_cycs(1, 0); - /* NOTE: When implementing the V20, care should be taken to not change - the zero flag. */ - if (is_nec) - cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG); break; case 0x30: /* DIV */ case 0x38: /* IDIV */ @@ -3843,7 +3349,7 @@ execx86(int cycs) break; } } -exec_completed: + if (completed) { repeating = 0; ovr_seg = NULL; @@ -3852,7 +3358,7 @@ exec_completed: if (in_lock) clear_lock = 1; clock_end(); - check_interrupts(0); + check_interrupts(); if (noint) noint = 0; diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index dc7f5ac11..7eadb94fa 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -20,6 +20,8 @@ add_library(cpu OBJECT cpu_table.c fpu.c x86.c 808x.c + vx0.c + vx0_biu.c 386.c 386_common.c 386_dynarec.c diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 6e675acc8..e0868861d 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1865,6 +1865,8 @@ cpu_set(void) cpu_exec = exec386_2386; } else if (cpu_s->cpu_type >= CPU_286) cpu_exec = exec386_2386; + else if (is_nec) + cpu_exec = execvx0; else cpu_exec = execx86; mmx_init(); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 865e76ffb..8e74bc78a 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -718,6 +718,7 @@ extern void codegen_reset(void); extern void cpu_set_edx(void); extern int divl(uint32_t val); extern void execx86(int32_t cycs); +extern void execvx0(int32_t cycs); extern void enter_smm(int in_hlt); extern void enter_smm_check(int in_hlt); extern void leave_smm(void); @@ -809,6 +810,8 @@ extern void SF_FPU_reset(void); extern void reset_808x(int hard); extern void interrupt_808x(uint16_t addr); +extern void reset_vx0(int hard); + extern void cpu_register_fast_off_handler(void *timer); extern void cpu_fast_off_advance(void); extern void cpu_fast_off_period_set(uint16_t vla, double period); diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c new file mode 100644 index 000000000..bd1a8da20 --- /dev/null +++ b/src/cpu/vx0.c @@ -0,0 +1,4783 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 808x CPU emulation, mostly ported from reenigne's XTCE, which + * is cycle-accurate. + * + * Authors: Andrew Jenner, + * Miran Grca, + * + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include + +#include "i8080.h" + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86.h" +#include <86box/machine.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/ppi.h> +#include <86box/timer.h> +#include <86box/gdbstub.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include "vx0_biu.h" + +#define do_cycle() wait(1) +#define do_cycle_no_modrm() if (!nx) \ + do_cycle() +#define do_cycle_i() do_cycle() +#define do_cycles(c) wait(c) +#define do_cycles_i(c) do_cycles(c) +#define do_cycle_nx() nx = 1 +#define do_cycle_nx_i() nx = 1 +#define do_cycles_nx(c) nx = 1; \ + if (c > 1) \ + do_cycles(c - 1) +#define do_cycles_nx_i(c) nx = 1; \ + if (c > 1) \ + do_cycles(c - 1) +#define addr_mode_match() cpu_mod == 3 +#define math_op(o) cpu_alu_op = o; \ + alu_op(bits) + +/* Various things needed for 8087. */ +#define OP_TABLE(name) ops_##name + +#define CPU_BLOCK_END() +#define SEG_CHECK_READ(seg) +#define SEG_CHECK_WRITE(seg) +#define CHECK_READ(a, b, c) +#define CHECK_WRITE(a, b, c) +#define UN_USED(x) (void) (x) +#define fetch_ea_16(val) +#define fetch_ea_32(val) +#define PREFETCH_RUN(a, b, c, d, e, f, g, h) + +#define CYCLES(val) \ + { \ + do_cycles(val); \ + } + +#define CLOCK_CYCLES_ALWAYS(val) \ + { \ + do_cycles(val); \ + } + +#define CLOCK_CYCLES_FPU(val) \ + { \ + do_cycles(val); \ + } + +# define CLOCK_CYCLES(val) \ + { \ + if (fpu_cycles > 0) { \ + fpu_cycles -= (val); \ + if (fpu_cycles < 0) { \ + do_cycles(val); \ + } \ + } else { \ + do_cycles(val); \ + } \ + } + +#define CONCURRENCY_CYCLES(c) fpu_cycles = (c) + +#define OP_MRM 1 +#define OP_EA 2 +#define OP_MEA (OP_MRM | OP_EA) +#define OP_GRP 4 +#define OP_DELAY 8 +#define OP_PRE 16 + +#define readmemb readmemb_vx0 +#define readmemw readmemw_vx0 +#define readmem readmem_vx0 +#define readmeml readmeml_vx0 +#define readmemq readmemq_vx0 +#define writememb writememb_vx0 +#define writememw writememw_vx0 +#define writemem writemem_vx0 +#define writememl writememl_vx0 +#define writememq writememq_vx0 + +typedef int (*OpFn)(uint32_t fetchdat); + +static void farret(int far); + +const uint8_t opf[256] = { OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 00 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 08 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 10 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 18 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 20 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 28 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 30 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 58 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ + OP_GRP, OP_GRP, OP_GRP, OP_GRP, OP_MEA, OP_MEA, OP_MEA, OP_MEA, /* 80 */ + OP_MRM, OP_MRM, OP_MEA, OP_MEA, OP_MRM, OP_MRM, OP_MEA, OP_MRM, /* 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B8 */ + 0, 0, 0, 0, OP_MEA, OP_MEA, OP_MRM, OP_MRM, /* C0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* C8 */ + OP_GRP, OP_GRP, OP_GRP, OP_GRP, 0, 0, 0, 0, /* D0 */ + OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, /* D8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E8 */ + OP_PRE, OP_PRE, OP_PRE, OP_PRE, 0, 0, OP_GRP, OP_GRP, /* F0 */ + 0, 0, 0, 0, 0, 0, OP_GRP, OP_GRP }; /* F8 */ + +const uint8_t opf_nec[256] = { OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 00 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, OP_PRE, /* 08 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 10 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, 0, 0, /* 18 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 20 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 28 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 30 */ + OP_MEA, OP_MEA, OP_MEA, OP_MEA, 0, 0, OP_PRE, 0, /* 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 58 */ + 0, 0, OP_MRM, OP_MRM, OP_PRE, OP_PRE, OP_MRM, OP_MRM, /* 60 */ + 0, OP_MRM, 0, OP_MEA, 0, 0, 0, 0, /* 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ + OP_GRP, OP_GRP, OP_GRP, OP_GRP, OP_MEA, OP_MEA, OP_MEA, OP_MEA, /* 80 */ + OP_MRM, OP_MRM, OP_MEA, OP_MEA, OP_MRM, OP_MRM, OP_MEA, OP_MRM, /* 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B8 */ + OP_GRP, OP_GRP, 0, 0, OP_MEA, OP_MEA, OP_MRM, OP_MRM, /* C0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* C8 */ + OP_GRP, OP_GRP, OP_GRP, OP_GRP, 0, 0, 0, 0, /* D0 */ + OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, /* D8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E8 */ + OP_PRE, OP_PRE, OP_PRE, OP_PRE, 0, 0, OP_GRP, OP_GRP, /* F0 */ + 0, 0, 0, 0, 0, 0, OP_GRP, OP_GRP }; /* F8 */ + +const uint8_t opf_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, /* 00 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 08 */ + OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, /* 10 */ + OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, OP_MRM, /* 18 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */ + OP_MRM, 0, OP_MRM, 0, 0, 0, 0, 0, /* 28 */ + OP_MRM, 0, OP_MRM, 0, 0, 0, 0, 0, /* 30 */ + OP_MRM, 0, OP_MRM, 0, 0, 0, 0, 0, /* 38 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 40 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 48 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 50 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 58 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 68 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 88 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* 98 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* A8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* B8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* C0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* C8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* D0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* D8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E0 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* E8 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* F0 */ + 0, 0, 0, 0, 0, 0, 0, 0 }; /* F8 */ + +uint8_t use_custom_nmi_vector = 0; + +uint32_t custom_nmi_vector = 0x00000000; + +/* Is the CPU 8088 or 8086. */ +int is8086 = 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; +static int in_0f = 0; +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]; + +static x86seg * _opseg[4]; + +enum { + MODRM_ADDR_BX_SI = 0x00, + MODRM_ADDR_BX_DI, + MODRM_ADDR_BP_SI, + MODRM_ADDR_BP_DI, + MODRM_ADDR_SI, + MODRM_ADDR_DI, + MODRM_ADDR_DISP16, + MODRM_ADDR_BX, + + MODRM_ADDR_BX_SI_DISP8 = 0x40, + MODRM_ADDR_BX_DI_DISP8, + MODRM_ADDR_BP_SI_DISP8, + MODRM_ADDR_BP_DI_DISP8, + MODRM_ADDR_SI_DISP8, + MODRM_ADDR_DI_DISP8, + MODRM_ADDR_BP_DISP8, + MODRM_ADDR_BX_DISP8, + + MODRM_ADDR_BX_SI_DISP16 = 0x80, + MODRM_ADDR_BX_DI_DISP16, + MODRM_ADDR_BP_SI_DISP16, + MODRM_ADDR_BP_DI_DISP16, + MODRM_ADDR_SI_DISP16, + MODRM_ADDR_DI_DISP16, + MODRM_ADDR_BP_DISP16, + MODRM_ADDR_BX_DISP16 +}; + +static uint8_t modrm_cycs_pre[256] = { [MODRM_ADDR_BX_SI] = 4, + [MODRM_ADDR_BX_DI] = 5, + [MODRM_ADDR_BP_SI] = 5, + [MODRM_ADDR_BP_DI] = 4, + [MODRM_ADDR_SI] = 2, + [MODRM_ADDR_DI] = 2, + [MODRM_ADDR_DISP16] = 0, + [MODRM_ADDR_BX] = 2, + [0x08 ... 0x3f] = 0, + [MODRM_ADDR_BX_SI_DISP8] = 4, + [MODRM_ADDR_BX_DI_DISP8] = 5, + [MODRM_ADDR_BP_SI_DISP8] = 5, + [MODRM_ADDR_BP_DI_DISP8] = 4, + [MODRM_ADDR_SI_DISP8] = 2, + [MODRM_ADDR_DI_DISP8] = 2, + [MODRM_ADDR_BP_DISP8] = 2, + [MODRM_ADDR_BX_DISP8] = 2, + [0x48 ... 0x7f] = 0, + [MODRM_ADDR_BX_SI_DISP16] = 4, + [MODRM_ADDR_BX_DI_DISP16] = 5, + [MODRM_ADDR_BP_SI_DISP16] = 5, + [MODRM_ADDR_BP_DI_DISP16] = 4, + [MODRM_ADDR_SI_DISP16] = 2, + [MODRM_ADDR_DI_DISP16] = 2, + [MODRM_ADDR_BP_DISP16] = 2, + [MODRM_ADDR_BX_DISP16] = 2, + [0x88 ... 0xff] = 0 }; + +static uint8_t modrm_cycs_post[256] = { [MODRM_ADDR_BX_SI] = 0, + [MODRM_ADDR_BX_DI] = 0, + [MODRM_ADDR_BP_SI] = 0, + [MODRM_ADDR_BP_DI] = 0, + [MODRM_ADDR_SI] = 0, + [MODRM_ADDR_DI] = 0, + [MODRM_ADDR_DISP16] = 1, + [MODRM_ADDR_BX] = 0, + [0x08 ... 0x3f] = 0, + [MODRM_ADDR_BX_SI_DISP8] = 3, + [MODRM_ADDR_BX_DI_DISP8] = 3, + [MODRM_ADDR_BP_SI_DISP8] = 3, + [MODRM_ADDR_BP_DI_DISP8] = 3, + [MODRM_ADDR_SI_DISP8] = 3, + [MODRM_ADDR_DI_DISP8] = 3, + [MODRM_ADDR_BP_DISP8] = 3, + [MODRM_ADDR_BX_DISP8] = 3, + [0x48 ... 0x7f] = 0, + [MODRM_ADDR_BX_SI_DISP16] = 2, + [MODRM_ADDR_BX_DI_DISP16] = 2, + [MODRM_ADDR_BP_SI_DISP16] = 2, + [MODRM_ADDR_BP_DI_DISP16] = 2, + [MODRM_ADDR_SI_DISP16] = 2, + [MODRM_ADDR_DI_DISP16] = 2, + [MODRM_ADDR_BP_DISP16] = 2, + [MODRM_ADDR_BX_DISP16] = 2, + [0x88 ... 0xff] = 0 }; + +#ifdef ENABLE_808X_LOG +#if 0 +void dumpregs(int); +#endif +int x808x_do_log = ENABLE_808X_LOG; + +static void +x808x_log(const char *fmt, ...) +{ + va_list ap; + + if (x808x_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define x808x_log(fmt, ...) +#endif + +static i8080 emulated_processor; +static bool cpu_md_write_disable = 1; + +static void +set_if(int cond) +{ + cpu_state.flags = (cpu_state.flags & ~I_FLAG) | (cond ? I_FLAG : 0); +} + +void +sync_from_i8080(void) +{ + AL = emulated_processor.a; + BH = emulated_processor.h; + BL = emulated_processor.l; + CH = emulated_processor.b; + CL = emulated_processor.c; + DH = emulated_processor.d; + DL = emulated_processor.e; + BP = emulated_processor.sp; + + cpu_state.pc = emulated_processor.pc; + cpu_state.flags &= 0xFF00; + cpu_state.flags |= emulated_processor.sf << 7; + cpu_state.flags |= emulated_processor.zf << 6; + cpu_state.flags |= emulated_processor.hf << 4; + cpu_state.flags |= emulated_processor.pf << 2; + cpu_state.flags |= 1 << 1; + cpu_state.flags |= emulated_processor.cf << 0; + set_if(emulated_processor.iff); +} + +void +sync_to_i8080(void) +{ + if (!is_nec) + return; + emulated_processor.a = AL; + emulated_processor.h = BH; + emulated_processor.l = BL; + emulated_processor.b = CH; + emulated_processor.c = CL; + emulated_processor.d = DH; + emulated_processor.e = DL; + emulated_processor.sp = BP; + emulated_processor.pc = cpu_state.pc; + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); + + emulated_processor.sf = (cpu_state.flags >> 7) & 1; + emulated_processor.zf = (cpu_state.flags >> 6) & 1; + emulated_processor.hf = (cpu_state.flags >> 4) & 1; + emulated_processor.pf = (cpu_state.flags >> 2) & 1; + emulated_processor.cf = (cpu_state.flags >> 0) & 1; + + emulated_processor.interrupt_delay = noint; +} + +uint16_t +get_last_addr(void) +{ + return last_addr; +} + +static void +set_ip(uint16_t new_ip) +{ + cpu_state.pc = new_ip; +} + +static void +startx86(void) +{ + /* Reset takes 6 cycles before first fetch. */ + do_cycle(); + biu_suspend_fetch(); + do_cycles_i(2); + biu_queue_flush(); + do_cycles_i(3); +} + +static void +load_cs(uint16_t seg) +{ + cpu_state.seg_cs.base = seg << 4; + cpu_state.seg_cs.seg = seg & 0xffff; +} + +static void +load_seg(uint16_t seg, x86seg *s) +{ + s->base = seg << 4; + s->seg = seg & 0xffff; +} + +static uint8_t +fetch_i8080_opcode(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(cs, addr); +} + +static uint8_t +fetch_i8080_data(UNUSED(void* priv), uint16_t addr) +{ + return readmemb(ds, addr); +} + +static void +put_i8080_data(UNUSED(void* priv), uint16_t addr, uint8_t val) +{ + writememb(ds, addr, val); +} + +static +uint8_t i8080_port_in(UNUSED(void* priv), uint8_t port) +{ + cpu_data = port; + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(8, 0, cpu_state.eaaddr); + return AL; +} + +static +void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) +{ + cpu_data = DX; + AL = val; + do_cycle_i(); + + cpu_state.eaaddr = cpu_data; + cpu_data = AL; + cpu_io_vx0(8, 1, port); +} + +void +reset_vx0(int hard) +{ + halted = 0; + in_hlt = 0; + in_0f = 0; + in_rep = 0; + in_lock = 0; + completed = 1; + repeating = 0; + clear_lock = 0; + ovr_seg = NULL; + + if (hard) { + opseg[0] = &es; + opseg[1] = &cs; + opseg[2] = &ss; + opseg[3] = &ds; + _opseg[0] = &cpu_state.seg_es; + _opseg[1] = &cpu_state.seg_cs; + _opseg[2] = &cpu_state.seg_ss; + _opseg[3] = &cpu_state.seg_ds; + } + + load_cs(0xFFFF); + cpu_state.pc = 0; + + if (is_nec) + cpu_state.flags |= MD_FLAG; + rammask = 0xfffff; + + cpu_alu_op = 0; + + nx = 0; + + use_custom_nmi_vector = 0x00; + custom_nmi_vector = 0x00000000; + + biu_reset(); + + started = 1; + modrm_loaded = 0; + + cpu_md_write_disable = 1; + i8080_init(&emulated_processor); + emulated_processor.write_byte = put_i8080_data; + emulated_processor.read_byte = fetch_i8080_data; + emulated_processor.read_byte_seg = fetch_i8080_opcode; + emulated_processor.port_in = i8080_port_in; + emulated_processor.port_out = i8080_port_out; +} + +static uint16_t +get_accum(int bits) +{ + return (bits == 16) ? AX : AL; +} + +static void +set_accum(int bits, uint16_t val) +{ + if (bits == 16) + AX = val; + else + AL = val; +} + +static uint16_t +sign_extend(uint8_t data) +{ + return data + (data < 0x80 ? 0 : 0xff00); +} + +#undef getr8 +#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) + +#undef setr8 +#define setr8(r, v) \ + if (r & 4) \ + cpu_state.regs[r & 3].b.h = v; \ + else \ + cpu_state.regs[r & 3].b.l = v; + +/* Reads a byte from the effective address. */ +static uint8_t +geteab(void) +{ + uint8_t ret; + + if (cpu_mod == 3) + ret = (getr8(cpu_rm)); + else + ret = readmemb(easeg, cpu_state.eaaddr); + + return ret; +} + +/* Reads a word from the effective address. */ +static uint16_t +geteaw(void) +{ + uint16_t ret; + + if (cpu_mod == 3) + ret = cpu_state.regs[cpu_rm].w; + else + ret = readmemw(easeg, cpu_state.eaaddr); + + return ret; +} + +/* Neede for 8087 - memory only. */ +static uint32_t +geteal(void) +{ + uint32_t ret; + + if (cpu_mod == 3) { + fatal("808x register geteal()\n"); + ret = 0xffffffff; + } else + ret = readmeml(easeg, cpu_state.eaaddr); + + return ret; +} + +/* Neede for 8087 - memory only. */ +static uint64_t +geteaq(void) +{ + uint32_t ret; + + if (cpu_mod == 3) { + fatal("808x register geteaq()\n"); + ret = 0xffffffff; + } else + ret = readmemq(easeg, cpu_state.eaaddr); + + return ret; +} + +static void +read_ea(int memory_only, int bits) +{ + if (cpu_mod != 3) { + if (bits == 16) + cpu_data = readmemw(easeg, cpu_state.eaaddr); + else + cpu_data = readmemb(easeg, cpu_state.eaaddr); + return; + } + if (!memory_only) { + if (bits == 8) { + cpu_data = getr8(cpu_rm); + } else + cpu_data = cpu_state.regs[cpu_rm].w; + } +} + +static void +read_ea_8to16(void) +{ + cpu_data = cpu_state.regs[cpu_rm & 3].w; +} + +static void +read_ea2(int bits) +{ + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + if (bits == 16) + cpu_data = readmemw(easeg, cpu_state.eaaddr); + else + cpu_data = readmemb(easeg, cpu_state.eaaddr); +} + +/* Writes a byte to the effective address. */ +static void +seteab(uint8_t val) +{ + if (cpu_mod == 3) { + setr8(cpu_rm, val); + } else { + do_cycle(); + writememb(easeg, cpu_state.eaaddr, val); + } +} + +/* Writes a word to the effective address. */ +static void +seteaw(uint16_t val) +{ + if (cpu_mod == 3) + cpu_state.regs[cpu_rm].w = val; + else { + do_cycle(); + writememw(easeg, cpu_state.eaaddr, val); + } +} + +static void +seteal(uint32_t val) +{ + if (cpu_mod == 3) { + fatal("808x register seteal()\n"); + return; + } else + writememl(easeg, cpu_state.eaaddr, val); +} + +static void +seteaq(uint64_t val) +{ + if (cpu_mod == 3) { + fatal("808x register seteaq()\n"); + return; + } else + writememq(easeg, cpu_state.eaaddr, val); +} + +/* Leave out the 686 stuff as it's not needed and + complicates compiling. */ +#define FPU_8087 +#define FPU_NEC +#define tempc tempc_fpu +#include "x87_sf.h" +#include "x87.h" +#include "x87_ops.h" +#undef tempc +#undef FPU_8087 + +static void +set_cf(int cond) +{ + cpu_state.flags = (cpu_state.flags & ~C_FLAG) | (cond ? C_FLAG : 0); +} + +static void +set_df(int cond) +{ + cpu_state.flags = (cpu_state.flags & ~D_FLAG) | (cond ? D_FLAG : 0); +} + +static void +set_of(int of) +{ + cpu_state.flags = (cpu_state.flags & ~0x800) | (of ? 0x800 : 0); +} + +static int +top_bit(uint16_t w, int bits) +{ + return (w & (1 << (bits - 1))); +} + +static void +set_of_add(int bits) +{ + set_of(top_bit((cpu_data ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); +} + +static void +set_of_sub(int bits) +{ + set_of(top_bit((cpu_dest ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); +} + +static void +set_af(int af) +{ + cpu_state.flags = (cpu_state.flags & ~0x10) | (af ? 0x10 : 0); +} + +static void +do_af(void) +{ + set_af(((cpu_data ^ cpu_src ^ cpu_dest) & 0x10) != 0); +} + +static void +set_sf(int bits) +{ + cpu_state.flags = (cpu_state.flags & ~0x80) | (top_bit(cpu_data, bits) ? 0x80 : 0); +} + +static void +set_pf(void) +{ + cpu_state.flags = (cpu_state.flags & ~4) | (!__builtin_parity(cpu_data & 0xFF) << 2); +} + +static void +set_of_rotate(int bits) +{ + set_of(top_bit(cpu_data ^ cpu_dest, bits)); +} + +static void +set_zf_ex(int zf) +{ + cpu_state.flags = (cpu_state.flags & ~0x40) | (zf ? 0x40 : 0); +} + +static void +set_zf(int bits) +{ + int size_mask = (1 << bits) - 1; + + set_zf_ex((cpu_data & size_mask) == 0); +} + +static void +set_pzs(int bits) +{ + set_pf(); + set_zf(bits); + set_sf(bits); +} + +static void +set_apzs(int bits) +{ + set_pzs(bits); + do_af(); +} + +static void +add(int bits) +{ + int size_mask = (1 << bits) - 1; + + cpu_data = cpu_dest + cpu_src; + set_apzs(bits); + set_of_add(bits); + + /* Anything - FF with carry on is basically anything + 0x100: value stays + unchanged but carry goes on. */ + if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + cpu_state.flags |= C_FLAG; + else + set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); +} + +static void +sub(int bits) +{ + int size_mask = (1 << bits) - 1; + + cpu_data = cpu_dest - cpu_src; + set_apzs(bits); + set_of_sub(bits); + + /* Anything - FF with carry on is basically anything - 0x100: value stays + unchanged but carry goes on. */ + if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) + cpu_state.flags |= C_FLAG; + else + set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); +} + +static void +bitwise(int bits, uint16_t data) +{ + cpu_data = data; + cpu_state.flags &= ~(C_FLAG | A_FLAG | V_FLAG); + set_pzs(bits); +} + +static void +test(int bits, uint16_t dest, uint16_t src) +{ + cpu_dest = dest; + cpu_src = src; + bitwise(bits, (cpu_dest & cpu_src)); +} + +static void +alu_op(int bits) +{ + switch (cpu_alu_op) { + case 1: + bitwise(bits, (cpu_dest | cpu_src)); + break; + case 2: + if (cpu_state.flags & C_FLAG) + cpu_src++; + fallthrough; + case 0: + add(bits); + break; + case 3: + if (cpu_state.flags & C_FLAG) + cpu_src++; + fallthrough; + case 5: + case 7: + sub(bits); + break; + case 4: + test(bits, cpu_dest, cpu_src); + break; + case 6: + bitwise(bits, (cpu_dest ^ cpu_src)); + break; + + default: + break; + } +} + +static void +mul(uint16_t a, uint16_t b) +{ + int negate = 0; + int bit_count = 8; + int carry; + uint16_t high_bit = 0x80; + uint16_t size_mask; + uint16_t c; + uint16_t r; + + size_mask = (1 << bit_count) - 1; + + if (opcode != 0xd5) { + if (opcode & 1) { + bit_count = 16; + high_bit = 0x8000; + } else + do_cycles(8); + + size_mask = (1 << bit_count) - 1; + + if ((rmdat & 0x38) == 0x28) { + if (!top_bit(a, bit_count)) { + if (top_bit(b, bit_count)) { + do_cycle(); + if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) + do_cycle(); + b = ~b + 1; + negate = 1; + } + } else { + do_cycle(); + a = ~a + 1; + negate = 1; + if (top_bit(b, bit_count)) { + b = ~b + 1; + negate = 0; + } else + do_cycles(4); + } + do_cycles(10); + } + do_cycles(3); + } + + c = 0; + a &= size_mask; + carry = (a & 1) != 0; + a >>= 1; + for (int i = 0; i < bit_count; ++i) { + do_cycles(7); + if (carry) { + cpu_src = c; + cpu_dest = b; + add(bit_count); + c = cpu_data & size_mask; + do_cycles(1); + carry = !!(cpu_state.flags & C_FLAG); + } + r = (c >> 1) + (carry ? high_bit : 0); + carry = (c & 1) != 0; + c = r; + r = (a >> 1) + (carry ? high_bit : 0); + carry = (a & 1) != 0; + a = r; + } + if (negate) { + c = ~c; + a = (~a + 1) & size_mask; + if (a == 0) + ++c; + do_cycles(9); + } + cpu_data = a; + cpu_dest = c; + + set_sf(bit_count); + set_pf(); + set_af(0); +} + +static void +set_co_mul(UNUSED(int bits), int carry) +{ + set_cf(carry); + set_of(carry); + set_zf_ex(!carry); + if (!carry) + do_cycle(); +} + +/* Pushes a word to the stack. */ +static void +push(uint16_t *val) +{ + if ((is186 && !is_nec) && (SP == 1)) { + writememw(ss - 1, 0, *val); + SP = cpu_state.eaaddr = 0xFFFF; + return; + } + SP -= 2; + cpu_state.eaaddr = (SP & 0xffff); + writememw(ss, cpu_state.eaaddr, *val); +} + +/* Pops a word from the stack. */ +static uint16_t +pop(void) +{ + cpu_state.eaaddr = (SP & 0xffff); + SP += 2; + return readmemw(ss, cpu_state.eaaddr); +} + +static void +nearcall(uint16_t new_ip) +{ + uint16_t ret_ip = cpu_state.pc & 0xffff; + + do_cycle_i(); + set_ip(new_ip); + biu_queue_flush(); + do_cycles_i(3); + push(&ret_ip); +} + +static void +farcall2(uint16_t new_cs, uint16_t new_ip) +{ + do_cycles_i(3); + push(&CS); + load_cs(new_cs); + do_cycles_i(2); + nearcall(new_ip); +} + +/* The INTR microcode routine. */ +static void +intr_routine(uint16_t intr, int skip_first) +{ + uint16_t vector = intr * 4; + uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + uint16_t new_cs; + uint16_t new_ip; + + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + x808x_log("CALLN/INT#/NMI#\n"); + } + + if (!skip_first) + do_cycle_i(); + do_cycles_i(2); + + cpu_state.eaaddr = vector & 0xffff; + new_ip = readmemw(0, cpu_state.eaaddr); + do_cycle_i(); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + new_cs = readmemw(0, cpu_state.eaaddr); + + biu_suspend_fetch(); + do_cycles_i(2); + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; + do_cycle_i(); + + farcall2(new_cs, new_ip); +} + +/* Was div(), renamed to avoid conflicts with stdlib div(). */ +static int +x86_div(uint16_t l, uint16_t h) +{ + int bit_count = 8; + int negative = 0; + int dividend_negative = 0; + int size_mask; + int carry; + uint16_t r; + + if (opcode & 1) { + l = AX; + h = DX; + bit_count = 16; + } + + size_mask = (1 << bit_count) - 1; + + if (opcode != 0xd4) { + if ((rmdat & 0x38) == 0x38) { + if (top_bit(h, bit_count)) { + h = ~h; + l = (~l + 1) & size_mask; + if (l == 0) + ++h; + h &= size_mask; + negative = 1; + dividend_negative = 1; + do_cycles(4); + } + if (top_bit(cpu_src, bit_count)) { + cpu_src = ~cpu_src + 1; + negative = !negative; + } else + do_cycle(); + do_cycles(9); + } + do_cycles(3); + } + do_cycles(8); + cpu_src &= size_mask; + if (h >= cpu_src) { + if (opcode != 0xd4) + do_cycle(); + intr_routine(0, 0); + return 0; + } + if (opcode != 0xd4) + do_cycle(); + do_cycles(2); + carry = 1; + for (int b = 0; b < bit_count; ++b) { + r = (l << 1) + (carry ? 1 : 0); + carry = top_bit(l, bit_count); + l = r; + r = (h << 1) + (carry ? 1 : 0); + carry = top_bit(h, bit_count); + h = r; + do_cycles(8); + if (carry) { + carry = 0; + h -= cpu_src; + if (b == bit_count - 1) + do_cycles(2); + } else { + carry = cpu_src > h; + if (!carry) { + h -= cpu_src; + do_cycle(); + if (b == bit_count - 1) + do_cycles(2); + } + } + } + l = ~((l << 1) + (carry ? 1 : 0)); + if (opcode != 0xd4 && (rmdat & 0x38) == 0x38) { + do_cycles(4); + if (top_bit(l, bit_count)) { + if (cpu_mod == 3) + do_cycle(); + intr_routine(0, 0); + return 0; + } + do_cycles(7); + if (negative) + l = ~l + 1; + if (dividend_negative) + h = ~h + 1; + } + if (opcode == 0xd4) { + AL = h & 0xff; + AH = l & 0xff; + } else { + AH = h & 0xff; + AL = l & 0xff; + if (opcode & 1) { + DX = h; + AX = l; + } + } + return 1; +} + +static uint16_t +string_increment(int bits) +{ + int d = bits >> 3; + if (cpu_state.flags & D_FLAG) + cpu_state.eaaddr -= d; + else + cpu_state.eaaddr += d; + cpu_state.eaaddr &= 0xffff; + return cpu_state.eaaddr; +} + +static void +lods(int bits) +{ + cpu_state.eaaddr = SI; + 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); + 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) +{ + cpu_state.eaaddr = DI; + if (bits == 16) + writememw(es, cpu_state.eaaddr, cpu_data); + else + writememb(es, cpu_state.eaaddr, (uint8_t) (cpu_data & 0xff)); + DI = string_increment(bits); +} + +static uint16_t +get_ea(void) +{ + if (opcode & 1) + return geteaw(); + else + return (uint16_t) geteab(); +} + +static uint16_t +get_reg(uint8_t reg) +{ + if (opcode & 1) + return cpu_state.regs[reg].w; + else + return (uint16_t) getr8(reg); +} + +static void +set_ea(uint16_t val) +{ + if (opcode & 1) + seteaw(val); + else + seteab((uint8_t) (val & 0xff)); +} + +static void +set_reg(uint8_t reg, uint16_t val) +{ + if (opcode & 1) + cpu_state.regs[reg].w = val; + else + setr8(reg, (uint8_t) (val & 0xff)); +} + +static void +cpu_data_opff_rm(void) +{ + if (!(opcode & 1)) { + if (cpu_mod != 3) + cpu_data |= 0xff00; + else + cpu_data = cpu_state.regs[cpu_rm].w; + } +} + +static void +farcall(uint16_t new_cs, uint16_t new_ip, int jump) +{ + if (jump) + do_cycle_i(); + biu_suspend_fetch(); + do_cycles_i(2); + push(&CS); + load_cs(new_cs); + do_cycles_i(2); + nearcall(new_ip); +} + +/* Calls an interrupt. */ +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; + + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + x808x_log("CALLN/INT#/NMI#\n"); + } + + do_cycles_i(3); + cpu_state.eaaddr = vector & 0xffff; + new_ip = readmemw(0, cpu_state.eaaddr); + do_cycle_i(); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + new_cs = readmemw(0, cpu_state.eaaddr); + + biu_suspend_fetch(); + do_cycles_i(2); + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; + + /* FARCALL2 */ + do_cycles_i(4); + push(&CS); + load_cs(new_cs); + do_cycle_i(); + + /* NEARCALL */ + old_ip = cpu_state.pc & 0xffff; + do_cycles_i(2); + set_ip(new_ip); + biu_queue_flush(); + do_cycles_i(3); + push(&old_ip); +} + +static void +int3(void) +{ + do_cycles_i(4); + intr_routine(3, 0); +} + +/* Ditto, but for breaking into emulation mode. */ +static void +interrupt_brkem(uint16_t addr) +{ + uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + uint16_t new_cs; + uint16_t new_ip; + uint16_t old_ip; + + do_cycles_i(3); + cpu_state.eaaddr = addr << 2; + new_ip = readmemw(0, cpu_state.eaaddr); + do_cycle_i(); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + new_cs = readmemw(0, cpu_state.eaaddr); + + biu_suspend_fetch(); + do_cycles_i(2); + push(&tempf); + cpu_state.flags &= ~(MD_FLAG); + cpu_md_write_disable = 0; + + /* FARCALL2 */ + do_cycles_i(4); + push(&CS); + load_cs(new_cs); + do_cycle_i(); + + /* NEARCALL */ + old_ip = cpu_state.pc & 0xffff; + do_cycles_i(2); + set_ip(new_ip); + biu_queue_flush(); + do_cycles_i(3); + push(&old_ip); + + sync_to_i8080(); + x808x_log("BRKEM mode\n"); +} + +void +retem_i8080(void) +{ + sync_from_i8080(); + + do_cycle_i(); + farret(1); + /* pop_flags() */ + cpu_state.flags = pop(); + do_cycle_i(); + + noint = 1; + nmi_enable = 1; + + emulated_processor.iff = !!(cpu_state.flags & I_FLAG); + + cpu_md_write_disable = 1; + + retem = 1; + + x808x_log("RETEM mode\n"); +} + +void +interrupt_808x(uint16_t addr) +{ + biu_suspend_fetch(); + do_cycles_i(2); + + intr_routine(addr, 0); +} + +static void +custom_nmi(void) +{ + uint16_t tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); + uint16_t new_cs; + uint16_t new_ip; + + if (!(cpu_state.flags & MD_FLAG) && is_nec) { + sync_from_i8080(); + x808x_log("CALLN/INT#/NMI#\n"); + } + + do_cycle_i(); + do_cycles_i(2); + + cpu_state.eaaddr = 0x0002; + (void) readmemw(0, cpu_state.eaaddr); + new_ip = custom_nmi_vector & 0xffff; + do_cycle_i(); + cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; + (void) readmemw(0, cpu_state.eaaddr); + new_cs = custom_nmi_vector >> 16; + + biu_suspend_fetch(); + do_cycles_i(2); + push(&tempf); + cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; + do_cycle_i(); + + farcall2(new_cs, new_ip); +} + +static int +irq_pending(void) +{ + uint8_t temp; + + temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || + ((in_hlt || (cpu_state.flags & I_FLAG)) && pic.int_pending && !noint); + + return temp; +} + +static int +bus_pic_ack(void) +{ + int old_in_lock = in_lock; + + in_lock = 1; + bus_request_type = BUS_PIC; + biu_begin_eu(); + biu_wait_for_read_finish(); + in_lock = old_in_lock; + return pic_data; +} + +static void +hw_int(uint16_t vector) +{ + biu_suspend_fetch(); + do_cycles_i(2); + + intr_routine(vector, 0); +} + +static void +int1(void) +{ + do_cycles_i(2); + intr_routine(1, 1); +} + +static void +int2(void) +{ + do_cycles_i(2); + intr_routine(2, 1); +} + +static void +check_interrupts(void) +{ + int temp; + + if (irq_pending()) { + if ((cpu_state.flags & T_FLAG) && !noint) { + int1(); + return; + } + if (nmi && nmi_enable && nmi_mask) { + nmi_enable = 0; + if (use_custom_nmi_vector) { + do_cycles(2); + custom_nmi(); + } else + int2(); + return; + } + if ((in_hlt || (cpu_state.flags & I_FLAG)) && pic.int_pending && !noint) { + repeating = 0; + completed = 1; + ovr_seg = NULL; + do_cycles(4); + /* ACK to PIC */ + biu_begin_eu(); + temp = bus_pic_ack(); + do_cycle(); + /* ACK to PIC */ + temp = bus_pic_ack(); + in_lock = 0; + clear_lock = 0; + /* Here is where temp should be filled, but we cheat. */ + opcode = 0x00; + hw_int(temp); + } + } +} + +/* The FARRET microcode routine. */ +static void +farret(int far) +{ + uint8_t far2 = !!(opcode & 0x08); + + do_cycle_i(); + set_ip(pop()); + biu_suspend_fetch(); + do_cycles_i(2); + + if ((!!far) != far2) + fatal("Far call distance mismatch (%i = %i)\n", !!far, far2); + + if (far) { + do_cycle_i(); + load_cs(pop()); + + biu_queue_flush(); + do_cycles_i(2); + } else { + biu_queue_flush(); + do_cycles_i(2); + } + + do_cycles_i(2); +} + +static void +iret_routine(void) +{ + do_cycle_i(); + farret(1); + /* pop_flags() */ + if (is_nec && cpu_md_write_disable) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; + do_cycle_i(); + noint = 1; + nmi_enable = 1; +} + +static void +rep_end(void) +{ + repeating = 0; + in_rep = 0; + completed = 1; +} + +static int +rep_start(void) +{ + if (!repeating) { + if (in_rep != 0) { + if (CX == 0) { + do_cycles_i(is_nec ? 1 : 4); + rep_end(); + return 0; + } else + do_cycles_i(is_nec ? 1 : 7); + } + } + + completed = 1; + return 1; +} + +static void +rep_interrupt(void) +{ + biu_suspend_fetch(); + do_cycles_i(4); + biu_queue_flush(); + + if (is_nec && (ovr_seg != NULL)) + set_ip((cpu_state.pc - 3) & 0xffff); + else + set_ip((cpu_state.pc - 2) & 0xffff); + + rep_end(); +} + +static void +sign_extend_al(void) +{ + if ((AL & 0x80) != 0) + AH = 0xff; + else + AH = 0x00; +} + +static void +sign_extend_ax(void) +{ + do_cycles(3); + if ((AX & 0x8000) == 0) + DX = 0x0000; + else { + do_cycle(); + DX = 0xffff; + } +} + +static void +reljmp(uint16_t new_ip, int jump) +{ + if (!is_nec && jump) + do_cycle_i(); + + biu_suspend_fetch(); + if (!is_nec) + do_cycles_i(3); + set_ip(new_ip); + biu_queue_flush(); + do_cycle_i(); +} + +static void +daa(void) +{ + uint16_t old_cf = cpu_state.flags & C_FLAG; + uint16_t old_af = cpu_state.flags & A_FLAG; + uint8_t old_al = AL; + uint8_t al_check; + + cpu_state.flags &= ~C_FLAG; + + al_check = (old_af ? 0x9f : 0x99); + + cpu_state.flags &= ~V_FLAG; + if (old_cf) { + if ((AL >= 0x1a) && (AL <= 0x7f)) + cpu_state.flags |= V_FLAG; + } else if ((AL >= 0x7a) && (AL <= 0x7f)) + cpu_state.flags |= V_FLAG; + + if (((AL & 0x0f) > 9) || (cpu_state.flags & A_FLAG)) { + AL += 6; + cpu_state.flags |= A_FLAG; + } else + cpu_state.flags &= ~A_FLAG; + + if ((old_al > al_check) || old_cf) { + AL += 0x60; + cpu_state.flags |= C_FLAG; + } else + cpu_state.flags &= ~C_FLAG; + + set_pzs(8); +} + +static void +das(void) +{ + uint8_t old_al = AL; + uint16_t old_af = cpu_state.flags & A_FLAG; + uint16_t old_cf = cpu_state.flags & C_FLAG; + uint8_t al_check = (old_af ? 0x9f : 0x99); + + cpu_state.flags &= ~V_FLAG; + + if (!old_af && !old_cf) { + if ((AL >= 0x9a) && (AL <= 0xdf)) + cpu_state.flags |= V_FLAG; + } else if (old_af && !old_cf) { + if (((AL >= 0x80) && (AL <= 0x85)) || ((AL >= 0xa0) && (AL <= 0xe5))) + cpu_state.flags |= V_FLAG; + } else if (!old_af && old_cf) { + if ((AL >= 0x80) && (AL <= 0xdf)) + cpu_state.flags |= V_FLAG; + } else if (old_af && old_cf) { + if ((AL >= 0x80) && (AL <= 0xe5)) + cpu_state.flags |= V_FLAG; + } + + cpu_state.flags &= ~C_FLAG; + if (((AL & 0x0f) > 9) || (cpu_state.flags & A_FLAG)) { + AL -= 6; + cpu_state.flags |= A_FLAG; + } else + cpu_state.flags &= ~A_FLAG; + + if ((old_al > al_check) || old_cf) { + AL -= 0x60; + cpu_state.flags |= C_FLAG; + } else + cpu_state.flags &= ~C_FLAG; + + set_pzs(8); +} + +static void +aaa(void) +{ + uint8_t old_al = AL; + uint8_t new_al; + + if (((AL & 0x0f) > 9) || (cpu_state.flags & A_FLAG)) { + AH += 1; + new_al = AL + 6; + AL = new_al & 0x0f; + cpu_state.flags |= A_FLAG; + cpu_state.flags |= C_FLAG; + } else { + new_al = AL; + AL &= 0x0f; + cpu_state.flags &= ~A_FLAG; + cpu_state.flags &= ~C_FLAG; + do_cycle_i(); + } + + cpu_state.flags &= ~(V_FLAG | Z_FLAG | N_FLAG); + if (new_al == 0x00) + cpu_state.flags |= Z_FLAG; + if ((old_al >= 0x7a) && (old_al <= 0x7f)) + cpu_state.flags |= V_FLAG; + if ((old_al >= 0x7a) && (old_al <= 0xf9)) + cpu_state.flags |= N_FLAG; + + cpu_data = new_al; + set_pf(); +} + +static void +aas(void) +{ + uint8_t old_al = AL; + uint16_t old_af = cpu_state.flags & A_FLAG; + uint8_t new_al; + + do_cycles_i(6); + + if (((AL & 0x0f) > 9) || old_af) { + new_al = AL - 6; + AH++; + AL = new_al & 0x0f; + cpu_state.flags |= (A_FLAG | C_FLAG); + } else { + new_al = AL; + AL &= 0x0f; + cpu_state.flags &= ~(C_FLAG | A_FLAG); + do_cycle_i(); + } + + cpu_state.flags &= ~(V_FLAG | Z_FLAG | N_FLAG); + if (new_al == 0x00) + cpu_state.flags |= Z_FLAG; + if (old_af && (old_al >= 0x80) && (old_al <= 0x85)) + cpu_state.flags |= V_FLAG; + if (!old_af && (old_al >= 0x80)) + cpu_state.flags |= N_FLAG; + if (old_af && ((old_al <= 0x05) || (old_al >= 0x86))) + cpu_state.flags |= N_FLAG; + + cpu_data = new_al; + set_pf(); +} + +static void +finalize(void) +{ + in_0f = 0; + repeating = 0; + ovr_seg = NULL; + in_rep = 0; + rep_c_flag = 0; + if (in_lock) + clear_lock = 1; + cpu_alu_op = 0; + + if (pfq_pos == 0) { + do { + if (nx) + nx = 0; + do_cycle(); + } while (pfq_pos == 0); + biu_preload_byte = biu_pfq_read(); + biu_queue_preload = 1; + do_cycle(); + } else { + biu_queue_preload = 1; + biu_preload_byte = biu_pfq_read(); + + biu_resume_on_queue_read(); + + do_cycle(); + } + + if (irq_pending()) + cpu_state.pc--; +} + +/* Fetches the effective address from the prefetch queue according to MOD and R/M. */ +static void +do_mod_rm(void) +{ + rmdat = biu_pfq_fetchb(); + cpu_reg = (rmdat >> 3) & 7; + cpu_mod = (rmdat >> 6) & 3; + cpu_rm = rmdat & 7; + + if (cpu_mod != 3) { + do_cycle(); + if (is_nec) + do_cycle(); + else if (modrm_cycs_pre[rmdat & 0xc7]) + do_cycles(modrm_cycs_pre[rmdat & 0xc7]); + + if ((rmdat & 0xc7) == 0x06) { + cpu_state.eaaddr = biu_pfq_fetchw(); + easeg = ovr_seg ? *ovr_seg : ds; + } else { + cpu_state.eaaddr = (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); + easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; + switch (rmdat & 0xc0) { + default: + break; + case 0x40: + cpu_state.eaaddr += sign_extend(biu_pfq_fetchb()); + break; + case 0x80: + cpu_state.eaaddr += biu_pfq_fetchw(); + break; + } + cpu_state.eaaddr &= 0xffff; + } + + if (!is_nec && modrm_cycs_post[rmdat & 0xc7]) + do_cycles(modrm_cycs_post[rmdat & 0xc7]); + } +} + +static void +decode(void) +{ + uint8_t op_f; + uint8_t prefix = 0; + + if (halted) + opcode = 0xf4; + else + opcode = biu_pfq_fetchb_common(); + + modrm_loaded = 0; + + while (1) { + prefix = 0; + + switch (opcode) { + case 0x0f: /* NEC/186 */ + if (is_nec) { + in_0f = 1; + prefix = 1; + } + break; + case 0x26: /* ES: */ + case 0x2e: /* CS: */ + case 0x36: /* SS: */ + case 0x3e: /* DS: */ + ovr_seg = opseg[(opcode >> 3) & 0x03]; + prefix = 1; + break; + case 0x64: /* REPNC */ + case 0x65: /* REPC */ + if (is_nec) { + in_rep = (opcode == 0x64 ? 1 : 2); + rep_c_flag = 1; + prefix = 1; + } + break; + case 0xf0: + case 0xf1: /* LOCK - F1 is alias */ + in_lock = 1; + prefix = 1; + break; + case 0xf2: /* REPNE */ + case 0xf3: /* REPE */ + in_rep = (opcode == 0xf2 ? 1 : 2); + rep_c_flag = 0; + prefix = 1; + break; + default: + break; + } + + if (prefix == 0) + break; + + do_cycle(); + + 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 +string_op(int bits) +{ + uint16_t tmpa; + uint16_t old_ax; + + if ((opcode & 0xf0) == 0x60) switch (opcode & 0x0e) { + case 0x0c: + old_ax = AX; + cpu_data = DX; + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 0, cpu_state.eaaddr); + cpu_data = AX; + stos(bits); + AX = old_ax; + break; + case 0x0e: + old_ax = AX; + lods(bits); + set_accum(bits, cpu_data); + cpu_data = DX; + do_cycle_i(); + /* biu_io_write_u16() */ + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 1, cpu_state.eaaddr); + AX = old_ax; + break; + } else switch (opcode & 0x0e) { + case 0x04: + lods(bits); + do_cycle_i(); + stos(bits); + break; + case 0x06: + do_cycle_i(); + if (is_nec) { + if (in_rep) { + lods_di(bits); + tmpa = cpu_data; + lods(bits); + } else { + lods(bits); + tmpa = cpu_data; + lods_di(bits); + } + } else { + lods(bits); + tmpa = cpu_data; + do_cycles_i(2); + lods_di(bits); + do_cycles_i(3); + } + + cpu_src = cpu_data; + cpu_dest = tmpa; + sub(bits); + break; + case 0x0e: + tmpa = AX; + do_cycles_i(2); + lods_di(bits); + do_cycles_i(3); + + cpu_src = cpu_data; + cpu_dest = tmpa; + sub(bits); + break; + case 0x0a: + cpu_data = AX; + stos(bits); + break; + case 0x0c: + lods(bits); + set_accum(bits, cpu_data); + break; + } +} + +static int do_print = 1; + +static void +execvx0_0f(void) +{ + uint8_t bit; + uint8_t odd; + uint8_t nibbles_count; + uint8_t destcmp; + uint8_t destbyte; + uint8_t srcbyte; + uint8_t nibble_result; + uint8_t temp_val; + uint8_t temp_al; + uint8_t bit_length; + uint8_t bit_offset; + int8_t nibble_result_s; + int bits; + uint32_t i; + uint32_t carry; + uint32_t nibble; + uint32_t srcseg; + uint32_t byteaddr; + + switch (opcode) { + case 0x10: /* TEST1 r8/m8, CL*/ + case 0x11: /* TEST1 r16/m16, CL*/ + case 0x18: /* TEST1 r8/m8, imm3 */ + case 0x19: /* TEST1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_cycles(2); + + bit = (opcode & 0x8) ? biu_pfq_fetchb() : CL; + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + set_zf_ex(!(cpu_data & (1 << bit))); + cpu_state.flags &= ~(V_FLAG | C_FLAG); + break; + + case 0x12: /* CLR1 r8/m8, CL*/ + case 0x13: /* CLR1 r16/m16, CL*/ + case 0x1a: /* CLR1 r8/m8, imm3 */ + case 0x1b: /* CLR1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_cycles(2); + + bit = (opcode & 0x8) ? biu_pfq_fetchb() : CL; + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xff) & ~(1 << bit)); + else + seteaw((cpu_data & 0xffff) & ~(1 << bit)); + break; + + case 0x14: /* SET1 r8/m8, CL*/ + case 0x15: /* SET1 r16/m16, CL*/ + case 0x1c: /* SET1 r8/m8, imm3 */ + case 0x1d: /* SET1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_cycles(2); + + bit = (opcode & 0x8) ? biu_pfq_fetchb() : CL; + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xff) | (1 << bit)); + else + seteaw((cpu_data & 0xffff) | (1 << bit)); + break; + + case 0x16: /* NOT1 r8/m8, CL*/ + case 0x17: /* NOT1 r16/m16, CL*/ + case 0x1e: /* NOT1 r8/m8, imm3 */ + case 0x1f: /* NOT1 r16/m16, imm4 */ + bits = 8 << (opcode & 0x1); + do_cycles(2); + + bit = (opcode & 0x8) ? (biu_pfq_fetchb()) : (CL); + bit &= ((1 << (3 + (opcode & 0x1))) - 1); + read_ea(0, bits); + + if (bits == 8) + seteab((cpu_data & 0xff) ^ (1 << bit)); + else + seteaw((cpu_data & 0xffff) ^ (1 << bit)); + break; + + case 0x20: /* ADD4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + do_cycles(4); + + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + do_cycles(19); + destcmp = read_mem_b((es) + DI + i); + + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result = (i == (nibbles_count / 2) && nibble == 1) ? (destbyte + carry) : + ((uint8_t) (destbyte)) + ((uint8_t) (srcbyte)) + ((uint32_t) carry); + carry = 0; + + while (nibble_result >= 10) { + nibble_result -= 10; + carry++; + } + + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result == 0); + + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result << (4 * nibble))); + } + + write_mem_b(es + DI + i, destcmp); + } + + set_cf(!!carry); + set_zf(!!zero); + break; + + case 0x22: /* SUB4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + do_cycles(4); + + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + do_cycles(19); + destcmp = read_mem_b((es) + DI + i); + + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = (i == (nibbles_count / 2) && nibble == 1) ? ((int8_t) destbyte - (int8_t) carry) : + ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; + } + + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); + } + + write_mem_b(es + DI + i, destcmp); + } + + set_cf(!!carry); + set_zf(!!zero); + break; + + case 0x26: /* CMP4S */ + odd = !!(CL % 2); + zero = 1; + nibbles_count = CL - odd; + i = 0; + carry = 0; + nibble = 0; + srcseg = ovr_seg ? *ovr_seg : ds; + + do_cycles(4); + + for (i = 0; i < ((nibbles_count / 2) + odd); i++) { + do_cycles(19); + destcmp = read_mem_b((es) + DI + i); + + for (nibble = 0; nibble < 2; nibble++) { + destbyte = destcmp >> (nibble ? 4 : 0); + srcbyte = read_mem_b(srcseg + SI + i) >> (nibble ? 4 : 0); + destbyte &= 0xF; + srcbyte &= 0xF; + nibble_result_s = ((int8_t) (destbyte)) - ((int8_t) (srcbyte)) - ((int8_t) carry); + carry = 0; + + while (nibble_result_s < 0) { + nibble_result_s += 10; + carry++; + } + + if (zero != 0 || (i == (nibbles_count / 2) && nibble == 1)) + zero = (nibble_result_s == 0); + + destcmp = ((destcmp & (nibble ? 0x0F : 0xF0)) | (nibble_result_s << (4 * nibble))); + } + } + + set_cf(!!carry); + set_zf(!!zero); + break; + + case 0x28: /* ROL4 r/m */ + do_cycles(20); + + temp_val = geteab(); + temp_al = AL; + + temp_al &= 0x0f; + temp_al |= (temp_val & 0xf0); + temp_val = (temp_al & 0x0f) | ((temp_val & 0x0f) << 4); + temp_al >>= 4; + temp_al &= 0x0f; + seteab(temp_val); + AL = temp_al; + break; + + case 0x2a: /* ROR4 r/m */ + do_cycles(20); + + temp_val = geteab(); + temp_al = AL; + + AL = temp_val & 0x0f; + temp_val = (temp_val >> 4) | ((temp_al & 0x0f) << 4); + + seteab(temp_val); + break; + + case 0x31: /* INS reg1, reg2 */ + case 0x39: /* INS reg8, imm4 */ + bit_length = ((opcode & 0x8) ? (biu_pfq_fetchb() & 0x0f) : (getr8(cpu_reg) & 0x0f)) + 1; + bit_offset = getr8(cpu_rm) & 0x0f; + byteaddr = (es) + DI; + i = 0; + + if (bit_offset >= 8) { + DI++; + byteaddr++; + bit_offset -= 8; + } + + 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)); + bit_offset++; + + if (bit_offset == 8) { + DI++; + bit_offset = 0; + } + } + + setr8(cpu_rm, bit_offset); + break; + + case 0x33: /* EXT reg1, reg2 */ + case 0x3b: /* EXT reg8, imm4 */ + bit_length = ((opcode & 0x8) ? (biu_pfq_fetchb() & 0x0f) : (getr8(cpu_reg) & 0x0f)) + 1; + bit_offset = getr8(cpu_rm) & 0x0f; + byteaddr = (ds) + SI; + i = 0; + + if (bit_offset >= 8) { + SI++; + byteaddr++; + bit_offset -= 8; + } + + AX = 0; + + for (i = 0; i < bit_length; i++) { + byteaddr = (ds) + SI; + AX |= (!!(readmemb(ds, SI) & (1 << bit_offset))) << i; + bit_offset++; + + if (bit_offset == 8) { + SI++; + bit_offset = 0; + } + } + + setr8(cpu_rm, bit_offset); + break; + + case 0xff: /* BRKEM */ + interrupt_brkem(biu_pfq_fetchb()); + break; + + default: + do_cycles_nx_i(2); /* Guess, based on NOP. */ + break; + } +} + +static void +execvx0_6x(uint16_t *jump) +{ + uint16_t lowbound; + uint16_t highbound; + uint16_t regval; + uint16_t wordtopush; + uint16_t immediate; + uint16_t tempw; + int bits; + int32_t templ; + + switch (opcode) { + case 0x60: /* PUSHA/PUSH R */ + writememw(ss, ((SP - 2) & 0xffff), AX); + biu_state_set_eu(); + writememw(ss, ((SP - 4) & 0xffff), CX); + biu_state_set_eu(); + writememw(ss, ((SP - 6) & 0xffff), DX); + biu_state_set_eu(); + writememw(ss, ((SP - 8) & 0xffff), BX); + biu_state_set_eu(); + writememw(ss, ((SP - 10) & 0xffff), SP); + biu_state_set_eu(); + writememw(ss, ((SP - 12) & 0xffff), BP); + biu_state_set_eu(); + writememw(ss, ((SP - 14) & 0xffff), SI); + biu_state_set_eu(); + writememw(ss, ((SP - 16) & 0xffff), DI); + SP -= 16; + break; + + case 0x61: /* POPA/POP R */ + DI = readmemw(ss, ((SP) & 0xffff)); + biu_state_set_eu(); + SI = readmemw(ss, ((SP + 2) & 0xffff)); + biu_state_set_eu(); + BP = readmemw(ss, ((SP + 4) & 0xffff)); + biu_state_set_eu(); + BX = readmemw(ss, ((SP + 8) & 0xffff)); + biu_state_set_eu(); + DX = readmemw(ss, ((SP + 10) & 0xffff)); + biu_state_set_eu(); + CX = readmemw(ss, ((SP + 12) & 0xffff)); + biu_state_set_eu(); + AX = readmemw(ss, ((SP + 14) & 0xffff)); + SP += 16; + break; + + case 0x62: /* BOUND r/m */ + lowbound = 0; + highbound = 0; + regval = 0; + + lowbound = readmemw(easeg, cpu_state.eaaddr); + highbound = readmemw(easeg, cpu_state.eaaddr + 2); + regval = get_reg(cpu_reg); + + if ((lowbound > regval) || (highbound < regval)) { + sw_int(5); + *jump = 1; + } + break; + + case 0x63: + if (is_nec) { + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + tempw = cpu_state.pc; + geteaw(); + do_cycles(60); + } + break; + + case 0x64: + case 0x65: + if (!is_nec) { + do_cycles_nx_i(2); /* Guess, based on NOP. */ + } + break; + + case 0x66 ... 0x67: /* FPO2 - NEC FPU instructions. */ + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + tempw = cpu_state.pc; + geteaw(); + /* fpu_op() */ + cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on + the 286+ core, but not here. */ + break; + + case 0x68: + wordtopush = biu_pfq_fetchw(); + push(&wordtopush); + break; + + case 0x69: + bits = 16; + read_ea(0, 16); + immediate = biu_pfq_fetchw(); + + templ = ((int) cpu_data) * ((int) immediate); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + set_reg(cpu_reg, templ & 0xffff); + do_cycles((cpu_mod == 3) ? 20 : 26); + break; + + case 0x6a: + wordtopush = sign_extend(biu_pfq_fetchb()); + push(&wordtopush); + break; + + case 0x6b: /* IMUL reg16,reg16/mem16,imm8 */ + read_ea(0, 16); + immediate = biu_pfq_fetchb(); + immediate = geteaw(); + if (immediate & 0x80) + immediate |= 0xff00; + + templ = ((int) cpu_data) * ((int) immediate); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + cpu_state.flags |= C_FLAG | V_FLAG; + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + set_reg(cpu_reg, templ & 0xffff); + do_cycles((cpu_mod == 3) ? 24 : 30); + break; + + case 0x6c: + case 0x6d: /* INM dst, DW/INS dst, DX */ + bits = 8 << (opcode & 1); + if (rep_start()) { + string_op(bits); + do_cycle_i(); + + if (in_rep != 0) { + completed = 0; + repeating = 1; + + do_cycle_i(); + if (irq_pending()) { + do_cycle_i(); + rep_interrupt(); + } + + do_cycle_i(); + /* decrement_register16() */ + CX--; + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } else + do_cycle_i(); + } + break; + + case 0x6e: + case 0x6f: /* OUTM DW, src/OUTS DX, src */ + bits = 8 << (opcode & 1); + if (rep_start()) { + string_op(bits); + do_cycles_i(3); + + if (in_rep != 0) { + completed = 0; + repeating = 1; + + do_cycle_i(); + /* decrement_register16() */ + CX--; + + if (irq_pending()) { + do_cycles_i(2); + rep_interrupt(); + } else { + do_cycles_i(2); + + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } + } + } + break; + + default: + do_cycles_nx_i(2); /* Guess, based on NOP. */ + break; + } +} + +/* Executes a single instruction. */ +void +execute_instruction(void) +{ + uint8_t temp = 0; + uint8_t tempb; + uint8_t nests; + + int8_t rel8; + int8_t temps; + + uint16_t addr; + uint16_t jump = 0; + uint16_t new_cs; + uint16_t new_ip; + uint16_t tempw; + uint16_t zero_cond; + uint16_t old_cs; + uint16_t old_ip; + uint16_t old_flags; + uint16_t prod16; + uint16_t tempw_int; + uint16_t size; + uint16_t tempbp; + uint16_t src16; + + int16_t rel16; + int16_t temps16; + + uint32_t prod32; + uint32_t templ; + uint32_t templ2 = 0; + + int bits; + int negate; + int tempws = 0; + int tempws2 = 0; + + completed = 1; + + if (nx) { + do_cycle(); + nx = 0; + } else if (!modrm_loaded) + do_cycle(); + + if (group_delay) { + group_delay = 0; + do_cycle(); + nx = 0; + } + + if (!is_nec && (opcode >= 0xc0) && (opcode <= 0xc1)) + opcode |= 0x02; + + if (is_nec && !(cpu_state.flags & MD_FLAG)) { + i8080_step(&emulated_processor); + set_if(emulated_processor.iff); + if (retem) + jump = 1; + retem = 0; + do_cycles(emulated_processor.cyc); + emulated_processor.cyc = 0; + } else if (is_nec && in_0f) + execvx0_0f(); + else if (is_nec && ((opcode & 0xf0) == 0x60)) + execvx0_6x(&jump); + else switch (opcode) { + case 0x00: /* ADD r/m8, r8; r8, r/m8; al, imm8 */ + 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; + /* read_operand8() */ + if (opcode & 0x04) { + cpu_data = biu_pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + } else { + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + 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); + } + } + do_cycles_nx_i(2); + if (!(opcode & 0x06) && (cpu_mod != 3)) + do_cycles_i(2); + + /* math_op8() */ + math_op((opcode >> 3) & 7); + /* write_operand8() */ + 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 0x0b: + case 0x0d: + case 0x11: /* ADC r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x13: + case 0x15: + case 0x19: /* SBB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x1b: + case 0x1d: + case 0x21: /* AND r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x23: + case 0x25: + case 0x29: /* SUB r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x2b: + case 0x2d: + case 0x31: /* XOR r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x33: + case 0x35: + bits = 16; + nx = 1; + /* read_operand16() */ + if (opcode & 0x04) { + cpu_data = biu_pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + } else { + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + 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); + } + } + do_cycles_nx_i(2); + if (!(opcode & 0x06) && (cpu_mod != 3)) + do_cycles_i(2); + + /* math_op16() */ + math_op((opcode >> 3) & 7); + /* write_operand16() */ + if (opcode & 0x04) + set_accum(bits, cpu_data); + else { + if (opcode & 0x02) + set_reg(cpu_reg, cpu_data); + else + set_ea(cpu_data); + } + break; + + case 0x06: + case 0x0e: + case 0x16: + case 0x1e: /* PUSH seg */ + do_cycles_i(3); + push(&(_opseg[(opcode >> 3) & 0x03]->seg)); + break; + + case 0x07: + case 0x17: + case 0x1f: /* POP seg */ + load_seg(pop(), _opseg[(opcode >> 3) & 0x03]); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; + break; + + case 0x0f: + if (!is_nec) { + load_cs(pop()); + /* All POP segment instructions suppress interrupts for one instruction. */ + noint = 1; + } + break; + + case 0x26: /* ES: */ + case 0x2e: /* CS: */ + case 0x36: /* SS: */ + case 0x3e: /* DS: */ + break; + + case 0x27: /* DAA */ + do_cycles_nx_i(3); + daa(); + break; + + case 0x2f: /* DAS */ + do_cycles_nx_i(3); + das(); + break; + + case 0x37: /* AAA */ + aaa(); + break; + + case 0x38: /* CMP r/m8, r8; r8, r/m8; al, imm8 */ + case 0x3a: + case 0x3c: + bits = 8; + /* read_operand8() */ + if (opcode & 0x04) { + cpu_data = biu_pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + } else { + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + 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); + } + } + + do_cycles_nx_i(2); + + /* math_op8() */ + math_op(7); + break; + + case 0x39: /* CMP r/m16, r16; r16, r/m16; ax, imm16 */ + case 0x3b: + case 0x3d: + bits = 16; + /* read_operand16() */ + if (opcode & 0x04) { + cpu_data = biu_pfq_fetch(); + cpu_dest = get_accum(bits); /* AX/AL */ + cpu_src = cpu_data; + } else { + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + 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); + } + } + + do_cycles_nx_i((opcode == 0x3d) ? 1 : 2); + + /* math_op16() */ + math_op(7); + break; + + case 0x3f: /*AAS*/ + aas(); + break; + + case 0x40 ... 0x47: /* INC r16 */ + /* read_operand16() */ + cpu_dest = cpu_state.regs[opcode & 7].w; + cpu_src = 1; + bits = 16; + /* math_op16() */ + cpu_data = cpu_dest + cpu_src; + set_of_add(bits); + do_af(); + set_pzs(16); + /* write_operand16() */ + cpu_state.regs[opcode & 7].w = cpu_data; + + do_cycles_nx(1); + break; + + case 0x48 ... 0x4f: /* DEC r16 */ + /* read_operand16() */ + cpu_dest = cpu_state.regs[opcode & 7].w; + cpu_src = 1; + bits = 16; + /* math_op16() */ + cpu_data = cpu_dest - cpu_src; + set_of_sub(bits); + do_af(); + set_pzs(16); + /* write_operand16() */ + cpu_state.regs[opcode & 7].w = cpu_data; + + do_cycles_nx(1); + break; + + case 0x50 ... 0x57: /* PUSH r16 */ + do_cycles_i(3); + + push(&(cpu_state.regs[opcode & 0x07].w)); + break; + + case 0x58 ... 0x5f: /* POP r16 */ + cpu_state.regs[opcode & 0x07].w = pop(); + do_cycle_nx_i(); + break; + + case 0x60 ... 0x7f: /* JMP rel8 */ + switch ((opcode >> 1) & 0x07) { + case 0x00: + jump = cpu_state.flags & V_FLAG; + break; + case 0x01: + jump = cpu_state.flags & C_FLAG; + break; + case 0x02: + jump = cpu_state.flags & Z_FLAG; + break; + case 0x03: + jump = cpu_state.flags & (C_FLAG | Z_FLAG); + break; + case 0x04: + jump = cpu_state.flags & N_FLAG; + break; + case 0x05: + jump = cpu_state.flags & P_FLAG; + break; + case 0x06: + jump = (!!(cpu_state.flags & N_FLAG)) != (!!(cpu_state.flags & V_FLAG)); + break; + case 0x07: + jump = (cpu_state.flags & Z_FLAG) || + ((!!(cpu_state.flags & N_FLAG)) != (!!(cpu_state.flags & V_FLAG))); + break; + } + if (opcode & 1) + jump = !jump; + + rel8 = (int8_t) biu_pfq_fetchb(); + new_ip = cpu_state.pc + rel8; + if (!is_nec) + do_cycle_i(); + + if (jump) + reljmp(new_ip, 1); + break; + + case 0x80: /* ADD/OR/ADC/SBB/AND/SUB/XOR/CMP r/m8, imm8 */ + case 0x82: + bits = 8; + /* read_opreand8() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + cpu_dest = cpu_data; + cpu_src = biu_pfq_fetchb() | 0xff00; + + do_cycle_nx(); + math_op((rmdat & 0x38) >> 3); + + if (cpu_mod != 3) + do_cycles_i(2); + + /* write_operand8() */ + if (cpu_alu_op != 7) + set_ea(cpu_data); + break; + + case 0x81: /* ADD/OR/ADC/SBB/AND/SUB/XOR/CMP r/m16, imm16 */ + bits = 16; + /* read_opreand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + cpu_dest = cpu_data; + cpu_src = biu_pfq_fetchw(); + + do_cycle_nx(); + math_op((rmdat & 0x38) >> 3); + + if (cpu_mod != 3) { + if (cpu_alu_op != 7) + do_cycles_i(2); + else { + do_cycles_nx_i(2); + } + } + + /* write_operand16() */ + if (cpu_alu_op != 7) + set_ea(cpu_data); + break; + + case 0x83: /* ADD/OR/ADC/SBB/AND/SUB/XOR/CMP r/m16, imm8 (sign-extended) */ + bits = 16; + /* read_opreand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + cpu_dest = cpu_data; + cpu_src = sign_extend(biu_pfq_fetchb()); + + do_cycle_nx(); + math_op((rmdat & 0x38) >> 3); + + if (cpu_mod != 3) + do_cycles_i(2); + + /* write_operand16() */ + if (cpu_alu_op != 7) + set_ea(cpu_data); + break; + + case 0x84: /* TEST r/m8, r8 */ + bits = 8; + /* read_operand8() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + + /* math_op8() */ + test(bits, cpu_data, get_reg(cpu_reg)); + + do_cycles_nx_i(2); + break; + + case 0x85: /* TEST r/m16, r16 */ + bits = 16; + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + + /* math_op16() */ + test(bits, cpu_data, get_reg(cpu_reg)); + + do_cycles_nx_i(2); + break; + + case 0x86: /* XHG r8, r/m8 */ + bits = 8; + /* read_operand8() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + cpu_src = get_reg(cpu_reg); + + do_cycles_nx(3); + + if (cpu_mod != 3) + do_cycles(2); + + /* write_operand8() */ + set_reg(cpu_reg, cpu_data); + set_ea(cpu_src); + break; + + case 0x87: /* XCHG r16, r/m16 */ + bits = 16; + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = get_ea(); + cpu_src = get_reg(cpu_reg); + + do_cycles_nx(3); + + if (cpu_mod != 3) + do_cycles(2); + + /* write_operand16() */ + set_reg(cpu_reg, cpu_data); + set_ea(cpu_src); + break; + + case 0x88: /* MOV r/m8, r8; MOV r8, r/m8 */ + case 0x8a: + bits = 8; + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + do_cycle_nx(); + /* read_operand8() */ + if (opcode == 0x88) + tempb = get_reg(cpu_reg); + else + tempb = get_ea(); + + if ((opcode == 0x88) && (cpu_mod != 3)) + do_cycles_i(2); + + /* write_operand8() */ + if (opcode == 0x88) + set_ea(tempb); + else + set_reg(cpu_reg, tempb); + break; + + case 0x89: /* MOV r/m16, r16; MOV r16, r/m16 */ + case 0x8b: + bits = 16; + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + do_cycle_nx(); + /* read_operand16() */ + if (opcode == 0x89) + tempw = get_reg(cpu_reg); + else + tempw = get_ea(); + + if ((opcode == 0x89) && (cpu_mod != 3)) + do_cycles_i(2); + + /* write_operand16() */ + if (opcode == 0x89) + set_ea(tempw); + else + set_reg(cpu_reg, tempw); + break; + + case 0x8c: /* MOV r/m16, SReg; MOV SReg, r/m16 */ + case 0x8e: + bits = 16; + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + if ((opcode == 0x8c) && (cpu_mod != 3)) + do_cycle_i(); + /* read_operand16() */ + if (opcode == 0x8c) + tempw = _opseg[(rmdat & 0x18) >> 3]->seg; + else + tempw = geteaw(); + /* write_operand16() */ + if (opcode == 0x8c) + seteaw(tempw); + else { + if ((rmdat & 0x18) == 0x08) + load_cs(tempw); + else + load_seg(tempw, _opseg[(rmdat & 0x18) >> 3]); + if (((rmdat & 0x18) >> 3) == 2) + noint = 1; + } + break; + + case 0x8d: /* LEA */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; + break; + + case 0x8f: /* POP r/m16 */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + do_cycle_i(); + /* pop_u16() */ + cpu_src = cpu_state.eaaddr; + cpu_data = pop(); + do_cycle_i(); + if (cpu_mod != 3) + do_cycles_i(2); + /* write_operand16() */ + cpu_state.eaaddr = cpu_src; + seteaw(cpu_data); + break; + + case 0x90 ... 0x97: /* XCHG AX, r */ + cpu_data = cpu_state.regs[opcode & 7].w; + do_cycles_nx_i(2); + cpu_state.regs[opcode & 7].w = AX; + AX = cpu_data; + break; + + case 0x98: /* CBW */ + sign_extend_al(); + break; + + case 0x99: /* CWD */ + sign_extend_ax(); + break; + + case 0x9a: /* CALLF */ + /* read_operand_faraddr() */ + new_ip = biu_pfq_fetchw(); + new_cs = biu_pfq_fetchw(); + + farcall(new_cs, new_ip, 1); + + jump = 1; + break; + + case 0x9b: /* WAIT */ + do_cycles(3); + break; + + case 0x9c: /* PUSHF */ + do_cycles(3); + /* push_flags() */ + if (is_nec) + tempw = (cpu_state.flags & 0x8fd7) | 0x7000; + else + tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + push(&tempw); + break; + + case 0x9d: /* POPF */ + /* pop_flags() */ + if (is_nec && cpu_md_write_disable) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; + sync_to_i8080(); + break; + + case 0x9e: /* SAHF */ + /* store_flags() */ + cpu_state.flags = (cpu_state.flags & 0xff02) | AH; + break; + + case 0x9f: /*LAHF*/ + /* load_flags() */ + /* set_register8() */ + AH = cpu_state.flags & 0xd7; + break; + + case 0xa0: /* MOV al, offset8 */ + bits = 8; + /* read_operand8() */ + cpu_state.eaaddr = biu_pfq_fetchw(); + tempb = readmem(ovr_seg ? *ovr_seg : ds); + /* set_register8() */ + set_accum(bits, tempb); + break; + + case 0xa1: /* MOV al, offset16 */ + bits = 16; + /* read_operand16() */ + cpu_state.eaaddr = biu_pfq_fetchw(); + tempw = readmem(ovr_seg ? *ovr_seg : ds); + /* set_register16() */ + set_accum(bits, tempw); + break; + + case 0xa2: /* MOV offset8, Al */ + bits = 8; + tempb = get_accum(bits); + /* write_operand8() */ + cpu_state.eaaddr = biu_pfq_fetchw(); + writemem((ovr_seg ? *ovr_seg : ds), tempb); + break; + + case 0xa3: /* MOV offset16, AX */ + bits = 16; + tempw = get_accum(bits); + /* write_operand16() */ + cpu_state.eaaddr = biu_pfq_fetchw(); + writemem((ovr_seg ? *ovr_seg : ds), tempw); + break; + + case 0xa4: /* MOVSB & MOVSW */ + case 0xa5: + bits = 8 << (opcode & 1); + + if (rep_start()) { + string_op(bits); + do_cycle_i(); + + if (in_rep != 0) { + completed = 0; + repeating = 1; + + /* decrement_register16() */ + CX--; + + if (irq_pending()) { + do_cycles_i(2); + rep_interrupt(); + } else { + do_cycles_i(2); + + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } + } else + do_cycle_i(); + } + break; + + case 0xa6: /* CMPSB, CMPSW, SCASB, SCASW */ + case 0xa7: + case 0xae: + case 0xaf: + bits = 8 << (opcode & 1); + if (rep_start()) { + string_op(bits); + + if (in_rep) { + uint8_t end = 0; + + completed = 0; + repeating = 1; + + do_cycle_i(); + /* decrement_register16() */ + CX--; + + if ((!!(cpu_state.flags & (rep_c_flag ? C_FLAG : Z_FLAG))) == (in_rep == 1)) { + rep_end(); + do_cycle_i(); + end = 1; + } + + if (!end) { + do_cycle_i(); + + if (irq_pending()) { + do_cycle_i(); + rep_interrupt(); + } + + do_cycle_i(); + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } else + do_cycle_i(); + } + } + break; + + case 0xa8: /* TEST al, imm8 */ + bits = 8; + /* read_operand8() */ + cpu_data = biu_pfq_fetch(); + /* math_op8() */ + test(bits, get_accum(bits), cpu_data); + break; + + case 0xa9: /* TEST ax, imm16 */ + bits = 16; + /* read_operand16() */ + cpu_data = biu_pfq_fetch(); + /* math_op16() */ + test(bits, get_accum(bits), cpu_data); + break; + + case 0xaa: /* STOSB & STOSW */ + case 0xab: + bits = 8 << (opcode & 1); + if (rep_start()) { + string_op(bits); + do_cycle_i(); + + if (in_rep != 0) { + completed = 0; + repeating = 1; + + do_cycle_i(); + if (irq_pending()) { + do_cycle_i(); + rep_interrupt(); + } + + do_cycle_i(); + /* decrement_register16() */ + CX--; + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } else + do_cycle_i(); + } + break; + + case 0xac: /* LODSB * LODSW */ + case 0xad: + bits = 8 << (opcode & 1); + if (rep_start()) { + string_op(bits); + do_cycles_i(3); + + if (in_rep != 0) { + completed = 0; + repeating = 1; + + do_cycle_i(); + /* decrement_register16() */ + CX--; + + if (irq_pending()) { + do_cycles_i(2); + rep_interrupt(); + } else { + do_cycles_i(2); + + if (CX == 0) + rep_end(); + else + do_cycle_i(); + } + } + } + break; + + case 0xb0 ... 0xb7: /* MOV r8, imm8 */ + bits = 8; + /* read_operand8() */ + tempb = biu_pfq_fetchb(); + /* set_register8() */ + if (opcode & 0x04) + cpu_state.regs[opcode & 0x03].b.h = tempb; + else + cpu_state.regs[opcode & 0x03].b.l = tempb; + do_cycle_i(); + break; + + case 0xb8 ... 0xbf: /* MOV r16, imm16 */ + bits = 16; + /* read_operand16() */ + tempw = biu_pfq_fetchw(); + /* set_register16() */ + cpu_state.regs[opcode & 0x07].w = tempw; + break; + + case 0xc0: /* rot imm8 */ + case 0xc1: + /* rot rm */ + bits = 8 << (opcode & 1); + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + /* read_operand() */ + cpu_data = get_ea(); + cpu_src = biu_pfq_fetchb(); + if (is186 && !is_nec) + cpu_src &= 0x1F; + do_cycles_i(6); + if (cpu_src > 0) { + for (uint8_t i = 0; i < cpu_src; i++) + do_cycles_i(4); + } + if (cpu_mod != 3) + do_cycle_i(); + /* bitshift_op() */ + 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; + + default: + break; + } + --cpu_src; + } + + if (opcode <= 0xd1) { + if (cpu_mod != 3) + do_cycle_i(); + } + + /* write_operand() */ + set_ea(cpu_data); + break; + + case 0xc2: /* RETN imm16 */ + bits = 8; + cpu_src = biu_pfq_fetchw(); + do_cycle_i(); + new_ip = pop(); + biu_suspend_fetch(); + set_ip(new_ip); + + do_cycles_i(2); + biu_queue_flush(); + do_cycles_i(3); + + /* release() */ + SP += cpu_src; + + jump = 1; + break; + + case 0xc3: /* RETN */ + bits = 8; + new_ip = pop(); + biu_suspend_fetch(); + set_ip(new_ip); + do_cycle_i(); + biu_queue_flush(); + do_cycles_i(2); + + jump = 1; + break; + + case 0xc4: /* LES */ + case 0xc5: /* LDS */ + bits = 16; + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + + do_cycles_i(2); + + /* read_operand_farptr() */ + read_ea(1, bits); + cpu_state.regs[cpu_reg].w = cpu_data; + read_ea2(bits); + + /* write_operand16() */ + load_seg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); + break; + + case 0xc6: /* MOV r/m8, imm8 */ + bits = 8; + /* read_operand8() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = biu_pfq_fetch(); + do_cycles(2); + /* write_operand8() */ + set_ea(cpu_data); + break; + + case 0xc7: /* MOV r/m16, imm16 */ + bits = 16; + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + cpu_data = biu_pfq_fetch(); + do_cycle_i(); + /* write_operand16() */ + set_ea(cpu_data); + break; + + case 0xc8: /* RETF imm16 */ + if (is_nec) { + /* ENTER/PREPARE */ + tempw_int = 0; + size = biu_pfq_fetchw(); + nests = biu_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; + break; + } else + fallthrough; + case 0xca: + bits = 16; + /* read_operand16() */ + cpu_src = biu_pfq_fetchw(); + farret(1); + /* release() */ + SP += cpu_src; + do_cycle_i(); + jump = 1; + break; + + case 0xc9: /* RETF */ + if (is_nec) { + /* LEAVE/DISPOSE */ + SP = BP; + BP = pop(); + break; + } else + fallthrough; + case 0xcb: + bits = 16; + do_cycle_i(); + farret(1); + jump = 1; + break; + + case 0xcc: /* INT 3 */ + do_cycles_i(4); + int3(); + jump = 1; + break; + + case 0xcd: /* INT imm8 */ + /* read_operand8() */ + temp = biu_pfq_fetchb(); + do_cycle_i(); + sw_int(temp); + jump = 1; + break; + + case 0xce: /* INTO */ + if (cpu_state.flags & V_FLAG) { + sw_int(4); + jump = 1; + } + break; + + case 0xcf: /* IRET */ + iret_routine(); + if (is_nec && !(cpu_state.flags & MD_FLAG)) + sync_to_i8080(); + jump = 1; + break; + + case 0xd0: /* ROL, ROR, RCL, RCR, SHL, SHR, SAR: r/m 8, 0x01 */ + case 0xd1: /* ROL, ROR, RCL, RCR, SHL, SHR, SAR: r/m 16, 0x01 */ + case 0xd2: /* ROL, ROR, RCL, RCR, SHL, SHR, SAR: r/m 8, cl */ + case 0xd3: /* ROL, ROR, RCL, RCR, SHL, SHR, SAR: r/m 16, cl */ + /* rot rm */ + bits = 8 << (opcode & 1); + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + /* read_operand() */ + cpu_data = get_ea(); + if ((opcode & 2) == 0) + cpu_src = 1; + else + cpu_src = CL; + if (is186 && !is_nec) + cpu_src &= 0x1F; + if (opcode >= 0xd2) { + do_cycles_i(6); + if (CL > 0) { + for (uint8_t i = 0; i < CL; i++) + do_cycles_i(4); + } + if (cpu_mod != 3) + do_cycle_i(); + } + /* bitshift_op() */ + while (cpu_src != 0) { + cpu_dest = cpu_data; + oldc = cpu_state.flags & C_FLAG; + if (is_nec && ((rmdat & 0x38) == 0x30)) + rmdat &= 0xef; /* Make it 0x20, so it aliases to SHL. */ + 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; + + default: + break; + } + --cpu_src; + } + + if (opcode <= 0xd1) { + if (cpu_mod != 3) + do_cycle_i(); + } + + /* write_operand() */ + set_ea(cpu_data); + break; + + case 0xd4: /* AAM */ + /* read_operand8() */ + cpu_src = biu_pfq_fetchb(); + + if (is_nec) { + if (!cpu_src) + cpu_src = 10; + AH = AL / cpu_src; + AL %= cpu_src; + cpu_data = AL; + set_pzs(8); + do_cycles(12); + } else { + /* Confirmed to be identical on V20/V30 to 808x, per + XTIDE working correctly on both (it uses AAM with + parameter other than 10. */ + /* aam() */ + if (x86_div(AL, 0)) { + cpu_data = AL; + set_pzs(8); + } + } + break; + + case 0xd5: /* AAD */ + /* read_operand8() */ + cpu_src = biu_pfq_fetchb(); + + if (is_nec) { + cpu_src = 10; + AL = (AH * cpu_src) + AL; + AH = 0; + cpu_data = AL; + set_pzs(8); + do_cycles(4); + } else { + if (is_nec) + cpu_src = 10; + /* aad() */ + mul(cpu_src, AH); + cpu_dest = AL; + cpu_src = cpu_data; + add(8); + AL = cpu_data; + AH = 0x00; + set_pzs(8); + } + break; + + case 0xd6: /* SALC */ + if (is_nec) { + do_cycles(14); + fallthrough; + } else { + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; + break; + } + case 0xd7: /* XLAT */ + do_cycles_i(3); + /* biu_read_u8() */ + cpu_state.eaaddr = (BX + AL) & 0xffff; + tempb = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + /* set_register8() */ + AL = tempb; + break; + + case 0xd8 ... 0xdf: /* ESC - FPU instructions. */ + /* read_operand16() */ + if (cpu_mod != 3) + do_cycles_i(2); /* load_operand() */ + tempw = cpu_state.pc; + geteaw(); + /* fpu_op() */ + 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; + } + } + } + cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on + the 286+ core, but not here. */ + break; + + case 0xe0: /* LOOPNE & LOOPE */ + case 0xe1: + /* decrement_register16() */ + --CX; + do_cycles_i(2); + + zero_cond = !(cpu_state.flags & Z_FLAG); + if (opcode == 0xe1) + zero_cond = !zero_cond; + + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + + if ((CX != 0x0000) && zero_cond) { + rel8 = (int8_t) cpu_data; + new_ip = (cpu_state.pc + rel8) & 0xffff; + reljmp(new_ip, 1); + jump = 1; + do_print = 0; + } else { + do_cycle_i(); + do_print = 1; + } + break; + + case 0xe2: /* LOOP */ + /* decrement_register16() */ + --CX; + do_cycles_i(2); + + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + + if (CX != 0x0000) { + rel8 = (int8_t) cpu_data; + new_ip = (cpu_state.pc + rel8) & 0xffff; + reljmp(new_ip, 1); + jump = 1; + do_print = 0; + } + if (!jump) { + do_cycle(); + do_print = 1; + } + break; + + case 0xe3: /* JCXZ */ + do_cycles_i(2); + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + + do_cycle_i(); + + if (CX == 0x0000) { + rel8 = (int8_t) cpu_data; + new_ip = (cpu_state.pc + rel8) & 0xffff; + reljmp(new_ip, 1); + jump = 1; + } else + do_cycle_i(); + break; + + case 0xe4: /* IN al, imm8 */ + bits = 8; + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + do_cycles_i(2); + + /* biu_io_read_u8() */ + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 0, cpu_state.eaaddr); + /* set_register8() */ + break; + + case 0xe5: /* IN ax, imm8 */ + bits = 16; + /* read_operand16() */ + cpu_data = biu_pfq_fetchb(); + do_cycles_i(2); + + /* biu_io_read_u16() */ + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 0, cpu_state.eaaddr); + /* set_register16() */ + break; + + case 0xe6: /* OUT imm8, al */ + bits = 8; + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + /* read_operand8() */ + tempb = AL; + do_cycles_i(2); + + /* biu_io_write_u8() */ + cpu_state.eaaddr = cpu_data; + cpu_data = tempb; + cpu_io_vx0(bits, 1, cpu_state.eaaddr); + break; + + case 0xe7: /* OUT imm8, ax */ + bits = 16; + /* read_operand8() */ + cpu_data = biu_pfq_fetchb(); + /* read_operand16() */ + tempw = AX; + do_cycles_i(2); + + /* biu_io_write_u16() */ + cpu_state.eaaddr = cpu_data; + cpu_data = tempw; + cpu_io_vx0(bits, 1, cpu_state.eaaddr); + break; + + case 0xe8: /* CALL rel16 */ + /* read_operand16() */ + rel16 = (int16_t) biu_pfq_fetchw(); + + biu_suspend_fetch(); + do_cycles_i(4); + + old_ip = cpu_state.pc; + new_ip = cpu_state.pc + rel16; + + set_ip(new_ip); + biu_queue_flush(); + do_cycles_i(3); + + push(&old_ip); + jump = 1; + break; + + case 0xe9: /* JMP rel16 */ + /* read_operand16() */ + rel16 = (int16_t) biu_pfq_fetchw(); + new_ip = (cpu_state.pc + rel16) & 0xffff; + + reljmp(new_ip, 1); + jump = 1; + break; + + case 0xea: /* JMP far [addr16:16] */ + /* read_operand_faraddr() */ + addr = biu_pfq_fetchw(); + tempw = biu_pfq_fetchw(); + load_cs(tempw); + set_ip(addr); + + biu_suspend_fetch(); + do_cycles_i(2); + biu_queue_flush(); + do_cycle_i(); + jump = 1; + break; + + case 0xeb: /* JMP rel8 */ + /* read_operand8() */ + rel8 = (int8_t) biu_pfq_fetchb(); + new_ip = (cpu_state.pc + rel8) & 0xffff; + + reljmp(new_ip, 1); + jump = 1; + break; + + case 0xec: /* IN al, dx */ + bits = 8; + /* read_operand8() */ + cpu_data = DX; + /* biu_io_read_u8() */ + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 0, cpu_state.eaaddr); + /* set_register8() */ + break; + + case 0xed: /* IN ax, dx */ + bits = 16; + /* read_operand16() */ + cpu_data = DX; + /* biu_io_read_u16() */ + cpu_state.eaaddr = cpu_data; + cpu_io_vx0(bits, 0, cpu_state.eaaddr); + /* set_register16() */ + break; + + case 0xee: /* OUT dx, al */ + bits = 8; + /* read_operand8() */ + cpu_data = DX; + /* read_operand8() */ + tempb = AL; + do_cycle_i(); + + /* biu_io_write_u8() */ + cpu_state.eaaddr = cpu_data; + cpu_data = tempb; + cpu_io_vx0(bits, 1, cpu_state.eaaddr); + break; + + case 0xef: /* OUT dx, ax */ + bits = 16; + /* read_operand8() */ + cpu_data = DX; + /* read_operand16() */ + tempw = AX; + do_cycle_i(); + + /* biu_io_write_u16() */ + cpu_state.eaaddr = cpu_data; + cpu_data = tempw; + cpu_io_vx0(bits, 1, cpu_state.eaaddr); + break; + + case 0xf0: + case 0xf1: /* LOCK - F1 is alias */ + break; + + case 0xf2: /* REPNE */ + case 0xf3: /* REPE */ + break; + + case 0xf4: /* HLT */ + if (is_nec) + in_hlt = 1; + + if (!repeating) { + biu_suspend_fetch(); + // biu_queue_flush(); + do_cycles(2); + /* TODO: biu_halt(); */ + do_cycle(); + } + + do_cycle_i(); + do_cycle_i(); + do_cycle_i(); + if (irq_pending()) { + halted = 0; + check_interrupts(); + } else { + repeating = 1; + completed = 0; + + halted = 1; + } + + if (is_nec) + in_hlt = 0; + break; + + case 0xf5: /* CMC */ + cpu_state.flags ^= C_FLAG; + break; + + case 0xf6: /* Miscellaneuous Opcode Extensions, r/m8, imm8 */ + bits = 8; + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + negate = !!in_rep; + + if (is_nec && ((rmdat & 0x38) >= 0x20)) switch (rmdat & 0x38) { + case 0x20: /* MUL */ + /* read_operand8() */ + cpu_data = get_ea(); + + AX = AL * cpu_data; + if (AH) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + do_cycles((cpu_mod == 3) ? 24 : 30); + break; + case 0x28: /* IMUL */ + /* read_operand8() */ + cpu_data = get_ea(); + + tempws = (int) ((int8_t) AL) * (int) ((int8_t) cpu_data); + AX = tempws & 0xffff; + if (((int16_t) AX >> 7) != 0 && ((int16_t) AX >> 7) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + do_cycles((cpu_mod == 3) ? 13 : 19); + break; + case 0x30: /* DIV */ + /* read_operand8() */ + cpu_data = get_ea(); + + src16 = AX; + if (cpu_data) + tempw = src16 / cpu_data; + if (cpu_data && !(tempw & 0xff00)) { + AH = src16 % cpu_data; + AL = (src16 / cpu_data) & 0xff; + cpu_state.flags |= 0x8D5; + cpu_state.flags &= ~1; + } else { + intr_routine(0, 0); + break; + } + + do_cycles((cpu_mod == 3) ? 21 : 27); + break; + case 0x38: /* IDIV */ + /* read_operand8() */ + cpu_data = get_ea(); + + tempws = (int) (int16_t) AX; + if (cpu_data != 0) + tempws2 = tempws / (int) ((int8_t) cpu_data); + temps = tempws2 & 0xff; + if (cpu_data && ((int) temps == tempws2)) { + AH = (tempws % (int) ((int8_t) cpu_data)) & 0xff; + AL = tempws2 & 0xff; + cpu_state.flags |= 0x8D5; + cpu_state.flags &= ~1; + } else { + intr_routine(0, 0); + break; + } + + do_cycles((cpu_mod == 3) ? 11 : 17); + break; + } else switch (rmdat & 0x38) { + case 0x00: /* TEST */ + case 0x08: + /* read_operand8() */ + cpu_data = get_ea(); + /* read_operand8() */ + cpu_src = biu_pfq_fetch(); + + do_cycles_i(is_nec ? 1 : 2); + + /* math_op8() */ + test(bits, cpu_data, cpu_src); + break; + case 0x10: /* NOT */ + case 0x18: /* NEG */ + /* read_operand8() */ + cpu_data = get_ea(); + /* math_op8() */ + if ((rmdat & 0x38) == 0x10) + cpu_data = ~cpu_data; + else { + cpu_src = cpu_data; + cpu_dest = 0; + sub(bits); + } + + if (cpu_mod != 3) + do_cycles_i(2); + + /* write_operand8() */ + set_ea(cpu_data); + break; + + case 0x20: /* MUL */ + case 0x28: /* IMUL */ + /* read_operand8() */ + cpu_data = get_ea(); + + /* mul8() */ + old_flags = cpu_state.flags; + mul(get_accum(bits), cpu_data); + prod16 = ((cpu_dest & 0xff) << 8) | (cpu_data & 0xff); + if (negate) + prod16 = -prod16; + cpu_dest = prod16 >> 8; + cpu_data = prod16 & 0xff; + AL = (uint8_t) cpu_data; + AH = (uint8_t) cpu_dest; + set_co_mul(bits, AH != ((AL & 0x80) == 0 || + (rmdat & 0x38) == 0x20 ? 0 : 0xff)); + if (!is_nec) + cpu_data = AH; + set_sf(bits); + set_pf(); + /* NOTE: When implementing the V20, care should be taken to not change + the zero flag. */ + if (is_nec) + cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG); + break; + + case 0x30: /* DIV */ + case 0x38: /* IDIV */ + /* read_operand8() */ + cpu_data = get_ea(); + + cpu_src = cpu_data; + if (x86_div(AL, AH)) { + if (!is_nec && negate) + AL = -AL; + do_cycle(); + } + break; + } + break; + + case 0xf7: /* Miscellaneuous Opcode Extensions, r/m16, imm16 */ + bits = 16; + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + negate = !!in_rep; + + if (is_nec && ((rmdat & 0x38) >= 0x20)) switch (rmdat & 0x38) { + case 0x20: /* MUL */ + /* read_operand16() */ + cpu_data = get_ea(); + + templ = AX * cpu_data; + AX = templ & 0xFFFF; + DX = templ >> 16; + if (DX) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + do_cycles((cpu_mod == 3) ? 29 : 35); + break; + case 0x28: /* IMUL */ + /* read_operand16() */ + cpu_data = get_ea(); + + templ = (int) ((int16_t) AX) * (int) ((int16_t) cpu_data); + AX = templ & 0xFFFF; + DX = templ >> 16; + if (((int32_t) templ >> 15) != 0 && ((int32_t) templ >> 15) != -1) + cpu_state.flags |= (C_FLAG | V_FLAG); + else + cpu_state.flags &= ~(C_FLAG | V_FLAG); + + do_cycles((cpu_mod == 3) ? 17 : 27); + break; + case 0x30: /* DIV */ + /* read_operand16() */ + cpu_data = get_ea(); + + templ = (DX << 16) | AX; + if (cpu_data) + templ2 = templ / cpu_data; + if (cpu_data && !(templ2 & 0xffff0000)) { + DX = templ % cpu_data; + AX = (templ / cpu_data) & 0xffff; + cpu_data = AX; + set_pzs(16); + } else { + intr_routine(0, 0); + break; + } + + do_cycles((cpu_mod == 3) ? 26 : 36); + break; + case 0x38: /* IDIV */ + /* read_operand16() */ + cpu_data = get_ea(); + + tempws = (int) ((DX << 16) | AX); + if (cpu_data) + tempws2 = tempws / (int) ((int16_t) cpu_data); + temps16 = tempws2 & 0xffff; + if ((cpu_data != 0) && ((int) temps16 == tempws2)) { + DX = tempws % (int) ((int16_t) cpu_data); + AX = tempws2 & 0xffff; + cpu_data = AX; + set_pzs(16); + } else { + intr_routine(0, 0); + break; + } + + do_cycles((cpu_mod == 3) ? 13 : 23); + break; + } else switch (rmdat & 0x38) { + case 0x00: /* TEST */ + case 0x08: + /* read_operand16() */ + cpu_data = get_ea(); + /* read_operand16() */ + cpu_src = biu_pfq_fetch(); + + do_cycle_i(); + + /* math_op16() */ + test(bits, cpu_data, cpu_src); + break; + case 0x10: /* NOT */ + case 0x18: /* NEG */ + /* read_operand16() */ + cpu_data = get_ea(); + /* math_op16() */ + if ((rmdat & 0x38) == 0x10) + cpu_data = ~cpu_data; + else { + cpu_src = cpu_data; + cpu_dest = 0; + sub(bits); + } + + if (cpu_mod != 3) + do_cycles_i(2); + + /* write_operand16() */ + set_ea(cpu_data); + break; + + case 0x20: /* MUL */ + case 0x28: /* IMUL */ + /* read_operand16() */ + cpu_data = get_ea(); + + /* mul8() */ + old_flags = cpu_state.flags; + mul(get_accum(bits), cpu_data); + prod32 = (((uint32_t) cpu_dest) << 16) | cpu_data; + if (negate) + prod32 = -prod32; + cpu_dest = prod32 >> 16; + cpu_data = prod32 & 0xffff; + AX = cpu_data; + DX = cpu_dest; + set_co_mul(bits, DX != ((AX & 0x8000) == 0 || + (rmdat & 0x38) == 0x20 ? 0 : 0xffff)); + cpu_data = DX; + set_sf(bits); + set_pf(); + /* NOTE: When implementing the V20, care should be taken to not change + the zero flag. */ + if (is_nec) + cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG); + break; + + case 0x30: /* DIV */ + case 0x38: /* IDIV */ + /* read_operand16() */ + cpu_data = get_ea(); + + cpu_src = cpu_data; + if (x86_div(AX, DX)) { + if (!is_nec && negate) + AX = -AX; + do_cycle(); + } + break; + } + break; + + case 0xf8: /* CLCSTC */ + case 0xf9: + set_cf(opcode & 1); + break; + + case 0xfa: /* CLISTI */ + case 0xfb: + set_if(opcode & 1); + break; + + case 0xfc: /* CLDSTD */ + case 0xfd: + set_df(opcode & 1); + break; + + case 0xfe: + bits = 8; + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); + switch (rmdat & 0x38) { + case 0x00: /* INC rm */ + case 0x08: /* DEC rm */ + /* read_operand8() */ + /* math_op8() */ + 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); + + if (cpu_mod != 3) + do_cycles_i(2); + /* write_operand8() */ + set_ea(cpu_data); + break; + case 0x10: /* CALL rm */ + /* read_operand8() */ + cpu_data_opff_rm(); + + cpu_state.oldpc = cpu_state.pc; + push((uint16_t *) &(cpu_state.oldpc)); + + biu_suspend_fetch(); + do_cycles(4); + biu_queue_flush(); + + set_ip(cpu_data | 0xff00); + break; + case 0x18: /* CALL rmd */ + if (cpu_mod == 3) { + /* biu_read_u8() */ + cpu_state.eaaddr = 0x0004; + tempb = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + + old_cs = CS & 0x00ff; + push(&old_cs); + old_ip = cpu_state.pc & 0x00ff; + push(&old_ip); + + biu_suspend_fetch(); + do_cycles(4); + biu_queue_flush(); + + read_ea_8to16(); + set_ip(cpu_data); + } else { + /* read_operand8() */ + new_ip = cpu_data | 0xff00; + + do_cycles_i(3); + + /* biu_read_u8() */ + read_ea2(bits); + cpu_data |= 0xff00; + new_cs = cpu_data; + + do_cycle_i(); + biu_suspend_fetch(); + do_cycles_i(3); + + old_cs = CS & 0x00ff; + push(&old_cs); + old_ip = cpu_state.pc & 0x00ff; + + load_cs(new_cs); + set_ip(new_ip); + + do_cycles_i(3); + biu_queue_flush(); + do_cycles_i(3); + + push(&old_ip); + } + break; + case 0x20: /* JMP rm */ + /* read_operand8() */ + cpu_data_opff_rm(); + + set_ip(cpu_data | 0xff00); + + biu_suspend_fetch(); + do_cycles(4); + biu_queue_flush(); + break; + case 0x28: /* JMP rmd */ + if (cpu_mod == 3) { + /* biu_read_u8() */ + cpu_state.eaaddr = 0x0004; + tempb = readmemb((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + + biu_suspend_fetch(); + do_cycles(4); + biu_queue_flush(); + + read_ea_8to16(); + set_ip(cpu_data); + } else { + /* read_operand8() */ + new_ip = cpu_data | 0xff00; + + /* biu_read_u8() */ + read_ea2(bits); + cpu_data |= 0xff00; + new_cs = cpu_data; + + biu_suspend_fetch(); + do_cycles(4); + biu_queue_flush(); + + load_cs(new_cs); + set_ip(new_ip); + } + break; + case 0x30: /* PUSH rm */ + case 0x38: + /* read_operand8() */ + do_cycles_i(3); + cpu_data &= 0x00ff; + push((uint16_t *) &cpu_data); + break; + } + break; + + case 0xff: + bits = 16; + if (cpu_mod != 3) + do_cycles_i(is_nec ? 1 : 2); /* load_operand() */ + read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); + switch (rmdat & 0x38) { + case 0x00: /* INC rm */ + case 0x08: /* DEC rm */ + /* read_operand16() */ + /* math_op16() */ + 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); + if (cpu_mod != 3) + do_cycles_i(2); + /* write_operand16() */ + set_ea(cpu_data); + break; + case 0x10: /* CALL rm */ + /* read_operand16() */ + cpu_data_opff_rm(); + + biu_suspend_fetch(); + do_cycles(4); + + cpu_state.oldpc = cpu_state.pc; + + old_ip = cpu_state.pc; + set_ip(cpu_data); + biu_queue_flush(); + do_cycles_i(3); + + push(&old_ip); + break; + case 0x18: /* CALL rmd */ + if (cpu_mod == 3) { + new_ip = cpu_data; + + /* biu_read_u16() */ + cpu_state.eaaddr = 0x0004; + new_cs = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + + do_cycle_i(); + biu_suspend_fetch(); + do_cycles_i(3); + + push(&CS); + old_ip = cpu_state.pc; + set_ip(new_ip); + + load_cs(new_cs); + + do_cycles_i(3); + biu_queue_flush(); + do_cycles_i(3); + + push(&old_ip); + } else { + do_cycle_i(); + /* read_operand_farptr() */ + new_ip = cpu_data; + read_ea2(bits); + new_cs = cpu_data; + + do_cycle_i(); + + biu_suspend_fetch(); + do_cycles_i(3); + + push(&CS); + + load_cs(new_cs); + old_ip = cpu_state.pc; + set_ip(new_ip); + do_cycles_i(3); + biu_queue_flush(); + do_cycles_i(3); + push(&old_ip); + } + break; + case 0x20: /* JMP rm */ + /* read_operand16() */ + cpu_data_opff_rm(); + + biu_suspend_fetch(); + do_cycle_i(); + set_ip(cpu_data); + biu_queue_flush(); + break; + case 0x28: /* JMP rmd */ + if (cpu_mod == 3) { + new_ip = cpu_data; + + do_cycle(); + biu_suspend_fetch(); + do_cycle(); + + /* biu_read_u16() */ + cpu_state.eaaddr = 0x0004; + new_cs = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); + + push(&CS); + biu_queue_flush(); + } else { + do_cycle_i(); + biu_suspend_fetch(); + do_cycle_i(); + + /* read_operand_farptr() */ + new_ip = cpu_data; + read_ea2(bits); + new_cs = cpu_data; + + load_cs(new_cs); + set_ip(new_ip); + biu_queue_flush(); + } + break; + case 0x30: /* PUSH rm */ + case 0x38: + /* read_operand16() */ + do_cycles_i(3); + + if (cpu_rm == 4) + cpu_rm -= 2; + push((uint16_t *) &cpu_data); + break; + } + break; + + default: + x808x_log("Illegal opcode: %02X\n", opcode); + biu_pfq_fetchb(); + do_cycles(8); + break; + } +} + +/* Executes instructions up to the specified number of cycles. */ +void +execvx0(int cycs) +{ + cycles += cycs; + + while (cycles > 0) { + if (started) { + started = 0; + startx86(); + } + + if (!repeating) { + cpu_state.oldpc = cpu_state.pc; + + if (clear_lock) { + in_lock = 0; + clear_lock = 0; + } + + if (!is_nec || (cpu_state.flags & MD_FLAG)) + decode(); + + oldc = cpu_state.flags & C_FLAG; + } + + x808x_log("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + + execute_instruction(); + + if (completed) { + if (opcode != 0xf4) + finalize(); + + check_interrupts(); + + if (noint) + noint = 0; + } + +#ifdef USE_GDBSTUB + if (gdbstub_instruction()) + return; +#endif + } +} diff --git a/src/cpu/vx0_biu.c b/src/cpu/vx0_biu.c new file mode 100644 index 000000000..b52b14245 --- /dev/null +++ b/src/cpu/vx0_biu.c @@ -0,0 +1,1152 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 808x BIU emulation. + * + * Authors: Andrew Jenner, + * Miran Grca, + * + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include "x86.h" +#include <86box/machine.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/nmi.h> +#include <86box/pic.h> +#include <86box/ppi.h> +#include <86box/timer.h> +#include <86box/gdbstub.h> +#include <86box/plat_fallthrough.h> +#include <86box/plat_unused.h> +#include "vx0_biu.h" + +#define do_cycle() wait(1) +#define do_cycle_i() do_cycle() + +uint8_t biu_preload_byte = 0x00; + +int bus_request_type = 0; + +int pic_data = -1; +int biu_queue_preload = 0; + +/* The IP equivalent of the current prefetch queue position. */ +static uint16_t pfq_ip = 0x0000; +static uint16_t pfq_in = 0x0000; + +/* Variables to aid with the prefetch queue operation. */ +static int pfq_size = 0; + +static int cycles_ex = 0; + +/* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ +static uint8_t pfq[6]; + +static int biu_cycles = 0; +static int biu_wait = 0; +static int biu_wait_length = 0; +static int refresh = 0; +static uint16_t mem_data = 0; +static uint32_t mem_seg = 0; +static uint16_t mem_addr = 0; +static int biu_state = 0; +static int biu_next_state = 0; +static int biu_scheduled_state = 0; +static int biu_state_length = 0; +static int biu_state_total_len = 0; +static int dma_state = 0; +static int dma_state_length = 0; +static int wait_states = 0; +static int fetch_suspended = 0; +static int ready = 1; +static int dma_wait_states = 0; + +#define BUS_CYCLE (biu_cycles & 3) +#define BUS_CYCLE_T1 biu_cycles = 0 +#define BUS_CYCLE_NEXT biu_cycles = (biu_cycles + 1) & 3 + +/* DEBUG stuff. */ +const char *lpBiuStates[7] = { "Ti ", "Ti S ", "Ti D ", "Ti R ", "Tw ", "T%i PF", "T%i EU" }; + +#ifdef ENABLE_808X_BIU_LOG +int x808x_biu_do_log = ENABLE_808X_BIU_LOG; + +static void +x808x_biu_log(const char *fmt, ...) +{ + va_list ap; + + if (x808x_biu_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define x808x_biu_log(fmt, ...) +#endif + +void +biu_set_bus_cycle(int bus_cycle) +{ + biu_cycles = bus_cycle; +} + +void +biu_set_bus_state(int bus_state) +{ + biu_state = bus_state; +} + +void +biu_set_bus_next_state(int bus_next_state) +{ + biu_state = bus_next_state; +} + +void +biu_set_cycle_t1(void) +{ + BUS_CYCLE_T1; +} + +void +biu_set_next_cycle(void) +{ + BUS_CYCLE_NEXT; +} + +int +biu_get_bus_cycle(void) +{ + return BUS_CYCLE; +} + +int +biu_get_bus_state(void) +{ + return biu_state; +} + +int +biu_get_bus_next_state(void) +{ + return biu_next_state; +} + +static void pfq_add(void); + +static void +pfq_resume(int delay) +{ + if (is_nec) + biu_state = BIU_STATE_PF; + else { + biu_state = BIU_STATE_RESUME; + biu_state_length = delay; + biu_state_total_len = delay; + } +} + +static void +pfq_switch_to_pf(int delay) +{ + if (is_nec) + biu_next_state = BIU_STATE_PF; + else { + biu_next_state = BIU_STATE_RESUME; + biu_state_length = delay; + biu_state_total_len = delay; + } +} + +static uint8_t +biu_queue_delay(void) +{ + if (is8086) + return pfq_pos == 4; + else + return pfq_pos == 3; +} + +static void +pfq_schedule(void) +{ + if (biu_state == BIU_STATE_EU) { + if (!is_nec && biu_queue_delay()) { + biu_next_state = BIU_STATE_DELAY; + biu_state_length = 3; + biu_state_total_len = 3; + } else if ((is_nec || !fetch_suspended) && (pfq_pos < 4)) + biu_next_state = BIU_STATE_PF; + else + biu_next_state = BIU_STATE_IDLE; + } else { + if (!is_nec && biu_queue_delay()) { + biu_next_state = BIU_STATE_DELAY; + biu_state_length = 3; + biu_state_total_len = 3; + } else + biu_next_state = BIU_STATE_PF; + } +} + +void +biu_reset(void) +{ + BUS_CYCLE_T1; + biu_cycles = 0; + biu_wait = 0; + refresh = 0; + bus_request_type = 0; + biu_queue_preload = 0; + pic_data = -1; + mem_data = 0; + mem_seg = 0; + mem_addr = 0; + wait_states = 0; + dma_state = DMA_STATE_IDLE; + dma_state_length = 0; + biu_state = BIU_STATE_IDLE; + biu_next_state = BIU_STATE_IDLE; + biu_scheduled_state = BIU_STATE_IDLE; + biu_state_length = 0; + pfq_size = is8086 ? 6 : 4; + pfq_in = 0x0000; +} + +static void +process_timers(void) +{ + /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ + tsc += ((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, (uint64_t) tsc)) + timer_process(); +} + +static void +cycles_forward(int c) +{ + for (int i = 0; i < c; i++) { + cycles--; + if (!is286) + process_timers(); + } + + cycles_ex++; +} + +static void +bus_outb(uint16_t port, uint8_t val) +{ + outb(port, val); +} + +static void +bus_outw(uint16_t port, uint16_t val) +{ + outw(port, val); +} + +static uint8_t +bus_inb(uint16_t port) +{ + uint8_t ret; + + ret = inb(port); + + return ret; +} + +static uint16_t +bus_inw(uint16_t port) +{ + uint16_t ret; + + ret = inw(port); + + return ret; +} + +static void +bus_do_io(int io_type) +{ + int old_cycles = cycles; + + x808x_biu_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); + } + + resub_cycles(old_cycles); +} + +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) +{ + int old_cycles = cycles; + + 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)); + } + + resub_cycles(old_cycles); +} + +static void +biu_print_cycle(void) +{ + if ((CS == DEBUG_SEG) && (cpu_state.pc >= DEBUG_OFF_L) && (cpu_state.pc <= DEBUG_OFF_H)) { + if (biu_state >= BIU_STATE_PF) { + if (biu_wait) { + x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s (%i)\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[BIU_STATE_WAIT], wait_states); + } else { + char temp[16] = { 0 }; + + sprintf(temp, lpBiuStates[biu_state], biu_cycles + 1); + x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, temp); + } + } else { + x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[biu_state]); + } + } +} + +static void +do_wait(void) +{ + if (wait_states > 0) + wait_states--; + + if (dma_wait_states > 0) + dma_wait_states--; +} + +static void +run_dma_cycle(void) +{ + int bus_cycle_check = ((biu_state < BIU_STATE_PF) || (BUS_CYCLE == BUS_T3) || + (BUS_CYCLE == BUS_T4) || biu_wait) && !in_lock; + + switch (dma_state) { + case DMA_STATE_TIMER: + dma_state = DMA_STATE_DREQ; + dma_state_length = 1; + break; + case DMA_STATE_DREQ: + dma_state = DMA_STATE_HRQ; + dma_state_length = 1; + break; + case DMA_STATE_HRQ: + if (!in_lock && bus_cycle_check) { + dma_state = DMA_STATE_HLDA; + dma_state_length = 1; + } + break; + case DMA_STATE_HLDA: + dma_state = DMA_STATE_OPERATING; + dma_state_length = 4; + break; + case DMA_STATE_OPERATING: + dma_state_length--; + if (dma_state_length == 3) { + dma_wait_states = 7; + ready = 0; + } else if (dma_state_length == 0) { + dma_state = DMA_STATE_IDLE; + dma_state_length = 1; + } + break; + } +} + +static void +biu_cycle_idle(int type) +{ + if ((CS == DEBUG_SEG) && (cpu_state.pc >= DEBUG_OFF_L) && (cpu_state.pc <= DEBUG_OFF_H)) { + x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[type]); + } + + run_dma_cycle(); + cycles_forward(1); + + do_wait(); +} + +/* Reads a byte from the memory but does not advance the BIU. */ +static uint8_t +readmembf(uint32_t a) +{ + uint8_t ret; + + a = cs + (a & 0xffff); + ret = read_mem_b(a); + + return ret; +} + +static uint16_t +readmemwf(uint16_t a) +{ + uint16_t ret; + + ret = read_mem_w(cs + (a & 0xffff)); + + return ret; +} + +static void +do_bus_access(void) +{ + int io_type = (biu_state == BIU_STATE_EU) ? bus_request_type : BUS_CODE; + + x808x_biu_log("[%04X:%04X] %02X bus access %02X\n", CS, cpu_state.pc, opcode, io_type); + + if (io_type != 0) { + wait_states = 0; + switch (io_type & BUS_ACCESS_TYPE) { + case BUS_CODE: + if (is8086) + pfq_in = readmemwf(pfq_ip); + else + pfq_in = readmembf(pfq_ip); + break; + case BUS_IO: + bus_do_io(io_type); + break; + case BUS_MEM: + bus_do_mem(io_type); + break; + case BUS_PIC: + pic_data = pic_irq_ack(); + break; + default: + break; + } + } +} + +void +resub_cycles(int old_cycles) +{ + if (old_cycles > cycles) + wait_states = old_cycles - cycles; + + cycles = old_cycles; +} + +static uint8_t +biu_queue_has_room(void) +{ + if (is8086) + return pfq_pos < 5; + else + return pfq_pos < 4; +} + +static int bus_access_done = 0; + +static void +biu_do_cycle(void) +{ + int biu_old_state = biu_state; + + biu_print_cycle(); + + switch (biu_state) { + default: + fatal("Invalid BIU state: %02X\n", biu_state); + break; + case BIU_STATE_RESUME: + if (biu_state_length > 0) { + biu_state_length--; + if (biu_state_length == 0) { + biu_state = BIU_STATE_PF; + biu_next_state = BIU_STATE_PF; + } + } else { + biu_state = BIU_STATE_PF; + biu_next_state = BIU_STATE_PF; + } + break; + case BIU_STATE_IDLE: + case BIU_STATE_SUSP: + biu_state = biu_next_state; + break; + case BIU_STATE_DELAY: + if (biu_state_length > 0) { + biu_state_length--; + if (biu_state_length == 0) { + if (biu_queue_has_room()) { + biu_state = BIU_STATE_PF; + biu_next_state = BIU_STATE_PF; + } else { + biu_state = BIU_STATE_IDLE; + biu_next_state = BIU_STATE_IDLE; + } + } + } else { + if (biu_queue_has_room()) { + biu_state = BIU_STATE_PF; + biu_next_state = BIU_STATE_PF; + } else { + biu_state = BIU_STATE_IDLE; + biu_next_state = BIU_STATE_IDLE; + } + } + break; + case BIU_STATE_PF: + case BIU_STATE_EU: + if (biu_wait) { + if ((wait_states == 0) && (dma_wait_states == 0)) { + biu_wait = 0; + BUS_CYCLE_NEXT; + } + } else { + if (BUS_CYCLE == BUS_T4) { + if (biu_state == BIU_STATE_PF) + pfq_add(); + biu_state = biu_next_state; + } + + if ((BUS_CYCLE == BUS_T3) && (biu_state == BIU_STATE_EU)) { + if ((bus_request_type != 0) && ((bus_request_type & BUS_ACCESS_TYPE) == BUS_IO)) + wait_states++; + } + + if ((BUS_CYCLE == BUS_T3) && ((wait_states != 0) || (dma_wait_states != 0))) + biu_wait = 1; + else { + biu_wait = 0; + BUS_CYCLE_NEXT; + } + + if ((BUS_CYCLE == BUS_T1) && (biu_state == BIU_STATE_IDLE) && biu_queue_delay()) { + if (biu_old_state == BIU_STATE_EU) + pfq_resume(2); + else + biu_state = BIU_STATE_PF; + } + } + + if (bus_access_done && !biu_wait) + bus_access_done = 0; + break; + } +} + +static int +biu_is_last_tw(void) +{ + return ((biu_state >= BIU_STATE_PF) && biu_wait && ((wait_states + dma_wait_states) == 1)); +} + +static void +biu_cycle(void) +{ + if (biu_state >= BIU_STATE_PF) { + if (BUS_CYCLE == BUS_T2) + pfq_schedule(); + else if (((BUS_CYCLE == BUS_T3) && !biu_wait) || biu_is_last_tw()) { + if (!bus_access_done) { + do_bus_access(); + bus_access_done = 1; + } + } + } + + run_dma_cycle(); + + biu_do_cycle(); + + cycles_forward(1); + + do_wait(); +} + +static void +biu_eu_request(void) +{ + switch (biu_state) { + default: + fatal("Invalid BIU state: %02X\n", biu_state); + break; + case BIU_STATE_RESUME: + /* Resume it - leftover cycles. */ + if (!is_nec) for (uint8_t i = 0; i < (biu_state_total_len - biu_state_length); i++) + biu_cycle_idle(biu_state); + break; + case BIU_STATE_IDLE: + case BIU_STATE_SUSP: + /* Resume it - 3 cycles. */ + if (!is_nec) for (uint8_t i = 0; i < 3; i++) + biu_cycle_idle(biu_state); + break; + case BIU_STATE_DELAY: + case BIU_STATE_EU: + /* Do the request immediately (needs hardware testing). */ + biu_state_length = 0; + break; + case BIU_STATE_PF: + /* Transition the state. */ + switch (BUS_CYCLE) { + case BUS_T1: + case BUS_T2: + /* Leftover BIU cycles. */ + do + biu_cycle(); + while (BUS_CYCLE != BUS_T1); + break; + case BUS_T3: + case BUS_T4: + /* Leftover BIU cycles. */ + do + biu_cycle(); + while (BUS_CYCLE != BUS_T1); + /* The two abort cycles. */ + if (!is_nec) for (uint8_t i = 0; i < 2; i++) + biu_cycle_idle(BIU_STATE_IDLE); + break; + + default: + break; + } + break; + } + + biu_state = BIU_STATE_EU; + biu_next_state = BIU_STATE_EU; + + biu_state_length = 0; +} + +void +wait(int c) +{ + x808x_biu_log("[%04X:%04X] %02X %i cycles\n", CS, cpu_state.pc, opcode, c); + + for (uint8_t i = 0; i < c; i++) + biu_cycle(); +} + +/* This is for external subtraction of cycles, ie. wait states. */ +void +sub_cycles(int c) +{ + cycles -= c; +} + +void +biu_begin_eu(void) +{ + biu_eu_request(); +} + +static void +biu_wait_for_write_finish(void) +{ + while (BUS_CYCLE != BUS_T4) { + biu_cycle(); + if (biu_wait_length == 1) + break; + } +} + +void +biu_wait_for_read_finish(void) +{ + biu_wait_for_write_finish(); + biu_cycle(); +} + +void +cpu_io_vx0(int bits, int out, uint16_t port) +{ + /* Do this, otherwise, the first half of the operation never happens. */ + if ((BUS_CYCLE == BUS_T4) && (biu_state == BIU_STATE_EU)) + BUS_CYCLE_T1; + + if (out) { + if (bits == 16) { + if (is8086 && !(port & 1)) { + bus_request_type = BUS_IO | BUS_OUT | BUS_WIDE; + biu_begin_eu(); + biu_wait_for_write_finish(); + } else { + bus_request_type = BUS_IO | BUS_OUT; + biu_begin_eu(); + biu_wait_for_write_finish(); + biu_cycle(); + biu_state = BIU_STATE_EU; + biu_state_length = 0; + bus_request_type = BUS_IO | BUS_OUT | BUS_HIGH; + biu_wait_for_write_finish(); + } + } else { + bus_request_type = BUS_IO | BUS_OUT; + biu_begin_eu(); + biu_wait_for_write_finish(); + } + } else { + if (bits == 16) { + if (is8086 && !(port & 1)) { + bus_request_type = BUS_IO | BUS_WIDE; + biu_begin_eu(); + biu_wait_for_read_finish(); + } else { + bus_request_type = BUS_IO; + biu_begin_eu(); + biu_wait_for_read_finish(); + biu_state = BIU_STATE_EU; + biu_state_length = 0; + bus_request_type = BUS_IO | BUS_HIGH; + biu_wait_for_read_finish(); + } + } else { + bus_request_type = BUS_IO; + biu_begin_eu(); + biu_wait_for_read_finish(); + } + } + + bus_request_type = 0; +} + +void +biu_state_set_eu(void) +{ + biu_state = BIU_STATE_EU; + biu_state_length = 0; +} + +/* Reads a byte from the memory and advances the BIU. */ +uint8_t +readmemb_vx0(uint32_t s, uint16_t a) +{ + uint8_t ret; + + mem_seg = s; + mem_addr = a; + /* Do this, otherwise, the first half of the operation never happens. */ + if ((BUS_CYCLE == BUS_T4) && (biu_state == BIU_STATE_EU)) + BUS_CYCLE_T1; + bus_request_type = BUS_MEM; + biu_begin_eu(); + biu_wait_for_read_finish(); + ret = mem_data & 0xff; + bus_request_type = 0; + + return ret; +} + +/* Reads a word from the memory and advances the BIU. */ +uint16_t +readmemw_vx0(uint32_t s, uint16_t a) +{ + uint16_t ret; + + mem_seg = s; + mem_addr = a; + /* Do this, otherwise, the first half of the operation never happens. */ + if ((BUS_CYCLE == BUS_T4) && (biu_state == BIU_STATE_EU)) + BUS_CYCLE_T1; + if (is8086 && !(a & 1)) { + bus_request_type = BUS_MEM | BUS_WIDE; + biu_begin_eu(); + biu_wait_for_read_finish(); + } else { + bus_request_type = BUS_MEM | BUS_HIGH; + biu_begin_eu(); + biu_wait_for_read_finish(); + biu_state = BIU_STATE_EU; + biu_state_length = 0; + bus_request_type = BUS_MEM; + biu_wait_for_read_finish(); + } + ret = mem_data; + bus_request_type = 0; + + return ret; +} + +uint16_t +readmem_vx0(uint32_t s) +{ + if (opcode & 1) + return readmemw_vx0(s, cpu_state.eaaddr); + else + return (uint16_t) readmemb_vx0(s, cpu_state.eaaddr); +} + +uint32_t +readmeml_vx0(uint32_t s, uint16_t a) +{ + uint32_t temp; + + temp = (uint32_t) (readmemw_vx0(s, a + 2)) << 16; + temp |= readmemw_vx0(s, a); + + return temp; +} + +uint64_t +readmemq_vx0(uint32_t s, uint16_t a) +{ + uint64_t temp; + + temp = (uint64_t) (readmeml_vx0(s, a + 4)) << 32; + temp |= readmeml_vx0(s, a); + + return temp; +} + +/* Writes a byte to the memory and advances the BIU. */ +void +writememb_vx0(uint32_t s, uint32_t a, uint8_t v) +{ + uint32_t addr = s + a; + + mem_seg = s; + mem_addr = a; + mem_data = v; + /* Do this, otherwise, the first half of the operation never happens. */ + if ((BUS_CYCLE == BUS_T4) && (biu_state == BIU_STATE_EU)) + BUS_CYCLE_T1; + bus_request_type = BUS_MEM | BUS_OUT; + biu_begin_eu(); + biu_wait_for_write_finish(); + bus_request_type = 0; + + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; +} + +/* Writes a word to the memory and advances the BIU. */ +void +writememw_vx0(uint32_t s, uint32_t a, uint16_t v) +{ + uint32_t addr = s + a; + + mem_seg = s; + mem_addr = a; + mem_data = v; + /* Do this, otherwise, the first half of the operation never happens. */ + if ((BUS_CYCLE == BUS_T4) && (biu_state == BIU_STATE_EU)) + BUS_CYCLE_T1; + if (is8086 && !(a & 1)) { + bus_request_type = BUS_MEM | BUS_OUT | BUS_WIDE; + biu_begin_eu(); + biu_wait_for_write_finish(); + } else { + bus_request_type = BUS_MEM | BUS_OUT | BUS_HIGH; + biu_begin_eu(); + biu_wait_for_write_finish(); + biu_cycle(); + biu_state = BIU_STATE_EU; + biu_state_length = 0; + bus_request_type = BUS_MEM | BUS_OUT; + biu_wait_for_write_finish(); + } + bus_request_type = 0; + + if ((addr >= 0xf0000) && (addr <= 0xfffff)) + last_addr = addr & 0xffff; +} + +void +writemem_vx0(uint32_t s, uint16_t v) +{ + if (opcode & 1) + writememw_vx0(s, cpu_state.eaaddr, v); + else + writememb_vx0(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); +} + +void +writememl_vx0(uint32_t s, uint32_t a, uint32_t v) +{ + writememw_vx0(s, a, v & 0xffff); + writememw_vx0(s, a + 2, v >> 16); +} + +void +writememq_vx0(uint32_t s, uint32_t a, uint64_t v) +{ + writememl_vx0(s, a, v & 0xffffffff); + writememl_vx0(s, a + 4, v >> 32); +} + +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))) { + /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes + free in the queue. */ + tempw = pfq_in; + *(uint16_t *) &(pfq[pfq_pos]) = tempw; + pfq_ip = (pfq_ip + 2) & 0xffff; + pfq_pos += 2; + } else if (!fetch_word && (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. */ + if (pfq_pos >= 0) + pfq[pfq_pos] = pfq_in & 0xff; + pfq_ip = (pfq_ip + 1) & 0xffff; + pfq_pos++; + } + + if (pfq_pos >= pfq_size) + pfq_pos = pfq_size; +} + +uint8_t +biu_pfq_read(void) +{ + uint8_t temp; + + temp = pfq[0]; + for (int 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; +} + +void +biu_resume_on_queue_read(void) +{ + if ((biu_next_state == BIU_STATE_IDLE) && (pfq_pos == 3)) + // pfq_switch_to_pf(is_nec ? 0 : ((biu_state == BIU_STATE_IDLE) ? 3 : 0)); + pfq_switch_to_pf(is_nec ? 0 : 3); +} + +/* 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. */ +uint8_t +biu_pfq_fetchb_common(void) +{ + uint8_t temp; + + if (biu_queue_preload) { + if (nx) + nx = 0; + + biu_queue_preload = 0; + return biu_preload_byte; + } + + if (pfq_pos > 0) { + if (biu_state == BIU_STATE_DELAY) { + while (biu_state == BIU_STATE_DELAY) + biu_cycle(); + } + + temp = biu_pfq_read(); + biu_resume_on_queue_read(); + } else { + /* Fill the queue. */ + while (pfq_pos == 0) + biu_cycle(); + + /* Fetch. */ + temp = biu_pfq_read(); + } + + do_cycle(); + return temp; +} + +/* The timings are above. */ +uint8_t +biu_pfq_fetchb(void) +{ + uint8_t ret; + + ret = biu_pfq_fetchb_common(); + return ret; +} + +/* Fetches a word from the prefetch queue, or from memory if the queue has + been drained. */ +uint16_t +biu_pfq_fetchw(void) +{ + uint16_t temp; + + temp = biu_pfq_fetchb_common(); + temp |= (biu_pfq_fetchb_common() << 8); + + return temp; +} + +uint16_t +biu_pfq_fetch(void) +{ + if (opcode & 1) + return biu_pfq_fetchw(); + else + return (uint16_t) biu_pfq_fetchb(); +} + +/* Adds bytes to the prefetch queue based on the instruction's cycle count. */ +static void +pfq_add(void) +{ + if ((biu_state == BIU_STATE_PF) && (pfq_pos < pfq_size)) + pfq_write(); +} + +void +biu_update_pc(void) +{ + pfq_ip = cpu_state.pc; + biu_queue_preload = 0; +} + +/* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ +void +biu_queue_flush(void) +{ + pfq_pos = 0; + biu_update_pc(); + + fetch_suspended = 0; + + /* FLUSH command. */ + if ((biu_state == BIU_STATE_SUSP) || (biu_state == BIU_STATE_IDLE)) + pfq_resume(3); +} + +static void +biu_bus_wait_finish(void) +{ + while (BUS_CYCLE != BUS_T4) + biu_cycle(); +} + +void +biu_suspend_fetch(void) +{ + biu_state_length = 0; + fetch_suspended = 1; + + if (biu_state == BIU_STATE_PF) { + if (is_nec) + BUS_CYCLE_T1; + else { + biu_bus_wait_finish(); + biu_cycle(); + } + biu_state = BIU_STATE_IDLE; + biu_next_state = BIU_STATE_IDLE; + } else { + if (biu_state == BIU_STATE_EU) + BUS_CYCLE_T1; + biu_state = BIU_STATE_IDLE; + biu_next_state = BIU_STATE_IDLE; + } +} + +/* Memory refresh read - called by reads and writes on DMA channel 0. */ +void +refreshread(void) +{ + if (dma_state == DMA_STATE_IDLE) { + dma_state = DMA_STATE_TIMER; + dma_state_length = 1; + } +} diff --git a/src/cpu/vx0_biu.h b/src/cpu/vx0_biu.h new file mode 100644 index 000000000..58e2ae257 --- /dev/null +++ b/src/cpu/vx0_biu.h @@ -0,0 +1,116 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * 808x BIU emulation header. + * + * Authors: Andrew Jenner, + * Miran Grca, + * + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. + */ +#ifndef EMU_808X_BIU_H +#define EMU_808X_BIU_H + +#define DEBUG_SEG 0xf000 +// #define DEBUG_SEG 0x0f3c +// #define DEBUG_SEG 0x1e1f +// #define DEBUG_SEG 0xf000 +// #define DEBUG_SEG 0xc800 +// #define DEBUG_SEG 0x0070 +// #define DEBUG_SEG 0x0291 +// #define DEBUG_SEG 0xefff +// #define DEBUG_SEG 0x15a2 + +// #define DEBUG_OFF_L 0x2c3b +// #define DEBUG_OFF_L 0xe182 +// #define DEBUG_OFF_L 0xf000 +// #define DEBUG_OFF_H 0xefff +// #define DEBUG_OFF_L 0x0000 +// #define DEBUG_OFF_H 0xffff +#define DEBUG_OFF_L 0xf300 +#define DEBUG_OFF_H 0xf3ff + +#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) + +#undef readmemb +#undef readmemw +#undef readmeml +#undef readmemq + +enum { + BUS_T1 = 0, + BUS_T2, + BUS_T3, + BUS_T4 +}; + +enum { + BIU_STATE_IDLE, + BIU_STATE_SUSP, + BIU_STATE_DELAY, + BIU_STATE_RESUME, + BIU_STATE_WAIT, + BIU_STATE_PF, + BIU_STATE_EU +}; + +enum { + DMA_STATE_IDLE, + DMA_STATE_TIMER, + DMA_STATE_DREQ, + DMA_STATE_HRQ, + DMA_STATE_HLDA, + DMA_STATE_OPERATING +}; + +/* Temporary BIU externs - move to 808x_biu.h. */ +extern void biu_resume_on_queue_read(void); +extern void wait(int c); +extern void biu_reset(void); +extern void cpu_io_vx0(int bits, int out, uint16_t port); +extern void biu_state_set_eu(void); +extern uint8_t readmemb_vx0(uint32_t s, uint16_t a); +extern uint16_t readmemw_vx0(uint32_t s, uint16_t a); +extern uint16_t readmem_vx0(uint32_t s); +extern uint32_t readmeml_vx0(uint32_t s, uint16_t a); +extern uint64_t readmemq_vx0(uint32_t s, uint16_t a); +extern void writememb_vx0(uint32_t s, uint32_t a, uint8_t v); +extern void writememw_vx0(uint32_t s, uint32_t a, uint16_t v); +extern void writemem_vx0(uint32_t s, uint16_t v); +extern void writememl_vx0(uint32_t s, uint32_t a, uint32_t v); +extern void writememq_vx0(uint32_t s, uint32_t a, uint64_t v); +extern uint8_t biu_pfq_read(void); +extern uint8_t biu_pfq_fetchb_common(void); +extern uint8_t biu_pfq_fetchb(void); +extern uint16_t biu_pfq_fetchw(void); +extern uint16_t biu_pfq_fetch(void); +extern void biu_update_pc(void); +extern void biu_queue_flush(void); +extern void biu_suspend_fetch(void); +extern void biu_begin_eu(void); +extern void biu_wait_for_read_finish(void); + +extern uint8_t biu_preload_byte; + +extern int nx; + +extern int schedule_fetch; +extern int in_lock; +extern int bus_request_type; +extern int pic_data; +extern int biu_queue_preload; + +#endif /*EMU_808X_BIU_H*/ diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 38e50a488..a19ac440a 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -367,8 +367,12 @@ reset_common(int hard) } else device_reset_all(DEVICE_SOFTRESET); - if (!is286) - reset_808x(hard); + if (!is286) { + if (is_nec) + reset_vx0(hard); + else + reset_808x(hard); + } in_lock = 0; diff --git a/src/cpu/x86.h b/src/cpu/x86.h index ccfeadea0..c0140520f 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -37,6 +37,7 @@ extern uint8_t opcode; extern uint8_t flags_p; extern uint8_t znptable8[256]; +extern uint16_t last_addr; extern uint16_t zero; extern uint16_t oldcs; extern uint16_t lastcs; @@ -44,6 +45,7 @@ extern uint16_t lastpc; extern uint16_t *mod1add[2][8]; extern uint16_t znptable16[65536]; +extern int pfq_pos; extern int x86_was_reset; extern int trap; extern int codegen_flat_ss; diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 4d099885a..f74e5e91a 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -551,7 +551,11 @@ static int FPU_ILLEGAL_a16(UNUSED(uint32_t fetchdat)) { geteaw(); +#ifdef FPU_NEC + do_cycles(timing_rr); +#else wait_cycs(timing_rr, 0); +#endif return 0; } #else diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index 417beea62..68955e07d 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -7,7 +7,11 @@ opFI(uint32_t fetchdat) cpu_state.npxc &= ~0x80; if (rmdat == 0xe1) cpu_state.npxc |= 0x80; +#ifdef FPU_NEC + do_cycles(3); +#else wait_cycs(3, 0); +#endif return 0; } #else diff --git a/src/cpu/x87_ops_sf.h b/src/cpu/x87_ops_sf.h index adbaa2003..722d86435 100644 --- a/src/cpu/x87_ops_sf.h +++ b/src/cpu/x87_ops_sf.h @@ -354,7 +354,11 @@ sf_FI(uint32_t fetchdat) fpu_state.cwd &= ~FPU_SW_Summary; if (rmdat == 0xe1) fpu_state.cwd |= FPU_SW_Summary; +#ifdef FPU_NEC + do_cycles(3); +#else wait_cycs(3, 0); +#endif return 0; } #else From 8b1e1ab1bffa065c9161bef52c7321277b4b04c3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 08:46:03 +0100 Subject: [PATCH 11/31] Bump version to 6.0, I think we have accumulated enough features to warrant that. --- CMakeLists.txt | 2 +- debian/changelog | 4 ++-- src/unix/assets/86Box.spec | 6 +++--- src/unix/assets/net.86box.86Box.metainfo.xml | 2 +- vcpkg.json | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b64902c12..b503b3e39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 5.4 + VERSION 6.0 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) diff --git a/debian/changelog b/debian/changelog index c0c4bf945..72e246145 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (5.4) UNRELEASED; urgency=medium +86box (6.0) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Tue, 23 Dec 2025 00:27:45 +0100 + -- Jasmine Iwanek Wed, 28 Jan 2026 08:45:23 +0100 diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index a189a5f41..aefac7a4f 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -12,10 +12,10 @@ # After a successful build, you can install the RPMs as follows: # sudo dnf install RPMS/$(uname -m)/86Box-3* RPMS/noarch/86Box-roms* -%global romver 5.4 +%global romver 6.0 Name: 86Box -Version: 5.4 +Version: 6.0 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Sat Aug 31 Jasmine Iwanek 5.4-1 +* Sat Aug 31 Jasmine Iwanek 6.0-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index c6a612a4c..4fdfe9c2a 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -11,7 +11,7 @@ net.86box.86Box.desktop - + diff --git a/vcpkg.json b/vcpkg.json index 4c0d502ef..6a4f6376c 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "5.4", + "version-string": "6.0", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later", From 5a189d49c3061789cba98357c847d610e604cf8e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 09:14:05 +0100 Subject: [PATCH 12/31] 808x and Vx0: Fix the remaining multiple definitions. --- src/cpu/cpu.h | 1 + src/cpu/vx0.c | 10 ---------- src/cpu/vx0_biu.c | 26 ++++++++++++------------- src/cpu/x87_ops.h | 32 +++++++++++++++---------------- src/dma.c | 4 ++-- src/include/86box/86box.h | 3 +++ src/video/vid_cga_compaq_plasma.c | 6 +++++- src/video/vid_cga_ncr.c | 6 +++++- src/video/vid_cga_olivetti.c | 6 +++++- 9 files changed, 50 insertions(+), 44 deletions(-) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 8e74bc78a..92d60f708 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -729,6 +729,7 @@ extern int idivl(int32_t val); extern void resetmcr(void); extern void resetx86(void); extern void refreshread(void); +extern void refreshread_vx0(void); extern void resetreadlookup(void); extern void softresetx86(void); extern void hardresetx86(void); diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index bd1a8da20..94a5fc56f 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -222,10 +222,6 @@ const uint8_t opf_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0 }; /* F8 */ -uint8_t use_custom_nmi_vector = 0; - -uint32_t custom_nmi_vector = 0x00000000; - /* Is the CPU 8088 or 8086. */ int is8086 = 0; int nx = 0; @@ -422,12 +418,6 @@ sync_to_i8080(void) emulated_processor.interrupt_delay = noint; } -uint16_t -get_last_addr(void) -{ - return last_addr; -} - static void set_ip(uint16_t new_ip) { diff --git a/src/cpu/vx0_biu.c b/src/cpu/vx0_biu.c index b52b14245..aba09d359 100644 --- a/src/cpu/vx0_biu.c +++ b/src/cpu/vx0_biu.c @@ -287,6 +287,15 @@ bus_inw(uint16_t port) return ret; } +void +resub_cycles_vx0(int old_cycles) +{ + if (old_cycles > cycles) + wait_states = old_cycles - cycles; + + cycles = old_cycles; +} + static void bus_do_io(int io_type) { @@ -310,7 +319,7 @@ bus_do_io(int io_type) AL = bus_inb((uint16_t) cpu_state.eaaddr); } - resub_cycles(old_cycles); + resub_cycles_vx0(old_cycles); } static void @@ -370,7 +379,7 @@ bus_do_mem(int io_type) mem_data = (mem_data & 0xff00) | ((uint16_t) bus_readb(mem_seg, (uint32_t) mem_addr)); } - resub_cycles(old_cycles); + resub_cycles_vx0(old_cycles); } static void @@ -510,15 +519,6 @@ do_bus_access(void) } } -void -resub_cycles(int old_cycles) -{ - if (old_cycles > cycles) - wait_states = old_cycles - cycles; - - cycles = old_cycles; -} - static uint8_t biu_queue_has_room(void) { @@ -715,7 +715,7 @@ wait(int c) /* This is for external subtraction of cycles, ie. wait states. */ void -sub_cycles(int c) +sub_cycles_vx0(int c) { cycles -= c; } @@ -1143,7 +1143,7 @@ biu_suspend_fetch(void) /* Memory refresh read - called by reads and writes on DMA channel 0. */ void -refreshread(void) +refreshread_vx0(void) { if (dma_state == DMA_STATE_IDLE) { dma_state = DMA_STATE_TIMER; diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index f74e5e91a..49b5c2378 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -581,7 +581,7 @@ FPU_ILLEGAL_a32(uint32_t fetchdat) #define ILLEGAL_a16 FPU_ILLEGAL_a16 #ifdef FPU_8087 -const OpFn OP_TABLE(sf_fpu_8087_d8)[32] = { +static const OpFn OP_TABLE(sf_fpu_8087_d8)[32] = { // clang-format off sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, @@ -590,7 +590,7 @@ const OpFn OP_TABLE(sf_fpu_8087_d8)[32] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_d9)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_d9)[256] = { // clang-format off sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -630,7 +630,7 @@ const OpFn OP_TABLE(sf_fpu_8087_d9)[256] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_da)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_da)[256] = { // clang-format off sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, sf_FMULil_a16, @@ -670,7 +670,7 @@ const OpFn OP_TABLE(sf_fpu_8087_da)[256] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_db)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_db)[256] = { // clang-format off sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -710,7 +710,7 @@ const OpFn OP_TABLE(sf_fpu_8087_db)[256] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_dc)[32] = { +static const OpFn OP_TABLE(sf_fpu_8087_dc)[32] = { // clang-format off sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, sf_FADDd_a16, sf_FMULd_a16, sf_FCOMd_a16, sf_FCOMPd_a16, sf_FSUBd_a16, sf_FSUBRd_a16, sf_FDIVd_a16, sf_FDIVRd_a16, @@ -719,7 +719,7 @@ const OpFn OP_TABLE(sf_fpu_8087_dc)[32] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_dd)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_dd)[256] = { // clang-format off sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -759,7 +759,7 @@ const OpFn OP_TABLE(sf_fpu_8087_dd)[256] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_de)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_de)[256] = { // clang-format off sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, @@ -799,7 +799,7 @@ const OpFn OP_TABLE(sf_fpu_8087_de)[256] = { // clang-format on }; -const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { +static const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { // clang-format off sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -839,7 +839,7 @@ const OpFn OP_TABLE(sf_fpu_8087_df)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_d8)[32] = { +static const OpFn OP_TABLE(fpu_8087_d8)[32] = { // clang-format off opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, @@ -848,7 +848,7 @@ const OpFn OP_TABLE(fpu_8087_d8)[32] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_d9)[256] = { +static const OpFn OP_TABLE(fpu_8087_d9)[256] = { // clang-format off opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, opFLDs_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -888,7 +888,7 @@ const OpFn OP_TABLE(fpu_8087_d9)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_da)[256] = { +static const OpFn OP_TABLE(fpu_8087_da)[256] = { // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, opFMULil_a16, @@ -928,7 +928,7 @@ const OpFn OP_TABLE(fpu_8087_da)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_db)[256] = { +static const OpFn OP_TABLE(fpu_8087_db)[256] = { // clang-format off opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -968,7 +968,7 @@ const OpFn OP_TABLE(fpu_8087_db)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_dc)[32] = { +static const OpFn OP_TABLE(fpu_8087_dc)[32] = { // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, @@ -977,7 +977,7 @@ const OpFn OP_TABLE(fpu_8087_dc)[32] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_dd)[256] = { +static const OpFn OP_TABLE(fpu_8087_dd)[256] = { // clang-format off opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, opFLDd_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, @@ -1017,7 +1017,7 @@ const OpFn OP_TABLE(fpu_8087_dd)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_de)[256] = { +static const OpFn OP_TABLE(fpu_8087_de)[256] = { // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, opFMULiw_a16, @@ -1057,7 +1057,7 @@ const OpFn OP_TABLE(fpu_8087_de)[256] = { // clang-format on }; -const OpFn OP_TABLE(fpu_8087_df)[256] = { +static const OpFn OP_TABLE(fpu_8087_df)[256] = { // clang-format off opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, diff --git a/src/dma.c b/src/dma.c index bfc294f2a..5dfd70ae8 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1503,7 +1503,7 @@ dma_channel_read_only(int channel) dma_channel_advance(channel); if (!dma_at && !channel) - refreshread(); + is_nec ? refreshread_vx0() : refreshread(); if (!dma_c->size) { temp = _dma_read(dma_c->ac, dma_c); @@ -1611,7 +1611,7 @@ dma_channel_read(int channel) dma_channel_advance(channel); if (!dma_at && !channel) - refreshread(); + is_nec ? refreshread_vx0() : refreshread(); if (!dma_c->size) { temp = _dma_read(dma_c->ac, dma_c); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index d32e13895..9cb91e7c6 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -315,6 +315,9 @@ extern uint16_t get_last_addr(void); extern void sub_cycles(int c); extern void resub_cycles(int old_cycles); +extern void sub_cycles_vx0(int c); +extern void resub_cycles_vx0(int old_cycles); + extern void ack_pause(void); extern void do_pause(int p); diff --git a/src/video/vid_cga_compaq_plasma.c b/src/video/vid_cga_compaq_plasma.c index b894daa9f..9eea61e0f 100644 --- a/src/video/vid_cga_compaq_plasma.c +++ b/src/video/vid_cga_compaq_plasma.c @@ -106,7 +106,11 @@ compaq_plasma_waitstates(UNUSED(void *priv)) int ws; ws = ws_array[cycles & 0xf]; - sub_cycles(ws); + + if (is_nec) + sub_cycles_vx0(ws); + else + sub_cycles(ws); } static void diff --git a/src/video/vid_cga_ncr.c b/src/video/vid_cga_ncr.c index cda38036b..dabbd85bf 100644 --- a/src/video/vid_cga_ncr.c +++ b/src/video/vid_cga_ncr.c @@ -91,7 +91,11 @@ nga_waitstates(UNUSED(void *priv)) int ws; ws = ws_array[cycles & 0xf]; - sub_cycles(ws); + + if (is_nec) + sub_cycles_vx0(ws); + else + sub_cycles(ws); } void diff --git a/src/video/vid_cga_olivetti.c b/src/video/vid_cga_olivetti.c index 0279621a1..ae539d084 100644 --- a/src/video/vid_cga_olivetti.c +++ b/src/video/vid_cga_olivetti.c @@ -157,7 +157,11 @@ ogc_waitstates(UNUSED(void *priv)) int ws; ws = ws_array[cycles & 0xf]; - sub_cycles(ws); + + if (is_nec) + sub_cycles_vx0(ws); + else + sub_cycles(ws); } void From 4e44ec7abc28e684b1c8db58c36226624d94787e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 09:31:29 +0100 Subject: [PATCH 13/31] And another multiple define. --- src/cpu/vx0.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index 94a5fc56f..0226284b6 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -222,8 +222,6 @@ const uint8_t opf_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0 }; /* F8 */ -/* Is the CPU 8088 or 8086. */ -int is8086 = 0; int nx = 0; static uint32_t cpu_src = 0; From 43aa0db7554ae0a57469df8c489e8fc1772e6a3c Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 09:50:18 +0100 Subject: [PATCH 14/31] Vx0: Rename wait() to wait_vx0() in order to fix warnings on Mac. --- src/cpu/vx0.c | 4 ++-- src/cpu/vx0_biu.c | 4 ++-- src/cpu/vx0_biu.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index 0226284b6..42bd7cc4b 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -41,11 +41,11 @@ #include <86box/plat_unused.h> #include "vx0_biu.h" -#define do_cycle() wait(1) +#define do_cycle() wait_vx0(1) #define do_cycle_no_modrm() if (!nx) \ do_cycle() #define do_cycle_i() do_cycle() -#define do_cycles(c) wait(c) +#define do_cycles(c) wait_vx0(c) #define do_cycles_i(c) do_cycles(c) #define do_cycle_nx() nx = 1 #define do_cycle_nx_i() nx = 1 diff --git a/src/cpu/vx0_biu.c b/src/cpu/vx0_biu.c index aba09d359..4f7a8e1d2 100644 --- a/src/cpu/vx0_biu.c +++ b/src/cpu/vx0_biu.c @@ -38,7 +38,7 @@ #include <86box/plat_unused.h> #include "vx0_biu.h" -#define do_cycle() wait(1) +#define do_cycle() wait_vx0(1) #define do_cycle_i() do_cycle() uint8_t biu_preload_byte = 0x00; @@ -705,7 +705,7 @@ biu_eu_request(void) } void -wait(int c) +wait_vx0(int c) { x808x_biu_log("[%04X:%04X] %02X %i cycles\n", CS, cpu_state.pc, opcode, c); diff --git a/src/cpu/vx0_biu.h b/src/cpu/vx0_biu.h index 58e2ae257..27d44797c 100644 --- a/src/cpu/vx0_biu.h +++ b/src/cpu/vx0_biu.h @@ -78,7 +78,7 @@ enum { /* Temporary BIU externs - move to 808x_biu.h. */ extern void biu_resume_on_queue_read(void); -extern void wait(int c); +extern void wait_vx0(int c); extern void biu_reset(void); extern void cpu_io_vx0(int bits, int out, uint16_t port); extern void biu_state_set_eu(void); From ae2b924532d7f70c0978fd3911ea53fdecaa118a Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:52:06 +0000 Subject: [PATCH 15/31] Translated using Weblate (German) Currently translated at 99.7% (1002 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/de/ --- src/qt/languages/de-DE.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qt/languages/de-DE.po b/src/qt/languages/de-DE.po index f377fcad0..5dccc6e54 100644 --- a/src/qt/languages/de-DE.po +++ b/src/qt/languages/de-DE.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"PO-Revision-Date: 2025-11-29 00:34+0000\n" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" "Last-Translator: OBattler \n" "Language-Team: German \n" "Language: de-DE\n" @@ -2872,7 +2872,7 @@ msgid "%1 VM Manager" msgstr "" msgid "%n disk(s)" -msgstr "" +msgstr "%n Festplatte(n)" msgid "Unknown Status" msgstr "Unbekannter Status" From 7658602d487e65d348d29d2ac8cd5ec811b5926d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:52:57 +0000 Subject: [PATCH 16/31] Translated using Weblate (Korean) Currently translated at 100.0% (1005 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/ko/ --- src/qt/languages/ko-KR.po | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/ko-KR.po b/src/qt/languages/ko-KR.po index cd186260b..a46dc07c7 100644 --- a/src/qt/languages/ko-KR.po +++ b/src/qt/languages/ko-KR.po @@ -1,8 +1,14 @@ msgid "" msgstr "" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" +"Language-Team: Korean \n" +"Language: ko-KR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 5.12.2\n" "X-Language: ko_KR\n" "X-Source-Language: en_US\n" @@ -1780,7 +1786,7 @@ msgid "VDE Socket:" msgstr "VDE 소켓:" msgid "TAP Bridge Device:" -msgstr "" +msgstr "TAP 브리지 장치:" msgid "86Box Unit Tester" msgstr "86Box 유닛 테스터" @@ -2173,16 +2179,16 @@ msgid "WSS DMA" msgstr "WSS DMA" msgid "RTC IRQ" -msgstr "" +msgstr "RTC의 IRQ" msgid "RTC Port Address" -msgstr "" +msgstr "RTC의 포트 주소" msgid "Onboard RTC" -msgstr "" +msgstr "온보드 RTC" msgid "Not installed" -msgstr "" +msgstr "설치되지 않음" msgid "Enable OPL" msgstr "OPL 사용" @@ -2806,7 +2812,7 @@ msgid "Toggle fullscreen" msgstr "전체 화면 모드 전환" msgid "Toggle UI in fullscreen" -msgstr "" +msgstr "전체 화면 모드에서 UI 전환" msgid "Release mouse pointer" msgstr "마우스 포인터를 해제합니다" From 67a243b6ce0706113cadbab5c90754bc6f1fe887 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:45:35 +0000 Subject: [PATCH 17/31] Translated using Weblate (Dutch) Currently translated at 100.0% (1005 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/nl/ --- src/qt/languages/nl-NL.po | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/nl-NL.po b/src/qt/languages/nl-NL.po index 63dcd239b..3ad6f4feb 100644 --- a/src/qt/languages/nl-NL.po +++ b/src/qt/languages/nl-NL.po @@ -1,8 +1,14 @@ msgid "" msgstr "" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" +"Language-Team: Dutch \n" +"Language: nl-NL\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.12.2\n" "X-Language: nl_NL\n" "X-Source-Language: en_US\n" @@ -1780,7 +1786,7 @@ msgid "VDE Socket:" msgstr "VDE-socket:" msgid "TAP Bridge Device:" -msgstr "" +msgstr "TAP-brugapparaat:" msgid "86Box Unit Tester" msgstr "86Box Apparaattester" @@ -2173,16 +2179,16 @@ msgid "WSS DMA" msgstr "WSS DMA" msgid "RTC IRQ" -msgstr "" +msgstr "IRQ van de RTC" msgid "RTC Port Address" -msgstr "" +msgstr "Poortadres van de RTC" msgid "Onboard RTC" -msgstr "" +msgstr "Ingebouwde RTC" msgid "Not installed" -msgstr "" +msgstr "Niet geïnstalleerd" msgid "Enable OPL" msgstr "OPL inschakelen" @@ -2806,7 +2812,7 @@ msgid "Toggle fullscreen" msgstr "Volledig scherm omschakelen" msgid "Toggle UI in fullscreen" -msgstr "" +msgstr "Schakel de UI in volledig scherm" msgid "Release mouse pointer" msgstr "Geef muis vrij" From a64c477b0bec5bf3aee77b668ad0a8923bfaeb09 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:55:18 +0000 Subject: [PATCH 18/31] Translated using Weblate (Swedish) Currently translated at 100.0% (1005 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/sv/ --- src/qt/languages/sv-SE.po | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/sv-SE.po b/src/qt/languages/sv-SE.po index eb7633168..5a8c7291c 100644 --- a/src/qt/languages/sv-SE.po +++ b/src/qt/languages/sv-SE.po @@ -1,8 +1,14 @@ msgid "" msgstr "" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" +"Language-Team: Swedish \n" +"Language: sv-SE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.12.2\n" "X-Language: sv_SE\n" "X-Source-Language: en_US\n" @@ -1780,7 +1786,7 @@ msgid "VDE Socket:" msgstr "VDE-sockel:" msgid "TAP Bridge Device:" -msgstr "" +msgstr "TAP-bryggaenhet:" msgid "86Box Unit Tester" msgstr "86Box enhetsprövare" @@ -2173,16 +2179,16 @@ msgid "WSS DMA" msgstr "WSS DMA" msgid "RTC IRQ" -msgstr "" +msgstr "IRQ för RTC" msgid "RTC Port Address" -msgstr "" +msgstr "Portadress för RTC" msgid "Onboard RTC" -msgstr "" +msgstr "Inbyggd RTC" msgid "Not installed" -msgstr "" +msgstr "Ej installerad" msgid "Enable OPL" msgstr "Aktivera OPL" @@ -2806,7 +2812,7 @@ msgid "Toggle fullscreen" msgstr "Helskärm" msgid "Toggle UI in fullscreen" -msgstr "" +msgstr "Växla UI till helskärmsläge" msgid "Release mouse pointer" msgstr "Släpp muspekare" From 242187215c8bfe2e8190e7629ee4d305005a8b62 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:56:10 +0000 Subject: [PATCH 19/31] Translated using Weblate (Vietnamese) Currently translated at 99.8% (1003 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/vi/ --- src/qt/languages/vi-VN.po | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/vi-VN.po b/src/qt/languages/vi-VN.po index 64d00e210..73b59831a 100644 --- a/src/qt/languages/vi-VN.po +++ b/src/qt/languages/vi-VN.po @@ -1,8 +1,15 @@ msgid "" msgstr "" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" +"Language-Team: Vietnamese \n" +"Language: vi-VN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 5.12.2\n" "X-Language: vi_VN\n" "X-Source-Language: en_US\n" @@ -1780,7 +1787,7 @@ msgid "VDE Socket:" msgstr "Ổ cắm VDE:" msgid "TAP Bridge Device:" -msgstr "" +msgstr "Thiết bị cầu nối TAP:" msgid "86Box Unit Tester" msgstr "Trình kiểm tra đơn vị 86box" @@ -2173,16 +2180,16 @@ msgid "WSS DMA" msgstr "WSS DMA" msgid "RTC IRQ" -msgstr "" +msgstr "IRQ của RTC" msgid "RTC Port Address" -msgstr "" +msgstr "Địa chỉ cổng của RTC" msgid "Onboard RTC" -msgstr "" +msgstr "RTC tích hợp trên bo mạch" msgid "Not installed" -msgstr "" +msgstr "Chưa được cài đặt" msgid "Enable OPL" msgstr "Bật OPL" @@ -2806,7 +2813,7 @@ msgid "Toggle fullscreen" msgstr "Bật/tắt toàn màn hình" msgid "Toggle UI in fullscreen" -msgstr "" +msgstr "Chuyển đổi giao diện người dùng sang chế độ toàn màn hình" msgid "Release mouse pointer" msgstr "Thả con trỏ chuột" From ee92ccb9c433011d8216d048b63aac7d34bbc83d Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:48:09 +0000 Subject: [PATCH 20/31] Translated using Weblate (Finnish) Currently translated at 97.8% (983 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/fi/ --- src/qt/languages/fi-FI.po | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/qt/languages/fi-FI.po b/src/qt/languages/fi-FI.po index a5f36d2d4..2351f1afa 100644 --- a/src/qt/languages/fi-FI.po +++ b/src/qt/languages/fi-FI.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2025-12-29 09:54+0000\n" -"Last-Translator: Daniel Gurney \n" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" "Language-Team: Finnish \n" "Language: fi-FI\n" "MIME-Version: 1.0\n" @@ -637,7 +637,7 @@ msgid "MO drives:" msgstr "Magneettisoptiset asemat (MO):" msgid "MO:" -msgstr "" +msgstr "MO:" msgid "Removable disks:" msgstr "Irrotettavat levyt:" @@ -1843,7 +1843,7 @@ msgid "Microsoft Serial Mouse" msgstr "Microsoft-sarjahiiri" msgid "Microsoft Serial BallPoint" -msgstr "" +msgstr "Microsoft BallPoint-sarjahiiri" msgid "Logitech Serial Mouse" msgstr "Logitech-sarjahiiri" @@ -1930,7 +1930,7 @@ msgid "Enable BIOS extension ROM Writes (ROM #4)" msgstr "Salli BIOS-laajennuksen ROM-kirjoitukset (ROM #4)" msgid "Linear framebuffer base" -msgstr "" +msgstr "Lineaarisen kehyspuskurin perusosoite" msgid "Address" msgstr "Osoite" @@ -2179,7 +2179,7 @@ msgid "WSS DMA" msgstr "WSS-DMA" msgid "RTC IRQ" -msgstr "" +msgstr "RTC:n IRQ" msgid "RTC Port Address" msgstr "RTC-portin osoite" @@ -2380,10 +2380,10 @@ msgid "Linear" msgstr "Lineaarinen" msgid "4th Order" -msgstr "" +msgstr "4. kertaluku" msgid "7th Order" -msgstr "" +msgstr "7. kertaluku" msgid "Non-timed (original)" msgstr "Ajastamaton (alkuperäinen)" From 91965610f29720eecbf46e7e9763cd707187cc85 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 27 Jan 2026 08:53:51 +0000 Subject: [PATCH 21/31] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?= =?UTF-8?q?=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (1005 of 1005 strings) Translation: 86Box/86Box Translate-URL: https://weblate.86box.net/projects/86box/86box/nb_NO/ --- src/qt/languages/nb-NO.po | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/qt/languages/nb-NO.po b/src/qt/languages/nb-NO.po index 88679fdd3..b22f0bf69 100644 --- a/src/qt/languages/nb-NO.po +++ b/src/qt/languages/nb-NO.po @@ -1,8 +1,15 @@ msgid "" msgstr "" +"PO-Revision-Date: 2026-01-28 08:57+0000\n" +"Last-Translator: OBattler \n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb-NO\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.12.2\n" "X-Language: nb_NO\n" "X-Source-Language: en_US\n" @@ -1780,7 +1787,7 @@ msgid "VDE Socket:" msgstr "VDE-kontakt:" msgid "TAP Bridge Device:" -msgstr "" +msgstr "TAP-broenhet:" msgid "86Box Unit Tester" msgstr "86Box-enhetstester" @@ -2173,16 +2180,16 @@ msgid "WSS DMA" msgstr "WSS-DMA" msgid "RTC IRQ" -msgstr "" +msgstr "IRQ for RTC" msgid "RTC Port Address" -msgstr "" +msgstr "Portadresse for RTC" msgid "Onboard RTC" -msgstr "" +msgstr "Innebygd RTC" msgid "Not installed" -msgstr "" +msgstr "Ikke installert" msgid "Enable OPL" msgstr "Aktiver OPL" @@ -2806,7 +2813,7 @@ msgid "Toggle fullscreen" msgstr "Veksle fullskjerm" msgid "Toggle UI in fullscreen" -msgstr "" +msgstr "Veksle mellom brukergrensesnittet i fullskjermmodus" msgid "Release mouse pointer" msgstr "Frigi musepeker" From f85bbe8d04c267270513de5307e31f37bc18a303 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 28 Jan 2026 11:13:45 +0100 Subject: [PATCH 22/31] Jenkins: Use UCRT64 shell on Windows. --- .ci/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index cc3e415cd..9084b80f3 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -147,7 +147,7 @@ def runBuild(args) { if (isUnix()) return sh(returnStatus: true, script: "chmod u+x '$WORKSPACE/.ci/build.sh' && exec '$WORKSPACE/.ci/build.sh' $args") else - return bat(returnStatus: true, script: "C:\\msys64\\msys2_shell.cmd -msys2 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'") + return bat(returnStatus: true, script: "C:\\msys64\\msys2_shell.cmd -ucrt64 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'") } def failStage() { From ea76bc615b8aed8873dc0d86bc6182b6ef1ea359 Mon Sep 17 00:00:00 2001 From: pankozaC++ <77279607+pankoza2-pl@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:05:20 +0100 Subject: [PATCH 23/31] Add the MACHINE_SOUND flag to the TriGem Como --- src/machine/machine_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 762c4410e..ca484969d 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -18517,7 +18517,7 @@ const machine_t machines[] = { .max_multi = 5.0 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 262144, From e9c41fe7d4c84489a4088f4df29900495cb58b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miran=20Gr=C4=8Da?= Date: Wed, 28 Jan 2026 20:34:51 +0100 Subject: [PATCH 24/31] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f4f32b2e..de6541e36 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ The 86Box project welcomes contributions from anyone, as long as some basic guidelines are followed. ## Emulated hardware -In order to accept new emulated hardware, the following criteria must be met: +In order to accept new emulated hardware or a request thereof, the following criteria must be met: * A ROM must be available and be added to [our ROM repository](https://github.com/86Box/roms) * Documentation must be available or it must be feasible to reverse engineer with a reasonable amount of time and effort From 3bcf6a75e5915fc4f21381e8b58c2dcfc19d8858 Mon Sep 17 00:00:00 2001 From: fleur!3 <149212571+cyrix6x86mx@users.noreply.github.com> Date: Wed, 28 Jan 2026 20:44:13 +0000 Subject: [PATCH 25/31] Update Pentium CPU table names for Socket 4 and 5/7 --- src/cpu/cpu_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index cb337b405..5d68b56cd 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -3616,7 +3616,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET4, .manufacturer = "Intel", - .name = "Pentium", + .name = "Pentium (Socket 4)", .internal_name = "pentium_p5", .cpus = (const CPU[]) { { @@ -3736,7 +3736,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET5_7, .manufacturer = "Intel", - .name = "Pentium", + .name = "Pentium (Socket 5/7)", .internal_name = "pentium_p54c", .cpus = (const CPU[]) { { From bd13b21cd1cbf8f774ac49b3d9c896e36d275560 Mon Sep 17 00:00:00 2001 From: fleur!3 <149212571+cyrix6x86mx@users.noreply.github.com> Date: Wed, 28 Jan 2026 20:54:34 +0000 Subject: [PATCH 26/31] Update the CPU names to be P5 and P54C instead of Socket 4 and 5/7 --- src/cpu/cpu_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 5d68b56cd..91808299a 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -3616,7 +3616,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET4, .manufacturer = "Intel", - .name = "Pentium (Socket 4)", + .name = "Pentium (P5)", .internal_name = "pentium_p5", .cpus = (const CPU[]) { { @@ -3736,7 +3736,7 @@ const cpu_family_t cpu_families[] = { { .package = CPU_PKG_SOCKET5_7, .manufacturer = "Intel", - .name = "Pentium (Socket 5/7)", + .name = "Pentium (P54C)", .internal_name = "pentium_p54c", .cpus = (const CPU[]) { { From 0055917012c79a0c880eae8ad77993e9206f8fd2 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Jan 2026 18:48:41 +0100 Subject: [PATCH 27/31] DEC Tulip 21040: Do not attempt to read the EEPROM data on reset, fixes #6768. --- src/network/net_tulip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index b5219cf23..2b2503904 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -886,7 +886,6 @@ static void tulip_reset(void *priv) { TULIPState *s = (TULIPState *) priv; - const uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); s->csr[0] = 0xfe000000; s->csr[1] = 0xffffffff; s->csr[2] = 0xffffffff; @@ -901,6 +900,8 @@ tulip_reset(void *priv) s->csr[14] = 0xffffffff; s->csr[15] = 0x8ff00000; if (s->device_info->local != 3) { + const uint16_t *eeprom_data = nmc93cxx_eeprom_data(s->eeprom); + s->subsys_id = eeprom_data[1]; s->subsys_ven_id = eeprom_data[0]; } From 484a61f65a69f964309a3c63741196165c7ac96a Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Jan 2026 19:47:26 +0100 Subject: [PATCH 28/31] Only use checkStateChanged from Qt 6.7 onwards, should fix GitHub Actions builds. --- src/qt/qt_defs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/qt_defs.hpp b/src/qt/qt_defs.hpp index 1190c0ed1..58de88b67 100644 --- a/src/qt/qt_defs.hpp +++ b/src/qt/qt_defs.hpp @@ -1,7 +1,7 @@ #ifndef QT_DEFS_HPP #define QT_DEFS_HPP -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) #define CHECK_STATE_CHANGED checkStateChanged #else #define CHECK_STATE_CHANGED stateChanged From d1d39415422c9fc85cf9174810c77768602987d8 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Jan 2026 04:03:20 +0100 Subject: [PATCH 29/31] 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*/ From e8eb606510b475cb84429b63753bedf467041074 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Jan 2026 07:59:24 +0100 Subject: [PATCH 30/31] Some improvements on said debug thunking to old 808x instructions. --- src/cpu/808x.c | 323 +++++++++++++++++++++++++++++----------------- src/cpu/vx0.c | 12 +- src/cpu/vx0_biu.h | 5 + 3 files changed, 214 insertions(+), 126 deletions(-) diff --git a/src/cpu/808x.c b/src/cpu/808x.c index a1d29e56a..8cb153cd2 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -64,6 +64,7 @@ int rep_c_flag = 0; int noint = 0; int tempc_fpu = 0; int clear_lock = 0; +int is_new_biu = 0; uint32_t cpu_src = 0; uint32_t cpu_dest = 0; @@ -72,13 +73,13 @@ uint32_t cpu_data = 0; uint32_t * ovr_seg = NULL; +/* Pointer tables needed for segment overrides. */ +uint32_t * opseg[4]; +x86seg * _opseg[4]; + /* The IP equivalent of the current prefetch queue position. */ static uint16_t pfq_ip; -/* Pointer tables needed for segment overrides. */ -static uint32_t *opseg[4]; -static x86seg *_opseg[4]; - static int pfq_size; uint16_t last_addr = 0x0000; @@ -255,7 +256,7 @@ fetch_and_bus(int c, int bus) static void wait_cycs(int c, int bus) { - if (is_nec) + if (is_new_biu) wait_vx0(c); else { cycles -= c; @@ -296,7 +297,7 @@ resub_cycles(int old_cycles) static void cpu_io(int bits, int out, uint16_t port) { - if (is_nec) + if (is_new_biu) cpu_io_vx0(bits, out, port); else { int old_cycles = cycles; @@ -343,7 +344,7 @@ cpu_io(int bits, int out, uint16_t port) static uint8_t readmemb(uint32_t s, uint32_t a) { - if (is_nec) + if (is_new_biu) return readmemb_vx0(s, a); else { uint8_t ret; @@ -371,7 +372,7 @@ readmembf(uint32_t a) static uint16_t readmemw(uint32_t s, uint16_t a) { - if (is_nec) + if (is_new_biu) return readmemw_vx0(s, a); else { uint16_t ret; @@ -382,7 +383,7 @@ readmemw(uint32_t s, uint16_t a) else { wait_cycs(4, 1); ret = read_mem_b(s + a); - ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8; + ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8; } return ret; @@ -402,7 +403,7 @@ readmemwf(uint16_t a) static uint16_t readmem(uint32_t s) { - if (is_nec) + if (is_new_biu) return readmem_vx0(s); else { if (opcode & 1) @@ -415,7 +416,7 @@ readmem(uint32_t s) static uint32_t readmeml(uint32_t s, uint16_t a) { - if (is_nec) + if (is_new_biu) return readmeml_vx0(s, a); else { uint32_t temp; @@ -430,7 +431,7 @@ readmeml(uint32_t s, uint16_t a) static uint64_t readmemq(uint32_t s, uint16_t a) { - if (is_nec) + if (is_new_biu) return readmemq_vx0(s, a); else { uint64_t temp; @@ -446,7 +447,7 @@ readmemq(uint32_t s, uint16_t a) static void writememb(uint32_t s, uint32_t a, uint8_t v) { - if (is_nec) + if (is_new_biu) writememb_vx0(s, a, v); else { uint32_t addr = s + a; @@ -463,7 +464,7 @@ writememb(uint32_t s, uint32_t a, uint8_t v) static void writememw(uint32_t s, uint32_t a, uint16_t v) { - if (is_nec) + if (is_new_biu) writememw_vx0(s, a, v); else { uint32_t addr = s + a; @@ -474,7 +475,7 @@ writememw(uint32_t s, uint32_t a, uint16_t v) else { write_mem_b(addr, v & 0xff); wait_cycs(4, 1); - addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff)); + addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff)); write_mem_b(addr, v >> 8); } @@ -486,7 +487,7 @@ writememw(uint32_t s, uint32_t a, uint16_t v) static void writemem(uint32_t s, uint16_t v) { - if (is_nec) + if (is_new_biu) writemem_vx0(s, v); else { if (opcode & 1) @@ -499,7 +500,7 @@ writemem(uint32_t s, uint16_t v) static void writememl(uint32_t s, uint32_t a, uint32_t v) { - if (is_nec) + if (is_new_biu) writememl_vx0(s, a, v); else { writememw(s, a, v & 0xffff); @@ -510,7 +511,7 @@ writememl(uint32_t s, uint32_t a, uint32_t v) static void writememq(uint32_t s, uint32_t a, uint64_t v) { - if (is_nec) + if (is_new_biu) writememl_vx0(s, a, v); else { writememl(s, a, v & 0xffffffff); @@ -542,7 +543,7 @@ pfq_write(void) static uint8_t pfq_read(void) { - if (is_nec) + if (is_new_biu) return biu_pfq_read(); else { uint8_t temp = pfq[0]; @@ -560,7 +561,7 @@ pfq_read(void) static uint8_t pfq_fetchb_common(void) { - if (is_nec) + if (is_new_biu) return biu_pfq_fetchb_common(); else { uint8_t temp; @@ -581,7 +582,7 @@ pfq_fetchb_common(void) static uint8_t pfq_fetchb(void) { - if (is_nec) + if (is_new_biu) return biu_pfq_fetchb(); else { uint8_t ret; @@ -597,7 +598,7 @@ pfq_fetchb(void) static uint16_t pfq_fetchw(void) { - if (is_nec) + if (is_new_biu) return biu_pfq_fetchw(); else { uint16_t temp; @@ -613,7 +614,7 @@ pfq_fetchw(void) static uint16_t pfq_fetch(void) { - if (is_nec) + if (is_new_biu) return biu_pfq_fetch(); else { if (opcode & 1) @@ -642,7 +643,7 @@ pfq_add(int c, int add) static void pfq_clear_pos(void) { - if (is_nec) + if (is_new_biu) biu_queue_flush(); else pfq_pos = 0; @@ -652,7 +653,7 @@ pfq_clear_pos(void) static void pfq_clear(void) { - if (is_nec) { + if (is_new_biu) { biu_suspend_fetch(); biu_queue_flush(); } else { @@ -705,6 +706,7 @@ static void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) void reset_808x(int hard) { + is_new_biu = 0; biu_cycles = 0; in_rep = 0; completed = 1; @@ -730,6 +732,8 @@ reset_808x(int hard) load_cs(0xFFFF); cpu_state.pc = 0; + if (is_nec) + cpu_state.flags |= MD_FLAG; rammask = 0xfffff; prefetching = 1; @@ -750,10 +754,9 @@ reset_808x(int hard) static void set_ip(uint16_t new_ip) { - if (is_nec) { + if (is_new_biu) cpu_state.pc = new_ip; - biu_queue_flush(); - } else { + else { pfq_ip = cpu_state.pc = new_ip; prefetching = 1; } @@ -969,7 +972,7 @@ seteaq(uint64_t val) static void push(uint16_t *val) { - if (is186 && (SP == 1)) { + if ((is186 && !is_nec) && (SP == 1)) { writememw(ss - 1, 0, *val); SP = cpu_state.eaaddr = 0xFFFF; return; @@ -992,57 +995,39 @@ static void access(int num, UNUSED(int bits)) { switch (num) { - case 0: + case 0: case 61: - case 63: - case 64: + case 63 ... 64: case 67: case 69: - case 71: - case 72: + case 71 ... 72: default: break; - case 1: - case 6: - case 7: - case 8: - case 9: + case 1: + case 6 ... 9: case 17: - case 20: - case 21: + case 20 ... 21: case 24: case 28: - case 47: - case 48: - case 49: - case 50: - case 51: - case 55: - case 56: + case 47 ... 51: + case 55 ... 56: case 62: case 66: case 68: wait_cycs(1, 0); break; - case 3: + case 3: case 11: case 15: - case 22: - case 23: - case 25: - case 26: + case 22 ... 23: + case 25 ... 26: case 35: - case 44: - case 45: - case 46: - case 52: - case 53: - case 54: + case 44 ... 46: + case 52 ... 54: wait_cycs(2, 0); break; case 16: - case 18: - case 19: + case 18 ... 19: case 27: case 32: case 37: @@ -1050,19 +1035,15 @@ access(int num, UNUSED(int bits)) wait_cycs(3, 0); break; case 10: - case 12: - case 13: - case 14: - case 29: - case 30: - case 33: - case 34: + case 12 ... 14: + case 29 ... 30: + case 33 ... 34: case 39: case 41: case 60: wait_cycs(4, 0); break; - case 4: + case 4: case 70: wait_cycs(5, 0); break; @@ -1079,7 +1060,10 @@ access(int num, UNUSED(int bits)) break; case 36: wait_cycs(1, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); wait_cycs(1, 0); if (cpu_mod != 3) wait_cycs(1, 0); @@ -1087,7 +1071,10 @@ access(int num, UNUSED(int bits)) break; case 43: wait_cycs(2, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); wait_cycs(1, 0); break; case 57: @@ -1102,14 +1089,20 @@ access(int num, UNUSED(int bits)) break; case 59: wait_cycs(2, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); if (cpu_mod != 3) wait_cycs(1, 0); wait_cycs(3, 0); break; case 65: wait_cycs(1, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); wait_cycs(2, 0); if (cpu_mod != 3) wait_cycs(1, 0); @@ -1134,20 +1127,39 @@ interrupt(uint16_t addr) cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; access(6, 16); new_cs = readmemw(0, cpu_state.eaaddr); - prefetching = 0; - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else { + prefetching = 0; + pfq_clear(); + } ovr_seg = NULL; - access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + if (is_new_biu) + wait_cycs(2, 0); + else + access(39, 16); + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); - access(40, 16); + if (is_nec) + cpu_state.flags |= MD_FLAG; + if (is_new_biu) + wait_cycs(4, 0); + else + access(40, 16); push(&old_cs); old_ip = cpu_state.pc; load_cs(new_cs); - access(68, 16); + if (is_new_biu) + wait_cycs(3, 0); + else + access(68, 16); set_ip(new_ip); - access(41, 16); + if (is_new_biu) { + biu_queue_flush(); + wait_cycs(4, 0); + } else + access(41, 16); push(&old_ip); } @@ -1172,9 +1184,11 @@ custom_nmi(void) pfq_clear(); ovr_seg = NULL; access(39, 16); - tempf = cpu_state.flags & 0x0fd7; + tempf = cpu_state.flags & (is_nec ? 0x8fd7 : 0x0fd7); push(&tempf); cpu_state.flags &= ~(I_FLAG | T_FLAG); + if (is_nec) + cpu_state.flags |= MD_FLAG; access(40, 16); push(&old_cs); old_ip = cpu_state.pc; @@ -1186,10 +1200,10 @@ custom_nmi(void) } static int -irq_pending(void) +irq_pending(int nec_hlt) { uint8_t temp; - int i_flag = (cpu_state.flags & I_FLAG); + int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint) || (i_flag && pic.int_pending && !noint); @@ -1197,12 +1211,12 @@ irq_pending(void) } static void -check_interrupts(void) +check_interrupts(int nec_hlt) { int temp; - int i_flag = (cpu_state.flags & I_FLAG); + int i_flag = (cpu_state.flags & I_FLAG) || nec_hlt; - if (irq_pending()) { + if (irq_pending(nec_hlt)) { if ((cpu_state.flags & T_FLAG) && !(noint & 1)) { interrupt(1); return; @@ -1251,10 +1265,13 @@ rep_action(int bits) return 0; wait_cycs(2, 0); t = CX; - if (irq_pending() && (repeating != 0)) { + if (irq_pending(0) && (repeating != 0)) { access(71, bits); pfq_clear(); - set_ip(cpu_state.pc - 2); + if (is_nec && (ovr_seg != NULL)) + set_ip(cpu_state.pc - 3); + else + set_ip(cpu_state.pc - 2); t = 0; } if (t == 0) { @@ -1276,14 +1293,14 @@ jump(uint16_t delta) { uint16_t old_ip; access(67, 8); - if (is_nec) + if (is_new_biu) 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) + if (is_new_biu) biu_queue_flush(); return old_ip; } @@ -1882,7 +1899,7 @@ execx86_instruction(void) { uint8_t temp = 0, temp2, old_af, nests; uint16_t addr, tempw, new_cs, new_ip, handled = 0; - uint16_t tempw_int, size, tempbp, lowbound; + uint16_t tempw_int, size, tempbp, lowbound, old_flags; uint16_t highbound, regval, orig_sp, wordtopush, immediate; int bits; uint32_t dest_seg; @@ -1937,6 +1954,18 @@ execx86_instruction(void) handled = 1; break; + case 0x64: + case 0x65: + if (is_nec) { + /* REPC/REPNC */ + wait_cycs(1, 0); + in_rep = (opcode == 0x64 ? 1 : 2); + rep_c_flag = 1; + completed = 0; + handled = 1; + } + break; + case 0x68: wordtopush = pfq_fetchw(); wait_cycs(1, 0); @@ -2058,7 +2087,9 @@ execx86_instruction(void) wait_cycs((cpu_mod != 3) ? 9 : 6, 0); - cpu_src &= 0x1F; + if (!is_nec) + cpu_src &= 0x1f; + while (cpu_src != 0) { cpu_dest = cpu_data; oldc = cpu_state.flags & C_FLAG; @@ -2516,13 +2547,22 @@ execx86_instruction(void) new_ip = pfq_fetchw(); wait_cycs(1, 0); new_cs = pfq_fetchw(); - pfq_clear(); - access(31, 16); + if (is_new_biu) + biu_suspend_fetch(); + else { + pfq_clear(); + access(31, 16); + } push(&(CS)); - access(60, 16); + if (!is_new_biu) + access(60, 16); cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); set_ip(new_ip); + if (is_new_biu) { + wait_cycs(3, 0); + biu_queue_flush(); + } access(32, 16); push((uint16_t *) &(cpu_state.oldpc)); break; @@ -2537,22 +2577,29 @@ execx86_instruction(void) } else { repeating = 1; completed = 0; - clock_end(); + if (!is_new_biu) + clock_end(); } #else wait_cycs(7, 0); - check_interrupts(); + check_interrupts(0); #endif break; case 0x9c: /* PUSHF */ access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; + if (is_nec) + tempw = (cpu_state.flags & 0x8fd7) | 0x7000; + else + 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; + if (is_nec && cpu_md_write_disable) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; wait_cycs(1, 0); if ((old_flags ^ cpu_state.flags) & T_FLAG) noint = 1; @@ -2616,7 +2663,7 @@ execx86_instruction(void) break; } repeating = 1; - if (!is_nec) + if (!is_new_biu) clock_end(); break; @@ -2656,7 +2703,7 @@ execx86_instruction(void) break; } repeating = 1; - if (!is_nec) + if (!is_new_biu) clock_end(); break; @@ -2687,7 +2734,7 @@ execx86_instruction(void) break; } repeating = 1; - if (!is_nec) + if (!is_new_biu) clock_end(); break; @@ -2717,7 +2764,10 @@ execx86_instruction(void) } if ((opcode & 9) == 9) wait_cycs(1, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); access(26, bits); new_ip = pop(); wait_cycs(2, 0); @@ -2736,6 +2786,8 @@ execx86_instruction(void) load_cs(new_cs); access(72, bits); set_ip(new_ip); + if (is_new_biu) + biu_queue_flush(); break; case 0xc4 ... 0xc5: /* LsS rw, rmd */ @@ -2786,8 +2838,13 @@ execx86_instruction(void) load_cs(new_cs); access(62, 8); set_ip(new_ip); + if (is_new_biu) + biu_queue_flush(); access(45, 8); - cpu_state.flags = pop() | 0x0002; + if (is_nec && cpu_md_write_disable) + cpu_state.flags = pop() | 0x8002; + else + cpu_state.flags = pop() | 0x0002; wait_cycs(5, 0); noint = 2; nmi_enable = 1; @@ -2807,7 +2864,7 @@ execx86_instruction(void) cpu_src = CL; wait_cycs((cpu_mod != 3) ? 9 : 6, 0); } - if (is186) + if (is186 && !is_nec) cpu_src &= 0x1f; while (cpu_src != 0) { cpu_dest = cpu_data; @@ -2894,7 +2951,11 @@ execx86_instruction(void) break; case 0xd5: /* AAD */ wait_cycs(1, 0); - mul(pfq_fetchb(), AH); + if (is_nec) { + (void) pfq_fetchb(); + mul(10, AH); + } else + mul(pfq_fetchb(), AH); cpu_dest = AL; cpu_src = cpu_data; add(8); @@ -2903,10 +2964,13 @@ execx86_instruction(void) set_pzs(8); break; case 0xd6: /* SALC */ - wait_cycs(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait_cycs(1, 0); - break; + if (!is_nec) { + wait_cycs(1, 0); + AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; + wait_cycs(1, 0); + break; + } + fallthrough; case 0xd7: /* XLATB */ cpu_state.eaaddr = (BX + AL) & 0xffff; access(4, 8); @@ -3054,8 +3118,13 @@ execx86_instruction(void) tempw = pfq_fetchw(); load_cs(tempw); access(70, 8); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + pfq_clear(); set_ip(addr); + if (is_new_biu) + biu_queue_flush(); break; case 0xeb: /* JMP rel */ wait_cycs(1, 0); @@ -3083,9 +3152,9 @@ execx86_instruction(void) pfq_clear(); } wait_cycs(1, 0); - if (irq_pending()) { + if (irq_pending(is_nec)) { wait_cycs(cycles & 1, 0); - check_interrupts(); + check_interrupts(is_nec); } else { repeating = 1; completed = 0; @@ -3126,6 +3195,7 @@ execx86_instruction(void) set_ea(cpu_data); break; case 0x20: case 0x28: /* MUL, IMUL */ + old_flags = cpu_state.flags; wait_cycs(1, 0); mul(get_accum(bits), cpu_data); if (opcode & 1) { @@ -3137,12 +3207,17 @@ execx86_instruction(void) 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; + if (!is_nec) + cpu_data = AH; } set_sf(bits); set_pf(); if (cpu_mod != 3) wait_cycs(1, 0); + /* NOTE: When implementing the V20, care should be taken to not change + the zero flag. */ + if (is_nec) + cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG); break; case 0x30: case 0x38: /* DIV, IDIV */ if (cpu_mod != 3) @@ -3193,13 +3268,18 @@ execx86_instruction(void) cpu_data_opff_rm(); access(63, bits); wait_cycs(1, 0); - pfq_clear(); + if (is_new_biu) + biu_suspend_fetch(); + else + 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); + if (is_new_biu) + biu_queue_flush(); wait_cycs(2, 0); access(35, bits); push((uint16_t *) &(cpu_state.oldpc)); @@ -3214,10 +3294,15 @@ execx86_instruction(void) access(36, bits); push(&(CS)); access(64, bits); - wait_cycs(4, 0); + if (!is_new_biu) + wait_cycs(4, 0); cpu_state.oldpc = cpu_state.pc; load_cs(new_cs); set_ip(new_ip); + if (is_new_biu) { + wait_cycs(3, 0); + biu_queue_flush(); + } access(37, bits); push((uint16_t *) &(cpu_state.oldpc)); break; @@ -3225,6 +3310,8 @@ execx86_instruction(void) cpu_data_opff_rm(); access(65, bits); set_ip(cpu_data); + if (is_new_biu) + biu_queue_flush(); break; case 0x28: /* JMP rmd */ new_ip = cpu_data; @@ -3236,6 +3323,8 @@ execx86_instruction(void) load_cs(new_cs); access(66, bits); set_ip(new_ip); + if (is_new_biu) + biu_queue_flush(); break; case 0x30: case 0x38: /* PUSH rm */ if (cpu_mod != 3) @@ -3285,7 +3374,7 @@ execx86(int cycs) if (in_lock) clear_lock = 1; clock_end(); - check_interrupts(); + check_interrupts(0); if (noint) noint = 0; diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index ab4fc5573..ee26e41c5 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -232,11 +232,6 @@ static int in_hlt = 0; static int retem = 0; static int halted = 0; -/* Pointer tables needed for segment overrides. */ -static uint32_t * opseg[4]; - -static x86seg * _opseg[4]; - enum { MODRM_ADDR_BX_SI = 0x00, MODRM_ADDR_BX_DI, @@ -473,8 +468,7 @@ void i8080_port_out(UNUSED(void* priv), uint8_t port, uint8_t val) void reset_vx0(int hard) { - reset_808x(hard); - + is_new_biu = 1; halted = 0; in_hlt = 0; in_0f = 0; @@ -4732,7 +4726,7 @@ execvx0(int cycs) #ifdef DEBUG_INSTRUCTIONS if (repeating) { - if ((opcode >= 0xa0) && (opcode <= 0xaf) && (opcode != 0x8e)) { + if ((opcode >= MIN_INS) && (opcode <= MAX_INS) && (opcode != SKIP_INS)) { execx86_instruction(); goto check_completed; } @@ -4751,7 +4745,7 @@ execvx0(int cycs) decode(); #ifdef DEBUG_INSTRUCTIONS - if ((opcode >= 0xa0) && (opcode <= 0xaf) && (opcode != 0x8e)) { + if ((opcode >= MIN_INS) && (opcode <= MAX_INS) && (opcode != SKIP_INS)) { oldc = cpu_state.flags & C_FLAG; execx86_instruction(); diff --git a/src/cpu/vx0_biu.h b/src/cpu/vx0_biu.h index 92eb661af..173a6947b 100644 --- a/src/cpu/vx0_biu.h +++ b/src/cpu/vx0_biu.h @@ -116,6 +116,7 @@ extern int rep_c_flag; extern int noint; extern int tempc_fpu; extern int clear_lock; +extern int is_new_biu; extern int schedule_fetch; extern int in_lock; @@ -130,4 +131,8 @@ extern uint32_t cpu_data; extern uint32_t *ovr_seg; +/* Pointer tables needed for segment overrides. */ +extern uint32_t * opseg[4]; +extern x86seg * _opseg[4]; + #endif /*EMU_808X_BIU_H*/ From 561a7171c33f34c5b9df09048e68fcb8581f010f Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 30 Jan 2026 08:58:48 +0100 Subject: [PATCH 31/31] NEC Vx0: Rename the logging functions. --- src/cpu/vx0.c | 34 +++++++++++++++++----------------- src/cpu/vx0_biu.c | 34 +++++++++++++++++----------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/cpu/vx0.c b/src/cpu/vx0.c index ee26e41c5..20924ea04 100644 --- a/src/cpu/vx0.c +++ b/src/cpu/vx0.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * 808x CPU emulation, mostly ported from reenigne's XTCE, which + * Vx0 CPU emulation, mostly ported from reenigne's XTCE, which * is cycle-accurate. * * Authors: Andrew Jenner, @@ -317,25 +317,25 @@ static uint8_t modrm_cycs_post[256] = { [MODRM_ADDR_BX_SI] = 0, [MODRM_ADDR_BX_DISP16] = 2, [0x88 ... 0xff] = 0 }; -#ifdef ENABLE_808X_LOG +#ifdef ENABLE_VX0_LOG #if 0 void dumpregs(int); #endif -int x808x_do_log = ENABLE_808X_LOG; +int vx0_do_log = ENABLE_VX0_LOG; static void -x808x_log(const char *fmt, ...) +vx0_log(const char *fmt, ...) { va_list ap; - if (x808x_do_log) { + if (vx0_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -# define x808x_log(fmt, ...) +# define vx0_log(fmt, ...) #endif static i8080 emulated_processor; @@ -584,7 +584,7 @@ geteal(void) uint32_t ret; if (cpu_mod == 3) { - fatal("808x register geteal()\n"); + fatal("Vx0 register geteal()\n"); ret = 0xffffffff; } else ret = readmeml(easeg, cpu_state.eaaddr); @@ -599,7 +599,7 @@ geteaq(void) uint32_t ret; if (cpu_mod == 3) { - fatal("808x register geteaq()\n"); + fatal("Vx0 register geteaq()\n"); ret = 0xffffffff; } else ret = readmemq(easeg, cpu_state.eaaddr); @@ -669,7 +669,7 @@ static void seteal(uint32_t val) { if (cpu_mod == 3) { - fatal("808x register seteal()\n"); + fatal("Vx0 register seteal()\n"); return; } else writememl(easeg, cpu_state.eaaddr, val); @@ -679,7 +679,7 @@ static void seteaq(uint64_t val) { if (cpu_mod == 3) { - fatal("808x register seteaq()\n"); + fatal("Vx0 register seteaq()\n"); return; } else writememq(easeg, cpu_state.eaaddr, val); @@ -1023,7 +1023,7 @@ intr_routine(uint16_t intr, int skip_first) if (!(cpu_state.flags & MD_FLAG) && is_nec) { sync_from_i8080(); - x808x_log("CALLN/INT#/NMI#\n"); + vx0_log("CALLN/INT#/NMI#\n"); } if (!skip_first) @@ -1268,7 +1268,7 @@ sw_int(uint16_t intr) if (!(cpu_state.flags & MD_FLAG) && is_nec) { sync_from_i8080(); - x808x_log("CALLN/INT#/NMI#\n"); + vx0_log("CALLN/INT#/NMI#\n"); } do_cycles_i(3); @@ -1344,7 +1344,7 @@ interrupt_brkem(uint16_t addr) push(&old_ip); sync_to_i8080(); - x808x_log("BRKEM mode\n"); + vx0_log("BRKEM mode\n"); } void @@ -1367,7 +1367,7 @@ retem_i8080(void) retem = 1; - x808x_log("RETEM mode\n"); + vx0_log("RETEM mode\n"); } void @@ -1388,7 +1388,7 @@ custom_nmi(void) if (!(cpu_state.flags & MD_FLAG) && is_nec) { sync_from_i8080(); - x808x_log("CALLN/INT#/NMI#\n"); + vx0_log("CALLN/INT#/NMI#\n"); } do_cycle_i(); @@ -4705,7 +4705,7 @@ execute_instruction(void) break; default: - x808x_log("Illegal opcode: %02X\n", opcode); + vx0_log("Illegal opcode: %02X\n", opcode); biu_pfq_fetchb(); do_cycles(8); break; @@ -4759,7 +4759,7 @@ execvx0(int cycs) oldc = cpu_state.flags & C_FLAG; } - x808x_log("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); + vx0_log("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode); execute_instruction(); diff --git a/src/cpu/vx0_biu.c b/src/cpu/vx0_biu.c index 4f7a8e1d2..92f1909a6 100644 --- a/src/cpu/vx0_biu.c +++ b/src/cpu/vx0_biu.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * 808x BIU emulation. + * Vx0 BIU emulation. * * Authors: Andrew Jenner, * Miran Grca, @@ -86,22 +86,22 @@ static int dma_wait_states = 0; /* DEBUG stuff. */ const char *lpBiuStates[7] = { "Ti ", "Ti S ", "Ti D ", "Ti R ", "Tw ", "T%i PF", "T%i EU" }; -#ifdef ENABLE_808X_BIU_LOG -int x808x_biu_do_log = ENABLE_808X_BIU_LOG; +#ifdef ENABLE_VX0_BIU_LOG +int vx0_biu_do_log = ENABLE_VX0_BIU_LOG; static void -x808x_biu_log(const char *fmt, ...) +vx0_biu_log(const char *fmt, ...) { va_list ap; - if (x808x_biu_do_log) { + if (vx0_biu_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -# define x808x_biu_log(fmt, ...) +# define vx0_biu_log(fmt, ...) #endif void @@ -301,7 +301,7 @@ bus_do_io(int io_type) { int old_cycles = cycles; - x808x_biu_log("(%02X) bus_do_io(%02X): %04X\n", opcode, io_type, cpu_state.eaaddr); + vx0_biu_log("(%02X) bus_do_io(%02X): %04X\n", opcode, io_type, cpu_state.eaaddr); if (io_type & BUS_OUT) { if (io_type & BUS_WIDE) @@ -388,18 +388,18 @@ biu_print_cycle(void) if ((CS == DEBUG_SEG) && (cpu_state.pc >= DEBUG_OFF_L) && (cpu_state.pc <= DEBUG_OFF_H)) { if (biu_state >= BIU_STATE_PF) { if (biu_wait) { - x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s (%i)\n", CS, cpu_state.pc, dma_state, dma_wait_states, - pfq_pos, lpBiuStates[BIU_STATE_WAIT], wait_states); + vx0_biu_log("[%04X:%04X] [%i, %i] (%i) %s (%i)\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[BIU_STATE_WAIT], wait_states); } else { char temp[16] = { 0 }; sprintf(temp, lpBiuStates[biu_state], biu_cycles + 1); - x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, - pfq_pos, temp); + vx0_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, temp); } } else { - x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, - pfq_pos, lpBiuStates[biu_state]); + vx0_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[biu_state]); } } } @@ -456,8 +456,8 @@ static void biu_cycle_idle(int type) { if ((CS == DEBUG_SEG) && (cpu_state.pc >= DEBUG_OFF_L) && (cpu_state.pc <= DEBUG_OFF_H)) { - x808x_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, - pfq_pos, lpBiuStates[type]); + vx0_biu_log("[%04X:%04X] [%i, %i] (%i) %s\n", CS, cpu_state.pc, dma_state, dma_wait_states, + pfq_pos, lpBiuStates[type]); } run_dma_cycle(); @@ -493,7 +493,7 @@ do_bus_access(void) { int io_type = (biu_state == BIU_STATE_EU) ? bus_request_type : BUS_CODE; - x808x_biu_log("[%04X:%04X] %02X bus access %02X\n", CS, cpu_state.pc, opcode, io_type); + vx0_biu_log("[%04X:%04X] %02X bus access %02X\n", CS, cpu_state.pc, opcode, io_type); if (io_type != 0) { wait_states = 0; @@ -707,7 +707,7 @@ biu_eu_request(void) void wait_vx0(int c) { - x808x_biu_log("[%04X:%04X] %02X %i cycles\n", CS, cpu_state.pc, opcode, c); + vx0_biu_log("[%04X:%04X] %02X %i cycles\n", CS, cpu_state.pc, opcode, c); for (uint8_t i = 0; i < c; i++) biu_cycle();