From 5225b37448d306ed9f0256e877512e32980e59ba Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sat, 6 Sep 2025 16:34:10 -0500 Subject: [PATCH 01/25] Initial implementation of the Yamaha YMF-701 audio controller --- src/include/86box/snd_ad1848.h | 4 + src/include/86box/sound.h | 3 + src/sound/CMakeLists.txt | 1 + src/sound/snd_ad1848.c | 37 +++ src/sound/snd_ymf701.c | 526 +++++++++++++++++++++++++++++++++ src/sound/sound.c | 1 + 6 files changed, 572 insertions(+) create mode 100644 src/sound/snd_ymf701.c diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index a7e38a6f8..3105d75f9 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -69,6 +69,9 @@ typedef struct ad1848_t { pc_timer_t timer_count; uint64_t timer_latch; + pc_timer_t cs4231a_irq_timer; + uint8_t is_opl3sa; + int16_t buffer[SOUNDBUFLEN * 2]; int pos; @@ -88,6 +91,7 @@ extern void ad1848_update(ad1848_t *ad1848); extern void ad1848_speed_changed(ad1848_t *ad1848); extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv); extern void ad1848_filter_aux2(void* priv, double* out_l, double* out_r); +extern void ad1848_is_opl3sa(ad1848_t *ad1848); extern void ad1848_init(ad1848_t *ad1848, uint8_t type); diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 5f91ec9d0..9b7b19d4d 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -236,6 +236,9 @@ extern const device_t tndy_device; extern const device_t wss_device; extern const device_t ncr_business_audio_device; +/* Yamaha YMF-7xx */ +extern const device_t ymf701_device; + #ifdef USE_LIBSERIALPORT /* External Audio device OPL2Board (Host Connected hardware)*/ extern const device_t opl2board_device; diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 9e2a75198..fdc60b971 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -51,6 +51,7 @@ add_library(snd OBJECT snd_ym7128.c snd_optimc.c snd_opl_esfm.c + snd_ymf701.c ) # TODO: Should platform-specific audio driver be here? diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index e9a4390c0..bad9f4d22 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -76,6 +76,12 @@ ad1848_setdma(ad1848_t *ad1848, int newdma) ad1848->dma = newdma; } +void +ad1848_is_opl3sa(ad1848_t *ad1848) +{ + ad1848->is_opl3sa = 1; +} + void ad1848_updatevolmask(ad1848_t *ad1848) { @@ -285,6 +291,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) ad1848_t *ad1848 = (ad1848_t *) priv; uint8_t temp = 0; uint8_t updatefreq = 0; + double i8_timebase = 0; switch (addr & 3) { case 0: /* Index */ @@ -344,6 +351,21 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv) ad1848->count = ad1848->regs[15] | (val << 8); break; + case 16: + if ((ad1848->type >= AD1848_TYPE_CS4231) && (ad1848->type < AD1848_TYPE_CS4235)) { + if (val & 0x40) { + ad1848_log("Timer Enable\n"); + ad1848_log("Timer value: %04X\n", ((ad1848->regs[21] << 8) + (ad1848->regs[20]))); + i8_timebase = (ad1848->regs[8] & 1) ? 9.92 : 9.969; + timer_set_delay_u64(&ad1848->cs4231a_irq_timer, (((ad1848->regs[21] << 8) + (ad1848->regs[20])) * i8_timebase * TIMER_USEC)); + } + else { + ad1848_log("Timer Disable\n"); + timer_disable(&ad1848->cs4231a_irq_timer); + } + } + break; + case 18 ... 19: if (ad1848->type >= AD1848_TYPE_CS4236B) { if (ad1848->type >= AD1848_TYPE_CS4235) { @@ -502,6 +524,8 @@ readonly_x: ad1848_updatefreq(ad1848); temp = (ad1848->type < AD1848_TYPE_CS4231) ? 2 : ((ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4); + if (ad1848->is_opl3sa) + temp = 2; /* OPL3-SA CODEC is CS4231-based but uses Aux1 for CD audio */ if (ad1848->regs[temp] & 0x80) ad1848->cd_vol_l = 0; else @@ -746,6 +770,16 @@ ad1848_poll(void *priv) } } +void +cs4231a_irq_poll(void *priv) +{ + ad1848_t *ad1848 = (ad1848_t *) priv; + ad1848_log("Firing timer IRQ\n"); + picint(1 << ad1848->irq); + ad1848_log("Setting timer interrupt bit in I24\n"); + ad1848->regs[24] |= 0x40; +} + void ad1848_filter_cd_audio(int channel, double *buffer, void *priv) { @@ -892,4 +926,7 @@ ad1848_init(ad1848_t *ad1848, uint8_t type) if ((ad1848->type != AD1848_TYPE_DEFAULT) && (ad1848->type != AD1848_TYPE_CS4248)) sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848); + + if ((ad1848->type >= AD1848_TYPE_CS4231) && (ad1848->type < AD1848_TYPE_CS4235)) + timer_add(&ad1848->cs4231a_irq_timer, cs4231a_irq_poll, ad1848, 0); } diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c new file mode 100644 index 000000000..430bfec4c --- /dev/null +++ b/src/sound/snd_ymf701.c @@ -0,0 +1,526 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Yamaha YMF-701 (OPL3-SA) audio controller emulation. + * + * + * + * Authors: Cacodemon345 + * Eluan Costa Miranda + * win2kgamer + * + * Copyright 2022 Cacodemon345. + * Copyright 2020 Eluan Costa Miranda. + * Copyright 2025 win2kgamer + */ + +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/midi.h> +#include <86box/timer.h> +#include <86box/pic.h> +#include <86box/sound.h> +#include <86box/gameport.h> +#include <86box/snd_ad1848.h> +#include <86box/snd_sb.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/plat_unused.h> +#include <86box/log.h> + +#ifdef ENABLE_YMF701_LOG +int ymf701_do_log = ENABLE_YMF701_LOG; + +static void +ymf701_log(void *priv, const char *fmt, ...) +{ + if (ymf701_do_log) { + va_list ap; + va_start(ap, fmt); + log_out(priv, fmt, ap); + va_end(ap); + } +} +#else +# define ymf701_log(fmt, ...) +#endif + +static int ymf701_wss_dma[4] = { 0, 0, 1, 3 }; +static int ymf701_wss_irq[8] = { 0, 7, 9, 10, 11, 0, 0, 0 }; + +typedef struct ymf701_t { + uint8_t type; + uint8_t fm_type; + + uint8_t wss_config; + uint8_t reg_enabled; + + uint16_t cur_addr; + uint16_t cur_wss_addr; + uint16_t cur_mpu401_addr; + + int cur_irq; + int cur_dma; + int cur_wss_enabled; + int cur_wss_irq; + int cur_wss_dma; + int cur_mpu401_irq; + int cur_mpu401_enabled; + void *gameport; + + uint8_t cur_mode; + + ad1848_t ad1848; + mpu_t *mpu; + + sb_t *sb; + uint8_t index; + uint8_t regs[6]; + uint8_t passwd_phase; + + uint8_t oldreadback; + + void * log; /* New logging system */ +} ymf701_t; + +static void +ymf701_filter_opl(void *priv, double *out_l, double *out_r) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + + if (ymf701->cur_wss_enabled) { + ad1848_filter_aux2((void *) &ymf701->ad1848, out_l, out_r); + } +} + +static uint8_t +ymf701_wss_read(uint16_t addr, void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + uint8_t ret = 0x00; + uint8_t port = addr - ymf701->cur_wss_addr; + + ymf701_log(ymf701->log, "WSS Read port = %04X\n", port); + + switch (port) { + case 0: + ret = ymf701->wss_config; + break; + case 3: + ret = 0x04 | (ymf701->wss_config & 0x40); + break; + default: + ret = ymf701->wss_config; + break; + } + ymf701_log(ymf701->log, "WSS Read: addr = %02X, val = %02X\n", addr, ret); + return ret; +} + +static void +ymf701_wss_write(uint16_t addr, uint8_t val, void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + uint8_t port = addr - ymf701->cur_wss_addr; + + ymf701_log(ymf701->log, "WSS Write: addr = %02X, val = %02X\n", addr, val); + switch (port) { + case 0: + ymf701->wss_config = val; + ymf701->cur_wss_dma = ymf701_wss_dma[val & 3]; + ymf701->cur_wss_irq = ymf701_wss_irq[(val >> 3) & 7]; + ad1848_setdma(&ymf701->ad1848, ymf701_wss_dma[val & 3]); + ad1848_setirq(&ymf701->ad1848, ymf701_wss_irq[(val >> 3) & 7]); + ymf701_log(ymf701->log, "Set IRQ to %02X\n", ymf701->cur_wss_irq); + ymf701_log(ymf701->log, "Set DMA to %02X\n", ymf701->cur_wss_dma); + break; + default: + break; + } +} + +static void +ymf701_get_buffer(int32_t *buffer, int len, void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + + /* wss part */ + ad1848_update(&ymf701->ad1848); + for (int c = 0; c < len * 2; c++) + buffer[c] += (ymf701->ad1848.buffer[c] / 2); + + ymf701->ad1848.pos = 0; + + /* sbprov2 part */ + sb_get_buffer_sbpro(buffer, len, ymf701->sb); +} + +static void +ymf701_remove_opl(ymf701_t *ymf701) +{ + io_removehandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_removehandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_removehandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); +} + +static void +ymf701_add_opl(ymf701_t *ymf701) +{ + /* DSP I/O handler is activated in sb_dsp_setaddr */ + io_sethandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); +} + +static void +ymf701_reg_write(uint16_t addr, uint8_t val, void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + uint16_t idx; + uint8_t old = ymf701->regs[idx]; + static uint8_t reg_enable_phase = 0; + + if (ymf701->reg_enabled) { + ymf701_log(ymf701->log, "Write with reg access enabled:\n"); + ymf701_log(ymf701->log, "addr = %02X, val = %02X\n", addr, val); + switch (addr) { + case 0xF86: + ymf701->index = val; + ymf701->passwd_phase = 0x01; + ymf701_log(ymf701->log, "Passwd phase 1\n"); + break; + case 0xF87: + switch (ymf701->index) { + case 0x01: /* WSS Config */ + ymf701->regs[0x01] = val; + ymf701->cur_mode = ymf701->cur_wss_enabled = !!(val & 0x20); + + sound_set_cd_audio_filter(NULL, NULL); + if (ymf701->cur_wss_enabled) /* WSS */ + sound_set_cd_audio_filter(ad1848_filter_cd_audio, &ymf701->ad1848); + else /* SBPro */ + sound_set_cd_audio_filter(sbpro_filter_cd_audio, ymf701->sb); + + io_removehandler(ymf701->cur_wss_addr, 0x0004, ymf701_wss_read, NULL, NULL, ymf701_wss_write, NULL, NULL, ymf701); + io_removehandler(ymf701->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &ymf701->ad1848); + switch ((val >> 3) & 0x3) { + case 0: /* WSBase = 0x530 */ + ymf701_log(ymf701->log, "WSS base is now 530h\n"); + ymf701->cur_wss_addr = 0x530; + break; + case 1: /* WSBase = 0xE80 */ + ymf701_log(ymf701->log, "WSS base is now E80h\n"); + ymf701->cur_wss_addr = 0xE80; + break; + case 2: /* WSBase = 0xF40 */ + ymf701_log(ymf701->log, "WSS base is now F40h\n"); + ymf701->cur_wss_addr = 0xF40; + break; + case 3: /* WSBase = 0x604 */ + ymf701_log(ymf701->log, "WSS base is now 604h\n"); + ymf701->cur_wss_addr = 0x604; + break; + default: + break; + } + io_sethandler(ymf701->cur_wss_addr, 0x0004, ymf701_wss_read, NULL, NULL, ymf701_wss_write, NULL, NULL, ymf701); + io_sethandler(ymf701->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &ymf701->ad1848); + break; + case 0x02: /* SB Config */ + ymf701->regs[0x02] = val; + io_removehandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + ymf701_remove_opl(ymf701); + ymf701->cur_addr = (val & 0x20) ? 0x240 : 0x220; + switch (val & 0x3) { + case 0: + ymf701->cur_dma = -1; + break; + case 1: + ymf701->cur_dma = 0; + break; + case 2: + ymf701->cur_dma = 1; + break; + case 3: + ymf701->cur_dma = 3; + break; + } + switch ((val >> 2) & 0x7) { + case 0: + ymf701->cur_irq = -1; + break; + case 1: + ymf701->cur_irq = 5; + break; + case 2: + ymf701->cur_irq = 7; + break; + case 3: + ymf701->cur_irq = 9; + break; + case 4: + ymf701->cur_irq = 10; + break; + case 5: + ymf701->cur_irq = 11; + break; + default: + break; + } + sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_addr); + sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_irq); + sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_dma); + ymf701_add_opl(ymf701); + io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + break; + case 0x03: /* MPU/OPL/Gameport Config */ + ymf701->regs[0x03] = val; + switch ((val >> 2) & 0x7) { + case 0: + ymf701->cur_mpu401_irq = -1; + break; + case 1: + ymf701->cur_mpu401_irq = 5; + break; + case 2: + ymf701->cur_mpu401_irq = 7; + break; + case 3: + ymf701->cur_mpu401_irq = 9; + break; + case 4: + ymf701->cur_mpu401_irq = 10; + break; + default: + break; + } + switch ((val >> 5) & 0x3) { + case 0: + ymf701->cur_mpu401_addr = 0x330; + break; + case 1: + ymf701->cur_mpu401_addr = 0x332; + break; + case 2: + ymf701->cur_mpu401_addr = 0x334; + break; + case 3: + ymf701->cur_mpu401_addr = 0x300; + break; + default: + break; + } + mpu401_change_addr(ymf701->mpu, ymf701->cur_mpu401_addr); + mpu401_setirq(ymf701->mpu, ymf701->cur_mpu401_irq); + gameport_remap(ymf701->gameport, (ymf701->regs[3] & 0x1) ? 0x200 : 0x00); + break; + case 0x04: /* LSI Version Register, on a real Intel Ruby board this is always 0 */ + break; + default: + break; + } + ymf701->passwd_phase = 0x02; + ymf701_log(ymf701->log, "Passwd phase 2\n"); + default: + break; + } + } + ymf701_log(ymf701->log, "Write: addr = %02X, val = %02X\n", addr, val); + if ((ymf701->reg_enabled) && (ymf701->passwd_phase == 0x02)) { + ymf701->reg_enabled = 0; + ymf701->passwd_phase = 0x00; + ymf701_log(ymf701->log, "Disabling reg access\n"); + } + if ((addr == 0xF86) && (val == 0x1D) && (!ymf701->reg_enabled)) { + ymf701->reg_enabled = 1; + ymf701_log(ymf701->log, "Enabling reg access\n"); + } +} + +static uint8_t +ymf701_reg_read(uint16_t addr, void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + uint8_t temp = 0xFF; + + if (ymf701->reg_enabled) { + switch (addr) { + case 0xF86: + temp = ymf701->index; + break; + case 0xF87: + temp = ymf701->regs[ymf701->index]; + /* Only goes into phase 2 on data reads? */ + ymf701->passwd_phase = 0x02; + ymf701_log(ymf701->log, "Passwd phase 2\n"); + break; + default: + break; + } + ymf701_log(ymf701->log, "Read with reg access enabled:\n"); + ymf701_log(ymf701->log, "addr = %02X, ret = %02X\n", addr, temp); + } + if ((ymf701->reg_enabled) && (ymf701->passwd_phase == 0x02)) { + ymf701->reg_enabled = 0; + ymf701->passwd_phase = 0x00; + ymf701_log(ymf701->log, "Disabling reg access\n"); + } + ymf701_log(ymf701->log, "Read: addr = %02X, ret = %02X\n", addr, temp); + return temp; +} + +static void * +ymf701_init(const device_t *info) +{ + ymf701_t *ymf701 = calloc(1, sizeof(ymf701_t)); + + ymf701->type = info->local & 0xFF; + + ymf701->cur_wss_addr = 0x530; + ymf701->cur_mode = 0; + ymf701->cur_addr = 0x220; + ymf701->cur_irq = 5; + ymf701->cur_wss_enabled = 0; + ymf701->cur_dma = 1; + ymf701->cur_mpu401_irq = 9; + ymf701->cur_mpu401_addr = 0x330; + ymf701->cur_mpu401_enabled = 1; + ymf701->cur_wss_dma = 0; + ymf701->cur_wss_irq = 11; + + ymf701->regs[0] = 0xFF; + ymf701->regs[1] = 0x24; + ymf701->regs[2] = 0x46; + ymf701->regs[3] = 0x87; + ymf701->regs[4] = 0x00; + + ymf701->log = log_open("YMF701"); + + ymf701->gameport = gameport_add(&gameport_pnp_device); + gameport_remap(ymf701->gameport, (ymf701->regs[3] & 0x1) ? 0x200 : 0x00); + + ad1848_init(&ymf701->ad1848, AD1848_TYPE_CS4231); + + ad1848_setirq(&ymf701->ad1848, ymf701->cur_wss_irq); + ad1848_setdma(&ymf701->ad1848, ymf701->cur_wss_dma); + + io_sethandler(0xF86, 2, ymf701_reg_read, NULL, NULL, ymf701_reg_write, NULL, NULL, ymf701); + + io_sethandler(ymf701->cur_wss_addr, 0x0004, ymf701_wss_read, NULL, NULL, ymf701_wss_write, NULL, NULL, ymf701); + io_sethandler(ymf701->cur_wss_addr + 0x0004, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &ymf701->ad1848); + + ymf701->sb = calloc(1, sizeof(sb_t)); + ymf701->sb->opl_enabled = 1; + + sb_dsp_set_real_opl(&ymf701->sb->dsp, 1); + sb_dsp_init(&ymf701->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf701); + sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_addr); + sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_irq); + sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_dma); + sb_ct1345_mixer_reset(ymf701->sb); + + ymf701->sb->opl_mixer = ymf701; + ymf701->sb->opl_mix = ymf701_filter_opl; + + fm_driver_get(FM_YMF262, &ymf701->sb->opl); + io_sethandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + + io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + + sound_add_handler(ymf701_get_buffer, ymf701); + music_add_handler(sb_get_music_buffer_sbpro, ymf701->sb); + ad1848_is_opl3sa(&ymf701->ad1848); + //sound_set_cd_audio_filter(sbpro_filter_cd_audio, ymf701->sb); /* CD audio filter for the default context */ + sound_set_cd_audio_filter(ad1848_filter_cd_audio, &ymf701->ad1848); + + ymf701->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); + mpu401_init(ymf701->mpu, ymf701->cur_mpu401_addr, ymf701->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401")); + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ymf701->sb->dsp); + + return ymf701; +} + +static void +ymf701_close(void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + + if (ymf701->log != NULL) { + log_close(ymf701->log); + ymf701->log = NULL; + } + + sb_close(ymf701->sb); + free(ymf701->mpu); + free(priv); +} + +static void +ymf701_speed_changed(void *priv) +{ + ymf701_t *ymf701 = (ymf701_t *) priv; + + ad1848_speed_changed(&ymf701->ad1848); + sb_speed_changed(ymf701->sb); +} + +static const device_config_t ymf701_config[] = { + // clang-format off + { + .name = "receive_input", + .description = "Receive MIDI input", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 1, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { + .name = "receive_input401", + .description = "Receive MIDI input (MPU-401)", + .type = CONFIG_BINARY, + .default_string = NULL, + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { { 0 } }, + .bios = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t ymf701_device = { + .name = "Yamaha YMF-701 (OPL3-SA)", + .internal_name = "ymf701", + .flags = DEVICE_ISA16, + .local = 0x00, + .init = ymf701_init, + .close = ymf701_close, + .reset = NULL, + .available = NULL, + .speed_changed = ymf701_speed_changed, + .force_redraw = NULL, + .config = ymf701_config +}; diff --git a/src/sound/sound.c b/src/sound/sound.c index c81dc47b0..f8239b298 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -158,6 +158,7 @@ static const SOUND_CARD sound_cards[] = { { &sb_vibra16s_device }, { &sb_vibra16xv_device }, { &wss_device }, + { &ymf701_device }, /* MCA */ { &adlib_mca_device }, { &ess_chipchat_16_mca_device }, From 433c45b3e6b0a02d0453497aaba65b569de78497 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sat, 6 Sep 2025 18:24:29 -0500 Subject: [PATCH 02/25] Give the Intel TC430HX and Sony Vaio PCV-90 their onboard YMF701 audio --- src/machine/m_at_socket7.c | 9 +++++++++ src/machine/machine_table.c | 8 ++++---- src/sound/snd_ymf701.c | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index b0651a8af..994f2151e 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -316,6 +316,9 @@ machine_at_tc430hx_gpio_init(void) else if (cpu_busspeed > 60000000) gpio |= 0xffff00ff; + if (sound_card_current[0] == SOUND_INTERNAL) + gpio |= 0xffff04ff; + machine_set_gpio_default(gpio); } @@ -350,6 +353,9 @@ machine_at_tc430hx_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(machine_get_vid_device(machine)); + if (sound_card_current[0] == SOUND_INTERNAL) + machine_snd = device_add(machine_get_snd_device(machine)); + device_add(&i430hx_device); device_add(&piix3_device); device_add_params(&pc87306_device, (void *) PCX730X_AMI); @@ -452,6 +458,9 @@ machine_at_pcv90_init(const machine_t *model) device_add_params(&pc87306_device, (void *) PCX730X_AMI); device_add(&intel_flash_bxt_ami_device); + if (sound_card_current[0] == SOUND_INTERNAL) + machine_snd = device_add(machine_get_snd_device(machine)); + return ret; } diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 7891bb3db..6a5ec2028 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -13854,7 +13854,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ + .flags = MACHINE_VIDEO | MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_SOUND | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal sound: Yamaha YMF701-S */ .ram = { .min = 8192, .max = 524288, @@ -13873,7 +13873,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &s3_virge_375_pci_device, - .snd_device = NULL, + .snd_device = &ymf701_device, .net_device = NULL }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix @@ -13991,7 +13991,7 @@ const machine_t machines[] = { .max_multi = 3.0 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, /* Machine has internal video: ATI Mach64GT-B 3D Rage II */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_SOUND | MACHINE_GAMEPORT, /* Machine has internal video: ATI Mach64GT-B 3D Rage II */ .ram = { .min = 8192, .max = 524288, @@ -14010,7 +14010,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &ymf701_device, .net_device = NULL }, /* [TEST] The board doesn't seem to have a KBC at all, which probably means it's an on-chip one on the PC87306 SIO. diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 430bfec4c..1e45c786a 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -286,7 +286,8 @@ ymf701_reg_write(uint16_t addr, uint8_t val, void *priv) sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_irq); sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_dma); ymf701_add_opl(ymf701); - io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + if (ymf701->cur_addr != 0x00) + io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); break; case 0x03: /* MPU/OPL/Gameport Config */ ymf701->regs[0x03] = val; From fef13a41dd1d45bf4b63728a7906146192b399c1 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sat, 13 Sep 2025 22:16:05 -0500 Subject: [PATCH 03/25] Remove now-unnecessary is_opl3sa AD1848 mixer hack --- src/include/86box/snd_ad1848.h | 2 -- src/sound/snd_ad1848.c | 8 -------- src/sound/snd_ymf701.c | 1 - 3 files changed, 11 deletions(-) diff --git a/src/include/86box/snd_ad1848.h b/src/include/86box/snd_ad1848.h index 3105d75f9..6e8282485 100644 --- a/src/include/86box/snd_ad1848.h +++ b/src/include/86box/snd_ad1848.h @@ -70,7 +70,6 @@ typedef struct ad1848_t { uint64_t timer_latch; pc_timer_t cs4231a_irq_timer; - uint8_t is_opl3sa; int16_t buffer[SOUNDBUFLEN * 2]; int pos; @@ -91,7 +90,6 @@ extern void ad1848_update(ad1848_t *ad1848); extern void ad1848_speed_changed(ad1848_t *ad1848); extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv); extern void ad1848_filter_aux2(void* priv, double* out_l, double* out_r); -extern void ad1848_is_opl3sa(ad1848_t *ad1848); extern void ad1848_init(ad1848_t *ad1848, uint8_t type); diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index bad9f4d22..cd988a9ef 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -76,12 +76,6 @@ ad1848_setdma(ad1848_t *ad1848, int newdma) ad1848->dma = newdma; } -void -ad1848_is_opl3sa(ad1848_t *ad1848) -{ - ad1848->is_opl3sa = 1; -} - void ad1848_updatevolmask(ad1848_t *ad1848) { @@ -524,8 +518,6 @@ readonly_x: ad1848_updatefreq(ad1848); temp = (ad1848->type < AD1848_TYPE_CS4231) ? 2 : ((ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4); - if (ad1848->is_opl3sa) - temp = 2; /* OPL3-SA CODEC is CS4231-based but uses Aux1 for CD audio */ if (ad1848->regs[temp] & 0x80) ad1848->cd_vol_l = 0; else diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 1e45c786a..b18c48953 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -447,7 +447,6 @@ ymf701_init(const device_t *info) sound_add_handler(ymf701_get_buffer, ymf701); music_add_handler(sb_get_music_buffer_sbpro, ymf701->sb); - ad1848_is_opl3sa(&ymf701->ad1848); //sound_set_cd_audio_filter(sbpro_filter_cd_audio, ymf701->sb); /* CD audio filter for the default context */ sound_set_cd_audio_filter(ad1848_filter_cd_audio, &ymf701->ad1848); From 9ee210f55d2e2244cf74b66a06f2f1997aed7553 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sat, 13 Sep 2025 22:34:25 -0500 Subject: [PATCH 04/25] Use new method of attaching OPL3 and CD audio to the AD1848 mixer --- src/sound/snd_ymf701.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index b18c48953..37f04157d 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -104,7 +104,7 @@ ymf701_filter_opl(void *priv, double *out_l, double *out_r) ymf701_t *ymf701 = (ymf701_t *) priv; if (ymf701->cur_wss_enabled) { - ad1848_filter_aux2((void *) &ymf701->ad1848, out_l, out_r); + ad1848_filter_channel((void *) &ymf701->ad1848, AD1848_AUX2, out_l, out_r); } } @@ -447,6 +447,7 @@ ymf701_init(const device_t *info) sound_add_handler(ymf701_get_buffer, ymf701); music_add_handler(sb_get_music_buffer_sbpro, ymf701->sb); + ad1848_set_cd_audio_channel(&ymf701->ad1848, AD1848_AUX1); //sound_set_cd_audio_filter(sbpro_filter_cd_audio, ymf701->sb); /* CD audio filter for the default context */ sound_set_cd_audio_filter(ad1848_filter_cd_audio, &ymf701->ad1848); From d4c9ee5613feabc88091eb7165d1bd22c6c8b51d Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sat, 13 Sep 2025 23:07:31 -0500 Subject: [PATCH 05/25] Code cleanup and comment updates --- src/sound/snd_ymf701.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 37f04157d..4506688c5 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -65,7 +65,6 @@ static int ymf701_wss_irq[8] = { 0, 7, 9, 10, 11, 0, 0, 0 }; typedef struct ymf701_t { uint8_t type; - uint8_t fm_type; uint8_t wss_config; uint8_t reg_enabled; @@ -93,8 +92,6 @@ typedef struct ymf701_t { uint8_t regs[6]; uint8_t passwd_phase; - uint8_t oldreadback; - void * log; /* New logging system */ } ymf701_t; @@ -115,8 +112,6 @@ ymf701_wss_read(uint16_t addr, void *priv) uint8_t ret = 0x00; uint8_t port = addr - ymf701->cur_wss_addr; - ymf701_log(ymf701->log, "WSS Read port = %04X\n", port); - switch (port) { case 0: ret = ymf701->wss_config; @@ -404,11 +399,12 @@ ymf701_init(const device_t *info) ymf701->cur_wss_dma = 0; ymf701->cur_wss_irq = 11; - ymf701->regs[0] = 0xFF; + /* Power-on default values are unknown, using BIOS-initialized values from an Intel Ruby board */ + ymf701->regs[0] = 0xFF; /* Index 0 is unused, return 0xFF */ ymf701->regs[1] = 0x24; ymf701->regs[2] = 0x46; ymf701->regs[3] = 0x87; - ymf701->regs[4] = 0x00; + ymf701->regs[4] = 0x00; /* LSI version register, always returns 0 */ ymf701->log = log_open("YMF701"); @@ -448,7 +444,6 @@ ymf701_init(const device_t *info) sound_add_handler(ymf701_get_buffer, ymf701); music_add_handler(sb_get_music_buffer_sbpro, ymf701->sb); ad1848_set_cd_audio_channel(&ymf701->ad1848, AD1848_AUX1); - //sound_set_cd_audio_filter(sbpro_filter_cd_audio, ymf701->sb); /* CD audio filter for the default context */ sound_set_cd_audio_filter(ad1848_filter_cd_audio, &ymf701->ad1848); ymf701->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); From ff32263927d435e634927335a6c340f1439a9d27 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 14 Sep 2025 12:14:45 -0500 Subject: [PATCH 06/25] Clarify SB variable names, correct WSS enable in init --- src/sound/snd_ymf701.c | 70 +++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 4506688c5..0ce57064f 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -69,12 +69,12 @@ typedef struct ymf701_t { uint8_t wss_config; uint8_t reg_enabled; - uint16_t cur_addr; + uint16_t cur_sb_addr; uint16_t cur_wss_addr; uint16_t cur_mpu401_addr; - int cur_irq; - int cur_dma; + int cur_sb_irq; + int cur_sb_dma; int cur_wss_enabled; int cur_wss_irq; int cur_wss_dma; @@ -168,8 +168,8 @@ ymf701_get_buffer(int32_t *buffer, int len, void *priv) static void ymf701_remove_opl(ymf701_t *ymf701) { - io_removehandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); - io_removehandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_removehandler(ymf701->cur_sb_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_removehandler(ymf701->cur_sb_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); io_removehandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); } @@ -177,8 +177,8 @@ static void ymf701_add_opl(ymf701_t *ymf701) { /* DSP I/O handler is activated in sb_dsp_setaddr */ - io_sethandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); - io_sethandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_sb_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_sb_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); io_sethandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); } @@ -238,51 +238,51 @@ ymf701_reg_write(uint16_t addr, uint8_t val, void *priv) break; case 0x02: /* SB Config */ ymf701->regs[0x02] = val; - io_removehandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + io_removehandler(ymf701->cur_sb_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); ymf701_remove_opl(ymf701); - ymf701->cur_addr = (val & 0x20) ? 0x240 : 0x220; + ymf701->cur_sb_addr = (val & 0x20) ? 0x240 : 0x220; switch (val & 0x3) { case 0: - ymf701->cur_dma = -1; + ymf701->cur_sb_dma = -1; break; case 1: - ymf701->cur_dma = 0; + ymf701->cur_sb_dma = 0; break; case 2: - ymf701->cur_dma = 1; + ymf701->cur_sb_dma = 1; break; case 3: - ymf701->cur_dma = 3; + ymf701->cur_sb_dma = 3; break; } switch ((val >> 2) & 0x7) { case 0: - ymf701->cur_irq = -1; + ymf701->cur_sb_irq = -1; break; case 1: - ymf701->cur_irq = 5; + ymf701->cur_sb_irq = 5; break; case 2: - ymf701->cur_irq = 7; + ymf701->cur_sb_irq = 7; break; case 3: - ymf701->cur_irq = 9; + ymf701->cur_sb_irq = 9; break; case 4: - ymf701->cur_irq = 10; + ymf701->cur_sb_irq = 10; break; case 5: - ymf701->cur_irq = 11; + ymf701->cur_sb_irq = 11; break; default: break; } - sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_addr); - sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_irq); - sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_dma); + sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_sb_addr); + sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_sb_irq); + sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_sb_dma); ymf701_add_opl(ymf701); - if (ymf701->cur_addr != 0x00) - io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + if (ymf701->cur_sb_addr != 0x00) + io_sethandler(ymf701->cur_sb_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); break; case 0x03: /* MPU/OPL/Gameport Config */ ymf701->regs[0x03] = val; @@ -388,11 +388,11 @@ ymf701_init(const device_t *info) ymf701->type = info->local & 0xFF; ymf701->cur_wss_addr = 0x530; - ymf701->cur_mode = 0; - ymf701->cur_addr = 0x220; - ymf701->cur_irq = 5; - ymf701->cur_wss_enabled = 0; - ymf701->cur_dma = 1; + ymf701->cur_mode = 1; + ymf701->cur_sb_addr = 0x220; + ymf701->cur_sb_irq = 5; + ymf701->cur_wss_enabled = 1; + ymf701->cur_sb_dma = 1; ymf701->cur_mpu401_irq = 9; ymf701->cur_mpu401_addr = 0x330; ymf701->cur_mpu401_enabled = 1; @@ -426,20 +426,20 @@ ymf701_init(const device_t *info) sb_dsp_set_real_opl(&ymf701->sb->dsp, 1); sb_dsp_init(&ymf701->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf701); - sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_addr); - sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_irq); - sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_dma); + sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_sb_addr); + sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_sb_irq); + sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_sb_dma); sb_ct1345_mixer_reset(ymf701->sb); ymf701->sb->opl_mixer = ymf701; ymf701->sb->opl_mix = ymf701_filter_opl; fm_driver_get(FM_YMF262, &ymf701->sb->opl); - io_sethandler(ymf701->cur_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); - io_sethandler(ymf701->cur_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_sb_addr + 0, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); + io_sethandler(ymf701->cur_sb_addr + 8, 0x0002, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); io_sethandler(0x0388, 0x0004, ymf701->sb->opl.read, NULL, NULL, ymf701->sb->opl.write, NULL, NULL, ymf701->sb->opl.priv); - io_sethandler(ymf701->cur_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); + io_sethandler(ymf701->cur_sb_addr + 4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, ymf701->sb); sound_add_handler(ymf701_get_buffer, ymf701); music_add_handler(sb_get_music_buffer_sbpro, ymf701->sb); From 82ad957380d2caa49f27adeb94d588c3d8e57613 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Sep 2025 19:16:55 +0200 Subject: [PATCH 07/25] PCjr: Fix 320x200x4 mode. --- src/video/vid_pcjr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/video/vid_pcjr.c b/src/video/vid_pcjr.c index fd8ef515b..62ce9b61d 100644 --- a/src/video/vid_pcjr.c +++ b/src/video/vid_pcjr.c @@ -467,8 +467,10 @@ vid_render(pcjr_t *pcjr, int line, int ho_s, int ho_d) dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1]; pcjr->memaddr++; - for (uint8_t c = 0; c < 8; c++) - buffer32->line[line][ef_x + (c << 1)] = buffer32->line[line][ef_x + (c << 1) + 1] = dat <<= 2; + for (uint8_t c = 0; c < 8; c++) { + buffer32->line[line][ef_x + (c << 1)] = buffer32->line[line][ef_x + (c << 1) + 1] = cols[dat >> 14]; + dat <<= 2; + } } break; case 0x102: /*640x200x2*/ From 39d66f00ef9e2ac201b556687566c9f160b57f73 Mon Sep 17 00:00:00 2001 From: win2kgamer <47463859+win2kgamer@users.noreply.github.com> Date: Sun, 14 Sep 2025 13:45:26 -0500 Subject: [PATCH 08/25] Remove two unused local variables causing a CodeQL failure --- src/sound/snd_ymf701.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 0ce57064f..001a5622b 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -186,8 +186,6 @@ static void ymf701_reg_write(uint16_t addr, uint8_t val, void *priv) { ymf701_t *ymf701 = (ymf701_t *) priv; - uint16_t idx; - uint8_t old = ymf701->regs[idx]; static uint8_t reg_enable_phase = 0; if (ymf701->reg_enabled) { From da398832c4bbd3058bb78a104dccdbd5038f4af4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Sep 2025 23:30:40 +0200 Subject: [PATCH 09/25] CUBX: Implement CMD-648 disabling via ACPI GPIO, fixes #6169. --- src/acpi.c | 6 +++++- src/disk/hdc.c | 4 ++++ src/disk/hdc_ide_cmd646.c | 24 ++++++++++++++---------- src/include/86box/hdc.h | 1 + 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 6ecca841b..411662e39 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -41,6 +41,7 @@ #include <86box/i2c.h> #include <86box/video.h> #include <86box/smbus.h> +#include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/hdc_ide_sff8038i.h> #include <86box/sis_55xx.h> @@ -1219,8 +1220,11 @@ acpi_reg_write_intel(int size, uint16_t addr, uint8_t val, void *priv) case 0x36: case 0x37: /* GPOREG - General Purpose Output Register (IO) */ - if (size == 1) + if (size == 1) { dev->regs.gporeg[addr & 3] = val; + if ((addr == 0x34) && !strcmp(machine_get_internal_name(), "cubx")) + hdc_onboard_enabled = (val & 0x01); + } break; default: acpi_reg_write_common_regs(size, addr, val, priv); diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 135528401..1e0d3f2bb 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -32,6 +32,8 @@ int hdc_current[HDC_MAX] = { 0, 0 }; +int hdc_onboard_enabled = 1; + #ifdef ENABLE_HDC_LOG int hdc_do_log = ENABLE_HDC_LOG; @@ -114,6 +116,8 @@ hdc_init(void) void hdc_reset(void) { + hdc_onboard_enabled = 1; + for (int i = 0; i < HDC_MAX; i++) { hdc_log("HDC %i: reset(current=%d, internal=%d)\n", i, hdc_current[i], hdc_current[i] == HDC_INTERNAL); diff --git a/src/disk/hdc_ide_cmd646.c b/src/disk/hdc_ide_cmd646.c index 7aa920e22..333cd5e30 100644 --- a/src/disk/hdc_ide_cmd646.c +++ b/src/disk/hdc_ide_cmd646.c @@ -145,6 +145,7 @@ cmd646_ide_handlers(cmd646_t *dev) int first = 0; int reg09 = dev->regs[0x09]; int reg50 = dev->regs[0x50]; + int dev_enabled = (hdc_onboard_enabled || !(dev->local & CMD64X_ONBOARD)); if ((dev->local & CMD_TYPE_648) && (dev->local & CMD648_RAID)) { reg09 = 0xff; @@ -180,7 +181,7 @@ cmd646_ide_handlers(cmd646_t *dev) if (dev->local & CMD_TYPE_648) pri_enabled = pri_enabled && (dev->regs[0x51] & 0x04); - if (pri_enabled) + if (dev_enabled && pri_enabled) ide_handlers(first, 1); if (dev->single_channel) @@ -205,7 +206,7 @@ cmd646_ide_handlers(cmd646_t *dev) sff_set_irq_mode(dev->bm[1], irq_mode[1]); cmd646_log("IDE %i: %04X, %04X, %i\n", first + 1, main, side, irq_mode[1]); - if ((dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) + if (dev_enabled && (dev->regs[0x04] & 0x01) && (dev->regs[0x51] & 0x08)) ide_handlers(first + 1, 1); } @@ -213,9 +214,10 @@ static void cmd646_ide_bm_handlers(cmd646_t *dev) { uint16_t base = (dev->regs[0x20] & 0xf0) | (dev->regs[0x21] << 8); + int dev_enabled = (hdc_onboard_enabled || !(dev->local & CMD64X_ONBOARD)); - sff_bus_master_handler(dev->bm[0], (dev->regs[0x04] & 1), base); - sff_bus_master_handler(dev->bm[1], (dev->regs[0x04] & 1), base + 8); + sff_bus_master_handler(dev->bm[0], dev_enabled && (dev->regs[0x04] & 1), base); + sff_bus_master_handler(dev->bm[1], dev_enabled && (dev->regs[0x04] & 1), base + 8); } uint8_t @@ -296,15 +298,16 @@ cmd646_bios_handler(cmd646_t *dev) static void cmd646_pci_write(int func, int addr, uint8_t val, void *priv) { - cmd646_t *dev = (cmd646_t *) priv; - int reg50 = dev->regs[0x50]; + cmd646_t *dev = (cmd646_t *) priv; + int reg50 = dev->regs[0x50]; + int dev_enabled = (hdc_onboard_enabled || !(dev->local & CMD64X_ONBOARD)); if ((dev->local & CMD_TYPE_648) && (dev->regs[0x0a] == 0x04) && (dev->regs[0x0b] == 0x01)) reg50 |= 0x40; cmd646_log("[%04X:%08X] (%08X) cmd646_pci_write(%i, %02X, %02X)\n", CS, cpu_state.pc, ESI, func, addr, val); - if (func == 0x00) + if (dev_enabled && (func == 0x00)) switch (addr) { case 0x04: if (dev->has_bios) @@ -480,10 +483,11 @@ cmd646_pci_write(int func, int addr, uint8_t val, void *priv) static uint8_t cmd646_pci_read(int func, int addr, void *priv) { - cmd646_t *dev = (cmd646_t *) priv; - uint8_t ret = 0xff; + cmd646_t *dev = (cmd646_t *) priv; + uint8_t ret = 0xff; + int dev_enabled = (hdc_onboard_enabled || !(dev->local & CMD64X_ONBOARD)); - if (func == 0x00) { + if (dev_enabled && (func == 0x00)) { ret = dev->regs[addr]; if ((addr == 0x09) && (dev->local & CMD_TYPE_648) && (dev->regs[0x0a] == 0x04)) diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 26fed9b0a..214ed84e5 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -30,6 +30,7 @@ #define HDC_MAX 4 extern int hdc_current[HDC_MAX]; +extern int hdc_onboard_enabled; extern const device_t st506_xt_xebec_device; /* st506_xt_xebec */ extern const device_t st506_xt_wdxt_gen_device; /* st506_xt_wdxt_gen */ From 9702e28e5c3f2fd8275c196c7ed38f4900d9e130 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 14 Sep 2025 23:47:43 +0200 Subject: [PATCH 10/25] YMF-701: Removed an unused variable. --- src/sound/snd_ymf701.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sound/snd_ymf701.c b/src/sound/snd_ymf701.c index 001a5622b..ff2f9f78a 100644 --- a/src/sound/snd_ymf701.c +++ b/src/sound/snd_ymf701.c @@ -185,8 +185,7 @@ ymf701_add_opl(ymf701_t *ymf701) static void ymf701_reg_write(uint16_t addr, uint8_t val, void *priv) { - ymf701_t *ymf701 = (ymf701_t *) priv; - static uint8_t reg_enable_phase = 0; + ymf701_t *ymf701 = (ymf701_t *) priv; if (ymf701->reg_enabled) { ymf701_log(ymf701->log, "Write with reg access enabled:\n"); From 6de981363e7409acf3a51a374bd6880f93816feb Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 2 Dec 2022 14:03:30 -0500 Subject: [PATCH 11/25] Use SQXTUN instead of UQXTN in PACKUSWB on arm64 --- src/codegen_new/codegen_backend_arm64_ops.c | 7 +++++++ src/codegen_new/codegen_backend_arm64_ops.h | 1 + src/codegen_new/codegen_backend_arm64_uops.c | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index 915cae93d..21f0df34d 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -180,6 +180,7 @@ # define OPCODE_SQSUB_V8B (0x0e202c00) # define OPCODE_SQSUB_V4H (0x0e602c00) # define OPCODE_SQXTN_V8B_8H (0x0e214800) +# define OPCODE_SQXTUN_V8B_8H (0x7e212800) # define OPCODE_SQXTN_V4H_4S (0x0e614800) # define OPCODE_SHL_VD (0x0f005400) # define OPCODE_SHL_VQ (0x4f005400) @@ -1225,6 +1226,12 @@ host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } + +void host_arm64_SQXTUN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_SQXTUN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); +} + void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg) { diff --git a/src/codegen_new/codegen_backend_arm64_ops.h b/src/codegen_new/codegen_backend_arm64_ops.h index df751b4aa..084bbb404 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.h +++ b/src/codegen_new/codegen_backend_arm64_ops.h @@ -184,6 +184,7 @@ void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); +void host_arm64_SQXTUN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 2bb6281ff..f6038f71f 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1480,8 +1480,8 @@ codegen_PACKUSWB(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_UQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_UQXTN_V8B_8H(block, dest_reg, dest_reg); + host_arm64_SQXTUN_V8B_8H(block, REG_V_TEMP, src_reg_b); + host_arm64_SQXTUN_V8B_8H(block, dest_reg, dest_reg); host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); From 1488097c7bd633678d16678fa1bbe403ee2c7fc1 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Fri, 2 Dec 2022 14:05:18 -0500 Subject: [PATCH 12/25] Reenable MMX opcodes on ARM new dynarec --- src/codegen_new/codegen_ops.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index bb7d1f3ee..039e0877a 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -86,13 +86,8 @@ RecompOpFn recomp_opcodes_0f[512] = { /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#else /*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, -#endif /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -100,15 +95,9 @@ RecompOpFn recomp_opcodes_0f[512] = { /*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#else /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, -#endif /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -119,13 +108,8 @@ RecompOpFn recomp_opcodes_0f[512] = { /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#else /*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, /*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, -#endif /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -133,15 +117,9 @@ RecompOpFn recomp_opcodes_0f[512] = { /*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16, /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 -/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -#else /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, -#endif // clang-format on }; From ffed72f8233ab952883cd71beab4899e6f901684 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Sep 2025 11:11:26 +0000 Subject: [PATCH 13/25] NDR (AArch64): Fix `ismmx` value assignment --- src/codegen_new/codegen_backend_arm64_ops.c | 7 ++++--- src/codegen_new/codegen_backend_arm64_uops.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index 21f0df34d..afe00fe4d 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -226,11 +226,11 @@ # define IMM_LOGICAL(imm) ((imm) << 10) -# define BIT_TBxZ(bit) ((((bit) &0x1f) << 19) | (((bit) &0x20) ? (1 << 31) : 0)) +# define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0)) # define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0) # define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0) -# define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) &0x1fffff) >> 2) << 5)) +# define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5)) # define OFFSET26(offset) ((offset >> 2) & 0x03ffffff) # define OFFSET12_B(offset) (offset << 10) @@ -1227,7 +1227,8 @@ host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SQXTN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQXTUN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) +void +host_arm64_SQXTUN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_SQXTUN_V8B_8H | Rd(dst_reg) | Rn(src_reg)); } diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index f6038f71f..4c00cbed2 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -801,7 +801,8 @@ codegen_MMX_ENTER(codeblock_t *block, uop_t *uop) host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[0] - (uintptr_t) &cpu_state); host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.tag[4] - (uintptr_t) &cpu_state); host_arm64_STR_IMM_W(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state); - host_arm64_STRB_IMM(block, REG_WZR, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); + host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 1); + host_arm64_STRB_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.ismmx - (uintptr_t) &cpu_state); return 0; } From 15a3df6135ef07218c141c2d99526cb072e10d5a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Sep 2025 16:18:19 +0000 Subject: [PATCH 14/25] Fix PACK* recompiled instructions on ARM64 --- src/codegen_new/codegen_backend_arm64_ops.c | 6 ++++++ src/codegen_new/codegen_backend_arm64_ops.h | 1 + src/codegen_new/codegen_backend_arm64_uops.c | 15 ++++++--------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index afe00fe4d..7f0518f04 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -208,6 +208,7 @@ # define OPCODE_ZIP1_V8B (0x0e003800) # define OPCODE_ZIP1_V4H (0x0e403800) # define OPCODE_ZIP1_V2S (0x0e803800) +# define OPCODE_ZIP1_V2D (0x4ec03800) # define OPCODE_ZIP2_V8B (0x0e007800) # define OPCODE_ZIP2_V4H (0x0e407800) # define OPCODE_ZIP2_V2S (0x0e807800) @@ -1483,6 +1484,11 @@ host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_re codegen_addlong(block, OPCODE_ZIP1_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } void +host_arm64_ZIP1_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_ZIP1_V2D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { codegen_addlong(block, OPCODE_ZIP2_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); diff --git a/src/codegen_new/codegen_backend_arm64_ops.h b/src/codegen_new/codegen_backend_arm64_ops.h index 084bbb404..152ab6793 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.h +++ b/src/codegen_new/codegen_backend_arm64_ops.h @@ -244,6 +244,7 @@ void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ZIP1_V2D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 4c00cbed2..925e6517b 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1449,9 +1449,8 @@ codegen_PACKSSWB(codeblock_t *block, uop_t *uop) int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_SQXTN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_SQXTN_V8B_8H(block, dest_reg, REG_V_TEMP); } else fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1466,9 +1465,8 @@ codegen_PACKSSDW(codeblock_t *block, uop_t *uop) int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_SQXTN_V4H_4S(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTN_V4H_4S(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_SQXTN_V4H_4S(block, dest_reg, REG_V_TEMP); } else fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1481,9 +1479,8 @@ codegen_PACKUSWB(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_SQXTUN_V8B_8H(block, REG_V_TEMP, src_reg_b); - host_arm64_SQXTUN_V8B_8H(block, dest_reg, dest_reg); - host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); + host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_SQXTUN_V8B_8H(block, dest_reg, REG_V_TEMP); } else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); From 62296072775381145c2e3627d8af057f0733be20 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Sep 2025 23:42:14 +0600 Subject: [PATCH 15/25] Temp MMX debugging logs --- src/codegen_new/codegen.c | 6 ++++++ src/codegen_new/codegen_ops_mmx_arith.c | 3 +++ src/codegen_new/codegen_ops_mmx_cmp.c | 3 +++ src/codegen_new/codegen_ops_mmx_loadstore.c | 6 ++++++ src/codegen_new/codegen_ops_mmx_logic.c | 5 +++++ src/codegen_new/codegen_ops_mmx_pack.c | 2 ++ src/codegen_new/codegen_ops_mmx_shift.c | 4 ++++ 7 files changed, 29 insertions(+) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 875dd72ca..57d8c4dbc 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -30,6 +30,12 @@ static struct { int TOP; } codegen_instructions[MAX_INSTRUCTION_COUNT]; +void +codegen_print_mmx(void) +{ + pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", cpu_state.MM[0], cpu_state.MM[1], cpu_state.MM[2], cpu_state.MM[3], cpu_state.MM[4], cpu_state.MM[5], cpu_state.MM[6], cpu_state.MM[7]); +} + int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) { diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index f01d64273..3ac6eb0d6 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -16,6 +16,8 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); + #define ropParith(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -37,6 +39,7 @@ uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index cf0cededb..865522f09 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -16,6 +16,8 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); + #define ropPcmp(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -37,6 +39,7 @@ uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index 9d37228ec..c0148781e 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -16,6 +16,8 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); + uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -36,6 +38,7 @@ ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -62,6 +65,7 @@ ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -84,6 +88,7 @@ ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -107,5 +112,6 @@ ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index dd50b486e..36d957c5e 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -16,6 +16,7 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -36,6 +37,7 @@ ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -58,6 +60,7 @@ ropPANDN(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -80,6 +83,7 @@ ropPOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetch uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -102,5 +106,6 @@ ropPXOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index c62aa10d0..69ec3ce3a 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -16,6 +16,7 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); #define ropPpack(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -37,6 +38,7 @@ uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index b812a9bb2..b1f41d1bb 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -16,6 +16,7 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" +extern void codegen_print_mmx(void); uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { @@ -39,6 +40,7 @@ ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } @@ -65,6 +67,7 @@ ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } @@ -91,6 +94,7 @@ ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } From 4735998b8a62631907157c02ded214d9fcc0fd52 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Sep 2025 23:46:00 +0600 Subject: [PATCH 16/25] Warning fixes --- src/codegen_new/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 57d8c4dbc..adc0d30d9 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -33,7 +33,7 @@ static struct { void codegen_print_mmx(void) { - pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", cpu_state.MM[0], cpu_state.MM[1], cpu_state.MM[2], cpu_state.MM[3], cpu_state.MM[4], cpu_state.MM[5], cpu_state.MM[6], cpu_state.MM[7]); + pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q, cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); } int From 97ab7a8ce8c715213b940fc0f9a675fcbeccc71d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 14 Sep 2025 23:47:18 +0600 Subject: [PATCH 17/25] More warning fixes --- src/codegen_new/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index adc0d30d9..0b3449500 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -33,7 +33,7 @@ static struct { void codegen_print_mmx(void) { - pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q, cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); + pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q); } int From d824fc36df1ae05d5a114bdfe46a7b835a7ac2c1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 12:34:34 +0600 Subject: [PATCH 18/25] Yet more logging --- src/codegen_new/codegen.c | 4 ++-- src/codegen_new/codegen_backend_arm64_uops.c | 8 ++++---- src/codegen_new/codegen_backend_x86-64_uops.c | 12 ++++++------ src/codegen_new/codegen_ir_defs.h | 4 ++-- src/codegen_new/codegen_ops_mmx_arith.c | 3 ++- src/codegen_new/codegen_ops_mmx_cmp.c | 3 ++- src/codegen_new/codegen_ops_mmx_loadstore.c | 6 +++++- src/codegen_new/codegen_ops_mmx_logic.c | 6 +++++- src/codegen_new/codegen_ops_mmx_pack.c | 3 ++- src/codegen_new/codegen_ops_mmx_shift.c | 5 ++++- 10 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 0b3449500..8dfb9b386 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -31,9 +31,9 @@ static struct { } codegen_instructions[MAX_INSTRUCTION_COUNT]; void -codegen_print_mmx(void) +codegen_print_mmx(const char* str) { - pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q); + pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX (%s)\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q, str); } int diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 925e6517b..c09b74fca 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -850,28 +850,28 @@ codegen_LOAD_FUNC_ARG3(codeblock_t *block, uop_t *uop) static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG0, uop->imm_data); + host_arm64_MOVX_IMM(block, REG_ARG0, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG1, uop->imm_data); + host_arm64_MOVX_IMM(block, REG_ARG1, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG2_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG2, uop->imm_data); + host_arm64_MOVX_IMM(block, REG_ARG2, uop->imm_data); return 0; } static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop) { - host_arm64_mov_imm(block, REG_ARG3, uop->imm_data); + host_arm64_MOVX_IMM(block, REG_ARG3, uop->imm_data); return 0; } diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index 356c8bcde..6b206d5b5 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -220,9 +220,9 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop) { # if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RCX, uop->imm_data); # else - host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RDI, uop->imm_data); # endif host_x86_CALL(block, uop->p); host_x86_TEST32_REG(block, REG_EAX, REG_EAX); @@ -906,9 +906,9 @@ static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop) { # if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RCX, uop->imm_data); # else - host_x86_MOV32_REG_IMM(block, REG_EDI, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RDI, uop->imm_data); # endif return 0; } @@ -916,9 +916,9 @@ static int codegen_LOAD_FUNC_ARG1_IMM(codeblock_t *block, uop_t *uop) { # if _WIN64 - host_x86_MOV32_REG_IMM(block, REG_EDX, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RDX, uop->imm_data); # else - host_x86_MOV32_REG_IMM(block, REG_ESI, uop->imm_data); + host_x86_MOV64_REG_IMM(block, REG_RSI, uop->imm_data); # endif return 0; } diff --git a/src/codegen_new/codegen_ir_defs.h b/src/codegen_new/codegen_ir_defs.h index 60f7badea..bfc19373b 100644 --- a/src/codegen_new/codegen_ir_defs.h +++ b/src/codegen_new/codegen_ir_defs.h @@ -336,7 +336,7 @@ typedef struct uop_t { ir_reg_t src_reg_a; ir_reg_t src_reg_b; ir_reg_t src_reg_c; - uint32_t imm_data; + uintptr_t imm_data; void *p; ir_host_reg_t dest_reg_a_real; ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real; @@ -601,7 +601,7 @@ uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_re } static inline void -uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm) +uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uintptr_t imm) { uop_t *uop = uop_alloc(ir, uop_type); diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 3ac6eb0d6..4f8a5d91c 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); #define ropParith(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ @@ -39,6 +39,7 @@ extern void codegen_print_mmx(void); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index 865522f09..d28c9197c 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); #define ropPcmp(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ @@ -39,6 +39,7 @@ extern void codegen_print_mmx(void); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index c0148781e..d7ff5b355 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -38,6 +38,7 @@ ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -65,6 +66,7 @@ ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -88,6 +90,7 @@ ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -112,6 +115,7 @@ ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index 36d957c5e..e8e092fad 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -37,6 +37,7 @@ ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -60,6 +61,7 @@ ropPANDN(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -83,6 +85,7 @@ ropPOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetch uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -106,6 +109,7 @@ ropPXOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 69ec3ce3a..5c01c7e92 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); #define ropPpack(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -38,6 +38,7 @@ extern void codegen_print_mmx(void); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index b1f41d1bb..42aea4f1c 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(void); +extern void codegen_print_mmx(const char* str); uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { @@ -40,6 +40,7 @@ ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; @@ -67,6 +68,7 @@ ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; @@ -94,6 +96,7 @@ ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } + uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; From 1d8877fba79e1eec6958e96c646cb0872541a65b Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 09:19:40 +0000 Subject: [PATCH 19/25] Progress on ARM64 MMX opcodes --- src/codegen_new/codegen.c | 4 ++-- src/codegen_new/codegen_backend_arm64_ops.c | 12 +++++++++++- src/codegen_new/codegen_backend_arm64_ops.h | 1 + src/codegen_new/codegen_backend_arm64_uops.c | 13 ++++++++++--- src/codegen_new/codegen_ops_mmx_arith.c | 3 ++- src/codegen_new/codegen_ops_mmx_cmp.c | 3 ++- src/codegen_new/codegen_ops_mmx_loadstore.c | 6 +++++- src/codegen_new/codegen_ops_mmx_logic.c | 3 ++- src/codegen_new/codegen_ops_mmx_pack.c | 3 ++- src/codegen_new/codegen_ops_mmx_shift.c | 5 ++++- 10 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 8dfb9b386..48d2afad9 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -31,9 +31,9 @@ static struct { } codegen_instructions[MAX_INSTRUCTION_COUNT]; void -codegen_print_mmx(const char* str) +codegen_print_mmx(const char* str, uint32_t fetchdat) { - pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX (%s)\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q, str); + pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX (%s, fetchdat 0x%08X)\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q, str, fetchdat); } int diff --git a/src/codegen_new/codegen_backend_arm64_ops.c b/src/codegen_new/codegen_backend_arm64_ops.c index 7f0518f04..9d5806edf 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.c +++ b/src/codegen_new/codegen_backend_arm64_ops.c @@ -102,6 +102,10 @@ # define OPCODE_SUB_LSR (0x25a << 21) # define OPCODE_SUBX_LSL (0x658 << 21) +# define OPCODE_INS_B (0x6e010400) +# define OPCODE_INS_H (0x6e020400) +# define OPCODE_INS_S (0x6e040400) +# define OPCODE_INS_D (0x6e080400) # define OPCODE_ADD_V8B (0x0e208400) # define OPCODE_ADD_V4H (0x0e608400) # define OPCODE_ADD_V2S (0x0ea08400) @@ -180,7 +184,7 @@ # define OPCODE_SQSUB_V8B (0x0e202c00) # define OPCODE_SQSUB_V4H (0x0e602c00) # define OPCODE_SQXTN_V8B_8H (0x0e214800) -# define OPCODE_SQXTUN_V8B_8H (0x7e212800) +# define OPCODE_SQXTUN_V8B_8H (0x2e212800) # define OPCODE_SQXTN_V4H_4S (0x0e614800) # define OPCODE_SHL_VD (0x0f005400) # define OPCODE_SHL_VQ (0x4f005400) @@ -718,6 +722,12 @@ host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element) codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element)); } +void +host_arm64_INS_D(codeblock_t *block, int dst_reg, int src_reg, int dst_index, int src_index) +{ + codegen_addlong(block, OPCODE_INS_D | Rd(dst_reg) | Rn(src_reg) | ((dst_index & 1) << 20) | ((src_index & 1) << 14)); +} + void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data) { diff --git a/src/codegen_new/codegen_backend_arm64_ops.h b/src/codegen_new/codegen_backend_arm64_ops.h index 152ab6793..129c2b2a3 100644 --- a/src/codegen_new/codegen_backend_arm64_ops.h +++ b/src/codegen_new/codegen_backend_arm64_ops.h @@ -72,6 +72,7 @@ void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_ void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element); +void host_arm64_INS_D(codeblock_t *block, int dst_reg, int src_reg, int dst_index, int src_index); void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index c09b74fca..c4923387c 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1449,7 +1449,8 @@ codegen_PACKSSWB(codeblock_t *block, uop_t *uop) int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_INS_D(block, REG_V_TEMP, dest_reg, 0, 0); + host_arm64_INS_D(block, REG_V_TEMP, src_reg_b, 1, 0); host_arm64_SQXTN_V8B_8H(block, dest_reg, REG_V_TEMP); } else fatal("PACKSSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1465,7 +1466,8 @@ codegen_PACKSSDW(codeblock_t *block, uop_t *uop) int src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_INS_D(block, REG_V_TEMP, dest_reg, 0, 0); + host_arm64_INS_D(block, REG_V_TEMP, src_reg_b, 1, 0); host_arm64_SQXTN_V4H_4S(block, dest_reg, REG_V_TEMP); } else fatal("PACKSSDW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1479,8 +1481,13 @@ codegen_PACKUSWB(codeblock_t *block, uop_t *uop) int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) { - host_arm64_ZIP1_V2D(block, REG_V_TEMP, dest_reg, src_reg_b); + host_arm64_INS_D(block, REG_V_TEMP, dest_reg, 0, 0); + host_arm64_INS_D(block, REG_V_TEMP, src_reg_b, 1, 0); host_arm64_SQXTUN_V8B_8H(block, dest_reg, REG_V_TEMP); + //host_arm64_ADD_V4H(block, dest_reg, dest_reg, src_reg_b); + //host_arm64_SQXTUN_V8B_8H(block, REG_V_TEMP, src_reg_b); + //host_arm64_SQXTUN_V8B_8H(block, dest_reg, dest_reg); + //host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 4f8a5d91c..4688f3e2b 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); #define ropParith(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ @@ -40,6 +40,7 @@ extern void codegen_print_mmx(const char* str); } \ \ uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index d28c9197c..09006cae7 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); #define ropPcmp(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ @@ -40,6 +40,7 @@ extern void codegen_print_mmx(const char* str); } \ \ uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index d7ff5b355..267e7312a 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) @@ -39,6 +39,7 @@ ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -67,6 +68,7 @@ ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -91,6 +93,7 @@ ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -116,6 +119,7 @@ ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index e8e092fad..24dbd167e 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { @@ -110,6 +110,7 @@ ropPXOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 5c01c7e92..86cd99e0a 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); #define ropPpack(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -39,6 +39,7 @@ extern void codegen_print_mmx(const char* str); } \ \ uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index 42aea4f1c..e6c6da410 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -16,7 +16,7 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str); +extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { @@ -41,6 +41,7 @@ ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; @@ -69,6 +70,7 @@ ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; @@ -97,6 +99,7 @@ ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t } uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); + uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; From fe28a8bb627326ace5b2a8804c857fa1a53c3077 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 11:47:03 +0000 Subject: [PATCH 20/25] Disable unrolling for now --- src/codegen_new/codegen_ops_helpers.h | 1 + src/codegen_new/codegen_ops_mmx_arith.c | 5 ----- src/codegen_new/codegen_ops_mmx_cmp.c | 5 ----- src/codegen_new/codegen_ops_mmx_loadstore.c | 12 ------------ src/codegen_new/codegen_ops_mmx_logic.c | 9 --------- src/codegen_new/codegen_ops_mmx_pack.c | 4 ---- src/codegen_new/codegen_ops_mmx_shift.c | 10 ---------- src/codegen_new/codegen_reg.c | 2 +- 8 files changed, 2 insertions(+), 46 deletions(-) diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 92b721099..0128e15ae 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -114,6 +114,7 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { + return 0; if (block->flags & CODEBLOCK_BYTE_MASK) return 0; diff --git a/src/codegen_new/codegen_ops_mmx_arith.c b/src/codegen_new/codegen_ops_mmx_arith.c index 4688f3e2b..f01d64273 100644 --- a/src/codegen_new/codegen_ops_mmx_arith.c +++ b/src/codegen_new/codegen_ops_mmx_arith.c @@ -16,8 +16,6 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); - #define ropParith(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -39,9 +37,6 @@ extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ - uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_cmp.c b/src/codegen_new/codegen_ops_mmx_cmp.c index 09006cae7..cf0cededb 100644 --- a/src/codegen_new/codegen_ops_mmx_cmp.c +++ b/src/codegen_new/codegen_ops_mmx_cmp.c @@ -16,8 +16,6 @@ #include "codegen_ops_mmx_cmp.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); - #define ropPcmp(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -39,9 +37,6 @@ extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ - uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index 267e7312a..e46af7e44 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -38,9 +38,6 @@ ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -67,9 +64,6 @@ ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -92,9 +86,6 @@ ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } @@ -118,8 +109,5 @@ ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg)); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index 24dbd167e..dec8d8c04 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -37,8 +37,6 @@ ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -61,8 +59,6 @@ ropPANDN(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -85,8 +81,6 @@ ropPOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetch uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } uint32_t @@ -109,8 +103,5 @@ ropPXOR(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetc uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); return op_pc + 1; } diff --git a/src/codegen_new/codegen_ops_mmx_pack.c b/src/codegen_new/codegen_ops_mmx_pack.c index 86cd99e0a..c62aa10d0 100644 --- a/src/codegen_new/codegen_ops_mmx_pack.c +++ b/src/codegen_new/codegen_ops_mmx_pack.c @@ -16,7 +16,6 @@ #include "codegen_ops_mmx_pack.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); #define ropPpack(func) \ uint32_t rop##func(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), \ uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \ @@ -38,9 +37,6 @@ extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uop_##func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \ } \ \ - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); \ - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); \ - uop_CALL_FUNC(ir, codegen_print_mmx); \ return op_pc + 1; \ } diff --git a/src/codegen_new/codegen_ops_mmx_shift.c b/src/codegen_new/codegen_ops_mmx_shift.c index e6c6da410..b812a9bb2 100644 --- a/src/codegen_new/codegen_ops_mmx_shift.c +++ b/src/codegen_new/codegen_ops_mmx_shift.c @@ -16,7 +16,6 @@ #include "codegen_ops_mmx_shift.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, UNUSED(uint32_t op_32), uint32_t op_pc) { @@ -40,9 +39,6 @@ ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } @@ -69,9 +65,6 @@ ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } @@ -98,9 +91,6 @@ ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t return 0; } - uop_LOAD_FUNC_ARG_IMM(ir, 0, (uintptr_t)__func__); - uop_LOAD_FUNC_ARG_IMM(ir, 1, fetchdat); - uop_CALL_FUNC(ir, codegen_print_mmx); codegen_mark_code_present(block, cs + op_pc + 1, 1); return op_pc + 2; } diff --git a/src/codegen_new/codegen_reg.c b/src/codegen_new/codegen_reg.c index f91377df8..b678bd6ac 100644 --- a/src/codegen_new/codegen_reg.c +++ b/src/codegen_new/codegen_reg.c @@ -201,7 +201,7 @@ static const uint8_t native_requested_sizes[9][8] = [REG_DOUBLE][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, [REG_FPU_ST_DOUBLE][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1, - [REG_POINTER][(sizeof(void *) == 4) ? (IREG_SIZE_L >> IREG_SIZE_SHIFT) : (IREG_SIZE_Q >> IREG_SIZE_SHIFT)] = 1 + [REG_POINTER][IREG_SIZE_Q >> IREG_SIZE_SHIFT] = 1 }; void From c3a6e826b4e3adf8264186f68afc4a0a54815387 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Mon, 15 Sep 2025 17:48:24 +0200 Subject: [PATCH 21/25] S3 928 and icd2061 mode rework (September 15th, 2025) The rework resolves around implementing the clock multiplier and multiplexing rate of the bt485 ramdac alongside existing additional flags for eventual fixes (like cr31 bit 1) as well as the true color bypass (for 16-bit and true color modes). These, together, allow proper rendering of the generic VESA S3 drivers alongside non-VESA ELSA OEM drivers on various guests. --- src/include/86box/vid_clockgen_icd2061.h | 38 ++ src/include/86box/vid_svga.h | 5 +- src/video/clockgen/vid_clockgen_icd2061.c | 19 +- src/video/ramdac/vid_ramdac_bt48x.c | 21 +- src/video/ramdac/vid_ramdac_sc1502x.c | 4 + src/video/vid_et4000w32.c | 2 + src/video/vid_s3.c | 513 ++++++++++------------ 7 files changed, 301 insertions(+), 301 deletions(-) create mode 100644 src/include/86box/vid_clockgen_icd2061.h diff --git a/src/include/86box/vid_clockgen_icd2061.h b/src/include/86box/vid_clockgen_icd2061.h new file mode 100644 index 000000000..78734a347 --- /dev/null +++ b/src/include/86box/vid_clockgen_icd2061.h @@ -0,0 +1,38 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * ICD2061 clock generator emulation. + * Also emulates the ICS9161 which is the same as the ICD2016, + * but without the need for tuning (which is irrelevant in + * emulation anyway). + * + * Used by ET4000w32/p (Diamond Stealth 32) and the S3 + * Vision964 family. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2018 Miran Grca. + */ +#ifndef VIDEO_CLOCKGEN_ICD2061_H +#define VIDEO_CLOCKGEN_ICD2061_H + +typedef struct icd2061_t { + float freq[3]; + float ref_clock; + + int count; + int bit_count; + int unlocked; + int state; + uint32_t data; + uint32_t ctrl; +} icd2061_t; + +#endif // VIDEO_CLOCKGEN_ICD2061_H diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index cbd6c511a..66ed2affe 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -142,6 +142,9 @@ typedef struct svga_t { int start_retrace_latch; int vga_mode; int half_pixel; + int clock_multiplier; + int true_color_bypass; + int multiplexing_rate; /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : 0MB-1MB - VRAM @@ -450,7 +453,7 @@ extern void ibm_rgb528_ramdac_set_ref_clock(void *priv, svga_t *svga, float r extern void icd2061_write(void *priv, int val); extern float icd2061_getclock(int clock, void *priv); -extern void icd2061_set_ref_clock(void *priv, svga_t *svga, float ref_clock); +extern void icd2061_set_ref_clock(void *priv, float ref_clock); /* The code is the same, the #define's are so that the correct name can be used. */ # define ics9161_write icd2061_write diff --git a/src/video/clockgen/vid_clockgen_icd2061.c b/src/video/clockgen/vid_clockgen_icd2061.c index f1925e769..a7f0286f2 100644 --- a/src/video/clockgen/vid_clockgen_icd2061.c +++ b/src/video/clockgen/vid_clockgen_icd2061.c @@ -33,20 +33,9 @@ #include <86box/timer.h> #include <86box/video.h> #include <86box/vid_svga.h> +#include <86box/vid_clockgen_icd2061.h> #include <86box/plat_unused.h> -typedef struct icd2061_t { - float freq[3]; - float ref_clock; - - int count; - int bit_count; - int unlocked; - int state; - uint32_t data; - uint32_t ctrl; -} icd2061_t; - #ifdef ENABLE_ICD2061_LOG int icd2061_do_log = ENABLE_ICD2061_LOG; @@ -155,14 +144,12 @@ icd2061_getclock(int clock, void *priv) } void -icd2061_set_ref_clock(void *priv, svga_t *svga, float ref_clock) +icd2061_set_ref_clock(void *priv, float ref_clock) { icd2061_t *icd2061 = (icd2061_t *) priv; - if (icd2061) + if (icd2061 != NULL) icd2061->ref_clock = ref_clock; - - svga_recalctimings(svga); } static void * diff --git a/src/video/ramdac/vid_ramdac_bt48x.c b/src/video/ramdac/vid_ramdac_bt48x.c index 64112e089..7ae96dfbd 100644 --- a/src/video/ramdac/vid_ramdac_bt48x.c +++ b/src/video/ramdac/vid_ramdac_bt48x.c @@ -101,7 +101,7 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_ switch (rs) { case 0x00: /* Palette Write Index Register (RS value = 0000) */ case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - case 0x03: + case 0x03: /* Palette Read Index Register (RS value = 0011) */ case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ svga->dac_pos = 0; svga->dac_status = addr & 0x03; @@ -362,14 +362,21 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga) void bt48x_recalctimings(void *priv, svga_t *svga) { - const bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv; - svga->interlace = ramdac->cmd_r2 & 0x08; - if (ramdac->cmd_r3 & 0x08) { - svga->hdisp <<= 1; /* x2 clock multiplier */ - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; + svga->interlace = !!(ramdac->cmd_r2 & 0x08); + svga->clock_multiplier = 0; + svga->multiplexing_rate = 0; + svga->true_color_bypass = 0; + if (ramdac->cmd_r3 & 0x08) { /* x2 clock multiplier */ + //pclog("2x multiplier.\n"); + svga->clock_multiplier = 1; } + svga->multiplexing_rate = (ramdac->cmd_r1 & 0x60) >> 5; + if (svga->bpp >= 15) + svga->true_color_bypass = !!(ramdac->cmd_r1 & 0x10); + + //pclog("CR0=%02x, CR1=%02x, CR2=%02x.\n", ramdac->cmd_r0, ramdac->cmd_r1, ramdac->cmd_r2); } void diff --git a/src/video/ramdac/vid_ramdac_sc1502x.c b/src/video/ramdac/vid_ramdac_sc1502x.c index 4fc603ee9..972e0d895 100644 --- a/src/video/ramdac/vid_ramdac_sc1502x.c +++ b/src/video/ramdac/vid_ramdac_sc1502x.c @@ -44,6 +44,7 @@ static void sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga) { int oldbpp = svga->bpp; + //pclog("BPP Val=%02x, truecolortype=%02x.\n", ramdac->ctrl, ramdac->regs[0x10] & 0x01); if (ramdac->ctrl & 0x80) { if (ramdac->ctrl & 0x40) { svga->bpp = 16; @@ -60,6 +61,7 @@ sc1502x_ramdac_bpp(sc1502x_ramdac_t *ramdac, svga_t *svga) } else svga->bpp = 8; } + //pclog("SVGA BPP=%d.\n", svga->bpp); if (oldbpp != svga->bpp) svga_recalctimings(svga); } @@ -135,9 +137,11 @@ sc1502x_rs2_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t * uint8_t rs = (addr & 0x03); rs |= ((!!rs2) << 2); + //pclog("RS=%02x, Write=%02x.\n", rs, val); switch (rs) { case 0x00: if (ramdac->ctrl & 0x10) { + //pclog("RAMDAC IDX=%02x, Write=%02x.\n", ramdac->idx, val); switch (ramdac->idx) { case 8: ramdac->regs[8] = val; diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index c1021e905..3f661eabd 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -2845,6 +2845,8 @@ et4000w32p_init(const device_t *info) et4000->svga.ramdac = device_add(&stg_ramdac_device); et4000->svga.clock_gen = device_add(&icd2061_device); et4000->svga.getclock = icd2061_getclock; + icd2061_set_ref_clock(et4000->svga.ramdac, 14318184.0f); + svga_recalctimings(&et4000->svga); break; default: diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 53f75365f..e3176381a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -16,6 +16,7 @@ * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 Miran Grca. */ +#include #include #include #include @@ -3000,6 +3001,8 @@ s3_out(uint16_t addr, uint8_t val, void *priv) if (svga->getclock == icd2061_getclock) { if (((val >> 2) & 3) != 3) icd2061_write(svga->clock_gen, (val >> 2) & 3); + else + icd2061_write(svga->clock_gen, svga->crtc[0x42] & 0x0f); } break; @@ -3026,7 +3029,9 @@ s3_out(uint16_t addr, uint8_t val, void *priv) } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ { - if (val & 0x08) + svga->chain2_write = !(val & 4); + svga->chain4 = (svga->chain4 & ~8) | (val & 8); + if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16; else svga->write_bank = svga->read_bank = s3->bank << 14; @@ -3212,7 +3217,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); if ((s3->chip >= S3_TRIO32) && (svga->bpp == 32)) svga->hwcursor.x <<= 1; - else if ((s3->chip >= S3_86C928 && s3->chip <= S3_86C805) && ((svga->bpp == 15) || (svga->bpp == 16))) { + else if ((s3->chip >= S3_86C928) && (s3->chip <= S3_86C805) && ((svga->bpp == 15) || (svga->bpp == 16))) { if ((s3->card_type == S3_MIROCRYSTAL10SD_805) && !(svga->crtc[0x45] & 0x04) && (svga->bpp == 16)) svga->hwcursor.x >>= 2; else @@ -3787,7 +3792,6 @@ s3_recalctimings(svga_t *svga) case 0xc0: s3->width = 1280; break; - default: break; } @@ -3823,112 +3827,51 @@ s3_recalctimings(svga_t *svga) if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " - "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], - svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, - svga->attrregs[0x10] & 0x40, svga->hdisp); + "attr=%02x, hdisp=%d, dotsperclock=%x, clksel=%x, clockmultiplier=%d, multiplexingrate=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], + svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 0x04, + svga->attrregs[0x10] & 0x40, svga->hdisp, svga->dots_per_clock, clk_sel, svga->clock_multiplier, svga->multiplexing_rate); switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; switch (s3->chip) { case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - s3_log("928 8bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - switch (s3->width) { - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + if (!svga->clock_multiplier) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; - break; - default: - break; + } } - break; - case 2048: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + svga->clock *= 2.0; + } else { + if (svga->multiplexing_rate == 0) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 1024: - switch (svga->hdisp) { - case 256: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 512: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->clock_multiplier == 1) { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; } - break; - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; + svga->clock *= 2.0; + } else { + if (svga->multiplexing_rate == 2) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + svga->clock *= 4.0; } - break; - case 2048: /*Account for the 1280x1024 resolution and the ELSA EEPROM resolutions*/ - switch (svga->hdisp) { - case 320: - case 384: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 576: - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - if (s3->ramdac_type == BT48X) { - if (!svga->interlace) { - if (svga->dispend >= 1024) { - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - } - } else { - if (svga->dispend >= 512) { - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - } - } - } - break; - } - break; - default: - break; + } } break; default: @@ -3936,72 +3879,8 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - switch (s3->width) { - case 1024: - switch (svga->hdisp) { - case 256: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 512: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - case 1280: /*Account for the 1280x1024 resolution*/ - switch (svga->hdisp) { - case 320: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - case 2048: /*Account for the 1280x1024 resolution and the ELSA EEPROM resolutions*/ - switch (svga->hdisp) { - case 320: - case 384: - svga->hdisp <<= 2; - svga->dots_per_clock <<= 2; - break; - case 576: - case 640: - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - break; - default: - break; - } - break; - default: - break; - } - break; - - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - default: - break; - } - break; - - default: - break; - } + if (!svga->chain4) + svga->chain4 |= 0x08; break; case S3_VISION964: switch (s3->card_type) { @@ -4126,69 +4005,82 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - if (!s3->color_16bit) { - s3_log("928 15bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; - } - switch (svga->hdisp) { /*This might be a driver issue*/ - case 800: - s3->width = 1024; - break; - case 1280: - s3->width = 2048; - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 2048: - if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } else { + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 1) { + if (svga->true_color_bypass) { + if (svga->crtc[0x31] & 0x02) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + svga->clock *= 2.0; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (!svga->clock_multiplier) + svga->clock *= 2.0; + } + } + } else { + if (svga->multiplexing_rate == 1) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - if (s3->ramdac_type == BT48X) - svga->clock /= 2.0; - else if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->multiplexing_rate == 1) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } } break; - default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { svga->hdisp >>= 1; svga->dots_per_clock >>= 1; - break; - default: - break; + } + } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + if (s3->width == 640) + svga->hdisp >>= 1; + } } break; - default: break; } @@ -4350,67 +4242,82 @@ s3_recalctimings(svga_t *svga) } break; case S3_86C928: - switch (s3->card_type) { - case S3_METHEUS_86C928: - s3_log("928 16bpp: ClockSel=%02x, width=%d, hdisp=%d, dotsperclock=%d.\n", clk_sel, s3->width, svga->hdisp, svga->dots_per_clock); - svga->hdisp <<= 1; - svga->dots_per_clock <<= 1; - svga->clock *= 2.0; - switch (svga->hdisp) { /*This might be a driver issue*/ - case 800: - s3->width = 1024; - break; - case 1280: - s3->width = 2048; - break; - default: - break; - } - break; - case S3_ELSAWIN1K_86C928: - case S3_ELSAWIN2K_86C928: - switch (s3->width) { - case 2048: - if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } else { + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->multiplexing_rate == 1) { + if (svga->true_color_bypass) { + if (svga->crtc[0x31] & 0x02) { + svga->hdisp <<= 2; + svga->dots_per_clock <<= 2; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + } + svga->clock *= 2.0; + } else { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + if (!svga->clock_multiplier) + svga->clock *= 2.0; + } + } + } else { + if (svga->multiplexing_rate == 1) { svga->hdisp <<= 1; svga->dots_per_clock <<= 1; + svga->clock *= 2.0; } - break; - default: - if (s3->ramdac_type == BT48X) - svga->clock /= 2.0; - else if (s3->ramdac_type == SC1502X) { - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; + } + } else if (svga->getclock == ics2494_getclock) { /*ICS2494 clock chip*/ + if (svga->multiplexing_rate == 1) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } } break; - default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - break; - case S3_SPEA_MERCURY_LITE_PCI: - switch (s3->width) { - case 640: + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { svga->hdisp >>= 1; svga->dots_per_clock >>= 1; - break; - default: - break; + } + } else if (svga->getclock == av9194_getclock) { /*AV9194 clock chip*/ + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->clock *= 2.0; + } else { + if (s3->width == 640) + svga->hdisp >>= 1; + } } break; - default: break; } @@ -4561,8 +4468,22 @@ s3_recalctimings(svga_t *svga) break; } break; - case S3_86C928PCI: + case S3_86C928: /*Technically the 928 cards don't support 24bpp.*/ + if (!svga->chain4) + svga->chain4 |= 0x08; + break; + case S3_86C928PCI: /*Technically the 928 cards don't support 24bpp.*/ switch (s3->card_type) { + case S3_ELSAWIN1KPCI_86C928: + if (svga->dots_per_clock == 16) { + svga->dots_per_clock >>= 1; + svga->hdisp = (svga->hdisp << 1) / 3; + svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; + svga->clock /= (2.0 / 3.0); + if (svga->hdisp == 640) + s3->width = 640; + } + break; case S3_SPEA_MERCURY_LITE_PCI: svga->hdisp = (svga->hdisp << 1) / 3; svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; @@ -4602,22 +4523,54 @@ s3_recalctimings(svga_t *svga) svga->render = svga_render_32bpp_highres; switch (s3->chip) { case S3_86C928: - switch (s3->card_type) { - case S3_ELSAWIN1K_86C928: - svga->hdisp >>= 2; - svga->dots_per_clock >>= 2; - svga->clock *= 2.0; + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case BT48X: /*BT485 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if ((svga->clock_multiplier == 1) || (s3->width >= 1024)) { + if (svga->true_color_bypass) { + svga->hdisp <<= 1; + svga->dots_per_clock <<= 1; + svga->clock *= 2.0; + } + } + if (svga->hdisp == 800) + s3->width = 1024; + } + break; + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (svga->crtc[0x31] & 0x02) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + if (svga->hdisp == 640) + s3->width = 1024; + } else { + svga->hdisp >>= 2; + svga->dots_per_clock >>= 2; + if (svga->hdisp == 800) + s3->width = 1024; + } + } break; default: break; } break; case S3_86C928PCI: - switch (s3->card_type) { - case S3_ELSAWIN1KPCI_86C928: - svga->hdisp >>= 2; - svga->dots_per_clock >>= 2; - svga->clock *= 2.0; + if (!svga->chain4) + svga->chain4 |= 0x08; + switch (s3->ramdac_type) { + case SC1502X: /*SC15025 RAMDAC*/ + if (svga->getclock == icd2061_getclock) { /*ICD2061 clock chip*/ + if (!(svga->crtc[0x31] & 0x02)) { + svga->hdisp >>= 2; + svga->dots_per_clock >>= 2; + if (s3->width >= 800) + svga->clock *= 2.0; + } + } break; default: break; @@ -10792,7 +10745,8 @@ s3_init(const device_t *info) /* DCS2824-0 = Diamond ICD2061A-compatible. */ svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); } break; @@ -10890,7 +10844,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_ELSAWIN2K_86C928: @@ -10906,7 +10861,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&ics9161_device); svga->getclock = ics9161_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_METHEUS_86C928: @@ -10936,7 +10892,8 @@ s3_init(const device_t *info) svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; s3->elsa_eeprom = 1; - icd2061_set_ref_clock(svga->ramdac, svga, 28322000.0f); + icd2061_set_ref_clock(svga->ramdac, 28322000.0f); + svga_recalctimings(svga); break; case S3_SPEA_MERCURY_LITE_PCI: @@ -10996,7 +10953,8 @@ s3_init(const device_t *info) s3->ramdac_type = BT48X; svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); break; } break; @@ -11075,7 +11033,8 @@ s3_init(const device_t *info) s3->ramdac_type = ATT498; svga->clock_gen = device_add(&icd2061_device); svga->getclock = icd2061_getclock; - icd2061_set_ref_clock(svga->ramdac, svga, 14318184.0f); + icd2061_set_ref_clock(svga->ramdac, 14318184.0f); + svga_recalctimings(svga); } else { svga->ramdac = device_add(&sdac_ramdac_device); s3->ramdac_type = S3_SDAC; From 0a22140c709736bd22826598790ec45c649cd04f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 15:56:00 +0000 Subject: [PATCH 22/25] Try for some fixes --- src/codegen_new/codegen.c | 15 +++------------ src/codegen_new/codegen_ir.c | 1 + src/codegen_new/codegen_ops_helpers.h | 1 - 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index 48d2afad9..bffa6b513 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -30,12 +30,6 @@ static struct { int TOP; } codegen_instructions[MAX_INSTRUCTION_COUNT]; -void -codegen_print_mmx(const char* str, uint32_t fetchdat) -{ - pclog("MMX results: %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX, %016llX (%s, fetchdat 0x%08X)\n", (unsigned long long)cpu_state.MM[0].q, (unsigned long long)cpu_state.MM[1].q, (unsigned long long)cpu_state.MM[2].q, (unsigned long long)cpu_state.MM[3].q, (unsigned long long)cpu_state.MM[4].q, (unsigned long long)cpu_state.MM[5].q, (unsigned long long)cpu_state.MM[6].q, (unsigned long long)cpu_state.MM[7].q, str, fetchdat); -} - int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP) { @@ -746,12 +740,9 @@ codegen_skip: else uop_MOV_IMM(ir, IREG_pc, op_pc + pc_off); uop_MOV_IMM(ir, IREG_oldpc, old_pc); - if (op_32 != last_op_32) - uop_MOV_IMM(ir, IREG_op32, op_32); - if (op_ea_seg != last_op_ea_seg) - uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); - if (op_ssegs != last_op_ssegs) - uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); + uop_MOV_IMM(ir, IREG_op32, op_32); + uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); + uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); uop_CALL_INSTRUCTION_FUNC(ir, op, fetchdat); codegen_flags_changed = 0; codegen_mark_code_present(block, cs + cpu_state.pc, 8); diff --git a/src/codegen_new/codegen_ir.c b/src/codegen_new/codegen_ir.c index d14fa0f23..dfd136289 100644 --- a/src/codegen_new/codegen_ir.c +++ b/src/codegen_new/codegen_ir.c @@ -53,6 +53,7 @@ duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) new_uop->imm_data = uop->imm_data; new_uop->p = uop->p; new_uop->pc = uop->pc; + new_uop->is_a16 = uop->is_a16; if (uop->jump_dest_uop != -1) { new_uop->jump_dest_uop = uop->jump_dest_uop + offset; diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 0128e15ae..92b721099 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -114,7 +114,6 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { - return 0; if (block->flags & CODEBLOCK_BYTE_MASK) return 0; From 7ac4b8de3a97b9dd7cdbbcf4bd7b613d5f5846f1 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 17:39:22 +0000 Subject: [PATCH 23/25] Revert some changes --- src/codegen_new/codegen.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index bffa6b513..875dd72ca 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -740,9 +740,12 @@ codegen_skip: else uop_MOV_IMM(ir, IREG_pc, op_pc + pc_off); uop_MOV_IMM(ir, IREG_oldpc, old_pc); - uop_MOV_IMM(ir, IREG_op32, op_32); - uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); - uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); + if (op_32 != last_op_32) + uop_MOV_IMM(ir, IREG_op32, op_32); + if (op_ea_seg != last_op_ea_seg) + uop_MOV_PTR(ir, IREG_ea_seg, (void *) op_ea_seg); + if (op_ssegs != last_op_ssegs) + uop_MOV_IMM(ir, IREG_ssegs, op_ssegs); uop_CALL_INSTRUCTION_FUNC(ir, op, fetchdat); codegen_flags_changed = 0; codegen_mark_code_present(block, cs + cpu_state.pc, 8); From fed75595da92648752baf2af5bc70a74c75c8dc8 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 19:09:06 +0000 Subject: [PATCH 24/25] Disable unrolling optimizations on ARM64 --- src/codegen_new/codegen_ops_helpers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 92b721099..61711d1ed 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -114,6 +114,10 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { + /* TODO: Re-enable this again after fixing mysterious crashes on ARM64. */ +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 + return 0; +#endif if (block->flags & CODEBLOCK_BYTE_MASK) return 0; From cc7ca6c65226ae7dd07e6d009d34699107ca1e79 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 15 Sep 2025 19:13:51 +0000 Subject: [PATCH 25/25] Cleanups --- src/codegen_new/codegen_backend_arm64_uops.c | 4 ---- src/codegen_new/codegen_ops.c | 8 ++++++++ src/codegen_new/codegen_ops_helpers.h | 2 +- src/codegen_new/codegen_ops_mmx_loadstore.c | 2 -- src/codegen_new/codegen_ops_mmx_logic.c | 1 - 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index c4923387c..d06685cb2 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -1484,10 +1484,6 @@ codegen_PACKUSWB(codeblock_t *block, uop_t *uop) host_arm64_INS_D(block, REG_V_TEMP, dest_reg, 0, 0); host_arm64_INS_D(block, REG_V_TEMP, src_reg_b, 1, 0); host_arm64_SQXTUN_V8B_8H(block, dest_reg, REG_V_TEMP); - //host_arm64_ADD_V4H(block, dest_reg, dest_reg, src_reg_b); - //host_arm64_SQXTUN_V8B_8H(block, REG_V_TEMP, src_reg_b); - //host_arm64_SQXTUN_V8B_8H(block, dest_reg, dest_reg); - //host_arm64_ZIP1_V2S(block, dest_reg, dest_reg, REG_V_TEMP); } else fatal("PACKUSWB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index 039e0877a..68861ff52 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -97,7 +97,11 @@ RecompOpFn recomp_opcodes_0f[512] = { /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#else /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#endif /*32-bit data*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -119,7 +123,11 @@ RecompOpFn recomp_opcodes_0f[512] = { /*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN, /*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR, +#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#else /*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL, +#endif // clang-format on }; diff --git a/src/codegen_new/codegen_ops_helpers.h b/src/codegen_new/codegen_ops_helpers.h index 61711d1ed..05928bd2f 100644 --- a/src/codegen_new/codegen_ops_helpers.h +++ b/src/codegen_new/codegen_ops_helpers.h @@ -114,7 +114,7 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr) { - /* TODO: Re-enable this again after fixing mysterious crashes on ARM64. */ + /* TODO: Re-enable this again after fixing mysterious crashes on ARM64 with MMX instructions used. */ #if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM || defined __aarch64__ || defined _M_ARM64 return 0; #endif diff --git a/src/codegen_new/codegen_ops_mmx_loadstore.c b/src/codegen_new/codegen_ops_mmx_loadstore.c index e46af7e44..9d37228ec 100644 --- a/src/codegen_new/codegen_ops_mmx_loadstore.c +++ b/src/codegen_new/codegen_ops_mmx_loadstore.c @@ -16,8 +16,6 @@ #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); - uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { diff --git a/src/codegen_new/codegen_ops_mmx_logic.c b/src/codegen_new/codegen_ops_mmx_logic.c index dec8d8c04..dd50b486e 100644 --- a/src/codegen_new/codegen_ops_mmx_logic.c +++ b/src/codegen_new/codegen_ops_mmx_logic.c @@ -16,7 +16,6 @@ #include "codegen_ops_mmx_logic.h" #include "codegen_ops_helpers.h" -extern void codegen_print_mmx(const char* str, uint32_t fetchdat); uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) {