Merge remote-tracking branch 'upstream/master' into feature/ich2

This commit is contained in:
Jasmine Iwanek
2023-08-09 15:41:54 -04:00
130 changed files with 7069 additions and 2971 deletions

21
.gitattributes vendored Normal file
View File

@@ -0,0 +1,21 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.cc text
*.cpp text
*.h text
*.hpp text
*.rc text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.ico binary
*.png binary
*.jpg binary
*.dat

View File

@@ -115,7 +115,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v1
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >-
@@ -234,7 +234,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v1
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >
@@ -341,7 +341,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v1
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >-
@@ -427,7 +427,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v1
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >-

View File

@@ -918,11 +918,15 @@ pc_init_modules(void)
#ifdef USE_DYNAREC
# if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(0);
if (__builtin_available(macOS 11.0, *)) {
pthread_jit_write_protect_np(0);
}
# endif
codegen_init();
# if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(1);
if (__builtin_available(macOS 11.0, *)) {
pthread_jit_write_protect_np(1);
}
# endif
#endif
@@ -1048,19 +1052,9 @@ pc_reset_hard_init(void)
/* Initialize the actual machine and its basic modules. */
machine_init();
/* Reset and reconfigure the serial ports. */
serial_standalone_init();
serial_passthrough_init();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();
/* Reset any ISA RTC cards. */
isartc_reset();
fdc_card_init();
fdd_reset();
/* Reset some basic devices. */
speaker_init();
shadowbios = 0;
/*
* Once the machine has been initialized, all that remains
@@ -1071,10 +1065,20 @@ pc_reset_hard_init(void)
* that will be a call to device_reset_all() later !
*/
/* Reset some basic devices. */
speaker_init();
if (joystick_type)
gameport_update_joystick_type();
/* Reset and reconfigure the Sound Card layer. */
sound_card_reset();
/* Reset and reconfigure the Network Card layer. */
network_reset();
lpt_devices_init();
shadowbios = 0;
/* Reset and reconfigure the serial ports. */
serial_standalone_init();
serial_passthrough_init();
/*
* Reset the mouse, this will attach it to any port needed.
@@ -1084,25 +1088,26 @@ pc_reset_hard_init(void)
/* Reset the Hard Disk Controller module. */
hdc_reset();
fdc_card_init();
fdd_reset();
/* Reset the CD-ROM Controller module. */
cdrom_interface_reset();
/* Reset and reconfigure the SCSI layer. */
scsi_card_init();
cdrom_hard_reset();
scsi_disk_hard_reset();
zip_hard_reset();
cdrom_hard_reset();
mo_hard_reset();
scsi_disk_hard_reset();
zip_hard_reset();
/* Reset and reconfigure the Network Card layer. */
network_reset();
if (joystick_type)
gameport_update_joystick_type();
/* Reset any ISA RTC cards. */
isartc_reset();
ui_sb_update_panes();
@@ -1119,6 +1124,11 @@ pc_reset_hard_init(void)
if (postcard_enabled)
device_add(&postcard_device);
if (IS_ARCH(machine, MACHINE_BUS_PCI)) {
pci_register_cards();
device_reset_all(DEVICE_PCI);
}
/* Reset the CPU module. */
resetx86();
dma_reset();
@@ -1273,10 +1283,12 @@ pc_run(void)
startblit();
cpu_exec(cpu_s->rspeed / 100);
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
// if (gdbstub_step == GDBSTUB_EXEC)
if (gdbstub_step == GDBSTUB_EXEC) {
#endif
#if 0
mouse_process();
if (!mouse_timed)
mouse_process();
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
}
#endif
joystick_process();
endblit();

View File

@@ -138,29 +138,29 @@ acpi_update_irq(acpi_t *dev)
if (sci_level) {
if (dev->irq_mode == 1)
pci_set_irq(dev->slot, dev->irq_pin);
pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state);
else if (dev->irq_mode == 2)
pci_set_mirq(5, dev->mirq_is_level);
pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state);
else
pci_set_mirq(0xf0 | dev->irq_line, 1);
pci_set_mirq(PCI_DIRQ_BASE | dev->irq_line, 1, &dev->irq_state);
} else {
if (dev->irq_mode == 1)
pci_clear_irq(dev->slot, dev->irq_pin);
pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state);
else if (dev->irq_mode == 2)
pci_clear_mirq(5, dev->mirq_is_level);
pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state);
else
pci_clear_mirq(0xf0 | dev->irq_line, 1);
pci_clear_mirq(PCI_DIRQ_BASE | dev->irq_line, 1, &dev->irq_state);
}
acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS));
}
void
acpi_raise_smi(void *priv, int do_smi)
static void
acpi_do_raise_smi(void *priv, int do_smi, int is_apm)
{
acpi_t *dev = (acpi_t *) priv;
if (dev->regs.glbctl & 0x01) {
if (is_apm || (dev->regs.glbctl & 0x01)) {
if ((dev->vendor == VEN_VIA) || (dev->vendor == VEN_VIA_596B)) {
if (!dev->regs.smi_lock || !dev->regs.smi_active) {
if (do_smi)
@@ -183,6 +183,12 @@ acpi_raise_smi(void *priv, int do_smi)
smi_raise();
}
void
acpi_raise_smi(void *priv, int do_smi)
{
acpi_do_raise_smi(priv, do_smi, 0);
}
static uint32_t
acpi_reg_read_common_regs(UNUSED(int size), uint16_t addr, void *priv)
{
@@ -1841,7 +1847,7 @@ acpi_apm_out(uint16_t port, uint8_t val, void *priv)
else if (dev->vendor == VEN_INTEL_ICH2)
if (dev->apm->do_smi)
dev->regs.smi_sts |= 0x00000020;
acpi_raise_smi(dev, dev->apm->do_smi);
acpi_do_raise_smi(dev, dev->apm->do_smi, 1);
} else
dev->apm->stat = val;
}
@@ -1916,6 +1922,9 @@ acpi_reset(void *priv)
dev->regs.pmsts |= 0x8000;
acpi_rtc_status = 0;
acpi_update_irq(dev);
dev->irq_state = 0;
}
static void

View File

@@ -46,11 +46,12 @@
typedef struct ali_1435_t {
uint8_t index;
uint8_t cfg_locked;
uint8_t pci_slot;
uint8_t pad;
uint8_t regs[16];
uint8_t pci_regs[256];
} ali1435_t;
#define ENABLE_ALI1435_LOG 1
#ifdef ENABLE_ALI1435_LOG
int ali1435_do_log = ENABLE_ALI1435_LOG;
@@ -190,24 +191,20 @@ ali1435_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0x23:
#if 0
#ifdef ENABLE_ALI1435_LOG
if (dev->index != 0x03)
ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val);
#endif
#endif
if (dev->index == 0x03)
dev->cfg_locked = (val != 0x69);
#ifdef ENABLE_ALI1435_LOG
else
ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val);
#endif
if (!dev->cfg_locked) {
pclog("M1435: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
/* PCI Mechanism select? */
case 0x00:
dev->regs[dev->index] = val;
pclog("PMC = %i\n", val != 0xc8);
pci_set_pmc(val != 0xc8);
ali1435_log("PMC = %i\n", val != 0xc8);
pci_key_write(((val & 0xc8) == 0xc8) ? 0xf0 : 0x00);
break;
/* ???? */
@@ -253,8 +250,6 @@ ali1435_reset(void *priv)
dev->regs[0x00] = 0xff;
pci_set_pmc(0);
dev->cfg_locked = 1;
memset(dev->pci_regs, 0, 256);
@@ -298,17 +293,10 @@ ali1435_init(UNUSED(const device_t *info))
*/
io_sethandler(0x0022, 0x0002, ali1435_read, NULL, NULL, ali1435_write, NULL, NULL, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev, &dev->pci_slot);
ali1435_reset(dev);
#if 0
pci_set_irq_level(PCI_INTA, 0);
pci_set_irq_level(PCI_INTB, 0);
pci_set_irq_level(PCI_INTC, 0);
pci_set_irq_level(PCI_INTD, 0);
#endif
return dev;
}

View File

@@ -622,7 +622,7 @@ ali1489_init(UNUSED(const device_t *info))
io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev);
/* Dummy M1489 PCI device */
dev->pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev, &dev->pci_slot);
device_add(&ide_pci_2ch_device);

View File

@@ -35,6 +35,11 @@
#include <86box/chipset.h>
typedef struct ali1531_t {
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t pci_conf[256];
smram_t *smram;
@@ -374,7 +379,7 @@ ali1531_init(UNUSED(const device_t *info))
ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t));
memset(dev, 0, sizeof(ali1531_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot);
dev->smram = smram_add();

View File

@@ -35,6 +35,11 @@
#include <86box/chipset.h>
typedef struct ali1541_t {
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t pci_conf[256];
smram_t *smram;
@@ -641,7 +646,7 @@ ali1541_init(UNUSED(const device_t *info))
ali1541_t *dev = (ali1541_t *) malloc(sizeof(ali1541_t));
memset(dev, 0, sizeof(ali1541_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev, &dev->pci_slot);
dev->smram = smram_add();

View File

@@ -47,6 +47,7 @@
#include <86box/chipset.h>
typedef struct ali1543_t {
uint8_t mirq_states[8];
uint8_t pci_conf[256];
uint8_t pmu_conf[256];
uint8_t usb_conf[256];
@@ -1474,12 +1475,12 @@ ali7101_read(int func, int addr, void *priv)
static void
ali5237_usb_update_interrupt(usb_t* usb, void *priv)
{
const ali1543_t *dev = (ali1543_t *) priv;
ali1543_t *dev = (ali1543_t *) priv;
if (usb->irq_level)
pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10));
pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]);
else
pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10));
pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10), &dev->mirq_states[4]);
}
static void
@@ -1595,16 +1596,16 @@ ali1543_init(const device_t *info)
memset(dev, 0, sizeof(ali1543_t));
/* Device 02: M1533 Southbridge */
dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev, &dev->pci_slot);
/* Device 0B: M5229 IDE Controller*/
dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, ali5229_read, ali5229_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, ali5229_read, ali5229_write, dev, &dev->ide_slot);
/* Device 0C: M7101 Power Managment Controller */
dev->pmu_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_PMU, ali7101_read, ali7101_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE_PMU, ali7101_read, ali7101_write, dev, &dev->pmu_slot);
/* Device 0F: M5237 USB */
dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, ali5237_read, ali5237_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, ali5237_read, ali5237_write, dev, &dev->usb_slot);
/* ACPI */
dev->acpi = device_add(&acpi_ali_device);

View File

@@ -36,6 +36,11 @@
#include <86box/chipset.h>
typedef struct ali1621_t {
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t pci_conf[256];
smram_t *smram[2];
@@ -671,7 +676,7 @@ ali1621_init(UNUSED(const device_t *info))
ali1621_t *dev = (ali1621_t *) malloc(sizeof(ali1621_t));
memset(dev, 0, sizeof(ali1621_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev, &dev->pci_slot);
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();

View File

@@ -122,6 +122,9 @@
typedef struct ims8848_t {
uint8_t idx;
uint8_t access_data;
uint8_t pci_slot;
uint8_t pad;
uint8_t regs[256];
uint8_t pci_conf[256];
@@ -392,7 +395,7 @@ ims8848_init(UNUSED(const device_t *info))
PCI Device 0: IMS 8849 Dummy for compatibility reasons
*/
io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev, &dev->pci_slot);
dev->smram = smram_add();
smram_set_separate_smram(1);

View File

@@ -52,6 +52,9 @@
typedef struct i420ex_t {
uint8_t has_ide;
uint8_t smram_locked;
uint8_t pci_slot;
uint8_t pad;
uint8_t regs[256];
uint16_t timer_base;
@@ -534,7 +537,7 @@ i420ex_init(const device_t *info)
dev->smram = smram_add();
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev, &dev->pci_slot);
dev->has_ide = info->local;

View File

@@ -57,6 +57,9 @@ typedef struct i4x0_t {
uint8_t max_drb;
uint8_t drb_unit;
uint8_t drb_default;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t regs[256];
uint8_t regs_locked[256];
uint8_t mem_state[256];
@@ -1241,12 +1244,12 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
switch (dev->type) {
case INTEL_440FX:
regs[0x93] = (val & 0x0f);
trc_write(0x0093, val & 0x06, NULL);
pci_write(0x0cf9, val & 0x06, NULL);
break;
case INTEL_440LX:
case INTEL_440EX:
regs[0x93] = (val & 0x0e);
trc_write(0x0093, val & 0x06, NULL);
pci_write(0x0cf9, val & 0x06, NULL);
break;
default:
break;
@@ -1518,7 +1521,7 @@ i4x0_read(int func, int addr, void *priv)
/* Special behavior for 440FX register 0x93 which is basically TRC in PCI space
with the addition of bits 3 and 0. */
if ((func == 0) && (addr == 0x93) && ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)))
ret = (ret & 0xf9) | (trc_read(0x0093, NULL) & 0x06);
ret = (ret & 0xf9) | (pci_read(0x0cf9, NULL) & 0x06);
}
return ret;
@@ -1910,7 +1913,7 @@ i4x0_init(const device_t *info)
(dev->type >= INTEL_440BX) ? 0x38 : 0x00, dev);
}
pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev, &dev->pci_slot);
if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02)) {
device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device);

View File

@@ -62,11 +62,15 @@ i450kx_log(const char *fmt, ...)
typedef struct i450kx_t {
smram_t *smram[2];
uint8_t bus_index;
uint8_t pb_slot;
uint8_t mc_slot;
uint8_t pad;
uint8_t pb_pci_conf[256];
uint8_t mc_pci_conf[256];
uint8_t mem_state[2][256];
uint8_t bus_index;
uint8_t mem_state[2][256];
} i450kx_t;
static void
@@ -801,8 +805,8 @@ i450kx_init(UNUSED(const device_t *info))
{
i450kx_t *dev = (i450kx_t *) malloc(sizeof(i450kx_t));
memset(dev, 0, sizeof(i450kx_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19h: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_AGPBRIDGE, mc_read, mc_write, dev); /* Device 14h: Intel 450KX Memory Controller MC */
pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();

View File

@@ -66,7 +66,7 @@ typedef struct _piix_ {
uint8_t max_func;
uint8_t pci_slot;
uint8_t no_mirq0;
uint8_t pad;
uint8_t usb_irq_state;
uint8_t regs[4][256];
uint8_t readout_regs[256];
uint8_t board_config[2];
@@ -1446,12 +1446,12 @@ piix_fast_off_count(void *priv)
static void
piix_usb_update_interrupt(usb_t* usb, void *priv)
{
const piix_t *dev = (piix_t *) priv;
piix_t *dev = (piix_t *) priv;
if (usb->irq_level)
pci_set_irq(dev->pci_slot, PCI_INTD);
pci_set_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state);
else
pci_clear_irq(dev->pci_slot, PCI_INTD);
pci_clear_irq(dev->pci_slot, PCI_INTD, &dev->usb_irq_state);
}
static void
@@ -1574,7 +1574,7 @@ piix_init(const device_t *info)
dev->no_mirq0 = (info->local >> 12) & 0x0f;
dev->func0_id = info->local >> 16;
dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev, &dev->pci_slot);
piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot);
piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot);

View File

@@ -37,6 +37,10 @@
typedef struct sio_t {
uint8_t id;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t regs[256];
uint16_t timer_base;
@@ -507,7 +511,7 @@ sio_init(const device_t *info)
sio_t *dev = (sio_t *) malloc(sizeof(sio_t));
memset(dev, 0, sizeof(sio_t));
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot);
dev->id = info->local;

View File

@@ -43,6 +43,10 @@
typedef struct opti822_t {
uint8_t irq_convert;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pci_regs[256];
} opti822_t;
@@ -393,7 +397,7 @@ opti822_init(UNUSED(const device_t *info))
opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t));
memset(dev, 0, sizeof(opti822_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot);
opti822_reset(dev);

View File

@@ -155,6 +155,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
switch (dev->idx) {
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
@@ -213,12 +214,14 @@ opti895_read(uint16_t addr, void *priv)
ret = dev->regs[dev->idx];
break;
case 0x24:
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
ret = dev->regs[dev->idx];
if (dev->idx == 0xe0)
ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green;
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[addr - 0xe1];

View File

@@ -66,13 +66,15 @@ sis_5511_log(const char *fmt, ...)
#endif
typedef struct sis_5511_t {
uint8_t pci_conf[256];
uint8_t pci_conf_sb[2][256];
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t regs[16];
int nb_pci_slot;
int sb_pci_slot;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[2][256];
sff8038i_t *ide_drive[2];
smram_t *smram;
@@ -713,8 +715,8 @@ sis_5511_reset(void *priv)
dev->pci_conf_sb[1][0x0a] = 1;
dev->pci_conf_sb[1][0x0b] = 1;
dev->pci_conf_sb[1][0x0e] = 0x80;
sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot);
sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot);
sff_set_slot(dev->ide_drive[0], dev->sb_slot);
sff_set_slot(dev->ide_drive[1], dev->sb_slot);
sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE);
sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8);
}
@@ -734,8 +736,8 @@ sis_5511_init(UNUSED(const device_t *info))
sis_5511_t *dev = (sis_5511_t *) malloc(sizeof(sis_5511_t));
memset(dev, 0, sizeof(sis_5511_t));
dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev); /* Device 0: SiS 5511 */
dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev); /* Device 1: SiS 5513 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot); /* Device 0: SiS 5511 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot); /* Device 1: SiS 5513 */
io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev); /* Ports 22h-23h: SiS 5513 ISA */
/* MIRQ */

View File

@@ -75,12 +75,14 @@ sis_5571_log(const char *fmt, ...)
#endif
typedef struct sis_5571_t {
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t usb_irq_state;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[3][256];
int nb_pci_slot;
int sb_pci_slot;
port_92_t *port_92;
sff8038i_t *ide_drive[2];
smram_t *smram;
@@ -670,7 +672,7 @@ pci_isa_bridge_read(int func, int addr, void *priv)
static void
sis_5571_usb_update_interrupt(usb_t* usb, void* priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
sis_5571_t *dev = (sis_5571_t *) priv;
if (dev->pci_conf_sb[0][0x68] & 0x80) {
/* TODO: Is the normal PCI interrupt inhibited when USB IRQ remapping is enabled? */
@@ -691,9 +693,9 @@ sis_5571_usb_update_interrupt(usb_t* usb, void* priv)
}
} else {
if (usb->irq_level)
pci_set_irq(dev->sb_pci_slot, PCI_INTA);
pci_set_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state);
else
pci_clear_irq(dev->sb_pci_slot, PCI_INTA);
pci_clear_irq(dev->sb_slot, PCI_INTA, &dev->usb_irq_state);
}
}
@@ -739,8 +741,8 @@ sis_5571_reset(void *priv)
dev->pci_conf_sb[1][0x0b] = 0x01;
dev->pci_conf_sb[1][0x0e] = 0x80;
dev->pci_conf_sb[1][0x4a] = 0x06;
sff_set_slot(dev->ide_drive[0], dev->sb_pci_slot);
sff_set_slot(dev->ide_drive[1], dev->sb_pci_slot);
sff_set_slot(dev->ide_drive[0], dev->sb_slot);
sff_set_slot(dev->ide_drive[1], dev->sb_slot);
sff_bus_master_reset(dev->ide_drive[0], BUS_MASTER_BASE);
sff_bus_master_reset(dev->ide_drive[1], BUS_MASTER_BASE + 8);
@@ -773,8 +775,8 @@ sis_5571_init(UNUSED(const device_t *info))
sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t));
memset(dev, 0x00, sizeof(sis_5571_t));
dev->nb_pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev);
dev->sb_pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot);
pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot);
/* MIRQ */
pci_enable_mirq(0);

View File

@@ -45,9 +45,13 @@
typedef struct sis_85c496_t {
uint8_t cur_reg;
uint8_t rmsmiblk_count;
uint8_t pci_slot;
uint8_t pad;
#ifndef USE_DRB_HACK
uint8_t drb_default;
uint8_t drb_bits;
uint8_t pad0;
uint8_t pad1;
#endif
uint8_t regs[127];
uint8_t pci_conf[256];
@@ -648,7 +652,7 @@ static void
dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */
dev->pci_conf[0xd1] = 0xff;
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c49x_pci_read, sis_85c49x_pci_write, dev, &dev->pci_slot);
#if 0
sis_85c497_isa_reset(dev);

View File

@@ -59,6 +59,10 @@ sis_85c50x_log(const char *fmt, ...)
typedef struct sis_85c50x_t {
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[256];
uint8_t regs[256];
@@ -426,10 +430,10 @@ sis_85c50x_init(UNUSED(const device_t *info))
memset(dev, 0x00, sizeof(sis_85c50x_t));
/* 501/502 (Northbridge) */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot);
/* 503 (Southbridge) */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev, &dev->sb_slot);
io_sethandler(0x0022, 0x0002, sis_85c50x_isa_read, NULL, NULL, sis_85c50x_isa_write, NULL, NULL, dev);
dev->smram[0] = smram_add();

View File

@@ -45,6 +45,11 @@
#define STPC_CLIENT 0x100e55cc
typedef struct stpc_t {
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t ide_slot;
uint8_t usb_slot;
uint32_t local;
/* Main registers (port 22h/23h) */
@@ -54,19 +59,19 @@ typedef struct stpc_t {
/* Host bus interface */
uint16_t host_base;
uint8_t host_offset;
uint8_t usb_irq_state;
uint8_t host_regs[256];
/* Local bus */
uint16_t localbus_base;
uint8_t localbus_offset;
uint8_t pad0;
uint8_t localbus_regs[256];
/* PCI devices */
uint8_t pci_conf[4][256];
smram_t *smram;
usb_t *usb;
int ide_slot;
int usb_slot;
sff8038i_t *bm[2];
/* Miscellaneous */
@@ -896,12 +901,12 @@ stpc_setup(stpc_t *dev)
static void
stpc_usb_update_interrupt(usb_t* usb, void* priv)
{
const stpc_t *dev = (stpc_t *) priv;
stpc_t *dev = (stpc_t *) priv;
if (usb->irq_level)
pci_set_irq(dev->usb_slot, PCI_INTA);
pci_set_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state);
else
pci_clear_irq(dev->usb_slot, PCI_INTA);
pci_clear_irq(dev->usb_slot, PCI_INTA, &dev->usb_irq_state);
}
static void
@@ -926,16 +931,16 @@ stpc_init(const device_t *info)
dev->local = info->local;
pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev);
dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev, &dev->nb_slot);
pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev, &dev->sb_slot);
if (dev->local == STPC_ATLAS) {
dev->usb_params.smi_handle = NULL;
dev->usb_params.update_interrupt = stpc_usb_update_interrupt;
dev->usb_params.parent_priv = dev;
dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_ide_read, stpc_ide_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE_IDE, stpc_ide_read, stpc_ide_write, dev, &dev->ide_slot);
dev->usb = device_add_parameters(&usb_device, &dev->usb_params);
dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_usb_read, stpc_usb_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE_USB, stpc_usb_read, stpc_usb_write, dev, &dev->usb_slot);
}
dev->bm[0] = device_add_inst(&sff8038i_device, 1);

View File

@@ -121,8 +121,13 @@ umc_8886_log(const char *fmt, ...)
#define SB_ID dev->sb_id
typedef struct umc_8886_t {
uint8_t max_func; /* Last function number */
uint8_t pci_conf_sb[2][256]; /* PCI Registers */
uint8_t max_func; /* Last function number */
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pci_conf_sb[2][256]; /* PCI Registers */
uint16_t sb_id; /* Southbridge Revision */
int has_ide; /* Check if Southbridge Revision is AF or F */
} umc_8886_t;
@@ -371,7 +376,7 @@ umc_8886_init(const device_t *info)
memset(dev, 0, sizeof(umc_8886_t));
dev->has_ide = !!(info->local == 0x886a);
pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev); /* Device 12: UMC 8886xx */
pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */
/* Add IDE if UM8886AF variant */
if (HAS_IDE)

View File

@@ -146,6 +146,8 @@ typedef struct hb4_t {
uint8_t shadow;
uint8_t shadow_read;
uint8_t shadow_write;
uint8_t pci_slot;
uint8_t pci_conf[256]; /* PCI Registers */
int mem_state[9];
smram_t *smram[3]; /* SMRAM Handlers */
@@ -393,7 +395,7 @@ hb4_init(UNUSED(const device_t *info))
hb4_t *dev = (hb4_t *) malloc(sizeof(hb4_t));
memset(dev, 0, sizeof(hb4_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev); /* Device 10: UMC 8881x */
pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev, &dev->pci_slot); /* Device 10: UMC 8881x */
/* Port 92 */
device_add(&port_92_pci_device);

View File

@@ -45,10 +45,15 @@
#define VIA_8601 0x86010500
typedef struct via_apollo_t {
uint32_t id;
uint8_t drb_unit;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pci_conf[256];
uint32_t id;
smram_t *smram;
agpgart_t *agpgart;
} via_apollo_t;
@@ -715,7 +720,7 @@ via_apollo_init(const device_t *info)
if (dev->id != VIA_8601)
apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev, &dev->pci_slot);
dev->id = info->local;

View File

