Fixed SMM, overhauled the emulation of the VIA northbridges, and added the Via Apollo VP3.

This commit is contained in:
OBattler
2020-04-01 08:59:29 +02:00
parent 2c8bcea38c
commit b8b198a56a
37 changed files with 1915 additions and 5024 deletions

View File

@@ -51,7 +51,8 @@ enum
typedef struct
{
uint8_t pm2_cntrl, max_func;
uint8_t pm2_cntrl, max_func,
smram_locked;
uint8_t regs[2][256], regs_locked[2][256];
int type;
} i4x0_t;
@@ -78,6 +79,127 @@ i4x0_map(uint32_t addr, uint32_t size, int state)
}
static void
i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
{
int state = ram ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache();
}
static void
i4x0_smram_handler_phase0(i4x0_t *dev)
{
uint32_t i, n;
/* Disable any active mappings. */
if (dev->type >= INTEL_430FX) {
if (dev->type >= INTEL_440BX) {
/* Disable high extended SMRAM. */
/* TODO: This area should point to A0000-FFFFF. */
for (i = 0x100a0000; i < 0x100fffff; i += MEM_GRANULARITY_SIZE) {
/* This is to make sure that if the remaining area is smaller than
or equal to MEM_GRANULARITY_SIZE, we do not change the state of
too much memory. */
n = ((mem_size << 10) - i);
/* Cap to MEM_GRANULARITY_SIZE if i is either at or beyond the end
of RAM or the remaining area is bigger than MEM_GRANULARITY_SIZE. */
if ((i >= (mem_size << 10)) || (n > MEM_GRANULARITY_SIZE))
n = MEM_GRANULARITY_SIZE;
i4x0_smram_map(0, i, n, (i < (mem_size << 10)));
i4x0_smram_map(1, i, n, (i < (mem_size << 10)));
if (n < MEM_GRANULARITY_SIZE) {
i4x0_smram_map(0, i + n, MEM_GRANULARITY_SIZE - n, 0);
i4x0_smram_map(1, i + n, MEM_GRANULARITY_SIZE - n, 0);
}
}
/* Disable TSEG. */
i4x0_smram_map(1, ((mem_size << 10) - (1 << 20)), (1 << 20), 1);
}
/* Disable low extended SMRAM. */
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
} else {
/* Disable low extended SMRAM. */
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
i4x0_smram_map(0, (mem_size << 10) - 0x10000, 0x10000, 1);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
i4x0_smram_map(1, (mem_size << 10) - 0x10000, 0x10000, 1);
}
}
static void
i4x0_smram_handler_phase1(i4x0_t *dev)
{
uint8_t *regs = (uint8_t *) dev->regs[0];
uint32_t s, base[2] = { 0x000a0000, 0x00020000 };
uint32_t size[2] = { 0, 0 };
if (dev->type >= INTEL_430FX) {
/* Set temporary bases and sizes. */
if ((dev->type >= INTEL_440BX) && (regs[0x73] & 0x80)) {
base[0] = 0x100a0000;
size[0] = 0x00060000;
} else {
base[0] = 0x000a0000;
size[0] = 0x00020000;
}
/* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40));
/* If the register is set accordingly, disable the mapping also in SMM. */
i4x0_smram_map(1, base[0], size[0], ((regs[0x72] & 0x08) && !(regs[0x72] & 0x20)));
/* TSEG mapping. */
if (dev->type >= INTEL_440BX) {
if ((regs[0x72] & 0x08) && (regs[0x73] & 0x01)) {
size[1] = (1 << (17 + ((regs[0x73] >> 1) & 0x03)));
base[1] = (mem_size << 10) - size[1];
} else
base[1] = size[1] = 0x00000000;
i4x0_smram_map(1, base[1], size[1], 1);
} else
base[1] = size[1] = 0x00000000;
} else {
size[0] = 0x00010000;
switch (regs[0x72] & 0x03) {
case 0:
default:
base[0] = (mem_size << 10) - size[0];
s = 1;
break;
case 1:
base[0] = size[0] = 0x00000000;
s = 1;
break;
case 2:
base[0] = 0x000a0000;
s = 0;
break;
case 3:
base[0] = 0x000b0000;
s = 0;
break;
}
if (base[0] != 0x00000000) {
/* If OSS = 1 and LSS = 0, extended SMRAM is visible outside SMM. */
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x38) == 0x20) || s);
/* If the register is set accordingly, disable the mapping also in SMM. */
i4x0_smram_map(0, base[0], size[0], !(regs[0x72] & 0x10) || s);
}
}
}
static void
i4x0_mask_bar(uint8_t *regs)
{
@@ -636,19 +758,27 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
}
break;
case 0x72: /* SMRAM */
i4x0_smram_handler_phase0(dev);
if (dev->type >= INTEL_430FX) {
if ((regs[0x72] & 0x10) || (val & 0x10)) {
regs[0x72] = (val & 0x38) | 0x02;
i4x0_map(0xa0000, 0x20000, 0);
} else {
regs[0x72] = (val & 0x78) | 0x02;
i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0);
if (dev->smram_locked)
regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20);
else {
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
regs[0x72] &= 0xbf;
}
} else {
if ((regs[0x72] ^ val) & 0x20)
i4x0_map(0xa0000, 0x20000, ((val & 0x20) == 0x20) ? 3 : 0);
regs[0x72] = val & 0x3f;
if (dev->smram_locked)
regs[0x72] = (regs[0x72] & 0xef) | (val & 0x10);
else {
regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f);
dev->smram_locked = (val & 0x08);
if (dev->smram_locked)
regs[0x72] &= 0xef;
}
}
i4x0_smram_handler_phase1(dev);
break;
case 0x73:
switch (dev->type) {
@@ -656,7 +786,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x73] = val & 0x03;
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x73] = val;
if (!dev->smram_locked) {
i4x0_smram_handler_phase0(dev);
regs[0x73] = (regs[0x72] & 0x38) | (val & 0xc7);
i4x0_smram_handler_phase1(dev);
}
break;
}
break;

587
src/chipset/via_apollo.c Normal file
View File

