mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 01:25:33 -07:00
Fixed SMM, overhauled the emulation of the VIA northbridges, and added the Via Apollo VP3.
This commit is contained in:
@@ -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
587
src/chipset/via_apollo.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
18
src/io.c
18
src/io.c
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
175
src/mem.c
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user