@@ -117,9 +117,10 @@ typedef struct {
} pipc_io_trap_t;
typedef struct _pipc_ {
uint32_t local;
uint8_t max_func;
uint8_t max_pcs;
uint8_t pci_slot;
uint8_t pad;
uint8_t pci_isa_regs[256];
uint8_t ide_regs[256];
@@ -129,10 +130,11 @@ typedef struct _pipc_ {
uint8_t fmnmi_regs[4];
uint8_t fmnmi_status;
uint32_t local;
sff8038i_t *bm[2];
nvr_t *nvr;
int nvr_enabled;
int slot;
ddma_t *ddma;
smbus_piix4_t *smbus;
usb_t *usb[2];
@@ -1094,7 +1096,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv)
case 0x47:
if (val & 0x01)
trc_write(0x0047, (val & 0x80) ? 0x06 : 0x04, NULL);
pci_write(0x0cf9, (val & 0x80) ? 0x06 : 0x04, NULL);
pic_set_shadow(!!(val & 0x10));
pic_elcr_io_handler(!!(val & 0x20));
dev->pci_isa_regs[0x47] = val & 0xfe;
@@ -1620,6 +1622,14 @@ pipc_reset(void *priv)
pipc_write(0, 0x44, 0x00, priv);
pipc_write(0, 0x77, 0x00, priv);
sff_set_slot(dev->bm[0], dev->pci_slot);
sff_set_slot(dev->bm[1], dev->pci_slot);
if (dev->local >= VIA_PIPC_686A)
ac97_via_set_slot(dev->ac97, dev->pci_slot, PCI_INTC);
if (dev->acpi)
acpi_set_slot(dev->acpi, dev->pci_slot);
}
static void *
@@ -1631,16 +1641,14 @@ pipc_init(const device_t *info)
pipc_log("PIPC: init()\n");
dev->local = info->local;
dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, pipc_read, pipc_write, dev, &dev->pci_slot);
dev->bm[0] = device_add_inst(&sff8038i_device, 1);
sff_set_slot(dev->bm[0], dev->slot);
sff_set_irq_mode(dev->bm[0], 0, 0);
sff_set_irq_mode(dev->bm[0], 1, 0);
sff_set_irq_pin(dev->bm[0], PCI_INTA);
dev->bm[1] = device_add_inst(&sff8038i_device, 2);
sff_set_slot(dev->bm[1], dev->slot);
sff_set_irq_mode(dev->bm[1], 0, 0);
sff_set_irq_mode(dev->bm[1], 1, 0);
sff_set_irq_pin(dev->bm[1], PCI_INTA);
@@ -1665,7 +1673,6 @@ pipc_init(const device_t *info)
dev->usb[1] = device_add_inst(&usb_device, 2);
dev->ac97 = device_add(&ac97_via_device);
ac97_via_set_slot(dev->ac97, dev->slot, PCI_INTC);
dev->sb = device_add_inst(&sb_pro_compat_device, 2);
sound_add_handler(pipc_sb_get_buffer, dev);
@@ -1695,7 +1702,6 @@ pipc_init(const device_t *info)
dev->ddma = device_add(&ddma_device);
if (dev->acpi) {
acpi_set_slot(dev->acpi, dev->slot);
acpi_set_nvr(dev->acpi, dev->nvr);
acpi_init_gporeg(dev->acpi, 0xff, 0xbf, 0xff, 0x7f);

View File

@@ -32,6 +32,10 @@
typedef struct vt82c505_t {
uint8_t index;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pci_conf[256];
} vt82c505_t;
@@ -203,7 +207,7 @@ vt82c505_init(UNUSED(const device_t *info))
vt82c505_t *dev = (vt82c505_t *) malloc(sizeof(vt82c505_t));
memset(dev, 0, sizeof(vt82c505_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, vt82c505_read, vt82c505_write, dev, &dev->pci_slot);
dev->pci_conf[0x00] = 0x06;
dev->pci_conf[0x01] = 0x11;

View File

@@ -1,5 +1,6 @@
#if defined __aarch64__ || defined _M_ARM64
# include <inttypes.h>
# include <stdint.h>
# include <86box/86box.h>
# include "cpu.h"
@@ -662,7 +663,7 @@ host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data)
} else if (!(imm_data & 0xfffffffffffff000ull)) {
codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
} else
fatal("CMNX_IMM %08x\n", imm_data);
fatal("CMNX_IMM %016" PRIx64 "\n", imm_data);
}
void
@@ -683,7 +684,7 @@ host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data)
} else if (!(imm_data & 0xfffffffffffff000ull)) {
codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
} else
fatal("CMPX_IMM %08x\n", imm_data);
fatal("CMPX_IMM %08llx\n", imm_data);
}
void

View File

@@ -553,7 +553,7 @@ codegen_FABS(codeblock_t *block, uop_t *uop)
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) {
host_arm64_FABS_D(block, dest_reg, src_reg_a);
} else
fatal("codegen_FABS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
fatal("codegen_FABS %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
@@ -566,7 +566,7 @@ codegen_FCHS(codeblock_t *block, uop_t *uop)
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) {
host_arm64_FNEG_D(block, dest_reg, src_reg_a);
} else
fatal("codegen_FCHS %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
fatal("codegen_FCHS %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
@@ -579,7 +579,7 @@ codegen_FSQRT(codeblock_t *block, uop_t *uop)
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a)) {
host_arm64_FSQRT_D(block, dest_reg, src_reg_a);
} else
fatal("codegen_FSQRT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
fatal("codegen_FSQRT %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
return 0;
}
@@ -1548,7 +1548,7 @@ codegen_PF2ID(codeblock_t *block, uop_t *uop)
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) {
host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a);
} else
fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real);
fatal("PF2ID %02x\n", uop->dest_reg_a_real);
return 0;
}
@@ -1655,7 +1655,7 @@ codegen_PFRCP(codeblock_t *block, uop_t *uop)
host_arm64_FDIV_S(block, dest_reg, REG_V_TEMP, src_reg_a);
host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0);
} else
fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real);
fatal("PFRCP %02x\n", uop->dest_reg_a_real);
return 0;
}
@@ -1672,7 +1672,7 @@ codegen_PFRSQRT(codeblock_t *block, uop_t *uop)
host_arm64_FDIV_S(block, dest_reg, dest_reg, REG_V_TEMP);
host_arm64_DUP_V2S(block, dest_reg, dest_reg, 0);
} else
fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real);
fatal("PFRSQRT %02x\n", uop->dest_reg_a_real);
return 0;
}
@@ -1698,7 +1698,7 @@ codegen_PI2FD(codeblock_t *block, uop_t *uop)
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a)) {
host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a);
} else
fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real);
fatal("PI2FD %02x\n", uop->dest_reg_a_real);
return 0;
}

View File

@@ -1,3 +1,4 @@
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -305,7 +306,7 @@ add_to_block_list(codeblock_t *block)
#ifndef RELEASE_BUILD
if (!block->page_mask)
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask, block->page_mask2);
fatal("add_to_block_list - mask = 0 %" PRIx64 " %" PRIx64 "\n", block->page_mask, block->page_mask2);
#endif
if (block_prev_nr) {

View File

@@ -12,17 +12,22 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include <86box/io.h>
#include <86box/nmi.h>
#include <86box/mem.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/machine.h>
#include <86box/gdbstub.h>
#ifndef OPS_286_386
#define OPS_286_386
#endif
#include "386_common.h"
#ifdef USE_NEW_DYNAREC
# include "codegen.h"
@@ -33,54 +38,7 @@
extern int codegen_flags_changed;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int timetolive;
uint16_t oldcs;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t oxpc;
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg _oldds;
#if 1
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
#else
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x2x */
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x3x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
#endif
static int fpu_cycles = 0;
#ifdef ENABLE_386_LOG
int x386_do_log = ENABLE_386_LOG;
@@ -103,9 +61,6 @@ x386_log(const char *fmt, ...)
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
#include "x86_flags.h"
/*
#define getbytef() \
((uint8_t) (fetchdat)); \
cpu_state.pc++
@@ -118,11 +73,141 @@ x386_log(const char *fmt, ...)
#define getword2f() \
((uint16_t) (fetchdat >> 8)); \
cpu_state.pc += 2
*/
#define OP_TABLE(name) ops_##name
static __inline void
fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (cpu_rm == 4) {
uint8_t sib = rmdat >> 8;
#if 0
switch (cpu_mod) {
case 0:
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
cpu_state.pc++;
break;
case 1:
cpu_state.pc++;
cpu_state.eaaddr = ((uint32_t) (int8_t) getbyte()) + cpu_state.regs[sib & 7].l;
break;
case 2:
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
cpu_state.pc += 5;
break;
}
/*SIB byte present*/
if ((sib & 7) == 5 && !cpu_mod)
cpu_state.eaaddr = getlong();
else if ((sib & 6) == 4 && !cpu_state.ssegs) {
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
} else {
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
if (cpu_mod) {
if (cpu_rm == 5 && !cpu_state.ssegs) {
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1) {
cpu_state.eaaddr += ((uint32_t) (int8_t) (rmdat >> 8));
cpu_state.pc++;
} else {
cpu_state.eaaddr += getlong();
}
} else if (cpu_rm == 5) {
cpu_state.eaaddr = getlong();
}
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
uint32_t addr = easeg + cpu_state.eaaddr;
if (readlookup2[addr >> 12] != (uintptr_t) -1)
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) -1)
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
}
}
static __inline void
fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (!cpu_mod && cpu_rm == 6) {
cpu_state.eaaddr = getword();
} else {
switch (cpu_mod) {
case 0:
cpu_state.eaaddr = 0;
break;
case 1:
cpu_state.eaaddr = (uint16_t) (int8_t) (rmdat >> 8);
cpu_state.pc++;
break;
case 2:
cpu_state.eaaddr = getword();
break;
}
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) {
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
uint32_t addr = easeg + cpu_state.eaaddr;
if (readlookup2[addr >> 12] != (uintptr_t) -1)
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != (uintptr_t) -1)
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
}
}
#define fetch_ea_16(rmdat) \
cpu_state.pc++; \
cpu_mod = (rmdat >> 6) & 3; \
cpu_reg = (rmdat >> 3) & 7; \
cpu_rm = rmdat & 7; \
if (cpu_mod != 3) { \
fetch_ea_16_long(rmdat); \
if (cpu_state.abrt) \
return 1; \
}
#define fetch_ea_32(rmdat) \
cpu_state.pc++; \
cpu_mod = (rmdat >> 6) & 3; \
cpu_reg = (rmdat >> 3) & 7; \
cpu_rm = rmdat & 7; \
if (cpu_mod != 3) { \
fetch_ea_32_long(rmdat); \
} \
if (cpu_state.abrt) \
return 1
#include "x86_flags.h"
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
do { \
if (cpu_prefetch_cycles) \
prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); \
} while (0)
#define PREFETCH_PREFIX() \
do { \
if (cpu_prefetch_cycles) \
prefetch_prefixes++; \
} while (0)
#define PREFETCH_FLUSH() prefetch_flush()
#ifndef FPU_CYCLES
#define FPU_CYCLES
#endif
#define OP_TABLE(name) ops_2386_##name
# define CLOCK_CYCLES(c) \
{ \
if (fpu_cycles > 0) { \
@@ -137,18 +222,13 @@ x386_log(const char *fmt, ...)
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
# define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
#else
# define CLOCK_CYCLES(c) cycles -= (c)
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
# define CONCURRENCY_CYCLES(c)
#endif
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "x86_ops.h"
#include "386_ops.h"
void
exec386(int cycs)
exec386_2386(int cycs)
{
int vector, tempi, cycdiff, oldcyc;
int cycle_period, ins_cycles;
@@ -184,7 +264,7 @@ exec386(int cycs)
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
if (in_smm)
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
x386_2386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;

View File

@@ -67,6 +67,38 @@ int soft_reset_mask = 0;
int smi_latched = 0;
int smm_in_hlt = 0, smi_block = 0;
int prefetch_prefixes = 0;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int timetolive;
uint16_t oldcs;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t oxpc;
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg _oldds;
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
uint32_t addr64, addr64_2;
uint32_t addr64a[8], addr64a_2[8];
@@ -321,6 +353,77 @@ x386_common_log(const char *fmt, ...)
# define x386_common_log(fmt, ...)
#endif
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
- Cycles used for non-instruction memory accesses are counted and subtracted
from the total cycles taken
- Any remaining cycles are used to refill the prefetch queue.
Note that this is only used for 286 / 386 systems. It is disabled when the
internal cache on 486+ CPUs is enabled.
*/
static int prefetch_bytes = 0;
void
prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
{
int mem_cycles = reads * cpu_cycles_read + reads_l * cpu_cycles_read_l + writes * cpu_cycles_write + writes_l * cpu_cycles_write_l;
if (instr_cycles < mem_cycles)
instr_cycles = mem_cycles;
prefetch_bytes -= prefetch_prefixes;
prefetch_bytes -= bytes;
if (modrm != -1) {
if (ea32) {
if ((modrm & 7) == 4) {
if ((modrm & 0x700) == 0x500)
prefetch_bytes -= 5;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 5;
} else {
if ((modrm & 0xc7) == 0x05)
prefetch_bytes -= 4;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes--;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 4;
}
} else {
if ((modrm & 0xc7) == 0x06)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) != 0xc0)
prefetch_bytes -= ((modrm & 0xc0) >> 6);
}
}
/* Fill up prefetch queue */
while (prefetch_bytes < 0) {
prefetch_bytes += cpu_prefetch_width;
cycles -= cpu_prefetch_cycles;
}
/* Subtract cycles used for memory access by instruction */
instr_cycles -= mem_cycles;
while (instr_cycles >= cpu_prefetch_cycles) {
prefetch_bytes += cpu_prefetch_width;
instr_cycles -= cpu_prefetch_cycles;
}
prefetch_prefixes = 0;
if (prefetch_bytes > 16)
prefetch_bytes = 16;
}
void
prefetch_flush(void)
{
prefetch_bytes = 0;
}
static __inline void
set_stack32(int s)
{

View File

@@ -22,6 +22,34 @@
#include <stddef.h>
#include <inttypes.h>
#ifdef OPS_286_386
#define readmemb_n(s,a,b) readmembl_no_mmut_2386((s)+(a),b)
#define readmemw_n(s,a,b) readmemwl_no_mmut_2386((s)+(a),b)
#define readmeml_n(s,a,b) readmemll_no_mmut_2386((s)+(a),b)
#define readmemb(s,a) readmembl_2386((s)+(a))
#define readmemw(s,a) readmemwl_2386((s)+(a))
#define readmeml(s,a) readmemll_2386((s)+(a))
#define readmemq(s,a) readmemql_2386((s)+(a))
#define writememb_n(s,a,b,v) writemembl_no_mmut_2386((s)+(a),b,v)
#define writememw_n(s,a,b,v) writememwl_no_mmut_2386((s)+(a),b,v)
#define writememl_n(s,a,b,v) writememll_no_mmut_2386((s)+(a),b,v)
#define writememb(s,a,v) writemembl_2386((s)+(a),v)
#define writememw(s,a,v) writememwl_2386((s)+(a),v)
#define writememl(s,a,v) writememll_2386((s)+(a),v)
#define writememq(s,a,v) writememql_2386((s)+(a),v)
#define do_mmut_rb(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 0)
#define do_mmut_rw(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 0)
#define do_mmut_rl(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 0)
#define do_mmut_rb2(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 0)
#define do_mmut_rw2(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 0)
#define do_mmut_rl2(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 0)
#define do_mmut_wb(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 1)
#define do_mmut_ww(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 1)
#define do_mmut_wl(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 1)
#else
#define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
#define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
#define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
@@ -97,6 +125,7 @@
#define do_mmut_wl(s, a, b) \
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
do_mmutranslate((s) + (a), b, 4, 1)
#endif
int checkio(uint32_t port, int mask);
@@ -191,6 +220,23 @@ int checkio(uint32_t port, int mask);
return 1; \
}
#ifdef OPS_286_386
/* TODO: Introduce functions to read exec. */
static __inline uint8_t fastreadb(uint32_t a)
{
return readmembl(a);
}
static __inline uint16_t fastreadw(uint32_t a)
{
return readmemwl(a);
}
static __inline uint32_t fastreadl(uint32_t a)
{
return readmemll(a);
}
#else
static __inline uint8_t
fastreadb(uint32_t a)
{
@@ -266,6 +312,7 @@ fastreadl(uint32_t a)
val |= (fastreadw(a + 2) << 16);
return val;
}
#endif
static __inline void *
get_ram_ptr(uint32_t a)
@@ -288,6 +335,37 @@ get_ram_ptr(uint32_t a)
extern int opcode_length[256];
#ifdef OPS_286_386
static __inline uint16_t
fastreadw_fetch(uint32_t a)
{
uint16_t val;
if ((a & 0xFFF) > 0xFFE) {
val = fastreadb(a);
if (opcode_length[val & 0xff] > 1)
val |= (fastreadb(a + 1) << 8);
return val;
}
return readmemwl(a);
}
static __inline uint32_t
fastreadl_fetch(uint32_t a)
{
uint32_t val;
if ((a & 0xFFF) > 0xFFC) {
val = fastreadw_fetch(a);
if (opcode_length[val & 0xff] > 2)
val |= (fastreadw(a + 2) << 16);
return val;
}
return readmemll(a);
}
#else
static __inline uint16_t
fastreadw_fetch(uint32_t a)
{
@@ -342,6 +420,7 @@ fastreadl_fetch(uint32_t a)
val |= (fastreadw(a + 2) << 16);
return val;
}
#endif
static __inline uint8_t
getbyte(void)
@@ -371,6 +450,67 @@ getquad(void)
return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32);
}
#ifdef OPS_286_386
static __inline uint8_t geteab(void)
{
if (cpu_mod == 3)
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
return readmemb(easeg, cpu_state.eaaddr);
}
static __inline uint16_t geteaw(void)
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].w;
return readmemw(easeg, cpu_state.eaaddr);
}
static __inline uint32_t geteal(void)
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].l;
return readmeml(easeg, cpu_state.eaaddr);
}
static __inline uint64_t geteaq(void)
{
return readmemq(easeg, cpu_state.eaaddr);
}
static __inline uint8_t geteab_mem(void)
{
return readmemb(easeg,cpu_state.eaaddr);
}
static __inline uint16_t geteaw_mem(void)
{
return readmemw(easeg,cpu_state.eaaddr);
}
static __inline uint32_t geteal_mem(void)
{
return readmeml(easeg,cpu_state.eaaddr);
}
static __inline int seteaq_cwc(void)
{
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
return 0;
}
static __inline void seteaq(uint64_t v)
{
if (seteaq_cwc())
return;
writememql(easeg + cpu_state.eaaddr, v);
}
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); writemembl_2386(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); writememwl_2386(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); writememll_2386(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
#define seteab_mem(v) writemembl_2386(easeg+cpu_state.eaaddr,v);
#define seteaw_mem(v) writememwl_2386(easeg+cpu_state.eaaddr,v);
#define seteal_mem(v) writememll_2386(easeg+cpu_state.eaaddr,v);
#else
static __inline uint8_t
geteab(void)
{
@@ -489,6 +629,7 @@ seteaq(uint64_t v)
*eal_w = v; \
else \
writememll(easeg + cpu_state.eaaddr, v);
#endif
#define getbytef() \
((uint8_t) (fetchdat)); \

View File

@@ -183,78 +183,6 @@ fetch_ea_16_long(uint32_t rmdat)
#include "x86_flags.h"
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
- Cycles used for non-instruction memory accesses are counted and subtracted
from the total cycles taken
- Any remaining cycles are used to refill the prefetch queue.
Note that this is only used for 286 / 386 systems. It is disabled when the
internal cache on 486+ CPUs is enabled.
*/
static int prefetch_bytes = 0;
static int prefetch_prefixes = 0;
static void
prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
{
int mem_cycles = reads * cpu_cycles_read + reads_l * cpu_cycles_read_l + writes * cpu_cycles_write + writes_l * cpu_cycles_write_l;
if (instr_cycles < mem_cycles)
instr_cycles = mem_cycles;
prefetch_bytes -= prefetch_prefixes;
prefetch_bytes -= bytes;
if (modrm != -1) {
if (ea32) {
if ((modrm & 7) == 4) {
if ((modrm & 0x700) == 0x500)
prefetch_bytes -= 5;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 5;
} else {
if ((modrm & 0xc7) == 0x05)
prefetch_bytes -= 4;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes--;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 4;
}
} else {
if ((modrm & 0xc7) == 0x06)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) != 0xc0)
prefetch_bytes -= ((modrm & 0xc0) >> 6);
}
}
/* Fill up prefetch queue */
while (prefetch_bytes < 0) {
prefetch_bytes += cpu_prefetch_width;
cycles -= cpu_prefetch_cycles;
}
/* Subtract cycles used for memory access by instruction */
instr_cycles -= mem_cycles;
while (instr_cycles >= cpu_prefetch_cycles) {
prefetch_bytes += cpu_prefetch_width;
instr_cycles -= cpu_prefetch_cycles;
}
prefetch_prefixes = 0;
if (prefetch_bytes > 16)
prefetch_bytes = 16;
}
static void
prefetch_flush(void)
{
prefetch_bytes = 0;
}
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
do { \
if (cpu_prefetch_cycles) \
@@ -556,7 +484,9 @@ exec386_dynarec_dyn(void)
x86_was_reset = 0;
# if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(0);
if (__builtin_available(macOS 11.0, *)) {
pthread_jit_write_protect_np(0);
}
# endif
codegen_block_start_recompile(block);
codegen_in_recompile = 1;
@@ -640,7 +570,9 @@ exec386_dynarec_dyn(void)
codegen_in_recompile = 0;
# if defined(__APPLE__) && defined(__aarch64__)
pthread_jit_write_protect_np(1);
if (__builtin_available(macOS 11.0, *)) {
pthread_jit_write_protect_np(1);
}
# endif
} else if (!cpu_state.abrt) {
/* Mark block but do not recompile */
@@ -858,3 +790,156 @@ exec386_dynarec(int cycs)
}
}
#endif
void
exec386(int cycs)
{
int vector, tempi, cycdiff, oldcyc;
int cycle_period, ins_cycles;
uint32_t addr;
cycles += cycs;
while (cycles > 0) {
cycle_period = (timer_target - (uint32_t) tsc) + 1;
x86_was_reset = 0;
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
oldcpl = CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
#ifndef USE_NEW_DYNAREC
x86_was_reset = 0;
#endif
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
if (in_smm)
x386_dynarec_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
#ifdef ENABLE_386_LOG
else if (in_smm)
x386_dynarec_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc);
#endif
#ifndef USE_NEW_DYNAREC
if (!use32)
cpu_state.pc &= 0xffff;
#endif
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
#ifndef USE_NEW_DYNAREC
CS = oldcs;
#endif
cpu_state.pc = cpu_state.oldpc;
x386_dynarec_log("Double fault\n");
pmodeint(8, 0);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_LOG
x386_dynarec_log("Triple fault - reset\n");
#endif
}
}
} else if (trap) {
flags_rebuild();
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
dr[6] |= 0x4000;
x86_int(1);
}
if (smi_line)
enter_smm_check(0);
else if (nmi && nmi_enable && nmi_mask) {
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
x86_int(2);
nmi_enable = 0;
#ifdef OLD_NMI_BEHAVIOR
if (nmi_auto_clear) {
nmi_auto_clear = 0;
nmi = 0;
}
#else
nmi = 0;
#endif
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) {
vector = picinterrupt();
if (vector != -1) {
flags_rebuild();
if (msw & 1)
pmodeint(vector, 0);
else {
writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags);
writememw(ss, (SP - 4) & 0xFFFF, CS);
writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
SP -= 6;
addr = (vector << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = readmemw(0, addr);
loadcs(readmemw(0, addr + 2));
}
}
}
ins_cycles -= cycles;
tsc += ins_cycles;
cycdiff = oldcyc - cycles;
if (timetolive) {
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline();
#ifdef USE_GDBSTUB
if (gdbstub_instruction())
return;
#endif
}
}
}

View File

