From d70f43828c86d72258a2d5737531e3a94b45ab73 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Feb 2025 05:12:54 +0900 Subject: [PATCH 01/36] replace magic numbers with predifined macros --- src/video/vid_ps55da2.c | 46 +++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 31559cc52..a517b7e6c 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -54,9 +54,14 @@ #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 +#define DA2_VM03_BASECHR 0x18000 +#define DA2_VM03_BASEEXATTR 0x10000 #define DA2_INVALIDACCESS8 0xff #define DA2_MASK_MMIO 0x1ffff -#define DA2_MASK_GRAM 0x1ffff +#define DA2_SIZE_VRAM 1024 * 1024 /* 0x100000 */ +#define DA2_SIZE_CRAM 4 * 1024 /* 0x1000 */ +#define DA2_SIZE_GAIJIRAM 256 * 1024 /* 0x40000 */ +#define DA2_MASK_A000 0x1ffff #define DA2_MASK_CRAM 0xfff #define DA2_MASK_GAIJIRAM 0x3ffff #define DA2_PIXELCLOCK 58000000.0 @@ -243,7 +248,7 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -// #define ENABLE_DA2_LOG 1 +#define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG @@ -370,7 +375,7 @@ typedef struct da2_t { { int enable; mem_mapping_t mapping; - uint8_t ram[256 * 1024]; + uint8_t ram[DA2_SIZE_GAIJIRAM]; uint8_t *font; int charset; } mmio; @@ -1855,10 +1860,10 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2->vram[(0x18000 + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((0x18000 + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((0x10000 + (da2->ma)) + 1) & da2->vram_mask]; - // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (0x18000 + da2->ma << 1) & da2->vram_mask, chr, attr); + chr = da2->vram[(DA2_VM03_BASECHR + (da2->ma)) & da2->vram_mask]; + attr = da2->vram[((DA2_VM03_BASECHR + (da2->ma)) + 1) & da2->vram_mask]; + extattr = da2->vram[((DA2_VM03_BASEEXATTR + (da2->ma)) + 1) & da2->vram_mask]; + // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; // fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg; @@ -1875,7 +1880,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->vram[(0x18000 + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs = da2->vram[(DA2_VM03_BASECHR + (da2->ma) + 2) & da2->vram_mask]; chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -1887,11 +1892,9 @@ da2_render_textm3(da2_t *da2) } } else { /* the char code is SBCS (ANK) */ - uint32_t fontbase; - fontbase = DA2_GAIJIRAM_SBCS; - uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint16_t font = da2->mmio.ram[DA2_GAIJIRAM_SBCS + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + font |= da2->mmio.ram[DA2_GAIJIRAM_SBCS+ chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2101,10 +2104,10 @@ da2_recalctimings(da2_t *da2) if (da2->crtc[LC_VIEWPORT_PRIORITY] & 0x80) { da2_log("Set videomode to PS/55 8 bpp graphics.\n"); da2->render = da2_render_color_8bpp; - da2->vram_display_mask = DA2_MASK_GRAM; + da2->vram_display_mask = DA2_MASK_A000; } else { /* PS/55 8-color */ da2_log("Set videomode to PS/55 4 bpp graphics.\n"); - da2->vram_display_mask = DA2_MASK_GRAM; + da2->vram_display_mask = DA2_MASK_A000; da2->render = da2_render_color_4bpp; } } else { @@ -3029,12 +3032,11 @@ da2_init(UNUSED(const device_t *info)) da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; - int memsize = 1024 * 1024; - da2->vram = calloc(1, memsize); - da2->vram_mask = memsize - 1; - da2->cram = calloc(1, 0x1000); + da2->vram = calloc(1, DA2_SIZE_VRAM); + da2->vram_mask = DA2_SIZE_VRAM - 1; + da2->cram = calloc(1, DA2_SIZE_CRAM); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ 0x1000000 >> 12); /* XX000h */ + da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ DA2_SIZE_VRAM >> 12); /* XX000h */ da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ da2->mmio.charset = device_get_config_int("charset"); @@ -3095,17 +3097,17 @@ da2_close(void *p) FILE *f; f = fopen("da2_cram.dmp", "wb"); if (f != NULL) { - fwrite(da2->cram, 0x1000, 1, f); + fwrite(da2->cram, DA2_SIZE_CRAM, 1, f); fclose(f); } f = fopen("da2_vram.dmp", "wb"); if (f != NULL) { - fwrite(da2->vram, 1024 * 1024, 1, f); + fwrite(da2->vram, DA2_SIZE_VRAM, 1, f); fclose(f); } f = fopen("da2_gram.dmp", "wb"); if (f != NULL) { - fwrite(da2->mmio.ram, 256 * 1024, 1, f); + fwrite(da2->mmio.ram, DA2_SIZE_GAIJIRAM, 1, f); fclose(f); } f = fopen("da2_attrpal.dmp", "wb"); From 4bc47894de81c995c36592b2a1eeafb59e9846c1 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Mon, 24 Feb 2025 05:53:34 +0900 Subject: [PATCH 02/36] safety read/write vram memory --- src/video/vid_ps55da2.c | 112 ++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index a517b7e6c..7c7891926 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -437,12 +437,19 @@ typedef struct { /* safety read for internal functions */ uint32_t -DA2_readvram_s(uint32_t addr, da2_t *da2) +DA2_vram_r(uint32_t addr, da2_t *da2) { if (addr & ~da2->vram_mask) return -1; return da2->vram[addr]; } +/* safety write for internal functions */ +void +DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) +{ + da2->vram[addr & da2->vram_mask] = val; + return; +} void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) @@ -455,10 +462,10 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) - writepx[i] = DA2_readvram_s((destaddr + 24) | i, da2) - | (DA2_readvram_s((destaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((destaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((destaddr + 0) | i, da2) << 24); + writepx[i] = DA2_vram_r((destaddr + 24) | i, da2) + | (DA2_vram_r((destaddr + 16) | i, da2) << 8) + | (DA2_vram_r((destaddr + 8) | i, da2) << 16) + | (DA2_vram_r((destaddr + 0) | i, da2) << 24); DA2_VidSeq32 mask32in; mask32in.d = (uint32_t) mask; @@ -487,8 +494,8 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s } } for (int i = 0; i < 8; i++) { - da2->vram[(da2->vram_mask & destaddr) | i] = (writepx[i] >> 24) & 0xff; - da2->vram[(da2->vram_mask & (destaddr + 8)) | i] = (writepx[i] >> 16) & 0xff; + DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); + DA2_vram_w((destaddr + 8) | i, (writepx[i] >> 16) & 0xff, da2); } } @@ -531,10 +538,10 @@ DA2_CopyPlaneDataWithBitmask(uint32_t srcaddr, uint32_t destaddr, uint16_t mask, srcaddr &= 0xfffffffe; srcaddr <<= 3; for (int i = 0; i < 8; i++) - srcpx.p8[i] = DA2_readvram_s((srcaddr + 24) | i, da2) - | (DA2_readvram_s((srcaddr + 16) | i, da2) << 8) - | (DA2_readvram_s((srcaddr + 8) | i, da2) << 16) - | (DA2_readvram_s((srcaddr + 0) | i, da2) << 24); + srcpx.p8[i] = DA2_vram_r((srcaddr + 24) | i, da2) + | (DA2_vram_r((srcaddr + 16) | i, da2) << 8) + | (DA2_vram_r((srcaddr + 8) | i, da2) << 16) + | (DA2_vram_r((srcaddr + 0) | i, da2) << 24); DA2_WritePlaneDataWithBitmask(destaddr, mask, &srcpx, da2); } @@ -560,7 +567,7 @@ pixel1tohex(uint32_t addr, int index, da2_t *da2) { uint8_t pixeldata = 0; for (int j = 0; j < 8; j++) { - if (da2->vram[(da2->vram_mask & (addr << 3)) | j] & (1 << (7 - index))) + if (DA2_vram_r(((addr << 3) | j) & (1 << (7 - index)), da2)) pixeldata++; } return pixeldata; @@ -1724,8 +1731,8 @@ da2_render_text(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2->cram[(da2->ma) & da2->vram_display_mask]; - attr = da2->cram[((da2->ma) + 1) & da2->vram_display_mask]; + chr = da2->cram[(da2->ma) & DA2_MASK_CRAM]; + attr = da2->cram[((da2->ma) + 1) & DA2_MASK_CRAM]; // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* IO 3E8h, Index 1Dh */ { /* --Parse attribute byte in color mode-- */ @@ -1860,9 +1867,9 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = da2->vram[(DA2_VM03_BASECHR + (da2->ma)) & da2->vram_mask]; - attr = da2->vram[((DA2_VM03_BASECHR + (da2->ma)) + 1) & da2->vram_mask]; - extattr = da2->vram[((DA2_VM03_BASEEXATTR + (da2->ma)) + 1) & da2->vram_mask]; + chr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma), da2); + attr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 1, da2); + extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + (da2->ma) + 1, da2); // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; @@ -1880,7 +1887,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->vram[(DA2_VM03_BASECHR + (da2->ma) + 2) & da2->vram_mask]; + chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -2116,9 +2123,7 @@ da2_recalctimings(da2_t *da2) da2_log("Set videomode to PS/55 Mode 03 text.\n"); da2->render = da2_render_textm3; da2->vram_display_mask = DA2_MASK_CRAM; - } - /* PS/55 text(color/mono) */ - else { + } else { /* PS/55 text(color/mono) */ da2_log("Set videomode to PS/55 Mode 8/E text.\n"); da2->render = da2_render_text; da2->vram_display_mask = DA2_MASK_CRAM; @@ -2243,19 +2248,19 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->gdcsrc[i] & ~bitmask); // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask) & da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) | da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask) ^ da2->gdcsrc[i]; - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask); + DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask) | (da2->vram[addr | i] & ~bitmask), da2); break; } } @@ -2273,30 +2278,30 @@ da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) case 0: /*Set*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->gdcsrc[i] & ~bitmask_l); // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | ((da2->gdcsrc[i] >> 8) & ~bitmask_h); - da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, (da2->gdcinput[i] & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, ((da2->gdcinput[i] >> 8) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 1: /*AND*/ // da2->vram[addr | i] = (da2->gdcinput[i] | ~bitmask_l) & da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) | ~bitmask_h) & (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] & da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) & (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 2: /*OR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) | da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) | (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] | da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) | (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; case 3: /*XOR*/ // da2->vram[addr | i] = (da2->gdcinput[i] & bitmask_l) ^ da2->gdcsrc[i]; // da2->vram[(addr + 8) | i] = ((da2->gdcinput[i] >> 8) & bitmask_h) ^ (da2->gdcsrc[i] >> 8); - da2->vram[addr | i] = ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l); - da2->vram[(addr + 8) | i] = (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) - | (da2->vram[(addr + 8) | i] & ~bitmask_h); + DA2_vram_w(addr | i, ((da2->gdcinput[i] ^ da2->gdcsrc[i]) & bitmask_l) | (da2->vram[addr | i] & ~bitmask_l), da2); + DA2_vram_w((addr + 8) | i, (((da2->gdcinput[i] >> 8) ^ (da2->gdcsrc[i] >> 8)) & bitmask_h) + | (da2->vram[(addr + 8) | i] & ~bitmask_h), da2); break; } } @@ -2359,7 +2364,6 @@ da2_mmio_read(uint32_t addr, void *p) } else return da2->gdcla[da2->readplane]; } else { /* text mode 3 */ - cycles -= video_timing_read_b; return da2->vram[addr]; } @@ -2371,8 +2375,7 @@ da2_mmio_readw(uint32_t addr, void *p) //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); - } else if (!(da2->ioctl[LS_MODE] & 1)) /* 16 color or 256 color mode */ - { + } else if (!(da2->ioctl[LS_MODE] & 1)) {/* 16 color or 256 color mode */ cycles -= video_timing_read_w; addr &= DA2_MASK_MMIO; for (int i = 0; i < 8; i++) @@ -2417,8 +2420,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) { da2_t *da2 = (da2_t *) p; // da2_log("da2_mmio_write %x %x\n", addr, val); - if ((addr & ~DA2_MASK_MMIO) != 0xA0000) - return; + // if ((addr & ~DA2_MASK_MMIO) != 0xA0000) + // return; addr &= DA2_MASK_MMIO; if (da2->ioctl[LS_MMIO] & 0x10) { @@ -2434,8 +2437,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } switch (da2->fctl[LF_MMIO_MODE]) { case 0xb0: /* Gaiji RAM 1011 0000 */ - addr &= DA2_MASK_GAIJIRAM; /* safety access */ - da2->mmio.ram[addr] = val; + da2->mmio.ram[addr & DA2_MASK_GAIJIRAM] = val; break; case 0x10: /* Font ROM 0001 0000 */ /* Read-Only */ @@ -2509,7 +2511,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = da2->gdcsrc[i]; + DA2_vram_w(addr | i, da2->gdcsrc[i], da2); break; case 0:/* equiv to vga write mode 0 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2517,7 +2519,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = val; + DA2_vram_w(addr | i, val, da2); } else { for (int i = 0; i < 8; i++) if (da2->gdcreg[LG_ENABLE_SRJ] & (1 << i)) @@ -2537,7 +2539,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) - da2->vram[addr | i] = (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2); //fprintf(da2->mmdbg_fp, "m1-1"); } else { for (int i = 0; i < 8; i++) @@ -2559,7 +2561,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) // da2_log("%02x%02x%02x%02x\n", da2->vram[addr + 0], da2->vram[addr + 1], da2->vram[addr + 2], da2->vram[addr + 3]); } else { /* mode 3h text */ cycles -= video_timing_write_b; - da2->vram[addr] = val; + DA2_vram_w(addr, val, da2); da2->fullchange = 2; } } @@ -2622,8 +2624,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) case 2: for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - da2->vram[addr | i] = da2->gdcsrc[i] & 0xff; - da2->vram[(addr + 8) | i] = da2->gdcsrc[i] >> 8; + DA2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); + DA2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); } break; case 0: @@ -2632,8 +2634,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - da2->vram[addr | i] = val & 0xff; - da2->vram[(addr + 8) | i] = val >> 8; + DA2_vram_w(addr | i, val & 0xff, da2); + DA2_vram_w((addr + 8) | i, val >> 8, da2); } } else { for (int i = 0; i < 8; i++) @@ -2649,9 +2651,9 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->writemask & (1 << i)) { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - da2->vram[addr | i] = wdata & 0xff; - da2->vram[(addr + 8) | i] = wdata >> 8; + uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + DA2_vram_w(addr | i, wdata & 0xff, da2); + DA2_vram_w((addr + 8) | i, wdata >> 8, da2); } } else { for (int i = 0; i < 8; i++) From 50300a1d9a949ccfb59b2b00a8bd9b794c802527 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:08:12 +0900 Subject: [PATCH 03/36] Add line drawing function (incomplete) remains a bug that the second hand doesn't appear in the Clock app of Windows 3.1. --- src/video/vid_ps55da2.c | 163 ++++++++++++++++++++++++++++++++++------ 1 file changed, 138 insertions(+), 25 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 7c7891926..f157d8fca 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -87,8 +87,9 @@ #define DA2_BLT_CCOPYF 3 #define DA2_BLT_CCOPYR 4 #define DA2_BLT_CPUTCHAR 5 -#define DA2_BLT_CDONE 6 -#define DA2_BLT_CLOAD 7 +#define DA2_BLT_CLINE 6 +#define DA2_BLT_CDONE 7 +#define DA2_BLT_CLOAD 8 /* POS ID = 0xeffe : Display Adapter II, III, V */ #define DA2_POSID_H 0xef #define DA2_POSID_L 0xfe @@ -253,7 +254,9 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 +// # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; static void @@ -388,6 +391,7 @@ typedef struct da2_t { #ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug + int debug_exesteps; #endif int payload_addr; pc_timer_t timer; @@ -398,14 +402,20 @@ typedef struct da2_t { int32_t srcaddr; int32_t size_x, tile_w; int32_t size_y; + int32_t dest_x; + int32_t dest_y; int16_t destpitch; int16_t srcpitch; int32_t fcolor; int32_t maskl, maskr; + int32_t count; + // int32_t countj; + int32_t d; + int octdir; int x, y; } bitblt; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM FILE *mmdbg_fp; FILE *mmrdbg_fp; uint32_t mmdbg_vidaddr; @@ -520,7 +530,7 @@ Param Desc 0A Plane Mask? 0B ROP?(8h or 200h + 0-3h) 0D -20 Exec (1) +20 Exec (1) or Exec without reset regs (21h) 21 ? 22 ? 23 Tile W @@ -718,6 +728,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_reg_ip++; if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; + da2->bitblt.debug_exesteps = 0; #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ @@ -749,11 +760,14 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ - { - da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - da2->bitblt.exec = DA2_BLT_CDONE; - } else if (da2->bitblt.reg[0x10] == 0xbc04) { /* Put char used by OS/2 (i'm not sure what the condition is) */ + // if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ + // { + // da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); + // da2->bitblt.exec = DA2_BLT_CDONE; + // } else + + /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ + if (da2->bitblt.reg[0x10] == 0xbc04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; /* Todo: addressing */ // if (da2->bitblt.reg[0x2F] == 0x90) /* destaddr -= 2, length += 1; */ @@ -776,7 +790,9 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif - } else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { + } + /* Put SBCS char used by OS/2 */ + else if (da2->bitblt.reg[0x10] == 0x0004 || da2->bitblt.reg[0x10] == 0x0E04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; @@ -792,7 +808,36 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.size_x, da2->bitblt.size_y, sjis_h, sjis_l); #endif } - /* Fill a rectangle(or draw a line) */ + /* Draw a line */ + else if (da2->bitblt.reg[0x5] == 0x43) { + // da2_log("drawline x=%d, y=%d, 24=%d, 2A=%d, 2B=%d, 2D=%d\n", + // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + // n24, n2a, n2b, da2->bitblt.reg[0x2D]); + da2->bitblt.exec = DA2_BLT_CLINE; + da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); + da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); + da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); + da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); + // da2->bitblt.raster_op = 0; + da2->bitblt.count = 0; + da2->bitblt.octdir = da2->bitblt.reg[0x2D]; + da2->bitblt.bitshift_destr = 0; + if (da2->bitblt.octdir & 0x04) /* dX > dY */ + da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; + else + da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; + da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", + da2->bitblt.dest_x, da2->bitblt.dest_y, + da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); + // FILE *f = fopen("da2_drawline.csv", "a"); + // if (f != NULL) { + // fprintf(f,"drawline,%d,%d,%d,%d,%d,%d\n", + // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), + // n24, n2a, n2b, da2->bitblt.reg[0x2D]); + // fclose(f); + // } + } + /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { da2_log("fillrect x=%d, y=%d, w=%d, h=%d, c=%d, 2f=%x, rowcount=%x\n", da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), @@ -824,7 +869,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), da2->bitblt.size_x, da2->bitblt.size_y); } - /* Block transfer (range copy) */ + /* Block copy */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x1040 && da2->bitblt.reg[0x3D] == 0x00) { da2->bitblt.exec = DA2_BLT_CCOPYF; da2->bitblt.srcaddr = da2->bitblt.reg[0x2A]; @@ -855,7 +900,13 @@ da2_bitblt_exec(void *p) { da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); +#ifdef ENABLE_DA2_DEBUGBLT + if(!(da2->bitblt.debug_exesteps & 0xf)) + da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); + da2->bitblt.debug_exesteps++; +#else da2_log("bitblt_exec: %d\n", da2->bitblt.exec); +#endif // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: @@ -865,6 +916,60 @@ da2_bitblt_exec(void *p) da2->bitblt.indata = 0; da2_bitblt_load(da2); break; + case DA2_BLT_CLINE: + int pos_x = da2->bitblt.dest_x + da2->bitblt.x; + int pos_y = da2->bitblt.dest_y + da2->bitblt.y; + + /* Draw a dot */ + // outb(0x680, da2->bitblt.octdir); + // da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; + int pixelmask = pos_x % 16; + if (pixelmask >= 8) + pixelmask = (0x8000 >> (pixelmask - 8)); + else + pixelmask = (0x80 >> pixelmask); + DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + // da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask); + da2->bitblt.count++; + + /* Bresenham's line */ + if (da2->bitblt.octdir & 0x04) { /* dX > dY */ + if (da2->bitblt.octdir & 0x02) { + da2->bitblt.x++; + } else { + da2->bitblt.x--; + } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_x); + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_y); + if (da2->bitblt.count >= da2->bitblt.size_x) + da2->bitblt.exec = DA2_BLT_CDONE; + } else { + if (da2->bitblt.octdir & 0x01) { + da2->bitblt.y++; + } else { + da2->bitblt.y--; + } + if (da2->bitblt.d >= 0) { + da2->bitblt.d -= (2 * da2->bitblt.size_y); + if (da2->bitblt.octdir & 0x02) { + da2->bitblt.x++; + } else { + da2->bitblt.x--; + } + } + da2->bitblt.d += (2 * da2->bitblt.size_x); + if (da2->bitblt.count >= da2->bitblt.size_y) + da2->bitblt.exec = DA2_BLT_CDONE; + } + break; case DA2_BLT_CFILLRECT: // da2_log("%x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); if (da2->bitblt.x >= da2->bitblt.size_x - 1) { @@ -982,11 +1087,14 @@ da2_bitblt_exec(void *p) // da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + (da2->bitblt.x * 2 ) + (da2->bitblt.y * 3) + 2; break; case DA2_BLT_CDONE: - /* initialize regs for debug dump */ - for (int i = 0; i < DA2_BLT_REGSIZE; i++) { - if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) - da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; - } + if (!(da2->bitblt.reg[0x20] & 0x20)) { + /* initialize regs and set magic value for debug dump */ + for (int i = 0; i < DA2_BLT_REGSIZE; i++) { + if (da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) + da2->bitblt.reg[i] = DA2_DEBUG_BLT_USEDRESET; + } + } else /* without init regs */ + da2->bitblt.reg[0x20] = 0; /* need to stop execution */ if (da2->bitblt.indata) da2->bitblt.exec = DA2_BLT_CLOAD; else @@ -1013,7 +1121,7 @@ da2_bitblt_dopayload(void *priv) // } if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) /* for OS/2 J1.3 */ + else if (da2->bitblt.indata) { if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; @@ -1339,9 +1447,10 @@ da2_in(uint16_t addr, void *p) } if (da2->bitblt.indata) temp |= 0x08; - da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); +#ifdef ENABLE_DA2_DEBUGMONWAIT + da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); +#endif } - // da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr,temp, cs >> 4, cpu_state.pc); break; case LF_INDEX: temp = da2->fctladdr; @@ -2381,7 +2490,7 @@ da2_mmio_readw(uint32_t addr, void *p) for (int i = 0; i < 8; i++) da2->gdcla[i] = (uint16_t) (da2->vram[(addr << 3) | i]) | ((uint16_t) (da2->vram[((addr << 3) + 8) | i]) << 8); /* read vram into latch */ -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM ////debug // if (((int)addr - (int)da2->mmrdbg_vidaddr) > 2 || (((int)da2->mmrdbg_vidaddr - (int)addr) > 2) || da2->mmrdbg_vidaddr == addr) //{ @@ -2465,7 +2574,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) /* align bitmask to even address */ if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_wB %x %02x\n", addr, val); // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ @@ -2577,7 +2686,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; -#ifdef ENABLE_DA2_DEBUGBLT +#ifdef ENABLE_DA2_DEBUGVRAM // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { @@ -3061,9 +3170,11 @@ da2_init(UNUSED(const device_t *info)) memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT da2->bitblt.debug_reg = malloc(DA2_DEBUG_BLTLOG_MAX * DA2_DEBUG_BLTLOG_SIZE); + da2->bitblt.debug_reg_ip = 0; +#endif +#ifdef ENABLE_DA2_DEBUGVRAM da2->mmdbg_fp = fopen("da2_mmiowdat.txt", "w"); da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); - da2->bitblt.debug_reg_ip = 0; #endif da2->bitblt.payload_addr = 0; da2_reset(da2); @@ -3162,11 +3273,13 @@ da2_close(void *p) } fclose(f); } + free(da2->bitblt.debug_reg); +#endif +#ifdef ENABLE_DA2_DEBUGVRAM if (da2->mmdbg_fp != NULL) fclose(da2->mmdbg_fp); if (da2->mmrdbg_fp != NULL) fclose(da2->mmrdbg_fp); - free(da2->bitblt.debug_reg); #endif free(da2->cram); free(da2->vram); From e9b8bbd0be4c575e5d420fbb24956c660776bcdf Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 25 Feb 2025 11:59:46 +0900 Subject: [PATCH 04/36] add bit invert operation in bitblt --- src/video/vid_ps55da2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f157d8fca..4922c6d30 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -502,6 +502,8 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s writepx[i] ^= srcpx->p8[i] & mask32.d; break; } + if (da2->bitblt.raster_op & 0x20) /* NOT */ + writepx[i] ^= 0xFFFFFFFF & mask32.d; } for (int i = 0; i < 8; i++) { DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); @@ -524,11 +526,11 @@ Param Desc 01 Color 03 Bit Shift 04 Select plane? -05 Dir(10 or 11) + Command?(40 or 48) +05 Dir(1000h or 1100h) + Command?(40 or 48) 08 Mask Left 09 Mask Right 0A Plane Mask? -0B ROP?(8h or 200h + 0-3h) +0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) 0D 20 Exec (1) or Exec without reset regs (21h) 21 ? @@ -709,9 +711,9 @@ da2_bitblt_load(da2_t *da2) i++; } da2->bitblt.exec = DA2_BLT_CIDLE; - // /* clear payload memory */ - // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - // da2->bitblt.payload_addr = 0; + /* clear payload memory */ + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { /* clear payload memory */ @@ -731,7 +733,7 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.debug_exesteps = 0; #endif da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x03; /* 01 AND, 03 XOR */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x23; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); // for (int i = 0; i <= 0xb; i++) // { @@ -780,7 +782,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 72 + 2; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; @@ -797,7 +798,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.srcaddr = da2->bitblt.reg[0x12] * 64 + 2 + DA2_FONTROM_BASESBCS; da2->bitblt.destaddr += 2; da2->bitblt.srcpitch = 0; - da2->bitblt.raster_op = da2->bitblt.reg[0x05] & 0x03; /* XOR */ da2->bitblt.bitshift_destr += 1; #ifdef ENABLE_DA2_DEBUGBLT uint32_t sjis_h = IBMJtoSJIS(da2->bitblt.reg[0x12]) >> 8; From 813afb8562d8cab16c7fdc88ad066015504584d7 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 26 Feb 2025 04:16:36 +0900 Subject: [PATCH 05/36] change bitblt exec speed slower probably the real machine is slower than this --- src/video/vid_ps55da2.c | 40 ++++++---------------------------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 4922c6d30..fa43ebeb6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -532,7 +532,7 @@ Param Desc 0A Plane Mask? 0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) 0D -20 Exec (1) or Exec without reset regs (21h) +20 Exec (1) or Exec without reset regs? (21h) 21 ? 22 ? 23 Tile W @@ -762,12 +762,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.exec = DA2_BLT_CDONE; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - // if (da2->bitblt.reg[0x2f] < 0x80) /* MS Paint 3.1 will cause hang up in 256 color mode */ - // { - // da2_log("bitblt not executed 2f:%x\n", da2->bitblt.reg[0x2f]); - // da2->bitblt.exec = DA2_BLT_CDONE; - // } else - /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ if (da2->bitblt.reg[0x10] == 0xbc04) { da2->bitblt.exec = DA2_BLT_CPUTCHAR; @@ -810,15 +804,11 @@ da2_bitblt_load(da2_t *da2) } /* Draw a line */ else if (da2->bitblt.reg[0x5] == 0x43) { - // da2_log("drawline x=%d, y=%d, 24=%d, 2A=%d, 2B=%d, 2D=%d\n", - // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - // n24, n2a, n2b, da2->bitblt.reg[0x2D]); da2->bitblt.exec = DA2_BLT_CLINE; da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); - // da2->bitblt.raster_op = 0; da2->bitblt.count = 0; da2->bitblt.octdir = da2->bitblt.reg[0x2D]; da2->bitblt.bitshift_destr = 0; @@ -829,13 +819,6 @@ da2_bitblt_load(da2_t *da2) da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", da2->bitblt.dest_x, da2->bitblt.dest_y, da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); - // FILE *f = fopen("da2_drawline.csv", "a"); - // if (f != NULL) { - // fprintf(f,"drawline,%d,%d,%d,%d,%d,%d\n", - // da2->bitblt.reg[0x29] % (da2->rowoffset * 2), da2->bitblt.reg[0x29] / (da2->rowoffset * 2), - // n24, n2a, n2b, da2->bitblt.reg[0x2D]); - // fclose(f); - // } } /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { @@ -922,7 +905,7 @@ da2_bitblt_exec(void *p) /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - // da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; int pixelmask = pos_x % 16; if (pixelmask >= 8) @@ -1107,26 +1090,15 @@ da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - // if (da2->bitblt.indata) /* for OS/2 J1.3 */ - // { - // if (da2->bitblt.exec == DA2_BLT_CIDLE) { - // da2->bitblt.exec = DA2_BLT_CLOAD; - // /* do all queues (ignore async executing) for OS/2 J1.3 commannd prompt that doesn't wait for idle */ - // da2_log("da2 Do bitblt\n"); - // while (da2->bitblt.exec != DA2_BLT_CIDLE) { - // da2_bitblt_exec(da2); - // } - // da2_log("da2 End bitblt %x\n", da2->bitblt.exec); - // } - // } if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) - { + else if (da2->bitblt.indata) { if (da2->bitblt.exec == DA2_BLT_CIDLE) { da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); } + } else { + // timer_disable(&da2->bitblt.timer); } } @@ -3189,7 +3161,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 1 * TIMER_USEC; + da2->bitblt.timerspeed = 10 * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From 3cde104ff683bb91c71768d32fbd8c8a26bf643b Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 27 Feb 2025 08:29:06 +0900 Subject: [PATCH 06/36] add inversion ROPs (still in debug) --- src/video/vid_ps55da2.c | 75 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index fa43ebeb6..91752a7a8 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -387,13 +387,13 @@ typedef struct da2_t { int bitshift_destr; int raster_op; uint8_t payload[DA2_BLT_MEMSIZE]; + int payload_addr; int32_t reg[DA2_BLT_REGSIZE]; // must be signed int #ifdef ENABLE_DA2_DEBUGBLT int32_t *debug_reg; // for debug int debug_reg_ip; // for debug int debug_exesteps; #endif - int payload_addr; pc_timer_t timer; int64_t timerspeed; int exec; @@ -409,7 +409,6 @@ typedef struct da2_t { int32_t fcolor; int32_t maskl, maskr; int32_t count; - // int32_t countj; int32_t d; int octdir; int x, y; @@ -460,7 +459,7 @@ DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) da2->vram[addr & da2->vram_mask] = val; return; } - +/* write pixel data with rop (Note: bitmask must be in big endian) */ void DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *srcpx, da2_t *da2) { @@ -487,7 +486,11 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s for (int i = 0; i < 8; i++) { if (da2->bitblt.bitshift_destr > 0) srcpx->p8[i] <<= 16 - da2->bitblt.bitshift_destr; - switch (da2->bitblt.raster_op) { + if (da2->bitblt.raster_op & 0x2010) /* NOT Src or NOT Pattern */ + srcpx->p8[i] = ~srcpx->p8[i] & mask32.d; + if (da2->bitblt.raster_op & 0x20) /* Dest NOT */ + writepx[i] = (~writepx[i] & mask32.d) | (writepx[i] & ~mask32.d); + switch (da2->bitblt.raster_op & 0x03) { case 0x00: /* None */ writepx[i] &= ~mask32.d; writepx[i] |= srcpx->p8[i] & mask32.d; @@ -502,8 +505,6 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s writepx[i] ^= srcpx->p8[i] & mask32.d; break; } - if (da2->bitblt.raster_op & 0x20) /* NOT */ - writepx[i] ^= 0xFFFFFFFF & mask32.d; } for (int i = 0; i < 8; i++) { DA2_vram_w(destaddr | i, (writepx[i] >> 24) & 0xff, da2); @@ -530,7 +531,13 @@ Param Desc 08 Mask Left 09 Mask Right 0A Plane Mask? -0B ROP?(8h or 200h) + Bitop (0 None, 1 AND, 2 OR, 3 XOR) +0B ROP + 2000 NOT Source + 200 Source / Pattern + 20 NOT Dest + 10 NOT Pattern + 8 ? + 0-3 Bit op (0 None, 1 AND, 2 OR, 3 XOR) 0D 20 Exec (1) or Exec without reset regs? (21h) 21 ? @@ -602,7 +609,7 @@ print_bytetobin(uint8_t b) b <<= 1; } } -// Convert internal char code to Shift JIS code +/* Convert internal char code to Shift JIS code */ inline int isKanji1(uint8_t chr) { @@ -649,17 +656,19 @@ da2_bitblt_load(da2_t *da2) { uint32_t value32; uint64_t value64; +#ifdef ENABLE_DA2_DEBUGBLT da2_log("bltload: loading params\n"); - // da2_log("BitBlt memory:\n"); - // if (da2->bitblt.payload[0] != 0) - // for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) - // { - // int i = j * 8; - // da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], - // da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); - // } + da2_log("BitBlt memory:\n"); + if (da2->bitblt.payload[0] != 0) + for (int j = 0; j < DA2_BLT_MEMSIZE / 8; j++) + { + int i = j * 8; + da2_log("%02x %02x %02x %02x %02x %02x %02x %02x \n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); + } +#endif int i = 0; - while (i < DA2_BLT_MEMSIZE) { + while (i < da2->bitblt.payload_addr) { if (da2->bitblt.reg[0x20] & 0x1) break; switch (da2->bitblt.payload[i]) { @@ -712,36 +721,26 @@ da2_bitblt_load(da2_t *da2) } da2->bitblt.exec = DA2_BLT_CIDLE; /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; + // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + // da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { /* clear payload memory */ memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT - for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { - // if(da2->bitblt.reg[i] != 0xfefe && da2->bitblt.reg[i] != DA2_DEBUG_BLT_NEVERUSED) da2_log("%02x: %04x (%d)\n",i, da2->bitblt.reg[i], da2->bitblt.reg[i]); - } for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; } da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * (da2->bitblt.debug_reg_ip + 1) - 1] = 0; da2->bitblt.debug_reg_ip++; - if (da2->bitblt.debug_reg_ip >= DA2_DEBUG_BLTLOG_MAX) + if ((DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip) >= DA2_DEBUG_BLTLOG_MAX) da2->bitblt.debug_reg_ip = 0; da2->bitblt.debug_exesteps = 0; #endif - da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ - da2->bitblt.raster_op = da2->bitblt.reg[0x0b] & 0x23; /* 01 AND, 03 XOR */ da2_log("bltload_exec: %x, rop: %x CS:PC=%4x:%4x\n", da2->bitblt.reg[0x5], da2->bitblt.reg[0x0b], CS, cpu_state.pc); - // for (int i = 0; i <= 0xb; i++) - // { - // da2_log("%02x ", da2->gdcreg[i]); - // da2->gdcreg[i] = da2->bitblt.reg[i] & 0xff; - // } - // da2_log("\n"); - + da2->bitblt.bitshift_destr = ((da2->bitblt.reg[0x3] >> 4) & 0x0f); /* set bit shift */ + da2->bitblt.raster_op = da2->bitblt.reg[0x0b]; da2->bitblt.destaddr = da2->bitblt.reg[0x29]; da2->bitblt.size_x = da2->bitblt.reg[0x33]; da2->bitblt.size_y = da2->bitblt.reg[0x35]; @@ -890,14 +889,13 @@ da2_bitblt_exec(void *p) #else da2_log("bitblt_exec: %d\n", da2->bitblt.exec); #endif - // da2_log("blt %x %x %x %x\n", da2->bitblt.destaddr, da2->bitblt.x, da2->bitblt.y); switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: // timer_disable(&da2->bitblt.timer); break; case DA2_BLT_CLOAD: - da2->bitblt.indata = 0; da2_bitblt_load(da2); + da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: int pos_x = da2->bitblt.dest_x + da2->bitblt.x; @@ -1512,7 +1510,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p) void da2_outw(uint16_t addr, uint16_t val, void *p) { - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -2534,8 +2532,10 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) da2->bitblt.indata = 1; if (da2->bitblt.payload_addr >= DA2_BLT_MEMSIZE) da2_log("da2_mmio_write payload overflow! mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); - da2->bitblt.payload[da2->bitblt.payload_addr] = val; - da2->bitblt.payload_addr++; + else { + da2->bitblt.payload[da2->bitblt.payload_addr] = val; + da2->bitblt.payload_addr++; + } break; default: da2_log("da2_mmio_write failed mem %x, addr %x, val %x\n", da2->fctl[LF_MMIO_MODE], addr, val); @@ -3008,7 +3008,6 @@ da2_loadfont(char *fname, void *p) { da2_t *da2 = (da2_t *) p; uint8_t buf; - // uint32_t code = 0; uint64_t fsize; if (!fname) return; From e49be34d3070730b63053a0df9bdffa833c01e8e Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Thu, 27 Feb 2025 11:15:57 +0900 Subject: [PATCH 07/36] fix an issue when loading bitblt data in async --- src/video/vid_ps55da2.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 91752a7a8..f8c72833e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -273,6 +273,11 @@ da2_log(const char *fmt, ...) #else # define da2_log(fmt, ...) #endif +#ifdef ENABLE_DA2_DEBUGBLT +# define da2_bltlog da2_log +#else +# define da2_bltlog(fmt, ...) +#endif typedef struct da2_t { // mem_mapping_t vmapping; @@ -678,7 +683,7 @@ da2_bitblt_load(da2_t *da2) value32 = da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_bltlog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; @@ -690,7 +695,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 3]; value32 <<= 8; value32 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); + da2_bltlog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; @@ -706,7 +711,7 @@ da2_bitblt_load(da2_t *da2) value64 |= da2->bitblt.payload[i + 3]; value64 <<= 8; value64 |= da2->bitblt.payload[i + 2]; - da2_log("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], + da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; i += 7; @@ -721,13 +726,10 @@ da2_bitblt_load(da2_t *da2) } da2->bitblt.exec = DA2_BLT_CIDLE; /* clear payload memory */ - // memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - // da2->bitblt.payload_addr = 0; + memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); + da2->bitblt.payload_addr = 0; /* [89] 20: 0001 (1) then execute payload */ if (da2->bitblt.reg[0x20] & 0x1) { - /* clear payload memory */ - memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); - da2->bitblt.payload_addr = 0; #ifdef ENABLE_DA2_DEBUGBLT for (i = 0; i < DA2_DEBUG_BLTLOG_SIZE; i++) { da2->bitblt.debug_reg[DA2_DEBUG_BLTLOG_SIZE * da2->bitblt.debug_reg_ip + i] = da2->bitblt.reg[i]; @@ -759,7 +761,6 @@ da2_bitblt_load(da2_t *da2) da2->bitblt.x = 0; da2->bitblt.y = 0; da2->bitblt.exec = DA2_BLT_CDONE; - timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* Put DBCS char used by OS/2 (i'm not sure what the condition is) */ if (da2->bitblt.reg[0x10] == 0xbc04) { @@ -886,8 +887,6 @@ da2_bitblt_exec(void *p) if(!(da2->bitblt.debug_exesteps & 0xf)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; -#else - da2_log("bitblt_exec: %d\n", da2->bitblt.exec); #endif switch (da2->bitblt.exec) { case DA2_BLT_CIDLE: @@ -903,7 +902,7 @@ da2_bitblt_exec(void *p) /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - da2_log("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + da2_bltlog("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; int pixelmask = pos_x % 16; if (pixelmask >= 8) @@ -1090,11 +1089,9 @@ da2_bitblt_dopayload(void *priv) timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); if (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); - else if (da2->bitblt.indata) { - if (da2->bitblt.exec == DA2_BLT_CIDLE) { + else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { da2->bitblt.exec = DA2_BLT_CLOAD; da2_bitblt_exec(da2); - } } else { // timer_disable(&da2->bitblt.timer); } @@ -2656,6 +2653,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + addr &= DA2_MASK_MMIO; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM @@ -2676,7 +2674,6 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) //} #endif cycles -= video_timing_write_w; - // cycles_lost += video_timing_write_w; // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); @@ -2765,7 +2762,6 @@ da2_mmio_writew(uint32_t addr, uint16_t val, void *p) da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ - addr &= DA2_MASK_MMIO; // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); @@ -2808,8 +2804,8 @@ static uint8_t da2_code_read(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - if ((addr & ~DA2_MASK_CRAM) != 0xE0000) - return DA2_INVALIDACCESS8; + // if ((addr & ~DA2_MASK_CRAM) != 0xE0000) + // return DA2_INVALIDACCESS8; addr &= DA2_MASK_CRAM; return da2->cram[addr]; } From 95f12bc206e955324731bfcac18025f034d6db09 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Feb 2025 00:50:01 +0900 Subject: [PATCH 08/36] fix glitch in Bitblt's line drawing function fix a line glitch issue occurs in MS Paint and QEMM Manifest apps. --- src/video/vid_ps55da2.c | 58 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index f8c72833e..c476d12b9 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -405,10 +405,11 @@ typedef struct da2_t { int indata; int32_t destaddr; int32_t srcaddr; - int32_t size_x, tile_w; - int32_t size_y; - int32_t dest_x; - int32_t dest_y; + int16_t size_x; + int16_t tile_w; + int16_t size_y; + int16_t dest_x; + int16_t dest_y; int16_t destpitch; int16_t srcpitch; int32_t fcolor; @@ -416,7 +417,7 @@ typedef struct da2_t { int32_t count; int32_t d; int octdir; - int x, y; + int x, y, wx1, wx2, wy1, wy2; } bitblt; #ifdef ENABLE_DA2_DEBUGVRAM @@ -805,20 +806,32 @@ da2_bitblt_load(da2_t *da2) /* Draw a line */ else if (da2->bitblt.reg[0x5] == 0x43) { da2->bitblt.exec = DA2_BLT_CLINE; - da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0x7ff); - da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0x7ff); - da2->bitblt.size_x = abs((da2->bitblt.reg[0x33] & 0x7ff) - (da2->bitblt.reg[0x32] & 0x7ff)); - da2->bitblt.size_y = abs((da2->bitblt.reg[0x35] & 0x7ff) - (da2->bitblt.reg[0x34] & 0x7ff)); - da2->bitblt.count = 0; - da2->bitblt.octdir = da2->bitblt.reg[0x2D]; + da2->bitblt.dest_x = (da2->bitblt.reg[0x32] & 0xffff); + da2->bitblt.dest_y = (da2->bitblt.reg[0x34] & 0xffff); + da2->bitblt.wx1 = (da2->bitblt.reg[0x32]) >> 16; + da2->bitblt.wx2 = (da2->bitblt.reg[0x33]) >> 16; + da2->bitblt.wy1 = (da2->bitblt.reg[0x34]) >> 16; + da2->bitblt.wy2 = (da2->bitblt.reg[0x35]) >> 16; + da2->bitblt.size_x = abs((int16_t)(da2->bitblt.reg[0x33] & 0xffff) - da2->bitblt.dest_x); + da2->bitblt.size_y = abs((int16_t)(da2->bitblt.reg[0x35] & 0xffff) - da2->bitblt.dest_y); + da2->bitblt.count = 0; + da2->bitblt.octdir = da2->bitblt.reg[0x2D]; da2->bitblt.bitshift_destr = 0; if (da2->bitblt.octdir & 0x04) /* dX > dY */ da2->bitblt.d = 2 * da2->bitblt.size_y - da2->bitblt.size_x; else da2->bitblt.d = 2 * da2->bitblt.size_x - da2->bitblt.size_y; - da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%d\n", + da2->bitblt.x = da2->bitblt.dest_x; + da2->bitblt.y = da2->bitblt.dest_y; + da2_log("drawline x=%d, y=%d, dx=%d, dy=%d, oct=%dn", da2->bitblt.dest_x, da2->bitblt.dest_y, da2->bitblt.size_x, da2->bitblt.size_y, da2->bitblt.octdir); + da2_log(" x1=%d, x2=%d, y1=%d, y2=%d\n", + da2->bitblt.reg[0x32] & 0x7ff, da2->bitblt.reg[0x33] & 0x7ff, + da2->bitblt.reg[0x34] & 0x7ff, da2->bitblt.reg[0x35] & 0x7ff); + da2_log(" ux1=%d,ux2=%d,uy1=%d,uy2=%d\n", + (da2->bitblt.reg[0x32] >> 16) & 0x7ff, (da2->bitblt.reg[0x33] >> 16) & 0x7ff, + (da2->bitblt.reg[0x34] >> 16) & 0x7ff, (da2->bitblt.reg[0x35] >> 16) & 0x7ff); } /* Fill a rectangle (or draw a horizontal / vertical line) */ else if ((da2->bitblt.reg[0x5] & 0xfff0) == 0x40 && da2->bitblt.reg[0x3D] == 0) { @@ -884,7 +897,7 @@ da2_bitblt_exec(void *p) da2_t *da2 = (da2_t *) p; // timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); #ifdef ENABLE_DA2_DEBUGBLT - if(!(da2->bitblt.debug_exesteps & 0xf)) + if(!(da2->bitblt.debug_exesteps & 0xff)) da2_log("bitblt_exec: %d %d\n", da2->bitblt.exec, da2->bitblt.debug_exesteps); da2->bitblt.debug_exesteps++; #endif @@ -897,23 +910,26 @@ da2_bitblt_exec(void *p) da2->bitblt.indata = 0; break; case DA2_BLT_CLINE: - int pos_x = da2->bitblt.dest_x + da2->bitblt.x; - int pos_y = da2->bitblt.dest_y + da2->bitblt.y; - /* Draw a dot */ // outb(0x680, da2->bitblt.octdir); - da2_bltlog("point: %d %d %d %d %d\n", pos_x, pos_y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); - int destaddr = pos_y * (da2->rowoffset * 2) + pos_x / 8; - int pixelmask = pos_x % 16; + da2_bltlog("point: %d %d %d %d %d\n", da2->bitblt.x, da2->bitblt.y, da2->bitblt.d, da2->bitblt.x, da2->bitblt.y); + int destaddr = da2->bitblt.y * (da2->rowoffset * 2) + da2->bitblt.x / 8; + int pixelmask = da2->bitblt.x % 16; if (pixelmask >= 8) pixelmask = (0x8000 >> (pixelmask - 8)); else pixelmask = (0x80 >> pixelmask); - DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); + + /* check the current position is inside the window */ + if (da2->bitblt.x < da2->bitblt.wx1 || da2->bitblt.x > da2->bitblt.wx2 + || da2->bitblt.y < da2->bitblt.wy1 || da2->bitblt.y > da2->bitblt.wy2) + ; + else + DA2_DrawColorWithBitmask(destaddr, da2->bitblt.fcolor, pixelmask, da2); // da2_log("draw: %x %x %x\n", destaddr, da2->bitblt.fcolor, pixelmask); da2->bitblt.count++; - /* Bresenham's line */ + /* calculate the next position with Bresenham's line algorithm */ if (da2->bitblt.octdir & 0x04) { /* dX > dY */ if (da2->bitblt.octdir & 0x02) { da2->bitblt.x++; From 726ce6c574076807772b4cbcfaedcfb309b2555d Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Fri, 28 Feb 2025 10:29:17 +0900 Subject: [PATCH 09/36] modify video memory mask and screen updating --- src/video/vid_ps55da2.c | 109 ++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index c476d12b9..441df620b 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -50,25 +50,29 @@ #define DA2_FONTROM_PATH_JPAN "roms/video/da2/94X1320.BIN" #define DA2_FONTROM_PATH_HANT "roms/video/da2/23F2698.BIN" -#define DA2_FONTROM_SIZE 1536 * 1024 +#define DA2_FONTROM_SIZE (1536 * 1024) #define DA2_FONTROM_BASESBCS 0x98000 #define DA2_GAIJIRAM_SBCS 0x34000 #define DA2_GAIJIRAM_SBEX 0x3c000 #define DA2_VM03_BASECHR 0x18000 #define DA2_VM03_BASEEXATTR 0x10000 -#define DA2_INVALIDACCESS8 0xff +#define DA2_INVALIDACCESS8 0xffu +#define DA2_INVALIDACCESS16 0xffffu +#define DA2_INVALIDACCESS32 0xffffffffu #define DA2_MASK_MMIO 0x1ffff -#define DA2_SIZE_VRAM 1024 * 1024 /* 0x100000 */ -#define DA2_SIZE_CRAM 4 * 1024 /* 0x1000 */ -#define DA2_SIZE_GAIJIRAM 256 * 1024 /* 0x40000 */ -#define DA2_MASK_A000 0x1ffff -#define DA2_MASK_CRAM 0xfff -#define DA2_MASK_GAIJIRAM 0x3ffff -#define DA2_PIXELCLOCK 58000000.0 +#define DA2_SIZE_VRAM (1024 * 1024) /* 0x100000 */ +#define DA2_SIZE_CRAM (4 * 1024) /* 0x1000 */ +#define DA2_SIZE_GAIJIRAM (256 * 1024) /* 0x40000 */ +#define DA2_MASK_A000 0x1ffff /* 0x1FFFF */ +#define DA2_MASK_CRAM 0xfff /* 0xFFF */ +#define DA2_MASK_GAIJIRAM 0x3ffff /* 0x3FFFF */ +#define DA2_MASK_VRAM 0xfffff /* 0xFFFFF */ +#define DA2_MASK_VRAMPLANE 0x1ffff /* 0x1FFFF */ +#define DA2_PIXELCLOCK 29000000.0 /* 58 MHz interlaced */ #define DA2_BLT_MEMSIZE 0x100 #define DA2_BLT_REGSIZE 0x40 #define DA2_DEBUG_BLTLOG_SIZE (DA2_BLT_REGSIZE + 1) -#define DA2_DEBUG_BLTLOG_MAX 256 * 1024 +#define DA2_DEBUG_BLTLOG_MAX (256 * 1024) #define DA2_DEBUG_BLT_NEVERUSED 0xfefefefe #define DA2_DEBUG_BLT_USEDRESET 0xfefefe #define DA2_DCONFIG_CHARSET_JPAN 0 /* for Code page 932 Japanese */ @@ -253,7 +257,7 @@ #endif #ifdef ENABLE_DA2_LOG -# define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGBLT 1 // # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 @@ -304,7 +308,6 @@ typedef struct da2_t { uint32_t decode_mask; uint32_t vram_max; - uint32_t vram_mask; uint32_t gdcla[8]; uint32_t gdcinput[8]; @@ -363,13 +366,11 @@ typedef struct da2_t { // uint32_t cram_display_mask; /* APA Buffer A0000-BFFFFh (128 KB) */ uint8_t *vram; - /* addr >> 12 = xx000h */ + /* xxh */ uint8_t *changedvram; /* (vram size - 1) >> 3 = 0x1FFFF */ uint32_t vram_display_mask; - // uint32_t write_bank, read_bank; - int fullchange; void (*render)(struct da2_t *da2); @@ -454,15 +455,17 @@ typedef struct { uint32_t DA2_vram_r(uint32_t addr, da2_t *da2) { - if (addr & ~da2->vram_mask) - return -1; + if (addr & ~DA2_MASK_VRAM) + return DA2_INVALIDACCESS32; return da2->vram[addr]; } /* safety write for internal functions */ void DA2_vram_w(uint32_t addr, uint8_t val, da2_t *da2) { - da2->vram[addr & da2->vram_mask] = val; + if (addr & ~DA2_MASK_VRAM) + return; + da2->vram[addr] = val; return; } /* write pixel data with rop (Note: bitmask must be in big endian) */ @@ -472,8 +475,7 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s uint32_t writepx[8]; destaddr &= 0xfffffffe; /* align to word address to work bit shift correctly */ // da2_log("DA2_WPDWB addr %x mask %x rop %x shift %d\n", destaddr, mask, da2->bitblt.raster_op, da2->bitblt.bitshift_destr); - da2->changedvram[(da2->vram_display_mask & destaddr) >> 12] = changeframecount; - da2->changedvram[(da2->vram_display_mask & (destaddr + 1)) >> 12] = changeframecount; + da2->changedvram[(DA2_MASK_VRAMPLANE & destaddr) >> 9] = changeframecount; destaddr <<= 3; /* read destination data with big endian order */ for (int i = 0; i < 8; i++) @@ -485,7 +487,6 @@ DA2_WritePlaneDataWithBitmask(uint32_t destaddr, const uint16_t mask, pixel32 *s DA2_VidSeq32 mask32in; mask32in.d = (uint32_t) mask; DA2_VidSeq32 mask32; - mask32.d = 0; mask32.b[3] = mask32in.b[0]; mask32.b[2] = mask32in.b[1]; mask32.d &= 0xffff0000; @@ -1395,7 +1396,7 @@ da2_in(uint16_t addr, void *p) case LS_DATA: // da2->ioctl[3] = 0x80; /* 3E1h:3 bit 7 color monitor, bit 3 busy(GC) bit 0 busy (IO?) */ if (da2->ioctladdr > 0xf) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->ioctl[da2->ioctladdr]; if (da2->ioctladdr == LS_STATUS) { /* Status register */ if (da2->attrc[LV_COMPATIBILITY] & 0x08) { /* for detecting monitor type and cable wiring */ @@ -1440,7 +1441,7 @@ da2_in(uint16_t addr, void *p) break; case LF_DATA: if (da2->fctladdr > 0x1f) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->fctl[da2->fctladdr]; break; case LC_INDEX: @@ -1448,7 +1449,7 @@ da2_in(uint16_t addr, void *p) break; case LC_DATA: if (da2->crtcaddr > 0x1f) - return DA2_INVALIDACCESS8; + return DA2_INVALIDACCESS16; temp = da2->crtc[da2->crtcaddr]; break; case LV_PORT: @@ -1741,14 +1742,13 @@ getfont_ps55dbcs(int32_t code, int32_t line, void *p) if (code >= 0x8000 && code <= 0x8183) code -= 0x6000; /* shift for IBM extended characters (I don't know how the real card works.) */ if (code < DA2_FONTROM_SIZE / 72 && fline >= 0 && fline < 24) { - font = da2->mmio.font[code * 72 + fline * 3]; /* 1111 1111 */ - font <<= 8; /* 1111 1111 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 1111 1111 2222 0000 */ - font >>= 1; /* 0111 1111 1222 2000 */ - font <<= 4; /* 0111 1111 1222 2000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0111 1111 1222 2000 2222 */ - font <<= 8; /* 0111 1111 1222 2000 2222 0000 0000 */ - font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0111 1111 1222 2000 2222 3333 3333 */ + font = da2->mmio.font[code * 72 + fline * 3]; /* 0000 0000 0000 0000 0000 0000 1111 1111 */ + font <<= 8; /* 0000 0000 0000 0000 1111 1111 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0xf0; /* 0000 0000 0000 0000 1111 1111 2222 0000 */ + font <<= 3; /* 0000 0000 0000 0111 1111 1222 2000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 1] & 0x0f; /* 0000 0000 0000 0111 1111 1222 2000 2222 */ + font <<= 8; /* 0000 0111 1111 1222 2000 2222 0000 0000 */ + font |= da2->mmio.font[code * 72 + fline * 3 + 2]; /* 0000 0111 1111 1222 2000 2222 3333 3333 */ font <<= 4; /* 0111 1111 1222 2000 2222 3333 3333 0000 */ /* font >>= 1;//put blank at column 1 (and 26) */ } else if (code >= 0xb000 && code <= 0xb75f) { @@ -1824,7 +1824,7 @@ da2_render_text(da2_t *da2) // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { chr = da2->cram[(da2->ma) & DA2_MASK_CRAM]; - attr = da2->cram[((da2->ma) + 1) & DA2_MASK_CRAM]; + attr = da2->cram[(da2->ma + 1) & DA2_MASK_CRAM]; // if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr); if (da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) /* IO 3E8h, Index 1Dh */ { /* --Parse attribute byte in color mode-- */ @@ -1864,7 +1864,7 @@ da2_render_text(da2_t *da2) /* Stay drawing If the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = da2->cram[((da2->ma) + 2) & da2->vram_display_mask]; + chr_dbcs = da2->cram[(da2->ma + 2) & DA2_MASK_CRAM]; chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -1935,7 +1935,7 @@ da2_render_text(da2_t *da2) da2->ma += 2; p += 13; } - da2->ma &= da2->vram_display_mask; + // da2->ma &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -1959,9 +1959,9 @@ da2_render_textm3(da2_t *da2) int chr_wide = 0; // da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc); for (x = 0; x < da2->hdisp; x += 13) { - chr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma), da2); - attr = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 1, da2); - extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + (da2->ma) + 1, da2); + chr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma, da2); + attr = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2); + extattr = DA2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2); // if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr); bg = attr >> 4; // if (da2->blink) bg &= ~0x8; @@ -1979,7 +1979,7 @@ da2_render_textm3(da2_t *da2) /* Stay drawing if the char code is DBCS and not at last column. */ if (chr_wide) { /* Get high DBCS code from the next video address */ - chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + (da2->ma) + 2, da2); + chr_dbcs = DA2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2); chr_dbcs <<= 8; chr_dbcs |= chr; /* Get the font pattern */ @@ -2027,7 +2027,7 @@ da2_render_textm3(da2_t *da2) da2->ma += 2; p += 13; } - da2->ma &= da2->vram_display_mask; + // da2->ma &= DA2_MASK_CRAM; // da2->writelines++; } } @@ -2035,7 +2035,7 @@ da2_render_textm3(da2_t *da2) void da2_render_color_4bpp(da2_t *da2) { - int changed_offset = da2->ma >> 12; + int changed_offset = da2->ma >> 9; // da2_log("ma %x cf %x\n", da2->ma, changed_offset); da2->plane_mask &= 0x0f; /*safety */ @@ -2084,7 +2084,7 @@ da2_render_color_4bpp(da2_t *da2) void da2_render_color_8bpp(da2_t *da2) { - int changed_offset = da2->ma >> 12; + int changed_offset = da2->ma >> 9; // da2_log("ma %x cf %x\n", da2->ma, changed_offset); if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) { @@ -2255,8 +2255,8 @@ da2_recalctimings(da2_t *da2) if (da2->dispofftime < TIMER_USEC) da2->dispofftime = TIMER_USEC; da2_log("da2 horiz total %i display end %i vidclock %f\n", da2->crtc[0], da2->crtc[1], da2->clock); - // da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); - // da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); + da2_log("da2 vert total %i display end %i max row %i vsync %i\n",da2->vtotal,da2->dispend,(da2->crtc[9]&31)+1,da2->vsyncstart); + da2_log("total %f on %i cycles off %i cycles frame %i sec %i\n",disptime*crtcconst,da2->dispontime,da2->dispofftime,(da2->dispontime+da2->dispofftime)*da2->vtotal,(da2->dispontime+da2->dispofftime)*da2->vtotal*70); // da2_log("da2->render %08X\n", da2->render); } @@ -2580,7 +2580,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) cycles -= video_timing_write_b; - da2->changedvram[addr >> 12] = changeframecount; + da2->changedvram[addr >> 9] = changeframecount;/* 0x1FFFF -> 0x1F */ addr <<= 3; for (int i = 0; i < 8; i++) @@ -2694,8 +2694,8 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) // da2_log("da2_gcW m%d a%x d%x\n", da2->writemode, addr, val); // da2_log("da2_gcW %05X %02X %04X:%04X esdi %04X:%04X dssi %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc, ES, DI, DS, SI); - da2->changedvram[addr >> 12] = changeframecount; - da2->changedvram[(addr + 1) >> 12] = changeframecount; + da2->changedvram[addr >> 9] = changeframecount; + // da2->changedvram[(addr + 1) >> 12] = changeframecount; addr <<= 3; for (int i = 0; i < 8; i++) @@ -2948,7 +2948,7 @@ da2_poll(void *priv) } da2->blink++; - for (x = 0; x < ((da2->vram_mask + 1) >> 12); x++) { + for (x = 0; x <= (DA2_MASK_VRAMPLANE >> 9); x++) { if (da2->changedvram[x]) da2->changedvram[x]--; } @@ -3089,7 +3089,7 @@ da2_reset(void *priv) da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ da2->pos_regs[1] = DA2_POSID_H; /* Adapter Identification Byte (High byte) */ - da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (they are changed by system software) */ + da2->pos_regs[2] = 0x40; /* Bit 7-5: 010=Mono, 100=Color, Bit 0 : Card Enable (set by reference diskette) */ da2->ioctl[LS_CONFIG1] = OldLSI | Page_Two; /* Configuration 1 : DA-II, 1024 KB */ da2->ioctl[LS_CONFIG1] |= ((da2->monitorid & 0x8) << 1); /* Configuration 1 : Monitor ID 3 */ da2->ioctl[LS_CONFIG2] = (da2->monitorid & 0x7); /* Configuration 2: Monitor ID 0-2 */ @@ -3127,11 +3127,10 @@ da2_init(UNUSED(const device_t *info)) da2->dispontime = 1000ull << 32; da2->dispofftime = 1000ull << 32; da2->vram = calloc(1, DA2_SIZE_VRAM); - da2->vram_mask = DA2_SIZE_VRAM - 1; da2->cram = calloc(1, DA2_SIZE_CRAM); da2->vram_display_mask = DA2_MASK_CRAM; - da2->changedvram = calloc(1, /*(memsize >> 12) << 1*/ DA2_SIZE_VRAM >> 12); /* XX000h */ - da2->monitorid = device_get_config_int("montype"); /* Configuration for Monitor ID (aaaa) -> (xxax xxxx, xxxx xaaa) */ + da2->monitorid = device_get_config_int("montype"); + da2->changedvram = calloc(1, (DA2_MASK_VRAMPLANE + 1) >> 9); /* XX000h */ da2->mmio.charset = device_get_config_int("charset"); da2->mmio.font = malloc(DA2_FONTROM_SIZE); @@ -3148,7 +3147,7 @@ da2_init(UNUSED(const device_t *info)) } mca_add(da2_mca_read, da2_mca_write, da2_mca_feedb, da2_mca_reset, da2); - da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); memset(da2->bitblt.payload, 0x00, DA2_BLT_MEMSIZE); memset(da2->bitblt.reg, 0xfe, DA2_BLT_REGSIZE * sizeof(uint32_t)); /* clear memory */ #ifdef ENABLE_DA2_DEBUGBLT @@ -3172,7 +3171,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 10 * TIMER_USEC; + da2->bitblt.timerspeed = 10ull * TIMER_USEC; timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; @@ -3275,7 +3274,7 @@ void da2_speed_changed(void *p) { da2_t *da2 = (da2_t *) p; - da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (float) (1ull << 32)); + da2->da2const = (uint64_t) ((cpuclock / DA2_PIXELCLOCK) * (double) (1ull << 32)); da2_recalctimings(da2); } From 31d05b3e45a60ab1bf0eb057bac8d012d788e031 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Sat, 1 Mar 2025 23:58:31 +0900 Subject: [PATCH 10/36] modify blank render --- src/video/vid_ps55da2.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 441df620b..46ef4caf6 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -257,9 +257,9 @@ #endif #ifdef ENABLE_DA2_LOG -// # define ENABLE_DA2_DEBUGBLT 1 -// # define ENABLE_DA2_DEBUGVRAM 1 -// # define ENABLE_DA2_DEBUGFULLSCREEN 1 +# define ENABLE_DA2_DEBUGBLT 1 +# define ENABLE_DA2_DEBUGVRAM 1 +# define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -1208,8 +1208,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_DATA: if (da2->crtcaddr > 0x1f) return; - // if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) - // da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); + if (!(da2->crtcaddr == LC_CURSOR_LOC_HIGH || da2->crtcaddr == LC_CURSOR_LOC_LOWJ)) + da2_log("DA2 Out addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->crtcaddr, val, cs >> 4, cpu_state.pc); if (!(da2->crtc[da2->crtcaddr] ^ val)) return; switch (da2->crtcaddr) { @@ -1325,6 +1325,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_DATA: // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: @@ -1332,6 +1333,11 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_MODE: da2->writemode = val & 3; + /* reset bit mask and plane mask (? idk when) */ + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->writemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case LG_MAP_MASKJ: da2->writemask = val & 0xff; @@ -1429,8 +1435,7 @@ da2_in(uint16_t addr, void *p) // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } - if (da2->bitblt.indata) - temp |= 0x08; + if (da2->bitblt.indata) temp |= 0x09; #ifdef ENABLE_DA2_DEBUGMONWAIT da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif @@ -1524,7 +1529,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p) void da2_outw(uint16_t addr, uint16_t val, void *p) { - // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1794,14 +1799,17 @@ void da2_render_blank(da2_t *da2) { int x, xx; + int cwidth; + if (da2->ioctl[LS_MODE] & 0x01) cwidth = 13; /* in character mode */ + else cwidth = 16; if (da2->firstline_draw == 2000) da2->firstline_draw = da2->displine; da2->lastline_draw = da2->displine; for (x = 0; x < da2->hdisp; x++) { - for (xx = 0; xx < 13; xx++) - ((uint32_t *) buffer32->line[da2->displine])[(x * 13) + xx + 32] = 0; + for (xx = 0; xx < cwidth; xx++) + ((uint32_t *) buffer32->line[da2->displine])[(x * cwidth) + xx + 32] = 0; } } /* Display Adapter Mode 8, E Drawing */ @@ -2152,8 +2160,10 @@ da2_recalctimings(da2_t *da2) double _dispontime, _dispofftime, disptime; /* if output disabled or VGA passthrough */ - if (!(da2->attrc[LV_COMPATIBILITY] & 0x08) || da2->ioctl[LS_MODE] & 0x02) + if (da2->ioctl[LS_MODE] & 0x02 || !(da2->attrc[LV_COMPATIBILITY] & 0x08)) { + da2->render = da2_render_blank; return; + } da2->vtotal = da2->crtc[LC_VERTICAL_TOTALJ] & 0xfff; da2->dispend = da2->crtc[LC_V_DISPLAY_ENABLE_END] & 0xfff; @@ -3171,7 +3181,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 10ull * TIMER_USEC; + da2->bitblt.timerspeed = 8ull * TIMER_USEC; /* Bitblt execution speed */ timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From 6f53e69efe666ac6824b03f098edc11cf8db97ff Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Mar 2025 07:47:15 +0900 Subject: [PATCH 11/36] added bit mask reset and alignment for compatibility with OS/2 J2.1 (beta), Windows 3.1 and Multitool Chart K3.1 in J-DOS. --- src/video/vid_ps55da2.c | 125 ++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 51 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 46ef4caf6..1b9ec473e 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -327,7 +327,7 @@ typedef struct da2_t { int fast; uint8_t colourcompare, colournocare; int readmode, writemode, readplane; - uint8_t writemask; + uint8_t planemask; uint32_t charseta, charsetb; uint8_t egapal[16]; @@ -441,6 +441,7 @@ void da2_bitblt_exec(void *p); void da2_updatevidselector(da2_t *da2); void da2_reset_ioctl(da2_t *da2); static void da2_reset(void *priv); +uint16_t rightRotate(uint16_t data, uint8_t count); typedef union { uint32_t d; @@ -687,6 +688,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 2]; da2_bltlog("[%02x] %02x: %04x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; i += 3; break; case 0x91: @@ -699,6 +701,7 @@ da2_bitblt_load(da2_t *da2) value32 |= da2->bitblt.payload[i + 2]; da2_bltlog("[%02x] %02x: %08x (%d)\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], value32, value32); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value32; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value32; i += 5; break; case 0x99: @@ -716,6 +719,7 @@ da2_bitblt_load(da2_t *da2) da2_bltlog("[%02x] %02x: %02x %02x %02x %02x %02x %02x\n", da2->bitblt.payload[i], da2->bitblt.payload[i + 1], da2->bitblt.payload[i + 2], da2->bitblt.payload[i + 3], da2->bitblt.payload[i + 4], da2->bitblt.payload[i + 5], da2->bitblt.payload[i + 6], da2->bitblt.payload[i + 7]); da2->bitblt.reg[da2->bitblt.payload[i + 1]] = value64; + // da2->gdcreg[da2->bitblt.payload[i + 1]] = value64; i += 7; break; case 0x00: @@ -1321,26 +1325,27 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2->attrc[da2->attraddr & 0x3f] = val; break; case LG_INDEX: + da2_log("DA2 Out addr %03X val %02X\n", addr, val); da2->gdcaddr = val; break; case LG_DATA: - // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); + // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); da2_log("DA2 Out addr %03X idx %02X val %02X\n", addr, da2->gdcaddr, val); - // if(da2->gdcaddr != 8 && da2->gdcaddr != 9) da2_log("DA2 GCOut idx %X val %02X %04X:%04X esdi %04X:%04X\n", da2->gdcaddr, val, cs >> 4, cpu_state.pc, ES, DI); + da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; switch (da2->gdcaddr & 0x1f) { case LG_READ_MAP_SELECT: da2->readplane = val & 0x7; break; case LG_MODE: da2->writemode = val & 3; - /* reset bit mask and plane mask (? idk when) */ - da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; - da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; - da2->writemask = 0xff; - da2->gdcreg[LG_MAP_MASKJ] = 0xff; + /* Resettting masks here gliches the screen in IBM Multitool Chart K3.1 */ + // da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + // da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + // da2->planemask = 0xff; + // da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case LG_MAP_MASKJ: - da2->writemask = val & 0xff; + da2->planemask = val & 0xff; break; case LG_COMMAND: break; @@ -1348,7 +1353,6 @@ da2_out(uint16_t addr, uint16_t val, void *p) da2_log("!!!DA2 GC Out addr %03X idx 10 val %02X\n", addr, val); return; } - da2->gdcreg[da2->gdcaddr & 0x0f] = val & 0xff; break; // case 0x3ed: /* used by Windows 3.1 display driver */ // da2->gdcreg[5] = val & 0xff; @@ -1424,7 +1428,7 @@ da2_in(uint16_t addr, void *p) temp |= 0x80; } temp &= 0xf6; /* clear busy bit */ - // if (da2->bitblt.indata) /* for OS/2 J1.3 */ + // if (da2->bitblt.indata) /* for OS/2 J1.3 command prompt scrolling */ // da2_bitblt_dopayload(da2); if (da2->bitblt.exec != DA2_BLT_CIDLE) { // da2_log("exec:%x\n", da2->bitblt.exec); @@ -1435,7 +1439,7 @@ da2_in(uint16_t addr, void *p) // timer_advance_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); // } } - if (da2->bitblt.indata) temp |= 0x09; + if (da2->bitblt.indata) temp |= 0x08; #ifdef ENABLE_DA2_DEBUGMONWAIT da2_log("DA2 In %04X(%02X) %04X %04X:%04X\n", addr, da2->ioctladdr, temp, cs >> 4, cpu_state.pc); #endif @@ -1529,7 +1533,7 @@ da2_outb(uint16_t addr, uint8_t val, void *p) void da2_outw(uint16_t addr, uint16_t val, void *p) { - da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log("DA2 Outw addr %03X val %04X\n", addr, val); da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; switch (addr) { @@ -1550,7 +1554,15 @@ da2_outw(uint16_t addr, uint16_t val, void *p) break; case 0x3EC: // da2_log("DA2 Outw addr %03X val %04X %04X:%04X\n", addr, val, cs >> 4, cpu_state.pc); + da2_log(" "); + // val = rightRotate(val, 8); + // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); + /* reset masks */ + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->planemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; break; case 0x3ED: da2->gdcaddr = LG_MODE; @@ -2340,11 +2352,12 @@ da2_mca_reset(void *p) da2_mca_write(0x102, 0, da2); } +/* ROP gdcinput and gdcsrc, and write the result with bitmask at addr (byte) */ static void da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) { for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropB o%x a%x d%x p%d m%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, bitmask); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ @@ -2368,13 +2381,15 @@ da2_gdcropB(uint32_t addr,uint8_t bitmask, da2_t *da2) } } } +/* ROP gdcinput and gdcsrc, and write the result with bitmask at addr (word) */ static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { + if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { // da2_log("da2_gdcropW m%x a%x d%x i%d ml%x mh%x\n", da2->gdcreg[LG_COMMAND] & 0x03, addr, da2->gdcinput[i], i, da2->gdcreg[LG_BIT_MASK_LOW], da2->gdcreg[LG_BIT_MASK_HIGH]); switch (da2->gdcreg[LG_COMMAND] & 0x03) { case 0: /*Set*/ @@ -2415,7 +2430,6 @@ da2_mmio_read(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; addr &= DA2_MASK_MMIO; - if (da2->ioctl[LS_MMIO] & 0x10) { if (da2->fctl[LF_MMIO_SEL] == 0x80) /* linear access */ @@ -2455,7 +2469,7 @@ da2_mmio_read(uint32_t addr, void *p) cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ - // da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); + da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { @@ -2474,7 +2488,9 @@ static uint16_t da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; - //da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + // da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); + da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); + if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); } else if (!(da2->ioctl[LS_MODE] & 1)) {/* 16 color or 256 color mode */ @@ -2566,11 +2582,14 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask to even address */ - if (addr & 1) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + /* align bitmask with even address for OS/2 J2.0 (need to verify the condition with Win 3.x) */ + if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; + #ifdef ENABLE_DA2_DEBUGVRAM - da2_log("da2_wB %x %02x\n", addr, val); + // da2_log("da2_wB %x %02x\n", addr, val); + da2_log("da2_wB %x %d %d %02x\n", addr, + addr % (da2->rowoffset * 2) * 8, addr / (da2->rowoffset * 2), val); // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { @@ -2581,7 +2600,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) for (int i = 0; i < 8; i++) { int pixeldata = 0; if (val & (1 << (7 - i))) - pixeldata = (da2->writemask & 0xf); + pixeldata = (da2->planemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2614,7 +2633,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) switch (da2->writemode) { case 2: /* equiv to vga write mode 1 */ for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) + if (da2->planemask & (1 << i)) DA2_vram_w(addr | i, da2->gdcsrc[i], da2); break; case 0:/* equiv to vga write mode 0 */ @@ -2622,7 +2641,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; if (bitmask == 0xff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) + if (da2->planemask & (1 << i)) DA2_vram_w(addr | i, val, da2); } else { for (int i = 0; i < 8; i++) @@ -2631,8 +2650,8 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) else da2->gdcinput[i] = val; - for (int i = 0; i < 8; i++) - da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ + // for (int i = 0; i < 8; i++) + // da2->debug_vramold[i] = da2->vram[addr | i]; /* use latch */ da2_gdcropB(addr, bitmask, da2); // for (int i = 0; i < 8; i++) // da2_log("\tsrc %02x in %02x bitm %02x mod %x rop %x: %02x -> %02x\n", da2->gdcsrc[i], da2->gdcinput[i], bitmask, da2->gdcreg[5],da2->gdcreg[LG_COMMAND], da2->debug_vramold[i], da2->vram[addr | i]);//use latch @@ -2640,17 +2659,17 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } break; case 1:/* equiv to vga write mode 2 */ - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) - DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2); - //fprintf(da2->mmdbg_fp, "m1-1"); - } else { + // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + // for (int i = 0; i < 8; i++) + // if (da2->planemask & (1 << i)) + // DA2_vram_w(addr | i, (((val & (1 << i)) ? 0xff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask), da2); + // //fprintf(da2->mmdbg_fp, "m1-1"); + // } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xff : 0); da2_gdcropB(addr, bitmask, da2); //fprintf(da2->mmdbg_fp, "m1-2"); - } + // } break; case 3:/* equiv to vga write mode 3 */ if (da2->gdcreg[LG_DATA_ROTATION] & 7) @@ -2658,7 +2677,7 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) bitmask &= val; for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xff : 0; da2_gdcropB(addr, bitmask, da2); break; } @@ -2678,22 +2697,25 @@ static void da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; - uint16_t bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + uint16_t bitmask; addr &= DA2_MASK_MMIO; + bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; bitmask <<= 8; bitmask |= (uint16_t) da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM + da2_log("da2_wW %x %d %d %02x\n", addr, + addr % (da2->rowoffset * 2) * 8, addr / (da2->rowoffset * 2), val); // if (!(da2->gdcreg[LG_COMMAND] & 0x08)) //{ if (((int) addr - (int) da2->mmdbg_vidaddr) > 2 || (((int) da2->mmdbg_vidaddr - (int) addr) > 2) || da2->mmdbg_vidaddr == addr) { - fprintf(da2->mmdbg_fp, "\nW %x ", addr); + fprintf(da2->mmdbg_fp, "\nW %x %x ", addr, val); for (int i = 0; i <= 0xb; i++) fprintf(da2->mmdbg_fp, "%02x ", da2->gdcreg[i]); } for (int i = 0; i < 16; i++) { int pixeldata = 0; if (val & (1 << (15 - i))) - pixeldata = (da2->writemask & 0xf); + pixeldata = (da2->planemask & 0xf); fprintf(da2->mmdbg_fp, "%X", pixeldata); } da2->mmdbg_vidaddr = addr; @@ -2727,7 +2749,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) switch (da2->writemode) { case 2: for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { DA2_vram_w(addr | i, da2->gdcsrc[i] & 0xff, da2); DA2_vram_w((addr + 8) | i, da2->gdcsrc[i] >> 8, da2); } @@ -2737,7 +2759,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { + if (da2->planemask & (1 << i)) { DA2_vram_w(addr | i, val & 0xff, da2); DA2_vram_w((addr + 8) | i, val >> 8, da2); } @@ -2752,18 +2774,18 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - for (int i = 0; i < 8; i++) - if (da2->writemask & (1 << i)) { - uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - DA2_vram_w(addr | i, wdata & 0xff, da2); - DA2_vram_w((addr + 8) | i, wdata >> 8, da2); - } - } else { + // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { + // for (int i = 0; i < 8; i++) + // if (da2->planemask & (1 << i)) { + // uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); + // DA2_vram_w(addr | i, wdata & 0xff, da2); + // DA2_vram_w((addr + 8) | i, wdata >> 8, da2); + // } + // } else { for (int i = 0; i < 8; i++) da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); da2_gdcropW(addr, bitmask, da2); - } + // } break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) @@ -2771,7 +2793,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) bitmask &= val; for (int i = 0; i < 8; i++) - da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; + da2->gdcinput[i] = (da2->gdcreg[LG_SET_RESETJ] & (1 << i)) ? 0xffff : 0; da2_gdcropW(addr, bitmask, da2); break; } @@ -2782,13 +2804,14 @@ static void da2_mmio_writew(uint32_t addr, uint16_t val, void *p) { da2_t *da2 = (da2_t *) p; + // if (da2->bitblt.exec != DA2_BLT_CIDLE) /* Bitblt is in operation. */ + // return; // if ((addr & ~0x1ffff) != 0xA0000) return; if (da2->ioctl[LS_MMIO] & 0x10) { // da2_log("da2_mmio_writeW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_write(addr, val & 0xff, da2); da2_mmio_write(addr + 1, val >> 8, da2); } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ - // return; // da2_log("da2_mmio_writeGW %x %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, val); da2_mmio_gc_writeW(addr, val, da2); } else { /* mode 3h text */ @@ -3181,7 +3204,7 @@ da2_init(UNUSED(const device_t *info)) mem_mapping_disable(&da2->cmapping); timer_add(&da2->timer, da2_poll, da2, 0); - da2->bitblt.timerspeed = 8ull * TIMER_USEC; /* Bitblt execution speed */ + da2->bitblt.timerspeed = 5ull * TIMER_USEC; /* Bitblt execution speed */ timer_add(&da2->bitblt.timer, da2_bitblt_dopayload, da2, 0); return da2; From e798030022d9ac1d0adfdbeada832a26aa9d33ed Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Tue, 4 Mar 2025 11:38:31 +0900 Subject: [PATCH 12/36] modify bit mask alignment, added delay for vidsel for Win 3.1. And added delay for switching video selector --- src/video/vid_ps55da2.c | 72 +++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1b9ec473e..0f5851c6f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -431,6 +431,7 @@ typedef struct da2_t { uint8_t pos_regs[8]; svga_t *mb_vga; uint8_t monitorid; + pc_timer_t timer_vidupd; int old_pos2; } da2_t; @@ -1108,11 +1109,13 @@ da2_bitblt_dopayload(void *priv) { da2_t *da2 = (da2_t *) priv; timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); - if (da2->bitblt.exec != DA2_BLT_CIDLE) - da2_bitblt_exec(da2); - else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { - da2->bitblt.exec = DA2_BLT_CLOAD; + /* do async operation but it causes the scrolling text glitch in OS/2 J1.3 Command Prompt (TODO) */ + if (da2->bitblt.exec != DA2_BLT_CIDLE) { + while (da2->bitblt.exec != DA2_BLT_CIDLE) da2_bitblt_exec(da2); + } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { + da2->bitblt.exec = DA2_BLT_CLOAD; + da2_bitblt_exec(da2); } else { // timer_disable(&da2->bitblt.timer); } @@ -1202,8 +1205,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) oldval = da2->fctl[da2->fctladdr]; da2->fctl[da2->fctladdr] = val; if (da2->fctladdr == 0 && oldval != val) { - da2->fullchange = changeframecount; - da2_recalctimings(da2); + da2_log("DA2 Out FCTL addr %03X idx %02X val %02X %04X:%04X\n", addr, da2->fctladdr, val, cs >> 4, cpu_state.pc); } break; case LC_INDEX: @@ -1338,7 +1340,7 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LG_MODE: da2->writemode = val & 3; - /* Resettting masks here gliches the screen in IBM Multitool Chart K3.1 */ + /* Resettting masks here gliches chart drawing in IBM Multitool Chart K3.1 */ // da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; // da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; // da2->planemask = 0xff; @@ -1558,11 +1560,13 @@ da2_outw(uint16_t addr, uint16_t val, void *p) // val = rightRotate(val, 8); // da2_out(LG_DATA, val, da2); da2_out(LG_DATA, val >> 8, da2); - /* reset masks */ - da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; - da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; - da2->planemask = 0xff; - da2->gdcreg[LG_MAP_MASKJ] = 0xff; + /* reset masks for compatibility with Win 3.1 solitaire */ + if (da2->gdcaddr == LG_MODE) { + da2->gdcreg[LG_BIT_MASK_LOW] = 0xff; + da2->gdcreg[LG_BIT_MASK_HIGH] = 0xff; + da2->planemask = 0xff; + da2->gdcreg[LG_MAP_MASKJ] = 0xff; + } break; case 0x3ED: da2->gdcaddr = LG_MODE; @@ -2151,8 +2155,9 @@ da2_render_color_8bpp(da2_t *da2) } void -da2_updatevidselector(da2_t *da2) +da2_updatevidselector_tick(void *priv) { + da2_t *da2 = (da2_t *) priv; if (da2->ioctl[LS_MODE] & 0x02) { /* VGA passthrough mode */ da2->override = 1; @@ -2165,6 +2170,12 @@ da2_updatevidselector(da2_t *da2) } } +void +da2_updatevidselector(da2_t *da2) +{ + timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); +} + void da2_recalctimings(da2_t *da2) { @@ -2386,6 +2397,7 @@ static void da2_gdcropW(uint32_t addr, uint16_t bitmask, da2_t *da2) { if((addr & 8) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = rightRotate(bitmask, 8); + // if((addr & 8)) bitmask = rightRotate(bitmask, 8); uint8_t bitmask_l = bitmask & 0xff; uint8_t bitmask_h = bitmask >> 8; for (int i = 0; i < 8; i++) { @@ -2582,9 +2594,15 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask with even address for OS/2 J2.0 (need to verify the condition with Win 3.x) */ - if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - else bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; + /* align bitmask with even address (need to verify the condition with OS/2 J2.x, Win 3.x and A-Train IV Win) */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ + // if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + /* Without byte align: Win 3.1 (Window Title) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ + /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok, DOS J4.0 MC - ok */ + if ((addr & 1)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; + else + /* No align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - bad */ + bitmask = da2->gdcreg[LG_BIT_MASK_LOW]; #ifdef ENABLE_DA2_DEBUGVRAM // da2_log("da2_wB %x %02x\n", addr, val); @@ -2756,7 +2774,7 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) break; case 0: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val]; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); if (bitmask == 0xffff && !(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { for (int i = 0; i < 8; i++) if (da2->planemask & (1 << i)) { @@ -2774,22 +2792,13 @@ da2_mmio_gc_writeW(uint32_t addr, uint16_t val, void *p) } break; case 1: - // if (!(da2->gdcreg[LG_COMMAND] & 0x03) && (!da2->gdcreg[LG_ENABLE_SRJ])) { - // for (int i = 0; i < 8; i++) - // if (da2->planemask & (1 << i)) { - // uint16_t wdata = (((val & (1 << i)) ? 0xffff : 0) & bitmask) | (da2->gdcsrc[i] & ~bitmask); - // DA2_vram_w(addr | i, wdata & 0xff, da2); - // DA2_vram_w((addr + 8) | i, wdata >> 8, da2); - // } - // } else { - for (int i = 0; i < 8; i++) - da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); - da2_gdcropW(addr, bitmask, da2); - // } + for (int i = 0; i < 8; i++) + da2->gdcinput[i] = ((val & (1 << i)) ? 0xffff : 0); + da2_gdcropW(addr, bitmask, da2); break; case 3: if (da2->gdcreg[LG_DATA_ROTATION] & 15) - val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); // val = svga_rotate[da2->gdcreg[LG_DATA_ROTATION] & 7][val];; TODO this wont work + val = rightRotate(val, da2->gdcreg[LG_DATA_ROTATION] & 15); bitmask &= val; for (int i = 0; i < 8; i++) @@ -3117,7 +3126,6 @@ da2_reset(void *priv) /* Initialize drawing */ da2->bitblt.exec = DA2_BLT_CIDLE; - da2->render = da2_render_blank; da2_reset_ioctl(da2); da2->pos_regs[0] = DA2_POSID_L; /* Adapter Identification Byte (Low byte) */ @@ -3192,6 +3200,8 @@ da2_init(UNUSED(const device_t *info)) da2->mmrdbg_fp = fopen("da2_mmiordat.txt", "w"); #endif da2->bitblt.payload_addr = 0; + + timer_add(&da2->timer_vidupd, da2_updatevidselector_tick, da2, 0);/* Init timer before executing reset */ da2_reset(da2); mem_mapping_add(&da2->mmio.mapping, 0xA0000, 0x20000, da2_mmio_read, da2_mmio_readw, NULL, da2_mmio_write, da2_mmio_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, da2); From 5a77092a717164bd67c3a8f786753f30e8c67e04 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 00:38:39 +0900 Subject: [PATCH 13/36] add support for 2nd sbcs in videomode 03 --- src/video/vid_ps55da2.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 0f5851c6f..1338304f1 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -1111,7 +1111,7 @@ da2_bitblt_dopayload(void *priv) timer_set_delay_u64(&da2->bitblt.timer, da2->bitblt.timerspeed); /* do async operation but it causes the scrolling text glitch in OS/2 J1.3 Command Prompt (TODO) */ if (da2->bitblt.exec != DA2_BLT_CIDLE) { - while (da2->bitblt.exec != DA2_BLT_CIDLE) + while (da2->bitblt.exec != DA2_BLT_CIDLE) /* this disables async operation */ da2_bitblt_exec(da2); } else if (da2->bitblt.indata && !(da2->ioctl[LS_MMIO] & 0x10) && (da2->bitblt.exec == DA2_BLT_CIDLE)) { da2->bitblt.exec = DA2_BLT_CLOAD; @@ -2015,9 +2015,14 @@ da2_render_textm3(da2_t *da2) } } else { /* the char code is SBCS (ANK) */ - uint16_t font = da2->mmio.ram[DA2_GAIJIRAM_SBCS + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ + uint32_t fontbase; + if (extattr & 0x80) /* second map of SBCS font */ + fontbase = DA2_GAIJIRAM_SBEX; + else + fontbase = DA2_GAIJIRAM_SBCS; + uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->sc * 2]; /* w13xh29 font */ font <<= 8; - font |= da2->mmio.ram[DA2_GAIJIRAM_SBCS+ chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ + font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */ // if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font); for (uint32_t n = 0; n < 13; n++) { p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]]; @@ -2176,6 +2181,17 @@ da2_updatevidselector(da2_t *da2) timer_set_delay_u64(&da2->timer_vidupd, 100000ull * TIMER_USEC); } +/* + Video modes supported by DOS J4.0 for the DA-2 (The DA-2 doesn't have a video BIOS on its card.) + Mode (hex) Type Colors Format Base Address PELs + 3 A/N/K 16 80 x 25 B8000h 1040 x 725 + 8 A/N/K 1 80 x 25 E0000h 1040 x 725 + A APA 1 78 x 25 A0000h 1024 x 768 + D APA 16 78 x 25 A0000h 1024 x 768 + E A/N/K 16 80 x 25 E0000h 1040 x 725 + F APA 256 A0000h 1024 x 768 + 45 (undoc) APA 16 A0000h 1040 x 768 +*/ void da2_recalctimings(da2_t *da2) { From 6c92eb61bf4e8c0d225b9f6354324ff766cc13ab Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:12:15 +0900 Subject: [PATCH 14/36] fix a screen glitch in OS/2 DOS MODE 1 fix a glitch in OS/2 DOS MODE 1 (monochrome graphics) --- src/video/vid_ps55da2.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 1338304f1..6568d9b45 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -259,7 +259,7 @@ #ifdef ENABLE_DA2_LOG # define ENABLE_DA2_DEBUGBLT 1 # define ENABLE_DA2_DEBUGVRAM 1 -# define ENABLE_DA2_DEBUGFULLSCREEN 1 +// # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 int da2_do_log = ENABLE_DA2_LOG; @@ -1227,7 +1227,9 @@ da2_out(uint16_t addr, uint16_t val, void *p) val = 0; break; case LC_START_ADDRESS_HIGH: - // if (da2->crtc[0x1c] & 0x40) return; + case LC_START_ADDRESS_LOW: + /* OS/2 DOS in MODE 1 read this to set the base line, but it does not work correctly. */ + val = 0; break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ case LC_VERTICAL_SYNC_START: /* Vertical Retrace Start Register */ @@ -1248,8 +1250,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) case LC_H_DISPLAY_ENABLE_END: case LC_VERTICAL_TOTALJ: case LC_MAXIMUM_SCAN_LINE: - case LC_START_ADDRESS_HIGH: - case LC_START_ADDRESS_LOW: + // case LC_START_ADDRESS_HIGH: + // case LC_START_ADDRESS_LOW: case LC_VERTICAL_SYNC_START: case LC_V_DISPLAY_ENABLE_END: case LC_START_VERTICAL_BLANK: @@ -2235,7 +2237,7 @@ da2_recalctimings(da2_t *da2) // da2->interlace = 0; - // da2->ma_latch = ((da2->crtc[0xc] & 0x3ff) << 8) | da2->crtc[0xd];//w + b + // da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];//w + b da2->ca_adj = 0; da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE]; @@ -2517,7 +2519,7 @@ da2_mmio_readw(uint32_t addr, void *p) { da2_t *da2 = (da2_t *) p; // da2_log("da2_readW: %x %x %x %x %x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr); - da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); + // da2_log("da2_readW: %x %x %x %x %x CS:PC=%4x:%4x\n", da2->ioctl[LS_MMIO], da2->fctl[LF_MMIO_SEL], da2->fctl[LF_MMIO_MODE], da2->fctl[LF_MMIO_ADDR], addr, CS, cpu_state.pc); if (da2->ioctl[LS_MMIO] & 0x10) { return (uint16_t) da2_mmio_read(addr, da2) | (uint16_t) (da2_mmio_read(addr + 1, da2) << 8); @@ -2553,7 +2555,7 @@ da2_mmio_readw(uint32_t addr, void *p) } return ~ret; } else { - // da2_log("da2_Rw: %05x=%04x\n", addr, da2->gdcla[da2->readplane]); + da2_log("da2_Rw: %05x(%d) = %04x\n", addr, da2->readplane, da2->gdcla[da2->readplane]); return da2->gdcla[da2->readplane]; } } else { @@ -3050,11 +3052,11 @@ da2_poll(void *priv) = da2->maback = da2->ma_latch; da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj; - da2->ma <<= 1; - da2->maback <<= 1; + // da2->ma <<= 1; + // da2->maback <<= 1; da2->ca <<= 1; - // da2_log("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,da2_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], da2_interlace, oddeven); + // da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF); } if (da2->vc == da2->vtotal) { // da2_log("VC vtotal\n"); From 5b7766bb7ab571aee906dac14f8548e53905586c Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:35:56 +0900 Subject: [PATCH 15/36] disable debug logging, update comments --- src/video/vid_ps55da2.c | 45 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 6568d9b45..335cbf86d 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -10,7 +10,7 @@ * * Notes: There are some known issues that should be corrected. * - Incorrect foreground text color appears on an active window in OS/2 J1.3. - * - BitBlt's text drawing function does not work correctly. + * - Glitches some part of graphics on the Control Panel in OS/2 J2.1 beta. * - The screen resolution and blanking interval time maybe not correct. * * The code should be tested with following cases. @@ -253,11 +253,11 @@ #define LG_SET_RESET_2 0x10 #ifndef RELEASE_BUILD -#define ENABLE_DA2_LOG 1 +// #define ENABLE_DA2_LOG 1 #endif #ifdef ENABLE_DA2_LOG -# define ENABLE_DA2_DEBUGBLT 1 +// # define ENABLE_DA2_DEBUGBLT 1 # define ENABLE_DA2_DEBUGVRAM 1 // # define ENABLE_DA2_DEBUGFULLSCREEN 1 // # define ENABLE_DA2_DEBUGMONWAIT 1 @@ -1228,7 +1228,8 @@ da2_out(uint16_t addr, uint16_t val, void *p) break; case LC_START_ADDRESS_HIGH: case LC_START_ADDRESS_LOW: - /* OS/2 DOS in MODE 1 read this to set the base line, but it does not work correctly. */ + /* The DOS J4.0 MODE 4 command and OS/2 driver write 0xFF00. + OS/2 DOS MODE 1 setup reads this to set the base line, but it causes the screen glitch. */ val = 0; break; case LC_VERTICAL_TOTALJ: /* Vertical Total */ @@ -1625,11 +1626,13 @@ da2_inb(uint16_t addr, void *p) uint16_t da2_inw(uint16_t addr, void *p) { - // uint16_t temp; + uint16_t temp; da2_t *da2 = (da2_t *) p; da2->inflipflop = 0; da2->outflipflop = 0; - return da2_in(addr, da2); + temp = da2_in(addr, da2); + da2_log("DA2 Inw addr %03X val %04X\n", addr, temp); + return temp; } /* IO 03DAh : Input Status Register 2 for DOSSHELL used by DOS J4.0 */ uint8_t @@ -2184,15 +2187,15 @@ da2_updatevidselector(da2_t *da2) } /* - Video modes supported by DOS J4.0 for the DA-2 (The DA-2 doesn't have a video BIOS on its card.) - Mode (hex) Type Colors Format Base Address PELs - 3 A/N/K 16 80 x 25 B8000h 1040 x 725 - 8 A/N/K 1 80 x 25 E0000h 1040 x 725 - A APA 1 78 x 25 A0000h 1024 x 768 - D APA 16 78 x 25 A0000h 1024 x 768 - E A/N/K 16 80 x 25 E0000h 1040 x 725 - F APA 256 A0000h 1024 x 768 - 45 (undoc) APA 16 A0000h 1040 x 768 + INT 10h video modes supported in DOS J4.0 (The DA-2 doesn't have a video BIOS on its card.) + Mode Type Colors Text Base Address PELs Render + 3 A/N/K 16 80 x 25 B0000h/B8000h 1040 x 725 textm3 + 8 A/N/K 2 80 x 25 E0000h 1040 x 725 text + Ah APA 1 78 x 25 A0000h 1024 x 768 color_4bpp + Dh APA 16 78 x 25 A0000h 1024 x 768 color_4bpp + Eh A/N/K 16 80 x 25 E0000h 1040 x 725 text + Fh APA 256 NA A0000h 1024 x 768 color_8bpp + 45h(undoc) APA 16 NA A0000h 1040 x 768 color_4bpp */ void da2_recalctimings(da2_t *da2) @@ -2499,7 +2502,9 @@ da2_mmio_read(uint32_t addr, void *p) cycles -= video_timing_read_b; for (int i = 0; i < 8; i++) da2->gdcla[i] = da2->vram[(addr << 3) | i]; /* read in byte */ +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_Rb: %05x=%02x\n", addr, da2->gdcla[da2->readplane]); +#endif if (da2->gdcreg[LG_MODE] & 0x08) { /* compare data across planes if the read mode bit (3EB 05, bit 3) is 1 */ uint8_t ret = 0; for (int i = 0; i < 8; i++) { @@ -2555,7 +2560,9 @@ da2_mmio_readw(uint32_t addr, void *p) } return ~ret; } else { +#ifdef ENABLE_DA2_DEBUGVRAM da2_log("da2_Rw: %05x(%d) = %04x\n", addr, da2->readplane, da2->gdcla[da2->readplane]); +#endif return da2->gdcla[da2->readplane]; } } else { @@ -2612,11 +2619,11 @@ da2_mmio_write(uint32_t addr, uint8_t val, void *p) } } else if (!(da2->ioctl[LS_MODE] & 1)) { /* 16 color or 256 color mode */ uint8_t bitmask; - /* align bitmask with even address (need to verify the condition with OS/2 J2.x, Win 3.x and A-Train IV Win) */ - /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ + /* Align bitmask with even address */ + /* With byte align: Win 3.1 (Window) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - ok */ // if ((addr & 1) && !(da2->gdcreg[LG_COMMAND] & 0x08)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; - /* Without byte align: Win 3.1 (Window Title) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ - /* With byte align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok, DOS J4.0 MC - ok */ + /* Without byte align: Win 3.1 (Window) - bad, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ + /* With byte align: Win 3.1 (Window) - ok, Solitaire 3.1 - ok, A-Train IV (splash): ok, OS/2 J2.0(cmd) - ok */ if ((addr & 1)) bitmask = da2->gdcreg[LG_BIT_MASK_HIGH]; else /* No align: Win 3.1 (Window Title) - ok, Solitaire 3.1 - ok, A-Train IV (splash): bad, OS/2 J2.0(cmd) - bad */ From 1a60f5aac4b7874cd0e16f78fa513b7b72a78949 Mon Sep 17 00:00:00 2001 From: Akamaki <97360908+akmed772@users.noreply.github.com> Date: Wed, 5 Mar 2025 13:01:58 +0900 Subject: [PATCH 16/36] remove video timing modification --- src/video/vid_ps55da2.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/video/vid_ps55da2.c b/src/video/vid_ps55da2.c index 335cbf86d..823ef4d2f 100644 --- a/src/video/vid_ps55da2.c +++ b/src/video/vid_ps55da2.c @@ -2220,14 +2220,7 @@ da2_recalctimings(da2_t *da2) if (da2->crtc[LC_START_H_DISPLAY_ENAB] & 1) { da2->hdisp--; da2->dispend -= 29; - } else { - // da2->vtotal += 2; - da2->dispend--; - // da2->vsyncstart++; - // da2->split++; - // da2->vblankstart++; - // da2->hdisp--; - } + } da2->htotal = da2->crtc[LC_HORIZONTAL_TOTAL]; da2->htotal += 1; From 8c2db2892d98b8b599f002c944667c47b10dc39e Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 5 Mar 2025 21:52:17 +0100 Subject: [PATCH 17/36] CPU: Fix Cyrix SMM instructions. --- src/cpu/386_ops.h | 104 +++++++++++++++++++++++++++++++++++++++++--- src/cpu/cpu.c | 10 +---- src/cpu/cpu.h | 50 +++++++++++---------- src/cpu/cpu_table.c | 87 ++++++++++++++++++++++++++++++++++++ src/cpu/x86_ops.h | 2 + 5 files changed, 215 insertions(+), 38 deletions(-) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index b8ef9edda..80a856482 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -859,12 +859,12 @@ const OpFn OP_TABLE(c486_0f)[1024] = { /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, +/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, @@ -1392,7 +1392,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1414,7 +1414,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1436,7 +1436,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -1458,7 +1458,99 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + // clang-format on +}; + +const OpFn OP_TABLE(c6x86l_0f)[1024] = { + // clang-format off + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 0802fa3ac..2d22ed796 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1462,22 +1462,16 @@ cpu_set(void) if (cpu_s->cpu_type == CPU_Cx6x86MX) x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86l_0f, dynarec_ops_386, dynarec_ops_c6x86l_0f); else - x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); -# if 0 x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); -# endif # else if (cpu_s->cpu_type == CPU_Cx6x86MX) x86_setopcodes(ops_386, ops_c6x86mx_0f); else if (cpu_s->cpu_type == CPU_Cx6x86L) - x86_setopcodes(ops_386, ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86l_0f); else - x86_setopcodes(ops_386, ops_c6x86mx_0f); -# if 0 x86_setopcodes(ops_386, ops_c6x86_0f); -# endif # endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 1d003ddc9..3e72db005 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -87,30 +87,32 @@ enum { enum { CPU_PKG_8088 = (1 << 0), CPU_PKG_8088_EUROPC = (1 << 1), - CPU_PKG_8086 = (1 << 2), - CPU_PKG_8086_MAZOVIA = (1 << 3), - CPU_PKG_188 = (1 << 4), - CPU_PKG_186 = (1 << 5), - CPU_PKG_286 = (1 << 6), - CPU_PKG_386SX = (1 << 7), - CPU_PKG_386DX = (1 << 8), - CPU_PKG_386DX_DESKPRO386 = (1 << 9), - CPU_PKG_M6117 = (1 << 10), - CPU_PKG_386SLC_IBM = (1 << 11), - CPU_PKG_486SLC = (1 << 12), - CPU_PKG_486SLC_IBM = (1 << 13), - CPU_PKG_486BL = (1 << 14), - CPU_PKG_486DLC = (1 << 15), - CPU_PKG_SOCKET1 = (1 << 16), - CPU_PKG_SOCKET3 = (1 << 17), - CPU_PKG_SOCKET3_PC330 = (1 << 18), - CPU_PKG_STPC = (1 << 19), - CPU_PKG_SOCKET4 = (1 << 20), - CPU_PKG_SOCKET5_7 = (1 << 21), - CPU_PKG_SOCKET8 = (1 << 22), - CPU_PKG_SLOT1 = (1 << 23), - CPU_PKG_SLOT2 = (1 << 24), - CPU_PKG_SOCKET370 = (1 << 25) + CPU_PKG_8088_VTECH = (1 << 2), + CPU_PKG_8086 = (1 << 3), + CPU_PKG_8086_MAZOVIA = (1 << 4), + CPU_PKG_8086_VTECH = (1 << 5), + CPU_PKG_188 = (1 << 6), + CPU_PKG_186 = (1 << 7), + CPU_PKG_286 = (1 << 8), + CPU_PKG_386SX = (1 << 9), + CPU_PKG_386DX = (1 << 10), + CPU_PKG_386DX_DESKPRO386 = (1 << 11), + CPU_PKG_M6117 = (1 << 12), + CPU_PKG_386SLC_IBM = (1 << 13), + CPU_PKG_486SLC = (1 << 14), + CPU_PKG_486SLC_IBM = (1 << 15), + CPU_PKG_486BL = (1 << 16), + CPU_PKG_486DLC = (1 << 17), + CPU_PKG_SOCKET1 = (1 << 18), + CPU_PKG_SOCKET3 = (1 << 19), + CPU_PKG_SOCKET3_PC330 = (1 << 20), + CPU_PKG_STPC = (1 << 21), + CPU_PKG_SOCKET4 = (1 << 22), + CPU_PKG_SOCKET5_7 = (1 << 23), + CPU_PKG_SOCKET8 = (1 << 24), + CPU_PKG_SLOT1 = (1 << 25), + CPU_PKG_SLOT2 = (1 << 26), + CPU_PKG_SOCKET370 = (1 << 27) }; #define CPU_SUPPORTS_DYNAREC 1 diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index b2ef71075..104d56d05 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -262,6 +262,50 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, + { + .package = CPU_PKG_8088_VTECH, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088_vtech", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + + { + .name = "10", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } + }, { .package = CPU_PKG_8086, .manufacturer = "Intel", @@ -399,6 +443,49 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, + { + .package = CPU_PKG_8086_VTECH, + .manufacturer = "Intel", + .name = "8086", + .internal_name = "8086_vtech", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } + }, { .package = CPU_PKG_188, .manufacturer = "Intel", diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 3dfb3f917..7aec16855 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -92,6 +92,7 @@ extern const OpFn dynarec_ops_pentiummmx_0f[1024]; # ifdef USE_CYRIX_6X86 extern const OpFn dynarec_ops_c6x86_0f[1024]; +extern const OpFn dynarec_ops_c6x86l_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; # endif /* USE_CYRIX_6X86 */ @@ -234,6 +235,7 @@ extern const OpFn ops_pentiummmx_0f[1024]; #ifdef USE_CYRIX_6X86 extern const OpFn ops_c6x86_0f[1024]; +extern const OpFn ops_c6x86l_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; #endif /* USE_CYRIX_6X86 */ From 5f3641ecbd7faf5caa77016392207a42ff9a2377 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 00:54:28 +0600 Subject: [PATCH 18/36] Implement Cyrix EMMI extensions and 4 FPU instructions PADDSIW, PSUBSIW, PMULHRW (named PMULHRWC in the code as recognized by some assemblers), PMULHRIW, PDISTIB, PMACHRIW, PAVEB, PMAGW, PMVZB, PMVNZB, PMVLZB, PMVGEZB, FTSTP, FRINT2, FRINEAR, FRICHOP are implemented for Cyrix 6x86MX. Cyrix 6x86(L) only has the last 4 instructions. --- src/cpu/386_ops.h | 9 +- src/cpu/cpu.c | 47 +- src/cpu/cpu.h | 10 + src/cpu/x86.c | 4 + src/cpu/x86_ops.h | 18 + src/cpu/x86_ops_mmx_emmi.h | 807 +++++++++++++++++++++++++++++++++++ src/cpu/x87_ops.h | 664 ++++++++++++++++++++++++++++ src/cpu/x87_ops_misc.h | 77 ++++ src/cpu/x87_ops_sf_arith.h | 81 ++++ src/cpu/x87_ops_sf_compare.h | 26 ++ 10 files changed, 1723 insertions(+), 20 deletions(-) create mode 100644 src/cpu/x86_ops_mmx_emmi.h diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 80a856482..e8300f134 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -206,6 +206,7 @@ extern void x386_dynarec_log(const char *fmt, ...); # include "x86_ops_mmx_mov.h" # include "x86_ops_mmx_pack.h" # include "x86_ops_mmx_shift.h" +# include "x86_ops_mmx_emmi.h" #endif #include "x86_ops_mov.h" #ifdef OPS_286_386 @@ -1857,7 +1858,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a16, opPADDSIW_a16, opPMAGW_a16, ILLEGAL, opPDISTIB_a16, opPSUBSIW_a16, ILLEGAL, ILLEGAL, opPMVZB_a16, opPMULHRWC_a16, opPMVNZB_a16, opPMVLZB_a16, opPMVGEZB_a16, opPMULHRIW_a16, opPMACHRIW_a16, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, @@ -1879,7 +1880,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a16, opPADDSIW_a16, opPMAGW_a16, ILLEGAL, opPDISTIB_a16, opPSUBSIW_a16, ILLEGAL, ILLEGAL, opPMVZB_a16, opPMULHRWC_a16, opPMVNZB_a16, opPMVLZB_a16, opPMVGEZB_a16, opPMULHRIW_a16, opPMACHRIW_a16, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, @@ -1901,7 +1902,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a32, opPADDSIW_a32, opPMAGW_a32, ILLEGAL, opPDISTIB_a32, opPSUBSIW_a32, ILLEGAL, ILLEGAL, opPMVZB_a32, opPMULHRWC_a32, opPMVNZB_a32, opPMVLZB_a32, opPMVGEZB_a32, opPMULHRIW_a32, opPMACHRIW_a32, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, @@ -1923,7 +1924,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ opPAVEB_a32, opPADDSIW_a32, opPMAGW_a32, ILLEGAL, opPDISTIB_a32, opPSUBSIW_a32, ILLEGAL, ILLEGAL, opPMVZB_a32, opPMULHRWC_a32, opPMVNZB_a32, opPMVLZB_a32, opPMVGEZB_a32, opPMULHRIW_a32, opPMACHRIW_a32, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, /*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 2d22ed796..13a109d38 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -279,13 +279,14 @@ uint8_t do_translate2 = 0; void (*cpu_exec)(int32_t cycs); -static uint8_t ccr0; -static uint8_t ccr1; -static uint8_t ccr2; -static uint8_t ccr3; -static uint8_t ccr4; -static uint8_t ccr5; -static uint8_t ccr6; +uint8_t ccr0; +uint8_t ccr1; +uint8_t ccr2; +uint8_t ccr3; +uint8_t ccr4; +uint8_t ccr5; +uint8_t ccr6; +uint8_t ccr7; static int cyrix_addr; @@ -557,7 +558,8 @@ cpu_set(void) cpu_busspeed = cpu_s->rspeed; cpu_multi = (int) ceil(cpu_s->multi); cpu_dmulti = cpu_s->multi; - ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; + ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; + ccr4 = 0x85; cpu_update_waitstates(); @@ -1442,19 +1444,27 @@ cpu_set(void) } # endif /* USE_DYNAREC */ if (fpu_softfloat) { + x86_opcodes_d9_a16 = ops_sf_fpu_cyrix_d9_a16; + x86_opcodes_d9_a32 = ops_sf_fpu_cyrix_d9_a32; x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_sf_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_sf_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_sf_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_sf_fpu_686_df_a32; + x86_opcodes_db_a16 = ops_sf_fpu_cyrix_686_db_a16; + x86_opcodes_db_a32 = ops_sf_fpu_cyrix_686_db_a32; + x86_opcodes_dd_a16 = ops_sf_fpu_cyrix_dd_a16; + x86_opcodes_dd_a32 = ops_sf_fpu_cyrix_dd_a32; + x86_opcodes_df_a16 = ops_sf_fpu_cyrix_686_df_a16; + x86_opcodes_df_a32 = ops_sf_fpu_cyrix_686_df_a32; } else { + x86_opcodes_d9_a16 = ops_fpu_cyrix_d9_a16; + x86_opcodes_d9_a32 = ops_fpu_cyrix_d9_a32; x86_opcodes_da_a16 = ops_fpu_686_da_a16; x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; + x86_opcodes_db_a16 = ops_fpu_cyrix_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_cyrix_686_db_a32; + x86_opcodes_dd_a16 = ops_fpu_cyrix_dd_a16; + x86_opcodes_dd_a32 = ops_fpu_cyrix_dd_a32; + x86_opcodes_df_a16 = ops_fpu_cyrix_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_cyrix_686_df_a32; } } @@ -4291,6 +4301,9 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) if ((ccr3 & 0xf0) == 0x10) ccr6 = val; break; + case 0xeb: /* CCR7 */ + ccr7 = val & 5; + break; } } @@ -4319,6 +4332,8 @@ cpu_read(uint16_t addr, UNUSED(void *priv)) return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; case 0xea: return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; + case 0xeb: + return ccr7; case 0xfe: return cpu_s->cyrix_id & 0xff; case 0xff: diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 3e72db005..8324c543e 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -589,6 +589,16 @@ extern uint32_t _tr[8]; extern uint32_t cache_index; extern uint8_t _cache[2048]; +/* For the Cyrix 6x86(MX) */ +extern uint8_t ccr0; +extern uint8_t ccr1; +extern uint8_t ccr2; +extern uint8_t ccr3; +extern uint8_t ccr4; +extern uint8_t ccr5; +extern uint8_t ccr6; +extern uint8_t ccr7; + /*Segments - _cs,_ds,_es,_ss are the segment structures CS,DS,ES,SS is the 16-bit data diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 6f15560f3..f1f5004d9 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -272,6 +272,10 @@ reset_common(int hard) msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw = 0; new_ne = 0; + + ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; + ccr4 = 0x85; + if (hascache) cr0 = 1 << 30; else diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 7aec16855..6d93fb435 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -265,14 +265,20 @@ extern const OpFn ops_sf_fpu_d8_a16[32]; extern const OpFn ops_sf_fpu_d8_a32[32]; extern const OpFn ops_sf_fpu_d9_a16[256]; extern const OpFn ops_sf_fpu_d9_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_d9_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_d9_a32[256]; extern const OpFn ops_sf_fpu_da_a16[256]; extern const OpFn ops_sf_fpu_da_a32[256]; extern const OpFn ops_sf_fpu_db_a16[256]; extern const OpFn ops_sf_fpu_db_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_sf_fpu_dc_a16[32]; extern const OpFn ops_sf_fpu_dc_a32[32]; extern const OpFn ops_sf_fpu_dd_a16[256]; extern const OpFn ops_sf_fpu_dd_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_dd_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_dd_a32[256]; extern const OpFn ops_sf_fpu_de_a16[256]; extern const OpFn ops_sf_fpu_de_a32[256]; extern const OpFn ops_sf_fpu_df_a16[256]; @@ -297,6 +303,8 @@ extern const OpFn ops_fpu_d8_a16[32]; extern const OpFn ops_fpu_d8_a32[32]; extern const OpFn ops_fpu_d9_a16[256]; extern const OpFn ops_fpu_d9_a32[256]; +extern const OpFn ops_fpu_cyrix_d9_a16[256]; +extern const OpFn ops_fpu_cyrix_d9_a32[256]; extern const OpFn ops_fpu_da_a16[256]; extern const OpFn ops_fpu_da_a32[256]; extern const OpFn ops_fpu_db_a16[256]; @@ -305,6 +313,8 @@ extern const OpFn ops_fpu_dc_a16[32]; extern const OpFn ops_fpu_dc_a32[32]; extern const OpFn ops_fpu_dd_a16[256]; extern const OpFn ops_fpu_dd_a32[256]; +extern const OpFn ops_fpu_cyrix_dd_a16[256]; +extern const OpFn ops_fpu_cyrix_dd_a32[256]; extern const OpFn ops_fpu_de_a16[256]; extern const OpFn ops_fpu_de_a32[256]; extern const OpFn ops_fpu_df_a16[256]; @@ -316,15 +326,23 @@ extern const OpFn ops_sf_fpu_686_da_a16[256]; extern const OpFn ops_sf_fpu_686_da_a32[256]; extern const OpFn ops_sf_fpu_686_db_a16[256]; extern const OpFn ops_sf_fpu_686_db_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_sf_fpu_686_df_a16[256]; extern const OpFn ops_sf_fpu_686_df_a32[256]; +extern const OpFn ops_sf_fpu_cyrix_686_df_a16[256]; +extern const OpFn ops_sf_fpu_cyrix_686_df_a32[256]; extern const OpFn ops_fpu_686_da_a16[256]; extern const OpFn ops_fpu_686_da_a32[256]; extern const OpFn ops_fpu_686_db_a16[256]; extern const OpFn ops_fpu_686_db_a32[256]; +extern const OpFn ops_fpu_cyrix_686_db_a16[256]; +extern const OpFn ops_fpu_cyrix_686_db_a32[256]; extern const OpFn ops_fpu_686_df_a16[256]; extern const OpFn ops_fpu_686_df_a32[256]; +extern const OpFn ops_fpu_cyrix_686_df_a16[256]; +extern const OpFn ops_fpu_cyrix_686_df_a32[256]; extern const OpFn ops_REPE[1024]; extern const OpFn ops_REPNE[1024]; diff --git a/src/cpu/x86_ops_mmx_emmi.h b/src/cpu/x86_ops_mmx_emmi.h new file mode 100644 index 000000000..4c994be0f --- /dev/null +++ b/src/cpu/x86_ops_mmx_emmi.h @@ -0,0 +1,807 @@ +/* Notes: "src2" means "first operand" */ + +static int +opPMULHRWC_a16(UNUSED(uint32_t fetchdat)) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->w[0] = ((int32_t) (dst->sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = ((int32_t) (dst->sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = ((int32_t) (dst->sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = ((int32_t) (dst->sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMULHRWC_a32(UNUSED(uint32_t fetchdat)) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->w[0] = ((int32_t) (dst->sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = ((int32_t) (dst->sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = ((int32_t) (dst->sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = ((int32_t) (dst->sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMULHRIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] = (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMULHRIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] = (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] = (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] = (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] = (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPDISTIB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->b[0] + abs(src2.b[0] - src.b[0])); + dst->b[1] = USATB(dst->b[1] + abs(src2.b[1] - src.b[1])); + dst->b[2] = USATB(dst->b[2] + abs(src2.b[2] - src.b[2])); + dst->b[3] = USATB(dst->b[3] + abs(src2.b[3] - src.b[3])); + dst->b[4] = USATB(dst->b[4] + abs(src2.b[4] - src.b[4])); + dst->b[5] = USATB(dst->b[5] + abs(src2.b[5] - src.b[5])); + dst->b[6] = USATB(dst->b[6] + abs(src2.b[6] - src.b[6])); + dst->b[7] = USATB(dst->b[7] + abs(src2.b[7] - src.b[7])); + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPDISTIB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->b[0] = USATB(dst->b[0] + abs(src2.b[0] - src.b[0])); + dst->b[1] = USATB(dst->b[1] + abs(src2.b[1] - src.b[1])); + dst->b[2] = USATB(dst->b[2] + abs(src2.b[2] - src.b[2])); + dst->b[3] = USATB(dst->b[3] + abs(src2.b[3] - src.b[3])); + dst->b[4] = USATB(dst->b[4] + abs(src2.b[4] - src.b[4])); + dst->b[5] = USATB(dst->b[5] + abs(src2.b[5] - src.b[5])); + dst->b[6] = USATB(dst->b[6] + abs(src2.b[6] - src.b[6])); + dst->b[7] = USATB(dst->b[7] + abs(src2.b[7] - src.b[7])); + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMACHRIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] += (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] += (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] += (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] += (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPMACHRIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->w[0] += (((int32_t) src2.sw[0] * (int32_t) src.sw[0]) + 0x4000) >> 15; + dst->w[1] += (((int32_t) src2.sw[1] * (int32_t) src.sw[1]) + 0x4000) >> 15; + dst->w[2] += (((int32_t) src2.sw[2] * (int32_t) src.sw[2]) + 0x4000) >> 15; + dst->w[3] += (((int32_t) src2.sw[3] * (int32_t) src.sw[3]) + 0x4000) >> 15; + + MMX_SETEXP(cpu_reg ^ 1); + return 0; +} + +static int +opPADDSIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] + src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] + src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] + src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg ^ 1); + + return 0; +} + +static int +opPADDSIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] + src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] + src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] + src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] + src.sw[3]); + + MMX_SETEXP(cpu_reg ^ 1); + + return 0; +} + +static int +opPSUBSIW_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] - src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] - src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] - src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPSUBSIW_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + src2 = MMX_GETREG(cpu_reg); + dst = MMX_GETREGP(cpu_reg ^ 1); + + MMX_GETSRC(); + + dst->sw[0] = SSATW(src2.sw[0] - src.sw[0]); + dst->sw[1] = SSATW(src2.sw[1] - src.sw[1]); + dst->sw[2] = SSATW(src2.sw[2] - src.sw[2]); + dst->sw[3] = SSATW(src2.sw[3] - src.sw[3]); + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPAVEB_a16(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = (dst->b[0] + src.b[0]) >> 1; + dst->b[1] = (dst->b[1] + src.b[1]) >> 1; + dst->b[2] = (dst->b[2] + src.b[2]) >> 1; + dst->b[3] = (dst->b[3] + src.b[3]) >> 1; + dst->b[4] = (dst->b[4] + src.b[4]) >> 1; + dst->b[5] = (dst->b[5] + src.b[5]) >> 1; + dst->b[6] = (dst->b[6] + src.b[6]) >> 1; + dst->b[7] = (dst->b[7] + src.b[7]) >> 1; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPAVEB_a32(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + dst->b[0] = (dst->b[0] + src.b[0]) >> 1; + dst->b[1] = (dst->b[1] + src.b[1]) >> 1; + dst->b[2] = (dst->b[2] + src.b[2]) >> 1; + dst->b[3] = (dst->b[3] + src.b[3]) >> 1; + dst->b[4] = (dst->b[4] + src.b[4]) >> 1; + dst->b[5] = (dst->b[5] + src.b[5]) >> 1; + dst->b[6] = (dst->b[6] + src.b[6]) >> 1; + dst->b[7] = (dst->b[7] + src.b[7]) >> 1; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMAGW_a16(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (abs(src.sw[0]) > abs(dst->sw[0])) dst->sw[0] = src.sw[0]; + if (abs(src.sw[1]) > abs(dst->sw[1])) dst->sw[1] = src.sw[1]; + if (abs(src.sw[2]) > abs(dst->sw[2])) dst->sw[2] = src.sw[2]; + if (abs(src.sw[3]) > abs(dst->sw[3])) dst->sw[3] = src.sw[3]; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMAGW_a32(uint32_t fetchdat) +{ + MMX_REG src; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + dst = MMX_GETREGP(cpu_reg); + + MMX_GETSRC(); + + if (abs(src.sw[0]) > abs(dst->sw[0])) dst->sw[0] = src.sw[0]; + if (abs(src.sw[1]) > abs(dst->sw[1])) dst->sw[1] = src.sw[1]; + if (abs(src.sw[2]) > abs(dst->sw[2])) dst->sw[2] = src.sw[2]; + if (abs(src.sw[3]) > abs(dst->sw[3])) dst->sw[3] = src.sw[3]; + + MMX_SETEXP(cpu_reg); + + return 0; +} + +static int +opPMVZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] == 0) dst->b[0] = src.b[0]; + if (src2.b[1] == 0) dst->b[1] = src.b[1]; + if (src2.b[2] == 0) dst->b[2] = src.b[2]; + if (src2.b[3] == 0) dst->b[3] = src.b[3]; + if (src2.b[4] == 0) dst->b[4] = src.b[4]; + if (src2.b[5] == 0) dst->b[5] = src.b[5]; + if (src2.b[6] == 0) dst->b[6] = src.b[6]; + if (src2.b[7] == 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] == 0) dst->b[0] = src.b[0]; + if (src2.b[1] == 0) dst->b[1] = src.b[1]; + if (src2.b[2] == 0) dst->b[2] = src.b[2]; + if (src2.b[3] == 0) dst->b[3] = src.b[3]; + if (src2.b[4] == 0) dst->b[4] = src.b[4]; + if (src2.b[5] == 0) dst->b[5] = src.b[5]; + if (src2.b[6] == 0) dst->b[6] = src.b[6]; + if (src2.b[7] == 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVNZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] != 0) dst->b[0] = src.b[0]; + if (src2.b[1] != 0) dst->b[1] = src.b[1]; + if (src2.b[2] != 0) dst->b[2] = src.b[2]; + if (src2.b[3] != 0) dst->b[3] = src.b[3]; + if (src2.b[4] != 0) dst->b[4] = src.b[4]; + if (src2.b[5] != 0) dst->b[5] = src.b[5]; + if (src2.b[6] != 0) dst->b[6] = src.b[6]; + if (src2.b[7] != 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVNZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.b[0] != 0) dst->b[0] = src.b[0]; + if (src2.b[1] != 0) dst->b[1] = src.b[1]; + if (src2.b[2] != 0) dst->b[2] = src.b[2]; + if (src2.b[3] != 0) dst->b[3] = src.b[3]; + if (src2.b[4] != 0) dst->b[4] = src.b[4]; + if (src2.b[5] != 0) dst->b[5] = src.b[5]; + if (src2.b[6] != 0) dst->b[6] = src.b[6]; + if (src2.b[7] != 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVLZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] < 0) dst->b[0] = src.b[0]; + if (src2.sb[1] < 0) dst->b[1] = src.b[1]; + if (src2.sb[2] < 0) dst->b[2] = src.b[2]; + if (src2.sb[3] < 0) dst->b[3] = src.b[3]; + if (src2.sb[4] < 0) dst->b[4] = src.b[4]; + if (src2.sb[5] < 0) dst->b[5] = src.b[5]; + if (src2.sb[6] < 0) dst->b[6] = src.b[6]; + if (src2.sb[7] < 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVLZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] < 0) dst->b[0] = src.b[0]; + if (src2.sb[1] < 0) dst->b[1] = src.b[1]; + if (src2.sb[2] < 0) dst->b[2] = src.b[2]; + if (src2.sb[3] < 0) dst->b[3] = src.b[3]; + if (src2.sb[4] < 0) dst->b[4] = src.b[4]; + if (src2.sb[5] < 0) dst->b[5] = src.b[5]; + if (src2.sb[6] < 0) dst->b[6] = src.b[6]; + if (src2.sb[7] < 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVGEZB_a16(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] >= 0) dst->b[0] = src.b[0]; + if (src2.sb[1] >= 0) dst->b[1] = src.b[1]; + if (src2.sb[2] >= 0) dst->b[2] = src.b[2]; + if (src2.sb[3] >= 0) dst->b[3] = src.b[3]; + if (src2.sb[4] >= 0) dst->b[4] = src.b[4]; + if (src2.sb[5] >= 0) dst->b[5] = src.b[5]; + if (src2.sb[6] >= 0) dst->b[6] = src.b[6]; + if (src2.sb[7] >= 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} + +static int +opPMVGEZB_a32(uint32_t fetchdat) +{ + MMX_REG src, src2; + MMX_REG *dst; + + if (!(ccr7 & 1)) { + x86illegal(); + return 1; + } + + MMX_ENTER(); + + fetch_ea_32(fetchdat); + + if (cpu_mod == 3) { + x86illegal(); + return 1; + } + + dst = MMX_GETREGP(cpu_reg); + src2 = MMX_GETREG(cpu_reg ^ 1); + + MMX_GETSRC(); + + if (src2.sb[0] >= 0) dst->b[0] = src.b[0]; + if (src2.sb[1] >= 0) dst->b[1] = src.b[1]; + if (src2.sb[2] >= 0) dst->b[2] = src.b[2]; + if (src2.sb[3] >= 0) dst->b[3] = src.b[3]; + if (src2.sb[4] >= 0) dst->b[4] = src.b[4]; + if (src2.sb[5] >= 0) dst->b[5] = src.b[5]; + if (src2.sb[6] >= 0) dst->b[6] = src.b[6]; + if (src2.sb[7] >= 0) dst->b[7] = src.b[7]; + + MMX_SETEXP(cpu_reg); + return 0; +} \ No newline at end of file diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index f1362bf76..97f5415b9 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -241,6 +241,24 @@ x87_fround32_64(double b) return (int64_t) x87_fround32(b); } +static __inline int64_t +x87_fround_nearest(double b) +{ + double da, dc; + int64_t a, c; + + da = floor(b); + dc = floor(b + 1.0); + a = (int64_t) da; + c = (int64_t) dc; + if ((b - a) < (c - b)) + return a; + else if ((b - a) > (c - b)) + return c; + else + return (a & 1) ? c : a; +} + static __inline int64_t x87_fround(double b) { @@ -1267,6 +1285,86 @@ const OpFn OP_TABLE(sf_fpu_d9_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(sf_fpu_cyrix_d9_a16)[256] = { + // clang-format off + /*0x00*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x18*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x20*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x28*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x30*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x38*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x40*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x58*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x60*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x68*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x70*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x78*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x80*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x98*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0xa0*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0xa8*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0xb0*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0xb8*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0xc0*/ sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + /*0xe0*/ sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, sf_FTSTP, ILLEGAL_a16, + /*0xe8*/ sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + /*0xf0*/ sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + /*0xf8*/ sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_d9_a32)[256] = { + // clang-format off + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, sf_FLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, sf_FSTs_a32, + sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, sf_FSTPs_a32, + sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, sf_FLDENV_a32, + sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, sf_FLDCW_a32, + sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, sf_FNSTENV_a32, + sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, sf_FNSTCW_a32, + + sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + sf_FCHS, sf_FABS, ILLEGAL_a32, ILLEGAL_a32, sf_FTST, sf_FXAM, sf_FTSTP, ILLEGAL_a32, + sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a32, + sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + // clang-format on +}; + const OpFn OP_TABLE(sf_fpu_287_da_a16)[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, @@ -1750,6 +1848,87 @@ const OpFn OP_TABLE(sf_fpu_686_db_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_cyrix_686_db_a16)[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, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + 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, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + 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, + sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRINT2, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; +const OpFn OP_TABLE(sf_fpu_cyrix_686_db_a32)[256] = { + // clang-format off + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, sf_FILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, sf_FISTil_a32, + sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, sf_FISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, sf_FLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, sf_FSTPe_a32, + + sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, sf_FCMOVNB, + sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, sf_FCMOVNE, + sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, sf_FCMOVNBE, + sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, sf_FCMOVNU, + sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, sf_FUCOMI_st0_stj, + sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, sf_FCOMI_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRINT2, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(sf_fpu_287_dc_a16)[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, @@ -1946,6 +2125,86 @@ const OpFn OP_TABLE(sf_fpu_dd_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(sf_fpu_cyrix_dd_a16)[256] = { + // clang-format off + /*0x00*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x18*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x20*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x28*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x30*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x38*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x40*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x58*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x60*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x68*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x70*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x78*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x80*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x98*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0xa0*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0xa8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb0*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0xb8*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0xc0*/ sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + /*0xe8*/ sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRICHOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_dd_a32)[256] = { + // clang-format off + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, sf_FLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, sf_FSTd_a32, + sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, sf_FSTPd_a32, + sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, sf_FRSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, sf_FNSAVE_a32, + sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, sf_FNSTSW_a32, + + sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRICHOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + const OpFn OP_TABLE(sf_fpu_287_de_a16)[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, @@ -2348,6 +2607,88 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(sf_fpu_cyrix_686_df_a16)[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, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + 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, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + 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, + sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, sf_FRINEAR, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(sf_fpu_cyrix_686_df_a32)[256] = { + // clang-format off + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, sf_FILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, sf_FISTiw_a32, + sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, sf_FISTPiw_a32, + sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, sf_FBLD_PACKED_BCD_a32, + sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, sf_FILDiq_a32, + sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, sf_FBSTP_PACKED_BCD_a32, + sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, sf_FISTPiq_a32, + + sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + sf_FNSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, sf_FUCOMIP_st0_stj, + sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, sf_FCOMIP_st0_stj, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, sf_FRINEAR, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(fpu_d8_a16)[32] = { // clang-format off opFADDs_a16, opFMULs_a16, opFCOMs_a16, opFCOMPs_a16, opFSUBs_a16, opFSUBRs_a16, opFDIVs_a16, opFDIVRs_a16, @@ -2526,6 +2867,86 @@ const OpFn OP_TABLE(fpu_d9_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(fpu_cyrix_d9_a16)[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, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + 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, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + 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, + opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, opFSTs_a16, + opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, opFSTPs_a16, + opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, opFLDENV_a16, + opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, opFLDCW_a16, + opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, opFSTENV_a16, + opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, opFSTCW_a16, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, opFTSTP, ILLEGAL_a16, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_d9_a32)[256] = { + // clang-format off + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, opFLDs_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, opFSTs_a32, + opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, opFSTPs_a32, + opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, opFLDENV_a32, + opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, opFLDCW_a32, + opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, opFSTENV_a32, + opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, opFSTCW_a32, + + opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, opFLD, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFNOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, /*Invalid*/ + opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, opFTSTP, ILLEGAL_a32, + opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, + opF2XM1, opFYL2X, opFPTAN, opFPATAN, opFXTRACT, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS + // clang-format on +}; + const OpFn OP_TABLE(fpu_287_da_a16)[256] = { // clang-format off opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, @@ -3009,6 +3430,87 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_cyrix_686_db_a16)[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, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + 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, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + 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, + opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, opFISTil_a16, + opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, opFISTPil_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, opFLDe_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, opFSTPe_a16, + + opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, + opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, + opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, + opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, + opFNOP, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL_a16, ILLEGAL_a16, + opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, + opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRINT2, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; +const OpFn OP_TABLE(fpu_cyrix_686_db_a32)[256] = { + // clang-format off + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, opFILDil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, opFISTil_a32, + opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, opFISTPil_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, opFLDe_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, opFSTPe_a32, + + opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, opFCMOVNB, + opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, opFCMOVNE, + opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, opFCMOVNBE, + opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, opFCMOVNU, + opFNOP, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL_a32, ILLEGAL_a32, + opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, opFUCOMI, + opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRINT2, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(fpu_287_dc_a16)[32] = { // clang-format off opFADDd_a16, opFMULd_a16, opFCOMd_a16, opFCOMPd_a16, opFSUBd_a16, opFSUBRd_a16, opFDIVd_a16, opFDIVRd_a16, @@ -3205,6 +3707,86 @@ const OpFn OP_TABLE(fpu_dd_a32)[256] = { // clang-format on }; +const OpFn OP_TABLE(fpu_cyrix_dd_a16)[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, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + 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, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + 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, + opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, opFSTd_a16, + opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, opFSTPd_a16, + opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, opFSTOR_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, opFSAVE_a16, + opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, opFSTSW_a16, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRICHOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_dd_a32)[256] = { + // clang-format off + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, opFLDd_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, opFSTd_a32, + opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, opFSTPd_a32, + opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, opFSTOR_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, opFSAVE_a32, + opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, opFSTSW_a32, + + opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, opFFREE, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFST, opFST, opFST, opFST, opFST, opFST, opFST, opFST, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, opFUCOM, + opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, opFUCOMP, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRICHOP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; + const OpFn OP_TABLE(fpu_287_de_a16)[256] = { // clang-format off opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, opFADDiw_a16, @@ -3607,6 +4189,88 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = { }; # endif +# ifndef OPS_286_386 +const OpFn OP_TABLE(fpu_cyrix_686_df_a16)[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, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + 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, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + 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, + opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, opFISTiw_a16, + opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, opFISTPiw_a16, + FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, FBLD_a16, + opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, opFILDiq_a16, + FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, FBSTP_a16, + FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, FISTPiq_a16, + + opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, + opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, + ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, opFRINEAR, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + // clang-format on +}; + +const OpFn OP_TABLE(fpu_cyrix_686_df_a32)[256] = { + // clang-format off + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, opFILDiw_a32, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, opFISTiw_a32, + opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, opFISTPiw_a32, + FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, FBLD_a32, + opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, opFILDiq_a32, + FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, FBSTP_a32, + FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, FISTPiq_a32, + + opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, opFFREEP, + opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, opFXCH, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, opFSTP, + opFSTSW_AX, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, opFUCOMIP, + opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, + ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, opFRINEAR, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, + // clang-format on +}; +# endif + const OpFn OP_TABLE(nofpu_a16)[256] = { // clang-format off op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, op_nofpu_a16, diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index c1f09fda9..cbad12e56 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -554,6 +554,22 @@ opFTST(UNUSED(uint32_t fetchdat)) return 0; } +static int +opFTSTP(UNUSED(uint32_t fetchdat)) +{ + FP_ENTER(); + cpu_state.pc++; + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); + if (ST(0) == 0.0) + cpu_state.npxs |= FPU_SW_C3; + else if (ST(0) < 0.0) + cpu_state.npxs |= FPU_SW_C0; + x87_pop(); + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; +} + static int opFXAM(UNUSED(uint32_t fetchdat)) { @@ -838,6 +854,67 @@ opFRNDINT(UNUSED(uint32_t fetchdat)) return 0; } +static int +opFRINT2(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + st0 = ST(0); + frac = modf(st0, &integral); + if (frac == 0.5 || frac == -0.5) { + dst0 = (st0 < 0) ? floor(st0) : ceil(st0); + } else { + dst0 = round(st0); + } + fesetround(prevRound); + ST(0) = (double) dst0; + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +opFRINEAR(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + ST(0) = (double) x87_fround_nearest(ST(0)); + fesetround(prevRound); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +opFRICHOP(UNUSED(uint32_t fetchdat)) +{ + double dst0, st0, integral, frac; + int prevRound; + + FP_ENTER(); + cpu_state.pc++; + prevRound = fegetround(); + fesetround(FE_TONEAREST); + ST(0) = (double) ((int64_t)(ST(0))); + fesetround(prevRound); + FP_TAG_VALID; + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + static int opFSCALE(UNUSED(uint32_t fetchdat)) { diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index c9e25e97c..620c44691 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -800,3 +800,84 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } + +static int +sf_FRINT2(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_maxMag, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +sf_FRINEAR(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_near_even, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} + +static int +sf_FRICHOP(uint32_t fetchdat) +{ + floatx80 result; + struct softfloat_status_t status; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_stack_underflow(fetchdat, 0, 0); + goto next_ins; + } + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + result = extF80_roundToInt(FPU_read_regi(0), softfloat_round_to_zero, true, &status); + + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { + FPU_save_regi(result, 0); + } + +next_ins: + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frndint) : (x87_timings.frndint * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); + return 0; +} diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index 945ed99d3..d1d9bc1dd 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -459,6 +459,32 @@ sf_FTST(uint32_t fetchdat) return 0; } +static int +sf_FTSTP(uint32_t fetchdat) +{ + const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); + struct softfloat_status_t status; + int rc; + + FP_ENTER(); + FPU_check_pending_exceptions(); + cpu_state.pc++; + clear_C1(); + if (IS_TAG_EMPTY(0)) { + FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); + } else { + status = i387cw_to_softfloat_status_word(i387_get_control_word()); + rc = extF80_compare_normal(FPU_read_regi(0), Const_Z, &status); + setcc(FPU_status_word_flags_fpu_compare(rc)); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); + FPU_pop(); + } + CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); + CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); + return 0; +} + static int sf_FXAM(UNUSED(uint32_t fetchdat)) { From c40aa61be419c6c6ed2365a2c69607964878b95a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 02:09:23 +0600 Subject: [PATCH 19/36] Cyrix 6x86: Correctly initalize ARR3 on reset to avoid some SMM problems --- src/cpu/x86.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cpu/x86.c b/src/cpu/x86.c index f1f5004d9..97ae19f3a 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -275,6 +275,8 @@ reset_common(int hard) ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0; ccr4 = 0x85; + cyrix.arr[3].base = 0x30000; + cyrix.arr[3].size = 65536; if (hascache) cr0 = 1 << 30; From 4c3ea296c3dbe7ab10c9660e2225059eebb1b676 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 5 Mar 2025 17:58:01 -0500 Subject: [PATCH 20/36] Fix ES1370 detection --- src/sound/snd_audiopci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index f8a6e4153..e3e2b9f1a 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -489,7 +489,10 @@ es137x_reset(void *priv) /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ - dev->si_cr = 0xff800000; + if (dev->type == AUDIOPCI_ES1370) + dev->si_cr = 0x00000000; + else + dev->si_cr = 0xff800000; /* DAC1 Channel Sample Count Register, Address 24H Addressable as word, longword */ From 2300339588f42744c8f5485a60a91b884fe6f8b3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:05:16 +0100 Subject: [PATCH 21/36] Included stdlib.h. --- src/cpu/386_dynarec_ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index c31b725b2..3d9a7e080 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -1,6 +1,7 @@ #include -#include #include +#include +#include #include #include #include From 9b47522f43116dfaa04a03d18ced128ecbf31299 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:12:45 +0100 Subject: [PATCH 22/36] FPU: Fix newly-introduced x87-related warnings. --- src/cpu/x87_ops_misc.h | 8 ++++++-- src/cpu/x87_ops_sf_arith.h | 4 ++++ src/cpu/x87_ops_sf_compare.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index cbad12e56..5821a5cd5 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -554,6 +554,7 @@ opFTST(UNUSED(uint32_t fetchdat)) return 0; } +#ifndef FPU_8087 static int opFTSTP(UNUSED(uint32_t fetchdat)) { @@ -569,6 +570,7 @@ opFTSTP(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; } +#endif static int opFXAM(UNUSED(uint32_t fetchdat)) @@ -854,6 +856,8 @@ opFRNDINT(UNUSED(uint32_t fetchdat)) return 0; } +#ifndef FPU_8087 +#ifndef OPS_286_386 static int opFRINT2(UNUSED(uint32_t fetchdat)) { @@ -882,7 +886,6 @@ opFRINT2(UNUSED(uint32_t fetchdat)) static int opFRINEAR(UNUSED(uint32_t fetchdat)) { - double dst0, st0, integral, frac; int prevRound; FP_ENTER(); @@ -896,11 +899,11 @@ opFRINEAR(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int opFRICHOP(UNUSED(uint32_t fetchdat)) { - double dst0, st0, integral, frac; int prevRound; FP_ENTER(); @@ -914,6 +917,7 @@ opFRICHOP(UNUSED(uint32_t fetchdat)) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int opFSCALE(UNUSED(uint32_t fetchdat)) diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index 620c44691..7abde322b 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -801,6 +801,8 @@ next_ins: return 0; } +#ifndef FPU_8087 +#ifndef OPS_286_386 static int sf_FRINT2(uint32_t fetchdat) { @@ -854,6 +856,7 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif static int sf_FRICHOP(uint32_t fetchdat) @@ -881,3 +884,4 @@ next_ins: CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.frndint) : (x87_concurrency.frndint * cpu_multi)); return 0; } +#endif diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index d1d9bc1dd..d90526b82 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -459,6 +459,7 @@ sf_FTST(uint32_t fetchdat) return 0; } +#ifndef FPU_8087 static int sf_FTSTP(uint32_t fetchdat) { @@ -484,6 +485,7 @@ sf_FTSTP(uint32_t fetchdat) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; } +#endif static int sf_FXAM(UNUSED(uint32_t fetchdat)) From 78f50c5b042ebd69c4fec875d47e10cf434e5806 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 6 Mar 2025 00:17:16 +0100 Subject: [PATCH 23/36] Move the Cyrix 6x86 out of the Dev branch. --- CMakeLists.txt | 1 - src/cpu/386_ops.h | 4 ---- src/cpu/CMakeLists.txt | 10 +--------- src/cpu/cpu.c | 10 ---------- src/cpu/cpu_table.c | 2 -- src/cpu/x86_ops.h | 4 ---- src/cpu/x86_ops_mmx_mov.h | 2 -- 7 files changed, 1 insertion(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c33bb3e9..fb71553e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -163,7 +163,6 @@ endif() cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF) -cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF) cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF) cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF) cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF) diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index e8300f134..5113ca817 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -1385,7 +1385,6 @@ const OpFn OP_TABLE(pentium_0f)[1024] = { // clang-format on }; -# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1569,7 +1568,6 @@ const OpFn OP_TABLE(c6x86l_0f)[1024] = { /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, // clang-format on }; -# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiummmx_0f)[1024] = { // clang-format off @@ -1847,7 +1845,6 @@ const OpFn OP_TABLE(k62_0f)[1024] = { // clang-format on }; -# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86mx_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1939,7 +1936,6 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, // clang-format on }; -# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiumpro_0f)[1024] = { // clang-format off diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index 890d02e3e..9c1385d4f 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -42,20 +42,12 @@ endif() endif() -if(CYRIX_6X86) - target_compile_definitions(cpu PRIVATE USE_CYRIX_6X86) - -if(DYNAREC) - add_library(ct686 OBJECT codegen_timing_686.c) - target_link_libraries(86Box ct686) -endif() -endif() - if(DYNAREC) target_sources(cpu PRIVATE 386_dynarec_ops.c) add_library(cgt OBJECT codegen_timing_486.c + codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 13a109d38..e6a22394a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -1420,7 +1420,6 @@ cpu_set(void) #endif /* USE_DYNAREC */ break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -1541,7 +1540,6 @@ cpu_set(void) else if (CPU_Cx6x86) CPUID = 0; /* Disabled on powerup by default */ break; -#endif /* USE_CYRIX_6X86 */ #ifdef USE_AMD_K5 case CPU_K5: @@ -2386,7 +2384,6 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: if (!EAX) { EAX = 0x00000001; @@ -2447,7 +2444,6 @@ cpu_CPUID(void) } else EAX = EBX = ECX = EDX = 0; break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: if (!EAX) { @@ -3124,7 +3120,6 @@ pentium_invalid_rdmsr: cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3164,7 +3159,6 @@ pentium_invalid_rdmsr: } cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -3945,7 +3939,6 @@ pentium_invalid_wrmsr: } break; -#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3979,7 +3972,6 @@ pentium_invalid_wrmsr: break; } break; -#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -4283,14 +4275,12 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) case 0xe8: /* CCR4 */ if ((ccr3 & 0xf0) == 0x10) { ccr4 = val; -#ifdef USE_CYRIX_6X86 if (cpu_s->cpu_type >= CPU_Cx6x86) { if (val & 0x80) CPUID = cpu_s->cpuid_model; else CPUID = 0; } -#endif /* USE_CYRIX_6X86 */ } break; case 0xe9: /* CCR5 */ diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 104d56d05..5a156853e 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -6095,7 +6095,6 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, -#ifdef USE_CYRIX_6X86 { .package = CPU_PKG_SOCKET5_7, .manufacturer = "Cyrix", @@ -6455,7 +6454,6 @@ const cpu_family_t cpu_families[] = { { .name = "", 0 } } }, -#endif /* USE_CYRIX_6X86 */ { .package = CPU_PKG_SOCKET8, .manufacturer = "Intel", diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 6d93fb435..ed95d04d9 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -90,11 +90,9 @@ extern const OpFn dynarec_ops_winchip2_0f[1024]; extern const OpFn dynarec_ops_pentium_0f[1024]; extern const OpFn dynarec_ops_pentiummmx_0f[1024]; -# ifdef USE_CYRIX_6X86 extern const OpFn dynarec_ops_c6x86_0f[1024]; extern const OpFn dynarec_ops_c6x86l_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; -# endif /* USE_CYRIX_6X86 */ extern const OpFn dynarec_ops_k6_0f[1024]; extern const OpFn dynarec_ops_k62_0f[1024]; @@ -233,11 +231,9 @@ extern const OpFn ops_winchip2_0f[1024]; extern const OpFn ops_pentium_0f[1024]; extern const OpFn ops_pentiummmx_0f[1024]; -#ifdef USE_CYRIX_6X86 extern const OpFn ops_c6x86_0f[1024]; extern const OpFn ops_c6x86l_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; -#endif /* USE_CYRIX_6X86 */ extern const OpFn ops_k6_0f[1024]; extern const OpFn ops_k62_0f[1024]; diff --git a/src/cpu/x86_ops_mmx_mov.h b/src/cpu/x86_ops_mmx_mov.h index 8855f8ccd..0bf928198 100644 --- a/src/cpu/x86_ops_mmx_mov.h +++ b/src/cpu/x86_ops_mmx_mov.h @@ -110,7 +110,6 @@ opMOVD_mm_l_a32(uint32_t fetchdat) return 0; } -#ifdef USE_CYRIX_6X86 /*Cyrix maps both MOVD and SMINT to the same opcode*/ static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) @@ -170,7 +169,6 @@ opMOVD_mm_l_a32_cx(uint32_t fetchdat) return 0; } -#endif /* USE_CYRIX_6X86 */ static int opMOVQ_q_mm_a16(uint32_t fetchdat) From 74368bfe7ab523f92d3533f0bdaf49c7c0611b4b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:26:11 +0600 Subject: [PATCH 24/36] Don't include `cpu.h` in `timer.h` Change the name of the define used to indicate SVGA multi-monitor-capable cards --- src/chipset/ali1531.c | 1 + src/chipset/ali1541.c | 1 + src/chipset/ali1543.c | 1 + src/chipset/ali6117.c | 1 + src/chipset/gc100.c | 1 + src/chipset/sis_5511_h2p.c | 1 + src/chipset/sis_5513_p2i.c | 1 + src/chipset/sis_5571_h2p.c | 1 + src/chipset/sis_5581_h2p.c | 1 + src/chipset/sis_5591_h2p.c | 1 + src/chipset/sis_5600_h2p.c | 1 + src/chipset/sis_85c50x.c | 1 + src/device/cartridge.c | 1 + src/device/keyboard_xt.c | 1 + src/device/serial.c | 1 + src/include/86box/timer.h | 2 +- src/include/86box/video.h | 2 ++ src/machine/m_at_socket5.c | 1 + src/machine/m_xt_olivetti.c | 1 + src/machine/m_xt_philips.c | 1 + src/mem/sst_flash.c | 1 + src/qt/qt_main.cpp | 1 + src/qt/qt_settingsdisplay.cpp | 6 +++--- src/scsi/scsi_t128.c | 1 + src/sound/snd_audiopci.c | 1 + src/sound/snd_gus.c | 1 + src/sound/snd_opl_esfm.c | 1 + src/sound/snd_opl_nuked.c | 1 + src/sound/snd_sb.c | 1 + src/timer.c | 1 + src/video/vid_ati_mach64.c | 1 + src/video/vid_ati_mach8.c | 1 + src/video/vid_chips_69000.c | 1 + src/video/vid_mga.c | 1 + src/video/vid_nga.c | 1 + src/video/vid_ogc.c | 1 + src/video/vid_table.c | 6 +++--- 37 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/chipset/ali1531.c b/src/chipset/ali1531.c index e765e6d45..53324f8e6 100644 --- a/src/chipset/ali1531.c +++ b/src/chipset/ali1531.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> diff --git a/src/chipset/ali1541.c b/src/chipset/ali1541.c index eed6ddbc5..ebbcd7e63 100644 --- a/src/chipset/ali1541.c +++ b/src/chipset/ali1541.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 69a8990e9..2f9273736 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> #include <86box/io.h> diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c index 707b528b2..88bb4b572 100644 --- a/src/chipset/ali6117.c +++ b/src/chipset/ali6117.c @@ -26,6 +26,7 @@ #include <86box/io.h> #include <86box/pci.h> #include <86box/pic.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/device.h> diff --git a/src/chipset/gc100.c b/src/chipset/gc100.c index 23455b952..e9eb05ecf 100644 --- a/src/chipset/gc100.c +++ b/src/chipset/gc100.c @@ -27,6 +27,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/nmi.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c index 543fcacc5..b94e69f26 100644 --- a/src/chipset/sis_5511_h2p.c +++ b/src/chipset/sis_5511_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c index 95a890fcf..b2346bbc4 100644 --- a/src/chipset/sis_5513_p2i.c +++ b/src/chipset/sis_5513_p2i.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c index d04964581..a28553487 100644 --- a/src/chipset/sis_5571_h2p.c +++ b/src/chipset/sis_5571_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c index d01e9dd28..83983376d 100644 --- a/src/chipset/sis_5581_h2p.c +++ b/src/chipset/sis_5581_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c index 048e7deea..74dd6dfbd 100644 --- a/src/chipset/sis_5591_h2p.c +++ b/src/chipset/sis_5591_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c index a15c6fff5..c23309de4 100644 --- a/src/chipset/sis_5600_h2p.c +++ b/src/chipset/sis_5600_h2p.c @@ -22,6 +22,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/mem.h> diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 192ae3767..e932ff6ca 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -24,6 +24,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/apm.h> #include <86box/machine.h> diff --git a/src/device/cartridge.c b/src/device/cartridge.c index d2e91ecb3..00464026a 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -22,6 +22,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/plat.h> #include <86box/ui.h> diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index 644168004..ddbcae61b 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -29,6 +29,7 @@ #include #include <86box/86box.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/fdd.h> #include <86box/machine.h> diff --git a/src/device/serial.c b/src/device/serial.c index c25da0070..deb97225a 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -27,6 +27,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/machine.h> #include <86box/io.h> diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 25aff6b2f..37a03d9ca 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -1,7 +1,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -#include "cpu.h" +extern uint64_t tsc; /* Maximum period, currently 1 second. */ #define MAX_USEC64 1000000ULL diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 7ad29838c..2985559e1 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -69,6 +69,8 @@ enum { #define VIDEO_FLAG_TYPE_NONE 5 #define VIDEO_FLAG_TYPE_MASK 7 +#define VIDEO_FLAG_TYPE_SECONDARY VIDEO_FLAG_TYPE_SPECIAL + typedef struct video_timings_t { int type; int write_b; diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index b6e82301b..02922b425 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -29,6 +29,7 @@ #include <86box/fdc_ext.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/fdd.h> #include <86box/fdc.h> diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index b6e4fb94a..34ca441ec 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -30,6 +30,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/io.h> #include <86box/pic.h> diff --git a/src/machine/m_xt_philips.c b/src/machine/m_xt_philips.c index 604ccebaf..eed54e07f 100644 --- a/src/machine/m_xt_philips.c +++ b/src/machine/m_xt_philips.c @@ -23,6 +23,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/nmi.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pit.h> #include <86box/mem.h> diff --git a/src/mem/sst_flash.c b/src/mem/sst_flash.c index b41e0f2e2..34bfae83a 100644 --- a/src/mem/sst_flash.c +++ b/src/mem/sst_flash.c @@ -25,6 +25,7 @@ #include <86box/device.h> #include <86box/mem.h> #include <86box/machine.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> #include <86box/plat.h> diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 7723261b4..719208c18 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -86,6 +86,7 @@ extern MainWindow *main_window; extern "C" { #include <86box/keyboard.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> extern int qt_nvr_save(void); diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 75f8d376b..b7a930711 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -220,9 +220,9 @@ SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) int secondaryFlags = video_card_get_flags(c); if (video_card_available(c) && device_is_valid(video_dev, machineId) - && !((secondaryFlags == primaryFlags) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) - && !(((primaryFlags == VIDEO_FLAG_TYPE_8514) || (primaryFlags == VIDEO_FLAG_TYPE_XGA)) && (secondaryFlags != VIDEO_FLAG_TYPE_MDA) && (secondaryFlags != VIDEO_FLAG_TYPE_SPECIAL)) - && !((primaryFlags != VIDEO_FLAG_TYPE_MDA) && (primaryFlags != VIDEO_FLAG_TYPE_SPECIAL) && ((secondaryFlags == VIDEO_FLAG_TYPE_8514) || (secondaryFlags == VIDEO_FLAG_TYPE_XGA)))) { + && !((secondaryFlags == primaryFlags) && (secondaryFlags != VIDEO_FLAG_TYPE_SECONDARY)) + && !(((primaryFlags == VIDEO_FLAG_TYPE_8514) || (primaryFlags == VIDEO_FLAG_TYPE_XGA)) && (secondaryFlags != VIDEO_FLAG_TYPE_MDA) && (secondaryFlags != VIDEO_FLAG_TYPE_SECONDARY)) + && !((primaryFlags != VIDEO_FLAG_TYPE_MDA) && (primaryFlags != VIDEO_FLAG_TYPE_SECONDARY) && ((secondaryFlags == VIDEO_FLAG_TYPE_8514) || (secondaryFlags == VIDEO_FLAG_TYPE_XGA)))) { ui->comboBoxVideoSecondary->addItem(name, c); if (c == curVideoCard_2) ui->comboBoxVideoSecondary->setCurrentIndex(ui->comboBoxVideoSecondary->count() - 1); diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index a40d803f1..5ac3b5d67 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -29,6 +29,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/dma.h> #include <86box/pic.h> diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index e3e2b9f1a..8d1de442b 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -39,6 +39,7 @@ #include <86box/pci.h> #include <86box/snd_ac97.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/plat_unused.h> #include <86box/snd_akm4531.h> diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 43638473c..1885581a5 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -15,6 +15,7 @@ #include <86box/nmi.h> #include <86box/pic.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #ifdef USE_GUSMAX # include <86box/snd_ad1848.h> diff --git a/src/sound/snd_opl_esfm.c b/src/sound/snd_opl_esfm.c index bcd2a56e9..b80d264d5 100644 --- a/src/sound/snd_opl_esfm.c +++ b/src/sound/snd_opl_esfm.c @@ -32,6 +32,7 @@ #include <86box/86box.h> #include <86box/sound.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/snd_opl.h> #include <86box/plat_unused.h> diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 03851a589..60f5ed2a6 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -46,6 +46,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/device.h> #include <86box/snd_opl.h> diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 4f8b8a0bd..689d0b91e 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -39,6 +39,7 @@ #include <86box/pic.h> #include <86box/rom.h> #include <86box/sound.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/snd_sb.h> #include <86box/plat_unused.h> diff --git a/src/timer.c b/src/timer.c index 9fed37511..03908890f 100644 --- a/src/timer.c +++ b/src/timer.c @@ -3,6 +3,7 @@ #include #include #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nv/vid_nv_rivatimer.h> diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 2df7782ff..24935e3a2 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -28,6 +28,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/pci.h> #include <86box/rom.h> diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 71dd973da..2038f1b1d 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -27,6 +27,7 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mca.h> #include <86box/pci.h> diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index 012a16348..a387e99fa 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -27,6 +27,7 @@ #include <86box/mem.h> #include <86box/rom.h> #include <86box/device.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index f11983a20..00570bd9f 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -23,6 +23,7 @@ #include #include <86box/86box.h> #include <86box/io.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pci.h> diff --git a/src/video/vid_nga.c b/src/video/vid_nga.c index 3640e5106..ef1c6cd40 100644 --- a/src/video/vid_nga.c +++ b/src/video/vid_nga.c @@ -30,6 +30,7 @@ #include <86box/io.h> #include <86box/video.h> #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pit.h> diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index 7fe5fbbeb..a49cd8a22 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -31,6 +31,7 @@ #include <86box/io.h> #include <86box/video.h> #include <86box/86box.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/mem.h> #include <86box/pit.h> diff --git a/src/video/vid_table.c b/src/video/vid_table.c index ff3073c73..d1df2ba20 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -141,10 +141,10 @@ video_cards[] = { { .device = &chips_69000_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5430_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &gd5434_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5436_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5436_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, { .device = &gd5440_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, - { .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, - { .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SPECIAL }, + { .device = &gd5446_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, + { .device = &gd5446_stb_pci_device, .flags = VIDEO_FLAG_TYPE_SECONDARY }, { .device = &gd5480_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000w32p_videomagic_revb_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, { .device = &et4000w32p_revc_pci_device, .flags = VIDEO_FLAG_TYPE_NONE }, From 0e42547cca39beb1d07fd007b4c2d8a1e0a92a8d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:34:24 +0600 Subject: [PATCH 25/36] Remove some `timer.h`-related include hacks --- src/qt/qt_machinestatus.cpp | 3 --- src/qt/qt_mainwindow.cpp | 9 ++++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index d1335873c..dee90f11c 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -19,9 +19,6 @@ #include "qt_machinestatus.hpp" extern "C" { -#define EMU_CPU_H // superhack - don't want timer.h to include cpu.h here, and some combo is preventing a compile -extern uint64_t tsc; - #include <86box/hdd.h> #include <86box/timer.h> #include <86box/86box.h> diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 89d17a07c..552fd0310 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -48,11 +48,10 @@ extern "C" { #include <86box/machine.h> #include <86box/vid_ega.h> #include <86box/version.h> -#if 0 -#include <86box/acpi.h> /* Requires timer.h include, which conflicts with Qt headers */ -#endif -extern atomic_int acpi_pwrbut_pressed; -extern int acpi_enabled; +#include <86box/timer.h> +#include <86box/apm.h> +#include <86box/nvr.h> +#include <86box/acpi.h> #ifdef USE_VNC # include <86box/vnc.h> From 9badd32c9cc14efde3fc7352d4edc9e8c1e1ec71 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:44:37 +0600 Subject: [PATCH 26/36] Remove more `nvr.h` hacks --- src/qt/qt_settingsmachine.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index 771f1cbec..9b1f9849e 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -32,13 +32,9 @@ extern "C" { #include <86box/config.h> #include <86box/device.h> #include <86box/machine.h> +#include <86box/nvr.h> } -// from nvr.h, which we can't import into CPP code -#define TIME_SYNC_DISABLED 0 -#define TIME_SYNC_ENABLED 1 -#define TIME_SYNC_UTC 2 - #include "qt_deviceconfig.hpp" #include "qt_models_common.hpp" From 4090c5a62cf61bc4f4437bb7df0577aed37106ee Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 6 Mar 2025 19:56:08 +0600 Subject: [PATCH 27/36] Fix SDL builds --- src/unix/unix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unix/unix.c b/src/unix/unix.c index 7f653b9b6..33b78ddb1 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -38,6 +38,7 @@ #include <86box/device.h> #include <86box/gameport.h> #include <86box/unix_sdl.h> +#include "cpu.h" #include <86box/timer.h> #include <86box/nvr.h> #include <86box/version.h> From 5c78fa52035892bbe695afc7eca72ec58d68de5a Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 6 Mar 2025 16:03:11 +0100 Subject: [PATCH 28/36] 8514/A compatible changes of the day (March 6th, 2025) 1. Follow the Mach32 manual more closely regarding vblank support. 2. The subsystem status now takes account of the other bits more accurately. 3. The Mach32 PCI, when used with the ATI 68860 ramdac, has its own bpp's when in accelerator mode, separate from the VGA compatible side, so fix this accordingly. 4. Reset the vram when a mapping change occurs, should clear the messups in the ATI Mach8/32 accel video mode tests. --- src/include/86box/vid_8514a.h | 2 +- src/video/vid_8514a.c | 71 +++++++++++++++----------- src/video/vid_ati68860_ramdac.c | 18 +++---- src/video/vid_ati_mach8.c | 88 ++++++++++++++++++++++++--------- 4 files changed, 115 insertions(+), 64 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 57e98cc44..bfde22d5e 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -213,7 +213,7 @@ typedef struct ibm8514_t { int vdisp2; int disp_cntl; int interlace; - uint8_t subsys_cntl; + uint16_t subsys_cntl; uint8_t subsys_stat; atomic_int fifo_idx; diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index 379772820..765258237 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -715,27 +715,13 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) break; case 0x42e8: - if (val & 0x01) - dev->subsys_stat &= ~0x01; - if (val & 0x02) - dev->subsys_stat &= ~0x02; - if (val & 0x04) - dev->subsys_stat &= ~0x04; - if (val & 0x08) - dev->subsys_stat &= ~0x08; + ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val); + dev->subsys_cntl = (dev->subsys_cntl & 0xff00) | val; + dev->subsys_stat &= ~val; break; case 0x42e9: - dev->subsys_cntl = val; - if (val & 0x01) - dev->subsys_stat |= 0x01; - if (val & 0x02) - dev->subsys_stat |= 0x02; - if (val & 0x04) - dev->subsys_stat |= 0x04; - if (val & 0x08) - dev->subsys_stat |= 0x08; - - if ((val & 0xc0) == 0xc0) { + dev->subsys_cntl = (dev->subsys_cntl & 0xff) | (val << 8); + if ((val & 0xc0) == 0x80) { dev->fifo_idx = 0; dev->force_busy = 0; dev->force_busy2 = 0; @@ -882,10 +868,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) switch (port) { case 0x2e8: - if (dev->vc == dev->v_syncstart) + if (dev->vc == dev->dispend) temp |= 0x02; - ibm8514_log("0x2E8 read: Display Status=%02x.\n", temp); + ibm8514_log("Read: Display Status1=%02x.\n", temp); break; case 0x6e8: @@ -910,21 +896,25 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) case 0x42e8: case 0x42e9: - if (dev->vc == dev->v_syncstart) - dev->subsys_stat |= 0x01; + if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) + temp |= 0x01; if (cmd == 6) { - if ((dev->accel.dx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.dx >= clip_l) && (dev->accel.dx <= clip_r_ibm) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b_ibm)) - dev->subsys_stat |= 0x02; + temp |= 0x02; } else { - if ((dev->accel.cx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r_ibm) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b_ibm)) - dev->subsys_stat |= 0x02; + temp |= 0x02; } if (!dev->fifo_idx) { @@ -932,9 +922,10 @@ ibm8514_accel_in(uint16_t port, svga_t *svga) temp |= 0x08; } - if (port & 1) + if (port & 1) { temp = dev->vram_512k_8514 ? 0x00 : 0x80; - else { + temp |= (dev->subsys_cntl >> 8); + } else { temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); temp |= 0x20; } @@ -1155,6 +1146,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1250,6 +1242,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1385,6 +1378,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; 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)) { @@ -1543,6 +1537,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; if (ibm8514_cpu_dest(svga)) { READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); } else @@ -1634,6 +1629,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; 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)) { @@ -1832,6 +1828,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -1989,6 +1986,7 @@ skip_vector_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; 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)) { @@ -2150,6 +2148,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2232,6 +2231,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2313,6 +2313,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2424,6 +2425,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2546,6 +2548,7 @@ skip_nibble_rect_write: (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2650,9 +2653,10 @@ skip_nibble_rect_write: dev->accel.cx = CLAMP(dev->accel.cx, clip_l, clip_r); if ((dev->accel.cx >= clip_l) && - (dev->accel.cx < clip_r) && + (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2811,6 +2815,7 @@ skip_nibble_rect_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -2978,6 +2983,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3075,6 +3081,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch ((mix_dat & 0x01) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -3174,6 +3181,7 @@ skip_nibble_bitblt_write: (dx <= (((uint64_t)clip_r) * 3)) && (dev->accel.dy >= (clip_t << 1)) && (dev->accel.dy <= (clip_b << 1))) { + dev->subsys_stat |= 0x02; READ(dev->accel.src + cx, src_dat); READ(dev->accel.dest + dx, dest_dat); @@ -3196,6 +3204,7 @@ skip_nibble_bitblt_write: (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3704,6 +3713,8 @@ ibm8514_poll(void *priv) dev->vc &= 0xfff; if (dev->vc == dev->dispend) { + dev->subsys_stat |= 0x01; + ibm8514_log("VBLANK irq.\n"); dev->dispon = 0; for (x = 0; x < ((dev->vram_mask + 1) >> 12); x++) { diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index bb5ccbf31..17b2a6d22 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -70,20 +70,19 @@ void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga) { ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; switch (addr) { case 0: - svga_out((dev && dev->on) ? 0x2ec : 0x3c8, val, svga); + svga_out(0x3c8, val, svga); break; case 1: - svga_out((dev && dev->on) ? 0x2ed : 0x3c9, val, svga); + svga_out(0x3c9, val, svga); break; case 2: - svga_out((dev && dev->on) ? 0x2ea : 0x3c6, val, svga); + svga_out(0x3c6, val, svga); break; case 3: - svga_out((dev && dev->on) ? 0x2eb : 0x3c7, val, svga); + svga_out(0x3c7, val, svga); break; default: ramdac->regs[addr & 0xf] = val; @@ -176,21 +175,20 @@ uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga) { const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv; - const ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint8_t temp = 0; switch (addr) { case 0: - temp = svga_in((dev && dev->on) ? 0x2ec : 0x3c8, svga); + temp = svga_in(0x3c8, svga); break; case 1: - temp = svga_in((dev && dev->on) ? 0x2ed : 0x3c9, svga); + temp = svga_in(0x3c9, svga); break; case 2: - temp = svga_in((dev && dev->on) ? 0x2ea : 0x3c6, svga); + temp = svga_in(0x3c6, svga); break; case 3: - temp = svga_in((dev && dev->on) ? 0x2eb : 0x3c7, svga); + temp = svga_in(0x3c7, svga); break; case 4: case 8: diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index 2038f1b1d..6e2798295 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -438,6 +438,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -661,6 +662,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -1067,6 +1069,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; if (mach->accel.dp_config & 0x02) { READ(dev->accel.src + dev->accel.cx, poly_src); poly_src = ((poly_src & rd_mask) == rd_mask); @@ -1308,6 +1311,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1441,6 +1445,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; mach->accel.clip_overrun = 0; if (mach->accel.linedraw_opt & 0x02) { if (dev->bpp) { @@ -1599,6 +1604,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -1733,6 +1739,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) { + dev->subsys_stat |= 0x02; mach->accel.clip_overrun = 0; switch (mix ? frgd_sel : bkgd_sel) { case 0: @@ -2028,6 +2035,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) { + dev->subsys_stat |= 0x02; switch (mix ? frgd_sel : bkgd_sel) { case 0: src_dat = dev->accel.bkgd_color; @@ -2333,6 +2341,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x2ed: rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); + mach_log("8514/A RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); if ((dev->local & 0xff) >= 0x02) { if (mach->regs[0xb0] & 0x20) { /*ATI extended 8514/A mode.*/ mach_log("Extended 8514/A mode.\n"); @@ -2341,10 +2350,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); mach32_updatemapping(mach, svga); } - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + if (dev->on) + svga_out(addr, val, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } } else svga_out(addr, val, svga); return; @@ -2355,6 +2368,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv) case 0x3C9: rs2 = !!(mach->regs[0xa0] & 0x20); rs3 = !!(mach->regs[0xa0] & 0x40); + mach_log("VGA RS2=%d, RS3=%d, addr=%03x.\n", rs2, rs3, addr); if ((dev->local & 0xff) >= 0x02) { if (svga->attrregs[0x10] & 0x40) { mach_log("VGA mode.\n"); @@ -2363,10 +2377,14 @@ mach_out(uint16_t addr, uint8_t val, void *priv) svga_recalctimings(svga); mach32_updatemapping(mach, svga); } - if (mach->pci_bus && !mach->ramdac_type) - ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); - else - ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + if (dev->on) + svga_out(addr, val, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + ati68860_ramdac_out((addr & 0x03) | (rs2 << 2) | (rs3 << 3), val, svga->ramdac, svga); + else + ati68875_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } } else svga_out(addr, val, svga); return; @@ -2481,10 +2499,14 @@ mach_in(uint16_t addr, void *priv) rs2 = !!(mach->accel.ext_ge_config & 0x1000); rs3 = !!(mach->accel.ext_ge_config & 0x2000); if ((dev->local & 0xff) >= 0x02) { - if (mach->pci_bus && !mach->ramdac_type) - temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); - else - temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + if (dev->on) + temp = svga_in(addr, svga); + else { + if (mach->pci_bus && !mach->ramdac_type) + temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); + else + temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } } else temp = svga_in(addr, svga); break; @@ -3407,7 +3429,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u static void mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - if (port != 0x42e8 && port != 0x42e9) + if (port == 0x42e8 || port == 0x42e9) mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { @@ -3422,7 +3444,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 break; case 0x42e9: ibm8514_accel_out(port, val, svga, 2); - if ((val & 0xc0) == 0xc0) { + if ((val & 0xc0) == 0x80) { dev->ext_fifo_idx = 0; mach->force_busy = 0; } @@ -3513,6 +3535,11 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 svga_recalctimings(svga); break; + case 0x46e8: + case 0x46e9: + mach_log("0x%04x write: VGA subsystem enable add-on=%02x.\n", port, val); + break; + case 0x4ae8: dev->accel.advfunc_cntl = val; dev->on = dev->accel.advfunc_cntl & 0x01; @@ -4201,6 +4228,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) switch (port) { case 0x2e8: + case 0x2e9: case 0x6e8: case 0x22e8: case 0x26e8: @@ -4212,18 +4240,22 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x42e8: case 0x42e9: - if (dev->vc == dev->v_syncstart) + if ((dev->subsys_cntl & 0x01) && !(dev->subsys_stat & 0x01) && (dev->vc == dev->dispend)) temp |= 0x01; if (mach->accel.cmd_type == -1) { if (cmd == 6) { - if ((dev->accel.dx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.dx >= clip_l) && (dev->accel.dx <= clip_r_ibm) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b_ibm)) temp |= 0x02; } else { - if ((dev->accel.cx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r_ibm) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b_ibm)) @@ -4234,7 +4266,9 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 1: case 2: case 5: - if ((dev->accel.dx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.dx >= clip_l) && (dev->accel.dx <= clip_r) && (dev->accel.dy >= clip_t) && (dev->accel.dy <= clip_b)) @@ -4242,7 +4276,9 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) break; case 3: case 4: - if ((dev->accel.cx >= clip_l) && + if ((dev->subsys_cntl & 0x02) && + !(dev->subsys_stat & 0x02) && + (dev->accel.cx >= clip_l) && (dev->accel.cx <= clip_r) && (dev->accel.cy >= clip_t) && (dev->accel.cy <= clip_b)) @@ -4257,16 +4293,17 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) if ((!dev->force_busy && !dev->force_busy2) || !mach->force_busy) temp |= 0x08; } - if (port & 1) + if (port & 1) { temp = dev->vram_512k_8514 ? 0x00 : 0x80; - else { + temp |= (dev->subsys_cntl >> 8); + } else { temp |= (dev->subsys_stat | (dev->vram_512k_8514 ? 0x00 : 0x80)); if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); else temp |= 0x20; } - mach_log("0x%04x read: Subsystem Status=%02x.\n", port, temp); + mach_log("0x%04x read: Subsystem Status=%02x, monitoralias=%02x.\n", port, temp, mach->accel.ext_ge_config & 0x07); break; /*ATI Mach8/32 specific registers*/ @@ -4403,7 +4440,8 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); + if (port == 0x2ee8 || port == 0x2ee9 || port == 0x42e8 || port == 0x42e9) + mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; } @@ -5419,6 +5457,10 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); mem_mapping_set_p(&svga->mapping, mach); } else { + if (!dev->on) { + memset(dev->vram, 0, dev->vram_size); + memset(dev->changedvram, 0, (dev->vram_size >> 12) + 1); + } mach_log("IBM compatible banked mapping.\n"); mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); mem_mapping_set_p(&svga->mapping, svga); From d25aed2da98cfc4e2208bb46cd24776d5e6b6020 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 7 Mar 2025 00:36:09 +0600 Subject: [PATCH 29/36] Add global mute option --- src/86box.c | 1 + src/config.c | 5 ++++ src/include/86box/86box.h | 1 + src/qt/icons/sound_mute.ico | Bin 0 -> 9622 bytes src/qt/qt_machinestatus.cpp | 45 +++++++++++++++++++++++++++++++----- src/qt/qt_machinestatus.hpp | 6 +++++ src/qt/qt_mainwindow.cpp | 1 + src/qt_resources.qrc | 1 + src/sound/openal.c | 2 +- src/sound/xaudio2.c | 2 +- 10 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 src/qt/icons/sound_mute.ico diff --git a/src/86box.c b/src/86box.c index 6b64cd2ec..aa3afb085 100644 --- a/src/86box.c +++ b/src/86box.c @@ -213,6 +213,7 @@ int do_auto_pause = 0; /* (C) Auto-pa int hook_enabled = 1; /* (C) Keyboard hook is enabled */ int test_mode = 0; /* (C) Test mode */ char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */ +int sound_muted = 0; /* (C) Is sound muted? */ int other_ide_present = 0; /* IDE controllers from non-IDE cards are present */ diff --git a/src/config.c b/src/config.c index 6c34c4790..07e770822 100644 --- a/src/config.c +++ b/src/config.c @@ -168,6 +168,7 @@ load_general(void) kbd_req_capture = ini_section_get_int(cat, "kbd_req_capture", 0); hide_status_bar = ini_section_get_int(cat, "hide_status_bar", 0); hide_tool_bar = ini_section_get_int(cat, "hide_tool_bar", 0); + sound_muted = ini_section_get_int(cat, "sound_muted", 0); confirm_reset = ini_section_get_int(cat, "confirm_reset", 1); confirm_exit = ini_section_get_int(cat, "confirm_exit", 1); @@ -1846,6 +1847,10 @@ save_general(void) const char *va_name; + ini_section_set_int(cat, "sound_muted", sound_muted); + if (sound_muted == 0) + ini_section_delete_var(cat, "sound_muted"); + ini_section_set_int(cat, "vid_resize", vid_resize); if (vid_resize == 0) ini_section_delete_var(cat, "vid_resize"); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index e4e5ecae1..79bb84009 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -158,6 +158,7 @@ extern int other_scsi_present; /* SCSI controllers from non-SCSI ca extern int hard_reset_pending; extern int fixed_size_x; extern int fixed_size_y; +extern int sound_muted; /* (C) Is sound muted? */ extern int do_auto_pause; /* (C) Auto-pause the emulator on focus loss */ extern int auto_paused; extern double mouse_sensitivity; /* (C) Mouse sensitivity scale */ diff --git a/src/qt/icons/sound_mute.ico b/src/qt/icons/sound_mute.ico new file mode 100644 index 0000000000000000000000000000000000000000..89a8407354ce0ef805689d75763cd17fd58ce52b GIT binary patch literal 9622 zcmeI2F^?QY5QTg3frUWg0!ujC3km%XxJ{hmz$3y#LPCTj#2ygBWDxKJHUNPJ38zQ| zcNRau(TdPGxd2PZiFL4Mx2Wo#Z>PIwW_NDxI1$iN@9VCvdhd15-pqPr=O%8??e9Cq z1NY&cbGMyyH*SRaPp>%lqsDID4D&Bub?$@LoI5xO^Y69p56yi`Yjmg#A+F#KweGyF zEK7-MY)p^By+dDHbLd#2?s<9((G6%GsHMc_-5hDHfE zj>d5jeXF+yFZvqtd+5_=-D+t$2Xi>cQ{;T2P#97}4zrX^huZt|d7J0reQt7;yDgK~X1Y9Wo{rqBraTdITIc;y+;IpxD#LdsMSiBy_d{0t; zj90cpO0Mb5zKSW^g5eX()^rSxKe*UU-PUs z?bKNYV=(9H=JedHkDLQ8koyowejl0u_ho9}(k0HsBkNJz%B_(XX8MU9+&L#)idF+Qt5he zIFV|8U5dMJN>x>|c=t?}4_?ShUnHy*~s4w zvs>TlGQE7hOW&`fZFI&tbpMuXE%p$PZOJEee{9v><$-GhHoAlU{t|8W4;R{CupeIo zG)m=(`_}J1XVIz6S)mEyDXa$%>0Z&aXlNbx2CoSh`^_=;Kt6Fi7=KseEU2q7*)RL* z)25a@=BWprCFjmHuz0)Wzpry`=D8Lg+Kj^^aH0Vxb5I$RYeXLPV4g?356$V&{o6IQ zd~F`_5JKZV@x?yjWDcT9K6%U|^~7UGJPL&&9J|gzvy**Omm_(^nS;bZjXTC5`v$3H z-yr$Mv7_~!OREe{v_ax%gDrwf2%v?wQYL4QHhDu49`d(YC8y5=>)SXkx`qZGn6v*8 z{DZ#-aHFa7 #include <86box/ui.h> #include <86box/machine_status.h> +#include <86box/config.h> }; #include @@ -89,7 +90,7 @@ struct Pixmaps { PixmapSetEmptyActive mo; PixmapSetActive hd; PixmapSetEmptyActive net; - QPixmap sound; + QPixmap sound, soundMuted; }; struct StateActive { @@ -215,6 +216,7 @@ struct MachineStatus::States { pixmaps.hd.load("/hard_disk%1.ico"); pixmaps.net.load("/network%1.ico"); pixmaps.sound = ProgSettings::loadIcon("/sound.ico").pixmap(pixmap_size); + pixmaps.soundMuted = ProgSettings::loadIcon("/sound_mute.ico").pixmap(pixmap_size); cartridge[0].pixmaps = &pixmaps.cartridge; cartridge[1].pixmaps = &pixmaps.cartridge; @@ -256,12 +258,19 @@ MachineStatus::MachineStatus(QObject *parent) , refreshTimer(new QTimer(this)) { d = std::make_unique(this); + muteUnmuteAction = nullptr; connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); refreshTimer->start(75); } MachineStatus::~MachineStatus() = default; +void +MachineStatus::setSoundGainAction(QAction* action) +{ + soundGainAction = action; +} + bool MachineStatus::hasCassette() { @@ -494,6 +503,28 @@ MachineStatus::refresh(QStatusBar *sbar) } sbar->removeWidget(d->sound.get()); + if (!muteUnmuteAction) { + muteUnmuteAction = new QAction; + connect(muteUnmuteAction, &QAction::triggered, this, [this]() { + sound_muted ^= 1; + config_save(); + if (d->sound) + d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + + muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); + }); + } + + if (!soundMenu) { + soundMenu = new QMenu((QWidget*)parent()); + + soundMenu->addAction(muteUnmuteAction); + soundMenu->addSeparator(); + soundMenu->addAction(soundGainAction); + + muteUnmuteAction->setParent(soundMenu); + } + if (cassette_enable) { d->cassette.label = std::make_unique(); d->cassette.setEmpty(QString(cassette_fname).isEmpty()); @@ -662,12 +693,14 @@ MachineStatus::refresh(QStatusBar *sbar) } d->sound = std::make_unique(); - d->sound->setPixmap(d->pixmaps.sound); - - connect(d->sound.get(), &ClickableLabel::doubleClicked, d->sound.get(), [](QPoint pos) { - SoundGain gain(main_window); - gain.exec(); + d->sound->setPixmap(sound_muted ? d->pixmaps.soundMuted : d->pixmaps.sound); + if (muteUnmuteAction) + muteUnmuteAction->setText(sound_muted ? tr("&Unmute") : tr("&Mute")); + + connect(d->sound.get(), &ClickableLabel::clicked, this, [this](QPoint pos) { + this->soundMenu->popup(pos - QPoint(0, this->soundMenu->sizeHint().height())); }); + d->sound->setToolTip(tr("Sound")); sbar->addWidget(d->sound.get()); d->text = std::make_unique(); diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index fc0e33e91..90b420763 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -1,6 +1,8 @@ #ifndef QT_MACHINESTATUS_HPP #define QT_MACHINESTATUS_HPP +#include +#include #include #include #include @@ -71,6 +73,7 @@ public: QString getMessage(); void clearActivity(); + void setSoundGainAction(QAction* action); public slots: void refresh(QStatusBar *sbar); void message(const QString &msg); @@ -82,6 +85,9 @@ private: struct States; std::unique_ptr d; QTimer *refreshTimer; + QAction *soundGainAction; + QAction *muteUnmuteAction; + QMenu *soundMenu; }; #endif // QT_MACHINESTATUS_HPP diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 552fd0310..61f5f6fe1 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -178,6 +178,7 @@ MainWindow::MainWindow(QWidget *parent) extern MainWindow *main_window; main_window = this; ui->setupUi(this); + status->setSoundGainAction(ui->actionSound_gain); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 1f6341786..6ca323b89 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -43,6 +43,7 @@ qt/icons/other_removable_devices.ico qt/icons/ports.ico qt/icons/sound.ico + qt/icons/sound_mute.ico qt/icons/storage_controllers.ico qt/icons/zip.ico qt/icons/zip_active.ico diff --git a/src/sound/openal.c b/src/sound/openal.c index a41199b23..90f626362 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -278,7 +278,7 @@ givealbuffer_common(const void *buf, const uint8_t src, const int size, const in alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed); if (processed >= 1) { - const double gain = pow(10.0, (double) sound_gain / 20.0); + const double gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0); alListenerf(AL_GAIN, (float) gain); alSourceUnqueueBuffers(source[src], 1, &buffer); diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c index 9b341f574..2aee97efc 100644 --- a/src/sound/xaudio2.c +++ b/src/sound/xaudio2.c @@ -245,7 +245,7 @@ givealbuffer_common(const void *buf, IXAudio2SourceVoice *sourcevoice, const siz if (!initialized) return; - (void) IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double) sound_gain / 20.0), + (void) IXAudio2MasteringVoice_SetVolume(mastervoice, sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0), XAUDIO2_COMMIT_NOW); XAUDIO2_BUFFER buffer = { 0 }; buffer.Flags = 0; From c1c4bcc889d59f5a4f714d6802e5592054f5cacf Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 15:54:50 +0500 Subject: [PATCH 30/36] Disable Win11 rounded window corners when the status bar is hidden --- src/qt/qt_mainwindow.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 61f5f6fe1..9802a2666 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -122,6 +122,19 @@ extern int qt_nvr_save(void); #include "x11_util.h" #endif +#ifdef Q_OS_WINDOWS +#include +#ifndef DWMWA_WINDOW_CORNER_PREFERENCE +#define DWMWA_WINDOW_CORNER_PREFERENCE 33 +#endif +#ifndef DWMWCP_DEFAULT +#define DWMWCP_DEFAULT 0 +#endif +#ifndef DWMWCP_DONOTROUND +#define DWMWCP_DONOTROUND 1 +#endif +#endif + #ifdef Q_OS_MACOS # include "cocoa_keyboard.hpp" // The namespace is required to avoid clashing typedefs; we only use this @@ -181,6 +194,10 @@ MainWindow::MainWindow(QWidget *parent) status->setSoundGainAction(ui->actionSound_gain); ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); +#ifdef Q_OS_WINDOWS + auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); + DwmSetWindowAttribute((HWND) this->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); this->centralWidget()->setStyleSheet("background-color: black;"); ui->toolBar->setVisible(!hide_tool_bar); @@ -1833,6 +1850,10 @@ MainWindow::on_actionHide_status_bar_triggered() hide_status_bar ^= 1; ui->actionHide_status_bar->setChecked(hide_status_bar); statusBar()->setVisible(!hide_status_bar); +#ifdef Q_OS_WINDOWS + auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); + DwmSetWindowAttribute((HWND) main_window->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif if (vid_resize >= 2) { setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); } else { From d6fa4d4f98f15f6b21ebffcff0bfa3a2f6b8a76a Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Thu, 6 Mar 2025 22:20:13 +0500 Subject: [PATCH 31/36] Disable Win11 rounded corners on the secondary monitor windows --- src/qt/qt_mainwindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 9802a2666..036f56375 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -816,6 +816,10 @@ MainWindow::initRendererMonitorSlot(int monitor_index) if (vid_resize == 2) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); secondaryRenderer->setWindowIcon(this->windowIcon()); +#ifdef Q_OS_WINDOWS + auto cornerPreference = DWMWCP_DONOTROUND; + DwmSetWindowAttribute((HWND) secondaryRenderer->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +#endif if (show_second_monitors) { secondaryRenderer->show(); if (window_remember) { From e6f96352e083a9df48e87babed6e3afadf7a0e89 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 02:01:00 +0500 Subject: [PATCH 32/36] Fix serial passthrough configure buttons not re-enabling when the checkboxes are toggled --- src/qt/qt_settingsports.cpp | 43 ++++++++++++++++--------------------- src/qt/qt_settingsports.hpp | 14 ++++++------ 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 9679c9e21..3855a8b68 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -68,21 +68,14 @@ SettingsPorts::SettingsPorts(QWidget *parent) for (int i = 0; i < SERIAL_MAX; i++) { auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + auto *buttonPass = findChild(QString("pushButtonSerialPassThru%1").arg(i + 1)); if (checkBox != NULL) checkBox->setChecked(com_ports[i].enabled > 0); - if (checkBoxPass != NULL) + if (checkBoxPass != NULL) { checkBoxPass->setChecked(serial_passthrough_enabled[i]); + buttonPass->setEnabled(serial_passthrough_enabled[i]); + } } - - ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]); - ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]); - ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]); - ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]); -#if 0 - ui->pushButtonSerialPassThru5->setEnabled(serial_passthrough_enabled[4]); - ui->pushButtonSerialPassThru6->setEnabled(serial_passthrough_enabled[5]); - ui->pushButtonSerialPassThru7->setEnabled(serial_passthrough_enabled[6]); -#endif } SettingsPorts::~SettingsPorts() @@ -181,45 +174,45 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() #endif void -SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru1_stateChanged(int state) { - ui->pushButtonSerialPassThru1->setEnabled(checked); + ui->pushButtonSerialPassThru1->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru2_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru2_stateChanged(int state) { - ui->pushButtonSerialPassThru2->setEnabled(checked); + ui->pushButtonSerialPassThru2->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru3_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru3_stateChanged(int state) { - ui->pushButtonSerialPassThru3->setEnabled(checked); + ui->pushButtonSerialPassThru3->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru4_stateChanged(int state) { - ui->pushButtonSerialPassThru4->setEnabled(checked); + ui->pushButtonSerialPassThru4->setEnabled(state == Qt::Checked); } #if 0 void -SettingsPorts::on_checkBoxSerialPassThru5_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru5_stateChanged(int state) { - ui->pushButtonSerialPassThru5->setEnabled(checked); + ui->pushButtonSerialPassThru5->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru6_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru6_stateChanged(int state) { - ui->pushButtonSerialPassThru6->setEnabled(checked); + ui->pushButtonSerialPassThru6->setEnabled(state == Qt::Checked); } void -SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked) +SettingsPorts::on_checkBoxSerialPassThru7_stateChanged(int state) { - ui->pushButtonSerialPassThru7->setEnabled(checked); + ui->pushButtonSerialPassThru7->setEnabled(state == Qt::Checked); } #endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index fb9cdb343..cba5bceff 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -18,14 +18,14 @@ public: #if 0 private slots: - void on_checkBoxSerialPassThru7_clicked(bool checked); - void on_checkBoxSerialPassThru6_clicked(bool checked); - void on_checkBoxSerialPassThru5_clicked(bool checked); + void on_checkBoxSerialPassThru7_stateChanged(int state); + void on_checkBoxSerialPassThru6_stateChanged(int state); + void on_checkBoxSerialPassThru5_stateChanged(int state); #endif - void on_checkBoxSerialPassThru4_clicked(bool checked); - void on_checkBoxSerialPassThru3_clicked(bool checked); - void on_checkBoxSerialPassThru2_clicked(bool checked); - void on_checkBoxSerialPassThru1_clicked(bool checked); + void on_checkBoxSerialPassThru4_stateChanged(int state); + void on_checkBoxSerialPassThru3_stateChanged(int state); + void on_checkBoxSerialPassThru2_stateChanged(int state); + void on_checkBoxSerialPassThru1_stateChanged(int state); private slots: #if 0 From b018017c55a5f2c8c80cc6816369ac56ef76811f Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 02:05:30 +0500 Subject: [PATCH 33/36] Disable serial passthrough checkboxes when the corresponding port is disabled --- src/qt/qt_settingsports.cpp | 54 ++++++++++++++++++++++++++++++++++++- src/qt/qt_settingsports.hpp | 22 ++++++++++----- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 3855a8b68..e5a8039a4 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -72,8 +72,9 @@ SettingsPorts::SettingsPorts(QWidget *parent) if (checkBox != NULL) checkBox->setChecked(com_ports[i].enabled > 0); if (checkBoxPass != NULL) { + checkBoxPass->setEnabled(com_ports[i].enabled > 0); checkBoxPass->setChecked(serial_passthrough_enabled[i]); - buttonPass->setEnabled(serial_passthrough_enabled[i]); + buttonPass->setEnabled((com_ports[i].enabled > 0) && serial_passthrough_enabled[i]); } } } @@ -173,6 +174,57 @@ SettingsPorts::on_pushButtonSerialPassThru7_clicked() } #endif +void +SettingsPorts::on_checkBoxSerial1_stateChanged(int state) +{ + ui->checkBoxSerialPassThru1->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru1->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru1->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial2_stateChanged(int state) +{ + ui->checkBoxSerialPassThru2->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru2->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru2->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial3_stateChanged(int state) +{ + ui->checkBoxSerialPassThru3->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru3->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru3->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial4_stateChanged(int state) +{ + ui->checkBoxSerialPassThru4->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru4->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru4->isChecked()); +} + +#if 0 +void +SettingsPorts::on_checkBoxSerial5_stateChanged(int state) +{ + ui->checkBoxSerialPassThru5->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru5->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru5->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial6_stateChanged(int state) +{ + ui->checkBoxSerialPassThru6->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru6->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru6->isChecked()); +} + +void +SettingsPorts::on_checkBoxSerial7_stateChanged(int state) +{ + ui->checkBoxSerialPassThru7->setEnabled(state == Qt::Checked); + ui->pushButtonSerialPassThru7->setEnabled((state == Qt::Checked) && ui->checkBoxSerialPassThru7->isChecked()); +} +#endif + void SettingsPorts::on_checkBoxSerialPassThru1_stateChanged(int state) { diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index cba5bceff..7d332509c 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -16,8 +16,8 @@ public: void save(); -#if 0 private slots: +#if 0 void on_checkBoxSerialPassThru7_stateChanged(int state); void on_checkBoxSerialPassThru6_stateChanged(int state); void on_checkBoxSerialPassThru5_stateChanged(int state); @@ -27,7 +27,16 @@ private slots: void on_checkBoxSerialPassThru2_stateChanged(int state); void on_checkBoxSerialPassThru1_stateChanged(int state); -private slots: +#if 0 + void on_checkBoxSerial7_stateChanged(int state); + void on_checkBoxSerial6_stateChanged(int state); + void on_checkBoxSerial5_stateChanged(int state); +#endif + void on_checkBoxSerial4_stateChanged(int state); + void on_checkBoxSerial3_stateChanged(int state); + void on_checkBoxSerial2_stateChanged(int state); + void on_checkBoxSerial1_stateChanged(int state); + #if 0 void on_pushButtonSerialPassThru7_clicked(); void on_pushButtonSerialPassThru6_clicked(); @@ -38,11 +47,10 @@ private slots: void on_pushButtonSerialPassThru2_clicked(); void on_pushButtonSerialPassThru1_clicked(); -private slots: - void on_checkBoxParallel4_stateChanged(int arg1); - void on_checkBoxParallel3_stateChanged(int arg1); - void on_checkBoxParallel2_stateChanged(int arg1); - void on_checkBoxParallel1_stateChanged(int arg1); + void on_checkBoxParallel4_stateChanged(int state); + void on_checkBoxParallel3_stateChanged(int state); + void on_checkBoxParallel2_stateChanged(int state); + void on_checkBoxParallel1_stateChanged(int state); private: Ui::SettingsPorts *ui; From 3bbeae91d1c405ea979b948c3407f3cef3479327 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Sat, 1 Mar 2025 15:22:36 +0500 Subject: [PATCH 34/36] Add plumbing for updates on machine change to the port settings page --- src/qt/qt_settings.cpp | 2 + src/qt/qt_settingsports.cpp | 149 +++++++++++++++++++----------------- src/qt/qt_settingsports.hpp | 69 +++++++++-------- 3 files changed, 116 insertions(+), 104 deletions(-) diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 67064b73a..471558e22 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -153,6 +153,8 @@ Settings::Settings(QWidget *parent) &SettingsSound::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, network, &SettingsNetwork::onCurrentMachineChanged); + connect(machine, &SettingsMachine::currentMachineChanged, ports, + &SettingsPorts::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, storageControllers, &SettingsStorageControllers::onCurrentMachineChanged); connect(machine, &SettingsMachine::currentMachineChanged, otherPeripherals, diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index e5a8039a4..630c843b9 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -38,6 +38,40 @@ SettingsPorts::SettingsPorts(QWidget *parent) , ui(new Ui::SettingsPorts) { ui->setupUi(this); + onCurrentMachineChanged(machine); +} + +SettingsPorts::~SettingsPorts() +{ + delete ui; +} + +void +SettingsPorts::save() +{ + for (int i = 0; i < PARALLEL_MAX; i++) { + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); + if (cbox != NULL) + lpt_ports[i].device = cbox->currentData().toInt(); + if (checkBox != NULL) + lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + } + + for (int i = 0; i < SERIAL_MAX; i++) { + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + if (checkBox != NULL) + com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + if (checkBoxPass != NULL) + serial_passthrough_enabled[i] = checkBoxPass->isChecked(); + } +} + +void +SettingsPorts::onCurrentMachineChanged(int machineId) +{ + this->machineId = machineId; for (int i = 0; i < PARALLEL_MAX; i++) { auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); @@ -79,33 +113,6 @@ SettingsPorts::SettingsPorts(QWidget *parent) } } -SettingsPorts::~SettingsPorts() -{ - delete ui; -} - -void -SettingsPorts::save() -{ - for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); - auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); - if (cbox != NULL) - lpt_ports[i].device = cbox->currentData().toInt(); - if (checkBox != NULL) - lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; - } - - for (int i = 0; i < SERIAL_MAX; i++) { - auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); - auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); - if (checkBox != NULL) - com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; - if (checkBoxPass != NULL) - serial_passthrough_enabled[i] = checkBoxPass->isChecked(); - } -} - void SettingsPorts::on_checkBoxParallel1_stateChanged(int state) { @@ -130,50 +137,6 @@ SettingsPorts::on_checkBoxParallel4_stateChanged(int state) ui->comboBoxLpt4->setEnabled(state == Qt::Checked); } -void -SettingsPorts::on_pushButtonSerialPassThru1_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru2_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru3_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru4_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); -} - -#if 0 -void -SettingsPorts::on_pushButtonSerialPassThru5_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru6_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); -} - -void -SettingsPorts::on_pushButtonSerialPassThru7_clicked() -{ - DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); -} -#endif - void SettingsPorts::on_checkBoxSerial1_stateChanged(int state) { @@ -268,3 +231,47 @@ SettingsPorts::on_checkBoxSerialPassThru7_stateChanged(int state) ui->pushButtonSerialPassThru7->setEnabled(state == Qt::Checked); } #endif + +void +SettingsPorts::on_pushButtonSerialPassThru1_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru2_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru3_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru4_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); +} + +#if 0 +void +SettingsPorts::on_pushButtonSerialPassThru5_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru6_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru7_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); +} +#endif diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index 7d332509c..83560914f 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -16,44 +16,47 @@ public: void save(); +public slots: + void onCurrentMachineChanged(int machineId); + private slots: -#if 0 - void on_checkBoxSerialPassThru7_stateChanged(int state); - void on_checkBoxSerialPassThru6_stateChanged(int state); - void on_checkBoxSerialPassThru5_stateChanged(int state); -#endif - void on_checkBoxSerialPassThru4_stateChanged(int state); - void on_checkBoxSerialPassThru3_stateChanged(int state); - void on_checkBoxSerialPassThru2_stateChanged(int state); - void on_checkBoxSerialPassThru1_stateChanged(int state); - -#if 0 - void on_checkBoxSerial7_stateChanged(int state); - void on_checkBoxSerial6_stateChanged(int state); - void on_checkBoxSerial5_stateChanged(int state); -#endif - void on_checkBoxSerial4_stateChanged(int state); - void on_checkBoxSerial3_stateChanged(int state); - void on_checkBoxSerial2_stateChanged(int state); - void on_checkBoxSerial1_stateChanged(int state); - -#if 0 - void on_pushButtonSerialPassThru7_clicked(); - void on_pushButtonSerialPassThru6_clicked(); - void on_pushButtonSerialPassThru5_clicked(); -#endif - void on_pushButtonSerialPassThru4_clicked(); - void on_pushButtonSerialPassThru3_clicked(); - void on_pushButtonSerialPassThru2_clicked(); - void on_pushButtonSerialPassThru1_clicked(); - - void on_checkBoxParallel4_stateChanged(int state); - void on_checkBoxParallel3_stateChanged(int state); - void on_checkBoxParallel2_stateChanged(int state); void on_checkBoxParallel1_stateChanged(int state); + void on_checkBoxParallel2_stateChanged(int state); + void on_checkBoxParallel3_stateChanged(int state); + void on_checkBoxParallel4_stateChanged(int state); + + void on_checkBoxSerial1_stateChanged(int state); + void on_checkBoxSerial2_stateChanged(int state); + void on_checkBoxSerial3_stateChanged(int state); + void on_checkBoxSerial4_stateChanged(int state); +#if 0 + void on_checkBoxSerial5_stateChanged(int state); + void on_checkBoxSerial6_stateChanged(int state); + void on_checkBoxSerial7_stateChanged(int state); +#endif + void on_checkBoxSerialPassThru1_stateChanged(int state); + void on_checkBoxSerialPassThru2_stateChanged(int state); + void on_checkBoxSerialPassThru3_stateChanged(int state); + void on_checkBoxSerialPassThru4_stateChanged(int state); +#if 0 + void on_checkBoxSerialPassThru5_stateChanged(int state); + void on_checkBoxSerialPassThru6_stateChanged(int state); + void on_checkBoxSerialPassThru7_stateChanged(int state); +#endif + + void on_pushButtonSerialPassThru1_clicked(); + void on_pushButtonSerialPassThru2_clicked(); + void on_pushButtonSerialPassThru3_clicked(); + void on_pushButtonSerialPassThru4_clicked(); +#if 0 + void on_pushButtonSerialPassThru5_clicked(); + void on_pushButtonSerialPassThru6_clicked(); + void on_pushButtonSerialPassThru7_clicked(); +#endif private: Ui::SettingsPorts *ui; + int machineId = 0; }; #endif // QT_SETTINGSPORTS_HPP From 676087bcaecd2986f48fdc919b430481023c06b9 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 00:11:45 +0500 Subject: [PATCH 35/36] Refactor into a function --- src/qt/qt_mainwindow.cpp | 22 +++------------------- src/qt/qt_util.cpp | 22 ++++++++++++++++++++++ src/qt/qt_util.hpp | 3 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 036f56375..1cc6c33c9 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -122,19 +122,6 @@ extern int qt_nvr_save(void); #include "x11_util.h" #endif -#ifdef Q_OS_WINDOWS -#include -#ifndef DWMWA_WINDOW_CORNER_PREFERENCE -#define DWMWA_WINDOW_CORNER_PREFERENCE 33 -#endif -#ifndef DWMWCP_DEFAULT -#define DWMWCP_DEFAULT 0 -#endif -#ifndef DWMWCP_DONOTROUND -#define DWMWCP_DONOTROUND 1 -#endif -#endif - #ifdef Q_OS_MACOS # include "cocoa_keyboard.hpp" // The namespace is required to avoid clashing typedefs; we only use this @@ -195,8 +182,7 @@ MainWindow::MainWindow(QWidget *parent) ui->stackedWidget->setMouseTracking(true); statusBar()->setVisible(!hide_status_bar); #ifdef Q_OS_WINDOWS - auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); - DwmSetWindowAttribute((HWND) this->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(this->winId(), (hide_status_bar ? false : true)); #endif statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); this->centralWidget()->setStyleSheet("background-color: black;"); @@ -817,8 +803,7 @@ MainWindow::initRendererMonitorSlot(int monitor_index) secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); secondaryRenderer->setWindowIcon(this->windowIcon()); #ifdef Q_OS_WINDOWS - auto cornerPreference = DWMWCP_DONOTROUND; - DwmSetWindowAttribute((HWND) secondaryRenderer->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(secondaryRenderer->winId(), false); #endif if (show_second_monitors) { secondaryRenderer->show(); @@ -1855,8 +1840,7 @@ MainWindow::on_actionHide_status_bar_triggered() ui->actionHide_status_bar->setChecked(hide_status_bar); statusBar()->setVisible(!hide_status_bar); #ifdef Q_OS_WINDOWS - auto cornerPreference = (hide_status_bar ? DWMWCP_DONOTROUND : DWMWCP_DEFAULT); - DwmSetWindowAttribute((HWND) main_window->winId(), DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); + util::setWin11RoundedCorners(main_window->winId(), (hide_status_bar ? false : true)); #endif if (vid_resize >= 2) { setFixedSize(fixed_size_x, fixed_size_y + menuBar()->height() + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 5c9059272..0c78c2f5e 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -26,6 +26,19 @@ #include #include "qt_util.hpp" +#ifdef Q_OS_WINDOWS +# include +# ifndef DWMWA_WINDOW_CORNER_PREFERENCE +# define DWMWA_WINDOW_CORNER_PREFERENCE 33 +# endif +# ifndef DWMWCP_DEFAULT +# define DWMWCP_DEFAULT 0 +# endif +# ifndef DWMWCP_DONOTROUND +# define DWMWCP_DONOTROUND 1 +# endif +#endif + extern "C" { #include <86box/86box.h> #include <86box/config.h> @@ -48,6 +61,15 @@ screenOfWidget(QWidget *widget) #endif } +#ifdef Q_OS_WINDOWS +void +setWin11RoundedCorners(WId hwnd, bool enable) +{ + auto cornerPreference = (enable ? DWMWCP_DEFAULT : DWMWCP_DONOTROUND); + DwmSetWindowAttribute((HWND) hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, (LPCVOID) &cornerPreference, sizeof(cornerPreference)); +} +#endif + QString DlgFilter(std::initializer_list extensions, bool last) { diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 6a0bdc30b..9432610b6 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -13,6 +13,9 @@ static constexpr auto UUID_MIN_LENGTH = 36; QString DlgFilter(std::initializer_list extensions, bool last = false); /* Returns screen the widget is on */ QScreen *screenOfWidget(QWidget *widget); +#ifdef Q_OS_WINDOWS +void setWin11RoundedCorners(WId hwnd, bool enable); +#endif QString currentUuid(); void storeCurrentUuid(); bool compareUuid(); From 05a005b6f0a681b965ab60ae7638c2c2408fd8e7 Mon Sep 17 00:00:00 2001 From: Alexander Babikov Date: Fri, 7 Mar 2025 05:21:16 +0500 Subject: [PATCH 36/36] Initialize the sound icon menu pointer Fixes a crash when clicking the icon --- src/qt/qt_machinestatus.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index 3c3f4019f..a00cc032b 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -259,6 +259,7 @@ MachineStatus::MachineStatus(QObject *parent) { d = std::make_unique(this); muteUnmuteAction = nullptr; + soundMenu = nullptr; connect(refreshTimer, &QTimer::timeout, this, &MachineStatus::refreshIcons); refreshTimer->start(75); }