@@ -0,0 +1,587 @@
/*
* 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.
*
* Implementation of the VIA Apollo series of chips.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Melissa Goad, <mszoopers@protonmail.com>
* Tiseno100,
*
* Copyright 2020 Miran Grca.
* Copyright 2020 Melissa Goad.
* Copyright 2020 Tiseno100.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_apollo_t
{
uint16_t id;
uint8_t pci_conf[2][256];
} via_apollo_t;
static void
apollo_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
apollo_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
{
int state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (ram == 0)
state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else if (ram == 1)
state = (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else if (ram == 2)
state = (MEM_READ_EXTERNAL_EX | MEM_WRITE_EXTANY);
else if (ram == 3)
state = (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache();
}
static void
via_apollo_setup(via_apollo_t *dev)
{
memset(dev, 0, sizeof(via_apollo_t));
/* Host Bridge */
dev->pci_conf[0][0x00] = 0x06; /*VIA*/
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = dev->id & 0xff;
dev->pci_conf[0][0x03] = (dev->id >> 8);
dev->pci_conf[0][0x04] = 6;
dev->pci_conf[0][0x05] = 0;
dev->pci_conf[0][0x06] = 0x90;
dev->pci_conf[0][0x07] = 0x02;
if (dev->id == 0x0597)
dev->pci_conf[0][0x08] = 1; /* Production Silicon ("Revision B") */
dev->pci_conf[0][0x09] = 0;
dev->pci_conf[0][0x0a] = 0;
dev->pci_conf[0][0x0b] = 6;
dev->pci_conf[0][0x0c] = 0;
dev->pci_conf[0][0x0d] = 0;
dev->pci_conf[0][0x0e] = 0;
dev->pci_conf[0][0x0f] = 0;
dev->pci_conf[0][0x10] = 0x08;
dev->pci_conf[0][0x34] = 0xa0;
if (dev->id == 0x0691) {
dev->pci_conf[0][0x56] = 0x01;
dev->pci_conf[0][0x57] = 0x01;
}
dev->pci_conf[0][0x5a] = 0x01;
dev->pci_conf[0][0x5b] = 0x01;
dev->pci_conf[0][0x5c] = 0x01;
dev->pci_conf[0][0x5d] = 0x01;
dev->pci_conf[0][0x5e] = 0x01;
dev->pci_conf[0][0x5f] = 0x01;
dev->pci_conf[0][0x64] = 0xec;
dev->pci_conf[0][0x65] = 0xec;
dev->pci_conf[0][0x66] = 0xec;
if (dev->id == 0x0691)
dev->pci_conf[0][0x67] = 0xec; /* DRAM Timing for Banks 6,7. */
dev->pci_conf[0][0x6b] = 0x01;
dev->pci_conf[0][0xa0] = 0x02;
dev->pci_conf[0][0xa2] = 0x10;
dev->pci_conf[0][0xa4] = 0x03;
dev->pci_conf[0][0xa5] = 0x02;
dev->pci_conf[0][0xa7] = 0x07;
/* PCI-to-PCI Bridge */
dev->pci_conf[1][0x00] = 0x06; /*VIA*/
dev->pci_conf[1][0x01] = 0x11;
dev->pci_conf[1][0x02] = dev->id & 0xff;
dev->pci_conf[1][0x03] = (dev->id >> 8) | 0x80;
dev->pci_conf[1][0x04] = 7;
dev->pci_conf[1][0x05] = 0;
dev->pci_conf[1][0x06] = 0x20;
dev->pci_conf[1][0x07] = 0x02;
dev->pci_conf[1][0x09] = 0;
dev->pci_conf[1][0x0a] = 4;
dev->pci_conf[1][0x0b] = 6;
dev->pci_conf[1][0x0c] = 0;
dev->pci_conf[1][0x0d] = 0;
dev->pci_conf[1][0x0e] = 1;
dev->pci_conf[1][0x0f] = 0;
dev->pci_conf[1][0x1c] = 0xf0;
dev->pci_conf[1][0x20] = 0xf0;
dev->pci_conf[1][0x21] = 0xff;
dev->pci_conf[1][0x24] = 0xf0;
dev->pci_conf[1][0x25] = 0xff;
}
static void
via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
if (func)
return;
/*Read-only addresses*/
if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) ||
((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) ||
(addr == 0x69) || ((addr >= 0x79) && (addr < 0x7e)) ||
((addr >= 0x81) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0x88)) ||
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xaa) && (addr < 0xac)) ||
((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) ||
(addr == 0xfd))
return;
if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == 0x0597))
return;
if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id != 0x0691))
return;
switch(addr) {
case 0x04:
dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40);
break;
case 0x07:
dev->pci_conf[0][0x07] &= ~(val & 0xb0);
break;
case 0x0d:
dev->pci_conf[0][0x0d] = (dev->pci_conf[0][0x0d] & ~0x07) | (val & 0x07);
dev->pci_conf[0][0x75] = (dev->pci_conf[0][0x75] & ~0x30) | ((val & 0x06) << 3);
break;
case 0x12: /* Graphics Aperture Base */
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13: /* Graphics Aperture Base */
dev->pci_conf[0][0x13] = val;
break;
case 0x50: /* Cache Control 1 */
if (dev->id == 0x0691)
dev->pci_conf[0][0x50] = val;
else
dev->pci_conf[0][0x50] = (dev->pci_conf[0][0x50] & ~0xf8) | (val & 0xf8);
break;
case 0x51: /* Cache Control 2 */
if (dev->id == 0x0691)
dev->pci_conf[0][0x51] = val;
else
dev->pci_conf[0][0x51] = (dev->pci_conf[0][0x51] & ~0xeb) | (val & 0xeb);
break;
case 0x52: /* Non_Cacheable Control */
if (dev->id == 0x0691)
dev->pci_conf[0][0x52] = (dev->pci_conf[0][0x52] & ~0x9f) | (val & 0x9f);
else
dev->pci_conf[0][0x52] = (dev->pci_conf[0][0x52] & ~0xf5) | (val & 0xf5);
break;
case 0x53: /* System Performance Control */
if (dev->id == 0x0691)
dev->pci_conf[0][0x53] = val;
else
dev->pci_conf[0][0x53] = (dev->pci_conf[0][0x53] & ~0xf0) | (val & 0xf0);
break;
case 0x58:
if (dev->id == 0x0597)
dev->pci_conf[0][0x58] = (dev->pci_conf[0][0x58] & ~0xee) | (val & 0xee);
else
dev->pci_conf[0][0x58] = val;
break;
case 0x59:
if (dev->id == 0x0691)
dev->pci_conf[0][0x59] = val;
else
dev->pci_conf[0][0x59] = (dev->pci_conf[0][0x59] & ~0xf0) | (val & 0xf0);
break;
case 0x61: /* Shadow RAM Control 1 */
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
apollo_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
apollo_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
apollo_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
apollo_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
break;
case 0x62: /* Shadow RAM Control 2 */
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
apollo_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
apollo_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
apollo_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
apollo_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
break;
case 0x63: /* Shadow RAM Control 3 */
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
apollo_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
if (dev->id == 0x0691) switch (val & 0x03) {
case 0x00:
default:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 0); /* Non-SMM: Code PCI, Data PCI */
break;
case 0x01:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 1); /* Non-SMM: Code DRAM, Data DRAM */
break;
case 0x02:
apollo_smram_map(1, 0x000a0000, 0x00020000, 3); /* SMM: Code Invalid, Data Invalid */
apollo_smram_map(0, 0x000a0000, 0x00020000, 2); /* Non-SMM: Code DRAM, Data PCI */
break;
case 0x03:
apollo_smram_map(1, 0x000a0000, 0x00020000, 1); /* SMM: Code DRAM, Data DRAM */
apollo_smram_map(0, 0x000a0000, 0x00020000, 3); /* Non-SMM: Code Invalid, Data Invalid */
break;
} else switch (val & 0x03) {
case 0x00:
default:
/* Disable SMI Address Redirection (default) */
apollo_smram_map(1, 0x000a0000, 0x00020000, 0);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 0);
break;
case 0x01:
/* Allow access to DRAM Axxxx-Bxxxx for both normal and SMI cycles */
apollo_smram_map(1, 0x000a0000, 0x00020000, 1);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 1);
break;
case 0x02:
/* Reserved */
apollo_smram_map(1, 0x000a0000, 0x00020000, 3);
if (dev->id == 0x0597) {
/* TODO: SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx
(this needs a 3xxxx-4xxxx mapping set to EXTERNAL). */
apollo_smram_map(1, 0x00030000, 0x00020000, 3);
}
apollo_smram_map(0, 0x000a0000, 0x00020000, 3);
break;
case 0x03:
/* Allow SMI Axxxx-Bxxxx DRAM access */
apollo_smram_map(1, 0x000a0000, 0x00020000, 1);
if (dev->id == 0x0597)
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
apollo_smram_map(0, 0x000a0000, 0x00020000, 0);
break;
}
break;
case 0x68:
if (dev->id == 0x0597)
dev->pci_conf[0][0x68] = (dev->pci_conf[0][0x6b] & ~0xfe) | (val & 0xfe);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x68] = val;
else
dev->pci_conf[0][0x68] = (dev->pci_conf[0][0x6b] & ~0xfd) | (val & 0xfd);
break;
case 0x6b:
if (dev->id == 0x0691)
dev->pci_conf[0][0x6b] = (dev->pci_conf[0][0x6b] & ~0xcf) | (val & 0xcf);
else
dev->pci_conf[0][0x6b] = (dev->pci_conf[0][0x6b] & ~0xc1) | (val & 0xc1);
break;
case 0x6c:
if (dev->id == 0x0597)
dev->pci_conf[0][0x6c] = (dev->pci_conf[0][0x6c] & ~0x1f) | (val & 0x1f);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x6c] = (dev->pci_conf[0][0x6c] & ~0x7f) | (val & 0x7f);
else
dev->pci_conf[0][0x6c] = val;
break;
case 0x6d:
if (dev->id == 0x0597)
dev->pci_conf[0][0x6d] = (dev->pci_conf[0][0x6d] & ~0x0f) | (val & 0x0f);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x6d] = (dev->pci_conf[0][0x6d] & ~0x7f) | (val & 0x7f);
else
dev->pci_conf[0][0x6d] = val;
break;
case 0x6e:
dev->pci_conf[0][0x6e] = (dev->pci_conf[0][0x6e] & ~0xb7) | (val & 0xb7);
break;
case 0x70:
if (dev->id == 0x0597)
dev->pci_conf[0][0x70] = (dev->pci_conf[0][0x70] & ~0xf1) | (val & 0xf1);
else
dev->pci_conf[0][0x70] = val;
break;
case 0x74:
dev->pci_conf[0][0x74] = (dev->pci_conf[0][0x74] & ~0xc0) | (val & 0xc0);
break;
case 0x75:
dev->pci_conf[0][0x75] = (dev->pci_conf[0][0x75] & ~0xcf) | (val & 0xcf);
break;
case 0x76:
dev->pci_conf[0][0x76] = (dev->pci_conf[0][0x76] & ~0xf0) | (val & 0xf0);
break;
case 0x77:
dev->pci_conf[0][0x77] = (dev->pci_conf[0][0x77] & ~0xc0) | (val & 0xc0);
break;
case 0x7e:
dev->pci_conf[0][0x7e] = (dev->pci_conf[0][0x7e] & ~0x3f) | (val & 0x3f);
break;
case 0x80:
dev->pci_conf[0][0x80] = (dev->pci_conf[0][0x80] & ~0x8f) | (val & 0x8f);
break;
case 0x84:
/* The datasheet first mentions 7-0 but then says 3-0 are reserved -
- minimum of 16 MB for the graphics aperture? */
dev->pci_conf[0][0x84] = (dev->pci_conf[0][0x84] & ~0xf0) | (val & 0xf0);
break;
case 0x88:
dev->pci_conf[0][0x88] = (dev->pci_conf[0][0x88] & ~0x07) | (val & 0x07);
break;
case 0x89:
dev->pci_conf[0][0x89] = (dev->pci_conf[0][0x89] & ~0xf0) | (val & 0xf0);
break;
case 0xa8:
dev->pci_conf[0][0xa8] = (dev->pci_conf[0][0xa8] & ~0x03) | (val & 0x03);
break;
case 0xa9:
dev->pci_conf[0][0xa9] = (dev->pci_conf[0][0xa9] & ~0x03) | (val & 0x03);
break;
case 0xac:
dev->pci_conf[0][0xac] = (dev->pci_conf[0][0xac] & ~0x0f) | (val & 0x0f);
break;
case 0xfc:
if (dev->id > 0x0597)
dev->pci_conf[0][0xfc] = (dev->pci_conf[0][0xfc] & ~0x01) | (val & 0x01);
break;
default:
dev->pci_conf[0][addr] = val;
break;
}
}
static void
via_apollo_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
if (func != 1)
return;
/*Read-only addresses*/
if ((addr < 4) || ((addr >= 5) && (addr < 7)) ||
((addr >= 8) && (addr < 0x18)) || (addr == 0x1b) ||
((addr >= 0x1e) && (addr < 0x20)) || ((addr >= 0x28) && (addr < 0x3e)) ||
(addr == 0x3f) || (addr >= 0x43))
return;
switch(addr) {
case 0x04:
dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47);
break;
case 0x07:
dev->pci_conf[1][0x07] &= ~(val & 0x30);
break;
case 0x20: /* Memory Base */
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: /* Memory Limit */
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: /* Prefetchable Memory Base */
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: /* Prefetchable Memory Limit */
dev->pci_conf[1][0x26] = val & 0xf0;
break;
case 0x3e:
dev->pci_conf[0][0x3e] = (dev->pci_conf[0][0x3e] & ~0x06) | (val & 0x06);
break;
case 0x41:
dev->pci_conf[0][0x41] = (dev->pci_conf[0][0x41] & ~0xfe) | (val & 0xfe);
break;
case 0x42:
if (dev->id == 0x0597)
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xec) | (val & 0xec);
else if (dev->id == 0x0598)
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xfc) | (val & 0xfc);
else
dev->pci_conf[0][0x42] = (dev->pci_conf[0][0x42] & ~0xf4) | (val & 0xf4);
break;
default:
dev->pci_conf[1][addr] = val;
break;
}
}
static uint8_t
via_apollo_read(int func, int addr, void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
static void
via_apollo_write(int func, int addr, uint8_t val, void *priv)
{
switch(func) {
case 0:
via_apollo_host_bridge_write(func, addr, val, priv);
break;
case 1:
via_apollo_pci_bridge_write(func, addr, val, priv);
break;
}
}
static void
via_apollo_reset(void *priv)
{
via_apollo_write(0, 0x61, 0x00, priv);
via_apollo_write(0, 0x62, 0x00, priv);
via_apollo_write(0, 0x63, 0x00, priv);
}
static void *
via_apollo_init(const device_t *info)
{
via_apollo_t *dev = (via_apollo_t *) malloc(sizeof(via_apollo_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apollo_read, via_apollo_write, dev);
dev->id = info->local;
via_apollo_setup(dev);
via_apollo_reset(dev);
return dev;
}
static void
via_apollo_close(void *priv)
{
via_apollo_t *dev = (via_apollo_t *) priv;
free(dev);
}
const device_t via_vp3_device =
{
"VIA Apollo VP3",
DEVICE_PCI,
0x0597, /*VT82C597*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t via_mvp3_device =
{
"VIA Apollo MVP3",
DEVICE_PCI,
0x0598, /*VT82C598MVP*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t via_apro_device = {
"VIA Apollo Pro",
DEVICE_PCI,
0x0691, /*VT82C691*/
via_apollo_init,
via_apollo_close,
via_apollo_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,345 +0,0 @@
/*
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.>
VIA Apollo Pro North Bridge emulation
VT82C691 used in the PC Partner APAS3 board
based on the model of VIA MVP3 by mooch & Sarah
Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
Copyright(C) 2020 Tiseno100
Copyright(C) 2020 Melissa Goad
Copyright(C) 2020 Miran Grca
Note: Due to 99.9% similarities with the VP3, MVP3 but also other later Apollo chipsets. We probably should create a common Apollo tree
just like the Intel 4x0 series.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_apro_t
{
uint8_t pci_conf[2][256];
} via_apro_t;
static void
apro_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
via_apro_pci_regs(via_apro_t *dev)
{
memset(dev, 0, sizeof(via_apro_t));
// Host Bridge registers
dev->pci_conf[0][0x00] = 0x06; // VIA
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = 0x91; // VT82C691
dev->pci_conf[0][0x03] = 0x06;
dev->pci_conf[0][0x04] = 6; // Command
dev->pci_conf[0][0x05] = 0;
// These(06h-0fh) probably aren't needed but as they're referenced by the MVP3 chipset code i added them too
dev->pci_conf[0][0x06] = 0; // Status
dev->pci_conf[0][0x07] = 0;
dev->pci_conf[0][0x09] = 0; // Program Interface
dev->pci_conf[0][0x0a] = 0; // Sub Class Code
dev->pci_conf[0][0x0b] = 0; // Base Class Code
dev->pci_conf[0][0x0c] = 0; // reserved
dev->pci_conf[0][0x0d] = 0; // Latency Timer
dev->pci_conf[0][0x0e] = 0; // Header Type
dev->pci_conf[0][0x0f] = 0; // Built-in Self test
dev->pci_conf[0][0x10] = 0x08; // Graphics Aperature Base
dev->pci_conf[0][0x34] = 0xa0; // Capability Pointer
dev->pci_conf[0][0x56] = 1; // Bank 6 Ending
dev->pci_conf[0][0x57] = 1; // Bank 7 Ending
dev->pci_conf[0][0x5a] = 1; // Bank 0 Ending
dev->pci_conf[0][0x5b] = 1; // Bank 1 Ending
dev->pci_conf[0][0x5c] = 1; // Bank 2 Ending
dev->pci_conf[0][0x5d] = 1; // Bank 3 Ending
dev->pci_conf[0][0x5e] = 1; // Bank 4 Ending
dev->pci_conf[0][0x5f] = 1; // Bank 5 Ending
dev->pci_conf[0][0x64] = 0xec; // DRAM Timing for Banks 0,1
dev->pci_conf[0][0x65] = 0xec; // DRAM Timing for Banks 2,3
dev->pci_conf[0][0x66] = 0xec; // DRAM Timing for Banks 4,5
dev->pci_conf[0][0x67] = 0x01; // DRAM Timing for Banks 6,7
dev->pci_conf[0][0x6b] = 1; // DRAM Abritration control
dev->pci_conf[0][0xa4] = 0x03; // AGP Status
dev->pci_conf[0][0xa5] = 0x02;
dev->pci_conf[0][0xa6] = 0;
dev->pci_conf[0][0xa7] = 0x07;
// PCI-to-PCI
dev->pci_conf[1][0x00] = 0x06; // VIA
dev->pci_conf[1][0x01] = 0x11;
dev->pci_conf[1][0x02] = 0x91; // VT82C691
dev->pci_conf[1][0x03] = 0x06;
dev->pci_conf[1][0x04] = 7; // Command
dev->pci_conf[1][0x05] = 0;
dev->pci_conf[1][0x06] = 0x20; // Status
dev->pci_conf[1][0x07] = 0x02;
dev->pci_conf[1][0x09] = 0; // Program Interface
dev->pci_conf[1][0x0A] = 4; // Sub Class Code
dev->pci_conf[1][0x0B] = 6; // Base Class Code
dev->pci_conf[1][0x0C] = 0; // reserved
dev->pci_conf[1][0x0D] = 0; // Latency Timer
dev->pci_conf[1][0x0E] = 1; // Header Type
dev->pci_conf[1][0x0F] = 0; // Built-in Self test
dev->pci_conf[1][0x1c] = 0xf0; // I/O Base
dev->pci_conf[1][0x20] = 0xf0; // Memory Base
dev->pci_conf[1][0x21] = 0xff;
dev->pci_conf[1][0x24] = 0xf0;
dev->pci_conf[1][0x25] = 0xff;
}
static void
host_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
// Read-Only registers. Exact same as MVP3
if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) || ((addr >= 0xe) && (addr < 0x12)) ||
((addr >= 0x14) && (addr < 0x50)) || ((addr >= 0x79) && (addr < 0x7e)) || ((addr >= 0x85) && (addr < 0x88)) ||
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xad) && (addr < 0xfd)))
return;
switch(addr){
case 0x04: // Command
dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40);
case 0x07: // Status
dev->pci_conf[0][0x07] &= ~(val & 0xb0);
break;
case 0x12: //Graphics Aperature Base
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13:
dev->pci_conf[0][0x13] = val;
break;
case 0x61: // Shadow RAM control 1
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
apro_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
apro_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
apro_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
apro_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
return;
case 0x62: // Shadow RAM Control 2
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
apro_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
apro_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
apro_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
apro_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
return;
case 0x63: // Shadow RAM Control 3
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
apro_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
apro_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
return;
//In case we throw somewhere
default:
dev->pci_conf[0][addr] = val;
break;
}
}
static void
pci_to_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
if (func != 1)
return;
//As with MVP3. Same deal
if ((addr < 4) || ((addr >= 5) && (addr < 7)) ||
((addr >= 8) && (addr < 0x18)) || (addr == 0x1b) ||
((addr >= 0x1e) && (addr < 0x20)) || ((addr >= 0x28) && (addr < 0x3e)) ||
(addr >= 0x43))
return;
switch(addr) {
case 0x04:
dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47);
break;
case 0x07:
dev->pci_conf[1][0x07] &= ~(val & 0x30);
break;
case 0x20: // Memory Base
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: // Memory Limit
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: // Prefetchable Memory base
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: // Prefetchable Memory limit
dev->pci_conf[1][0x26] = val & 0xf0;
break;
default:
dev->pci_conf[1][addr] = val;
break;
}
}
static uint8_t
via_apro_read(int func, int addr, void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
static void
via_apro_write(int func, int addr, uint8_t val, void *priv)
{
switch(func) {
case 0:
host_bridge_write(func, addr, val, priv);
break;
case 1:
pci_to_pci_bridge_write(func, addr, val, priv);
break;
}
}
static void
via_apro_reset(void *priv)
{
via_apro_write(0, 0x63, via_apro_read(0, 0x63, priv) & 0xcf, priv);
}
static void *
via_apro_init(const device_t *info)
{
via_apro_t *dev = (via_apro_t *) malloc(sizeof(via_apro_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_apro_read, via_apro_write, dev);
via_apro_pci_regs(dev);
return dev;
}
static void
via_apro_close(void *priv)
{
via_apro_t *dev = (via_apro_t *) priv;
free(dev);
}
const device_t via_apro_device = {
"VIA Apollo Pro",
DEVICE_PCI,
0,
via_apro_init,
via_apro_close,
via_apro_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,324 +0,0 @@
/*
* 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.
*
* Implementation of the VIA MVP3 chip.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Melissa Goad, <mszoopers@protonmail.com>
*
* Copyright 2020 Miran Grca, Melissa Goad.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct via_mvp3_t
{
uint8_t pci_conf[2][256];
} via_mvp3_t;
static void
mvp3_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
via_mvp3_setup(via_mvp3_t *dev)
{
memset(dev, 0, sizeof(via_mvp3_t));
/* Host Bridge */
dev->pci_conf[0][0x00] = 0x06; /*VIA*/
dev->pci_conf[0][0x01] = 0x11;
dev->pci_conf[0][0x02] = 0x98; /*VT82C598MVP*/
dev->pci_conf[0][0x03] = 0x05;
dev->pci_conf[0][0x04] = 6;
dev->pci_conf[0][0x05] = 0;
dev->pci_conf[0][0x06] = 0x90;
dev->pci_conf[0][0x07] = 0x02;
dev->pci_conf[0][0x09] = 0;
dev->pci_conf[0][0x0a] = 0;
dev->pci_conf[0][0x0b] = 6;
dev->pci_conf[0][0x0c] = 0;
dev->pci_conf[0][0x0d] = 0;
dev->pci_conf[0][0x0e] = 0;
dev->pci_conf[0][0x0f] = 0;
dev->pci_conf[0][0x10] = 0x08;
dev->pci_conf[0][0x34] = 0xa0;
dev->pci_conf[0][0x5a] = 0x01;
dev->pci_conf[0][0x5b] = 0x01;
dev->pci_conf[0][0x5c] = 0x01;
dev->pci_conf[0][0x5d] = 0x01;
dev->pci_conf[0][0x5e] = 0x01;
dev->pci_conf[0][0x5f] = 0x01;
dev->pci_conf[0][0x64] = 0xec;
dev->pci_conf[0][0x65] = 0xec;
dev->pci_conf[0][0x66] = 0xec;
dev->pci_conf[0][0x6b] = 0x01;
dev->pci_conf[0][0xa0] = 0x02;
dev->pci_conf[0][0xa2] = 0x10;
dev->pci_conf[0][0xa4] = 0x03;
dev->pci_conf[0][0xa5] = 0x02;
dev->pci_conf[0][0xa7] = 0x07;
/* PCI-to-PCI Bridge */
dev->pci_conf[1][0x00] = 0x06; /*VIA*/
dev->pci_conf[1][0x01] = 0x11;
dev->pci_conf[1][0x02] = 0x98; /*VT82C598MVP*/
dev->pci_conf[1][0x03] = 0x85;
dev->pci_conf[1][0x04] = 7;
dev->pci_conf[1][0x05] = 0;
dev->pci_conf[1][0x06] = 0x20;
dev->pci_conf[1][0x07] = 0x02;
dev->pci_conf[1][0x09] = 0;
dev->pci_conf[1][0x0a] = 4;
dev->pci_conf[1][0x0b] = 6;
dev->pci_conf[1][0x0c] = 0;
dev->pci_conf[1][0x0d] = 0;
dev->pci_conf[1][0x0e] = 1;
dev->pci_conf[1][0x0f] = 0;
dev->pci_conf[1][0x1c] = 0xf0;
dev->pci_conf[1][0x20] = 0xf0;
dev->pci_conf[1][0x21] = 0xff;
dev->pci_conf[1][0x24] = 0xf0;
dev->pci_conf[1][0x25] = 0xff;
}
static void
via_mvp3_host_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_mvp3_t *dev = (via_mvp3_t *) priv;
if (func)
return;
/*Read-only addresses*/
if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) ||
((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) ||
((addr >= 0x79) && (addr < 0x7e)) || ((addr >= 0x85) && (addr < 0x88)) ||
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xad) && (addr < 0xfd)))
return;
switch(addr) {
case 0x04:
dev->pci_conf[0][0x04] = (dev->pci_conf[0][0x04] & ~0x40) | (val & 0x40);
break;
case 0x07:
dev->pci_conf[0][0x07] &= ~(val & 0xb0);
break;
case 0x12: /* Graphics Aperture Base */
dev->pci_conf[0][0x12] = (val & 0xf0);
break;
case 0x13: /* Graphics Aperture Base */
dev->pci_conf[0][0x13] = val;
break;
case 0x61: /* Shadow RAM Control 1 */
if ((dev->pci_conf[0][0x61] ^ val) & 0x03)
mvp3_map(0xc0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x61] ^ val) & 0x0c)
mvp3_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x61] ^ val) & 0x30)
mvp3_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x61] ^ val) & 0xc0)
mvp3_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x61] = val;
return;
case 0x62: /* Shadow RAM Control 2 */
if ((dev->pci_conf[0][0x62] ^ val) & 0x03)
mvp3_map(0xd0000, 0x04000, val & 0x03);
if ((dev->pci_conf[0][0x62] ^ val) & 0x0c)
mvp3_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->pci_conf[0][0x62] ^ val) & 0x30)
mvp3_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->pci_conf[0][0x62] ^ val) & 0xc0)
mvp3_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x62] = val;
return;
case 0x63: /* Shadow RAM Control 3 */
if ((dev->pci_conf[0][0x63] ^ val) & 0x30) {
mvp3_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
mvp3_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val;
return;
default:
dev->pci_conf[0][addr] = val;
break;
}
}
static void
via_mvp3_pci_bridge_write(int func, int addr, uint8_t val, void *priv)
{
via_mvp3_t *dev = (via_mvp3_t *) priv;
if (func != 1)
return;
/*Read-only addresses*/
if ((addr < 4) || ((addr >= 5) && (addr < 7)) ||
((addr >= 8) && (addr < 0x18)) || (addr == 0x1b) ||
((addr >= 0x1e) && (addr < 0x20)) || ((addr >= 0x28) && (addr < 0x3e)) ||
(addr >= 0x43))
return;
switch(addr) {
case 0x04:
dev->pci_conf[1][0x04] = (dev->pci_conf[1][0x04] & ~0x47) | (val & 0x47);
break;
case 0x07:
dev->pci_conf[1][0x07] &= ~(val & 0x30);
break;
case 0x20: /* Memory Base */
dev->pci_conf[1][0x20] = val & 0xf0;
break;
case 0x22: /* Memory Limit */
dev->pci_conf[1][0x22] = val & 0xf0;
break;
case 0x24: /* Prefetchable Memory Base */
dev->pci_conf[1][0x24] = val & 0xf0;
break;
case 0x26: /* Prefetchable Memory Limit */
dev->pci_conf[1][0x26] = val & 0xf0;
break;
default:
dev->pci_conf[1][addr] = val;
break;
}
}
static uint8_t
via_mvp3_read(int func, int addr, void *priv)
{
via_mvp3_t *dev = (via_mvp3_t *) priv;
uint8_t ret = 0xff;
switch(func) {
case 0:
ret = dev->pci_conf[0][addr];
break;
case 1:
ret = dev->pci_conf[1][addr];
break;
}
return ret;
}
static void
via_mvp3_write(int func, int addr, uint8_t val, void *priv)
{
switch(func) {
case 0:
via_mvp3_host_bridge_write(func, addr, val, priv);
break;
case 1:
via_mvp3_pci_bridge_write(func, addr, val, priv);
break;
}
}
static void
via_mvp3_reset(void *priv)
{
via_mvp3_write(0, 0x63, via_mvp3_read(0, 0x63, priv) & 0xcf, priv);
}
static void *
via_mvp3_init(const device_t *info)
{
via_mvp3_t *dev = (via_mvp3_t *) malloc(sizeof(via_mvp3_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, via_mvp3_read, via_mvp3_write, dev);
via_mvp3_setup(dev);
return dev;
}
static void
via_mvp3_close(void *priv)
{
via_mvp3_t *dev = (via_mvp3_t *) priv;
free(dev);
}
const device_t via_mvp3_device =
{
"VIA MVP3",
DEVICE_PCI,
0,
via_mvp3_init,
via_mvp3_close,
via_mvp3_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -234,6 +234,10 @@ exec386(int cycs)
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
if (in_smm)
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
@@ -242,7 +246,11 @@ exec386(int cycs)
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
} else
#ifdef ENABLE_386_LOG
if (in_smm)
x386_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc);
#endif
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
@@ -272,12 +280,25 @@ exec386(int cycs)
}
}
if (!in_smm && smi_line/* && is_pentium*/) {
if ((in_smm == 0) && smi_line) {
#ifdef ENABLE_386_LOG
x386_log("SMI while not in SMM\n");
#endif
enter_smm();
smi_line = 0;
} else if (in_smm && smi_line/* && is_pentium*/) {
} else if ((in_smm == 1) && smi_line) {
/* Mark this so that we don't latch more than one SMI. */
#ifdef ENABLE_386_LOG
x386_log("SMI while in unlatched SMM\n");
#endif
smi_latched = 1;
smi_line = 0;
} else if ((in_smm == 2) && smi_line) {
/* Mark this so that we don't latch more than one SMI. */
#ifdef ENABLE_386_LOG
x386_log("SMI while in latched SMM\n");
#endif
smi_line = 0;
}
ins_cycles -= cycles;

View File

@@ -1,910 +0,0 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#ifdef USE_DYNAREC
#include "codegen.h"
#ifdef USE_NEW_DYNAREC
#include "codegen_backend.h"
#endif
#endif
#include "386_common.h"
#define CPU_BLOCK_END() cpu_block_end = 1
int inrecomp = 0, cpu_block_end = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
#ifdef ENABLE_386_DYNAREC_LOG
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;
void
x386_dynarec_log(const char *fmt, ...)
{
va_list ap;
if (x386_dynarec_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_dynarec_log(fmt, ...)
#endif
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;
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] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
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] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
#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"
/*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()
{
prefetch_bytes = 0;
}
#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()
void enter_smm()
{
uint32_t smram_state = smbase + 0xfe00;
uint32_t old_cr0 = cr0;
uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16);
cr0 &= ~0x8000000d;
cpu_state.flags = 2;
cpu_state.eflags = 0;
in_smm = 1;
mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
smi_latched = 1;
mem_writel_phys(smram_state + 0xf8, smbase);
mem_writel_phys(smram_state + 0x128, cr4);
mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit);
mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base);
mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access);
mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit);
mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base);
mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access);
mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit);
mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base);
mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access);
mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit);
mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base);
mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access);
mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit);
mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base);
mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access);
mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit);
mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base);
mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access);
mem_writel_phys(smram_state + 0x178, ldt.limit);
mem_writel_phys(smram_state + 0x17c, ldt.base);
mem_writel_phys(smram_state + 0x180, ldt.access);
mem_writel_phys(smram_state + 0x184, gdt.limit);
mem_writel_phys(smram_state + 0x188, gdt.base);
mem_writel_phys(smram_state + 0x18c, gdt.access);
mem_writel_phys(smram_state + 0x190, idt.limit);
mem_writel_phys(smram_state + 0x194, idt.base);
mem_writel_phys(smram_state + 0x198, idt.access);
mem_writel_phys(smram_state + 0x19c, tr.limit);
mem_writel_phys(smram_state + 0x1a0, tr.base);
mem_writel_phys(smram_state + 0x1a4, tr.access);
mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg);
mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg);
mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg);
mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg);
mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg);
mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg);
mem_writel_phys(smram_state + 0x1c0, ldt.seg);
mem_writel_phys(smram_state + 0x1c4, tr.seg);
mem_writel_phys(smram_state + 0x1c8, dr[7]);
mem_writel_phys(smram_state + 0x1cc, dr[6]);
mem_writel_phys(smram_state + 0x1d0, EAX);
mem_writel_phys(smram_state + 0x1d4, ECX);
mem_writel_phys(smram_state + 0x1d8, EDX);
mem_writel_phys(smram_state + 0x1dc, EBX);
mem_writel_phys(smram_state + 0x1e0, ESP);
mem_writel_phys(smram_state + 0x1e4, EBP);
mem_writel_phys(smram_state + 0x1e8, ESI);
mem_writel_phys(smram_state + 0x1ec, EDI);
mem_writel_phys(smram_state + 0x1f0, cpu_state.pc);
mem_writel_phys(smram_state + 0x1d0, old_flags);
mem_writel_phys(smram_state + 0x1f8, cr3);
mem_writel_phys(smram_state + 0x1fc, old_cr0);
ds = es = fs_seg = gs = ss = 0;
DS = ES = FS = GS = SS = 0;
cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit
= cpu_state.seg_ss.limit = 0xffffffff;
cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high
= cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff;
cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low
= cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0;
cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access
= cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93;
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked
= cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
CS = 0x3000;
cs = smbase;
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff;
cpu_state.seg_cs.limit_low = 0;
cpu_state.seg_cs.access = 0x93;
cpu_state.seg_cs.checked = 1;
cr4 = 0;
dr[7] = 0x400;
cpu_state.pc = 0x8000;
nmi_mask = 0;
}
void leave_smm()
{
uint32_t smram_state = smbase + 0xfe00;
smbase = mem_readl_phys(smram_state + 0xf8);
cr4 = mem_readl_phys(smram_state + 0x128);
cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130);
cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134);
cpu_state.seg_es.limit_low = cpu_state.seg_es.base;
cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138);
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c);
cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140);
cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base;
cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144);
cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148);
cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c);
cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base;
cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150);
cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154);
cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158);
cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base;
cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c);
cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160);
cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164);
cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base;
cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168);
cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c);
cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170);
cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base;
cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174);
ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178);
ldt.base = mem_readl_phys(smram_state + 0x17c);
ldt.limit_low = ldt.base;
ldt.access = mem_readl_phys(smram_state + 0x180);
gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184);
gdt.base = mem_readl_phys(smram_state + 0x188);
gdt.limit_low = gdt.base;
gdt.access = mem_readl_phys(smram_state + 0x18c);
idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190);
idt.base = mem_readl_phys(smram_state + 0x194);
idt.limit_low = idt.base;
idt.access = mem_readl_phys(smram_state + 0x198);
tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c);
tr.base = mem_readl_phys(smram_state + 0x1a0);
tr.limit_low = tr.base;
tr.access = mem_readl_phys(smram_state + 0x1a4);
ES = mem_readl_phys(smram_state + 0x1a8);
CS = mem_readl_phys(smram_state + 0x1ac);
SS = mem_readl_phys(smram_state + 0x1b0);
DS = mem_readl_phys(smram_state + 0x1b4);
FS = mem_readl_phys(smram_state + 0x1b8);
GS = mem_readl_phys(smram_state + 0x1bc);
ldt.seg = mem_readl_phys(smram_state + 0x1c0);
tr.seg = mem_readl_phys(smram_state + 0x1c4);
dr[7] = mem_readl_phys(smram_state + 0x1c8);
dr[6] = mem_readl_phys(smram_state + 0x1cc);
EAX = mem_readl_phys(smram_state + 0x1d0);
ECX = mem_readl_phys(smram_state + 0x1d4);
EDX = mem_readl_phys(smram_state + 0x1d8);
EBX = mem_readl_phys(smram_state + 0x1dc);
ESP = mem_readl_phys(smram_state + 0x1e0);
EBP = mem_readl_phys(smram_state + 0x1e4);
ESI = mem_readl_phys(smram_state + 0x1e8);
EDI = mem_readl_phys(smram_state + 0x1ec);
cpu_state.pc = mem_readl_phys(smram_state + 0x1f0);
uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4);
cpu_state.flags = new_flags & 0xffff;
cpu_state.eflags = new_flags >> 16;
cr3 = mem_readl_phys(smram_state + 0x1f8);
cr0 = mem_readl_phys(smram_state + 0x1fc);
cpu_state.seg_cs.access &= ~0x60;
cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss
if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG))
{
cpu_state.seg_cs.checked = CS ? 1 : 0;
cpu_state.seg_ds.checked = DS ? 1 : 0;
cpu_state.seg_es.checked = ES ? 1 : 0;
cpu_state.seg_fs.checked = FS ? 1 : 0;
cpu_state.seg_gs.checked = GS ? 1 : 0;
cpu_state.seg_ss.checked = SS ? 1 : 0;
}
else
{
cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked
= cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
}
mem_restore_mem_state(smbase, 131072);
in_smm = 0;
nmi_mask = 1;
}
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"
#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
#ifdef USE_DYNAREC
static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
int vector;
uint32_t addr;
int tempi;
int cycdiff;
int oldcyc;
uint32_t start_pc = 0;
int cyc_period = cycs / 2000; /*5us*/
cycles_main += cycs;
while (cycles_main > 0)
{
int cycles_start;
cycles += cyc_period;
cycles_start = cycles;
while (cycles>0)
{
oldcs = CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cycdiff=0;
oldcyc=cycles;
if (!CACHE_ON()) /*Interpret block*/
{
cpu_block_end = 0;
x86_was_reset = 0;
while (!cpu_block_end)
{
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
}
if (!use32) cpu_state.pc &= 0xffff;
if (((cs + cpu_state.pc) >> 12) != pccache)
CPU_BLOCK_END();
/* if (ssegs)
{
ds=oldds;
ss=oldss;
ssegs=0;
}*/
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (cpu_state.abrt)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
ins++;
/* if ((cs + pc) == 4)
fatal("4\n");*/
/* if (ins >= 141400000)
output = 3;*/
}
}
else
{
uint32_t phys_addr = get_phys(cs+cpu_state.pc);
int hash = HASH(phys_addr);
codeblock_t *block = codeblock_hash[hash];
int valid_block = 0;
trap = 0;
if (block && !cpu_state.abrt)
{
page_t *page = &pages[phys_addr >> 12];
/*Block must match current CS, PC, code segment size,
and physical address. The physical address check will
also catch any page faults at this stage*/
valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
(block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (!valid_block)
{
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
{
/*Walk page tree to see if we find the correct block*/
codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
if (new_block)
{
valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
(new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (valid_block)
block = new_block;
}
}
}
if (valid_block && (block->page_mask & *block->dirty_mask))
{
codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr);
page->dirty_mask[(phys_addr >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
if (valid_block && block->page_mask2)
{
/*We don't want the second page to cause a page
fault at this stage - that would break any
code crossing a page boundary where the first
page is present but the second isn't. Instead
allow the first page to be interpreted and for
the page fault to occur when the page boundary
is actually crossed.*/
uint32_t phys_addr_2 = get_phys_noabrt(block->endpc);
page_t *page_2 = &pages[phys_addr_2 >> 12];
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
valid_block = 0;
else if (block->page_mask2 & *block->dirty_mask2)
{
codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2);
page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
}
if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
block->flags &= ~CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0;
}
}
if (valid_block && block->was_recompiled)
{
void (*code)() = (void *)&block->data[BLOCK_START];
codeblock_hash[hash] = block;
inrecomp=1;
code();
inrecomp=0;
if (!use32) cpu_state.pc &= 0xffff;
cpu_recomp_blocks++;
}
else if (valid_block && !cpu_state.abrt)
{
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
cpu_new_blocks++;
codegen_block_start_recompile(block);
codegen_in_recompile = 1;
while (!cpu_block_end)
{
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end_recompile(block);
if (x86_was_reset)
codegen_reset();
codegen_in_recompile = 0;
}
else if (!cpu_state.abrt)
{
/*Mark block but do not recompile*/
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
codegen_block_init(phys_addr);
while (!cpu_block_end)
{
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
codegen_endpc = (cs + cpu_state.pc) + 8;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
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;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end();
if (x86_was_reset)
codegen_reset();
}
}
cycdiff=oldcyc-cycles;
tsc += cycdiff;
if (cpu_state.abrt)
{
flags_rebuild();
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
CS = oldcs;
cpu_state.pc = cpu_state.oldpc;
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Double fault %i\n", ins);
#endif
pmodeint(8, 0);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Triple fault - reset\n");
#endif
}
}
}
if (in_smm && smi_line && is_pentium)
{
enter_smm();
}
if (trap)
{
flags_rebuild();
if (msw&1)
{
pmodeint(1,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 = (1 << 2) + idt.base;
cpu_state.flags&=~I_FLAG;
cpu_state.flags&=~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
oldcs = CS;
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear)
{
nmi_auto_clear = 0;
nmi = 0;
}
}
else if ((cpu_state.flags&I_FLAG) && pic_intpending)
{
vector=picinterrupt();
if (vector!=-1)
{
CPU_BLOCK_END();
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;
cpu_state.flags&=~I_FLAG;
cpu_state.flags&=~T_FLAG;
oxpc=cpu_state.pc;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
cycles_main -= (cycles_start - cycles);
}
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,900 +0,0 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#ifdef USE_DYNAREC
#include "codegen.h"
#ifdef USE_NEW_DYNAREC
#include "codegen_backend.h"
#endif
#endif
#include "386_common.h"
#define CPU_BLOCK_END() cpu_block_end = 1
int inrecomp = 0, cpu_block_end = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
#ifdef ENABLE_386_DYNAREC_LOG
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;
void
x386_dynarec_log(const char *fmt, ...)
{
va_list ap;
if (x386_dynarec_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_dynarec_log(fmt, ...)
#endif
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;
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] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
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] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
#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"
/*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()
{
prefetch_bytes = 0;
}
#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()
void enter_smm()
{
uint32_t smram_state = smbase + 0xfe00;
uint32_t old_cr0 = cr0;
uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16);
cr0 &= ~0x8000000d;
cpu_state.flags = 2;
cpu_state.eflags = 0;
in_smm = 1;
mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
smi_latched = 1;
mem_writel_phys(smram_state + 0xf8, smbase);
mem_writel_phys(smram_state + 0x128, cr4);
mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit);
mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base);
mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access);
mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit);
mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base);
mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access);
mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit);
mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base);
mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access);
mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit);
mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base);
mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access);
mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit);
mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base);
mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access);
mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit);
mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base);
mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access);
mem_writel_phys(smram_state + 0x178, ldt.limit);
mem_writel_phys(smram_state + 0x17c, ldt.base);
mem_writel_phys(smram_state + 0x180, ldt.access);
mem_writel_phys(smram_state + 0x184, gdt.limit);
mem_writel_phys(smram_state + 0x188, gdt.base);
mem_writel_phys(smram_state + 0x18c, gdt.access);
mem_writel_phys(smram_state + 0x190, idt.limit);
mem_writel_phys(smram_state + 0x194, idt.base);
mem_writel_phys(smram_state + 0x198, idt.access);
mem_writel_phys(smram_state + 0x19c, tr.limit);
mem_writel_phys(smram_state + 0x1a0, tr.base);
mem_writel_phys(smram_state + 0x1a4, tr.access);
mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg);
mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg);
mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg);
mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg);
mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg);
mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg);
mem_writel_phys(smram_state + 0x1c0, ldt.seg);
mem_writel_phys(smram_state + 0x1c4, tr.seg);
mem_writel_phys(smram_state + 0x1c8, dr[7]);
mem_writel_phys(smram_state + 0x1cc, dr[6]);
mem_writel_phys(smram_state + 0x1d0, EAX);
mem_writel_phys(smram_state + 0x1d4, ECX);
mem_writel_phys(smram_state + 0x1d8, EDX);
mem_writel_phys(smram_state + 0x1dc, EBX);
mem_writel_phys(smram_state + 0x1e0, ESP);
mem_writel_phys(smram_state + 0x1e4, EBP);
mem_writel_phys(smram_state + 0x1e8, ESI);
mem_writel_phys(smram_state + 0x1ec, EDI);
mem_writel_phys(smram_state + 0x1f0, cpu_state.pc);
mem_writel_phys(smram_state + 0x1d0, old_flags);
mem_writel_phys(smram_state + 0x1f8, cr3);
mem_writel_phys(smram_state + 0x1fc, old_cr0);
ds = es = fs_seg = gs = ss = 0;
DS = ES = FS = GS = SS = 0;
cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit
= cpu_state.seg_ss.limit = 0xffffffff;
cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high
= cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff;
cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low
= cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0;
cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access
= cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93;
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked
= cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
CS = 0x3000;
cs = smbase;
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff;
cpu_state.seg_cs.limit_low = 0;
cpu_state.seg_cs.access = 0x93;
cpu_state.seg_cs.checked = 1;
cr4 = 0;
dr[7] = 0x400;
cpu_state.pc = 0x8000;
nmi_mask = 0;
}
void leave_smm()
{
uint32_t smram_state = smbase + 0xfe00;
smbase = mem_readl_phys(smram_state + 0xf8);
cr4 = mem_readl_phys(smram_state + 0x128);
cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130);
cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134);
cpu_state.seg_es.limit_low = cpu_state.seg_es.base;
cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138);
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c);
cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140);
cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base;
cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144);
cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148);
cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c);
cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base;
cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150);
cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154);
cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158);
cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base;
cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c);
cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160);
cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164);
cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base;
cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168);
cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c);
cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170);
cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base;
cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174);
ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178);
ldt.base = mem_readl_phys(smram_state + 0x17c);
ldt.limit_low = ldt.base;
ldt.access = mem_readl_phys(smram_state + 0x180);
gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184);
gdt.base = mem_readl_phys(smram_state + 0x188);
gdt.limit_low = gdt.base;
gdt.access = mem_readl_phys(smram_state + 0x18c);
idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190);
idt.base = mem_readl_phys(smram_state + 0x194);
idt.limit_low = idt.base;
idt.access = mem_readl_phys(smram_state + 0x198);
tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c);
tr.base = mem_readl_phys(smram_state + 0x1a0);
tr.limit_low = tr.base;
tr.access = mem_readl_phys(smram_state + 0x1a4);
ES = mem_readl_phys(smram_state + 0x1a8);
CS = mem_readl_phys(smram_state + 0x1ac);
SS = mem_readl_phys(smram_state + 0x1b0);
DS = mem_readl_phys(smram_state + 0x1b4);
FS = mem_readl_phys(smram_state + 0x1b8);
GS = mem_readl_phys(smram_state + 0x1bc);
ldt.seg = mem_readl_phys(smram_state + 0x1c0);
tr.seg = mem_readl_phys(smram_state + 0x1c4);
dr[7] = mem_readl_phys(smram_state + 0x1c8);
dr[6] = mem_readl_phys(smram_state + 0x1cc);
EAX = mem_readl_phys(smram_state + 0x1d0);
ECX = mem_readl_phys(smram_state + 0x1d4);
EDX = mem_readl_phys(smram_state + 0x1d8);
EBX = mem_readl_phys(smram_state + 0x1dc);
ESP = mem_readl_phys(smram_state + 0x1e0);
EBP = mem_readl_phys(smram_state + 0x1e4);
ESI = mem_readl_phys(smram_state + 0x1e8);
EDI = mem_readl_phys(smram_state + 0x1ec);
cpu_state.pc = mem_readl_phys(smram_state + 0x1f0);
uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4);
cpu_state.flags = new_flags & 0xffff;
cpu_state.eflags = new_flags >> 16;
cr3 = mem_readl_phys(smram_state + 0x1f8);
cr0 = mem_readl_phys(smram_state + 0x1fc);
cpu_state.seg_cs.access &= ~0x60;
cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss
if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG))
{
cpu_state.seg_cs.checked = CS ? 1 : 0;
cpu_state.seg_ds.checked = DS ? 1 : 0;
cpu_state.seg_es.checked = ES ? 1 : 0;
cpu_state.seg_fs.checked = FS ? 1 : 0;
cpu_state.seg_gs.checked = GS ? 1 : 0;
cpu_state.seg_ss.checked = SS ? 1 : 0;
}
else
{
cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked
= cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
}
mem_restore_mem_state(smbase, 131072);
in_smm = 0;
nmi_mask = 1;
}
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"
#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
#ifdef USE_DYNAREC
static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
int vector;
uint32_t addr;
int tempi;
int cycdiff;
int oldcyc;
uint32_t start_pc = 0;
int cyc_period = cycs / 2000; /*5us*/
cycles_main += cycs;
while (cycles_main > 0)
{
int cycles_start;
cycles += cyc_period;
cycles_start = cycles;
while (cycles>0)
{
oldcs = CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cycdiff=0;
oldcyc=cycles;
if (!CACHE_ON()) /*Interpret block*/
{
cpu_block_end = 0;
x86_was_reset = 0;
while (!cpu_block_end)
{
oldcs = CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
}
if (!use32) cpu_state.pc &= 0xffff;
if (((cs + cpu_state.pc) >> 12) != pccache)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (cpu_state.abrt)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
ins++;
}
}
else
{
uint32_t phys_addr = get_phys(cs+cpu_state.pc);
int hash = HASH(phys_addr);
codeblock_t *block = codeblock_hash[hash];
int valid_block = 0;
trap = 0;
if (block && !cpu_state.abrt)
{
page_t *page = &pages[phys_addr >> 12];
/*Block must match current CS, PC, code segment size,
and physical address. The physical address check will
also catch any page faults at this stage*/
valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
(block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (!valid_block)
{
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
{
/*Walk page tree to see if we find the correct block*/
codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
if (new_block)
{
valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
(new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (valid_block)
block = new_block;
}
}
}
if (valid_block && (block->page_mask & *block->dirty_mask))
{
codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr);
page->dirty_mask[(phys_addr >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
if (valid_block && block->page_mask2)
{
/*We don't want the second page to cause a page
fault at this stage - that would break any
code crossing a page boundary where the first
page is present but the second isn't. Instead
allow the first page to be interpreted and for
the page fault to occur when the page boundary
is actually crossed.*/
uint32_t phys_addr_2 = get_phys_noabrt(block->endpc);
page_t *page_2 = &pages[phys_addr_2 >> 12];
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
valid_block = 0;
else if (block->page_mask2 & *block->dirty_mask2)
{
codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2);
page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
}
if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
block->flags &= ~CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0;
}
}
if (valid_block && block->was_recompiled)
{
void (*code)() = (void *)&block->data[BLOCK_START];
codeblock_hash[hash] = block;
inrecomp=1;
code();
inrecomp=0;
if (!use32) cpu_state.pc &= 0xffff;
cpu_recomp_blocks++;
}
else if (valid_block && !cpu_state.abrt)
{
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
cpu_new_blocks++;
codegen_block_start_recompile(block);
codegen_in_recompile = 1;
while (!cpu_block_end)
{
oldcs = CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end_recompile(block);
if (x86_was_reset)
codegen_reset();
codegen_in_recompile = 0;
}
else if (!cpu_state.abrt)
{
/*Mark block but do not recompile*/
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
codegen_block_init(phys_addr);
while (!cpu_block_end)
{
oldcs=CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
codegen_endpc = (cs + cpu_state.pc) + 8;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
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;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end();
if (x86_was_reset)
codegen_reset();
}
}
cycdiff=oldcyc-cycles;
tsc += cycdiff;
if (cpu_state.abrt)
{
flags_rebuild();
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
cpu_state.pc = cpu_state.oldpc;
CS = oldcs;
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Double fault %i\n", ins);
#endif
pmodeint(8, 0);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Triple fault - reset\n");
#endif
}
}
}
if (in_smm && smi_line && is_pentium)
{
enter_smm();
}
else if (trap)
{
flags_rebuild();
if (msw&1)
{
pmodeint(1,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 = (1 << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
oldcs = CS;
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear)
{
nmi_auto_clear = 0;
nmi = 0;
}
}
else if ((cpu_state.flags&I_FLAG) && pic_intpending)
{
vector = picinterrupt();
if (vector != -1)
{
CPU_BLOCK_END();
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;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
oxpc=cpu_state.pc;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
cycles_main -= (cycles_start - cycles);
}
}
#endif

View File

@@ -66,7 +66,7 @@ static __inline void fetch_ea_16_long(uint32_t rmdat)
#define OP_TABLE(name) dynarec_ops_ ## name
#define CLOCK_CYCLES(c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#define CLOCK_CYCLES(c) in_hlt = 0
#define CLOCK_CYCLES_ALWAYS(c) do { cycles -= (c); in_hlt = 0; } while(0)
#include "386_ops.h"

View File

@@ -972,7 +972,10 @@ reset_common(int hard)
cpu_alu_op = 0;
in_smm = smi_latched = 0;
smi_line = 0;
smi_line = in_hlt = 0;
if (hard)
smbase = 0x00030000;
}

View File

@@ -39,10 +39,13 @@
* USA.
*/
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/device.h>
@@ -132,7 +135,7 @@ const OpFn *x86_opcodes_REPE;
const OpFn *x86_opcodes_REPNE;
const OpFn *x86_opcodes_3DNOW;
int in_smm = 0, smi_line = 0, smi_latched = 0;
int in_smm = 0, smi_line = 0, smi_latched = 0, in_hlt = 0;
uint32_t smbase = 0x30000;
CPU *cpu_s;
@@ -163,7 +166,7 @@ int is286,
hascache,
isibm486,
israpidcad,
is_pentium;
is_pentium, is_k5, is_k6, is_p6;
int hasfpu;
@@ -237,7 +240,29 @@ int timing_misaligned;
static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6;
int cpu_has_feature(int feature)
#ifdef ENABLE_CPU_LOG
int cpu_do_log = ENABLE_CPU_LOG;
void
cpu_log(const char *fmt, ...)
{
va_list ap;
if (cpu_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define cpu_log(fmt, ...)
#endif
int
cpu_has_feature(int feature)
{
return cpu_features & feature;
}
@@ -291,7 +316,28 @@ cpu_set(void)
is486dx = (cpu_s->cpu_type >= CPU_i486DX) && (cpu_s->cpu_type < CPU_i486DX2);
is486dx2 = (cpu_s->cpu_type >= CPU_i486DX2) && (cpu_s->cpu_type < CPU_iDX4);
isdx4 = (cpu_s->cpu_type >= CPU_iDX4) && (cpu_s->cpu_type < CPU_WINCHIP);
is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP);
is_pentium = (cpu_s->cpu_type == CPU_PENTIUM) || (cpu_s->cpu_type == CPU_PENTIUMMMX);
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
is_k5 = (cpu_s->cpu_type == CPU_K5) || (cpu_s->cpu_type == CPU_5K86);
#else
is_k5 = 0;
#endif
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
is_k6 = (cpu_s->cpu_type == CPU_K6);
#else
is_k6 = 0;
#endif
#ifdef USE_NEW_DYNAREC
is_k6 = is_k6 || (cpu_s->cpu_type == CPU_K6_2) || (cpu_s->cpu_type == CPU_K6_2C) ||
(cpu_s->cpu_type == CPU_K6_3) || (cpu_s->cpu_type == CPU_K6_2P) ||
(cpu_s->cpu_type == CPU_K6_3P);
#endif
#if defined(DEV_BRANCH) && defined(USE_I686)
is_p6 = (cpu_s->cpu_type == CPU_PENTIUMPRO) || (cpu_s->cpu_type == CPU_PENTIUM2) ||
(cpu_s->cpu_type == CPU_PENTIUM2D);
#else
is_p6 = 0;
#endif
hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD);
hascache = (cpu_s->cpu_type >= CPU_486SLC) || (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL);
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
@@ -2362,6 +2408,7 @@ void cpu_ven_reset(void)
void cpu_RDMSR()
{
cpu_log("RDMSR %08X\n", ECX);
switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type)
{
case CPU_WINCHIP:
@@ -2833,7 +2880,7 @@ void cpu_RDMSR()
break;
default:
i686_invalid_rdmsr:
// pclog("RDMSR: Invalid MSR: %08X\n", ECX);
cpu_log("RDMSR: Invalid MSR: %08X\n", ECX);
x86gpf(NULL, 0);
break;
}
@@ -2849,6 +2896,7 @@ void cpu_WRMSR()
uint64_t temp;
#endif
cpu_log("WRMSR %08X %08X%08X\n", ECX, EDX, EAX);
switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type)
{
case CPU_WINCHIP:
@@ -3249,7 +3297,7 @@ void cpu_WRMSR()
break;
default:
i686_invalid_wrmsr:
// pclog("WRMSR: Invalid MSR: %08X\n", ECX);
cpu_log("WRMSR: Invalid MSR: %08X\n", ECX);
x86gpf(NULL, 0);
break;
}

View File

@@ -382,11 +382,12 @@ extern double cpu_dmulti;
extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment
penalties when crossing 8-byte boundaries*/
extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4;
extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4;
extern int is_pentium, is_k5, is_k6, is_p6;
extern int hascache;
extern int isibm486;
extern int is_rapidcad;
extern int hasfpu;
extern int is_rapidcad;
extern int hasfpu;
#define CPU_FEATURE_RDTSC (1 << 0)
#define CPU_FEATURE_MSR (1 << 1)
#define CPU_FEATURE_MMX (1 << 2)
@@ -397,7 +398,7 @@ extern int hasfpu;
extern uint32_t cpu_features;
extern int in_smm, smi_line, smi_latched;
extern int in_smm, smi_line, smi_latched, in_hlt;
extern uint32_t smbase;
#ifdef USE_NEW_DYNAREC

View File

@@ -1,695 +0,0 @@
/*
* 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.
*
* Define all known processor types.
*
* Available cpuspeeds:
*
* 0 = 16 MHz
* 1 = 20 MHz
* 2 = 25 MHz
* 3 = 33 MHz
* 4 = 40 MHz
* 5 = 50 MHz
* 6 = 66 MHz
* 7 = 75 MHz
* 8 = 80 MHz
* 9 = 90 MHz
* 10 = 100 MHz
* 11 = 120 MHz
* 12 = 133 MHz
* 13 = 150 MHz
* 14 = 160 MHz
* 15 = 166 MHz
* 16 = 180 MHz
* 17 = 200 MHz
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* leilei,
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 leilei.
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/machine.h>
CPU cpus_8088[] = {
/*8088 standard*/
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_pcjr[] = {
/*8088 PCjr*/
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_europc[] = {
/*8088 EuroPC*/
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_8086[] = {
/*8086 standard*/
{"8086/7.16", CPU_8086, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/9.54", CPU_8086, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8086/10", CPU_8086, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/12", CPU_8086, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/16", CPU_8086, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_pc1512[] = {
/*8086 Amstrad*/
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_286[] = {
/*286*/
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_ibmat[] = {
/*286*/
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_ibmxt286[] = {
/*286*/
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_ps1_m2011[] = {
/*286*/
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 9}
};
CPU cpus_ps2_m30_286[] = {
/*286*/
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_i386SX[] = {
/*i386SX*/
{"i386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
{"i386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"i386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"i386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
{"i386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_i386DX[] = {
/*i386DX/RapidCAD*/
{"i386DX/16", CPU_386DX, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2},
{"i386DX/20", CPU_386DX, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"i386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"i386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
{"i386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
{"RapidCAD/25", CPU_RAPIDCAD, 25000000, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
{"RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
{"RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_Am386SX[] = {
/*Am386SX*/
{"Am386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
{"Am386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"Am386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"Am386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
{"Am386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_Am386DX[] = {
/*Am386DX*/
{"Am386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"Am386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
{"Am386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_486SLC[] = {
/*Cx486SLC*/
{"Cx486SLC/20", CPU_486SLC, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
{"Cx486SLC/25", CPU_486SLC, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
{"Cx486SLC/33", CPU_486SLC, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
{"Cx486SRx2/32", CPU_486SLC, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 4},
{"Cx486SRx2/40", CPU_486SLC, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
{"Cx486SRx2/50", CPU_486SLC, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM386SLC[] = {
/*IBM 386SLC*/
{"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0, 0x300, 0, 0, 0, 3,3,3,3, 2},
{"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3},
{"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM486SLC[] = {
/*IBM 486SLC*/
{"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, 0, 6,6,3,3, 4},
{"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0, 0x400, 0, 0, 0, 7,7,6,6, 5},
{"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6},
{"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8},
{"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 7},
{"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9},
{"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM486BL[] = {
/*IBM Blue Lightning*/
{"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6},
{"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8},
{"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9},
{"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_486DLC[] = {
/*Cx486DLC*/
{"Cx486DLC/25", CPU_486DLC, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3},
{"Cx486DLC/33", CPU_486DLC, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4},
{"Cx486DLC/40", CPU_486DLC, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5},
{"Cx486DRx2/32", CPU_486DLC, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4},
{"Cx486DRx2/40", CPU_486DLC, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
{"Cx486DRx2/50", CPU_486DLC, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
{"Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 8},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_i486S1[] = {
/*i486*/
{"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
{"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
{"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
{"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5},
{"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*Only added the DX4 OverDrive as the others would be redundant*/
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_Am486S1[] = {
/*Am486*/
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
{"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
{"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_Cx486S1[] = {
/*Cyrix 486*/
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_i486[] = {
/*i486/P24T*/
{"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
{"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
{"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
{"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, /*CPUID available on DX2, DX4, P24T, >= 40 MHz*/
{"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
{"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/
{"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9},
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
{"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
{"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_Am486[] = {
/*Am486/5x86*/
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
{"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"Am486DX4/75", CPU_Am486DX, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
{"Am486DX4/90", CPU_Am486DX, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Am486DX4/100", CPU_Am486DX, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Am486DX4/120", CPU_Am486DX, 120000000, 3, 40000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
{"Am5x86/P75", CPU_Am486DX, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
{"Am5x86/P75+", CPU_Am486DX, 150000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
{"Am5x86/P90", CPU_Am486DX, 160000000, 4, 40000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_Cx486[] = {
/*Cyrix 486*/
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"Cx486DX4/75", CPU_Cx486DX, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
{"Cx486DX4/100", CPU_Cx486DX, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
/*Cyrix 5x86*/
{"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/
{"Cx5x86/100", CPU_Cx5x86, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
{"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
CPU cpus_6x863V[] = {
/*Cyrix 6x86*/
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_6x86[] = {
/*Cyrix 6x86*/
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86L*/
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86MX/MII*/
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#ifdef USE_NEW_DYNAREC
CPU cpus_6x86SS7[] = {
/*Cyrix 6x86*/
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86L*/
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86MX/MII*/
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
{"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
{"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 31666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
{"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
CPU cpus_WinChip[] = {
/*IDT WinChip*/
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
#ifdef USE_NEW_DYNAREC
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2},
#endif
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#ifdef USE_NEW_DYNAREC
CPU cpus_WinChip_SS7[] = {
/*IDT WinChip*/
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9},
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2},
{"WinChip 2A/266", CPU_WINCHIP2, 233333333, 7/3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28},
{"WinChip 2A/300", CPU_WINCHIP2, 250000000, 5/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
CPU cpus_Pentium5V[] = {
/*Intel Pentium (5V, socket 4)*/
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_Pentium5V50[] = {
/*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/
{"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6},
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
{"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12},
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_PentiumS5[] = {
/*Intel Pentium (Socket 5)*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
/*Intel Pentium OverDrive*/
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_Pentium3V[] = {
/*Intel Pentium*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*Intel Pentium OverDrive*/
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_Pentium[] = {
/*Intel Pentium*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*Intel Pentium MMX*/
{"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
/*Mobile Pentium*/
{"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
/*Intel Pentium OverDrive*/
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K))
CPU cpus_K5[] = {
/*AMD K5 (Socket 5)*/
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_K56[] = {
/*AMD K5 (Socket 7)*/
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*AMD K6 (Socket 7*/
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
#ifdef USE_NEW_DYNAREC
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
{"K6-2/300 AFR-66", CPU_K6_2, 300000000, 9/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
{"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33, 17, 17, 44},
#endif
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#ifdef USE_NEW_DYNAREC
CPU cpus_K56_SS7[] = {
/*AMD K5 (Socket 7)*/
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*AMD K6 (Socket 7)*/
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
/*AMD K6-2 (Socket 7/Super Socket 7)*/
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28},
{"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32},
{"K6-2/300", CPU_K6_2, 300000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36},
{"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40},
{"K6-2/350", CPU_K6_2C, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42},
{"K6-2/366", CPU_K6_2C, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44},
{"K6-2/380", CPU_K6_2C, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46},
{"K6-2/400", CPU_K6_2C, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-2/450", CPU_K6_2C, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-2/475", CPU_K6_2C, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-2/500", CPU_K6_2C, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"K6-2/533", CPU_K6_2C, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
{"K6-2/550", CPU_K6_2C, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
/*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/
{"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-2+/500", CPU_K6_2P, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 32323232, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
{"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 32333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
{"K6-III/400", CPU_K6_3, 400000000, 4, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-III/450", CPU_K6_3, 450000000, 9/2, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-III+/400", CPU_K6_3P, 400000000, 4, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-III+/500", CPU_K6_3P, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
CPU cpus_PentiumPro[] = {
/*Intel Pentium Pro*/
{"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*Intel Pentium II OverDrive*/
{"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
{"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33},
{"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
{"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
{"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#endif

View File

@@ -132,7 +132,7 @@ static int opSYSEXIT(uint32_t fetchdat)
do_seg_load(&cpu_state.seg_ss, sysexit_ss_seg_data);
stack32 = 1;
flushmmucache_cr3();
flushmmucache();
cycles -= timing_call_pm;

View File

@@ -607,6 +607,8 @@ static int opF7_l_a32(uint32_t fetchdat)
static int opHLT(uint32_t fetchdat)
{
in_hlt = 0;
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x86gpf(NULL,0);
@@ -615,8 +617,10 @@ static int opHLT(uint32_t fetchdat)
if (!((cpu_state.flags & I_FLAG) && pic_intpending))
{
CLOCK_CYCLES_ALWAYS(100);
if (!((cpu_state.flags & I_FLAG) && pic_intpending))
if (!((cpu_state.flags & I_FLAG) && pic_intpending)) {
in_hlt = 1;
cpu_state.pc--;
}
}
else
CLOCK_CYCLES(5);
@@ -831,6 +835,7 @@ static void loadall_load_segment(uint32_t addr, x86seg *s)
uint32_t attrib = readmeml(0, addr);
uint32_t segdat3 = (attrib >> 16) & 0xff;
s->access = (attrib >> 8) & 0xff;
s->ar_high = segdat3;
s->base = readmeml(0, addr + 4);
s->limit = readmeml(0, addr + 8);
@@ -953,10 +958,8 @@ static int opRSM(uint32_t fetchdat)
if (in_smm)
{
leave_smm();
if (smi_latched) {
smi_latched = 0;
if (smi_latched)
enter_smm();
}
CPU_BLOCK_END();
return 0;
}

View File

@@ -115,7 +115,7 @@
typedef struct {
int bit32, cur_dev,
irq, inited,
diag;
diag, force_ata3;
uint16_t base_main, side_main;
pc_timer_t timer;
} ide_board_t;
@@ -281,7 +281,7 @@ ide_irq_raise(ide_t *ide)
ide_log("IDE %i: IRQ raise\n", ide->board);
if (!(ide->fdisk & 2)) {
if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv);
else if (ide_boards[ide->board]->irq != -1)
picint(1 << ide_boards[ide->board]->irq);
@@ -303,7 +303,7 @@ ide_irq_lower(ide_t *ide)
ide_log("IDE %i: IRQ lower\n", ide->board);
if (ide->irqstat) {
if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv);
else if (ide_boards[ide->board]->irq != -1)
picintc(1 << ide_boards[ide->board]->irq);
@@ -323,7 +323,7 @@ ide_irq_update(ide_t *ide)
if (!(ide->fdisk & 2) && ide->irqstat) {
ide_log("IDE %i: IRQ update raise\n", ide->board);
if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq) {
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) {
ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv);
ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv);
} else if (ide_boards[ide->board]->irq != -1) {
@@ -332,7 +332,7 @@ ide_irq_update(ide_t *ide)
}
} else if (ide->fdisk & 2) {
ide_log("IDE %i: IRQ update lower\n", ide->board);
if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq)
ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv);
else if (ide_boards[ide->board]->irq != -1)
picintc(1 << ide_boards[ide->board]->irq);
@@ -390,26 +390,26 @@ static int
ide_get_max(ide_t *ide, int type)
{
if (ide->type == IDE_ATAPI)
return ide->get_max(ide_bm[ide->board] != NULL, type);
return ide->get_max(!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type);
switch(type) {
case TYPE_PIO: /* PIO */
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 1;
return 0; /* Maximum PIO 0 for legacy PIO-only drive. */
case TYPE_SDMA: /* SDMA */
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 2;
return -1;
case TYPE_MDMA: /* MDMA */
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 2;
return -1;
case TYPE_UDMA: /* UDMA */
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 2;
return -1;
@@ -424,16 +424,16 @@ static int
ide_get_timings(ide_t *ide, int type)
{
if (ide->type == IDE_ATAPI)
return ide->get_timings(ide_bm[ide->board] != NULL, type);
return ide->get_timings(!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type);
switch(type) {
case TIMINGS_DMA:
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 120;
return 0;
case TIMINGS_PIO:
if (ide_bm[ide->board] != NULL)
if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL))
return 120;
return 0;
@@ -529,7 +529,7 @@ static void ide_hd_identify(ide_t *ide)
ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]);
}
if (ide_bm[ide->board]) {
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board]) {
ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/
ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/
ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/
@@ -550,7 +550,7 @@ ide_identify(ide_t *ide)
memset(ide->buffer, 0, 512);
if (ide->type == IDE_ATAPI)
ide->identify(ide, ide_bm[ide->board] != NULL);
ide->identify(ide, !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL));
else if (ide->type != IDE_NONE)
ide_hd_identify(ide);
else {
@@ -840,7 +840,7 @@ ide_atapi_attach(ide_t *ide)
ide->type = IDE_ATAPI;
ide_allocate_buffer(ide);
ide_set_signature(ide);
ide->mdma_mode = (1 << ide->get_max(!ide_bm[ide->board], TYPE_PIO));
ide->mdma_mode = (1 << ide->get_max(ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board], TYPE_PIO));
ide->error = 1;
ide->cfg_spt = ide->cfg_hpc = 0;
}
@@ -926,7 +926,7 @@ ide_atapi_callback(ide_t *ide)
#endif
out = (ide->sc->packet_status & 0x01);
if (ide_bm[ide->board] && ide_bm[ide->board]->dma) {
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) {
ret = ide_bm[ide->board]->dma(ide->board,
ide->sc->temp_buffer, ide->sc->packet_len,
out, ide_bm[ide->board]->priv);
@@ -2040,7 +2040,7 @@ ide_callback(void *priv)
case WIN_READ_DMA:
case WIN_READ_DMA_ALT:
if ((ide->type == IDE_ATAPI) || !ide_bm[ide->board]) {
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) {
ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel);
goto abort_cmd;
}
@@ -2058,7 +2058,7 @@ ide_callback(void *priv)
ide->pos=0;
if (ide_bm[ide->board] && ide_bm[ide->board]->dma) {
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) {
/* We should not abort - we should simply wait for the host to start DMA. */
ret = ide_bm[ide->board]->dma(ide->board,
ide->sector_buffer, ide->sector_pos * 512,
@@ -2143,7 +2143,7 @@ ide_callback(void *priv)
case WIN_WRITE_DMA:
case WIN_WRITE_DMA_ALT:
if ((ide->type == IDE_ATAPI) || !ide_bm[ide->board]) {
if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) {
ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel);
goto abort_cmd;
}
@@ -2152,7 +2152,7 @@ ide_callback(void *priv)
goto id_not_found;
}
if (ide_bm[ide->board] && ide_bm[ide->board]->dma) {
if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) {
if (ide->secount)
ide->sector_pos = ide->secount;
else
@@ -2466,6 +2466,20 @@ ide_clear_bus_master(int board)
}
/* This so drives can be forced to ATA-3 (no DMA) for machines that hide the on-board PCI IDE controller
(eg. Packard Bell PB640 and ASUS P/I-P54TP4XE), breaking DMA drivers unless this is done. */
extern void
ide_board_set_force_ata3(int board, int force_ata3)
{
ide_log("ide_board_set_force_ata3(%i, %i)\n", board, force_ata3);
if ((ide_boards[board] == NULL)|| !ide_boards[board]->inited)
return;
ide_boards[board]->force_ata3 = force_ata3;
}
static void
ide_board_close(int board)
{

View File

@@ -757,8 +757,6 @@ dma_channel_read(int channel)
if (!AT && !channel)
refreshread();
/* if (!AT && channel)
pclog("DMA refresh read on channel %i\n", channel); */
if (! dma_c->size) {
temp = _dma_read(dma_c->ac);
@@ -830,11 +828,6 @@ dma_channel_write(int channel, uint16_t val)
if ((dma_c->mode & 0xC) != 4)
return(DMA_NODATA);
/* if (!AT)
refreshread();
if (!AT)
pclog("DMA refresh write on channel %i\n", channel); */
if (! dma_c->size) {
_dma_write(dma_c->ac, val & 0xff);

View File

@@ -13,10 +13,12 @@
* Author: RichardG, <richardg867@gmail.com>
* Copyright 2020 RichardG.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define HAVE_STDARG_H
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
@@ -67,6 +69,26 @@ static uint8_t w83781d_write(w83781d_t *dev, uint8_t reg, uint8_t val, uint8_t b
static void w83781d_reset(w83781d_t *dev, uint8_t initialization);
#ifdef ENABLE_W83781D_LOG
int w83781d_do_log = ENABLE_W83781D_LOG;
static void
w83781d_log(const char *fmt, ...)
{
va_list ap;
if (w83781d_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define w83781d_log(fmt, ...)
#endif
static void
w83781d_remap(w83781d_t *dev)
{
@@ -200,7 +222,7 @@ w83781d_read(w83781d_t *dev, uint8_t reg, uint8_t bank)
ret = dev->regs[reg];
}
pclog("w83781d_read(%02x, %d) = %02x\n", reg, bank, ret);
w83781d_log("w83781d_read(%02x, %d) = %02x\n", reg, bank, ret);
return ret;
}

View File

@@ -65,6 +65,7 @@ extern const device_t sis_85c50x_device;
#endif
/* VIA */
extern const device_t via_vp3_device;
extern const device_t via_mvp3_device;
extern const device_t via_apro_device;

View File

@@ -130,6 +130,8 @@ extern void ide_pri_disable(void);
extern void ide_sec_enable(void);
extern void ide_sec_disable(void);
extern void ide_board_set_force_ata3(int board, int force_ata3);
extern double ide_atapi_get_period(uint8_t channel);
extern void ide_set_callback(uint8_t channel, double callback);

View File

@@ -101,6 +101,7 @@ extern int keyboard_ismsexit(void);
extern void keyboard_at_adddata_keyboard_raw(uint8_t val);
extern void keyboard_at_adddata_mouse(uint8_t val);
extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *);
extern void keyboard_at_set_a20_key(int state);
extern uint8_t keyboard_at_get_mouse_scan(void);
extern void keyboard_at_set_mouse_scan(uint8_t val);
extern void keyboard_at_reset(void);

View File

@@ -263,6 +263,7 @@ extern int machine_at_endeavor_init(const machine_t *);
extern int machine_at_zappa_init(const machine_t *);
extern int machine_at_mb500n_init(const machine_t *);
extern int machine_at_president_init(const machine_t *);
extern int machine_at_apollo_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(USE_VECTRA54)
extern int machine_at_vectra54_init(const machine_t *);
#endif

View File

@@ -35,6 +35,8 @@
#define MEM_READ_INTERNAL 0x10
#define MEM_READ_EXTERNAL 0x20
#define MEM_READ_DISABLED 0x30
#define MEM_READ_NORMAL 0x40 /* SMM only - means use the non-SMM state */
#define MEM_READ_EXTERNAL_EX 0x50 /* External but with internal exec - needed by the VIA Apollo Pro */
#define MEM_READ_ROMCS 0x60 /* EXTERNAL type + ROMC flag */
#define MEM_READ_EXTANY 0x70 /* Any EXTERNAL type */
#define MEM_READ_MASK 0xf0
@@ -43,16 +45,21 @@
#define MEM_WRITE_INTERNAL 0x01
#define MEM_WRITE_EXTERNAL 0x02
#define MEM_WRITE_DISABLED 0x03
#define MEM_WRITE_NORMAL 0x04 /* SMM only - means use the non-SMM state */
#define MEM_WRITE_ROMCS 0x06 /* EXTERNAL type + ROMC flag */
#define MEM_WRITE_EXTANY 0x07 /* Any EXTERNAL type */
#define MEM_WRITE_MASK 0x0f
#define MEM_STATE_SMM_SHIFT 8
/* #define's for memory granularity, currently 16k, but may
change in the future - 4k works, less does not because of
internal 4k pages. */
#ifdef DEFAULT_GRANULARITY
#define MEM_GRANULARITY_BITS 14
#define MEM_GRANULARITY_SIZE (1 << MEM_GRANULARITY_BITS)
#define MEM_GRANULARITY_HBOUND (MEM_GRANULARITY_SIZE - 2)
#define MEM_GRANULARITY_QBOUND (MEM_GRANULARITY_SIZE - 4)
#define MEM_GRANULARITY_MASK (MEM_GRANULARITY_SIZE - 1)
#define MEM_GRANULARITY_HMASK ((1 << (MEM_GRANULARITY_BITS - 1)) - 1)
#define MEM_GRANULARITY_QMASK ((1 << (MEM_GRANULARITY_BITS - 2)) - 1)
@@ -61,6 +68,8 @@
#else
#define MEM_GRANULARITY_BITS 12
#define MEM_GRANULARITY_SIZE (1 << MEM_GRANULARITY_BITS)
#define MEM_GRANULARITY_HBOUND (MEM_GRANULARITY_SIZE - 2)
#define MEM_GRANULARITY_QBOUND (MEM_GRANULARITY_SIZE - 4)
#define MEM_GRANULARITY_MASK (MEM_GRANULARITY_SIZE - 1)
#define MEM_GRANULARITY_HMASK ((1 << (MEM_GRANULARITY_BITS - 1)) - 1)
#define MEM_GRANULARITY_QMASK ((1 << (MEM_GRANULARITY_BITS - 2)) - 1)
@@ -260,9 +269,12 @@ extern void mem_mapping_set_addr(mem_mapping_t *,
extern void mem_mapping_set_exec(mem_mapping_t *, uint8_t *exec);
extern void mem_mapping_disable(mem_mapping_t *);
extern void mem_mapping_enable(mem_mapping_t *);
extern void mem_mapping_recalc(uint64_t base, uint64_t size);
extern void mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state);
extern void mem_set_mem_state(uint32_t base, uint32_t size, int state);
extern void mem_restore_mem_state(uint32_t base, uint32_t size);
extern void mem_set_mem_state_smm(uint32_t base, uint32_t size, int state);
extern uint8_t mem_readb_phys(uint32_t addr);
extern uint16_t mem_readw_phys(uint32_t addr);
@@ -311,6 +323,7 @@ extern void mem_add_upper_bios(void);
extern void mem_add_bios(void);
extern void mem_init(void);
extern void mem_reset(void);
extern void mem_remap_top(int kb);

View File

@@ -469,8 +469,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
uint8_t *fregs;
/* Return on unsupported function. */
if (func > dev->max_func)
return;
if (dev->max_func > 0) {
if (func > dev->max_func)
return;
} else {
if (func > 1)
return;
}
piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr);
fregs = (uint8_t *) dev->regs[func];
@@ -872,7 +877,7 @@ piix_read(int func, int addr, void *priv)
uint8_t ret = 0xff, *fregs;
/* Return on unsupported function. */
if (func <= dev->max_func) {
if ((func <= dev->max_func) || ((func == 1) && (dev->max_func == 0))) {
fregs = (uint8_t *) dev->regs[func];
ret = fregs[addr];

View File

@@ -354,6 +354,9 @@ inb(uint16_t port)
// if (!found)
// pclog("inb(%04X) = %02X\n", port, ret);
// if (in_smm)
// pclog("inb(%04X) = %02X\n", port, ret);
return(ret);
}
@@ -364,6 +367,9 @@ outb(uint16_t port, uint8_t val)
io_t *p;
int found = 0;
// if (in_smm)
// pclog("outb(%04X, %02X)\n", port, val);
if (io[port]) {
p = io[port];
while(p) {
@@ -411,6 +417,9 @@ inw(uint16_t port)
if (!found)
ret = (inb(port) | (inb(port + 1) << 8));
// if (in_smm)
// pclog("inw(%04X) = %04X\n", port, ret);
return ret;
}
@@ -420,6 +429,9 @@ outw(uint16_t port, uint16_t val)
{
io_t *p;
// if (in_smm)
// pclog("outw(%04X, %04X)\n", port, val);
p = io[port];
if (p) {
while(p) {
@@ -459,6 +471,9 @@ inl(uint16_t port)
if (!found)
ret = (inw(port) | (inw(port + 2) << 16));
// if (in_smm)
// pclog("inl(%04X) = %08X\n", port, ret);
return ret;
}
@@ -468,6 +483,9 @@ outl(uint16_t port, uint32_t val)
{
io_t *p;
// if (in_smm)
// pclog("outl(%04X, %08X)\n", port, val);
p = io[port];
if (p) {
while(p) {

View File

@@ -2627,3 +2627,12 @@ keyboard_at_get_mouse_scan(void)
{
return(mouse_scan ? 0x10 : 0x00);
}
void
keyboard_at_set_a20_key(int state)
{
atkbd_t *dev = SavedKbd;
write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1));
}

View File

@@ -36,6 +36,7 @@
#include <86box/keyboard.h>
#include <86box/intel_flash.h>
#include <86box/intel_sio.h>
#include <86box/nvr.h>
#include <86box/piix.h>
#include <86box/sio.h>
#include <86box/video.h>
@@ -243,6 +244,8 @@ machine_at_p54tp4xe_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device);
device_add(&i430fx_device);
device_add(&piix_device);
ide_board_set_force_ata3(0, 1);
ide_board_set_force_ata3(1, 1);
device_add(&fdc37c665_device);
device_add(&intel_flash_bxt_device);
@@ -381,6 +384,37 @@ machine_at_president_init(const machine_t *model)
}
int
machine_at_apollo_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/apollo/S728P.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
device_add(&ls486e_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
device_add(&i430fx_device);
device_add(&piix_device);
device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c932fr_device);
device_add(&intel_flash_bxt_device);
return ret;
}
#if defined(DEV_BRANCH) && defined(USE_VECTRA54)
int
machine_at_vectra54_init(const machine_t *model)

View File

@@ -122,7 +122,8 @@ machine_at_pb640_init(const machine_t *model)
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
device_add(&i430fx_pb640_device);
device_add(&piix_device);
device_add(&ide_isa_2ch_device);
ide_board_set_force_ata3(0, 1);
ide_board_set_force_ata3(1, 1);
if (gfxcard == VID_INTERNAL)
device_add(&gd5440_onboard_pci_device);

View File

@@ -179,10 +179,11 @@ const machine_t machines[] = {
{ "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL },
#endif
{ "[486 PCI] ASUS PCI/I-486SP3G", "486sp3g", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486sp3g_init, NULL },
{ "[486 PCI] Intel Classic/PCI", "alfredo", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL },
{ "[486 PCI] Lucky Star LS-486E", "ls486e", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_ls486e_init, NULL },
{ "[486 PCI] Rise Computer R418", "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL },
{ "[486 PCI] ASUS PCI/I-486SP3G", "486sp3g", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486sp3g_init, NULL },
{ "[486 PCI] Zida Tomato 4DP", "4dps", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_4dps_init, NULL },
{ "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL },
#if defined(DEV_BRANCH) && defined(USE_VPP60)
@@ -195,7 +196,7 @@ const machine_t machines[] = {
{ "[Socket 5 NX] IBM Ambra DP90 PCI", "ambradp90", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp90_init, NULL },
{ "[Socket 5 NX] Gigabyte GA-586IP", "430nx", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_430nx_init, NULL },
{ "[Socket 5 FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL },
{ "[Socket 5 FX] AMI Apollo", "apollo", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_apollo_init, NULL },
#if defined(DEV_BRANCH) && defined(USE_VECTRA54)
{ "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 767, machine_at_vectra54_init, NULL },
#endif
@@ -203,11 +204,12 @@ const machine_t machines[] = {
{ "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL },
{ "[Socket 5 FX] President Award 430FX PCI","president", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL },
{ "[Socket 7-3V FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL },
{ "[Socket 7-3V FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL },
{ "[Socket 7-3V FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device },
#if defined(DEV_BRANCH) && defined(USE_MRTHOR)
{ "[Socket 7-3V FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL },
#endif
{ "[Socket 7-3V FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device },
{ "[Socket 7-3V FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device },
{ "[Socket 7-3V HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL },

175
src/mem.c
View File

@@ -120,7 +120,7 @@ int purgeable_page_count = 0;
static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
static uint8_t *_mem_exec[MEM_MAPPINGS_NO];
static int _mem_state[MEM_MAPPINGS_NO], _mem_state_bak[MEM_MAPPINGS_NO];
static int _mem_state[MEM_MAPPINGS_NO];
#if FIXME
#if (MEM_GRANULARITY_BITS >= 12)
@@ -1187,11 +1187,12 @@ uint16_t
mem_readw_phys(uint32_t addr)
{
mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS];
uint16_t temp;
uint16_t temp, *p;
if (_mem_exec[addr >> MEM_GRANULARITY_BITS])
return ((uint16_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK];
else if (map && map->read_w)
if ((addr <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) {
p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]);
return *p;
} else if ((addr <= MEM_GRANULARITY_HBOUND) && (map && map->read_w))
return map->read_w(addr, map->p);
else {
temp = mem_readb_phys(addr + 1) << 8;
@@ -1206,11 +1207,12 @@ uint32_t
mem_readl_phys(uint32_t addr)
{
mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS];
uint32_t temp;
uint32_t temp, *p;
if (_mem_exec[addr >> MEM_GRANULARITY_BITS])
return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_QMASK];
else if (map && map->read_l)
if ((addr <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) {
p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]);
return *p;
} else if ((addr <= MEM_GRANULARITY_QBOUND) && (map && map->read_l))
return map->read_l(addr, map->p);
else {
temp = mem_readw_phys(addr + 2) << 16;
@@ -1237,10 +1239,12 @@ void
mem_writew_phys(uint32_t addr, uint16_t val)
{
mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS];
uint16_t *p;
if (_mem_exec[addr >> MEM_GRANULARITY_BITS])
((uint16_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK] = val;
else if (map && map->write_w)
if ((addr <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) {
p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]);
*p = val;
} else if ((addr <= MEM_GRANULARITY_HBOUND) && (map && map->write_w))
map->write_w(addr, val, map->p);
else {
mem_writeb_phys(addr, val & 0xff);
@@ -1253,10 +1257,12 @@ void
mem_writel_phys(uint32_t addr, uint32_t val)
{
mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS];
uint32_t *p;
if (_mem_exec[addr >> MEM_GRANULARITY_BITS])
((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_QMASK] = val;
else if (map && map->write_l)
if ((addr <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) {
p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]);
*p = val;
} else if ((addr <= MEM_GRANULARITY_QBOUND) && (map && map->read_l))
map->write_l(addr, val, map->p);
else {
mem_writew_phys(addr, val & 0xffff);
@@ -1268,6 +1274,11 @@ mem_writel_phys(uint32_t addr, uint32_t val)
uint8_t
mem_read_ram(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read B %02X from %08X\n", ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return ram[addr];
@@ -1277,6 +1288,11 @@ mem_read_ram(uint32_t addr, void *priv)
uint16_t
mem_read_ramw(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return *(uint16_t *)&ram[addr];
@@ -1286,6 +1302,11 @@ mem_read_ramw(uint32_t addr, void *priv)
uint32_t
mem_read_raml(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return *(uint32_t *)&ram[addr];
@@ -1453,6 +1474,10 @@ mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p)
void
mem_write_ram(uint32_t addr, uint8_t val, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Write B %02X to %08X\n", val, addr);
#endif
addwritelookup(mem_logical_addr, addr);
mem_write_ramb_page(addr, val, &pages[addr >> 12]);
}
@@ -1461,6 +1486,10 @@ mem_write_ram(uint32_t addr, uint8_t val, void *priv)
void
mem_write_ramw(uint32_t addr, uint16_t val, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Write W %04X to %08X\n", val, addr);
#endif
addwritelookup(mem_logical_addr, addr);
mem_write_ramw_page(addr, val, &pages[addr >> 12]);
}
@@ -1469,6 +1498,10 @@ mem_write_ramw(uint32_t addr, uint16_t val, void *priv)
void
mem_write_raml(uint32_t addr, uint32_t val, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Write L %08X to %08X\n", val, addr);
#endif
addwritelookup(mem_logical_addr, addr);
mem_write_raml_page(addr, val, &pages[addr >> 12]);
}
@@ -1477,7 +1510,7 @@ mem_write_raml(uint32_t addr, uint32_t val, void *priv)
static uint8_t
mem_read_remapped(uint32_t addr, void *priv)
{
if(addr >= (mem_size * 1024) && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addreadlookup(mem_logical_addr, addr);
return ram[addr];
@@ -1487,7 +1520,7 @@ mem_read_remapped(uint32_t addr, void *priv)
static uint16_t
mem_read_remappedw(uint32_t addr, void *priv)
{
if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addreadlookup(mem_logical_addr, addr);
return *(uint16_t *)&ram[addr];
@@ -1497,7 +1530,7 @@ mem_read_remappedw(uint32_t addr, void *priv)
static uint32_t
mem_read_remappedl(uint32_t addr, void *priv)
{
if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addreadlookup(mem_logical_addr, addr);
return *(uint32_t *)&ram[addr];
@@ -1508,7 +1541,7 @@ static void
mem_write_remapped(uint32_t addr, uint8_t val, void *priv)
{
uint32_t oldaddr = addr;
if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addwritelookup(mem_logical_addr, addr);
mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]);
@@ -1519,7 +1552,7 @@ static void
mem_write_remappedw(uint32_t addr, uint16_t val, void *priv)
{
uint32_t oldaddr = addr;
if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addwritelookup(mem_logical_addr, addr);
mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]);
@@ -1530,7 +1563,7 @@ static void
mem_write_remappedl(uint32_t addr, uint32_t val, void *priv)
{
uint32_t oldaddr = addr;
if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024))
if ((addr >= (mem_size * 1024)) && (addr < ((mem_size + 384) * 1024)))
addr = 0xA0000 + (addr - (mem_size * 1024));
addwritelookup(mem_logical_addr, addr);
mem_write_raml_page(addr, val, &pages[oldaddr >> 12]);
@@ -1638,8 +1671,13 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr)
static __inline int
mem_mapping_read_allowed(uint32_t flags, int state)
mem_mapping_read_allowed(uint32_t flags, int state, int exec)
{
int smm_state = state >> MEM_STATE_SMM_SHIFT;
if (in_smm && ((smm_state & MEM_READ_MASK) != MEM_READ_NORMAL))
state = smm_state;
switch (state & MEM_READ_MASK) {
case MEM_READ_DISABLED:
return 0;
@@ -1659,6 +1697,12 @@ mem_mapping_read_allowed(uint32_t flags, int state)
case MEM_READ_EXTANY:
return !(flags & MEM_MAPPING_INTERNAL);
case MEM_READ_EXTERNAL_EX:
if (exec)
return !(flags & MEM_MAPPING_EXTERNAL);
else
return !(flags & MEM_MAPPING_INTERNAL);
case MEM_READ_INTERNAL:
return !(flags & MEM_MAPPING_EXTERNAL);
@@ -1673,6 +1717,11 @@ mem_mapping_read_allowed(uint32_t flags, int state)
static __inline int
mem_mapping_write_allowed(uint32_t flags, int state)
{
int smm_state = state >> MEM_STATE_SMM_SHIFT;
if (in_smm && ((smm_state & MEM_WRITE_MASK) != MEM_WRITE_NORMAL))
state = smm_state;
switch (state & MEM_WRITE_MASK) {
case MEM_WRITE_DISABLED:
return 0;
@@ -1703,7 +1752,7 @@ mem_mapping_write_allowed(uint32_t flags, int state)
}
static void
void
mem_mapping_recalc(uint64_t base, uint64_t size)
{
mem_mapping_t *map = base_mapping.next;
@@ -1729,16 +1778,29 @@ mem_mapping_recalc(uint64_t base, uint64_t size)
for (c = start; c < end; c += MEM_GRANULARITY_SIZE) {
if ((map->read_b || map->read_w || map->read_l) &&
mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) {
mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 0)) {
#ifdef ENABLE_MEM_LOG
if ((start >= 0xa0000) && (start <= 0xbffff))
mem_log("Read allowed: %08X (mapping for %08X)\n", map, start);
#endif
read_mapping[c >> MEM_GRANULARITY_BITS] = map;
if (map->exec)
_mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base);
else
_mem_exec[c >> MEM_GRANULARITY_BITS] = NULL;
}
if (map->exec &&
mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS], 1)) {
#ifdef ENABLE_MEM_LOG
if ((start >= 0xa0000) && (start <= 0xbffff))
mem_log("Exec allowed: %08X (mapping for %08X)\n", map, start);
#endif
_mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base);
}
if ((map->write_b || map->write_w || map->write_l) &&
mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS]))
mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) {
#ifdef ENABLE_MEM_LOG
if ((start >= 0xa0000) && (start <= 0xbffff))
mem_log("Write allowed: %08X (mapping for %08X)\n", map, start);
#endif
write_mapping[c >> MEM_GRANULARITY_BITS] = map;
}
}
}
map = map->next;
@@ -1810,6 +1872,13 @@ mem_mapping_add(mem_mapping_t *map,
}
void
mem_mapping_do_recalc(mem_mapping_t *map)
{
mem_mapping_recalc(map->base, map->size);
}
void
mem_mapping_set_handler(mem_mapping_t *map,
uint8_t (*read_b)(uint32_t addr, void *p),
@@ -1888,15 +1957,19 @@ mem_mapping_enable(mem_mapping_t *map)
void
mem_set_mem_state(uint32_t base, uint32_t size, int state)
mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state)
{
uint32_t c;
for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) {
_mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state[(c + base) >> MEM_GRANULARITY_BITS];
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = state;
// if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
// pclog("Set mem state for block at %08X to %02X\n", c + base, state);
if (smm)
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x00ff) | ((state & 0xff) << 8);
else
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xff00) | (state & 0xff);
#ifdef ENABLE_MEM_LOG
if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
mem_log("Set mem state for block at %08X to %02X\n", c + base, state);
#endif
}
mem_mapping_recalc(base, size);
@@ -1904,17 +1977,16 @@ mem_set_mem_state(uint32_t base, uint32_t size, int state)
void
mem_restore_mem_state(uint32_t base, uint32_t size)
mem_set_mem_state(uint32_t base, uint32_t size, int state)
{
uint32_t c;
mem_set_mem_state_common(0, base, size, state);
}
for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) {
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS];
// if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
// pclog("Reset mem state for block at %08X\n", c + base);
}
mem_mapping_recalc(base, size);
void
mem_set_mem_state_smm(uint32_t base, uint32_t size, int state)
{
mem_set_mem_state_common(1, base, size, state);
}
@@ -2082,11 +2154,15 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
memset(&base_mapping, 0x00, sizeof(base_mapping));
memset(_mem_state, 0x00, sizeof(_mem_state));
memset(_mem_state_bak, 0x00, sizeof(_mem_state_bak));
/* Set SMM states to (MEM_READ_NORMAL | MEM_WRITE_NORMAL). */
for (c = 0; c < MEM_MAPPINGS_NO; c++)
_mem_state[c] |= 0x4400;
mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_set_mem_state(0x0c0000, 0x40000,
/* mem_set_mem_state(0x0c0000, 0x40000,
MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); */
mem_set_mem_state(0x0a0000, 0x60000,
MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
mem_mapping_add(&ram_low_mapping, 0x00000,
@@ -2115,12 +2191,17 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
}
}
if (mem_size > 768)
/* if (mem_size > 768)
mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000,
mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); */
if (mem_size > 768)
mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000,
mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL);
mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024,
mem_read_remapped,mem_read_remappedw,mem_read_remappedl,
mem_write_remapped,mem_write_remappedw,mem_write_remappedl,

View File

@@ -84,12 +84,18 @@ sio_detect_init(const device_t *info)
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0108, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0250, 0x0002,
io_sethandler(0x0250, 0x0003,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0279, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0370, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x03e3, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x03f0, 0x0002,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
io_sethandler(0x0a79, 0x0001,
sio_detect_read, NULL, NULL, sio_detect_write, NULL, NULL, dev);
return dev;
}

View File

@@ -1,519 +0,0 @@
/*
* 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.
*
* Emulation of the Winbond W83977F Super I/O Chip.
*
* Winbond W83977F Super I/O Chip
* Used by the Award 430TX
*
*
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2020 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pci.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/lpt.h>
#include <86box/serial.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/sio.h>
#define HEFRAS (dev->regs[0x26] & 0x40)
typedef struct {
uint8_t tries, regs[48],
dev_regs[256][208];
int locked, rw_locked,
cur_reg, base_address,
type;
fdc_t *fdc;
serial_t *uart[2];
} w83977f_t;
static void w83977f_write(uint16_t port, uint8_t val, void *priv);
static uint8_t w83977f_read(uint16_t port, void *priv);
static void
w83977f_remap(w83977f_t *dev)
{
io_removehandler(0x3f0, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
io_removehandler(0x370, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
dev->base_address = (HEFRAS ? 0x370 : 0x3f0);
io_sethandler(dev->base_address, 0x0002,
w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev);
}
static uint8_t
get_lpt_length(w83977f_t *dev)
{
uint8_t length = 4;
if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) &&
((dev->dev_regs[1][0xc0] & 0x07) != 0x04))
length = 8;
return length;
}
static void
w83977f_fdc_handler(w83977f_t *dev)
{
uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31];
fdc_remove(dev->fdc);
pclog("fdc: %02X %02X %04X\n", dev->dev_regs[0][0x00], dev->regs[0x22], io_base);
if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8))
fdc_set_base(dev->fdc, io_base);
fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f);
}
static void
w83977f_lpt_handler(w83977f_t *dev)
{
uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31];
int io_len = get_lpt_length(dev);
io_base &= (0xfff & ~io_len);
io_mask = 0xffc;
if (io_len == 8)
io_mask = 0xff8;
lpt1_remove();
if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask))
lpt1_init(io_base);
lpt1_irq(dev->dev_regs[1][0x40] & 0x0f);
}
static void
w83977f_serial_handler(w83977f_t *dev, int uart)
{
uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31];
double clock_src = 24000000.0 / 13.0;
serial_remove(dev->uart[uart]);
if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8))
serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f);
switch (dev->dev_regs[2 + uart][0xc0] & 0x03) {
case 0x00:
clock_src = 24000000.0 / 13.0;
break;
case 0x01:
clock_src = 24000000.0 / 12.0;
break;
case 0x02:
clock_src = 24000000.0 / 1.0;
break;
case 0x03:
clock_src = 24000000.0 / 1.625;
break;
}
serial_set_clock_src(dev->uart[uart], clock_src);
}
static void
w83977f_write(uint16_t port, uint8_t val, void *priv)
{
w83977f_t *dev = (w83977f_t *) priv;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0;
uint8_t ld = dev->regs[7];
// pclog("W83977F Write: %04X %02X\n", port, val);
if (index) {
if ((val == 0x87) && !dev->locked) {
if (dev->tries) {
dev->locked = 1;
dev->tries = 0;
} else
dev->tries++;
} else {
if (dev->locked) {
if (val == 0xaa)
dev->locked = 0;
else
dev->cur_reg = val;
} else {
if (dev->tries)
dev->tries = 0;
}
}
return;
} else {
if (dev->locked) {
if (dev->rw_locked)
return;
if (dev->cur_reg >= 0x30) {
valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30];
dev->dev_regs[ld][dev->cur_reg - 0x30] = val;
} else {
valxor = val ^ dev->regs[dev->cur_reg];
dev->regs[dev->cur_reg] = val;
}
} else
return;
}
switch (dev->cur_reg) {
case 0x02:
if (valxor & 0x02)
softresetx86();
break;
case 0x22:
if (valxor & 0x20)
w83977f_serial_handler(dev, 1);
if (valxor & 0x10)
w83977f_serial_handler(dev, 0);
if (valxor & 0x08)
w83977f_lpt_handler(dev);
if (valxor & 0x01)
w83977f_fdc_handler(dev);
break;
case 0x26:
if (valxor & 0x20)
dev->rw_locked = (val & 0x20) ? 1 : 0;
case 0x30:
if (valxor & 0x01) switch (ld) {
case 0x00:
w83977f_fdc_handler(dev);
break;
case 0x01:
w83977f_lpt_handler(dev);
break;
case 0x02: case 0x03:
w83977f_serial_handler(dev, ld - 2);
break;
}
break;
case 0x60: case 0x61:
if (valxor & 0xff) switch (ld) {
case 0x00:
w83977f_fdc_handler(dev);
break;
case 0x01:
w83977f_lpt_handler(dev);
break;
case 0x02: case 0x03:
w83977f_serial_handler(dev, ld - 2);
break;
}
break;
case 0x70:
if (valxor & 0x0f) switch (ld) {
case 0x00:
w83977f_fdc_handler(dev);
break;
case 0x01:
w83977f_lpt_handler(dev);
break;
case 0x02: case 0x03:
w83977f_serial_handler(dev, ld - 2);
break;
}
break;
case 0xf0:
switch (ld) {
case 0x00:
if (valxor & 0x20)
fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1);
if (valxor & 0x10)
fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0);
if (valxor & 0x01)
fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0);
break;
case 0x01:
if (valxor & 0x07)
w83977f_lpt_handler(dev);
break;
case 0x02: case 0x03:
if (valxor & 0x03)
w83977f_serial_handler(dev, ld - 2);
break;
}
break;
case 0xf1:
switch (ld) {
case 0x00:
if (valxor & 0xc0)
fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6);
if (valxor & 0x0c)
fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2);
if (valxor & 0x02)
fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0);
if (valxor & 0x01)
fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0);
break;
}
break;
case 0xf2:
switch (ld) {
case 0x00:
if (valxor & 0xc0)
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
if (valxor & 0x30)
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
if (valxor & 0x0c)
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
if (valxor & 0x03)
fdc_update_rwc(dev->fdc, 0, val & 0x03);
break;
}
break;
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
switch (ld) {
case 0x00:
if (valxor & 0x18)
fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3);
break;
}
break;
}
}
static uint8_t
w83977f_read(uint16_t port, void *priv)
{
w83977f_t *dev = (w83977f_t *) priv;
uint8_t ret = 0xff;
uint8_t index = (port & 1) ? 0 : 1;
uint8_t ld = dev->regs[7];
if (dev->locked) {
if (index)
ret = dev->cur_reg;
else {
if (!dev->rw_locked) {
if ((dev->cur_reg == 0xf2) && (ld == 0x00))
ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6));
else if (dev->cur_reg >= 0x30)
ret = dev->dev_regs[ld][dev->cur_reg - 0x30];
else
ret = dev->regs[dev->cur_reg];
}
}
}
// pclog("W83977F Read: %04X %02X\n", port, ret);
return ret;
}
static void
w83977f_reset(w83977f_t *dev)
{
int i;
memset(dev->regs, 0, 48);
for (i = 0; i < 256; i++)
memset(dev->dev_regs[i], 0, 208);
dev->regs[0x20] = 0x97;
dev->regs[0x21] = dev->type ? 0x73 : 0x71;
dev->regs[0x22] = 0xff;
dev->regs[0x24] = dev->type ? 0x84 : 0xa4;
/* WARNING: Array elements are register - 0x30. */
/* Logical Device 0 (FDC) */
dev->dev_regs[0][0x00] = 0x01;
if (!dev->type)
dev->dev_regs[0][0x01] = 0x02;
dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0;
dev->dev_regs[0][0x40] = 0x06;
if (!dev->type)
dev->dev_regs[0][0x41] = 0x02; /* Read-only */
dev->dev_regs[0][0x44] = 0x02;
dev->dev_regs[0][0xc0] = 0x0e;
/* Logical Device 1 (Parallel Port) */
dev->dev_regs[1][0x00] = 0x01;
if (!dev->type)
dev->dev_regs[1][0x01] = 0x02;
dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78;
dev->dev_regs[1][0x40] = 0x07;
if (!dev->type)
dev->dev_regs[1][0x41] = 0x02; /* Read-only */
dev->dev_regs[1][0x44] = 0x04;
dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is priner mode. */
/* Logical Device 2 (UART A) */
dev->dev_regs[2][0x00] = 0x01;
if (!dev->type)
dev->dev_regs[2][0x01] = 0x02;
dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8;
dev->dev_regs[2][0x40] = 0x04;
if (!dev->type)
dev->dev_regs[2][0x41] = 0x02; /* Read-only */
/* Logical Device 3 (UART B) */
dev->dev_regs[3][0x00] = 0x01;
if (!dev->type)
dev->dev_regs[3][0x01] = 0x02;
dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8;
dev->dev_regs[3][0x40] = 0x03;
if (!dev->type)
dev->dev_regs[3][0x41] = 0x02; /* Read-only */
/* Logical Device 4 (RTC) */
if (!dev->type) {
dev->dev_regs[4][0x00] = 0x01;
dev->dev_regs[4][0x01] = 0x02;
dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70;
dev->dev_regs[4][0x40] = 0x08;
dev->dev_regs[4][0x41] = 0x02; /* Read-only */
}
/* Logical Device 5 (KBC) */
dev->dev_regs[5][0x00] = 0x01;
if (!dev->type)
dev->dev_regs[5][0x01] = 0x02;
dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60;
dev->dev_regs[5][0x40] = 0x01;
if (!dev->type)
dev->dev_regs[5][0x41] = 0x02; /* Read-only */
dev->dev_regs[5][0x42] = 0x0c;
if (!dev->type)
dev->dev_regs[5][0x43] = 0x02; /* Read-only? */
dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40;
/* Logical Device 6 (IR) = UART C */
if (!dev->type) {
dev->dev_regs[6][0x01] = 0x02;
dev->dev_regs[6][0x41] = 0x02; /* Read-only */
dev->dev_regs[6][0x44] = 0x04;
dev->dev_regs[6][0x45] = 0x04;
}
/* Logical Device 7 (Auxiliary I/O Part I) */
if (!dev->type)
dev->dev_regs[7][0x01] = 0x02;
if (!dev->type)
dev->dev_regs[7][0x41] = 0x02; /* Read-only */
if (!dev->type)
dev->dev_regs[7][0x43] = 0x02; /* Read-only? */
dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01;
dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01;
dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01;
dev->dev_regs[7][0xb6] = 0x01;
if (dev->type)
dev->dev_regs[7][0xb7] = 0x01;
/* Logical Device 8 (Auxiliary I/O Part II) */
if (!dev->type)
dev->dev_regs[8][0x01] = 0x02;
if (!dev->type)
dev->dev_regs[8][0x41] = 0x02; /* Read-only */
if (!dev->type)
dev->dev_regs[8][0x43] = 0x02; /* Read-only? */
dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01;
dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01;
dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01;
dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01;
/* Logical Device 9 (Auxiliary I/O Part III) */
if (dev->type) {
dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01;
dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01;
dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01;
dev->dev_regs[7][0xb6] = 0x01; dev->dev_regs[7][0xb7] = 0x01;
}
fdc_reset(dev->fdc);
serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ);
serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ);
w83977f_fdc_handler(dev);
w83977f_lpt_handler(dev);
w83977f_serial_handler(dev, 0);
w83977f_serial_handler(dev, 1);
w83977f_remap(dev);
dev->locked = 0;
dev->rw_locked = 0;
}
static void
w83977f_close(void *priv)
{
w83977f_t *dev = (w83977f_t *) priv;
free(dev);
}
static void *
w83977f_init(const device_t *info)
{
w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t));
memset(dev, 0, sizeof(w83977f_t));
dev->type = info->local;
dev->fdc = device_add(&fdc_at_smc_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
w83977f_reset(dev);
return dev;
}
const device_t w83977f_device = {
"Winbond W83977F Super I/O",
0,
0,
w83977f_init, w83977f_close, NULL,
NULL, NULL, NULL,
NULL
};
const device_t w83977tf_device = {
"Winbond W83977TF Super I/O",
0,
1,
w83977f_init, w83977f_close, NULL,
NULL, NULL, NULL,
NULL
};

View File

@@ -283,14 +283,6 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
}
}
break;
case 4:
// pclog("NVR RAM mask set to %i\n", !!(val & 0x80));
break;
case 5:
// pclog("Reserved set to %i\n", !!(val & 0x04));
// pclog("RTC is now %sabled\n", (val & 0x08) ? "en" : "dis");
// pclog("NVR RAM bank set to %i\n", !!(val & 0x20));
break;
case 9:
if (valxor & 0x44) {
fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0);
@@ -302,7 +294,6 @@ pc87306_write(uint16_t port, uint8_t val, void *priv)
pc87306_gpio_init(dev);
break;
case 0x12:
// pclog("NVR RAM 38-3F lock set to %i\n", !!(val & 0x01));
if (valxor & 0x30)
pc87306_gpio_init(dev);
break;

View File

@@ -197,7 +197,6 @@ w83787f_write(uint16_t port, uint8_t val, void *priv)
w83787f_t *dev = (w83787f_t *) priv;
uint8_t valxor = 0;
uint8_t max = 0x15;
pclog("W83787F: Write %02X to %04X\n", val, port);
if (port == 0x250) {
if (val == dev->key)
@@ -312,8 +311,6 @@ w83787f_read(uint16_t port, void *priv)
}
}
pclog("W83787F: Read %02X from %04X\n", ret, port);
return ret;
}

View File

@@ -566,7 +566,7 @@ CPUOBJ := cpu.o cpu_table.o \
CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
via_mvp3.o via_apro.o wd76c10.o
via_apollo.o wd76c10.o
MCHOBJ := machine.o machine_table.o \
m_xt.o m_xt_compaq.o \
@@ -585,7 +585,7 @@ MCHOBJ := machine.o machine_table.o \
m_at_socket8.o
DEVOBJ := bugger.o hwm.o hwm_w83781d.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \
sio_acc3221.o \
sio_detect.o sio_acc3221.o \
sio_f82c710.o \
sio_fdc37c66x.o sio_fdc37c669.o \
sio_fdc37c93x.o \

View File

@@ -571,7 +571,7 @@ CPUOBJ := cpu.o cpu_table.o \
CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
via_mvp3.o via_apro.o wd76c10.o
via_apollo.o wd76c10.o
MCHOBJ := machine.o machine_table.o \
m_xt.o m_xt_compaq.o \