@@ -179,7 +179,9 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_bcd.h"
#include "x86_ops_bit.h"
#include "x86_ops_bitscan.h"
#ifndef OPS_286_386
#include "x86_ops_cyrix.h"
#endif
#include "x86_ops_flag.h"
#include "x86_ops_fpu.h"
#include "x86_ops_inc_dec.h"
@@ -188,6 +190,7 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_jump.h"
#include "x86_ops_misc.h"
#include "x87_ops.h"
#ifndef OPS_286_386
#include "x86_ops_i686.h"
#include "x86_ops_mmx.h"
#include "x86_ops_mmx_arith.h"
@@ -196,30 +199,44 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_mmx_mov.h"
#include "x86_ops_mmx_pack.h"
#include "x86_ops_mmx_shift.h"
#endif
#include "x86_ops_mov.h"
#include "x86_ops_mov_ctrl.h"
#include "x86_ops_mov_seg.h"
#include "x86_ops_movx.h"
#ifndef OPS_286_386
#include "x86_ops_msr.h"
#endif
#include "x86_ops_mul.h"
#include "x86_ops_pmode.h"
#include "x86_ops_prefix.h"
#ifdef IS_DYNAREC
# include "x86_ops_rep_dyn.h"
#else
#ifdef OPS_286_386
# include "x86_ops_rep_2386.h"
#else
# include "x86_ops_rep.h"
#endif
#endif
#include "x86_ops_ret.h"
#include "x86_ops_set.h"
#include "x86_ops_stack.h"
#ifdef OPS_286_386
#include "x86_ops_string_2386.h"
#else
#include "x86_ops_string.h"
#endif
#include "x86_ops_xchg.h"
#include "x86_ops_call.h"
#include "x86_ops_shift.h"
#ifndef OPS_286_386
#include "x86_ops_amd.h"
#include "x86_ops_3dnow.h"
#endif
#include <time.h>
#ifndef OPS_286_386
static int
opVPCEXT(uint32_t fetchdat)
{
@@ -331,7 +348,50 @@ opVPCEXT(uint32_t fetchdat)
return 1;
}
#endif
#ifdef OPS_286_386
static int op0F_w_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
return x86_2386_opcodes_0f[opcode](fetchdat >> 8);
}
static int op0F_l_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
return x86_2386_opcodes_0f[opcode | 0x100](fetchdat >> 8);
}
static int op0F_w_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
return x86_2386_opcodes_0f[opcode | 0x200](fetchdat >> 8);
}
static int op0F_l_a32(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
fopcode = opcode;
cpu_state.pc++;
PREFETCH_PREFIX();
return x86_2386_opcodes_0f[opcode | 0x300](fetchdat >> 8);
}
#else
static int
op0F_w_a16(uint32_t fetchdat)
{
@@ -376,6 +436,7 @@ op0F_l_a32(uint32_t fetchdat)
return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8);
}
#endif
const OpFn OP_TABLE(186_0f)[1024] = {
// clang-format off
@@ -745,6 +806,7 @@ const OpFn OP_TABLE(486_0f)[1024] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(c486_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
@@ -928,6 +990,7 @@ const OpFn OP_TABLE(stpc_0f)[1024] = {
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
// clang-format on
};
#endif
const OpFn OP_TABLE(ibm486_0f)[1024] = {
// clang-format off
@@ -1021,6 +1084,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(winchip_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
@@ -2036,6 +2100,7 @@ const OpFn OP_TABLE(pentium2d_0f)[1024] = {
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
// clang-format on
};
#endif
const OpFn OP_TABLE(186)[1024] = {
// clang-format off

View File

@@ -15,6 +15,7 @@
* Copyright 2023 gloriouscow.
* Copyright 2023 Miran Grca.
*/
#include <inttypes.h>
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
@@ -76,7 +77,11 @@ void
queue_set_size(size_t size)
{
if (size > QUEUE_MAX)
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
fatal("Requested prefetch queue of %zu bytes is too big\n", size);
#else
fatal("Requested prefetch queue of %i bytes is too big\n", size);
#endif
queue.size = size;
}

View File

@@ -18,6 +18,7 @@
* Copyright 2016-2020 Miran Grca.
* Copyright 2018-2021 Fred N. van Kempen.
*/
#include <inttypes.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
@@ -125,6 +126,27 @@ const OpFn *x86_opcodes_REPE;
const OpFn *x86_opcodes_REPNE;
const OpFn *x86_opcodes_3DNOW;
const OpFn *x86_2386_opcodes;
const OpFn *x86_2386_opcodes_0f;
const OpFn *x86_2386_opcodes_d8_a16;
const OpFn *x86_2386_opcodes_d8_a32;
const OpFn *x86_2386_opcodes_d9_a16;
const OpFn *x86_2386_opcodes_d9_a32;
const OpFn *x86_2386_opcodes_da_a16;
const OpFn *x86_2386_opcodes_da_a32;
const OpFn *x86_2386_opcodes_db_a16;
const OpFn *x86_2386_opcodes_db_a32;
const OpFn *x86_2386_opcodes_dc_a16;
const OpFn *x86_2386_opcodes_dc_a32;
const OpFn *x86_2386_opcodes_dd_a16;
const OpFn *x86_2386_opcodes_dd_a32;
const OpFn *x86_2386_opcodes_de_a16;
const OpFn *x86_2386_opcodes_de_a32;
const OpFn *x86_2386_opcodes_df_a16;
const OpFn *x86_2386_opcodes_df_a32;
const OpFn *x86_2386_opcodes_REPE;
const OpFn *x86_2386_opcodes_REPNE;
uint16_t cpu_fast_off_count;
uint16_t cpu_fast_off_val;
uint16_t temp_seg_data[4] = { 0, 0, 0, 0 };
@@ -535,9 +557,12 @@ cpu_set(void)
#else
x86_setopcodes(ops_386, ops_386_0f);
#endif
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
x86_opcodes_3DNOW = ops_3DNOW;
x86_setopcodes_2386(ops_2386_386, ops_2386_386_0f);
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
x86_2386_opcodes_REPE = ops_2386_REPE;
x86_2386_opcodes_REPNE = ops_2386_REPNE;
x86_opcodes_3DNOW = ops_3DNOW;
#ifdef USE_DYNAREC
x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE;
@@ -599,6 +624,23 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_sf_fpu_de_a32;
x86_opcodes_df_a16 = ops_sf_fpu_df_a16;
x86_opcodes_df_a32 = ops_sf_fpu_df_a32;
x86_2386_opcodes_d8_a16 = ops_2386_sf_fpu_d8_a16;
x86_2386_opcodes_d8_a32 = ops_2386_sf_fpu_d8_a32;
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_df_a32;
} else {
x86_opcodes_d8_a16 = ops_fpu_d8_a16;
x86_opcodes_d8_a32 = ops_fpu_d8_a32;
@@ -616,6 +658,23 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_fpu_de_a32;
x86_opcodes_df_a16 = ops_fpu_df_a16;
x86_opcodes_df_a32 = ops_fpu_df_a32;
x86_2386_opcodes_d8_a16 = ops_2386_fpu_d8_a16;
x86_2386_opcodes_d8_a32 = ops_2386_fpu_d8_a32;
x86_2386_opcodes_d9_a16 = ops_2386_fpu_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_fpu_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_fpu_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_fpu_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_fpu_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_fpu_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_fpu_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_fpu_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_fpu_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_fpu_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_fpu_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_fpu_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_fpu_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_fpu_df_a32;
}
} else {
#ifdef USE_DYNAREC
@@ -652,6 +711,23 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_nofpu_a32;
x86_opcodes_df_a16 = ops_nofpu_a16;
x86_opcodes_df_a32 = ops_nofpu_a32;
x86_2386_opcodes_d8_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_d8_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_d9_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_d9_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_da_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_da_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_db_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_db_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_dc_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_dc_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_dd_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_dd_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_de_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_de_a32 = ops_2386_nofpu_a32;
x86_2386_opcodes_df_a16 = ops_2386_nofpu_a16;
x86_2386_opcodes_df_a32 = ops_2386_nofpu_a32;
}
#ifdef USE_DYNAREC
@@ -678,6 +754,7 @@ cpu_set(void)
#else
x86_setopcodes(ops_186, ops_186_0f);
#endif
x86_setopcodes_2386(ops_2386_186, ops_2386_186_0f);
break;
case CPU_286:
@@ -686,6 +763,7 @@ cpu_set(void)
#else
x86_setopcodes(ops_286, ops_286_0f);
#endif
x86_setopcodes_2386(ops_2386_286, ops_2386_286_0f);
if (fpu_type == FPU_287) {
#ifdef USE_DYNAREC
@@ -736,6 +814,21 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32;
x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16;
x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32;
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32;
} else {
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
@@ -751,6 +844,21 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32;
}
}
@@ -793,11 +901,13 @@ cpu_set(void)
#else
x86_setopcodes(ops_386, ops_ibm486_0f);
#endif
x86_setopcodes_2386(ops_2386_386, ops_2386_ibm486_0f);
cpu_features = CPU_FEATURE_MSR;
/* FALLTHROUGH */
case CPU_386SX:
case CPU_386DX:
if (fpu_type == FPU_287) { /* In case we get Deskpro 386 emulation */
/* In case we get Deskpro 386 emulation */
if (fpu_type == FPU_287) {
#ifdef USE_DYNAREC
if (fpu_softfloat) {
x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16;
@@ -846,6 +956,21 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32;
x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16;
x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32;
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32;
} else {
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
@@ -861,6 +986,21 @@ cpu_set(void)
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16;
x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32;
x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16;
x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32;
x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16;
x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32;
x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16;
x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32;
x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16;
x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32;
x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16;
x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32;
x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16;
x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32;
}
}
@@ -907,6 +1047,7 @@ cpu_set(void)
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
timing_rr = 1; /* register dest - register src */
timing_rm = 3; /* register dest - memory src */
@@ -946,6 +1087,7 @@ cpu_set(void)
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
timing_rr = 1; /* register dest - register src */
timing_rm = 3; /* register dest - memory src */
@@ -998,6 +1140,7 @@ cpu_set(void)
#else
x86_setopcodes(ops_386, ops_486_0f);
#endif
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
timing_rr = 1; /* register dest - register src */
timing_rm = 2; /* register dest - memory src */
@@ -1611,7 +1754,7 @@ cpu_set(void)
break;
default:
fatal("cpu_set : unknown CPU type %llu\n", cpu_s->cpu_type);
fatal("cpu_set : unknown CPU type %" PRIu64 "\n", cpu_s->cpu_type);
}
switch (fpu_type) {
@@ -1643,9 +1786,13 @@ cpu_set(void)
cpu_exec = exec386_dynarec;
else
#endif
cpu_exec = exec386;
/* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */
if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC))
cpu_exec = exec386;
else
cpu_exec = exec386_2386;
} else if (cpu_s->cpu_type >= CPU_286)
cpu_exec = exec386;
cpu_exec = exec386_2386;
else
cpu_exec = execx86;
mmx_init();
@@ -2753,6 +2900,10 @@ amd_k_invalid_rdmsr:
EAX = msr.ecx1a0 & 0xffffffff;
EDX = msr.ecx1a0 >> 32;
break;
case 0x1d9:
EAX = msr.debug_ctl & 0xffffffff;
EDX = msr.debug_ctl >> 32;
break;
case 0x1e0:
EAX = msr.ecx1e0 & 0xffffffff;
EDX = msr.ecx1e0 >> 32;
@@ -3202,6 +3353,9 @@ amd_k_invalid_wrmsr:
case 0x1a0:
msr.ecx1a0 = EAX | ((uint64_t) EDX << 32);
break;
case 0x1d9:
msr.debug_ctl = EAX | ((uint64_t) EDX << 32);
break;
case 0x1e0:
msr.ecx1e0 = EAX | ((uint64_t) EDX << 32);
break;
@@ -3440,6 +3594,13 @@ x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f)
}
#endif
void
x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f)
{
x86_2386_opcodes = opcodes;
x86_2386_opcodes_0f = opcodes_0f;
}
void
cpu_update_waitstates(void)
{

View File

@@ -280,10 +280,11 @@ typedef struct {
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t ecx186; /* 0x00000186, 0x00000187 */
uint64_t ecx187; /* 0x00000186, 0x00000187 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */
uint64_t ecx1e0; /* 0x000001e0 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
@@ -399,8 +400,13 @@ typedef struct {
MMX_REG MM[8];
#ifdef USE_NEW_DYNAREC
# if defined(__APPLE__) && defined(__aarch64__)
uint64_t old_fp_control;
uint64_t new_fp_control;
# else
uint32_t old_fp_control;
uint32_t new_fp_control;
# endif
# if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
uint16_t old_fp_control2;
uint16_t new_fp_control2;
@@ -753,6 +759,7 @@ extern void execx86(int cycs);
extern void enter_smm(int in_hlt);
extern void enter_smm_check(int in_hlt);
extern void leave_smm(void);
extern void exec386_2386(int cycs);
extern void exec386(int cycs);
extern void exec386_dynarec(int cycs);
extern int idivl(int32_t val);
@@ -836,6 +843,8 @@ extern int hlt_reset_pending;
extern cyrix_t cyrix;
extern int prefetch_prefixes;
extern uint8_t use_custom_nmi_vector;
extern uint32_t custom_nmi_vector;
@@ -860,5 +869,8 @@ extern MMX_REG *MMP[8];
extern uint16_t *MMEP[8];
extern void mmx_init(void);
extern void prefetch_flush(void);
extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32);
#endif /*EMU_CPU_H*/

View File

@@ -44,9 +44,9 @@
typedef int (*OpFn)(uint32_t fetchdat);
#ifdef USE_DYNAREC
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f,
const OpFn *dynarec_opcodes,
const OpFn *dynarec_opcodes_0f);
extern void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f,
const OpFn *dynarec_opcodes,
const OpFn *dynarec_opcodes_0f);
extern const OpFn *x86_dynarec_opcodes;
extern const OpFn *x86_dynarec_opcodes_0f;
@@ -187,7 +187,7 @@ extern const OpFn dynarec_ops_REPNE[1024];
extern const OpFn dynarec_ops_3DNOW[256];
extern const OpFn dynarec_ops_3DNOWE[256];
#else
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
extern void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
#endif
@@ -330,6 +330,113 @@ extern const OpFn ops_REPNE[1024];
extern const OpFn ops_3DNOW[256];
extern const OpFn ops_3DNOWE[256];
extern void x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f);
extern const OpFn *x86_2386_opcodes;
extern const OpFn *x86_2386_opcodes_0f;
extern const OpFn *x86_2386_opcodes_d8_a16;
extern const OpFn *x86_2386_opcodes_d8_a32;
extern const OpFn *x86_2386_opcodes_d9_a16;
extern const OpFn *x86_2386_opcodes_d9_a32;
extern const OpFn *x86_2386_opcodes_da_a16;
extern const OpFn *x86_2386_opcodes_da_a32;
extern const OpFn *x86_2386_opcodes_db_a16;
extern const OpFn *x86_2386_opcodes_db_a32;
extern const OpFn *x86_2386_opcodes_dc_a16;
extern const OpFn *x86_2386_opcodes_dc_a32;
extern const OpFn *x86_2386_opcodes_dd_a16;
extern const OpFn *x86_2386_opcodes_dd_a32;
extern const OpFn *x86_2386_opcodes_de_a16;
extern const OpFn *x86_2386_opcodes_de_a32;
extern const OpFn *x86_2386_opcodes_df_a16;
extern const OpFn *x86_2386_opcodes_df_a32;
extern const OpFn *x86_2386_opcodes_REPE;
extern const OpFn *x86_2386_opcodes_REPNE;
extern const OpFn ops_2386_186[1024];
extern const OpFn ops_2386_186_0f[1024];
extern const OpFn ops_2386_286[1024];
extern const OpFn ops_2386_286_0f[1024];
extern const OpFn ops_2386_386[1024];
extern const OpFn ops_2386_386_0f[1024];
extern const OpFn ops_2386_486_0f[1024];
extern const OpFn ops_2386_ibm486_0f[1024];
extern const OpFn ops_2386_sf_fpu_287_d9_a16[256];
extern const OpFn ops_2386_sf_fpu_287_d9_a32[256];
extern const OpFn ops_2386_sf_fpu_287_da_a16[256];
extern const OpFn ops_2386_sf_fpu_287_da_a32[256];
extern const OpFn ops_2386_sf_fpu_287_db_a16[256];
extern const OpFn ops_2386_sf_fpu_287_db_a32[256];
extern const OpFn ops_2386_sf_fpu_287_dc_a16[32];
extern const OpFn ops_2386_sf_fpu_287_dc_a32[32];
extern const OpFn ops_2386_sf_fpu_287_dd_a16[256];
extern const OpFn ops_2386_sf_fpu_287_dd_a32[256];
extern const OpFn ops_2386_sf_fpu_287_de_a16[256];
extern const OpFn ops_2386_sf_fpu_287_de_a32[256];
extern const OpFn ops_2386_sf_fpu_287_df_a16[256];
extern const OpFn ops_2386_sf_fpu_287_df_a32[256];
extern const OpFn ops_2386_sf_fpu_d8_a16[32];
extern const OpFn ops_2386_sf_fpu_d8_a32[32];
extern const OpFn ops_2386_sf_fpu_d9_a16[256];
extern const OpFn ops_2386_sf_fpu_d9_a32[256];
extern const OpFn ops_2386_sf_fpu_da_a16[256];
extern const OpFn ops_2386_sf_fpu_da_a32[256];
extern const OpFn ops_2386_sf_fpu_db_a16[256];
extern const OpFn ops_2386_sf_fpu_db_a32[256];
extern const OpFn ops_2386_sf_fpu_dc_a16[32];
extern const OpFn ops_2386_sf_fpu_dc_a32[32];
extern const OpFn ops_2386_sf_fpu_dd_a16[256];
extern const OpFn ops_2386_sf_fpu_dd_a32[256];
extern const OpFn ops_2386_sf_fpu_de_a16[256];
extern const OpFn ops_2386_sf_fpu_de_a32[256];
extern const OpFn ops_2386_sf_fpu_df_a16[256];
extern const OpFn ops_2386_sf_fpu_df_a32[256];
extern const OpFn ops_2386_fpu_287_d9_a16[256];
extern const OpFn ops_2386_fpu_287_d9_a32[256];
extern const OpFn ops_2386_fpu_287_da_a16[256];
extern const OpFn ops_2386_fpu_287_da_a32[256];
extern const OpFn ops_2386_fpu_287_db_a16[256];
extern const OpFn ops_2386_fpu_287_db_a32[256];
extern const OpFn ops_2386_fpu_287_dc_a16[32];
extern const OpFn ops_2386_fpu_287_dc_a32[32];
extern const OpFn ops_2386_fpu_287_dd_a16[256];
extern const OpFn ops_2386_fpu_287_dd_a32[256];
extern const OpFn ops_2386_fpu_287_de_a16[256];
extern const OpFn ops_2386_fpu_287_de_a32[256];
extern const OpFn ops_2386_fpu_287_df_a16[256];
extern const OpFn ops_2386_fpu_287_df_a32[256];
extern const OpFn ops_2386_fpu_d8_a16[32];
extern const OpFn ops_2386_fpu_d8_a32[32];
extern const OpFn ops_2386_fpu_d9_a16[256];
extern const OpFn ops_2386_fpu_d9_a32[256];
extern const OpFn ops_2386_fpu_da_a16[256];
extern const OpFn ops_2386_fpu_da_a32[256];
extern const OpFn ops_2386_fpu_db_a16[256];
extern const OpFn ops_2386_fpu_db_a32[256];
extern const OpFn ops_2386_fpu_dc_a16[32];
extern const OpFn ops_2386_fpu_dc_a32[32];
extern const OpFn ops_2386_fpu_dd_a16[256];
extern const OpFn ops_2386_fpu_dd_a32[256];
extern const OpFn ops_2386_fpu_de_a16[256];
extern const OpFn ops_2386_fpu_de_a32[256];
extern const OpFn ops_2386_fpu_df_a16[256];
extern const OpFn ops_2386_fpu_df_a32[256];
extern const OpFn ops_2386_nofpu_a16[256];
extern const OpFn ops_2386_nofpu_a32[256];
extern const OpFn ops_2386_REPE[1024];
extern const OpFn ops_2386_REPNE[1024];
extern const OpFn ops_2386_3DNOW[256];
#define C0 (1 << 8)
#define C1 (1 << 9)
#define C2 (1 << 10)

View File

@@ -115,6 +115,7 @@ opCMPXCHG_l_a32(uint32_t fetchdat)
return 0;
}
#ifndef OPS_286_386
static int
opCMPXCHG8B_a16(uint32_t fetchdat)
{
@@ -169,6 +170,7 @@ opCMPXCHG8B_a32(uint32_t fetchdat)
cycles -= (cpu_mod == 3) ? 6 : 10;
return 0;
}
#endif
/* dest = eab, src = r8 */
static int

View File

@@ -769,6 +769,7 @@ opMOV_r_l_a32(uint32_t fetchdat)
return 0;
}
#ifndef OPS_286_386
#define opCMOV(condition) \
static int opCMOV##condition##_w_a16(uint32_t fetchdat) \
{ \
@@ -865,3 +866,4 @@ opCMOV(NL)
opCMOV(LE)
opCMOV(NLE)
// clang-format on
#endif

863
src/cpu/x86_ops_rep_2386.h Normal file
View File

@@ -0,0 +1,863 @@
#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \
static int opREP_INSB_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
addr64 = 0x00000000; \
\
if (CNT_REG > 0) { \
uint8_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX, 1); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \
high_page = 0; \
do_mmut_wb(es, DEST_REG, &addr64); \
if (cpu_state.abrt) \
return 1; \
temp = inb(DX); \
writememb_n(es, DEST_REG, addr64, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) \
DEST_REG--; \
else \
DEST_REG++; \
CNT_REG--; \
cycles -= 15; \
reads++; \
writes++; \
total_cycles += 15; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_INSW_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
addr64a[0] = addr64a[1] = 0x00000000; \
\
if (CNT_REG > 0) { \
uint16_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX, 2); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
high_page = 0; \
do_mmut_ww(es, DEST_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
temp = inw(DX); \
writememw_n(es, DEST_REG, addr64a, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 2; \
else \
DEST_REG += 2; \
CNT_REG--; \
cycles -= 15; \
reads++; \
writes++; \
total_cycles += 15; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_INSL_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
\
if (CNT_REG > 0) { \
uint32_t temp; \
\
SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX, 4); \
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
high_page = 0; \
do_mmut_wl(es, DEST_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
temp = inl(DX); \
writememl_n(es, DEST_REG, addr64a, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 4; \
else \
DEST_REG += 4; \
CNT_REG--; \
cycles -= 15; \
reads++; \
writes++; \
total_cycles += 15; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
\
static int opREP_OUTSB_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
if (CNT_REG > 0) { \
uint8_t temp; \
SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX, 1); \
outb(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG--; \
else \
SRC_REG++; \
CNT_REG--; \
cycles -= 14; \
reads++; \
writes++; \
total_cycles += 14; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_OUTSW_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
if (CNT_REG > 0) { \
uint16_t temp; \
SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX, 2); \
outw(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 2; \
else \
SRC_REG += 2; \
CNT_REG--; \
cycles -= 14; \
reads++; \
writes++; \
total_cycles += 14; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_OUTSL_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
\
if (CNT_REG > 0) { \
uint32_t temp; \
SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
check_io_perm(DX, 4); \
outl(DX, temp); \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 4; \
else \
SRC_REG += 4; \
CNT_REG--; \
cycles -= 14; \
reads++; \
writes++; \
total_cycles += 14; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
\
static int opREP_MOVSB_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
addr64 = addr64_2 = 0x00000000; \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) { \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
} \
while (CNT_REG > 0) { \
uint8_t temp; \
\
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
high_page = 0; \
do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \
if (cpu_state.abrt) \
break; \
do_mmut_wb(es, DEST_REG, &addr64_2); \
if (cpu_state.abrt) \
break; \
temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \
if (cpu_state.abrt) \
return 1; \
writememb_n(es, DEST_REG, addr64_2, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG--; \
SRC_REG--; \
} else { \
DEST_REG++; \
SRC_REG++; \
} \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
reads++; \
writes++; \
total_cycles += is486 ? 3 : 4; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_MOVSW_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
addr64a[0] = addr64a[1] = 0x00000000; \
addr64a_2[0] = addr64a_2[1] = 0x00000000; \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) { \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
} \
while (CNT_REG > 0) { \
uint16_t temp; \
\
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
high_page = 0; \
do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
break; \
do_mmut_ww(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
break; \
temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
writememw_n(es, DEST_REG, addr64a_2, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG -= 2; \
SRC_REG -= 2; \
} else { \
DEST_REG += 2; \
SRC_REG += 2; \
} \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
reads++; \
writes++; \
total_cycles += is486 ? 3 : 4; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_MOVSL_##size(uint32_t fetchdat) \
{ \
int reads = 0, writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) { \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
} \
while (CNT_REG > 0) { \
uint32_t temp; \
\
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
high_page = 0; \
do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
break; \
do_mmut_wl(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
break; \
temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
writememl_n(es, DEST_REG, addr64a_2, temp); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG -= 4; \
SRC_REG -= 4; \
} else { \
DEST_REG += 4; \
SRC_REG += 4; \
} \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
reads++; \
writes++; \
total_cycles += is486 ? 3 : 4; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
\
static int opREP_STOSB_##size(uint32_t fetchdat) \
{ \
int writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) { \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
writememb(es, DEST_REG, AL); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
DEST_REG--; \
else \
DEST_REG++; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_STOSW_##size(uint32_t fetchdat) \
{ \
int writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) { \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
writememw(es, DEST_REG, AX); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 2; \
else \
DEST_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_STOSL_##size(uint32_t fetchdat) \
{ \
int writes = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) { \
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
writememl(es, DEST_REG, EAX); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 4; \
else \
DEST_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
\
static int opREP_LODSB_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) { \
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \
AL = readmemb(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
SRC_REG--; \
else \
SRC_REG++; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_LODSW_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) { \
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
AX = readmemw(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 2; \
else \
SRC_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_LODSL_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
if (CNT_REG > 0) \
SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) { \
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); \
if (cpu_state.abrt) \
return 1; \
if (cpu_state.flags & D_FLAG) \
SRC_REG -= 4; \
else \
SRC_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; \
total_cycles += is486 ? 4 : 5; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
if (CNT_REG > 0) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
}
#define CHEK_READ(a, b, c)
#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \
static int opREP_CMPSB_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
\
addr64 = addr64_2 = 0x00000000; \
\
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) { \
uint8_t temp, temp2; \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_READ(&cpu_state.seg_es); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \
high_page = uncached = 0; \
do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \
if (cpu_state.abrt) \
return 1; \
do_mmut_rb2(es, DEST_REG, &addr64_2); \
if (cpu_state.abrt) \
return 1; \
temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \
if (cpu_state.abrt) \
return 1; \
temp2 = readmemb_n(es, DEST_REG, addr64_2); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG--; \
SRC_REG--; \
} else { \
DEST_REG++; \
SRC_REG++; \
} \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; \
total_cycles += is486 ? 7 : 9; \
setsub8(temp, temp2); \
tempz = (ZF_SET()) ? 1 : 0; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_CMPSW_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
\
addr64a[0] = addr64a[1] = 0x00000000; \
addr64a_2[0] = addr64a_2[1] = 0x00000000; \
\
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) { \
uint16_t temp, temp2; \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_READ(&cpu_state.seg_es); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
high_page = uncached = 0; \
do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
do_mmut_rw2(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
return 1; \
temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
temp2 = readmemw_n(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG -= 2; \
SRC_REG -= 2; \
} else { \
DEST_REG += 2; \
SRC_REG += 2; \
} \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; \
total_cycles += is486 ? 7 : 9; \
setsub16(temp, temp2); \
tempz = (ZF_SET()) ? 1 : 0; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_CMPSL_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
\
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \
\
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) { \
uint32_t temp, temp2; \
SEG_CHECK_READ(cpu_state.ea_seg); \
SEG_CHECK_READ(&cpu_state.seg_es); \
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
high_page = uncached = 0; \
do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
do_mmut_rl2(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
return 1; \
temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
if (cpu_state.abrt) \
return 1; \
temp2 = readmeml_n(es, DEST_REG, addr64a_2); \
if (cpu_state.abrt) \
return 1; \
\
if (cpu_state.flags & D_FLAG) { \
DEST_REG -= 4; \
SRC_REG -= 4; \
} else { \
DEST_REG += 4; \
SRC_REG += 4; \
} \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; \
total_cycles += is486 ? 7 : 9; \
setsub32(temp, temp2); \
tempz = (ZF_SET()) ? 1 : 0; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
\
static int opREP_SCASB_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) { \
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
uint8_t temp = readmemb(es, DEST_REG); \
if (cpu_state.abrt) \
break; \
setsub8(AL, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
if (cpu_state.flags & D_FLAG) \
DEST_REG--; \
else \
DEST_REG++; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; \
total_cycles += is486 ? 5 : 8; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_SCASW_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) { \
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
uint16_t temp = readmemw(es, DEST_REG); \
if (cpu_state.abrt) \
break; \
setsub16(AX, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 2; \
else \
DEST_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; \
total_cycles += is486 ? 5 : 8; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
} \
static int opREP_SCASL_##size(uint32_t fetchdat) \
{ \
int reads = 0, total_cycles = 0, tempz; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) { \
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
uint32_t temp = readmeml(es, DEST_REG); \
if (cpu_state.abrt) \
break; \
setsub32(EAX, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
if (cpu_state.flags & D_FLAG) \
DEST_REG -= 4; \
else \
DEST_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; \
total_cycles += is486 ? 5 : 8; \
if (cycles < cycles_end) \
break; \
} \
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
if ((CNT_REG > 0) && (FV == tempz)) { \
CPU_BLOCK_END(); \
cpu_state.pc = cpu_state.oldpc; \
return 1; \
} \
return cpu_state.abrt; \
}
REP_OPS(a16, CX, SI, DI)
REP_OPS(a32, ECX, ESI, EDI)
REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0)
REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1)
REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0)
REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1)
static int
opREPNE(uint32_t fetchdat)
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
opREPE(uint32_t fetchdat)
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1408,6 +1408,7 @@ const OpFn OP_TABLE(sf_fpu_da_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(sf_fpu_686_da_a16)[256] = {
// clang-format off
sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16,
@@ -1487,6 +1488,7 @@ const OpFn OP_TABLE(sf_fpu_686_da_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(sf_fpu_287_db_a16)[256] = {
// clang-format off
@@ -1648,6 +1650,7 @@ const OpFn OP_TABLE(sf_fpu_db_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(sf_fpu_686_db_a16)[256] = {
// clang-format off
sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16,
@@ -1726,6 +1729,7 @@ const OpFn OP_TABLE(sf_fpu_686_db_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(sf_fpu_287_dc_a16)[32] = {
// clang-format off
@@ -2243,6 +2247,7 @@ const OpFn OP_TABLE(sf_fpu_df_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = {
// clang-format off
sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16,
@@ -2322,6 +2327,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(fpu_d8_a16)[32] = {
// clang-format off
@@ -2661,6 +2667,7 @@ const OpFn OP_TABLE(fpu_da_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(fpu_686_da_a16)[256] = {
// clang-format off
opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16,
@@ -2740,6 +2747,7 @@ const OpFn OP_TABLE(fpu_686_da_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(fpu_287_db_a16)[256] = {
// clang-format off
@@ -2901,6 +2909,7 @@ const OpFn OP_TABLE(fpu_db_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(fpu_686_db_a16)[256] = {
// clang-format off
opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16,
@@ -2979,6 +2988,7 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(fpu_287_dc_a16)[32] = {
// clang-format off
@@ -3496,6 +3506,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = {
// clang-format on
};
#ifndef OPS_286_386
const OpFn OP_TABLE(fpu_686_df_a16)[256] = {
// clang-format off
opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16,
@@ -3575,6 +3586,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = {
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
// clang-format on
};
#endif
const OpFn OP_TABLE(nofpu_a16)[256] = {
// clang-format off

View File

@@ -242,6 +242,7 @@ opFUCOMPP(uint32_t fetchdat)
return 0;
}
#ifndef OPS_286_386
static int
opFCOMI(uint32_t fetchdat)
{
@@ -274,6 +275,7 @@ opFCOMIP(uint32_t fetchdat)
return 0;
}
#endif
#endif
static int
opFDIV(uint32_t fetchdat)
@@ -476,6 +478,7 @@ opFUCOMP(uint32_t fetchdat)
return 0;
}
#ifndef OPS_286_386
static int
opFUCOMI(uint32_t fetchdat)
{
@@ -508,3 +511,4 @@ opFUCOMIP(uint32_t fetchdat)
return 0;
}
#endif
#endif

View File

@@ -1045,6 +1045,7 @@ opFSTCW_a32(uint32_t fetchdat)
#endif
#ifndef FPU_8087
#ifndef OPS_286_386
# define opFCMOV(condition) \
static int opFCMOV##condition(uint32_t fetchdat) \
{ \
@@ -1073,3 +1074,4 @@ opFCMOV(NBE)
opFCMOV(NU)
// clang-format on
#endif
#endif

View File

@@ -224,6 +224,7 @@ next_ins:
return 0;
}
#ifndef OPS_286_386
static int
sf_FCOMI_st0_stj(uint32_t fetchdat)
{
@@ -285,6 +286,7 @@ next_ins:
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
return 0;
}
#endif
static int
sf_FUCOM_sti(uint32_t fetchdat)
@@ -346,6 +348,7 @@ next_ins:
return 0;
}
#ifndef OPS_286_386
static int
sf_FUCOMI_st0_stj(uint32_t fetchdat)
{
@@ -407,6 +410,7 @@ next_ins:
return 0;
}
#endif
#endif
static int
sf_FTST(uint32_t fetchdat)

View File

@@ -1279,6 +1279,7 @@ sf_FSTP_sti(uint32_t fetchdat)
}
#ifndef FPU_8087
#ifndef OPS_286_386
# define sf_FCMOV(condition) \
static int sf_FCMOV##condition(uint32_t fetchdat) \
{ \
@@ -1310,3 +1311,4 @@ sf_FCMOV(NBE)
sf_FCMOV(NU)
// clang-format on
#endif
#endif

View File

@@ -128,6 +128,10 @@ typedef struct atkbc_t {
uint8_t channel;
uint8_t stat_hi;
uint8_t pending;
uint8_t irq_state;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t mem[0x100];
@@ -347,15 +351,15 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi)
dev->status |= STAT_MFULL;
if (dev->mem[0x20] & 0x02)
picint_common(1 << 12, 0, 1);
picint_common(1 << 1, 0, 0);
picint_common(1 << 12, 0, 1, NULL);
picint_common(1 << 1, 0, 0, NULL);
} else {
if (dev->mem[0x20] & 0x01)
picint_common(1 << 1, 0, 1);
picint_common(1 << 12, 0, 0);
picint_common(1 << 1, 0, 1, NULL);
picint_common(1 << 12, 0, 0, NULL);
}
} else if (dev->mem[0x20] & 0x01)
picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
dev->ob = temp;
}
@@ -720,10 +724,10 @@ write_p2(atkbc_t *dev, uint8_t val)
/* PS/2: Handle IRQ's. */
if (dev->misc_flags & FLAG_PS2) {
/* IRQ 12 */
picint_common(1 << 12, 0, val & 0x20);
picint_common(1 << 12, 0, val & 0x20, NULL);
/* IRQ 1 */
picint_common(1 << 1, 0, val & 0x10);
picint_common(1 << 1, 0, val & 0x10, NULL);
}
#endif
@@ -879,6 +883,9 @@ write64_generic(void *priv, uint8_t val)
}
break;
/* TODO: Make this command do nothing on the Regional HT6542,
or else, Efflixi's Award OPTi 495 BIOS gets a stuck key
in Norton Commander 3.0. */
case 0xaf: /* read keyboard version */
kbc_at_log("ATkbc: read keyboard version\n");
kbc_delay_to_ob(dev, kbc_award_revision, 0, 0x00);
@@ -1550,7 +1557,8 @@ kbc_at_process_cmd(void *priv)
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
dev->p1 = dev->p1 & 0xff;
write_p2(dev, 0x4b);
picintc(0x1002);
picintc(0x1000);
picintc(0x0002);
}
dev->status = (dev->status & 0x0f) | 0x60;
@@ -1569,7 +1577,8 @@ kbc_at_process_cmd(void *priv)
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
dev->p1 = dev->p1 & 0xff;
write_p2(dev, 0xcf);
picintc(0x0002);
picintclevel(0x0002, &dev->irq_state);
dev->irq_state = 0;
}
dev->status = (dev->status & 0x0f) | 0x60;
@@ -1852,7 +1861,7 @@ kbc_at_read(uint16_t port, void *priv)
/* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit.
This also means that in AT mode, the IRQ is level-triggered. */
if (!(dev->misc_flags & FLAG_PS2))
picintc(1 << 1);
picintclevel(1 << 1, &dev->irq_state);
break;
case 0x64:
@@ -1901,8 +1910,13 @@ kbc_at_reset(void *priv)
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
dev->misc_flags |= FLAG_PS2;
kbc_at_do_poll = kbc_at_poll_ps2;
} else
picintc(0x1000);
picintc(0x0002);
} else {
kbc_at_do_poll = kbc_at_poll_at;
picintclevel(0x0002, &dev->irq_state);
dev->irq_state = 0;
}
dev->misc_flags |= FLAG_CACHE;
@@ -1924,8 +1938,6 @@ kbc_at_close(void *priv)
atkbc_t *dev = (atkbc_t *) priv;
int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1;
kbc_at_reset(dev);
/* Stop timers. */
timer_disable(&dev->send_delay_timer);

View File

@@ -167,6 +167,12 @@ keyboard_input(int down, uint16_t scan)
case 0x138: /* Right Alt */
shift |= 0x40;
break;
case 0x15b: /* Left Windows */
shift |= 0x08;
break;
case 0x15c: /* Right Windows */
shift |= 0x80;
break;
default:
break;
@@ -191,6 +197,12 @@ keyboard_input(int down, uint16_t scan)
case 0x138: /* Right Alt */
shift &= ~0x40;
break;
case 0x15b: /* Left Windows */
shift &= ~0x08;
break;
case 0x15c: /* Right Windows */
shift &= ~0x80;
break;
case 0x03a: /* Caps Lock */
caps_lock ^= 1;
break;

View File

@@ -19,7 +19,9 @@
* Copyright 2016-2018 Miran Grca.
* Copyright 2017-2018 Fred N. van Kempen.
*/
#include <math.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -37,17 +39,22 @@ typedef struct mouse_t {
} mouse_t;
int mouse_type = 0;
int mouse_x;
int mouse_y;
int mouse_z;
int mouse_buttons;
atomic_int mouse_x;
atomic_int mouse_y;
atomic_int mouse_z;
atomic_int mouse_buttons;
int mouse_mode;
int mouse_timed = 1;
int mouse_tablet_in_proximity = 0;
int tablet_tool_type = 1; /* 0 = Puck/Cursor, 1 = Pen */
double mouse_x_abs;
double mouse_y_abs;
double mouse_sensitivity = 1.0;
double mouse_x_error = 0.0;
double mouse_y_error = 0.0;
pc_timer_t mouse_timer; /* mouse event timer */
static const device_t mouse_none_device = {
@@ -155,22 +162,80 @@ mouse_close(void)
static void
mouse_timer_poll(UNUSED(void *priv))
{
/* Poll at 255 Hz, maximum supported by PS/2 mic. */
/* Poll at the specified sample rate. */
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
if (gdbstub_step == GDBSTUB_EXEC)
if (gdbstub_step == GDBSTUB_EXEC) {
#endif
mouse_process();
if (mouse_timed)
mouse_process();
#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */
}
#endif
}
void
mouse_scale(int x, int y)
{
double scaled_x = (((double) x) * mouse_sensitivity) + mouse_x_error;
double scaled_y = (((double) y) * mouse_sensitivity) + mouse_y_error;
mouse_x += (int) scaled_x;
mouse_y += (int) scaled_y;
mouse_x_error = scaled_x - floor(scaled_x);
mouse_y_error = scaled_y - floor(scaled_y);
}
void
mouse_scale_x(int x)
{
double scaled_x = ((double) x) * mouse_sensitivity + mouse_x_error;
mouse_x += (int) scaled_x;
mouse_x_error = scaled_x - ((double) mouse_x);
}
void
mouse_scale_y(int y)
{
double scaled_y = ((double) y) * mouse_sensitivity + mouse_y_error;
mouse_y += (int) scaled_y;
mouse_y_error = scaled_y - ((double) mouse_y);
}
void
mouse_set_z(int z)
{
mouse_z += z;
}
void
mouse_set_buttons_ex(int b)
{
mouse_buttons = b;
}
int
mouse_get_buttons_ex(void)
{
return mouse_buttons;
}
void
mouse_set_sample_rate(double new_rate)
{
mouse_timed = (new_rate > 0.0);
timer_stop(&mouse_timer);
sample_rate = new_rate;
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
if (mouse_timed)
timer_on_auto(&mouse_timer, 1000000.0 / sample_rate);
}
void
@@ -186,6 +251,9 @@ mouse_reset(void)
mouse_x = mouse_y = mouse_z = 0;
mouse_buttons = 0x00;
mouse_mode = 0;
mouse_timed = 1;
mouse_x_error = mouse_y_error = 0.0;
/* If no mouse configured, we're done. */
if (mouse_type == 0)
@@ -222,19 +290,14 @@ mouse_process(void)
if (mouse_curr == NULL)
return;
if (mouse_poll_ex)
if ((mouse_mode >= 1) && mouse_poll_ex)
mouse_poll_ex();
else
mouse_poll();
if ((mouse_dev_poll != NULL) || (mouse_curr->poll != NULL)) {
if (mouse_curr->poll != NULL)
mouse_curr->poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_x_abs, mouse_y_abs, mouse_priv);
else
mouse_dev_poll(mouse_x, mouse_y, mouse_z, mouse_buttons, mouse_priv);
/* Reset mouse deltas. */
mouse_x = mouse_y = mouse_z = 0;
}
}

View File

@@ -68,6 +68,7 @@
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -80,6 +81,7 @@
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/random.h>
@@ -147,8 +149,6 @@ typedef struct mouse {
int irq;
int bn;
int flags;
int mouse_delayed_dx;
int mouse_delayed_dy;
int mouse_buttons;
int mouse_buttons_last;
int toggle_counter;
@@ -480,10 +480,13 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
mouse_t *dev = (mouse_t *) priv;
int xor ;
if (!mouse_capture && !video_fullscreen)
return 1;
if (!(dev->flags & FLAG_ENABLED))
return 1; /* Mouse is disabled, do nothing. */
if (!x && !y && !((b ^ dev->mouse_buttons_last) & 0x07)) {
if (!mouse_x && !mouse_y && !((b ^ dev->mouse_buttons_last) & 0x07)) {
dev->mouse_buttons_last = b;
return 1; /* State has not changed, do nothing. */
}
@@ -498,7 +501,7 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
so update bits 6-3 here. */
/* If the mouse has moved, set bit 6. */
if (x || y)
if (mouse_x || mouse_y)
dev->mouse_buttons |= 0x40;
/* Set bits 3-5 according to button state changes. */
@@ -508,26 +511,30 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
dev->mouse_buttons_last = b;
/* Clamp x and y to between -128 and 127 (int8_t range). */
if (x > 127)
x = 127;
if (x < -128)
x = -128;
if (y > 127)
y = 127;
if (y < -128)
y = -128;
if (dev->timer_enabled) {
/* Update delayed coordinates. */
dev->mouse_delayed_dx += x;
dev->mouse_delayed_dy += y;
} else {
if (!dev->timer_enabled) {
/* If the counters are not frozen, update them. */
if (!(dev->flags & FLAG_HOLD)) {
dev->current_x = (int8_t) x;
dev->current_y = (int8_t) y;
if (mouse_x > 127) {
dev->current_x = 127;
mouse_x -= 127;
} else if (mouse_x < 1-128) {
dev->current_x = -128;
mouse_x += 128;
} else {
dev->current_x = mouse_x;
mouse_x = 0;
}
if (mouse_y > 127) {
dev->current_y = 127;
mouse_y -= 127;
} else if (mouse_y < 1-128) {
dev->current_y = -128;
mouse_y += 128;
} else {
dev->current_y = mouse_y;
mouse_y = 0;
}
dev->current_b = dev->mouse_buttons;
}
@@ -538,6 +545,7 @@ bm_poll(int x, int y, UNUSED(int z), int b, UNUSED(double abs_x), UNUSED(double
bm_log("DEBUG: Data Interrupt Fired...\n");
}
}
return 0;
}
@@ -548,31 +556,31 @@ bm_update_data(mouse_t *dev)
{
int delta_x;
int delta_y;
int xor ;
int xor;
/* If the counters are not frozen, update them. */
if (!(dev->flags & FLAG_HOLD)) {
if ((mouse_capture || video_fullscreen) && !(dev->flags & FLAG_HOLD)) {
/* Update the deltas and the delays. */
if (dev->mouse_delayed_dx > 127) {
if (mouse_x > 127) {
delta_x = 127;
dev->mouse_delayed_dx -= 127;
} else if (dev->mouse_delayed_dx < -128) {
mouse_x -= 127;
} else if (mouse_x < -128) {
delta_x = -128;
dev->mouse_delayed_dx += 128;
mouse_x += 128;
} else {
delta_x = dev->mouse_delayed_dx;
dev->mouse_delayed_dx = 0;
delta_x = mouse_x;
mouse_x = 0;
}
if (dev->mouse_delayed_dy > 127) {
if (mouse_y > 127) {
delta_y = 127;
dev->mouse_delayed_dy -= 127;
} else if (dev->mouse_delayed_dy < -128) {
mouse_y -= 127;
} else if (mouse_y < -128) {
delta_y = -128;
dev->mouse_delayed_dy += 128;
mouse_y += 128;
} else {
delta_y = dev->mouse_delayed_dy;
dev->mouse_delayed_dy = 0;
delta_y = mouse_y;
mouse_y = 0;
}
dev->current_x = (int8_t) delta_x;
@@ -659,8 +667,6 @@ bm_init(const device_t *info)
}
mouse_set_buttons(dev->bn);
dev->mouse_delayed_dx = 0;
dev->mouse_delayed_dy = 0;
dev->mouse_buttons = 0;
dev->mouse_buttons_last = 0;
dev->sig_val = 0; /* the signature port value */
@@ -707,6 +713,8 @@ bm_init(const device_t *info)
else
bm_log("Standard MS/Logitech BusMouse initialized\n");
mouse_set_sample_rate(0.0);
return dev;
}

View File

@@ -13,6 +13,7 @@
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
*/
#include <stdarg.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -23,6 +24,7 @@
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
enum {
@@ -75,40 +77,51 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
uint8_t buff[3] = { 0x08, 0x00, 0x00 };
int temp_z;
if (dev->x > 255) {
dev->x = 255;
if (mouse_x > 255) {
buff[0] |= 0x40;
buff[1] = 255;
mouse_x -= 255;
} else if (mouse_x < -256) {
buff[0] |= (0x40 | 0x10);
mouse_x += 256;
} else {
if (mouse_x < 0)
buff[0] |= 0x10;
buff[1] = mouse_x;
mouse_x = 0;
}
if (dev->x < -256) {
dev->x = -256;
buff[0] |= 0x40;
}
if (dev->y > 255) {
dev->y = 255;
buff[0] |= 0x80;
}
if (dev->y < -256) {
dev->y = -256;
buff[0] |= 0x80;
}
if (dev->z < -8)
dev->z = -8;
if (dev->z > 7)
dev->z = 7;
if (dev->x < 0)
buff[0] |= 0x10;
if (dev->y < 0)
buff[0] |= 0x20;
buff[0] |= (dev->b & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
buff[1] = (dev->x & 0xff);
buff[2] = (dev->y & 0xff);
if (mouse_y < -255) {
buff[0] |= 0x80;
buff[2] = 255;
mouse_y += 255;
} else if (mouse_y > 256) {
buff[0] |= (0x80 | 0x20);
mouse_y -= 256;
} else {
if (mouse_y > 0)
buff[0] |= 0x20;
buff[2] = -mouse_y;
mouse_y = 0;
}
if (dev->z < -7) {
temp_z = 7;
temp_z += 7;
} else if (mouse_z > 8) {
temp_z = (-8) & 0x0f;
mouse_z -= 8;
} else {
temp_z = (-mouse_y) & 0x0f;
mouse_z = 0;
}
buff[0] |= (mouse_buttons & ((dev->flags & FLAG_INTELLI) ? 0x07 : 0x03));
kbc_at_dev_queue_add(dev, buff[0], main);
kbc_at_dev_queue_add(dev, buff[1], main);
kbc_at_dev_queue_add(dev, buff[2], main);
if (dev->flags & FLAG_INTMODE) {
temp_z = dev->z & 0x0f;
if (dev->flags & FLAG_5BTN) {
if (mouse_buttons & 8)
temp_z |= 0x10;
@@ -121,8 +134,6 @@ ps2_report_coordinates(atkbc_dev_t *dev, int main)
}
kbc_at_dev_queue_add(dev, temp_z, main);
}
dev->x = dev->y = dev->z = 0;
}
static void
@@ -132,7 +143,7 @@ ps2_set_defaults(atkbc_dev_t *dev)
dev->rate = 100;
mouse_set_sample_rate(100.0);
dev->resolution = 2;
dev->flags &= 0x88;
dev->flags &= 0x188;
mouse_scan = 0;
}
@@ -316,25 +327,17 @@ ps2_poll(int x, int y, int z, int b, UNUSED(double abs_x), UNUSED(double abs_y),
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3;
if (!mouse_scan || (!x && !y && !z && (b == dev->b)))
return 0xff;
int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || (!x && !y && !z && (b == dev->b))) ||
((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size)));
if ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size))) {
dev->x = x;
dev->y = -y;
dev->z = -z;
dev->b = b;
} else {
dev->x += x;
dev->y -= y;
dev->z -= z;
if (!cond) {
dev->b = b;
if (dev->mode == MODE_STREAM)
ps2_report_coordinates(dev, 1);
}
if ((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size)))
ps2_report_coordinates(dev, 1);
return 0;
return cond;
}
/*

File diff suppressed because it is too large Load Diff

View File

@@ -56,7 +56,7 @@ typedef struct pci_bridge_t {
uint8_t regs[256];
uint8_t bus_index;
int slot;
uint8_t slot;
} pci_bridge_t;
#ifdef ENABLE_PCI_BRIDGE_LOG
@@ -552,7 +552,10 @@ pci_bridge_init(const device_t *info)
pci_bridge_reset(dev);
dev->slot = pci_add_card(AGP_BRIDGE(dev->local) ? PCI_ADD_AGPBRIDGE : PCI_ADD_BRIDGE, pci_bridge_read, pci_bridge_write, dev);
if (AGP_BRIDGE(dev->local))
pci_add_card(PCI_ADD_AGPBRIDGE, pci_bridge_read, pci_bridge_write, dev, &dev->slot);
else
dev->slot = pci_add_bridge(pci_bridge_read, pci_bridge_write, dev);
if ((info->local != PCI_BRIDGE_INTEL_ICH2) && (info->local != AGP_BRIDGE_INTEL_815EP)) { /* Let the machine configuration slot handle the absurd interrupt tables */
interrupt_count = sizeof(interrupts);

View File

@@ -29,10 +29,14 @@
#include <86box/postcard.h>
#include "cpu.h"
#define POSTCARDS_NUM 4
#define POSTCARD_MASK (POSTCARDS_NUM - 1)
static uint16_t postcard_port;
static uint8_t postcard_written;
static uint8_t postcard_code;
static uint8_t postcard_prev_code;
static uint8_t postcard_written[POSTCARDS_NUM];
static uint8_t postcard_ports_num = 1;
static uint8_t postcard_codes[POSTCARDS_NUM];
static uint8_t postcard_prev_codes[POSTCARDS_NUM];
#define UISTR_LEN 13
static char postcard_str[UISTR_LEN]; /* UI output string */
@@ -61,12 +65,46 @@ int postcard_do_log = 0;
static void
postcard_setui(void)
{
if (!postcard_written)
sprintf(postcard_str, "POST: -- --");
else if (postcard_written == 1)
sprintf(postcard_str, "POST: %02X --", postcard_code);
else
sprintf(postcard_str, "POST: %02X %02X", postcard_code, postcard_prev_code);
if (postcard_ports_num > 1) {
char ps[2][POSTCARDS_NUM][64] = { { 0 },
{ 0 } };
for (uint8_t i = 0; i < POSTCARDS_NUM; i++) {
if (!postcard_written[i]) {
sprintf(ps[0][i], "--");
sprintf(ps[1][i], "--");
} else if (postcard_written[i] == 1) {
sprintf(ps[0][i], "%02X", postcard_codes[i]);
sprintf(ps[1][i], "--");
} else {
sprintf(ps[0][i], "%02X", postcard_codes[i]);
sprintf(ps[1][i], "%02X", postcard_prev_codes[i]);
}
}
switch (postcard_ports_num) {
default:
case 2:
sprintf(postcard_str, "POST: %s%s %s%s",
ps[0][0], ps[0][1], ps[1][0], ps[1][1]);
break;
case 3:
sprintf(postcard_str, "POST: %s/%s%s %s/%s%s",
ps[0][0], ps[0][1], ps[0][2], ps[1][0], ps[1][1], ps[1][2]);
break;
case 4:
sprintf(postcard_str, "POST: %s%s/%s%s %s%s/%s%s",
ps[0][0], ps[0][1], ps[0][2], ps[0][3],
ps[1][0], ps[1][1], ps[1][2], ps[1][3]);
break;
}
} else {
if (!postcard_written[0])
sprintf(postcard_str, "POST: -- --");
else if (postcard_written[0] == 1)
sprintf(postcard_str, "POST: %02X --", postcard_codes[0]);
else
sprintf(postcard_str, "POST: %02X %02X", postcard_codes[0], postcard_prev_codes[0]);
}
ui_sb_bugui(postcard_str);
@@ -79,22 +117,27 @@ postcard_setui(void)
static void
postcard_reset(void)
{
postcard_written = 0;
postcard_code = postcard_prev_code = 0x00;
memset(postcard_written, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
memset(postcard_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
memset(postcard_prev_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
postcard_setui();
}
static void
postcard_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv))
postcard_write(uint16_t port, uint8_t val, UNUSED(void *priv))
{
if (postcard_written && (val == postcard_code))
uint8_t matches = 0;
if (postcard_written[port & POSTCARD_MASK] &&
(val == postcard_codes[port & POSTCARD_MASK]))
return;
postcard_prev_code = postcard_code;
postcard_code = val;
if (postcard_written < 2)
postcard_written++;
postcard_prev_codes[port & POSTCARD_MASK] = postcard_codes[port & POSTCARD_MASK];
postcard_codes[port & POSTCARD_MASK] = val;
if (postcard_written[port & POSTCARD_MASK] < 2)
postcard_written[port & POSTCARD_MASK]++;
postcard_setui();
}
@@ -102,7 +145,7 @@ postcard_write(UNUSED(uint16_t port), uint8_t val, UNUSED(void *priv))
static void *
postcard_init(UNUSED(const device_t *info))
{
postcard_reset();
postcard_ports_num = 1;
if (machine_has_bus(machine, MACHINE_BUS_MCA))
postcard_port = 0x680; /* MCA machines */
@@ -110,16 +153,21 @@ postcard_init(UNUSED(const device_t *info))
postcard_port = 0x190; /* ISA PS/2 machines */
else if (strstr(machines[machine].name, " IBM XT "))
postcard_port = 0x60; /* IBM XT */
else if (strstr(machines[machine].name, " IBM PCjr"))
else if (strstr(machines[machine].name, " IBM PCjr")) {
postcard_port = 0x10; /* IBM PCjr */
else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI))
postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */
} else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI))
postcard_port = 0x84; /* ISA Compaq machines */
else if (strstr(machines[machine].name, "Olivetti"))
postcard_port = 0x378; /* Olivetti machines */
else
postcard_port = 0x80; /* AT and clone machines */
postcard_log("POST card initializing on port %04Xh\n", postcard_port);
postcard_reset();
if (postcard_port)
io_sethandler(postcard_port, 1,
io_sethandler(postcard_port, postcard_ports_num,
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
return postcard_write;
@@ -129,7 +177,7 @@ static void
postcard_close(UNUSED(void *priv))
{
if (postcard_port)
io_removehandler(postcard_port, 1,
io_removehandler(postcard_port, postcard_ports_num,
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
}

View File

@@ -48,6 +48,8 @@ enum {
SERIAL_INT_TIMEOUT = 16
};
void serial_update_ints(serial_t *dev);
static int next_inst = 0;
static serial_device_t serial_devices[SERIAL_MAX];
@@ -84,6 +86,8 @@ serial_reset_port(serial_t *dev)
dev->out_new = 0xffff;
memset(dev->xmit_fifo, 0, 16);
memset(dev->rcvr_fifo, 0, 16);
serial_update_ints(dev);
dev->irq_state = 0;
}
void
@@ -102,6 +106,13 @@ serial_transmit_period(serial_t *dev)
dev->sd->transmit_period_callback(dev, dev->sd->priv, dev->transmit_period);
}
void
serial_do_irq(serial_t *dev, int set)
{
if (dev->irq != 0xff)
picint_common(1 << dev->irq, !!(dev->type >= SERIAL_16450), set, &dev->irq_state);
}
void
serial_update_ints(serial_t *dev)
{
@@ -131,13 +142,7 @@ serial_update_ints(serial_t *dev)
dev->iir = 0;
}
if (stat && (dev->irq != 0xff) && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR))) {
if (dev->type >= SERIAL_16450)
picintlevel(1 << dev->irq);
else
picint(1 << dev->irq);
} else
picintc(1 << dev->irq);
serial_do_irq(dev, stat && ((dev->mctrl & 8) || (dev->type == SERIAL_8250_PCJR)));
}
static void
@@ -595,7 +600,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
dev->sd->rcr_callback(dev, dev->sd->priv);
}
if (!(val & 8) && (dev->mctrl & 8))
picintc(1 << dev->irq);
serial_do_irq(dev, 0);
if ((val ^ dev->mctrl) & 0x10)
serial_reset_fifo(dev);
dev->mctrl = val;
@@ -792,23 +797,6 @@ serial_setup(serial_t *dev, uint16_t addr, uint8_t irq)
dev->irq = irq;
}
serial_t *
serial_attach(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
void *priv)
{
serial_device_t *sd = &serial_devices[port];
sd->rcr_callback = rcr_callback;
sd->dev_write = dev_write;
sd->transmit_period_callback = NULL;
sd->lcr_callback = NULL;
sd->priv = priv;
return sd->serial;
}
serial_t *
serial_attach_ex(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),

View File

@@ -42,9 +42,12 @@ typedef struct cmd640_t {
uint8_t id;
uint8_t in_cfg;
uint8_t channels;
uint8_t pci, regs[256];
uint8_t pci;
uint8_t irq_state;
uint8_t pci_slot;
uint8_t pad0;
uint8_t regs[256];
uint32_t local;
int slot;
int irq_mode[2];
int irq_pin;
int irq_line;
@@ -95,12 +98,12 @@ cmd640_set_irq(int channel, void *priv)
if (irq) {
if (dev->irq_mode[channel] == 1)
pci_set_irq(dev->slot, dev->irq_pin);
pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state);
else
picint(1 << (14 + channel));
} else {
if (dev->irq_mode[channel] == 1)
pci_clear_irq(dev->slot, dev->irq_pin);
pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state);
else
picintc(1 << (14 + channel));
}
@@ -500,7 +503,10 @@ cmd640_init(const device_t *info)
if (info->flags & DEVICE_PCI) {
device_add(&ide_pci_2ch_device);
dev->slot = pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev);
if (info->local & 0x80000)
pci_add_card(PCI_ADD_NORMAL, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot);
else
pci_add_card(PCI_ADD_IDE, cmd640_pci_read, cmd640_pci_write, dev, &dev->pci_slot);
if (dev->channels & 0x01)
ide_set_bus_master(0, NULL, cmd640_set_irq, dev);

View File

@@ -41,11 +41,16 @@ typedef struct cmd646_t {
uint8_t vlb_idx;
uint8_t single_channel;
uint8_t in_cfg;
uint8_t pci_slot;
uint8_t regs[256];
uint32_t local;
int slot;
int irq_mode[2];
int irq_pin;
int irq_mode[2];
sff8038i_t *bm[2];
} cmd646_t;
@@ -102,6 +107,9 @@ cmd646_ide_handlers(cmd646_t *dev)
uint16_t side;
int irq_mode[2] = { 0, 0 };
sff_set_slot(dev->bm[0], dev->pci_slot);
sff_set_slot(dev->bm[1], dev->pci_slot);
ide_pri_disable();
if ((dev->regs[0x09] & 0x01) && (dev->regs[0x50] & 0x40)) {
@@ -382,7 +390,10 @@ cmd646_init(const device_t *info)
device_add(&ide_pci_2ch_device);
dev->slot = pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev);
if (info->local & 0x80000)
pci_add_card(PCI_ADD_NORMAL, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot);
else
pci_add_card(PCI_ADD_IDE, cmd646_pci_read, cmd646_pci_write, dev, &dev->pci_slot);
dev->single_channel = !!(info->local & 0x20000);

View File

@@ -409,31 +409,31 @@ sff_bus_master_set_irq(int channel, void *priv)
case 1:
/* Native PCI IRQ mode with interrupt pin. */
if (irq)
pci_set_irq(dev->slot, dev->irq_pin);
pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state);
else
pci_clear_irq(dev->slot, dev->irq_pin);
pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state);
break;
case 2:
case 5:
/* MIRQ 0 or 1. */
if (irq)
pci_set_mirq(dev->irq_mode[channel] & 1, 0);
pci_set_mirq((dev->irq_mode[channel] & 1), 0, &dev->irq_state);
else
pci_clear_mirq(dev->irq_mode[channel] & 1, 0);
pci_clear_mirq((dev->irq_mode[channel] & 1), 0, &dev->irq_state);
break;
case 3:
/* Native PCI IRQ mode with specified interrupt line. */
if (irq)
picintlevel(1 << dev->irq_line);
picintlevel(1 << dev->irq_line, &dev->irq_state);
else
picintc(1 << dev->irq_line);
picintclevel(1 << dev->irq_line, &dev->irq_state);
break;
case 4:
/* ALi Aladdin Native PCI INTAJ mode. */
if (irq)
pci_set_mirq(channel + 2, dev->irq_level[channel]);
pci_set_mirq((channel + 2), dev->irq_level[channel], &dev->irq_state);
else
pci_clear_mirq(channel + 2, dev->irq_level[channel]);
pci_clear_mirq((channel + 2), dev->irq_level[channel], &dev->irq_state);
break;
}
}
@@ -456,6 +456,7 @@ sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base)
dev->addr = 0x00000000;
dev->ptr0 = 0x00;
dev->count = dev->eot = 0x00000000;
dev->irq_state = 0;
ide_pri_disable();
ide_sec_disable();
@@ -570,6 +571,7 @@ sff_init(UNUSED(const device_t *info))
dev->irq_pin = PCI_INTA;
dev->irq_line = 14;
dev->irq_level[0] = dev->irq_level[1] = 0;
dev->irq_state = 0;
next_id++;

View File

@@ -123,7 +123,8 @@ typedef struct acpi_regs_t {
typedef struct acpi_t {
acpi_regs_t regs;
uint8_t gpireg2_default;
uint8_t pad[3];
uint8_t irq_state;
uint8_t pad[2];
uint8_t gporeg_default[4];
uint8_t suspend_types[8];
uint16_t io_base;

View File

@@ -26,11 +26,11 @@ typedef struct sff8038i_t {
uint8_t ptr0;
uint8_t enabled;
uint8_t dma_mode;
uint8_t irq_state;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint16_t base;
uint16_t pad2;
uint16_t pad1;
uint32_t ptr;
uint32_t ptr_cur;
uint32_t addr;

View File

@@ -83,7 +83,8 @@ extern lpt_port_t lpt_ports[PARALLEL_MAX];
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
extern uint8_t lpt_read(uint16_t port, void *priv);
extern void lpt_irq(void *priv, int raise);
extern uint8_t lpt_read_status(int port);
extern void lpt_irq(void *priv, int raise);
extern char *lpt_device_get_name(int id);
extern char *lpt_device_get_internal_name(int id);

View File

@@ -331,6 +331,24 @@ extern void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val);
extern void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write);
extern uint8_t readmembl_2386(uint32_t addr);
extern void writemembl_2386(uint32_t addr, uint8_t val);
extern uint16_t readmemwl_2386(uint32_t addr);
extern void writememwl_2386(uint32_t addr, uint16_t val);
extern uint32_t readmemll_2386(uint32_t addr);
extern void writememll_2386(uint32_t addr, uint32_t val);
extern uint64_t readmemql_2386(uint32_t addr);
extern void writememql_2386(uint32_t addr, uint64_t val);
extern uint8_t readmembl_no_mmut_2386(uint32_t addr, uint32_t a64);
extern void writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val);
extern uint16_t readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64);
extern void writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val);
extern uint32_t readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64);
extern void writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val);
extern void do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write);
extern uint8_t *getpccache(uint32_t a);
extern uint64_t mmutranslatereal(uint32_t addr, int rw);
extern uint32_t mmutranslatereal32(uint32_t addr, int rw);
@@ -429,6 +447,9 @@ extern void mem_close(void);
extern void mem_reset(void);
extern void mem_remap_top(int kb);
extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
#ifdef EMU_CPU_H
static __inline uint32_t
get_phys(uint32_t addr)

View File

@@ -20,6 +20,11 @@
#ifndef EMU_MOUSE_H
#define EMU_MOUSE_H
#ifndef __cplusplus
/* Yes, a big no-no, but I'm saving myself time here. */
#include <stdatomic.h>
#endif
#define MOUSE_TYPE_NONE 0 /* no mouse configured */
#define MOUSE_TYPE_INTERNAL 1 /* machine has internal mouse */
#define MOUSE_TYPE_LOGIBUS 2 /* Logitech/ATI Bus Mouse */
@@ -39,20 +44,26 @@
#define MOUSE_TYPE_ONBOARD 0x80 /* Mouse is an on-board version of one of the above. */
#ifdef __cplusplus
extern "C" {
#else
extern atomic_int mouse_x;
extern atomic_int mouse_y;
extern atomic_int mouse_z;
extern atomic_int mouse_buttons;
#endif
extern int mouse_type;
extern int mouse_x;
extern int mouse_y;
extern int mouse_z;
extern int mouse_mode; /* 1 = Absolute, 0 = Relative */
extern int mouse_timed; /* 1 = Timed, 0 = Constant */
extern int mouse_tablet_in_proximity;
extern double mouse_x_abs;
extern double mouse_y_abs;
extern int mouse_buttons;
extern int tablet_tool_type;
extern double mouse_sensitivity;
extern double mouse_x_error;
extern double mouse_y_error;
#ifdef EMU_DEVICE_H
extern const device_t *mouse_get_device(int mouse);
@@ -79,11 +90,16 @@ extern void mouse_set_buttons(int buttons);
extern void mouse_set_poll_ex(void (*poll_ex)(void));
extern void mouse_process(void);
extern void mouse_set_poll(int (*f)(int, int, int, int, void *), void *);
extern void mouse_poll(void);
extern void mouse_bus_set_irq(void *priv, int irq);
extern void mouse_set_sample_rate(double new_rate);
extern void mouse_scale(int x, int y);
extern void mouse_scale_x(int x);
extern void mouse_scale_y(int y);
extern void mouse_set_z(int z);
extern void mouse_set_buttons_ex(int b);
extern int mouse_get_buttons_ex(void);
extern char *mouse_get_name(int mouse);
extern char *mouse_get_internal_name(int mouse);

View File

@@ -11,146 +11,260 @@
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2023 Miran Grca.
*/
#ifndef EMU_PCI_H
#define EMU_PCI_H
#define PCI_REG_COMMAND 0x04
#define PCI_REG_VENDOR_ID_L 0x00
#define PCI_REG_VENDOR_ID_H 0x01
#define PCI_REG_DEVICE_ID_L 0x02
#define PCI_REG_DEVICE_ID_H 0x03
#define PCI_REG_COMMAND_L 0x04
#define PCI_REG_COMMAND_H 0x05
#define PCI_REG_STATUS_L 0x06
#define PCI_REG_STATUS_H 0x07
#define PCI_REG_REVISION 0x08
#define PCI_REG_PROG_IF 0x09
#define PCI_REG_SUBCLASS 0x0a
#define PCI_REG_CLASS 0x0b
#define PCI_REG_CACHELINE_SIZE 0x0c
#define PCI_REG_LATENCY_TIMER 0x0d
#define PCI_REG_HEADER_TYPE 0x0e
#define PCI_REG_BIST 0x0f
#define PCI_COMMAND_IO 0x01
#define PCI_COMMAND_MEM 0x02
#define PCI_COMMAND_L_IO 0x01
#define PCI_COMMAND_L_MEM 0x02
#define PCI_COMMAND_L_BM 0x04
#define PCI_COMMAND_L_SPECIAL 0x08
#define PCI_COMMAND_L_MEM_WIEN 0x10
#define PCI_COMMAND_L_VGASNOOP 0x20
#define PCI_COMMAND_L_PARITY 0x40
#define PCI_NO_IRQ_STEERING 0x8000
#define PCI_CAN_SWITCH_TYPE 0x10000
#define PCI_NO_BRIDGES 0x20000
#define PCI_ALWAYS_EXPOSE_DEV0 0x40000
#define PCI_COMMAND_H_SERR 0x01
#define PCI_COMMAND_H_FAST_B2B 0x02
#define PCI_COMMAND_H_INT_DIS 0x04
#define PCI_CONFIG_TYPE_1 1
#define PCI_CONFIG_TYPE_2 2
#define PCI_STATUS_L_INT 0x08
#define PCI_STATUS_L_CAPAB 0x10
#define PCI_STATUS_L_66MHZ 0x20
#define PCI_STATUS_L_FAST_B2B 0x80
#define PCI_CONFIG_TYPE_MASK 0x7fff
#define PCI_STATUS_H_MDPERR 0x01 /* Master Data Parity Error */
#define PCI_STATUS_H_DEVSEL 0x06
#define PCI_STATUS_H_STA 0x08 /* Signaled Target Abort */
#define PCI_STATUS_H_RTA 0x10 /* Received Target Abort */
#define PCI_STATUS_H_RMA 0x20 /* Received Master Abort */
#define PCI_STATUS_H_SSE 0x40 /* Signaled System Error */
#define PCI_STATUS_H_DPERR 0x80 /* Detected Parity Error */
#define PCI_INTA 1
#define PCI_INTB 2
#define PCI_INTC 3
#define PCI_INTD 4
#define PCI_DEVSEL_FAST 0x00
#define PCI_DEVSEL_MEDIUM 0x02
#define PCI_DEVSEL_SLOW 0x04
#define PCI_MIRQ0 0
#define PCI_MIRQ1 1
#define PCI_MIRQ2 2
#define PCI_MIRQ3 3
#define PCI_MIRQ4 4
#define PCI_MIRQ5 5
#define PCI_MIRQ6 6
#define PCI_MIRQ7 7
#define FLAG_MECHANISM_1 0x00000001
#define FLAG_MECHANISM_2 0x00000002
#define FLAG_MECHANISM_SWITCH 0x00000004
#define FLAG_CONFIG_IO_ON 0x00000008
#define FLAG_CONFIG_DEV0_IO_ON 0x00000010
#define FLAG_CONFIG_M1_IO_ON 0x00000020
#define FLAG_NO_IRQ_STEERING 0x00000040
#define FLAG_NO_BRIDGES 0x00000080
#define PCI_IRQ_DISABLED -1
#define FLAG_MECHANISM_MASK FLAG_MECHANISM_1 | FLAG_MECHANISM_2
#define FLAG_MASK 0x0000007f
#define PCI_ADD_STRICT 0x80
#define PCI_INTA 1
#define PCI_INTB 2
#define PCI_INTC 3
#define PCI_INTD 4
#define PCI_MIRQ0 0
#define PCI_MIRQ1 1
#define PCI_MIRQ2 2
#define PCI_MIRQ3 3
#define PCI_MIRQ4 4
#define PCI_MIRQ5 5
#define PCI_MIRQ6 6
#define PCI_MIRQ7 7
#define PCI_IRQ_DISABLED -1
#define PCI_ADD_STRICT 0x40
#define PCI_ADD_MASK (PCI_ADD_STRICT - 1)
#define PCI_ADD_VFIO 0x80
#define PCI_ADD_VFIO_MASK (PCI_ADD_VFIO - 1)
#define PCI_CARD_VFIO PCI_ADD_VFIO
#define PCI_BUS_INVALID 0xff
#define PCI_IGNORE_NO_SLOT 0xff
/* The number of an invalid PCI card. */
#define PCI_CARD_INVALID 0xef
/* PCI cards (currently 32). */
#define PCI_CARDS_NUM 0x20
#define PCI_CARD_MAX (PCI_CARDS_NUM - 1)
/* The number of PCI card INT pins - always at 4 per the PCI specification. */
#define PCI_INT_PINS_NUM 4
/* The base for MIRQ lines accepted by pci_irq(). */
#define PCI_MIRQ_BASE PCI_CARDS_NUM
/* PCI MIRQ lines (currently 8, this many are needed by the ALi M1543(C). */
#define PCI_MIRQS_NUM 8
#define PCI_MIRQ_MAX (PCI_MIRQS_NUM - 1)
/* The base for direct IRQ lines accepted by pci_irq(). */
#define PCI_DIRQ_BASE 0xf0
/* PCI direct IRQ lines (currently 16 because we only emulate the legacy PIC). */
#define PCI_DIRQS_NUM 16
#define PCI_DIRQ_MAX (PCI_DIRQS_NUM - 1)
/* PCI IRQ routings (currently 16, this many are needed by the OPTi 822). */
#define PCI_IRQS_NUM 16
#define PCI_IRQ_MAX (PCI_IRQS_NUM - 1)
/* Legacy flags. */
#define PCI_REG_COMMAND PCI_REG_COMMAND_L
#define PCI_COMMAND_IO PCI_COMMAND_L_IO
#define PCI_COMMAND_MEM PCI_COMMAND_L_MEM
#define PCI_CONFIG_TYPE_1 FLAG_MECHANISM_1
#define PCI_CONFIG_TYPE_2 FLAG_MECHANISM_2
#define PCI_CAN_SWITCH_TYPE FLAG_MECHANISM_SWITCH
#define PCI_ALWAYS_EXPOSE_DEV0 FLAG_CONFIG_DEV0_IO_ON
#define PCI_NO_IRQ_STEERING FLAG_NO_IRQ_STEERING
#define PCI_NO_BRIDGES FLAG_NO_BRIDGES
#define PCI_CONFIG_TYPE_MASK FLAG_MECHANISM_MASK
#define bar_t pci_bar_t
#define trc_init pci_trc_init
#define pci_register_slot(card, type, inta, intb, intc, intd) \
pci_register_bus_slot(0, card, type, inta, intb, intc, intd)
#define pci_set_mirq(mirq, level, irq_state) \
pci_irq(PCI_MIRQ_BASE | mirq, 0, level, 1, irq_state)
#define pci_set_irq(slot, pci_int, irq_state) \
pci_irq(slot, pci_int, 0, 1, irq_state)
#define pci_clear_mirq(mirq, level, irq_state) \
pci_irq(PCI_MIRQ_BASE | mirq, 0, level, 0, irq_state)
#define pci_clear_irq(slot, pci_int, irq_state) \
pci_irq(slot, pci_int, 0, 0, irq_state)
enum {
PCI_CARD_NORTHBRIDGE = 0,
PCI_CARD_AGPBRIDGE = 1,
PCI_CARD_SOUTHBRIDGE = 2,
PCI_CARD_SOUTHBRIDGE_IDE = 3,
PCI_CARD_SOUTHBRIDGE_PMU = 4,
PCI_CARD_SOUTHBRIDGE_USB = 5,
PCI_CARD_NORTHBRIDGE_SEC = 1,
PCI_CARD_AGPBRIDGE = 2,
PCI_CARD_SOUTHBRIDGE = 3,
PCI_CARD_SOUTHBRIDGE_IDE = 4,
PCI_CARD_SOUTHBRIDGE_PMU = 5,
PCI_CARD_SOUTHBRIDGE_USB = 6,
PCI_CARD_AGP = 0x0f,
PCI_CARD_NORMAL = 0x10,
PCI_CARD_VIDEO = 0x11,
PCI_CARD_SCSI = 0x12,
PCI_CARD_SOUND = 0x13,
PCI_CARD_IDE = 0x14,
PCI_CARD_NETWORK = 0x15,
PCI_CARD_BRIDGE = 0x16
PCI_CARD_HANGUL = 0x12,
PCI_CARD_IDE = 0x13,
PCI_CARD_SCSI = 0x14,
PCI_CARD_SOUND = 0x15,
PCI_CARD_MODEM = 0x16,
PCI_CARD_NETWORK = 0x17,
PCI_CARD_UART = 0x18,
PCI_CARD_USB = 0x19,
PCI_CARD_BRIDGE = 0x1a
};
enum {
PCI_ADD_NORTHBRIDGE = 0,
PCI_ADD_AGPBRIDGE = 1,
PCI_ADD_SOUTHBRIDGE = 2,
PCI_ADD_SOUTHBRIDGE_IDE = 3,
PCI_ADD_SOUTHBRIDGE_PMU = 4,
PCI_ADD_SOUTHBRIDGE_USB = 5,
PCI_ADD_NORTHBRIDGE_SEC = 1,
PCI_ADD_AGPBRIDGE = 2,
PCI_ADD_SOUTHBRIDGE = 3,
PCI_ADD_SOUTHBRIDGE_IDE = 4,
PCI_ADD_SOUTHBRIDGE_PMU = 5,
PCI_ADD_SOUTHBRIDGE_USB = 6,
PCI_ADD_AGP = 0x0f,
PCI_ADD_NORMAL = 0x10,
PCI_ADD_VIDEO = 0x11,
PCI_ADD_SCSI = 0x12,
PCI_ADD_SOUND = 0x13,
PCI_ADD_IDE = 0x14,
PCI_ADD_NETWORK = 0x15,
PCI_ADD_BRIDGE = 0x16
PCI_ADD_HANGUL = 0x12,
PCI_ADD_IDE = 0x13,
PCI_ADD_SCSI = 0x14,
PCI_ADD_SOUND = 0x15,
PCI_ADD_MODEM = 0x16,
PCI_ADD_NETWORK = 0x17,
PCI_ADD_UART = 0x18,
PCI_ADD_USB = 0x19,
PCI_ADD_BRIDGE = 0x1a
};
typedef union {
uint32_t addr;
uint8_t addr_regs[4];
} bar_t;
} pci_bar_t;
extern int pci_burst_time;
extern int agp_burst_time;
extern int pci_nonburst_time;
extern int agp_nonburst_time;
#define PCI_IO_ON 0x01
#define PCI_IO_DEV0 0x02
extern int pci_flags;
extern uint32_t pci_base;
extern uint32_t pci_size;
extern int pci_burst_time;
extern int agp_burst_time;
extern int pci_nonburst_time;
extern int agp_nonburst_time;
extern int pci_take_over_io;
extern void pci_set_irq_routing(int pci_int, int irq);
extern void pci_set_irq_level(int pci_int, int level);
extern void pci_enable_mirq(int mirq);
extern void pci_set_mirq_routing(int mirq, int irq);
extern uint32_t pci_base;
extern uint32_t pci_size;
/* PCI raise IRQ: the first parameter is slot if < PCI_MIRQ_BASE, MIRQ if >= PCI_MIRQ_BASE
and < PCI_DIRQ_BASE, and direct IRQ line if >= PCI_DIRQ_BASE (RichardG's
hack that may no longer be needed). */
extern void pci_irq(uint8_t slot, uint8_t pci_int, int level, int set, uint8_t *irq_state);
extern uint8_t pci_get_int(uint8_t slot, uint8_t pci_int);
extern void pci_type2_write(uint16_t port, uint8_t val, void *priv);
extern void pci_type2_writew(uint16_t port, uint16_t val, void *priv);
extern void pci_type2_writel(uint16_t port, uint32_t val, void *priv);
extern uint8_t pci_type2_read(uint16_t port, void *priv);
extern uint16_t pci_type2_readw(uint16_t port, void *priv);
extern uint32_t pci_type2_readl(uint16_t port, void *priv);
/* Relocate a PCI device to a new slot, required for the configurable
IDSEL's of ALi M1543(c). */
extern void pci_relocate_slot(int type, int new_slot);
extern void pci_set_irq_routing(int pci_int, int irq);
extern void pci_set_irq_level(int pci_int, int level);
/* Write PCI enable/disable key, split for the ALi M1435. */
extern void pci_key_write(uint8_t val);
extern void pci_enable_mirq(int mirq);
extern void pci_set_mirq_routing(int mirq, int irq);
/* Set PMC (ie. change PCI configuration mechanism), 0 = #2, 1 = #1. */
extern void pci_set_pmc(uint8_t pmc);
extern int pci_irq_is_level(int irq);
extern void pci_pic_reset(void);
extern void pci_reset(void);
extern void pci_set_mirq(uint8_t mirq, int level);
extern void pci_set_irq(uint8_t card, uint8_t pci_int);
extern void pci_clear_mirq(uint8_t mirq, int level);
extern void pci_clear_irq(uint8_t card, uint8_t pci_int);
extern uint8_t pci_get_int(uint8_t card, uint8_t pci_int);
/* Needed for the io.c handling of configuration mechanism #2 ports C000-CFFF. */
extern void pci_write(uint16_t port, uint8_t val, void *priv);
extern void pci_writew(uint16_t port, uint16_t val, void *priv);
extern void pci_writel(uint16_t port, uint32_t val, void *priv);
extern uint8_t pci_read(uint16_t port, void *priv);
extern uint16_t pci_readw(uint16_t port, void *priv);
extern uint32_t pci_readl(uint16_t port, void *priv);
extern void pci_reset(void);
extern void pci_init(int type);
extern uint8_t pci_register_bus(void);
extern void pci_set_pmc(uint8_t pmc);
extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number);
extern void pci_relocate_slot(int type, int new_slot);
extern void pci_register_slot(int card, int type,
int inta, int intb, int intc, int intd);
extern void pci_register_bus_slot(int bus, int card, int type,
int inta, int intb, int intc, int intd);
extern void pci_close(void);
extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv);
extern uint8_t pci_register_bus(void);
extern void pci_remap_bus(uint8_t bus_index, uint8_t bus_number);
extern void pci_register_bus_slot(int bus, int card, int type, int inta, int intb, int intc, int intd);
extern void trc_init(void);
/* Add a PCI card. */
extern void pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv),
void (*write)(int func, int addr, uint8_t val, void *priv), void *priv, uint8_t *slot);
extern uint8_t trc_read(uint16_t port, void *priv);
extern void trc_write(uint16_t port, uint8_t val, void *priv);
/* Add an instance of the PCI bridge. */
extern uint8_t pci_add_bridge(uint8_t (*read)(int func, int addr, void *priv),
void (*write)(int func, int addr, uint8_t val, void *priv), void *priv);
extern void pci_bridge_set_ctl(void *priv, uint8_t ctl);
/* Register the cards that have been added into slots. */
extern void pci_register_cards(void);
extern void pci_pic_reset(void);
extern void pci_init(int flags);
/* PCI bridge stuff. */
extern void pci_bridge_set_ctl(void *priv, uint8_t ctl);
#ifdef EMU_DEVICE_H
extern const device_t dec21150_device;

View File

@@ -19,6 +19,13 @@
#ifndef EMU_PIC_H
#define EMU_PIC_H
typedef struct pic_latch {
uint8_t d;
uint8_t e;
uint8_t q;
uint8_t nq;
} pic_latch_t;
typedef struct pic {
uint8_t icw1;
uint8_t icw2;
@@ -38,8 +45,13 @@ typedef struct pic {
uint8_t special_mask_mode;
uint8_t auto_eoi_rotate;
uint8_t interrupt;
uint8_t lines;
uint8_t data_bus;
uint8_t irq_latch;
uint8_t has_slaves;
uint8_t flags;
uint8_t edge_lines;
uint8_t pad;
uint32_t lines[8];
uint32_t at;
struct pic *slaves[8];
} pic_t;
@@ -70,12 +82,22 @@ extern void pic2_init(void);
extern void pic_reset(void);
extern int picint_is_level(int irq);
extern void picint_common(uint16_t num, int level, int set);
extern void picint(uint16_t num);
extern void picintlevel(uint16_t num);
extern void picintc(uint16_t num);
extern void picint_common(uint16_t num, int level, int set, uint8_t *irq_state);
extern int picinterrupt(void);
#define PIC_IRQ_EDGE 0
#define PIC_IRQ_LEVEL 1
#define PIC_SLAVE_PENDING 0x01
#define PIC_FREEZE 0x02
#define PIC_MASTER_CLEAR 0x04
/* Legacy defines. */
#define picint(num) picint_common(num, PIC_IRQ_EDGE, 1, NULL)
#define picintlevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 1, irq_state)
#define picintc(num) picint_common(num, PIC_IRQ_EDGE, 0, NULL)
#define picintclevel(num, irq_state) picint_common(num, PIC_IRQ_LEVEL, 0, irq_state)
extern uint8_t pic_irq_ack(void);
#endif /*EMU_PIC_H*/

View File

@@ -396,6 +396,10 @@ typedef struct x54x_t {
uint8_t setup_info_len;
uint8_t max_id;
uint8_t pci_slot;
uint8_t irq_state;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t temp_cdb[12];
/* for multi-threading, keep these volatile */
@@ -437,7 +441,7 @@ typedef struct x54x_t {
volatile int PendingInterrupt;
volatile int Lock;
volatile int target_data_len;
volatile int pad0;
volatile int pad2;
uint32_t Base;
uint32_t fdc_address;

View File

@@ -74,13 +74,13 @@ typedef struct serial_s {
uint8_t out;
uint8_t msr_set;
uint8_t pad;
uint8_t irq_state;
uint8_t pad0;
uint8_t pad1;
uint16_t dlab;
uint16_t base_address;
uint16_t out_new;
uint16_t pad2;
uint16_t pad1;
uint8_t rcvr_fifo_pos;
uint8_t xmit_fifo_pos;
@@ -113,16 +113,16 @@ typedef struct serial_port_s {
extern serial_port_t com_ports[SERIAL_MAX];
extern serial_t *serial_attach(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
void *priv);
extern serial_t *serial_attach_ex(int port,
void (*rcr_callback)(struct serial_s *serial, void *p),
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
void *priv);
#define serial_attach(port, rcr_callback, dev_write, priv) \
serial_attach_ex(port, rcr_callback, dev_write, NULL, NULL, priv);
extern void serial_remove(serial_t *dev);
extern void serial_set_type(serial_t *dev, int type);
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);

View File

@@ -271,6 +271,8 @@ typedef struct voodoo_t {
int pci_enable;
uint8_t pci_slot;
uint8_t dac_data[8];
int dac_reg;
int dac_reg_ff;

110
src/io.c
View File

@@ -286,16 +286,22 @@ inb(uint16_t port)
io_t *p;
io_t *q;
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_type2_read(port, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_read(port, NULL);
found = 1;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_type2_read(port, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_read(port, NULL);
found = 1;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
while (p) {
@@ -303,7 +309,9 @@ inb(uint16_t port)
if (p->inb) {
ret &= p->inb(port, p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -338,16 +346,22 @@ outb(uint16_t port, uint8_t val)
io_t *p;
io_t *q;
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_type2_write(port, val, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_write(port, val, NULL);
found = 1;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
pci_type2_write(port, val, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
pci_write(port, val, NULL);
found = 1;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
while (p) {
@@ -355,7 +369,9 @@ outb(uint16_t port, uint8_t val)
if (p->outb) {
p->outb(port, val, p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -381,17 +397,23 @@ inw(uint16_t port)
io_t *q;
uint16_t ret = 0xffff;
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
uint8_t ret8[2];
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_type2_readw(port, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_readw(port, NULL);
found = 2;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_type2_readw(port, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_readw(port, NULL);
found = 2;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
while (p) {
@@ -399,7 +421,9 @@ inw(uint16_t port)
if (p->inw) {
ret &= p->inw(port, p->priv);
found |= 2;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -413,7 +437,9 @@ inw(uint16_t port)
if (p->inb && !p->inw) {
ret8[i] &= p->inb(port + i, p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -444,16 +470,22 @@ outw(uint16_t port, uint16_t val)
io_t *p;
io_t *q;
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_type2_writew(port, val, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_writew(port, val, NULL);
found = 2;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
pci_type2_writew(port, val, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
pci_writew(port, val, NULL);
found = 2;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
while (p) {
@@ -461,7 +493,9 @@ outw(uint16_t port, uint16_t val)
if (p->outw) {
p->outw(port, val, p->priv);
found |= 2;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -473,7 +507,9 @@ outw(uint16_t port, uint16_t val)
if (p->outb && !p->outw) {
p->outb(port + i, val >> (i << 3), p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -502,16 +538,22 @@ inl(uint16_t port)
uint16_t ret16[2];
uint8_t ret8[4];
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_type2_readl(port, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
ret = pci_readl(port, NULL);
found = 4;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_type2_readl(port, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
ret = pci_readl(port, NULL);
found = 4;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
while (p) {
@@ -519,7 +561,9 @@ inl(uint16_t port)
if (p->inl) {
ret &= p->inl(port, p->priv);
found |= 4;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -532,7 +576,9 @@ inl(uint16_t port)
if (p->inw && !p->inl) {
ret16[0] &= p->inw(port, p->priv);
found |= 2;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -543,7 +589,9 @@ inl(uint16_t port)
if (p->inw && !p->inl) {
ret16[1] &= p->inw(port + 2, p->priv);
found |= 2;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -560,7 +608,9 @@ inl(uint16_t port)
if (p->inb && !p->inw && !p->inl) {
ret8[i] &= p->inb(port + i, p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -591,17 +641,23 @@ outl(uint16_t port, uint32_t val)
io_t *p;
io_t *q;
int found = 0;
#ifdef ENABLE_IO_LOG
int qfound = 0;
#endif
int i = 0;
if ((pci_take_over_io & PCI_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_type2_writel(port, val, NULL);
if ((pci_flags & FLAG_CONFIG_IO_ON) && (port >= pci_base) && (port < (pci_base + pci_size))) {
pci_writel(port, val, NULL);
found = 4;
#ifdef ENABLE_IO_LOG
qfound = 1;
} else if ((pci_take_over_io & PCI_IO_DEV0) && (port >= 0xc000) && (port < 0xc100)) {
pci_type2_writel(port, val, NULL);
#endif
} else if ((pci_flags & FLAG_CONFIG_DEV0_IO_ON) && (port >= 0xc000) && (port < 0xc100)) {
pci_writel(port, val, NULL);
found = 4;
#ifdef ENABLE_IO_LOG
qfound = 1;
#endif
} else {
p = io[port];
if (p) {
@@ -610,7 +666,9 @@ outl(uint16_t port, uint32_t val)
if (p->outl) {
p->outl(port, val, p->priv);
found |= 4;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -623,7 +681,9 @@ outl(uint16_t port, uint32_t val)
if (p->outw && !p->outl) {
p->outw(port + i, val >> (i << 3), p->priv);
found |= 2;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}
@@ -636,7 +696,9 @@ outl(uint16_t port, uint32_t val)
if (p->outb && !p->outw && !p->outl) {
p->outb(port + i, val >> (i << 3), p->priv);
found |= 1;
#ifdef ENABLE_IO_LOG
qfound++;
#endif
}
p = q;
}

View File

@@ -165,6 +165,20 @@ lpt_read(uint16_t port, void *priv)
return ret;
}
uint8_t
lpt_read_status(int port)
{
lpt_port_t *dev = &(lpt_ports[port]);
uint8_t ret = 0xff;
if (dev->dt && dev->dt->read_status && dev->priv)
ret = dev->dt->read_status(dev->priv) | 0x07;
else
ret = 0xdf;
return ret;
}
void
lpt_irq(void *priv, int raise)
{

View File

@@ -633,6 +633,7 @@ machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU oth
return ret;
machine_at_common_init(model);
device_add(&ide_vlb_2ch_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
@@ -642,8 +643,8 @@ machine_at_pc330_6573_init(const machine_t *model) /* doesn't like every CPU oth
device_add(&opti802g_pci_device);
device_add(&opti822_device);
device_add(&keyboard_ps2_device);
device_add(&fdc37c665_device);
device_add(&keyboard_ps2_ami_device);
device_add(&fdc37c665_ide_device);
device_add(&ide_opti611_vlb_device);
device_add(&intel_flash_bxt_device);
@@ -1527,11 +1528,11 @@ machine_at_pcm5330_init(const machine_t *model)
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x0B, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0C, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0D, PCI_CARD_SOUTHBRIDGE_IDE, 0, 0, 0, 0);
pci_register_slot(0x0E, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4);
pci_register_slot(0x13, PCI_CARD_NORMAL, 1, 2, 3, 4);
device_add(&stpc_serial_device);
device_add(&w83977f_370_device);
device_add(&keyboard_ps2_ami_pci_device);
@@ -1738,7 +1739,7 @@ machine_at_ms4134_init(const machine_t *model)
device_add(&fdc37c665_ide_pri_device);
pci_init(PCI_CAN_SWITCH_TYPE | PCI_ALWAYS_EXPOSE_DEV0);
pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0B, PCI_CARD_SCSI, 4, 1, 2, 3);
@@ -1772,7 +1773,7 @@ machine_at_tg486gp_init(const machine_t *model)
device_add(&fdc37c665_ide_pri_device);
pci_init(PCI_CAN_SWITCH_TYPE | PCI_ALWAYS_EXPOSE_DEV0);
pci_init(FLAG_MECHANISM_1 | FLAG_MECHANISM_2 | PCI_ALWAYS_EXPOSE_DEV0);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x0F, PCI_CARD_NORMAL, 1, 2, 3, 4);

View File

@@ -122,12 +122,20 @@ static int key_queue_end = 0;
static void
recalc_address(pcjr_t *pcjr)
{
uint8_t masked_memctrl = pcjr->memctrl;
/* According to the Technical Reference, bits 2 and 5 are
ignored if there is only 64k of RAM and there are only
4 pages. */
if (mem_size < 128)
masked_memctrl &= ~0x24;
if ((pcjr->memctrl & 0xc0) == 0xc0) {
pcjr->vram = &ram[(pcjr->memctrl & 0x06) << 14];
pcjr->b8000 = &ram[(pcjr->memctrl & 0x30) << 11];
pcjr->vram = &ram[(masked_memctrl & 0x06) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11];
} else {
pcjr->vram = &ram[(pcjr->memctrl & 0x07) << 14];
pcjr->b8000 = &ram[(pcjr->memctrl & 0x38) << 11];
pcjr->vram = &ram[(masked_memctrl & 0x07) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11];
}
}
@@ -160,11 +168,17 @@ vid_out(uint16_t addr, uint8_t val, void *priv)
uint8_t old;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
pcjr->crtcreg = val & 0x1f;
return;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
old = pcjr->crtc[pcjr->crtcreg];
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
if (old != val) {
@@ -190,6 +204,10 @@ vid_out(uint16_t addr, uint8_t val, void *priv)
case 0x3df:
pcjr->memctrl = val;
pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to
then be readable from port 60, others it errors out
with only 64k RAM set (but somehow, still works with
128k or more RAM). */
pcjr->addr_mode = val >> 6;
recalc_address(pcjr);
break;
@@ -206,11 +224,17 @@ vid_in(uint16_t addr, void *priv)
uint8_t ret = 0xff;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
ret = pcjr->crtcreg;
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = pcjr->crtc[pcjr->crtcreg];
break;
@@ -591,8 +615,6 @@ kbd_write(uint16_t port, uint8_t val, void *priv)
case 0x61:
pcjr->pb = val;
timer_process();
if (cassette != NULL)
pc_cas_set_motor(cassette, (pcjr->pb & 0x08) == 0);
@@ -647,7 +669,9 @@ kbd_read(uint16_t port, void *priv)
case 0x62:
ret = (pcjr->latched ? 1 : 0);
ret |= 0x02; /*Modem card not installed*/
ret |= 0x02; /* Modem card not installed */
if (mem_size < 128)
ret |= 0x08; /* 64k expansion card not installed */
if ((pcjr->pb & 0x08) || (cassette == NULL))
ret |= (ppispeakon ? 0x10 : 0);
else
@@ -810,6 +834,8 @@ machine_pcjr_init(UNUSED(const machine_t *model))
pcjr = malloc(sizeof(pcjr_t));
memset(pcjr, 0x00, sizeof(pcjr_t));
pcjr->memctrl = -1;
if (mem_size < 128)
pcjr->memctrl &= ~0x24;
display_type = machine_get_config_int("display_type");
pcjr->composite = (display_type != PCJR_RGB);
@@ -853,7 +879,10 @@ machine_pcjr_init(UNUSED(const machine_t *model))
device_add(&ns8250_pcjr_device);
serial_set_next_inst(SERIAL_MAX); /* So that serial_standalone_init() won't do anything. */
/* "All the inputs are 'read' with one 'IN' from address hex 201." - PCjr Technical Reference (Nov. 83), p.2-119 */
/* "All the inputs are 'read' with one 'IN' from address hex 201." - PCjr Technical Reference (Nov. 83), p.2-119
Note by Miran Grca: Meanwhile, the same Technical Reference clearly says that
the gameport is on ports 201-207. */
standalone_gameport_type = &gameport_201_device;
return ret;

View File

@@ -108,7 +108,7 @@ machine_init_ex(int m)
/* Reset the fast off stuff. */
cpu_fast_off_reset();
pci_take_over_io = 0x00000000;
pci_flags = 0x00000000;
}
/* All good, boot the machine! */

View File

@@ -303,7 +303,7 @@ const machine_t machines[] = {
.bus_flags = MACHINE_PCJR,
.flags = MACHINE_VIDEO_FIXED,
.ram = {
.min = 128,
.min = 64,
.max = 640,
.step = 64
},

View File

@@ -13,5 +13,5 @@
# Copyright 2020-2021 David Hrdlička.
#
add_library(mem OBJECT 815ep_spd_hack.c catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c rom.c
row.c smram.c spd.c sst_flash.c)
add_library(mem OBJECT 815ep_spd_hack.c catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c mmu_2386.c
rom.c row.c smram.c spd.c sst_flash.c)

View File

@@ -119,14 +119,15 @@ int purgeable_page_count = 0;
uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */
mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
/* FIXME: re-do this with a 'mem_ops' struct. */
static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */
static uint8_t *readlookupp;
static uint8_t *writelookupp;
static mem_mapping_t *base_mapping;
static mem_mapping_t *last_mapping;
static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO];
static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO];
static uint8_t *_mem_exec[MEM_MAPPINGS_NO];

901
src/mem/mmu_2386.c Normal file
View File

@@ -0,0 +1,901 @@
/*
* 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.
*
* Memory handling and MMU.
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/version.h>
#include "cpu.h"
#include "x86_ops.h"
#include "x86.h"
#include <86box/machine.h>
#include <86box/m_xt_xi8088.h>
#include <86box/config.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/plat.h>
#include <86box/rom.h>
#include <86box/gdbstub.h>
#ifdef USE_DYNAREC
# include "codegen_public.h"
#else
#ifdef USE_NEW_DYNAREC
# define PAGE_MASK_SHIFT 6
#else
# define PAGE_MASK_INDEX_MASK 3
# define PAGE_MASK_INDEX_SHIFT 10
# define PAGE_MASK_SHIFT 4
#endif
# define PAGE_MASK_MASK 63
#endif
#if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
#define BLOCK_PC_INVALID 0xffffffff
#define BLOCK_INVALID 0
#endif
#define mmutranslate_read_2386(addr) mmutranslatereal_2386(addr,0)
#define mmutranslate_write_2386(addr) mmutranslatereal_2386(addr,1)
uint64_t
mmutranslatereal_2386(uint32_t addr, int rw)
{
uint32_t temp, temp2, temp3;
uint32_t addr2;
if (cpu_state.abrt)
return 0xffffffffffffffffULL;
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
temp = temp2 = mem_readl_phys(addr2);
if (!(temp & 1)) {
cr2 = addr;
temp &= 1;
if (CPL == 3) temp |= 4;
if (rw) temp |= 2;
cpu_state.abrt = ABRT_PF;
abrt_error = temp;
return 0xffffffffffffffffULL;
}
temp = mem_readl_phys((temp & ~0xfff) + ((addr >> 10) & 0xffc));
temp3 = temp & temp2;
if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (is486 && (cr0 & WP_FLAG))))) {
cr2 = addr;
temp &= 1;
if (CPL == 3)
temp |= 4;
if (rw)
temp |= 2;
cpu_state.abrt = ABRT_PF;
abrt_error = temp;
return 0xffffffffffffffffULL;
}
mmu_perm = temp & 4;
mem_writel_phys(addr2, mem_readl_phys(addr) | 0x20);
mem_writel_phys((temp2 & ~0xfff) + ((addr >> 10) & 0xffc), mem_readl_phys((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) | (rw ? 0x60 : 0x20));
return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff));
}
uint64_t
mmutranslate_noabrt_2386(uint32_t addr, int rw)
{
uint32_t temp,temp2,temp3;
uint32_t addr2;
if (cpu_state.abrt)
return 0xffffffffffffffffULL;
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
temp = temp2 = mem_readl_phys(addr2);
if (! (temp & 1))
return 0xffffffffffffffffULL;
temp = mem_readl_phys((temp & ~0xfff) + ((addr >> 10) & 0xffc));
temp3 = temp & temp2;
if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG))))
return 0xffffffffffffffffULL;
return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff));
}
uint8_t
readmembl_2386(uint32_t addr)
{
mem_mapping_t *map;
uint64_t a;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
high_page = 0;
if (cr0 >> 31) {
a = mmutranslate_read_2386(addr);
addr64 = (uint32_t) a;
if (a > 0xffffffffULL)
return 0xff;
}
addr = (uint32_t) (addr64 & rammask);
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_b)
return map->read_b(addr, map->priv);
return 0xff;
}
void
writemembl_2386(uint32_t addr, uint8_t val)
{
mem_mapping_t *map;
uint64_t a;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
addr64 = (uint64_t) addr;
mem_logical_addr = addr;
high_page = 0;
if (cr0 >> 31) {
a = mmutranslate_write_2386(addr);
addr64 = (uint32_t) a;
if (a > 0xffffffffULL)
return;
}
addr = (uint32_t) (addr64 & rammask);
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_b)
map->write_b(addr, val, map->priv);
}
/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */
uint8_t
readmembl_no_mmut_2386(uint32_t addr, uint32_t a64)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
mem_logical_addr = addr;
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return 0xff;
addr = a64 & rammask;
} else
addr &= rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_b)
return map->read_b(addr, map->priv);
return 0xff;
}
/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */
void
writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
mem_logical_addr = addr;
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return;
addr = a64 & rammask;
} else
addr &= rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_b)
map->write_b(addr, val, map->priv);
}
uint16_t
readmemwl_2386(uint32_t addr)
{
mem_mapping_t *map;
int i;
uint64_t a;
addr64a[0] = addr;
addr64a[1] = addr + 1;
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2);
mem_logical_addr = addr;
high_page = 0;
if (addr & 1) {
if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffe) {
if (cr0 >> 31) {
for (i = 0; i < 2; i++) {
a = mmutranslate_read_2386(addr + i);
addr64a[i] = (uint32_t) a;
if (a > 0xffffffffULL)
return 0xffff;
}
}
return readmembl_no_mmut(addr, addr64a[0]) |
(((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8);
}
}
if (cr0 >> 31) {
a = mmutranslate_read_2386(addr);
addr64a[0] = (uint32_t) a;
if (a > 0xffffffffULL)
return 0xffff;
} else
addr64a[0] = (uint64_t) addr;
addr = addr64a[0] & rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_w)
return map->read_w(addr, map->priv);
if (map && map->read_b) {
return map->read_b(addr, map->priv) |
((uint16_t) (map->read_b(addr + 1, map->priv)) << 8);
}
return 0xffff;
}
void
writememwl_2386(uint32_t addr, uint16_t val)
{
mem_mapping_t *map;
int i;
uint64_t a;
addr64a[0] = addr;
addr64a[1] = addr + 1;
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2);
mem_logical_addr = addr;
high_page = 0;
if (addr & 1) {
if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffe) {
if (cr0 >> 31) {
for (i = 0; i < 2; i++) {
a = mmutranslate_write_2386(addr + i);
addr64a[i] = (uint32_t) a;
if (a > 0xffffffffULL)
return;
}
}
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
writemembl_no_mmut(addr, addr64a[0], val);
writemembl_no_mmut(addr + 1, addr64a[1], val >> 8);
return;
}
}
if (cr0 >> 31) {
a = mmutranslate_write_2386(addr);
addr64a[0] = (uint32_t) a;
if (a > 0xffffffffULL)
return;
}
addr = addr64a[0] & rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_w) {
map->write_w(addr, val, map->priv);
return;
}
if (map && map->write_b) {
map->write_b(addr, val, map->priv);
map->write_b(addr + 1, val >> 8, map->priv);
return;
}
}
/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */
uint16_t
readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2);
mem_logical_addr = addr;
if (addr & 1) {
if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffe) {
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return 0xffff;
}
return readmembl_no_mmut(addr, a64[0]) |
(((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8);
}
}
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return 0xffff;
addr = (uint32_t) (a64[0] & rammask);
} else
addr &= rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_w)
return map->read_w(addr, map->priv);
if (map && map->read_b) {
return map->read_b(addr, map->priv) |
((uint16_t) (map->read_b(addr + 1, map->priv)) << 8);
}
return 0xffff;
}
/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */
void
writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2);
mem_logical_addr = addr;
if (addr & 1) {
if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffe) {
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return;
}
writemembl_no_mmut(addr, a64[0], val);
writemembl_no_mmut(addr + 1, a64[1], val >> 8);
return;
}
}
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return;
addr = (uint32_t) (a64[0] & rammask);
} else
addr &= rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_w) {
map->write_w(addr, val, map->priv);
return;
}
if (map && map->write_b) {
map->write_b(addr, val, map->priv);
map->write_b(addr + 1, val >> 8, map->priv);
return;
}
}
uint32_t
readmemll_2386(uint32_t addr)
{
mem_mapping_t *map;
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
addr64a[i] = (uint64_t) (addr + i);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4);
mem_logical_addr = addr;
high_page = 0;
if (addr & 3) {
if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffc) {
if (cr0 >> 31) {
for (i = 0; i < 4; i++) {
if (i == 0) {
a = mmutranslate_read_2386(addr + i);
addr64a[i] = (uint32_t) a;
} else if (!((addr + i) & 0xfff)) {
a = mmutranslate_read_2386(addr + 3);
addr64a[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
} else {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
if (a > 0xffffffffULL)
return 0xffff;
}
}
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
return readmemwl_no_mmut(addr, addr64a) |
(((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16);
}
}
if (cr0 >> 31) {
a = mmutranslate_read_2386(addr);
addr64a[0] = (uint32_t) a;
if (a > 0xffffffffULL)
return 0xffffffff;
}
addr = addr64a[0] & rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_l)
return map->read_l(addr, map->priv);
if (map && map->read_w)
return map->read_w(addr, map->priv) |
((uint32_t) (map->read_w(addr + 2, map->priv)) << 16);
if (map && map->read_b)
return map->read_b(addr, map->priv) |
((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) |
((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) |
((uint32_t) (map->read_b(addr + 3, map->priv)) << 24);
return 0xffffffff;
}
void
writememll_2386(uint32_t addr, uint32_t val)
{
mem_mapping_t *map;
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 4; i++)
addr64a[i] = (uint64_t) (addr + i);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4);
mem_logical_addr = addr;
high_page = 0;
if (addr & 3) {
if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffc) {
if (cr0 >> 31) {
for (i = 0; i < 4; i++) {
if (i == 0) {
a = mmutranslate_write_2386(addr + i);
addr64a[i] = (uint32_t) a;
} else if (!((addr + i) & 0xfff)) {
a = mmutranslate_write_2386(addr + 3);
addr64a[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
} else {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
if (a > 0xffffffffULL)
return;
}
}
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
writememwl_no_mmut(addr, &(addr64a[0]), val);
writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16);
return;
}
}
if (cr0 >> 31) {
a = mmutranslate_write_2386(addr);
addr64a[0] = (uint32_t) a;
if (a > 0xffffffffULL)
return;
}
addr = addr64a[0] & rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_l) {
map->write_l(addr, val, map->priv);
return;
}
if (map && map->write_w) {
map->write_w(addr, val, map->priv);
map->write_w(addr + 2, val >> 16, map->priv);
return;
}
if (map && map->write_b) {
map->write_b(addr, val, map->priv);
map->write_b(addr + 1, val >> 8, map->priv);
map->write_b(addr + 2, val >> 16, map->priv);
map->write_b(addr + 3, val >> 24, map->priv);
return;
}
}
/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */
uint32_t
readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4);
mem_logical_addr = addr;
if (addr & 3) {
if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffc) {
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return 0xffffffff;
}
return readmemwl_no_mmut(addr, a64) |
((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16);
}
}
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return 0xffffffff;
addr = (uint32_t) (a64[0] & rammask);
} else
addr &= rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_l)
return map->read_l(addr, map->priv);
if (map && map->read_w)
return map->read_w(addr, map->priv) |
((uint32_t) (map->read_w(addr + 2, map->priv)) << 16);
if (map && map->read_b)
return map->read_b(addr, map->priv) |
((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) |
((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) |
((uint32_t) (map->read_b(addr + 3, map->priv)) << 24);
return 0xffffffff;
}
/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */
void
writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val)
{
mem_mapping_t *map;
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4);
mem_logical_addr = addr;
if (addr & 3) {
if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xffc) {
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return;
}
writememwl_no_mmut(addr, &(a64[0]), val);
writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16);
return;
}
}
if (cr0 >> 31) {
if (cpu_state.abrt || high_page)
return;
addr = (uint32_t) (a64[0] & rammask);
} else
addr &= rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_l) {
map->write_l(addr, val, map->priv);
return;
}
if (map && map->write_w) {
map->write_w(addr, val, map->priv);
map->write_w(addr + 2, val >> 16, map->priv);
return;
}
if (map && map->write_b) {
map->write_b(addr, val, map->priv);
map->write_b(addr + 1, val >> 8, map->priv);
map->write_b(addr + 2, val >> 16, map->priv);
map->write_b(addr + 3, val >> 24, map->priv);
return;
}
}
uint64_t
readmemql_2386(uint32_t addr)
{
mem_mapping_t *map;
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
addr64a[i] = (uint64_t) (addr + i);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8);
mem_logical_addr = addr;
high_page = 0;
if (addr & 7) {
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xff8) {
if (cr0 >> 31) {
for (i = 0; i < 8; i++) {
if (i == 0) {
a = mmutranslate_read_2386(addr + i);
addr64a[i] = (uint32_t) a;
} else if (!((addr + i) & 0xfff)) {
a = mmutranslate_read_2386(addr + 7);
addr64a[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
} else {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
if (a > 0xffffffffULL)
return 0xffff;
}
}
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
return readmemll_no_mmut(addr, addr64a) |
(((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32);
}
}
if (cr0 >> 31) {
a = mmutranslate_read_2386(addr);
addr64a[0] = (uint32_t) a;
if (a > 0xffffffffULL)
return 0xffffffffffffffffULL;
}
addr = addr64a[0] & rammask;
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->read_l)
return map->read_l(addr, map->priv) | ((uint64_t)map->read_l(addr + 4, map->priv) << 32);
return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32);
}
void
writememql_2386(uint32_t addr, uint64_t val)
{
mem_mapping_t *map;
int i;
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < 8; i++)
addr64a[i] = (uint64_t) (addr + i);
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8);
mem_logical_addr = addr;
high_page = 0;
if (addr & 7) {
cycles -= timing_misaligned;
if ((addr & 0xfff) > 0xff8) {
if (cr0 >> 31) {
for (i = 0; i < 8; i++) {
if (i == 0) {
a = mmutranslate_write_2386(addr + i);
addr64a[i] = (uint32_t) a;
} else if (!((addr + i) & 0xfff)) {
a = mmutranslate_write_2386(addr + 7);
addr64a[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
} else {
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
addr64a[i] = (uint32_t) a;
}
if (addr64a[i] > 0xffffffffULL)
return;
}
}
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
their result as a parameter to be used if needed. */
writememll_no_mmut(addr, addr64a, val);
writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32);
return;
}
}
if (cr0 >> 31) {
addr64a[0] = mmutranslate_write_2386(addr);
if (addr64a[0] > 0xffffffffULL)
return;
}
addr = addr64a[0] & rammask;
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
if (map && map->write_l) {
map->write_l(addr, val, map->priv);
map->write_l(addr + 4, val >> 32, map->priv);
return;
}
if (map && map->write_w) {
map->write_w(addr, val, map->priv);
map->write_w(addr + 2, val >> 16, map->priv);
map->write_w(addr + 4, val >> 32, map->priv);
map->write_w(addr + 6, val >> 48, map->priv);
return;
}
if (map && map->write_b) {
map->write_b(addr, val, map->priv);
map->write_b(addr + 1, val >> 8, map->priv);
map->write_b(addr + 2, val >> 16, map->priv);
map->write_b(addr + 3, val >> 24, map->priv);
map->write_b(addr + 4, val >> 32, map->priv);
map->write_b(addr + 5, val >> 40, map->priv);
map->write_b(addr + 6, val >> 48, map->priv);
map->write_b(addr + 7, val >> 56, map->priv);
return;
}
}
void
do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write)
{
int i;
uint32_t last_addr = addr + (num - 1);
uint64_t a = 0x0000000000000000ULL;
for (i = 0; i < num; i++)
a64[i] = (uint64_t) addr;
for (i = 0; i < num; i++) {
if (cr0 >> 31) {
/* If we have encountered at least one page fault, mark all subsequent addresses as
having page faulted, prevents false negatives in readmem*l_no_mmut. */
if ((i > 0) && cpu_state.abrt && !high_page)
a64[i] = a64[i - 1];
/* If we are on the same page, there is no need to translate again, as we can just
reuse the previous result. */
else if (i == 0) {
a = mmutranslatereal_2386(addr, write);
a64[i] = (uint32_t) a;
} else if (!(addr & 0xfff)) {
a = mmutranslatereal_2386(last_addr, write);
a64[i] = (uint32_t) a;
if (!cpu_state.abrt) {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
} else {
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
a64[i] = (uint32_t) a;
}
}
addr++;
}
}

View File

@@ -97,36 +97,45 @@ static uint8_t rtl8019as_pnp_rom[] = {
typedef struct nic_t {
dp8390_t *dp8390;
const char *name;
uint8_t pnp_csnsav;
uint8_t pci_slot;
uint8_t irq_state;
uint8_t pad;
/* RTL8019AS/RTL8029AS registers */
uint8_t config0;
uint8_t config2;
uint8_t config3;
uint8_t _9346cr;
uint8_t pci_regs[PCI_REGSIZE];
uint8_t eeprom[128]; /* for RTL8029AS */
uint8_t maclocal[6]; /* configured MAC (local) address */
/* POS registers, MCA boards only */
uint8_t pos_regs[8];
int board;
int is_pci;
int is_mca;
int is_8bit;
uint32_t base_address;
int base_irq;
int has_bios;
uint32_t base_address;
uint32_t bios_addr;
uint32_t bios_size;
uint32_t bios_mask;
int card; /* PCI card slot */
int has_bios;
int pad;
bar_t pci_bar[2];
uint8_t pci_regs[PCI_REGSIZE];
uint8_t eeprom[128]; /* for RTL8029AS */
rom_t bios_rom;
void *pnp_card;
uint8_t pnp_csnsav;
uint8_t maclocal[6]; /* configured MAC (local) address */
/* RTL8019AS/RTL8029AS registers */
uint8_t config0;
uint8_t config2;
uint8_t config3;
uint8_t _9346cr;
uint32_t pad0;
/* POS registers, MCA boards only */
uint8_t pos_regs[8];
} nic_t;
#ifdef ENABLE_NE2K_LOG
@@ -150,13 +159,13 @@ nelog(int lvl, const char *fmt, ...)
static void
nic_interrupt(void *priv, int set)
{
const nic_t *dev = (nic_t *) priv;
nic_t *dev = (nic_t *) priv;
if (dev->is_pci) {
if (set)
pci_set_irq(dev->card, PCI_INTA);
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
else
pci_clear_irq(dev->card, PCI_INTA);
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
} else {
if (set)
picint(1 << dev->base_irq);
@@ -1087,8 +1096,7 @@ nic_init(const device_t *info)
mem_mapping_disable(&dev->bios_rom.mapping);
/* Add device to the PCI bus, keep its slot number. */
dev->card = pci_add_card(PCI_ADD_NORMAL,
nic_pci_read, nic_pci_write, dev);
pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev, &dev->pci_slot);
}
/* Initialize the RTL8029 EEPROM. */

View File

@@ -216,7 +216,8 @@ typedef struct {
uint32_t base_address;
int base_irq;
int dma_channel;
int card; /* PCI card slot */
uint8_t pci_slot; /* PCI card slot */
uint8_t irq_state;
int xmit_pos;
/** Register Address Pointer */
uint32_t u32RAP;
@@ -413,9 +414,9 @@ pcnet_do_irq(nic_t *dev, int issue)
{
if (dev->is_pci) {
if (issue)
pci_set_irq(dev->card, PCI_INTA);
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
else
pci_clear_irq(dev->card, PCI_INTA);
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
} else {
if (issue)
picint(1 << dev->base_irq);
@@ -2995,8 +2996,7 @@ pcnet_init(const device_t *info)
pcnet_pci_regs[0x04] = 3;
/* Add device to the PCI bus, keep its slot number. */
dev->card = pci_add_card(PCI_ADD_NORMAL,
pcnet_pci_read, pcnet_pci_write, dev);
pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev, &dev->pci_slot);
} else if (dev->board == DEV_AM79C961) {
dev->dma_channel = -1;

View File

@@ -306,7 +306,7 @@ typedef struct local_t {
uint8_t read_addr;
uint8_t wp_0d;
uint8_t wp_32;
uint8_t pad;
uint8_t irq_state;
uint8_t pad0;
uint8_t addr[8];
@@ -434,6 +434,21 @@ check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2)
return 1;
}
static void
timer_update_irq(nvr_t *nvr)
{
local_t *local = (local_t *) nvr->data;
uint8_t irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & (REGB_UIE | REGB_AIE | REGB_PIE);
if (irq) {
nvr->regs[RTC_REGC] |= REGC_IRQF;
picintlevel(1 << nvr->irq, &local->irq_state);
} else {
nvr->regs[RTC_REGC] &= ~REGC_IRQF;
picintclevel(1 << nvr->irq, &local->irq_state);
}
}
/* Update the NVR registers from the internal clock. */
static void
timer_update(void *priv)
@@ -442,45 +457,38 @@ timer_update(void *priv)
local_t *local = (local_t *) nvr->data;
struct tm tm;
local->ecount = 0LL;
if (local->ecount == (244ULL * TIMER_USEC)) {
rtc_tick();
if (!(nvr->regs[RTC_REGB] & REGB_SET)) {
/* Get the current time from the internal clock. */
nvr_time_get(&tm);
/* Update registers with current time. */
time_set(nvr, &tm);
/* Clear update status. */
local->stat = 0x00;
/* Check for any alarms we need to handle. */
if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) && check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* &&
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) &&
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS)*/
) {
if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && check_alarm(nvr, RTC_HOURS) &&
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) /* &&
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) && check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS) */) {
nvr->regs[RTC_REGC] |= REGC_AF;
if (nvr->regs[RTC_REGB] & REGB_AIE) {
/* Generate an interrupt. */
if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) {
picintlevel(1 << nvr->irq);
nvr->regs[RTC_REGC] |= REGC_IRQF;
}
}
timer_update_irq(nvr);
}
/* Schedule the end of the update. */
local->ecount = 1984ULL * TIMER_USEC;
timer_set_delay_u64(&local->update_timer, local->ecount);
} else {
/*
* The flag and interrupt should be issued
* on update ended, not started.
*/
nvr->regs[RTC_REGC] |= REGC_UF;
if (nvr->regs[RTC_REGB] & REGB_UIE) {
/* Generate an interrupt. */
if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) {
picintlevel(1 << nvr->irq);
nvr->regs[RTC_REGC] |= REGC_IRQF;
}
}
timer_update_irq(nvr);
/* Clear update status. */
local->stat = 0x00;
local->ecount = 0LL;
}
}
@@ -525,13 +533,7 @@ timer_intr(void *priv)
timer_load_count(nvr);
nvr->regs[RTC_REGC] |= REGC_PF;
if (nvr->regs[RTC_REGB] & REGB_PIE) {
/* Generate an interrupt. */
if ((nvr->irq != -1) && (!(nvr->regs[RTC_REGC] & REGC_IRQF))) {
picintlevel(1 << nvr->irq);
nvr->regs[RTC_REGC] |= REGC_IRQF;
}
}
timer_update_irq(nvr);
}
}
@@ -541,15 +543,14 @@ timer_tick(nvr_t *nvr)
{
local_t *local = (local_t *) nvr->data;
/* Only update it there is no SET in progress. */
if (!(nvr->regs[RTC_REGB] & REGB_SET)) {
/* Only update it there is no SET in progress.
Also avoid updating it is DV2-DV0 are not set to 0, 1, 0. */
if (((nvr->regs[RTC_REGA] & 0x70) == 0x20) && !(nvr->regs[RTC_REGB] & REGB_SET)) {
/* Set the UIP bit, announcing the update. */
local->stat = REGA_UIP;
rtc_tick();
/* Schedule the actual update. */
local->ecount = (244ULL + 1984ULL) * TIMER_USEC;
local->ecount = 244ULL * TIMER_USEC;
timer_set_delay_u64(&local->update_timer, local->ecount);
}
}
@@ -583,32 +584,29 @@ nvr_reg_write(uint16_t reg, uint8_t val, void *priv)
local_t *local = (local_t *) nvr->data;
struct tm tm;
uint8_t old;
uint8_t irq = 0;
uint8_t old_irq = 0;
old = nvr->regs[reg];
switch (reg) {
case RTC_SECONDS: /* bit 7 of seconds is read-only */
nvr_reg_common_write(reg, val & 0x7f, nvr, local);
break;
case RTC_REGA:
nvr->regs[RTC_REGA] = val;
timer_load_count(nvr);
if ((val & nvr->regs[RTC_REGA]) & ~REGA_UIP) {
nvr->regs[RTC_REGA] = (nvr->regs[RTC_REGA] & REGA_UIP) | (val & ~REGA_UIP);
timer_load_count(nvr);
}
break;
case RTC_REGB:
old_irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & 0x70;
nvr->regs[RTC_REGB] = val;
if (((old ^ val) & REGB_SET) && (val & REGB_SET)) {
/* According to the datasheet... */
nvr->regs[RTC_REGA] &= ~REGA_UIP;
nvr->regs[RTC_REGB] &= ~REGB_UIE;
}
irq = (nvr->regs[RTC_REGB] & nvr->regs[RTC_REGC]) & 0x70;
if (old_irq && !irq) {
picintc(1 << nvr->irq);
nvr->regs[RTC_REGC] &= ~REGC_IRQF;
} else if (!old_irq && irq) {
picintlevel(1 << nvr->irq);
nvr->regs[RTC_REGC] |= REGC_IRQF;
val &= ~REGB_UIE;
local->stat &= ~REGA_UIP;
}
nvr->regs[RTC_REGB] = val;
timer_update_irq(nvr);
break;
case RTC_REGC: /* R/O */
@@ -698,9 +696,9 @@ nvr_read(uint16_t addr, void *priv)
break;
case RTC_REGC:
ret = nvr->regs[RTC_REGC];
picintc(1 << nvr->irq);
nvr->regs[RTC_REGC] = 0x00;
ret = nvr->regs[RTC_REGC] & (REGC_IRQF | REGC_PF | REGC_AF | REGC_UF);
nvr->regs[RTC_REGC] &= ~(REGC_IRQF | REGC_PF | REGC_AF | REGC_UF);
timer_update_irq(nvr);
break;
case RTC_REGD:

1674
src/pci.c

File diff suppressed because it is too large Load Diff

View File

@@ -17,17 +17,24 @@ typedef struct pci_dummy_t {
bar_t pci_bar[2];
uint8_t card;
uint8_t pci_slot;
uint8_t irq_state;
uint8_t interrupt_on;
uint8_t irq_level;
} pci_dummy_t;
static void
pci_dummy_interrupt(int set, pci_dummy_t *dev)
{
if (set)
pci_set_irq(dev->card, PCI_INTA);
else
pci_clear_irq(dev->card, PCI_INTA);
if (set != dev->irq_level) {
if (set)
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
else
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
}
dev->irq_level = set;
}
static uint8_t
@@ -160,8 +167,8 @@ pci_dummy_pci_read(int func, int addr, void *priv)
ret = dev->pci_regs[addr];
break;
case 0x08: /* Techncially, revision, but we return the card (slot) here. */
ret = dev->card;
case 0x08: /* Techncially, revision, but we return the slot here. */
ret = dev->pci_slot;
break;
case 0x10: /* PCI_BAR 7:5 */
@@ -236,7 +243,7 @@ pci_dummy_pci_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x3c: /* PCI_ILR */
pclog("AB0B:071A Device %02X: IRQ now: %i\n", dev->card, val);
pclog("AB0B:071A Device %02X: IRQ now: %i\n", dev->pci_slot, val);
dev->pci_regs[addr] = val;
return;
@@ -273,7 +280,7 @@ pci_dummy_card_init(UNUSED(const device_t *info))
{
pci_dummy_t *dev = (pci_dummy_t *) calloc(1, sizeof(pci_dummy_t));
dev->card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev);
pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev, &dev->pci_slot);
return dev;
}

368
src/pic.c
View File

@@ -51,20 +51,21 @@ pic_t pic2;
static pc_timer_t pic_timer;
static uint16_t smi_irq_mask = 0x0000;
static uint16_t smi_irq_status = 0x0000;
static uint16_t enabled_latches = 0x0000;
static uint16_t latched_irqs = 0x0000;
static int shadow = 0;
static int elcr_enabled = 0;
static int tmr_inited = 0;
static int latched = 0;
static int pic_pci = 0;
static int kbd_latch = 0;
static int mouse_latch = 0;
static uint16_t smi_irq_mask = 0x0000;
static uint16_t smi_irq_status = 0x0000;
static void (*update_pending)(void);
static uint16_t latched_irqs = 0x0000;
static void (*update_pending)(void);
static void pic_update_request(pic_t *dev, int irq);
static void pic_cascade(int set);
#ifdef ENABLE_PIC_LOG
int pic_do_log = ENABLE_PIC_LOG;
@@ -223,12 +224,7 @@ find_best_interrupt(pic_t *dev)
static __inline void
pic_update_pending_xt(void)
{
if (find_best_interrupt(&pic) != -1) {
latched++;
if (latched == 1)
timer_on_auto(&pic_timer, 0.35);
} else if (latched == 0)
pic.int_pending = 0;
pic.int_pending = (find_best_interrupt(&pic) != -1);
}
static __inline void
@@ -236,24 +232,15 @@ pic_update_pending_at(void)
{
pic2.int_pending = (find_best_interrupt(&pic2) != -1);
if (pic2.int_pending)
pic.irr |= (1 << pic2.icw3);
else
pic.irr &= ~(1 << pic2.icw3);
pic_cascade(pic2.int_pending);
pic.int_pending = (find_best_interrupt(&pic) != -1);
}
static void
pic_callback(void *priv)
pic_callback(UNUSED(void *priv))
{
pic_t *dev = (pic_t *) priv;
dev->int_pending = 1;
latched--;
if (latched > 0)
timer_on_auto(&pic_timer, 0.35);
update_pending();
}
void
@@ -268,8 +255,13 @@ pic_reset(void)
pic.is_master = 1;
pic.interrupt = pic2.interrupt = 0x17;
if (is_at)
pic.has_slaves = 0;
pic2.has_slaves = 0;
if (is_at) {
pic.slaves[2] = &pic2;
pic.has_slaves = 1;
}
if (tmr_inited)
timer_on_auto(&pic_timer, 0.0);
@@ -326,8 +318,16 @@ pic_acknowledge(pic_t *dev)
int pic_int_num = 1 << pic_int;
dev->isr |= pic_int_num;
if (!pic_level_triggered(dev, pic_int) || !(dev->lines & pic_int_num))
dev->irr &= ~pic_int_num;
/* Simulate the clearing of the edge pulse. */
dev->edge_lines &= ~pic_int_num;
/* Clear the edge sense latch. */
dev->irq_latch &= ~pic_int_num;
dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not
override the one currently being processed. */
/* Clear the reset latch. */
pic_update_request(dev, pic_int);
}
/* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ
@@ -403,12 +403,12 @@ pic_latch_read(UNUSED(uint16_t addr), UNUSED(void *priv))
{
uint8_t ret = 0xff;
pic_log("pic_latch_read(%i, %i): %02X%02X\n", kbd_latch, mouse_latch, pic2.lines & 0x10, pic.lines & 0x02);
pic_log("pic_latch_read(%04X): %02X%02X\n", enabled_latches, latched_irqs & 0x10, latched_irqs & 0x02);
if (kbd_latch && (latched_irqs & 0x0002))
if ((latched_irqs & enabled_latches) & 0x0002)
picintc(0x0002);
if (mouse_latch && (latched_irqs & 0x1000))
if ((latched_irqs & enabled_latches) & 0x1000)
picintc(0x1000);
/* Return FF - we just lower IRQ 1 and IRQ 12. */
@@ -433,12 +433,8 @@ pic_read(uint16_t addr, void *priv)
}
} else {
/* Standard 8259 PIC read */
#ifndef UNDEFINED_READ
/* Put the IRR on to the data bus by default until the real PIC is probed. */
dev->data_bus = dev->irr;
#endif
if (dev->ocw3 & 0x04) {
dev->interrupt &= ~0x20; /* Freeze the interrupt until the poll is over. */
dev->flags &= ~PIC_FREEZE; /* Freeze the interrupt until the poll is over. */
if (dev->int_pending) {
dev->data_bus = 0x80 | (dev->interrupt & 7);
pic_acknowledge(dev);
@@ -452,10 +448,8 @@ pic_read(uint16_t addr, void *priv)
else if (dev->ocw3 & 0x02) {
if (dev->ocw3 & 0x01)
dev->data_bus = dev->isr;
#ifdef UNDEFINED_READ
else
dev->data_bus = 0x00;
#endif
dev->data_bus = dev->irr;
}
/* If A0 = 0, VIA shadow is disabled, and poll mode is disabled,
simply read whatever is currently on the data bus. */
@@ -470,6 +464,7 @@ static void
pic_write(uint16_t addr, uint8_t val, void *priv)
{
pic_t *dev = (pic_t *) priv;
uint8_t i;
pic_log("pic_write(%04X, %02X, %08X)\n", addr, val, priv);
@@ -494,7 +489,10 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
break;
case STATE_NONE:
dev->imr = val;
update_pending();
if (is286)
update_pending();
else
timer_on_auto(&pic_timer, 1.0 * ((10000000.0 * (double) xt_cpu_multi) / (double) cpu_s->rspeed));
break;
default:
@@ -511,7 +509,13 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
if (!(dev->icw1 & 1))
dev->icw4 = 0x00;
dev->ocw2 = dev->ocw3 = 0x00;
dev->irr = dev->lines;
dev->irr = 0x00;
dev->edge_lines = 0x00;
dev->irq_latch = 0x00;
dev->flags |= PIC_MASTER_CLEAR;
for (i = 0; i <= 7; i++)
pic_update_request(dev, i);
dev->flags &= ~PIC_MASTER_CLEAR;
dev->imr = dev->isr = 0x00;
dev->ack_bytes = dev->priority = 0x00;
dev->auto_eoi_rotate = dev->special_mask_mode = 0x00;
@@ -522,7 +526,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
} else if (val & 0x08) {
dev->ocw3 = val;
if (dev->ocw3 & 0x04)
dev->interrupt |= 0x20; /* Freeze the interrupt until the poll is over. */
dev->flags |= PIC_FREEZE; /* Freeze the interrupt until the poll is over. */
if (dev->ocw3 & 0x40)
dev->special_mask_mode = !!(dev->ocw3 & 0x20);
} else {
@@ -554,12 +558,15 @@ pic_set_pci(void)
void
pic_kbd_latch(int enable)
{
uint16_t old_latches = enabled_latches;
pic_log("PIC keyboard latch now %sabled\n", enable ? "en" : "dis");
if (!!(enable | mouse_latch) != !!(kbd_latch | mouse_latch))
io_handler(!!(enable | mouse_latch), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL);
enable = (!!enable) << 1;
enabled_latches = (enabled_latches & 0x1000) | enable;
kbd_latch = !!enable;
if (!!(enabled_latches & 0x1002) != !!(old_latches & 0x1002))
io_handler(!!(enabled_latches & 0x1002), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL);
if (!enable)
picintc(0x0002);
@@ -568,12 +575,15 @@ pic_kbd_latch(int enable)
void
pic_mouse_latch(int enable)
{
uint16_t old_latches = enabled_latches;
pic_log("PIC mouse latch now %sabled\n", enable ? "en" : "dis");
if (!!(kbd_latch | enable) != !!(kbd_latch | mouse_latch))
io_handler(!!(kbd_latch | enable), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL);
enable = (!!enable) << 12;
enabled_latches = (enabled_latches & 0x0002) | enable;
mouse_latch = !!enable;
if (!!(enabled_latches & 0x1002) != !!(old_latches & 0x1002))
io_handler(!!(enabled_latches & 0x1002), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL);
if (!enable)
picintc(0x1000);
@@ -585,11 +595,11 @@ pic_reset_hard(void)
pic_reset();
/* Explicitly reset the latches. */
kbd_latch = mouse_latch = 0;
enabled_latches = 0x0000;
latched_irqs = 0x0000;
/* The situation is as follows: There is a giant mess when it comes to these latches on real hardware,
to the point that there's even boards with board-level latched that get used in place of the latches
to the point that there's even boards with board-level latches that get used in place of the latches
on the chipset, therefore, I'm just doing this here for the sake of simplicity. */
if (machine_has_bus(machine, MACHINE_BUS_PS2_LATCH)) {
pic_kbd_latch(0x01);
@@ -626,30 +636,131 @@ pic2_init(void)
}
void
picint_common(uint16_t num, int level, int set)
pic_update_lines(pic_t *dev, uint16_t num, int level, int set, uint8_t *irq_state)
{
int raise;
uint8_t b;
uint8_t slaves = 0;
uint8_t old_edge_lines, bit;
switch (level) {
case PIC_IRQ_EDGE:
old_edge_lines = dev->edge_lines;
dev->edge_lines &= ~num;
if (set)
dev->edge_lines |= num;
if ((dev->isr & num) || (dev->flags & PIC_MASTER_CLEAR))
dev->irq_latch = (dev->irq_latch & ~num) | (dev->edge_lines & num);
else if ((dev->edge_lines & num) && !(old_edge_lines & num))
dev->irq_latch |= num;
break;
case PIC_IRQ_LEVEL:
for (uint8_t i = 0; i < 8; i++) {
bit = (1 << i);
if ((num & bit) && ((!!*irq_state) != !!set))
dev->lines[i] += (set ? 1 : -1);
}
if ((!!*irq_state) != !!set)
*irq_state = set;
break;
}
}
static uint8_t
pic_irq_get_request(pic_t *dev, int irq)
{
uint8_t ret;
ret = ((dev->edge_lines & (1 << irq)) || (dev->lines[irq] > 0));
pic_log("pic_irq_get_request(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
return ret;
}
static uint8_t
pic_es_latch_clear(pic_t *dev, int irq)
{
uint8_t ret;
ret = (dev->isr & (1 << irq)) || (dev->flags & PIC_MASTER_CLEAR);
pic_log("pic_es_latch_clear(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
return ret;
}
static uint8_t
pic_es_latch_out(pic_t *dev, int irq)
{
uint8_t ret;
ret = !((pic_es_latch_clear(dev, irq) && (dev->irq_latch & (1 << irq))) || !pic_irq_get_request(dev, irq));
pic_log("pic_es_latch_out(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
return ret;
}
static uint8_t
pic_es_latch_nor(pic_t *dev, int irq)
{
uint8_t ret;
ret = !(pic_es_latch_out(dev, irq) || picint_is_level(irq));
pic_log("pic_es_latch_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
return ret;
}
static uint8_t
pic_irq_request_nor(pic_t *dev, int irq)
{
uint8_t ret;
ret = !(pic_es_latch_nor(dev, irq) || !pic_irq_get_request(dev, irq));
pic_log("pic_irq_request_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
return ret;
}
static void
pic_update_request(pic_t *dev, int irq)
{
dev->irr &= ~(1 << irq);
if (dev->flags & PIC_FREEZE) {
pic_log("pic_update_request(%08X, %i): FREEZE#\n", (uint32_t) (uintptr_t) dev, irq);
} else {
dev->irr |= (pic_irq_request_nor(dev, irq) << irq);
pic_log("pic_update_request(%08X, %i): IRR = %02X\n", (uint32_t) (uintptr_t) dev, irq, dev->irr);
}
}
static void
pic_update_irr(pic_t *dev, uint16_t num)
{
for (uint8_t i = 0; i < 8; i++) {
if (num & (1 << i))
pic_update_request(dev, i);
}
pic_log("IRQ %04x: IRR now: %02X\n", num, dev->irr);
}
void
picint_common(uint16_t num, int level, int set, uint8_t *irq_state)
{
pic_log("picint_common(%04X, %i, %i, %08X)\n", num, level, set, (uint32_t) (uintptr_t) irq_state);
set = !!set;
/* Make sure to ignore all slave IRQ's, and in case of AT+,
translate IRQ 2 to IRQ 9. */
for (uint8_t i = 0; i < 8; i++) {
b = (uint8_t) (1 << i);
raise = num & b;
if (pic.icw3 & b) {
slaves++;
if (raise) {
num &= ~b;
if (pic.at && (i == 2))
num |= (1 << 9);
}
}
if (num & pic.icw3) {
num &= ~pic.icw3;
if (pic.at)
num |= (1 << 9);
}
if (!slaves)
if (!pic.has_slaves)
num &= 0x00ff;
if (!num) {
@@ -660,77 +771,41 @@ picint_common(uint16_t num, int level, int set)
if (num & 0x0100)
acpi_rtc_status = !!set;
if (set) {
if (smi_irq_mask & num) {
smi_raise();
smi_irq_status |= num;
}
if (num & 0xff00) {
if (level)
pic2.lines |= (num >> 8);
/* Latch IRQ 12 if the mouse latch is enabled. */
if ((num & 0x1000) && mouse_latch)
latched_irqs |= 0x1000;
pic2.irr |= (num >> 8);
}
if (num & 0x00ff) {
if (level)
pic.lines |= (num & 0x00ff);
/* Latch IRQ 1 if the keyboard latch is enabled. */
if (kbd_latch && (num & 0x0002))
latched_irqs |= 0x0002;
pic.irr |= (num & 0x00ff);
}
} else {
smi_irq_status &= ~num;
if (num & 0xff00) {
pic2.lines &= ~(num >> 8);
/* Unlatch IRQ 12 if the mouse latch is enabled. */
if ((num & 0x1000) && mouse_latch)
latched_irqs &= 0xefff;
pic2.irr &= ~(num >> 8);
}
if (num & 0x00ff) {
pic.lines &= ~(num & 0x00ff);
/* Unlatch IRQ 1 if the keyboard latch is enabled. */
if (kbd_latch && (num & 0x0002))
latched_irqs &= 0xfffd;
pic.irr &= ~(num & 0x00ff);
}
smi_irq_status &= ~num;
if (set && (smi_irq_mask & num)) {
smi_raise();
smi_irq_status |= num;
}
if (!(pic.interrupt & 0x20) && !(pic2.interrupt & 0x20))
if (num & 0xff00) {
pic_update_lines(&pic2, num >> 8, level, set, irq_state);
/* Latch IRQ 12 if the mouse latch is enabled. */
if ((num & enabled_latches) & 0x1000)
latched_irqs = (latched_irqs & 0xefff) | (set << 12);
pic_update_irr(&pic2, num >> 8);
}
if (num & 0x00ff) {
pic_update_lines(&pic, num & 0x00ff, level, set, irq_state);
/* Latch IRQ 1 if the keyboard latch is enabled. */
if ((num & enabled_latches) & 0x0002)
latched_irqs = (latched_irqs & 0xfffd) | (set << 1);
pic_update_irr(&pic, num & 0x00ff);
}
if (!(pic.flags & PIC_FREEZE) && !(pic2.flags & PIC_FREEZE))
update_pending();
}
void
picint(uint16_t num)
static void
pic_cascade(int set)
{
picint_common(num, 0, 1);
}
void
picintlevel(uint16_t num)
{
picint_common(num, 1, 1);
}
void
picintc(uint16_t num)
{
picint_common(num, 0, 0);
pic_update_lines(&pic, (1 << pic2.icw3), PIC_IRQ_EDGE, set, NULL);
pic_update_irr(&pic, (1 << pic2.icw3));
}
static uint8_t
@@ -742,15 +817,12 @@ pic_i86_mode(pic_t *dev)
static uint8_t
pic_irq_ack_read(pic_t *dev, int phase)
{
uint8_t intr = dev->interrupt & 0x47;
uint8_t slave = intr & 0x40;
intr &= 0x07;
uint8_t intr = dev->interrupt & 0x07;
uint8_t slave = dev->flags & PIC_SLAVE_PENDING;
pic_log(" pic_irq_ack_read(%08X, %i)\n", dev, phase);
if (dev != NULL) {
if (phase == 0) {
dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not
override the one currently being processed. */
pic_acknowledge(dev);
if (slave)
dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase);
@@ -796,7 +868,7 @@ pic_irq_ack(void)
exit(-1);
}
pic.interrupt |= 0x40; /* Mark slave pending. */
pic.flags |= PIC_SLAVE_PENDING;
}
ret = pic_irq_ack_read(&pic, pic.ack_bytes);
@@ -804,8 +876,13 @@ pic_irq_ack(void)
if (pic.ack_bytes == 0) {
/* Needed for Xi8088. */
if (pic.interrupt & 0x40)
if (pic.flags & PIC_SLAVE_PENDING) {
pic2.flags &= ~PIC_FREEZE;
pic_update_request(&pic2, pic2.interrupt & 0x07);
pic2.interrupt = 0x17;
}
pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE);
pic_update_request(&pic, pic.interrupt & 0x07);
pic.interrupt = 0x17;
update_pending();
}
@@ -826,7 +903,7 @@ picinterrupt(void)
exit(-1);
}
pic.interrupt |= 0x40; /* Mark slave pending. */
pic.flags |= PIC_SLAVE_PENDING;
}
if ((pic.interrupt == 0) && (pit_devs[1].data != NULL))
@@ -838,8 +915,13 @@ picinterrupt(void)
pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3);
if (pic.ack_bytes == 0) {
if (pic.interrupt & 0x40)
if (pic.flags & PIC_SLAVE_PENDING) {
pic2.flags &= ~PIC_FREEZE;
pic_update_request(&pic2, pic2.interrupt & 0x07);
pic2.interrupt = 0x17;
}
pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE);
pic_update_request(&pic, pic.interrupt & 0x07);
pic.interrupt = 0x17;
update_pending();
}

View File

@@ -37,21 +37,6 @@ static std::vector<std::pair<int, libevdev *>> evdev_mice;
static std::atomic<bool> stopped = false;
static QThread *evdev_thread;
static std::atomic<int> evdev_mouse_rel_x = 0, evdev_mouse_rel_y = 0;
void
evdev_mouse_poll()
{
if (!evdev_mice.size() || !mouse_capture) {
evdev_mouse_rel_x = 0;
evdev_mouse_rel_y = 0;
return;
}
mouse_x = evdev_mouse_rel_x;
mouse_y = evdev_mouse_rel_y;
evdev_mouse_rel_x = evdev_mouse_rel_y = 0;
}
void
evdev_thread_func()
{
@@ -67,11 +52,11 @@ evdev_thread_func()
struct input_event ev;
if (pfds[i].revents & POLLIN) {
while (libevdev_next_event(evdev_mice[i].second, LIBEVDEV_READ_FLAG_NORMAL, &ev) == 0) {
if (ev.type == EV_REL && mouse_capture) {
if (evdev_mice.size() && (ev.type == EV_REL) && mouse_capture) {
if (ev.code == REL_X)
evdev_mouse_rel_x += ev.value;
mouse_scale_x(ev.value);
if (ev.code == REL_Y)
evdev_mouse_rel_y += ev.value;
mouse_scale_y(ev.value);
}
}
}

View File

@@ -1,4 +1,3 @@
#ifdef EVDEV_INPUT
void evdev_init();
void evdev_mouse_poll();
#endif

View File

@@ -17,13 +17,6 @@ extern int mouse_capture;
extern void plat_mouse_capture(int);
}
typedef struct mouseinputdata {
int deltax, deltay, deltaz;
int mousebuttons;
} mouseinputdata;
static mouseinputdata mousedata;
CocoaEventFilter::~CocoaEventFilter()
{
}
@@ -31,6 +24,8 @@ CocoaEventFilter::~CocoaEventFilter()
bool
CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, result_t *result)
{
int b = 0;
if (mouse_capture) {
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = (NSEvent *) message;
@@ -38,12 +33,11 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message,
|| [event type] == NSEventTypeLeftMouseDragged
|| [event type] == NSEventTypeRightMouseDragged
|| [event type] == NSEventTypeOtherMouseDragged) {
mousedata.deltax += [event deltaX];
mousedata.deltay += [event deltaY];
mouse_scale([event deltaX], [event deltaY]);
return true;
}
if ([event type] == NSEventTypeScrollWheel) {
mousedata.deltaz += [event deltaY];
mouse_set_z([event deltaY]);
return true;
}
switch ([event type]) {
@@ -51,27 +45,32 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message,
return false;
case NSEventTypeLeftMouseDown:
{
mousedata.mousebuttons |= 1;
b = mouse_get_buttons_ex() | 1;
mouse_set_buttons_ex(b);
break;
}
case NSEventTypeLeftMouseUp:
{
mousedata.mousebuttons &= ~1;
b = mouse_get_buttons_ex() & ~1;
mouse_set_buttons_ex(b);
break;
}
case NSEventTypeRightMouseDown:
{
mousedata.mousebuttons |= 2;
b = mouse_get_buttons_ex() | 2;
mouse_set_buttons_ex(b);
break;
}
case NSEventTypeRightMouseUp:
{
mousedata.mousebuttons &= ~2;
b = mouse_get_buttons_ex() & ~2;
mouse_set_buttons_ex(b);
break;
}
case NSEventTypeOtherMouseDown:
{
mousedata.mousebuttons |= 4;
b = mouse_get_buttons_ex() | 4;
mouse_set_buttons_ex(b);
break;
}
case NSEventTypeOtherMouseUp:
@@ -80,7 +79,8 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message,
plat_mouse_capture(0);
return true;
}
mousedata.mousebuttons &= ~4;
b = mouse_get_buttons_ex() & ~4;
mouse_set_buttons_ex(b);
break;
}
}
@@ -89,13 +89,3 @@ CocoaEventFilter::nativeEventFilter(const QByteArray &eventType, void *message,
}
return false;
}
extern "C" void
macos_poll_mouse()
{
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
}

View File

@@ -256,7 +256,6 @@ main(int argc, char *argv[])
auto rawInputFilter = WindowsRawInputFilter::Register(main_window);
if (rawInputFilter) {
app.installNativeEventFilter(rawInputFilter.get());
QObject::connect(main_window, &MainWindow::pollMouse, (WindowsRawInputFilter *) rawInputFilter.get(), &WindowsRawInputFilter::mousePoll, Qt::DirectConnection);
main_window->setSendKeyboardInput(false);
}
#endif

View File

@@ -253,8 +253,6 @@ MainWindow::MainWindow(QWidget *parent)
emit updateMenuResizeOptions();
connect(this, &MainWindow::pollMouse, ui->stackedWidget, &RendererStack::mousePoll, Qt::DirectConnection);
connect(this, &MainWindow::setMouseCapture, this, [this](bool state) {
mouse_capture = state ? 1 : 0;
qt_mouse_capture(mouse_capture);
@@ -630,7 +628,7 @@ MainWindow::MainWindow(QWidget *parent)
setContextMenuPolicy(Qt::PreventContextMenu);
/* Remove default Shift+F10 handler, which unfocuses keyboard input even with no context menu. */
connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [this](){});
connect(new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F10), this), &QShortcut::activated, this, [](){});
connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot);
connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection);
@@ -764,7 +762,6 @@ MainWindow::initRendererMonitorSlot(int monitor_index)
secondaryRenderer->switchRenderer((RendererStack::Renderer) vid_api);
secondaryRenderer->setMouseTracking(true);
}
connect(this, &MainWindow::pollMouse, secondaryRenderer.get(), &RendererStack::mousePoll, Qt::DirectConnection);
}
}
@@ -890,6 +887,9 @@ MainWindow::on_actionSettings_triggered()
Settings settings(this);
settings.setModal(true);
settings.setWindowModality(Qt::WindowModal);
settings.setWindowFlag(Qt::CustomizeWindowHint, true);
settings.setWindowFlag(Qt::WindowTitleHint, true);
settings.setWindowFlag(Qt::WindowSystemMenuHint, false);
settings.exec();
switch (settings.result()) {

View File

@@ -39,7 +39,6 @@ signals:
void paint(const QImage &image);
void resizeContents(int w, int h);
void resizeContentsMonitor(int w, int h, int monitor_index);
void pollMouse();
void statusBarMessage(const QString &msg);
void updateStatusBarPanes();
void updateStatusBarActivity(int tag, bool active);

View File

@@ -49,26 +49,21 @@
extern "C" {
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/video.h>
double mouse_sensitivity = 1.0;
double mouse_x_error = 0.0, mouse_y_error = 0.0;
#include <86box/mouse.h>
}
struct mouseinputdata {
atomic_int deltax;
atomic_int deltay;
atomic_int deltaz;
atomic_int mousebuttons;
atomic_bool mouse_tablet_in_proximity;
std::atomic<double> x_abs;
std::atomic<double> y_abs;
char *mouse_type;
};
static mouseinputdata mousedata;
extern "C" void macos_poll_mouse();
extern MainWindow *main_window;
RendererStack::RendererStack(QWidget *parent, int monitor_index)
: QStackedWidget(parent)
@@ -78,8 +73,9 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index)
m_monitor_index = monitor_index;
#if defined __unix__ && !defined __HAIKU__
char *mouse_type = getenv("EMU86BOX_MOUSE"), auto_mouse_type[16];
if (!mouse_type || (mouse_type[0] == '\0') || !stricmp(mouse_type, "auto")) {
char auto_mouse_type[16];
mousedata.mouse_type = getenv("EMU86BOX_MOUSE");
if (!mousedata.mouse_type || (mousedata.mouse_type[0] == '\0') || !stricmp(mousedata.mouse_type, "auto")) {
if (QApplication::platformName().contains("wayland"))
strcpy(auto_mouse_type, "wayland");
else if (QApplication::platformName() == "eglfs")
@@ -88,35 +84,27 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index)
strcpy(auto_mouse_type, "xinput2");
else
auto_mouse_type[0] = '\0';
mouse_type = auto_mouse_type;
mousedata.mouse_type = auto_mouse_type;
}
# ifdef WAYLAND
if (!stricmp(mouse_type, "wayland")) {
if (!stricmp(mousedata.mouse_type, "wayland")) {
wl_init();
this->mouse_poll_func = wl_mouse_poll;
this->mouse_capture_func = wl_mouse_capture;
this->mouse_uncapture_func = wl_mouse_uncapture;
}
# endif
# ifdef EVDEV_INPUT
if (!stricmp(mouse_type, "evdev")) {
if (!stricmp(mousedata.mouse_type, "evdev"))
evdev_init();
this->mouse_poll_func = evdev_mouse_poll;
}
# endif
if (!stricmp(mouse_type, "xinput2")) {
if (!stricmp(mousedata.mouse_type, "xinput2")) {
extern void xinput2_init();
extern void xinput2_poll();
extern void xinput2_exit();
xinput2_init();
this->mouse_poll_func = xinput2_poll;
this->mouse_exit_func = xinput2_exit;
}
#endif
#ifdef __APPLE__
this->mouse_poll_func = macos_poll_mouse;
#endif
}
RendererStack::~RendererStack()
@@ -149,49 +137,25 @@ RendererStack::mousePoll()
{
if (m_monitor_index >= 1) {
if (mouse_mode >= 1) {
mouse_x_abs = mousedata.x_abs;
mouse_y_abs = mousedata.y_abs;
if (!mouse_tablet_in_proximity) {
mouse_x_abs = mousedata.x_abs;
mouse_y_abs = mousedata.y_abs;
if (!mouse_tablet_in_proximity)
mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity;
}
if (mousedata.mouse_tablet_in_proximity) {
mouse_buttons = mousedata.mousebuttons;
}
}
return;
}
#ifdef Q_OS_WINDOWS
if (mouse_mode == 0) {
mouse_x_abs = mousedata.x_abs;
mouse_y_abs = mousedata.y_abs;
mouse_x_abs = mousedata.x_abs;
mouse_y_abs = mousedata.y_abs;
return;
}
#endif
#ifndef __APPLE__
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
if (this->mouse_poll_func)
#endif
this->mouse_poll_func();
mouse_x_abs = mousedata.x_abs;
mouse_y_abs = mousedata.y_abs;
mouse_tablet_in_proximity = mousedata.mouse_tablet_in_proximity;
double scaled_x = mouse_x * mouse_sensitivity + mouse_x_error;
double scaled_y = mouse_y * mouse_sensitivity + mouse_y_error;
mouse_x = static_cast<int>(scaled_x);
mouse_y = static_cast<int>(scaled_y);
mouse_x_error = scaled_x - mouse_x;
mouse_y_error = scaled_y - mouse_y;
}
int ignoreNextMouseEvent = 1;
@@ -212,8 +176,9 @@ RendererStack::mouseReleaseEvent(QMouseEvent *event)
isMouseDown &= ~1;
return;
}
if (mouse_capture || mouse_mode >= 1) {
mousedata.mousebuttons &= ~event->button();
if (mouse_capture || (mouse_mode >= 1)) {
if ((mouse_mode >= 1) && ((m_monitor_index < 1) || mousedata.mouse_tablet_in_proximity))
mouse_set_buttons_ex(mouse_get_buttons_ex() & ~event->button());
}
isMouseDown &= ~1;
}
@@ -222,8 +187,9 @@ void
RendererStack::mousePressEvent(QMouseEvent *event)
{
isMouseDown |= 1;
if (mouse_capture || mouse_mode >= 1) {
mousedata.mousebuttons |= event->button();
if (mouse_capture || (mouse_mode >= 1)) {
if ((mouse_mode >= 1) && ((m_monitor_index < 1) || mousedata.mouse_tablet_in_proximity))
mouse_set_buttons_ex(mouse_get_buttons_ex() | event->button());
}
event->accept();
}
@@ -231,9 +197,7 @@ RendererStack::mousePressEvent(QMouseEvent *event)
void
RendererStack::wheelEvent(QWheelEvent *event)
{
if (mouse_capture) {
mousedata.deltaz += event->pixelDelta().y();
}
mouse_set_z(event->pixelDelta().y());
}
void
@@ -258,8 +222,12 @@ RendererStack::mouseMoveEvent(QMouseEvent *event)
event->accept();
return;
}
mousedata.deltax += event->pos().x() - oldPos.x();
mousedata.deltay += event->pos().y() - oldPos.y();
#if defined __unix__ && !defined __HAIKU__
if (!stricmp(mousedata.mouse_type, "wayland"))
mouse_scale(event->pos().x() - oldPos.x(), event->pos().y() - oldPos.y());
#endif
if (QApplication::platformName() == "eglfs") {
leaveEvent((QEvent *) event);
ignoreNextMouseEvent--;

View File

@@ -82,9 +82,9 @@ public:
rendererWindow->onResize(width, height);
}
void (*mouse_poll_func)() = nullptr;
void (*mouse_capture_func)(QWindow *window) = nullptr;
void (*mouse_uncapture_func)() = nullptr;
void (*mouse_exit_func)() = nullptr;
signals:

View File

@@ -198,12 +198,6 @@ static const uint16_t sdl_to_xt[0x200] = {
[SDL_SCANCODE_NONUSBACKSLASH] = 0x56,
};
typedef struct mouseinputdata {
int deltax, deltay, deltaz;
int mousebuttons;
} mouseinputdata;
static mouseinputdata mousedata;
// #define ENABLE_SDL_LOG 3
#ifdef ENABLE_SDL_LOG
int sdl_do_log = ENABLE_SDL_LOG;
@@ -620,16 +614,14 @@ sdl_main()
event.wheel.x *= -1;
event.wheel.y *= -1;
}
mousedata.deltaz = event.wheel.y;
mouse_set_z(event.wheel.y);
}
break;
}
case SDL_MOUSEMOTION:
{
if (mouse_capture || video_fullscreen) {
mousedata.deltax += event.motion.xrel;
mousedata.deltay += event.motion.yrel;
}
if (mouse_capture || video_fullscreen)
mouse_scale(event.motion.xrel, event.motion.yrel);
break;
}
case SDL_MOUSEBUTTONDOWN:
@@ -660,10 +652,10 @@ sdl_main()
buttonmask = 4;
break;
}
if (event.button.state == SDL_PRESSED) {
mousedata.mousebuttons |= buttonmask;
} else
mousedata.mousebuttons &= ~buttonmask;
if (event.button.state == SDL_PRESSED)
mouse_set_buttons_ex(mouse_get_buttons_ex() | buttonmask);
else
mouse_set_buttons_ex(mouse_get_buttons_ex() & ~buttonmask);
}
break;
}
@@ -714,13 +706,3 @@ sdl_mouse_capture(int on)
{
SDL_SetRelativeMouseMode((SDL_bool) on);
}
void
sdl_mouse_poll()
{
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
}

View File

@@ -68,6 +68,5 @@ enum sdl_main_status {
extern enum sdl_main_status sdl_main();
extern void sdl_mouse_capture(int on);
extern void sdl_mouse_poll();
#endif /*WIN_SDL_H*/

View File

@@ -88,12 +88,6 @@ qt_blit(int x, int y, int w, int h, int monitor_index)
main_window->blitToWidget(x, y, w, h, monitor_index);
}
void
mouse_poll()
{
main_window->pollMouse();
}
extern "C" int vid_resize;
void
plat_resize_request(int w, int h, int monitor_index)

View File

@@ -35,6 +35,8 @@
#include <QMenuBar>
#include <atomic>
#include <windows.h>
#include <86box/keyboard.h>
@@ -338,85 +340,71 @@ void
WindowsRawInputFilter::mouse_handle(PRAWINPUT raw)
{
RAWMOUSE state = raw->data.mouse;
static int x;
static int y;
static int x, delta_x;
static int y, delta_y;
static int b, delta_z;
b = mouse_get_buttons_ex();
/* read mouse buttons and wheel */
if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
buttons |= 1;
b |= 1;
else if (state.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP)
buttons &= ~1;
b &= ~1;
if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
buttons |= 4;
b |= 4;
else if (state.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
buttons &= ~4;
b &= ~4;
if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
buttons |= 2;
b |= 2;
else if (state.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
buttons &= ~2;
b &= ~2;
if (state.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN)
buttons |= 8;
b |= 8;
else if (state.usButtonFlags & RI_MOUSE_BUTTON_4_UP)
buttons &= ~8;
b &= ~8;
if (state.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN)
buttons |= 16;
b |= 16;
else if (state.usButtonFlags & RI_MOUSE_BUTTON_5_UP)
buttons &= ~16;
b &= ~16;
mouse_set_buttons_ex(b);
if (state.usButtonFlags & RI_MOUSE_WHEEL) {
dwheel += (SHORT) state.usButtonData / 120;
}
delta_z = (SHORT) state.usButtonData / 120;
mouse_set_z(delta_z);
} else
delta_z = 0;
if (state.usFlags & MOUSE_MOVE_ABSOLUTE) {
/* absolute mouse, i.e. RDP or VNC
* seems to work fine for RDP on Windows 10
* Not sure about other environments.
*/
dx += (state.lLastX - x) / 25;
dy += (state.lLastY - y) / 25;
delta_x = (state.lLastX - x) / 25;
delta_y = (state.lLastY - y) / 25;
x = state.lLastX;
y = state.lLastY;
} else {
/* relative mouse, i.e. regular mouse */
dx += state.lLastX;
dy += state.lLastY;
delta_x = state.lLastX;
delta_y = state.lLastY;
}
HWND wnd = (HWND) window->winId();
mouse_scale(delta_x, delta_y);
HWND wnd = (HWND)window->winId();
RECT rect;
GetWindowRect(wnd, &rect);
int left = rect.left + (rect.right - rect.left) / 2;
int top = rect.top + (rect.bottom - rect.top) / 2;
int top = rect.top + (rect.bottom - rect.top) / 2;
SetCursorPos(left, top);
}
void
WindowsRawInputFilter::mousePoll()
{
if (mouse_mode >= 1) return;
if (mouse_capture || video_fullscreen) {
static int b = 0;
if (dx != 0 || dy != 0 || dwheel != 0) {
mouse_x += dx;
mouse_y += dy;
mouse_z = dwheel;
dx = 0;
dy = 0;
dwheel = 0;
}
if (b != buttons) {
mouse_buttons = buttons;
b = buttons;
}
}
}

View File

@@ -59,9 +59,6 @@ public:
~WindowsRawInputFilter();
public slots:
void mousePoll();
private:
MainWindow *window;
uint16_t scancode_map[768];

View File

@@ -26,6 +26,7 @@
#include <QGuiApplication>
extern "C" {
#include <86box/mouse.h>
#include <86box/plat.h>
}
@@ -34,28 +35,12 @@ static zwp_relative_pointer_v1 *rel_pointer = nullptr;
static zwp_pointer_constraints_v1 *conf_pointer_interface = nullptr;
static zwp_locked_pointer_v1 *conf_pointer = nullptr;
static int rel_mouse_x = 0;
static int rel_mouse_y = 0;
static bool wl_init_ok = false;
void
rel_mouse_event(void *data, zwp_relative_pointer_v1 *zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real)
{
rel_mouse_x += wl_fixed_to_int(dx_real);
rel_mouse_y += wl_fixed_to_int(dy_real);
}
extern "C" {
extern int mouse_x, mouse_y;
}
void
wl_mouse_poll()
{
mouse_x = rel_mouse_x;
mouse_y = rel_mouse_y;
rel_mouse_x = 0;
rel_mouse_y = 0;
mouse_scale(wl_fixed_to_int(dx_real), wl_fixed_to_int(dy_real));
}
static struct zwp_relative_pointer_v1_listener rel_listener = {

Some files were not shown because too many files have changed in this diff Show More